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