udp.c File Reference

UDP protocol. More...

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <byteswap.h>
#include <errno.h>
#include <gpxe/tcpip.h>
#include <gpxe/iobuf.h>
#include <gpxe/xfer.h>
#include <gpxe/open.h>
#include <gpxe/uri.h>
#include <gpxe/udp.h>

Go to the source code of this file.

Data Structures

struct  udp_connection
 A UDP connection. More...

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static LIST_HEAD (udp_conns)
 List of registered UDP connections.
static int udp_bind (struct udp_connection *udp)
 Bind UDP connection to local port.
static int udp_open_common (struct xfer_interface *xfer, struct sockaddr *peer, struct sockaddr *local, int promisc)
 Open a UDP connection.
int udp_open (struct xfer_interface *xfer, struct sockaddr *peer, struct sockaddr *local)
 Open a UDP connection.
int udp_open_promisc (struct xfer_interface *xfer)
 Open a promiscuous UDP connection.
static void udp_close (struct udp_connection *udp, int rc)
 Close a UDP connection.
static int udp_tx (struct udp_connection *udp, struct io_buffer *iobuf, struct sockaddr_tcpip *src, struct sockaddr_tcpip *dest, struct net_device *netdev)
 Transmit data via a UDP connection to a specified address.
static struct udp_connectionudp_demux (struct sockaddr_tcpip *local)
 Identify UDP connection by local address.
static int udp_rx (struct io_buffer *iobuf, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum)
 Process a received packet.
static void udp_xfer_close (struct xfer_interface *xfer, int rc)
 Close interface.
static struct io_bufferudp_alloc_iob (struct xfer_interface *xfer, size_t len)
 Allocate I/O buffer for UDP.
static int udp_xfer_deliver_iob (struct xfer_interface *xfer, struct io_buffer *iobuf, struct xfer_metadata *meta)
 Deliver datagram as I/O buffer.
static int udp_open_uri (struct xfer_interface *xfer, struct uri *uri)
 Open UDP URI.

Variables

static struct
xfer_interface_operations 
udp_xfer_operations
 UDP data transfer interface operations.
struct tcpip_protocol udp_protocol
struct tcpip_protocol udp_protocol __tcpip_protocol
struct socket_opener
udp_socket_opener 
__socket_opener
 UDP socket opener.
int udp_sock_dgram = UDP_SOCK_DGRAM
 Linkage hack.
struct uri_opener udp_uri_opener __uri_opener
 UDP URI opener.


Detailed Description

UDP protocol.

Definition in file udp.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER   ) 

static LIST_HEAD ( udp_conns   )  [static]

List of registered UDP connections.

static int udp_bind ( struct udp_connection udp  )  [static]

Bind UDP connection to local port.

Parameters:
udp UDP connection
Return values:
rc Return status code
Opens the UDP connection and binds to the specified local port. If no local port is specified, the first available port will be used.

Definition at line 58 of file udp.c.

References DBGC, EADDRINUSE, htons, udp_connection::list, list_for_each_entry, udp_connection::local, ntohs, and sockaddr_tcpip::st_port.

Referenced by udp_open_common().

00058                                                    {
00059         struct udp_connection *existing;
00060         static uint16_t try_port = 1023;
00061 
00062         /* If no port specified, find the first available port */
00063         if ( ! udp->local.st_port ) {
00064                 while ( try_port ) {
00065                         try_port++;
00066                         if ( try_port < 1024 )
00067                                 continue;
00068                         udp->local.st_port = htons ( try_port );
00069                         if ( udp_bind ( udp ) == 0 )
00070                                 return 0;
00071                 }
00072                 return -EADDRINUSE;
00073         }
00074 
00075         /* Attempt bind to local port */
00076         list_for_each_entry ( existing, &udp_conns, list ) {
00077                 if ( existing->local.st_port == udp->local.st_port ) {
00078                         DBGC ( udp, "UDP %p could not bind: port %d in use\n",
00079                                udp, ntohs ( udp->local.st_port ) );
00080                         return -EADDRINUSE;
00081                 }
00082         }
00083 
00084         /* Add to UDP connection list */
00085         DBGC ( udp, "UDP %p bound to port %d\n",
00086                udp, ntohs ( udp->local.st_port ) );
00087 
00088         return 0;
00089 }

