iPXE
udp.c
Go to the documentation of this file.
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 <ipxe/tcpip.h>
8 #include <ipxe/iobuf.h>
9 #include <ipxe/xfer.h>
10 #include <ipxe/open.h>
11 #include <ipxe/uri.h>
12 #include <ipxe/netdevice.h>
13 #include <ipxe/udp.h>
14 
15 /** @file
16  *
17  * UDP protocol
18  */
19 
20 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
21 FILE_SECBOOT ( PERMITTED );
22 
23 /**
24  * A UDP connection
25  *
26  */
28  /** Reference counter */
29  struct refcnt refcnt;
30  /** List of UDP connections */
31  struct list_head list;
32 
33  /** Data transfer interface */
34  struct interface xfer;
35 
36  /** Local socket address */
38  /** Remote socket address */
40 };
41 
42 /**
43  * List of registered UDP connections
44  */
45 static LIST_HEAD ( udp_conns );
46 
47 /* Forward declatations */
49 struct tcpip_protocol udp_protocol __tcpip_protocol;
50 
51 /**
52  * Check if local UDP port is available
53  *
54  * @v port Local port number
55  * @ret port Local port number, or negative error
56  */
57 static int udp_port_available ( int port ) {
58  struct udp_connection *udp;
59 
60  list_for_each_entry ( udp, &udp_conns, list ) {
61  if ( udp->local.st_port == htons ( port ) )
62  return -EADDRINUSE;
63  }
64  return port;
65 }
66 
67 /**
68  * Open a UDP connection
69  *
70  * @v xfer Data transfer interface
71  * @v peer Peer socket address, or NULL
72  * @v local Local socket address, or NULL
73  * @v promisc Socket is promiscuous
74  * @ret rc Return status code
75  */
76 static int udp_open_common ( struct interface *xfer,
77  struct sockaddr *peer, struct sockaddr *local,
78  int promisc ) {
79  struct sockaddr_tcpip *st_peer = ( struct sockaddr_tcpip * ) peer;
80  struct sockaddr_tcpip *st_local = ( struct sockaddr_tcpip * ) local;
81  struct udp_connection *udp;
82  int port;
83  int rc;
84 
85  /* Allocate and initialise structure */
86  udp = zalloc ( sizeof ( *udp ) );
87  if ( ! udp )
88  return -ENOMEM;
89  DBGC ( udp, "UDP %p allocated\n", udp );
90  ref_init ( &udp->refcnt, NULL );
91  intf_init ( &udp->xfer, &udp_xfer_desc, &udp->refcnt );
92  if ( st_peer )
93  memcpy ( &udp->peer, st_peer, sizeof ( udp->peer ) );
94  if ( st_local )
95  memcpy ( &udp->local, st_local, sizeof ( udp->local ) );
96 
97  /* Bind to local port */
98  if ( ! promisc ) {
99  port = tcpip_bind ( st_local, udp_port_available );
100  if ( port < 0 ) {
101  rc = port;
102  DBGC ( udp, "UDP %p could not bind: %s\n",
103  udp, strerror ( rc ) );
104  goto err;
105  }
106  udp->local.st_port = htons ( port );
107  DBGC ( udp, "UDP %p bound to port %d\n",
108  udp, ntohs ( udp->local.st_port ) );
109  }
110 
111  /* Attach parent interface, transfer reference to connection
112  * list and return
113  */
114  intf_plug_plug ( &udp->xfer, xfer );
115  list_add ( &udp->list, &udp_conns );
116  return 0;
117 
118  err:
119  ref_put ( &udp->refcnt );
120  return rc;
121 }
122 
123 /**
124  * Open a UDP connection
125  *
126  * @v xfer Data transfer interface
127  * @v peer Peer socket address
128  * @v local Local socket address, or NULL
129  * @ret rc Return status code
130  */
131 int udp_open ( struct interface *xfer, struct sockaddr *peer,
132  struct sockaddr *local ) {
133  return udp_open_common ( xfer, peer, local, 0 );
134 }
135 
136 /**
137  * Open a promiscuous UDP connection
138  *
139  * @v xfer Data transfer interface
140  * @ret rc Return status code
141  *
142  * Promiscuous UDP connections are required in order to support the
143  * PXE API.
144  */
145 int udp_open_promisc ( struct interface *xfer ) {
146  return udp_open_common ( xfer, NULL, NULL, 1 );
147 }
148 
149 /**
150  * Close a UDP connection
151  *
152  * @v udp UDP connection
153  * @v rc Reason for close
154  */
155 static void udp_close ( struct udp_connection *udp, int rc ) {
156 
157  /* Close data transfer interface */
158  intf_shutdown ( &udp->xfer, rc );
159 
160  /* Remove from list of connections and drop list's reference */
161  list_del ( &udp->list );
162  ref_put ( &udp->refcnt );
163 
164  DBGC ( udp, "UDP %p closed\n", udp );
165 }
166 
167 /**
168  * Transmit data via a UDP connection to a specified address
169  *
170  * @v udp UDP connection
171  * @v iobuf I/O buffer
172  * @v src Source address, or NULL to use default
173  * @v dest Destination address, or NULL to use default
174  * @v netdev Network device, or NULL to use default
175  * @ret rc Return status code
176  */
177 static int udp_tx ( struct udp_connection *udp, struct io_buffer *iobuf,
178  struct sockaddr_tcpip *src, struct sockaddr_tcpip *dest,
179  struct net_device *netdev ) {
180  struct udp_header *udphdr;
181  size_t len;
182  int rc;
183 
184  /* Check we can accommodate the header */
185  if ( ( rc = iob_ensure_headroom ( iobuf,
186  MAX_LL_NET_HEADER_LEN ) ) != 0 ) {
187  free_iob ( iobuf );
188  return rc;
189  }
190 
191  /* Fill in default values if not explicitly provided */
192  if ( ! src )
193  src = &udp->local;
194  if ( ! dest )
195  dest = &udp->peer;
196 
197  /* Add the UDP header */
198  udphdr = iob_push ( iobuf, sizeof ( *udphdr ) );
199  len = iob_len ( iobuf );
200  udphdr->dest = dest->st_port;
201  udphdr->src = src->st_port;
202  udphdr->len = htons ( len );
203  udphdr->chksum = 0;
204  udphdr->chksum = tcpip_chksum ( udphdr, len );
205 
206  /* Dump debugging information */
207  DBGC2 ( udp, "UDP %p TX %d->%d len %d\n", udp,
208  ntohs ( udphdr->src ), ntohs ( udphdr->dest ),
209  ntohs ( udphdr->len ) );
210 
211  /* Send it to the next layer for processing */
212  if ( ( rc = tcpip_tx ( iobuf, &udp_protocol, src, dest, netdev,
213  &udphdr->chksum ) ) != 0 ) {
214  DBGC ( udp, "UDP %p could not transmit packet: %s\n",
215  udp, strerror ( rc ) );
216  return rc;
217  }
218 
219  return 0;
220 }
221 
222 /**
223  * Identify UDP connection by local address
224  *
225  * @v local Local address
226  * @ret udp UDP connection, or NULL
227  */
228 static struct udp_connection * udp_demux ( struct sockaddr_tcpip *local ) {
229  static const struct sockaddr_tcpip empty_sockaddr = { .pad = { 0, } };
230  struct udp_connection *udp;
231 
232  list_for_each_entry ( udp, &udp_conns, list ) {
233  if ( ( ( udp->local.st_family == local->st_family ) ||
234  ( udp->local.st_family == 0 ) ) &&
235  ( ( udp->local.st_port == local->st_port ) ||
236  ( udp->local.st_port == 0 ) ) &&
237  ( ( memcmp ( udp->local.pad, local->pad,
238  sizeof ( udp->local.pad ) ) == 0 ) ||
239  ( memcmp ( udp->local.pad, empty_sockaddr.pad,
240  sizeof ( udp->local.pad ) ) == 0 ) ) ) {
241  return udp;
242  }
243  }
244  return NULL;
245 }
246 
247 /**
248  * Process a received packet
249  *
250  * @v iobuf I/O buffer
251  * @v netdev Network device
252  * @v st_src Partially-filled source address
253  * @v st_dest Partially-filled destination address
254  * @v pshdr_csum Pseudo-header checksum
255  * @ret rc Return status code
256  */
257 static int udp_rx ( struct io_buffer *iobuf,
258  struct net_device *netdev __unused,
259  struct sockaddr_tcpip *st_src,
260  struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum ) {
261  struct udp_header *udphdr = iobuf->data;
262  struct udp_connection *udp;
263  struct xfer_metadata meta;
264  size_t ulen;
265  unsigned int csum;
266  int rc = 0;
267 
268  /* Sanity check packet */
269  if ( iob_len ( iobuf ) < sizeof ( *udphdr ) ) {
270  DBG ( "UDP packet too short at %zd bytes (min %zd bytes)\n",
271  iob_len ( iobuf ), sizeof ( *udphdr ) );
272 
273  rc = -EINVAL;
274  goto done;
275  }
276  ulen = ntohs ( udphdr->len );
277  if ( ulen < sizeof ( *udphdr ) ) {
278  DBG ( "UDP length too short at %zd bytes "
279  "(header is %zd bytes)\n", ulen, sizeof ( *udphdr ) );
280  rc = -EINVAL;
281  goto done;
282  }
283  if ( ulen > iob_len ( iobuf ) ) {
284  DBG ( "UDP length too long at %zd bytes (packet is %zd "
285  "bytes)\n", ulen, iob_len ( iobuf ) );
286  rc = -EINVAL;
287  goto done;
288  }
289  if ( udphdr->chksum ) {
290  csum = tcpip_continue_chksum ( pshdr_csum, iobuf->data, ulen );
291  if ( csum != 0 ) {
292  DBG ( "UDP checksum incorrect (is %04x including "
293  "checksum field, should be 0000)\n", csum );
294  rc = -EINVAL;
295  goto done;
296  }
297  }
298 
299  /* Parse parameters from header and strip header */
300  st_src->st_port = udphdr->src;
301  st_dest->st_port = udphdr->dest;
302  udp = udp_demux ( st_dest );
303  iob_unput ( iobuf, ( iob_len ( iobuf ) - ulen ) );
304  iob_pull ( iobuf, sizeof ( *udphdr ) );
305 
306  /* Dump debugging information */
307  DBGC2 ( udp, "UDP %p RX %d<-%d len %zd\n", udp,
308  ntohs ( udphdr->dest ), ntohs ( udphdr->src ), ulen );
309 
310  /* Ignore if no matching connection found */
311  if ( ! udp ) {
312  DBG ( "No UDP connection listening on port %d\n",
313  ntohs ( udphdr->dest ) );
314  rc = -ENOTCONN;
315  goto done;
316  }
317 
318  /* Pass data to application */
319  memset ( &meta, 0, sizeof ( meta ) );
320  meta.src = ( struct sockaddr * ) st_src;
321  meta.dest = ( struct sockaddr * ) st_dest;
322  rc = xfer_deliver ( &udp->xfer, iob_disown ( iobuf ), &meta );
323 
324  done:
325  free_iob ( iobuf );
326  return rc;
327 }
328 
329 struct tcpip_protocol udp_protocol __tcpip_protocol = {
330  .name = "UDP",
331  .rx = udp_rx,
332  .zero_csum = TCPIP_NEGATIVE_ZERO_CSUM,
333  .tcpip_proto = IP_UDP,
334 };
335 
336 /***************************************************************************
337  *
338  * Data transfer interface
339  *
340  ***************************************************************************
341  */
342 
343 /**
344  * Allocate I/O buffer for UDP
345  *
346  * @v udp UDP connection
347  * @v len Payload size
348  * @ret iobuf I/O buffer, or NULL
349  */
350 static struct io_buffer * udp_xfer_alloc_iob ( struct udp_connection *udp,
351  size_t len ) {
352  struct io_buffer *iobuf;
353 
354  iobuf = alloc_iob ( MAX_LL_NET_HEADER_LEN + len );
355  if ( ! iobuf ) {
356  DBGC ( udp, "UDP %p cannot allocate buffer of length %zd\n",
357  udp, len );
358  return NULL;
359  }
361  return iobuf;
362 }
363 
364 /**
365  * Deliver datagram as I/O buffer
366  *
367  * @v udp UDP connection
368  * @v iobuf Datagram I/O buffer
369  * @v meta Data transfer metadata
370  * @ret rc Return status code
371  */
372 static int udp_xfer_deliver ( struct udp_connection *udp,
373  struct io_buffer *iobuf,
374  struct xfer_metadata *meta ) {
375 
376  /* Transmit data, if possible */
377  return udp_tx ( udp, iobuf, ( ( struct sockaddr_tcpip * ) meta->src ),
378  ( ( struct sockaddr_tcpip * ) meta->dest ),
379  meta->netdev );
380 }
381 
382 /** UDP data transfer interface operations */
387 };
388 
389 /** UDP data transfer interface descriptor */
390 static struct interface_descriptor udp_xfer_desc =
391  INTF_DESC ( struct udp_connection, xfer, udp_xfer_operations );
392 
393 /***************************************************************************
394  *
395  * Openers
396  *
397  ***************************************************************************
398  */
399 
400 /** UDP socket opener */
401 struct socket_opener udp_socket_opener __socket_opener = {
403  .open = udp_open,
404 };
405 
406 /** Linkage hack */
408 
409 /**
410  * Open UDP URI
411  *
412  * @v xfer Data transfer interface
413  * @v uri URI
414  * @ret rc Return status code
415  */
416 static int udp_open_uri ( struct interface *xfer, struct uri *uri ) {
417  struct sockaddr_tcpip peer;
418 
419  /* Sanity check */
420  if ( ! uri->host )
421  return -EINVAL;
422 
423  memset ( &peer, 0, sizeof ( peer ) );
424  peer.st_port = htons ( uri_port ( uri, 0 ) );
425  return xfer_open_named_socket ( xfer, SOCK_DGRAM,
426  ( struct sockaddr * ) &peer,
427  uri->host, NULL );
428 }
429 
430 /** UDP URI opener */
431 struct uri_opener udp_uri_opener __uri_opener = {
432  .scheme = "udp",
433  .open = udp_open_uri,
434 };
#define iob_pull(iobuf, len)
Definition: iobuf.h:107
#define EINVAL
Invalid argument.
Definition: errno.h:429
An object interface operation.
Definition: interface.h:18
#define TCPIP_NEGATIVE_ZERO_CSUM
Negative zero checksum value.
Definition: tcpip.h:31
TCP/IP socket address.
Definition: tcpip.h:76
struct interface xfer
Data transfer interface.
Definition: udp.c:34
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
unsigned short uint16_t
Definition: stdint.h:11
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:250
Data transfer metadata.
Definition: xfer.h:23
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition: interface.c:279
char pad[sizeof(struct sockaddr) -(sizeof(sa_family_t)+sizeof(uint16_t)+sizeof(uint16_t)+sizeof(uint16_t))]
Padding.
Definition: tcpip.h:99
uint16_t chksum
Checksum.
Definition: udp.h:38
static void udp_close(struct udp_connection *udp, int rc)
Close a UDP connection.
Definition: udp.c:155
static int udp_port_available(int port)
Check if local UDP port is available.
Definition: udp.c:57
#define IP_UDP
Definition: in.h:15
#define list_add(new, head)
Add a new entry to the head of a list.
Definition: list.h:70
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:65
Error codes.
#define iob_push(iobuf, len)
Definition: iobuf.h:89
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:153
#define SOCK_DGRAM
Definition: socket.h:30
sa_family_t st_family
Socket address family (part of struct sockaddr)
Definition: tcpip.h:78
#define EADDRINUSE
Address already in use.
Definition: errno.h:304
#define DBGC(...)
Definition: compiler.h:505
static struct interface_descriptor udp_xfer_desc
UDP data transfer interface descriptor.
Definition: udp.c:48
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition: interface.c:108
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition: xfer.c:159
struct refcnt refcnt
Reference counter.
Definition: udp.c:29
#define ntohs(value)
Definition: byteswap.h:137
Uniform Resource Identifiers.
struct io_buffer * alloc_iob(size_t len)
Allocate I/O buffer.
Definition: iobuf.c:131
int semantics
Communication semantics (e.g.
Definition: open.h:73
static LIST_HEAD(udp_conns)
List of registered UDP connections.
struct list_head list
List of UDP connections.
Definition: udp.c:31
uint16_t src
Source port.
Definition: udp.h:32
int tcpip_bind(struct sockaddr_tcpip *st_local, int(*available)(int port))
Bind to local TCP/IP port.
Definition: tcpip.c:215
A doubly-linked list entry (or list head)
Definition: list.h:19
Data transfer interfaces.
A reference counter.
Definition: refcnt.h:27
uint16_t len
Length.
Definition: udp.h:36
#define UDP_SOCK_DGRAM
Definition: socket.h:29
#define list_del(list)
Delete an entry from a list.
Definition: list.h:120
#define ENOMEM
Not enough space.
Definition: errno.h:535
#define iob_disown(iobuf)
Disown an I/O buffer.
Definition: iobuf.h:217
A UDP connection.
Definition: udp.c:27
void * memcpy(void *dest, const void *src, size_t len) __nonnull
u8 port
Port number.
Definition: CIB_PRM.h:31
FILE_SECBOOT(PERMITTED)
Assertions.
#define MAX_LL_NET_HEADER_LEN
Maximum combined length of a link-layer and network-layer header.
Definition: netdevice.h:59
An object interface.
Definition: interface.h:125
static const void * src
Definition: string.h:48
#define list_for_each_entry(pos, head, member)
Iterate over entries in a list.
Definition: list.h:432
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
struct tcpip_protocol udp_protocol __tcpip_protocol
ICMPv4 TCP/IP protocol.
Definition: udp.c:49
ring len
Length.
Definition: dwmac.h:231
static struct net_device * netdev
Definition: gdbudp.c:52
const char * scheme
URI protocol name.
Definition: open.h:54
Transport-network layer interface.
static int udp_rx(struct io_buffer *iobuf, struct net_device *netdev __unused, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum)
Process a received packet.
Definition: udp.c:257
static struct interface_operation udp_xfer_operations[]
UDP data transfer interface operations.
Definition: udp.c:383
int udp_open_promisc(struct interface *xfer)
Open a promiscuous UDP connection.
Definition: udp.c:145
#define ENOTCONN
The socket is not connected.
Definition: errno.h:570
uint16_t st_port
TCP/IP port.
Definition: tcpip.h:82
const char * name
Protocol name.
Definition: tcpip.h:107
Generalized socket address structure.
Definition: socket.h:97
An object interface descriptor.
Definition: interface.h:56
#define iob_unput(iobuf, len)
Definition: iobuf.h:140
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:662
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:160
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:33
static struct udp_connection * udp_demux(struct sockaddr_tcpip *local)
Identify UDP connection by local address.
Definition: udp.c:228
A network device.
Definition: netdevice.h:353
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:195
Data transfer interface opening.
const char * host
Host name.
Definition: uri.h:77
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.
Definition: udp.c:177
uint16_t dest
Destination port.
Definition: udp.h:34
int udp_sock_dgram
Linkage hack.
Definition: udp.c:407
static int udp_xfer_deliver(struct udp_connection *udp, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram as I/O buffer.
Definition: udp.c:372
A transport-layer protocol of the TCP/IP stack (eg.
Definition: tcpip.h:105
Network device management.
#define iob_reserve(iobuf, len)
Definition: iobuf.h:72
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:81
struct socket_opener udp_socket_opener __socket_opener
UDP socket opener.
Definition: udp.c:401
int udp_open(struct interface *xfer, struct sockaddr *peer, struct sockaddr *local)
Open a UDP connection.
Definition: udp.c:131
#define DBGC2(...)
Definition: compiler.h:522
struct sockaddr_tcpip local
Local socket address.
Definition: udp.c:37
void * data
Start of data.
Definition: iobuf.h:53
static int udp_open_common(struct interface *xfer, struct sockaddr *peer, struct sockaddr *local, int promisc)
Open a UDP connection.
Definition: udp.c:76
unsigned int uri_port(const struct uri *uri, unsigned int default_port)
Get port from URI.
Definition: uri.c:456
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" return dest
Definition: string.h:151
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
struct sockaddr_tcpip peer
Remote socket address.
Definition: udp.c:39
A Uniform Resource Identifier.
Definition: uri.h:65
struct mschapv2_challenge peer
Peer challenge.
Definition: mschapv2.h:12
uint8_t meta
Metadata flags.
Definition: ena.h:14
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition: interface.h:204
UDP constants.
Definition: udp.h:30
A URI opener.
Definition: open.h:48
int tcpip_tx(struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest, struct net_device *netdev, uint16_t *trans_csum)
Transmit a TCP/IP packet.
Definition: tcpip.c:92
int iob_ensure_headroom(struct io_buffer *iobuf, size_t len)
Ensure I/O buffer has sufficient headroom.
Definition: iobuf.c:235
uint16_t tcpip_chksum(const void *data, size_t len)
Calculate TCP/IP checkum.
Definition: tcpip.c:204
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:115
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
String functions.
#define htons(value)
Definition: byteswap.h:136
struct bofm_section_header done
Definition: bofm_test.c:46
UDP protocol.
uint16_t tcpip_continue_chksum(uint16_t partial, const void *data, size_t len)
Calculate continued TCP/IP checkum.
Definition: x86_tcpip.c:46
int xfer_open_named_socket(struct interface *xfer, int semantics, struct sockaddr *peer, const char *name, struct sockaddr *local)
Open named socket.
Definition: resolv.c:403
struct uri_opener udp_uri_opener __uri_opener
UDP URI opener.
Definition: udp.c:431
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:107
static struct io_buffer * udp_xfer_alloc_iob(struct udp_connection *udp, size_t len)
Allocate I/O buffer for UDP.
Definition: udp.c:350
static int udp_open_uri(struct interface *xfer, struct uri *uri)
Open UDP URI.
Definition: udp.c:416
void * memset(void *dest, int character, size_t len) __nonnull
A socket opener.
Definition: open.h:71
A persistent I/O buffer.
Definition: iobuf.h:38