[tcp] Ignore duplicate ACKs in TCP ESTABLISHED state
[people/oremanj/gpxe.git] / src / net / udp.c
1 #include <stdint.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <assert.h>
5 #include <byteswap.h>
6 #include <errno.h>
7 #include <gpxe/tcpip.h>
8 #include <gpxe/iobuf.h>
9 #include <gpxe/xfer.h>
10 #include <gpxe/open.h>
11 #include <gpxe/uri.h>
12 #include <gpxe/udp.h>
13
14 /** @file
15  *
16  * UDP protocol
17  */
18
19 FILE_LICENCE ( GPL2_OR_LATER );
20
21 /**
22  * A UDP connection
23  *
24  */
25 struct udp_connection {
26         /** Reference counter */
27         struct refcnt refcnt;
28         /** List of UDP connections */
29         struct list_head list;
30
31         /** Data transfer interface */
32         struct xfer_interface xfer;
33
34         /** Local socket address */
35         struct sockaddr_tcpip local;
36         /** Remote socket address */
37         struct sockaddr_tcpip peer;
38 };
39
40 /**
41  * List of registered UDP connections
42  */
43 static LIST_HEAD ( udp_conns );
44
45 /* Forward declatations */
46 static struct xfer_interface_operations udp_xfer_operations;
47 struct tcpip_protocol udp_protocol;
48
49 /**
50  * Bind UDP connection to local port
51  *
52  * @v udp               UDP connection
53  * @ret rc              Return status code
54  *
55  * Opens the UDP connection and binds to the specified local port.  If
56  * no local port is specified, the first available port will be used.
57  */
58 static int udp_bind ( struct udp_connection *udp ) {
59         struct udp_connection *existing;
60         static uint16_t try_port = 1023;
61
62         /* If no port specified, find the first available port */
63         if ( ! udp->local.st_port ) {
64                 while ( try_port ) {
65                         try_port++;
66                         if ( try_port < 1024 )
67                                 continue;
68                         udp->local.st_port = htons ( try_port );
69                         if ( udp_bind ( udp ) == 0 )
70                                 return 0;
71                 }
72                 return -EADDRINUSE;
73         }
74
75         /* Attempt bind to local port */
76         list_for_each_entry ( existing, &udp_conns, list ) {
77                 if ( existing->local.st_port == udp->local.st_port ) {
78                         DBGC ( udp, "UDP %p could not bind: port %d in use\n",
79                                udp, ntohs ( udp->local.st_port ) );
80                         return -EADDRINUSE;
81                 }
82         }
83
84         /* Add to UDP connection list */
85         DBGC ( udp, "UDP %p bound to port %d\n",
86                udp, ntohs ( udp->local.st_port ) );
87
88         return 0;
89 }
90
91 /**
92  * Open a UDP connection
93  *
94  * @v xfer              Data transfer interface
95  * @v peer              Peer socket address, or NULL
96  * @v local             Local socket address, or NULL
97  * @v promisc           Socket is promiscuous
98  * @ret rc              Return status code
99  */
100 static int udp_open_common ( struct xfer_interface *xfer,
101                              struct sockaddr *peer, struct sockaddr *local,
102                              int promisc ) {
103         struct sockaddr_tcpip *st_peer = ( struct sockaddr_tcpip * ) peer;
104         struct sockaddr_tcpip *st_local = ( struct sockaddr_tcpip * ) local;
105         struct udp_connection *udp;
106         int rc;
107
108         /* Allocate and initialise structure */
109         udp = zalloc ( sizeof ( *udp ) );
110         if ( ! udp )
111                 return -ENOMEM;
112         DBGC ( udp, "UDP %p allocated\n", udp );
113         xfer_init ( &udp->xfer, &udp_xfer_operations, &udp->refcnt );
114         if ( st_peer )
115                 memcpy ( &udp->peer, st_peer, sizeof ( udp->peer ) );
116         if ( st_local )
117                 memcpy ( &udp->local, st_local, sizeof ( udp->local ) );
118
119         /* Bind to local port */
120         if ( ! promisc ) {
121                 if ( ( rc = udp_bind ( udp ) ) != 0 )
122                         goto err;
123         }
124
125         /* Attach parent interface, transfer reference to connection
126          * list and return
127          */
128         xfer_plug_plug ( &udp->xfer, xfer );
129         list_add ( &udp->list, &udp_conns );
130         return 0;
131
132  err:
133         ref_put ( &udp->refcnt );
134         return rc;
135 }
136
137 /**
138  * Open a UDP connection
139  *
140  * @v xfer              Data transfer interface
141  * @v peer              Peer socket address
142  * @v local             Local socket address, or NULL
143  * @ret rc              Return status code
144  */
145 int udp_open ( struct xfer_interface *xfer, struct sockaddr *peer,
146                struct sockaddr *local ) {
147         return udp_open_common ( xfer, peer, local, 0 );
148 }
149
150 /**
151  * Open a promiscuous UDP connection
152  *
153  * @v xfer              Data transfer interface
154  * @ret rc              Return status code
155  *
156  * Promiscuous UDP connections are required in order to support the
157  * PXE API.
158  */
159 int udp_open_promisc ( struct xfer_interface *xfer ) {
160         return udp_open_common ( xfer, NULL, NULL, 1 );
161 }
162
163 /**
164  * Close a UDP connection
165  *
166  * @v udp               UDP connection
167  * @v rc                Reason for close
168  */
169 static void udp_close ( struct udp_connection *udp, int rc ) {
170
171         /* Close data transfer interface */
172         xfer_nullify ( &udp->xfer );
173         xfer_close ( &udp->xfer, rc );
174
175         /* Remove from list of connections and drop list's reference */
176         list_del ( &udp->list );
177         ref_put ( &udp->refcnt );
178
179         DBGC ( udp, "UDP %p closed\n", udp );
180 }
181
182 /**
183  * Transmit data via a UDP connection to a specified address
184  *
185  * @v udp               UDP connection
186  * @v iobuf             I/O buffer
187  * @v src               Source address, or NULL to use default
188  * @v dest              Destination address, or NULL to use default
189  * @v netdev            Network device, or NULL to use default
190  * @ret rc              Return status code
191  */
192 static int udp_tx ( struct udp_connection *udp, struct io_buffer *iobuf,
193                     struct sockaddr_tcpip *src, struct sockaddr_tcpip *dest,
194                     struct net_device *netdev ) {
195         struct udp_header *udphdr;
196         size_t len;
197         int rc;
198
199         /* Check we can accommodate the header */
200         if ( ( rc = iob_ensure_headroom ( iobuf, UDP_MAX_HLEN ) ) != 0 ) {
201                 free_iob ( iobuf );
202                 return rc;
203         }
204
205         /* Fill in default values if not explicitly provided */
206         if ( ! src )
207                 src = &udp->local;
208         if ( ! dest )
209                 dest = &udp->peer;
210
211         /* Add the UDP header */
212         udphdr = iob_push ( iobuf, sizeof ( *udphdr ) );
213         len = iob_len ( iobuf );
214         udphdr->dest = dest->st_port;
215         udphdr->src = src->st_port;
216         udphdr->len = htons ( len );
217         udphdr->chksum = 0;
218         udphdr->chksum = tcpip_chksum ( udphdr, len );
219
220         /* Dump debugging information */
221         DBGC ( udp, "UDP %p TX %d->%d len %d\n", udp,
222                ntohs ( udphdr->src ), ntohs ( udphdr->dest ),
223                ntohs ( udphdr->len ) );
224
225         /* Send it to the next layer for processing */
226         if ( ( rc = tcpip_tx ( iobuf, &udp_protocol, src, dest, netdev,
227                                &udphdr->chksum ) ) != 0 ) {
228                 DBGC ( udp, "UDP %p could not transmit packet: %s\n",
229                        udp, strerror ( rc ) );
230                 return rc;
231         }
232
233         return 0;
234 }
235
236 /**
237  * Identify UDP connection by local address
238  *
239  * @v local             Local address
240  * @ret udp             UDP connection, or NULL
241  */
242 static struct udp_connection * udp_demux ( struct sockaddr_tcpip *local ) {
243         static const struct sockaddr_tcpip empty_sockaddr = { .pad = { 0, } };
244         struct udp_connection *udp;
245
246         list_for_each_entry ( udp, &udp_conns, list ) {
247                 if ( ( ( udp->local.st_family == local->st_family ) ||
248                        ( udp->local.st_family == 0 ) ) &&
249                      ( ( udp->local.st_port == local->st_port ) ||
250                        ( udp->local.st_port == 0 ) ) &&
251                      ( ( memcmp ( udp->local.pad, local->pad,
252                                   sizeof ( udp->local.pad ) ) == 0 ) ||
253                        ( memcmp ( udp->local.pad, empty_sockaddr.pad,
254                                   sizeof ( udp->local.pad ) ) == 0 ) ) ) {
255                         return udp;
256                 }
257         }
258         return NULL;
259 }
260
261 /**
262  * Process a received packet
263  *
264  * @v iobuf             I/O buffer
265  * @v st_src            Partially-filled source address
266  * @v st_dest           Partially-filled destination address
267  * @v pshdr_csum        Pseudo-header checksum
268  * @ret rc              Return status code
269  */
270 static int udp_rx ( struct io_buffer *iobuf, struct sockaddr_tcpip *st_src,
271                     struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum ) {
272         struct udp_header *udphdr = iobuf->data;
273         struct udp_connection *udp;
274         struct xfer_metadata meta;
275         size_t ulen;
276         unsigned int csum;
277         int rc = 0;
278
279         /* Sanity check packet */
280         if ( iob_len ( iobuf ) < sizeof ( *udphdr ) ) {
281                 DBG ( "UDP packet too short at %zd bytes (min %zd bytes)\n",
282                       iob_len ( iobuf ), sizeof ( *udphdr ) );
283                 
284                 rc = -EINVAL;
285                 goto done;
286         }
287         ulen = ntohs ( udphdr->len );
288         if ( ulen < sizeof ( *udphdr ) ) {
289                 DBG ( "UDP length too short at %zd bytes "
290                       "(header is %zd bytes)\n", ulen, sizeof ( *udphdr ) );
291                 rc = -EINVAL;
292                 goto done;
293         }
294         if ( ulen > iob_len ( iobuf ) ) {
295                 DBG ( "UDP length too long at %zd bytes (packet is %zd "
296                       "bytes)\n", ulen, iob_len ( iobuf ) );
297                 rc = -EINVAL;
298                 goto done;
299         }
300         if ( udphdr->chksum ) {
301                 csum = tcpip_continue_chksum ( pshdr_csum, iobuf->data, ulen );
302                 if ( csum != 0 ) {
303                         DBG ( "UDP checksum incorrect (is %04x including "
304                               "checksum field, should be 0000)\n", csum );
305                         rc = -EINVAL;
306                         goto done;
307                 }
308         }
309
310         /* Parse parameters from header and strip header */
311         st_src->st_port = udphdr->src;
312         st_dest->st_port = udphdr->dest;
313         udp = udp_demux ( st_dest );
314         iob_unput ( iobuf, ( iob_len ( iobuf ) - ulen ) );
315         iob_pull ( iobuf, sizeof ( *udphdr ) );
316
317         /* Dump debugging information */
318         DBGC ( udp, "UDP %p RX %d<-%d len %zd\n", udp,
319                ntohs ( udphdr->dest ), ntohs ( udphdr->src ), ulen );
320
321         /* Ignore if no matching connection found */
322         if ( ! udp ) {
323                 DBG ( "No UDP connection listening on port %d\n",
324                       ntohs ( udphdr->dest ) );
325                 rc = -ENOTCONN;
326                 goto done;
327         }
328
329         /* Pass data to application */
330         memset ( &meta, 0, sizeof ( meta ) );
331         meta.src = ( struct sockaddr * ) st_src;
332         meta.dest = ( struct sockaddr * ) st_dest;
333         rc = xfer_deliver_iob_meta ( &udp->xfer, iob_disown ( iobuf ), &meta );
334
335  done:
336         free_iob ( iobuf );
337         return rc;
338 }
339
340 struct tcpip_protocol udp_protocol __tcpip_protocol = {
341         .name = "UDP",
342         .rx = udp_rx,
343         .tcpip_proto = IP_UDP,
344 };
345
346 /***************************************************************************
347  *
348  * Data transfer interface
349  *
350  ***************************************************************************
351  */
352
353 /**
354  * Close interface
355  *
356  * @v xfer              Data transfer interface
357  * @v rc                Reason for close
358  */
359 static void udp_xfer_close ( struct xfer_interface *xfer, int rc ) {
360         struct udp_connection *udp =
361                 container_of ( xfer, struct udp_connection, xfer );
362
363         /* Close connection */
364         udp_close ( udp, rc );
365 }
366
367 /**
368  * Allocate I/O buffer for UDP
369  *
370  * @v xfer              Data transfer interface
371  * @v len               Payload size
372  * @ret iobuf           I/O buffer, or NULL
373  */
374 static struct io_buffer * udp_alloc_iob ( struct xfer_interface *xfer,
375                                           size_t len ) {
376         struct udp_connection *udp =
377                 container_of ( xfer, struct udp_connection, xfer );     
378         struct io_buffer *iobuf;
379
380         iobuf = alloc_iob ( UDP_MAX_HLEN + len );
381         if ( ! iobuf ) {
382                 DBGC ( udp, "UDP %p cannot allocate buffer of length %zd\n",
383                        udp, len );
384                 return NULL;
385         }
386         iob_reserve ( iobuf, UDP_MAX_HLEN );
387         return iobuf;
388 }
389
390 /**
391  * Deliver datagram as I/O buffer
392  *
393  * @v xfer              Data transfer interface
394  * @v iobuf             Datagram I/O buffer
395  * @v meta              Data transfer metadata
396  * @ret rc              Return status code
397  */
398 static int udp_xfer_deliver_iob ( struct xfer_interface *xfer,
399                                   struct io_buffer *iobuf,
400                                   struct xfer_metadata *meta ) {
401         struct udp_connection *udp =
402                 container_of ( xfer, struct udp_connection, xfer );
403
404         /* Transmit data, if possible */
405         udp_tx ( udp, iobuf, ( ( struct sockaddr_tcpip * ) meta->src ),
406                  ( ( struct sockaddr_tcpip * ) meta->dest ), meta->netdev );
407
408         return 0;
409 }
410
411 /** UDP data transfer interface operations */
412 static struct xfer_interface_operations udp_xfer_operations = {
413         .close          = udp_xfer_close,
414         .vredirect      = ignore_xfer_vredirect,
415         .window         = unlimited_xfer_window,
416         .alloc_iob      = udp_alloc_iob,
417         .deliver_iob    = udp_xfer_deliver_iob,
418         .deliver_raw    = xfer_deliver_as_iob,
419 };
420
421 /***************************************************************************
422  *
423  * Openers
424  *
425  ***************************************************************************
426  */
427
428 /** UDP socket opener */
429 struct socket_opener udp_socket_opener __socket_opener = {
430         .semantics      = UDP_SOCK_DGRAM,
431         .family         = AF_INET,
432         .open           = udp_open,
433 };
434
435 /** Linkage hack */
436 int udp_sock_dgram = UDP_SOCK_DGRAM;
437
438 /**
439  * Open UDP URI
440  *
441  * @v xfer              Data transfer interface
442  * @v uri               URI
443  * @ret rc              Return status code
444  */
445 static int udp_open_uri ( struct xfer_interface *xfer, struct uri *uri ) {
446         struct sockaddr_tcpip peer;
447
448         /* Sanity check */
449         if ( ! uri->host )
450                 return -EINVAL;
451
452         memset ( &peer, 0, sizeof ( peer ) );
453         peer.st_port = htons ( uri_port ( uri, 0 ) );
454         return xfer_open_named_socket ( xfer, SOCK_DGRAM,
455                                         ( struct sockaddr * ) &peer,
456                                         uri->host, NULL );
457 }
458
459 /** UDP URI opener */
460 struct uri_opener udp_uri_opener __uri_opener = {
461         .scheme         = "udp",
462         .open           = udp_open_uri,
463 };