static int udp_open_common ( struct xfer_interface xfer,
struct sockaddr peer,
struct sockaddr local,
int  promisc 
) [static]

Open a UDP connection.

Parameters:
xfer Data transfer interface
peer Peer socket address, or NULL
local Local socket address, or NULL
promisc Socket is promiscuous
Return values:
rc Return status code

Definition at line 100 of file udp.c.

References DBGC, ENOMEM, udp_connection::list, list_add, udp_connection::local, memcpy, udp_connection::peer, ref_put(), udp_connection::refcnt, udp_bind(), udp_xfer_operations, udp_connection::xfer, xfer_init(), and zalloc().

Referenced by udp_open(), and udp_open_promisc().

00102                                            {
00103         struct sockaddr_tcpip *st_peer = ( struct sockaddr_tcpip * ) peer;
00104         struct sockaddr_tcpip *st_local = ( struct sockaddr_tcpip * ) local;
00105         struct udp_connection *udp;
00106         int rc;
00107 
00108         /* Allocate and initialise structure */
00109         udp = zalloc ( sizeof ( *udp ) );
00110         if ( ! udp )
00111                 return -ENOMEM;
00112         DBGC ( udp, "UDP %p allocated\n", udp );
00113         xfer_init ( &udp->xfer, &udp_xfer_operations, &udp->refcnt );
00114         if ( st_peer )
00115                 memcpy ( &udp->peer, st_peer, sizeof ( udp->peer ) );
00116         if ( st_local )
00117                 memcpy ( &udp->local, st_local, sizeof ( udp->local ) );
00118 
00119         /* Bind to local port */
00120         if ( ! promisc ) {
00121                 if ( ( rc = udp_bind ( udp ) ) != 0 )
00122                         goto err;
00123         }
00124 
00125         /* Attach parent interface, transfer reference to connection
00126          * list and return
00127          */
00128         xfer_plug_plug ( &udp->xfer, xfer );
00129         list_add ( &udp->list, &udp_conns );
00130         return 0;
00131 
00132  err:
00133         ref_put ( &udp->refcnt );
00134         return rc;
00135 }

int udp_open ( struct xfer_interface xfer,
struct sockaddr peer,
struct sockaddr local 
)

Open a UDP connection.

Parameters:
xfer Data transfer interface
peer Peer socket address
local Local socket address, or NULL
Return values:
rc Return status code

Definition at line 145 of file udp.c.

References udp_open_common().

00146                                         {
00147         return udp_open_common ( xfer, peer, local, 0 );
00148 }

int udp_open_promisc ( struct xfer_interface xfer  ) 

Open a promiscuous UDP connection.

Parameters:
xfer Data transfer interface
Return values:
rc Return status code
Promiscuous UDP connections are required in order to support the PXE API.

Definition at line 159 of file udp.c.

References NULL, and udp_open_common().

Referenced by pxenv_udp_open().

00159                                                      {
00160         return udp_open_common ( xfer, NULL, NULL, 1 );
00161 }

static void udp_close ( struct udp_connection udp,
int  rc 
) [static]

Close a UDP connection.

Parameters:
udp UDP connection
rc Reason for close

Definition at line 169 of file udp.c.

References DBGC, udp_connection::list, list_del, ref_put(), udp_connection::refcnt, udp_connection::xfer, and xfer_close().

Referenced by udp_xfer_close().

00169                                                              {
00170 
00171         /* Close data transfer interface */
00172         xfer_nullify ( &udp->xfer );
00173         xfer_close ( &udp->xfer, rc );
00174 
00175         /* Remove from list of connections and drop list's reference */
00176         list_del ( &udp->list );
00177         ref_put ( &udp->refcnt );
00178 
00179         DBGC ( udp, "UDP %p closed\n", udp );
00180 }

static int udp_tx ( struct udp_connection udp,
struct io_buffer iobuf,
struct sockaddr_tcpip src,
struct sockaddr_tcpip dest,
struct net_device netdev 
) [static]

