Add qemu 2.4.0
[kvmfornfv.git] / qemu / roms / ipxe / src / net / tcpip.c
1 #include <stdint.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #include <byteswap.h>
6 #include <ipxe/iobuf.h>
7 #include <ipxe/tables.h>
8 #include <ipxe/ipstat.h>
9 #include <ipxe/netdevice.h>
10 #include <ipxe/tcpip.h>
11
12 /** @file
13  *
14  * Transport-network layer interface
15  *
16  * This file contains functions and utilities for the
17  * TCP/IP transport-network layer interface
18  */
19
20 FILE_LICENCE ( GPL2_OR_LATER );
21
22 /**
23  * Process a received TCP/IP packet
24  *
25  * @v iobuf             I/O buffer
26  * @v netdev            Network device
27  * @v tcpip_proto       Transport-layer protocol number
28  * @v st_src            Partially-filled source address
29  * @v st_dest           Partially-filled destination address
30  * @v pshdr_csum        Pseudo-header checksum
31  * @v stats             IP statistics
32  * @ret rc              Return status code
33  *
34  * This function expects a transport-layer segment from the network
35  * layer.  The network layer should fill in as much as it can of the
36  * source and destination addresses (i.e. it should fill in the
37  * address family and the network-layer addresses, but leave the ports
38  * and the rest of the structures as zero).
39  */
40 int tcpip_rx ( struct io_buffer *iobuf, struct net_device *netdev,
41                uint8_t tcpip_proto, struct sockaddr_tcpip *st_src,
42                struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum,
43                struct ip_statistics *stats ) {
44         struct tcpip_protocol *tcpip;
45
46         /* Hand off packet to the appropriate transport-layer protocol */
47         for_each_table_entry ( tcpip, TCPIP_PROTOCOLS ) {
48                 if ( tcpip->tcpip_proto == tcpip_proto ) {
49                         DBG ( "TCP/IP received %s packet\n", tcpip->name );
50                         stats->in_delivers++;
51                         return tcpip->rx ( iobuf, netdev, st_src, st_dest,
52                                            pshdr_csum );
53                 }
54         }
55
56         DBG ( "Unrecognised TCP/IP protocol %d\n", tcpip_proto );
57         stats->in_unknown_protos++;
58         free_iob ( iobuf );
59         return -EPROTONOSUPPORT;
60 }
61
62 /**
63  * Find TCP/IP network-layer protocol
64  *
65  * @v st_dest           Destination address
66  * @ret tcpip_net       TCP/IP network-layer protocol, or NULL if not found
67  */
68 static struct tcpip_net_protocol *
69 tcpip_net_protocol ( struct sockaddr_tcpip *st_dest ) {
70         struct tcpip_net_protocol *tcpip_net;
71
72         for_each_table_entry ( tcpip_net, TCPIP_NET_PROTOCOLS ) {
73                 if ( tcpip_net->sa_family == st_dest->st_family )
74                         return tcpip_net;
75         }
76
77         DBG ( "Unrecognised TCP/IP address family %d\n", st_dest->st_family );
78         return NULL;
79 }
80
81 /**
82  * Transmit a TCP/IP packet
83  *
84  * @v iobuf             I/O buffer
85  * @v tcpip_protocol    Transport-layer protocol
86  * @v st_src            Source address, or NULL to use route default
87  * @v st_dest           Destination address
88  * @v netdev            Network device to use if no route found, or NULL
89  * @v trans_csum        Transport-layer checksum to complete, or NULL
90  * @ret rc              Return status code
91  */
92 int tcpip_tx ( struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol,
93                struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest,
94                struct net_device *netdev, uint16_t *trans_csum ) {
95         struct tcpip_net_protocol *tcpip_net;
96
97         /* Hand off packet to the appropriate network-layer protocol */
98         tcpip_net = tcpip_net_protocol ( st_dest );
99         if ( tcpip_net ) {
100                 DBG ( "TCP/IP sending %s packet\n", tcpip_net->name );
101                 return tcpip_net->tx ( iobuf, tcpip_protocol, st_src, st_dest,
102                                        netdev, trans_csum );
103         }
104
105         free_iob ( iobuf );
106         return -EAFNOSUPPORT;
107 }
108
109 /**
110  * Determine transmitting network device
111  *
112  * @v st_dest           Destination address
113  * @ret netdev          Network device, or NULL
114  */
115 struct net_device * tcpip_netdev ( struct sockaddr_tcpip *st_dest ) {
116         struct tcpip_net_protocol *tcpip_net;
117
118         /* Hand off to the appropriate network-layer protocol */
119         tcpip_net = tcpip_net_protocol ( st_dest );
120         if ( tcpip_net )
121                 return tcpip_net->netdev ( st_dest );
122
123         return NULL;
124 }
125
126 /**
127  * Determine maximum transmission unit
128  *
129  * @v st_dest           Destination address
130  * @ret mtu             Maximum transmission unit
131  */
132 size_t tcpip_mtu ( struct sockaddr_tcpip *st_dest ) {
133         struct tcpip_net_protocol *tcpip_net;
134         struct net_device *netdev;
135         size_t mtu;
136
137         /* Find appropriate network-layer protocol */
138         tcpip_net = tcpip_net_protocol ( st_dest );
139         if ( ! tcpip_net )
140                 return 0;
141
142         /* Find transmitting network device */
143         netdev = tcpip_net->netdev ( st_dest );
144         if ( ! netdev )
145                 return 0;
146
147         /* Calculate MTU */
148         mtu = ( netdev->max_pkt_len - netdev->ll_protocol->ll_header_len -
149                 tcpip_net->header_len );
150
151         return mtu;
152 }
153
154 /**
155  * Calculate continued TCP/IP checkum
156  *
157  * @v partial           Checksum of already-summed data, in network byte order
158  * @v data              Data buffer
159  * @v len               Length of data buffer
160  * @ret cksum           Updated checksum, in network byte order
161  *
162  * Calculates a TCP/IP-style 16-bit checksum over the data block.  The
163  * checksum is returned in network byte order.
164  *
165  * This function may be used to add new data to an existing checksum.
166  * The function assumes that both the old data and the new data start
167  * on even byte offsets; if this is not the case then you will need to
168  * byte-swap either the input partial checksum, the output checksum,
169  * or both.  Deciding which to swap is left as an exercise for the
170  * interested reader.
171  */
172 uint16_t generic_tcpip_continue_chksum ( uint16_t partial,
173                                          const void *data, size_t len ) {
174         unsigned int cksum = ( ( ~partial ) & 0xffff );
175         unsigned int value;
176         unsigned int i;
177         
178         for ( i = 0 ; i < len ; i++ ) {
179                 value = * ( ( uint8_t * ) data + i );
180                 if ( i & 1 ) {
181                         /* Odd bytes: swap on little-endian systems */
182                         value = be16_to_cpu ( value );
183                 } else {
184                         /* Even bytes: swap on big-endian systems */
185                         value = le16_to_cpu ( value );
186                 }
187                 cksum += value;
188                 if ( cksum > 0xffff )
189                         cksum -= 0xffff;
190         }
191         
192         return ( ~cksum );
193 }
194
195 /**
196  * Calculate TCP/IP checkum
197  *
198  * @v data              Data buffer
199  * @v len               Length of data buffer
200  * @ret cksum           Checksum, in network byte order
201  *
202  * Calculates a TCP/IP-style 16-bit checksum over the data block.  The
203  * checksum is returned in network byte order.
204  */
205 uint16_t tcpip_chksum ( const void *data, size_t len ) {
206         return tcpip_continue_chksum ( TCPIP_EMPTY_CSUM, data, len );
207 }
208
209 /**
210  * Bind to local TCP/IP port
211  *
212  * @v st_local          Local TCP/IP socket address, or NULL
213  * @v available         Function to check port availability
214  * @ret port            Local port number, or negative error
215  */
216 int tcpip_bind ( struct sockaddr_tcpip *st_local,
217                  int ( * available ) ( int port ) ) {
218         uint16_t flags = 0;
219         uint16_t try_port = 0;
220         uint16_t min_port;
221         uint16_t max_port;
222         unsigned int offset;
223         unsigned int i;
224
225         /* Extract parameters from local socket address */
226         if ( st_local ) {
227                 flags = st_local->st_flags;
228                 try_port = ntohs ( st_local->st_port );
229         }
230
231         /* If an explicit port is specified, check its availability */
232         if ( try_port )
233                 return available ( try_port );
234
235         /* Otherwise, find an available port in the range [1,1023] or
236          * [1025,65535] as appropriate.
237          */
238         min_port = ( ( ( ! flags ) & TCPIP_BIND_PRIVILEGED ) + 1 );
239         max_port = ( ( flags & TCPIP_BIND_PRIVILEGED ) - 1 );
240         offset = random();
241         for ( i = 0 ; i <= max_port ; i++ ) {
242                 try_port = ( ( i + offset ) & max_port );
243                 if ( try_port < min_port )
244                         continue;
245                 if ( available ( try_port ) < 0 )
246                         continue;
247                 return try_port;
248         }
249         return -EADDRINUSE;
250 }