8 #include <gpxe/pkbuff.h>
9 #include <gpxe/tables.h>
10 #include <gpxe/netdevice.h>
11 #include <gpxe/tcpip_if.h>
15 * Transport-network layer interface
17 * This file contains functions and utilities for the transport-network layer interface
20 /** Registered network-layer protocols that support TCPIP */
21 static struct tcpip_net_protocol tcpip_net_protocols[0] __table_start ( tcpip_net_protocols );
22 static struct tcpip_net_protocol tcpip_net_protocols_end[0] __table_end ( tcpip_net_protocols );
24 struct tcpip_protocol;
26 /** Registered transport-layer protocols that support TCPIP */
27 static struct tcpip_protocol tcpip_protocols[0] __table_start ( tcpip_protocols );
28 static struct tcpip_protocol tcpip_protocols_end[0] __table_end ( tcpip_protocols );
30 /** Identify TCPIP network-layer protocol
32 * @v sa_family Network address family
33 * @ret tcpip Protocol supporting TCPIP, or NULL
35 static struct tcpip_net_protocol * tcpip_find_protocol ( sa_family_t sa_family ) {
36 struct tcpip_net_protocol *tcpip_net;
38 for ( tcpip_net = tcpip_net_protocols;
39 tcpip_net < tcpip_net_protocols_end; ++tcpip_net ) {
40 if ( tcpip_net->sa_family == sa_family ) {
47 /** Identify TCPIP transport-layer protocol
49 * @v trans_proto Transport-layer protocol number, IP_XXX
50 * @ret tcpip_protocol Transport-layer protocol, or NULL
52 struct tcpip_protocol* find_tcpip_protocol ( uint8_t trans_proto ) {
53 struct tcpip_protocol *tcpip;
55 for ( tcpip = tcpip_protocols; tcpip <= tcpip_protocols_end;
57 if ( tcpip->trans_proto == trans_proto ) {
64 /** Process a received packet
66 * @v pkb Packet buffer
67 * @v trans_proto Transport-layer protocol number
68 * @v src Source network-layer address
69 * @v dest Destination network-layer address
71 * This function expects a transport-layer segment from the network-layer
73 void trans_rx ( struct pk_buff *pkb, uint8_t trans_proto, struct in_addr *src,
74 struct in_addr *dest ) {
75 struct tcpip_protocol *tcpip;
77 /* Identify the transport layer protocol */
78 for ( tcpip = tcpip_protocols; tcpip <= tcpip_protocols_end; ++tcpip ) {
79 if ( tcpip->trans_proto == trans_proto ) {
80 DBG ( "Packet sent to %s module", tcpip->name );
81 tcpip->rx ( pkb, src, dest );
86 /** Transmit a transport-layer segment
88 * @v pkb Packet buffer
89 * @v trans_proto Transport-layer protocol
90 * @v sock Destination socket address
93 int trans_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip,
94 struct sockaddr *sock ) {
96 /* Identify the network layer protocol and send it using xxx_tx() */
97 switch ( sock->sa_family ) {
98 case AF_INET: /* IPv4 network family */
99 return ipv4_tx ( pkb, tcpip, &sock->sin.sin_addr );
100 case AF_INET6: /* IPv6 network family */
101 return ipv6_tx ( pkb, tcpip, &sock->sin6.sin6_addr );
103 DBG ( "Network family %d not supported", sock->sa_family );
104 return -EAFNOSUPPORT;
108 * Calculate internet checksum
110 * @v data Pointer to the data
111 * @v len Length of data to be checksummed
112 * @ret chksum 16 bit internet checksum
114 * This function calculates the internet checksum (refer RFC1071) for "len"
115 * bytes beginning at the location "data"
117 uint16_t calc_chksum ( void *data, size_t len ) {
118 register long sum = 0;
120 unsigned short *temp;
122 temp = (unsigned short*) data++;
127 sum += *(unsigned char *)data;
129 while ( sum >> 16 ) {
130 sum = ( sum & 0xffff ) + ( sum >> 16 );