Transmit data via a UDP connection to a specified address.

Parameters:
udp UDP connection
iobuf I/O buffer
src Source address, or NULL to use default
dest Destination address, or NULL to use default
netdev Network device, or NULL to use default
Return values:
rc Return status code

Definition at line 192 of file udp.c.

References udp_header::chksum, DBGC, udp_header::dest, free_iob(), htons, iob_ensure_headroom(), iob_len(), iob_push, udp_header::len, udp_connection::local, ntohs, udp_connection::peer, udp_header::src, sockaddr_tcpip::st_port, strerror(), tcpip_chksum(), tcpip_tx(), UDP_MAX_HLEN, and udp_protocol.

Referenced by udp_xfer_deliver_iob().

00194                                                 {
00195         struct udp_header *udphdr;
00196         size_t len;
00197         int rc;
00198 
00199         /* Check we can accommodate the header */
00200         if ( ( rc = iob_ensure_headroom ( iobuf, UDP_MAX_HLEN ) ) != 0 ) {
00201                 free_iob ( iobuf );
00202                 return rc;
00203         }
00204 
00205         /* Fill in default values if not explicitly provided */
00206         if ( ! src )
00207                 src = &udp->local;
00208         if ( ! dest )
00209                 dest = &udp->peer;
00210 
00211         /* Add the UDP header */
00212         udphdr = iob_push ( iobuf, sizeof ( *udphdr ) );
00213         len = iob_len ( iobuf );
00214         udphdr->dest = dest->st_port;
00215         udphdr->src = src->st_port;
00216         udphdr->len = htons ( len );
00217         udphdr->chksum = 0;
00218         udphdr->chksum = tcpip_chksum ( udphdr, len );
00219 
00220         /* Dump debugging information */
00221         DBGC ( udp, "UDP %p TX %d->%d len %d\n", udp,
00222                ntohs ( udphdr->src ), ntohs ( udphdr->dest ),
00223                ntohs ( udphdr->len ) );
00224 
00225         /* Send it to the next layer for processing */
00226         if ( ( rc = tcpip_tx ( iobuf, &udp_protocol, src, dest, netdev,
00227                                &udphdr->chksum ) ) != 0 ) {
00228                 DBGC ( udp, "UDP %p could not transmit packet: %s\n",
00229                        udp, strerror ( rc ) );
00230                 return rc;
00231         }
00232 
00233         return 0;
00234 }

static struct udp_connection* udp_demux ( struct sockaddr_tcpip local  )  [static, read]

Identify UDP connection by local address.

Parameters:
local Local address
Return values:
udp UDP connection, or NULL

Definition at line 242 of file udp.c.

References udp_connection::list, list_for_each_entry, udp_connection::local, memcmp(), NULL, sockaddr_tcpip::pad, sockaddr_tcpip::st_family, and sockaddr_tcpip::st_port.

Referenced by udp_rx().

00242                                                                           {
00243         static const struct sockaddr_tcpip empty_sockaddr = { .pad = { 0, } };
00244         struct udp_connection *udp;
00245 
00246         list_for_each_entry ( udp, &udp_conns, list ) {
00247                 if ( ( ( udp->local.st_family == local->st_family ) ||
00248                        ( udp->local.st_family == 0 ) ) &&
00249                      ( ( udp->local.st_port == local->st_port ) ||
00250                        ( udp->local.st_port == 0 ) ) &&
00251                      ( ( memcmp ( udp->local.pad, local->pad,
00252                                   sizeof ( udp->local.pad ) ) == 0 ) ||
00253                        ( memcmp ( udp->local.pad, empty_sockaddr.pad,
00254                                   sizeof ( udp->local.pad ) ) == 0 ) ) ) {
00255                         return udp;
00256                 }
00257         }
00258         return NULL;
00259 }

static int udp_rx ( struct io_buffer iobuf,
struct sockaddr_tcpip st_src,
struct sockaddr_tcpip st_dest,
uint16_t  pshdr_csum 
) [static]

Process a received packet.

Parameters:
iobuf I/O buffer
st_src Partially-filled source address
st_dest Partially-filled destination address
pshdr_csum Pseudo-header checksum
Return values:
rc Return status code

