5c5e596216a43d92fe46de0e7520e33fce65d657
[gpxe.git] / src / net / tcpip_if.c
1 #include <stdint.h>
2 #include <string.h>
3 #include <errno.h>
4 #include <malloc.h>
5 #include <byteswap.h>
6 #include <gpxe/in.h>
7 #include <gpxe/ip.h>
8 #include <gpxe/pkbuff.h>
9 #include <gpxe/tables.h>
10 #include <gpxe/netdevice.h>
11 #include <gpxe/tcpip_if.h>
12
13 /** @file
14  *
15  * Transport-network layer interface
16  *
17  * This file contains functions and utilities for the transport-network layer interface
18  */
19
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 );
23
24 struct tcpip_protocol;
25
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 );
29
30 /** Identify TCPIP network-layer protocol
31  *
32  * @v sa_family  Network address family
33  * @ret tcpip      Protocol supporting TCPIP, or NULL
34  */
35 static struct tcpip_net_protocol * tcpip_find_protocol ( sa_family_t sa_family ) {
36         struct tcpip_net_protocol *tcpip_net;
37
38         for ( tcpip_net = tcpip_net_protocols; 
39                 tcpip_net < tcpip_net_protocols_end; ++tcpip_net ) {
40                 if ( tcpip_net->sa_family == sa_family ) {
41                         return tcpip_net;
42                 }
43         }
44         return NULL;
45 }
46
47 /** Identify TCPIP transport-layer protocol
48  *
49  * @v trans_proto       Transport-layer protocol number, IP_XXX
50  * @ret tcpip_protocol  Transport-layer protocol, or NULL
51  */
52 struct tcpip_protocol* find_tcpip_protocol ( uint8_t trans_proto ) {
53         struct tcpip_protocol *tcpip;
54
55         for ( tcpip = tcpip_protocols; tcpip <= tcpip_protocols_end; 
56                 ++tcpip ) {
57                 if ( tcpip->trans_proto == trans_proto ) {
58                         return tcpip;
59                 }
60         }
61         return NULL;
62 }
63
64 /** Process a received packet
65  *
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
70  *
71  * This function expects a transport-layer segment from the network-layer
72  */
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;
76
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 );
82                 }
83         }
84 }
85
86 /** Transmit a transport-layer segment
87  *
88  * @v pkb               Packet buffer
89  * @v trans_proto       Transport-layer protocol
90  * @v sock              Destination socket address
91  * @ret                 Status
92  */
93 int trans_tx ( struct pk_buff *pkb, struct tcpip_protocol *tcpip,
94                struct sockaddr *sock ) {
95
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 );
102         }
103         DBG ( "Network family %d not supported", sock->sa_family );
104         return -EAFNOSUPPORT;
105 }
106
107 /**
108  * Calculate internet checksum
109  *
110  * @v data      Pointer to the data
111  * @v len       Length of data to be checksummed
112  * @ret chksum  16 bit internet checksum
113  *
114  * This function calculates the internet checksum (refer RFC1071) for "len"
115  * bytes beginning at the location "data"
116  */
117 uint16_t calc_chksum ( void *data, size_t len ) {
118         register long sum = 0;
119         uint16_t checksum;
120         unsigned short *temp;
121         while ( len > 1 ) {
122                 temp = (unsigned short*) data++;
123                 sum += *temp;
124                 len -= 2;
125         }
126         if ( len > 0 ) {
127                 sum += *(unsigned char *)data;
128         }
129         while ( sum >> 16 ) {
130                 sum = ( sum & 0xffff ) + ( sum >> 16 );
131         }
132         checksum = ~sum;
133         return checksum;
134 }
135
136