Provide a mechanism for returning the encapsulator as well as the
[people/xl0/gpxe.git] / src / net / interface.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/interface.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 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 trans_protocol;
25
26 /** Registered transport-layer protocols */
27 static struct trans_protocol trans_protocols[0] __table_start ( trans_protocols );
28 static struct trans_protocol trans_protocols_end[0] __table_end ( trans_protocols );
29
30 /** Identify TCPIP net 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;
37
38         for ( tcpip = tcpip_net_protocols; tcpip < tcpip_net_protocols_end; tcpip++ ) {
39                 if ( tcpip->sa_family == sa_family ) {
40                         return tcpip;
41                 }
42         }
43         return NULL;
44 }
45
46 /** Identify transport-layer protocol
47  *
48  * @v trans_proto       Transport-layer protocol number, IP_XXX
49  * @ret trans_protocol  Transport-layer protocol, or NULL
50  */
51 struct trans_protocol* find_trans_protocol ( uint8_t trans_proto ) {
52         struct trans_protocol *trans_protocol;
53
54         for ( trans_protocol = trans_protocols; trans_protocol <= trans_protocols_end; ++trans_protocol ) {
55                 if ( trans_protocol->trans_proto == trans_proto ) {
56                         return trans_protocol;
57                 }
58         }
59         return NULL;
60 }
61
62 /** Process a received packet
63  *
64  * @v pkb               Packet buffer
65  * @v trans_proto       Transport-layer protocol number
66  * @v src               Source network-layer address
67  * @v dest              Destination network-layer address
68  *
69  * This function expects a transport-layer segment from the network-layer
70  */
71 void trans_rx ( struct pk_buff *pkb, uint8_t trans_proto, struct in_addr *src, struct in_addr *dest ) {
72         struct trans_protocol *trans_protocol;
73
74         /* Identify the transport layer protocol */
75         for ( trans_protocol = trans_protocols; trans_protocol <= trans_protocols_end; ++trans_protocol ) {
76                 if ( trans_protocol->trans_proto == trans_proto ) {
77                         DBG ( "Packet sent to %s module", trans_protocol->name );
78                         trans_protocol->rx ( pkb, src, dest );
79                 }
80         }
81 }
82
83 /** Transmit a transport-layer segment
84  *
85  * @v pkb               Packet buffer
86  * @v trans_proto       Transport-layer protocol
87  * @v sock              Destination socket address
88  * @ret                 Status
89  */
90 int trans_tx ( struct pk_buff *pkb, uint8_t trans_proto, struct sockaddr *sock ) {
91
92         /* Identify the network layer protocol and send it using xxx_tx() */
93         switch ( sock->sa_family ) {
94         case AF_INET: /* IPv4 network family */
95                 return ipv4_tx ( pkb, trans_proto, &sock->sin.sin_addr );
96         case AF_INET6: /* IPv6 network family */
97                 return ipv6_tx ( pkb, trans_proto, &sock->sin6.sin6_addr );
98         default:
99                 DBG ( "Network family %d not supported", sock->sa_family );
100         }
101         return -EPROTONOSUPPORT;
102 }
103
104 /**
105  * Calculate internet checksum
106  *
107  * @v data      Pointer to the data
108  * @v len       Length of data to be checksummed
109  * @ret chksum  16 bit internet checksum
110  *
111  * This function calculates the internet checksum (refer RFC1071) for len bytes beginning at the location data
112  */
113 uint16_t calc_chksum ( void *data, size_t len ) {
114         register long sum = 0;
115         uint16_t checksum;
116         unsigned short *temp;
117         while ( len > 1 ) {
118                 temp = (unsigned short*) data++;
119                 sum += *temp;
120                 len -= 2;
121         }
122         if ( len > 0 ) {
123                 sum += *(unsigned char *)data;
124         }
125         while ( sum >> 16 ) {
126                 sum = ( sum & 0xffff ) + ( sum >> 16 );
127         }
128         checksum = ~sum;
129         return checksum;
130 }
131
132