Definition at line 270 of file udp.c.

References udp_header::chksum, io_buffer::data, DBG, DBGC, xfer_metadata::dest, udp_header::dest, EINVAL, ENOTCONN, free_iob(), iob_disown, iob_len(), iob_pull, iob_unput, udp_header::len, memset(), ntohs, xfer_metadata::src, udp_header::src, sockaddr_tcpip::st_port, tcpip_continue_chksum(), udp_demux(), udp_connection::xfer, and xfer_deliver_iob_meta().

00271                                                                           {
00272         struct udp_header *udphdr = iobuf->data;
00273         struct udp_connection *udp;
00274         struct xfer_metadata meta;
00275         size_t ulen;
00276         unsigned int csum;
00277         int rc = 0;
00278 
00279         /* Sanity check packet */
00280         if ( iob_len ( iobuf ) < sizeof ( *udphdr ) ) {
00281                 DBG ( "UDP packet too short at %zd bytes (min %zd bytes)\n",
00282                       iob_len ( iobuf ), sizeof ( *udphdr ) );
00283                 
00284                 rc = -EINVAL;
00285                 goto done;
00286         }
00287         ulen = ntohs ( udphdr->len );
00288         if ( ulen < sizeof ( *udphdr ) ) {
00289                 DBG ( "UDP length too short at %zd bytes "
00290                       "(header is %zd bytes)\n", ulen, sizeof ( *udphdr ) );
00291                 rc = -EINVAL;
00292                 goto done;
00293         }
00294         if ( ulen > iob_len ( iobuf ) ) {
00295                 DBG ( "UDP length too long at %zd bytes (packet is %zd "
00296                       "bytes)\n", ulen, iob_len ( iobuf ) );
00297                 rc = -EINVAL;
00298                 goto done;
00299         }
00300         if ( udphdr->chksum ) {
00301                 csum = tcpip_continue_chksum ( pshdr_csum, iobuf->data, ulen );
00302                 if ( csum != 0 ) {
00303                         DBG ( "UDP checksum incorrect (is %04x including "
00304                               "checksum field, should be 0000)\n", csum );
00305                         rc = -EINVAL;
00306                         goto done;
00307                 }
00308         }
00309 
00310         /* Parse parameters from header and strip header */
00311         st_src->st_port = udphdr->src;
00312         st_dest->st_port = udphdr->dest;
00313         udp = udp_demux ( st_dest );
00314         iob_unput ( iobuf, ( iob_len ( iobuf ) - ulen ) );
00315         iob_pull ( iobuf, sizeof ( *udphdr ) );
00316 
00317         /* Dump debugging information */
00318         DBGC ( udp, "UDP %p RX %d<-%d len %zd\n", udp,
00319                ntohs ( udphdr->dest ), ntohs ( udphdr->src ), ulen );
00320 
00321         /* Ignore if no matching connection found */
00322         if ( ! udp ) {
00323                 DBG ( "No UDP connection listening on port %d\n",
00324                       ntohs ( udphdr->dest ) );
00325                 rc = -ENOTCONN;
00326                 goto done;
00327         }
00328 
00329         /* Pass data to application */
00330         memset ( &meta, 0, sizeof ( meta ) );
00331         meta.src = ( struct sockaddr * ) st_src;
00332         meta.dest = ( struct sockaddr * ) st_dest;
00333         rc = xfer_deliver_iob_meta ( &udp->xfer, iob_disown ( iobuf ), &meta );
00334 
00335  done:
00336         free_iob ( iobuf );
00337         return rc;
00338 }

static void udp_xfer_close ( struct xfer_interface xfer,
int  rc 
) [static]

Close interface.

Parameters:
xfer Data transfer interface
rc Reason for close

Definition at line 359 of file udp.c.

References container_of, and udp_close().

00359                                                                    {
00360         struct udp_connection *udp =
00361                 container_of ( xfer, struct udp_connection, xfer );
00362 
00363         /* Close connection */
00364         udp_close ( udp, rc );
00365 }

static struct io_buffer* udp_alloc_iob ( struct xfer_interface xfer,
size_t  len 
) [static, read]

Allocate I/O buffer for UDP.

Parameters:
xfer Data transfer interface
len Payload size
Return values:
iobuf I/O buffer, or NULL

Definition at line 374 of file udp.c.

References alloc_iob(), container_of, DBGC, iob_reserve, NULL, and UDP_MAX_HLEN.

00375                                                        {
00376         struct udp_connection *udp =
00377                 container_of ( xfer, struct udp_connection, xfer );     
00378         struct io_buffer *iobuf;
00379 
00380         iobuf = alloc_iob ( UDP_MAX_HLEN + len );
00381         if ( ! iobuf ) {
00382                 DBGC ( udp, "UDP %p cannot allocate buffer of length %zd\n",
00383                        udp, len );
00384                 return NULL;
00385         }
00386         iob_reserve ( iobuf, UDP_MAX_HLEN );
00387         return iobuf;
00388 }

static int udp_xfer_deliver_iob ( struct xfer_interface xfer,
struct io_buffer iobuf,
struct xfer_metadata meta 
) [static]

Deliver datagram as I/O buffer.

Parameters:
xfer Data transfer interface
iobuf Datagram I/O buffer
meta Data transfer metadata
Return values:
rc Return status code

Definition at line 398 of file udp.c.

References container_of, xfer_metadata::dest, xfer_metadata::netdev, xfer_metadata::src, and udp_tx().

00400                                                                {
00401         struct udp_connection *udp =
00402                 container_of ( xfer, struct udp_connection, xfer );
00403 
00404         /* Transmit data, if possible */
00405         udp_tx ( udp, iobuf, ( ( struct sockaddr_tcpip * ) meta->src ),
00406                  ( ( struct sockaddr_tcpip * ) meta->dest ), meta->netdev );
00407 
00408         return 0;
00409 }

static int udp_open_uri ( struct xfer_interface xfer,
struct uri uri 
) [static]

Open UDP URI.

Parameters:
xfer Data transfer interface
uri URI
Return values:
rc Return status code

Definition at line 445 of file udp.c.

References EINVAL, uri::host, htons, memset(), NULL, SOCK_DGRAM, sockaddr_tcpip::st_port, uri_port(), and xfer_open_named_socket().

00445                                                                          {
00446         struct sockaddr_tcpip peer;
00447 
00448         /* Sanity check */
00449         if ( ! uri->host )
00450                 return -EINVAL;
00451 
00452         memset ( &peer, 0, sizeof ( peer ) );
00453         peer.st_port = htons ( uri_port ( uri, 0 ) );
00454         return xfer_open_named_socket ( xfer, SOCK_DGRAM,
00455                                         ( struct sockaddr * ) &peer,
00456                                         uri->host, NULL );
00457 }


Variable Documentation

static struct xfer_interface_operations udp_xfer_operations [static, read]

Initial value:

 {
        .close          = udp_xfer_close,
        .vredirect      = ignore_xfer_vredirect,
        .window         = unlimited_xfer_window,
        .alloc_iob      = udp_alloc_iob,
        .deliver_iob    = udp_xfer_deliver_iob,
        .deliver_raw    = xfer_deliver_as_iob,
}
UDP data transfer interface operations.

Definition at line 46 of file udp.c.

Referenced by udp_open_common().

Definition at line 47 of file udp.c.

Referenced by udp_tx().

Initial value:

 {
        .name = "UDP",
        .rx = udp_rx,
        .tcpip_proto = IP_UDP,
}

Definition at line 340 of file udp.c.

struct socket_opener udp_socket_opener __socket_opener

Initial value:

 {
        .semantics      = UDP_SOCK_DGRAM,
        .family         = AF_INET,
        .open           = udp_open,
}
UDP socket opener.

Definition at line 429 of file udp.c.

struct uri_opener udp_uri_opener __uri_opener

Initial value:

 {
        .scheme         = "udp",
        .open           = udp_open_uri,
}
UDP URI opener.

Definition at line 460 of file udp.c.


Generated on Tue Apr 6 20:01:56 2010 for gPXE by  doxygen 1.5.7.1