iPXE
pxe_udp.c
Go to the documentation of this file.
1 /** @file
2  *
3  * PXE UDP API
4  *
5  */
6 
7 #include <string.h>
8 #include <byteswap.h>
9 #include <ipxe/iobuf.h>
10 #include <ipxe/xfer.h>
11 #include <ipxe/udp.h>
12 #include <ipxe/uaccess.h>
13 #include <ipxe/process.h>
14 #include <ipxe/netdevice.h>
15 #include <ipxe/malloc.h>
16 #include <realmode.h>
17 #include <pxe.h>
18 
19 /*
20  * Copyright (C) 2004 Michael Brown <mbrown@fensystems.co.uk>.
21  *
22  * This program is free software; you can redistribute it and/or
23  * modify it under the terms of the GNU General Public License as
24  * published by the Free Software Foundation; either version 2 of the
25  * License, or any later version.
26  *
27  * This program is distributed in the hope that it will be useful, but
28  * WITHOUT ANY WARRANTY; without even the implied warranty of
29  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30  * General Public License for more details.
31  *
32  * You should have received a copy of the GNU General Public License
33  * along with this program; if not, write to the Free Software
34  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
35  * 02110-1301, USA.
36  *
37  * You can also choose to distribute this program under the terms of
38  * the Unmodified Binary Distribution Licence (as given in the file
39  * COPYING.UBDL), provided that you have satisfied its requirements.
40  */
41 
42 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
43 
44 /** A PXE UDP pseudo-header */
46  /** Source IP address */
48  /** Source port */
50  /** Destination IP address */
52  /** Destination port */
54 } __attribute__ (( packed ));
55 
56 /** A PXE UDP connection */
58  /** Data transfer interface to UDP stack */
59  struct interface xfer;
60  /** Local address */
62  /** List of received packets */
63  struct list_head list;
64 };
65 
66 /**
67  * Receive PXE UDP data
68  *
69  * @v pxe_udp PXE UDP connection
70  * @v iobuf I/O buffer
71  * @v meta Data transfer metadata
72  * @ret rc Return status code
73  *
74  * Receives a packet as part of the current pxenv_udp_read()
75  * operation.
76  */
78  struct io_buffer *iobuf,
79  struct xfer_metadata *meta ) {
80  struct pxe_udp_pseudo_header *pshdr;
81  struct sockaddr_in *sin_src;
82  struct sockaddr_in *sin_dest;
83  int rc;
84 
85  /* Extract metadata */
86  assert ( meta );
87  sin_src = ( struct sockaddr_in * ) meta->src;
88  assert ( sin_src );
89  assert ( sin_src->sin_family == AF_INET );
90  sin_dest = ( struct sockaddr_in * ) meta->dest;
91  assert ( sin_dest );
92  assert ( sin_dest->sin_family == AF_INET );
93 
94  /* Construct pseudo-header */
95  if ( ( rc = iob_ensure_headroom ( iobuf, sizeof ( *pshdr ) ) ) != 0 ) {
96  DBG ( "PXE could not prepend pseudo-header\n" );
97  rc = -ENOMEM;
98  goto drop;
99  }
100  pshdr = iob_push ( iobuf, sizeof ( *pshdr ) );
101  pshdr->src_ip = sin_src->sin_addr.s_addr;
102  pshdr->s_port = sin_src->sin_port;
103  pshdr->dest_ip = sin_dest->sin_addr.s_addr;
104  pshdr->d_port = sin_dest->sin_port;
105 
106  /* Add to queue */
107  list_add_tail ( &iobuf->list, &pxe_udp->list );
108 
109  return 0;
110 
111  drop:
112  free_iob ( iobuf );
113  return rc;
114 }
115 
116 /** PXE UDP data transfer interface operations */
119 };
120 
121 /** PXE UDP data transfer interface descriptor */
124 
125 /** The PXE UDP connection */
126 static struct pxe_udp_connection pxe_udp = {
128  .local = {
129  .sin_family = AF_INET,
130  },
131  .list = LIST_HEAD_INIT ( pxe_udp.list ),
132 };
133 
134 /**
135  * UDP OPEN
136  *
137  * @v pxenv_udp_open Pointer to a struct s_PXENV_UDP_OPEN
138  * @v s_PXENV_UDP_OPEN::src_ip IP address of this station, or 0.0.0.0
139  * @ret #PXENV_EXIT_SUCCESS Always
140  * @ret s_PXENV_UDP_OPEN::Status PXE status code
141  * @err #PXENV_STATUS_UDP_OPEN UDP connection already open
142  * @err #PXENV_STATUS_OUT_OF_RESOURCES Could not open connection
143  *
144  * Prepares the PXE stack for communication using pxenv_udp_write()
145  * and pxenv_udp_read().
146  *
147  * The IP address supplied in s_PXENV_UDP_OPEN::src_ip will be
148  * recorded and used as the local station's IP address for all further
149  * communication, including communication by means other than
150  * pxenv_udp_write() and pxenv_udp_read(). (If
151  * s_PXENV_UDP_OPEN::src_ip is 0.0.0.0, the local station's IP address
152  * will remain unchanged.)
153  *
154  * You can only have one open UDP connection at a time. This is not a
155  * meaningful restriction, since pxenv_udp_write() and
156  * pxenv_udp_read() allow you to specify arbitrary local and remote
157  * ports and an arbitrary remote address for each packet. According
158  * to the PXE specifiation, you cannot have a UDP connection open at
159  * the same time as a TFTP connection; this restriction does not apply
160  * to Etherboot.
161  *
162  * On x86, you must set the s_PXE::StatusCallout field to a nonzero
163  * value before calling this function in protected mode. You cannot
164  * call this function with a 32-bit stack segment. (See the relevant
165  * @ref pxe_x86_pmode16 "implementation note" for more details.)
166  *
167  * @note The PXE specification does not make it clear whether the IP
168  * address supplied in s_PXENV_UDP_OPEN::src_ip should be used only
169  * for this UDP connection, or retained for all future communication.
170  * The latter seems more consistent with typical PXE stack behaviour.
171  *
172  * @note Etherboot currently ignores the s_PXENV_UDP_OPEN::src_ip
173  * parameter.
174  *
175  */
177  int rc;
178 
179  DBG ( "PXENV_UDP_OPEN" );
180 
181  /* Record source IP address */
183  DBG ( " %s\n", inet_ntoa ( pxe_udp.local.sin_addr ) );
184 
185  /* Open network device, if necessary */
186  if ( pxe_netdev && ( ! netdev_is_open ( pxe_netdev ) ) &&
187  ( ( rc = netdev_open ( pxe_netdev ) ) != 0 ) ) {
188  DBG ( "PXENV_UDP_OPEN could not (implicitly) open %s: %s\n",
189  pxe_netdev->name, strerror ( rc ) );
190  pxenv_udp_open->Status = PXENV_STATUS ( rc );
191  return PXENV_EXIT_FAILURE;
192  }
193 
194  /* Open promiscuous UDP connection */
195  intf_restart ( &pxe_udp.xfer, 0 );
196  if ( ( rc = udp_open_promisc ( &pxe_udp.xfer ) ) != 0 ) {
197  DBG ( "PXENV_UDP_OPEN could not open promiscuous socket: %s\n",
198  strerror ( rc ) );
199  pxenv_udp_open->Status = PXENV_STATUS ( rc );
200  return PXENV_EXIT_FAILURE;
201  }
202 
204  return PXENV_EXIT_SUCCESS;
205 }
206 
207 /**
208  * UDP CLOSE
209  *
210  * @v pxenv_udp_close Pointer to a struct s_PXENV_UDP_CLOSE
211  * @ret #PXENV_EXIT_SUCCESS Always
212  * @ret s_PXENV_UDP_CLOSE::Status PXE status code
213  * @err None -
214  *
215  * Closes a UDP connection opened with pxenv_udp_open().
216  *
217  * You can only have one open UDP connection at a time. You cannot
218  * have a UDP connection open at the same time as a TFTP connection.
219  * You cannot use pxenv_udp_close() to close a TFTP connection; use
220  * pxenv_tftp_close() instead.
221  *
222  * On x86, you must set the s_PXE::StatusCallout field to a nonzero
223  * value before calling this function in protected mode. You cannot
224  * call this function with a 32-bit stack segment. (See the relevant
225  * @ref pxe_x86_pmode16 "implementation note" for more details.)
226  *
227  */
228 static PXENV_EXIT_t
230  struct io_buffer *iobuf;
231  struct io_buffer *tmp;
232 
233  DBG ( "PXENV_UDP_CLOSE\n" );
234 
235  /* Close UDP connection */
236  intf_restart ( &pxe_udp.xfer, 0 );
237 
238  /* Discard any received packets */
240  list_del ( &iobuf->list );
241  free_iob ( iobuf );
242  }
243 
245  return PXENV_EXIT_SUCCESS;
246 }
247 
248 /**
249  * UDP WRITE
250  *
251  * @v pxenv_udp_write Pointer to a struct s_PXENV_UDP_WRITE
252  * @v s_PXENV_UDP_WRITE::ip Destination IP address
253  * @v s_PXENV_UDP_WRITE::gw Relay agent IP address, or 0.0.0.0
254  * @v s_PXENV_UDP_WRITE::src_port Source UDP port, or 0
255  * @v s_PXENV_UDP_WRITE::dst_port Destination UDP port
256  * @v s_PXENV_UDP_WRITE::buffer_size Length of the UDP payload
257  * @v s_PXENV_UDP_WRITE::buffer Address of the UDP payload
258  * @ret #PXENV_EXIT_SUCCESS Packet was transmitted successfully
259  * @ret #PXENV_EXIT_FAILURE Packet could not be transmitted
260  * @ret s_PXENV_UDP_WRITE::Status PXE status code
261  * @err #PXENV_STATUS_UDP_CLOSED UDP connection is not open
262  * @err #PXENV_STATUS_UNDI_TRANSMIT_ERROR Could not transmit packet
263  *
264  * Transmits a single UDP packet. A valid IP and UDP header will be
265  * prepended to the payload in s_PXENV_UDP_WRITE::buffer; the buffer
266  * should not contain precomputed IP and UDP headers, nor should it
267  * contain space allocated for these headers. The first byte of the
268  * buffer will be transmitted as the first byte following the UDP
269  * header.
270  *
271  * If s_PXENV_UDP_WRITE::gw is 0.0.0.0, normal IP routing will take
272  * place. See the relevant @ref pxe_routing "implementation note" for
273  * more details.
274  *
275  * If s_PXENV_UDP_WRITE::src_port is 0, port 2069 will be used.
276  *
277  * You must have opened a UDP connection with pxenv_udp_open() before
278  * calling pxenv_udp_write().
279  *
280  * On x86, you must set the s_PXE::StatusCallout field to a nonzero
281  * value before calling this function in protected mode. You cannot
282  * call this function with a 32-bit stack segment. (See the relevant
283  * @ref pxe_x86_pmode16 "implementation note" for more details.)
284  *
285  * @note Etherboot currently ignores the s_PXENV_UDP_WRITE::gw
286  * parameter.
287  *
288  */
289 static PXENV_EXIT_t
291  struct sockaddr_in dest;
292  struct xfer_metadata meta = {
293  .src = ( struct sockaddr * ) &pxe_udp.local,
294  .dest = ( struct sockaddr * ) &dest,
295  .netdev = pxe_netdev,
296  };
297  size_t len;
298  struct io_buffer *iobuf;
300  int rc;
301 
302  DBG ( "PXENV_UDP_WRITE" );
303 
304  /* Construct destination socket address */
305  memset ( &dest, 0, sizeof ( dest ) );
306  dest.sin_family = AF_INET;
307  dest.sin_addr.s_addr = pxenv_udp_write->ip;
308  dest.sin_port = pxenv_udp_write->dst_port;
309 
310  /* Set local (source) port. PXE spec says source port is 2069
311  * if not specified. Really, this ought to be set at UDP open
312  * time but hey, we didn't design this API.
313  */
315  if ( ! pxe_udp.local.sin_port )
316  pxe_udp.local.sin_port = htons ( 2069 );
317 
318  /* FIXME: we ignore the gateway specified, since we're
319  * confident of being able to do our own routing. We should
320  * probably allow for multiple gateways.
321  */
322 
323  /* Allocate and fill data buffer */
324  len = pxenv_udp_write->buffer_size;
325  iobuf = xfer_alloc_iob ( &pxe_udp.xfer, len );
326  if ( ! iobuf ) {
327  DBG ( " out of memory\n" );
329  return PXENV_EXIT_FAILURE;
330  }
331  buffer = real_to_user ( pxenv_udp_write->buffer.segment,
332  pxenv_udp_write->buffer.offset );
333  copy_from_user ( iob_put ( iobuf, len ), buffer, 0, len );
334 
335  DBG ( " %04x:%04x+%x %d->%s:%d\n", pxenv_udp_write->buffer.segment,
336  pxenv_udp_write->buffer.offset, pxenv_udp_write->buffer_size,
337  ntohs ( pxenv_udp_write->src_port ),
338  inet_ntoa ( dest.sin_addr ),
339  ntohs ( pxenv_udp_write->dst_port ) );
340 
341  /* Transmit packet */
342  if ( ( rc = xfer_deliver ( &pxe_udp.xfer, iobuf, &meta ) ) != 0 ) {
343  DBG ( "PXENV_UDP_WRITE could not transmit: %s\n",
344  strerror ( rc ) );
345  pxenv_udp_write->Status = PXENV_STATUS ( rc );
346  return PXENV_EXIT_FAILURE;
347  }
348 
350  return PXENV_EXIT_SUCCESS;
351 }
352 
353 /**
354  * UDP READ
355  *
356  * @v pxenv_udp_read Pointer to a struct s_PXENV_UDP_READ
357  * @v s_PXENV_UDP_READ::dest_ip Destination IP address, or 0.0.0.0
358  * @v s_PXENV_UDP_READ::d_port Destination UDP port, or 0
359  * @v s_PXENV_UDP_READ::buffer_size Size of the UDP payload buffer
360  * @v s_PXENV_UDP_READ::buffer Address of the UDP payload buffer
361  * @ret #PXENV_EXIT_SUCCESS A packet has been received
362  * @ret #PXENV_EXIT_FAILURE No packet has been received
363  * @ret s_PXENV_UDP_READ::Status PXE status code
364  * @ret s_PXENV_UDP_READ::src_ip Source IP address
365  * @ret s_PXENV_UDP_READ::dest_ip Destination IP address
366  * @ret s_PXENV_UDP_READ::s_port Source UDP port
367  * @ret s_PXENV_UDP_READ::d_port Destination UDP port
368  * @ret s_PXENV_UDP_READ::buffer_size Length of UDP payload
369  * @err #PXENV_STATUS_UDP_CLOSED UDP connection is not open
370  * @err #PXENV_STATUS_FAILURE No packet was ready to read
371  *
372  * Receive a single UDP packet. This is a non-blocking call; if no
373  * packet is ready to read, the call will return instantly with
374  * s_PXENV_UDP_READ::Status==PXENV_STATUS_FAILURE.
375  *
376  * If s_PXENV_UDP_READ::dest_ip is 0.0.0.0, UDP packets addressed to
377  * any IP address will be accepted and may be returned to the caller.
378  *
379  * If s_PXENV_UDP_READ::d_port is 0, UDP packets addressed to any UDP
380  * port will be accepted and may be returned to the caller.
381  *
382  * You must have opened a UDP connection with pxenv_udp_open() before
383  * calling pxenv_udp_read().
384  *
385  * On x86, you must set the s_PXE::StatusCallout field to a nonzero
386  * value before calling this function in protected mode. You cannot
387  * call this function with a 32-bit stack segment. (See the relevant
388  * @ref pxe_x86_pmode16 "implementation note" for more details.)
389  *
390  * @note The PXE specification (version 2.1) does not state that we
391  * should fill in s_PXENV_UDP_READ::dest_ip and
392  * s_PXENV_UDP_READ::d_port, but Microsoft Windows' NTLDR program
393  * expects us to do so, and will fail if we don't.
394  *
395  */
397  struct in_addr dest_ip_wanted = { .s_addr = pxenv_udp_read->dest_ip };
398  struct in_addr dest_ip;
399  struct io_buffer *iobuf;
400  struct pxe_udp_pseudo_header *pshdr;
401  uint16_t d_port_wanted = pxenv_udp_read->d_port;
404  size_t len;
405 
406  /* Try receiving a packet, if the queue is empty */
407  if ( list_empty ( &pxe_udp.list ) )
408  step();
409 
410  /* Remove first packet from the queue */
411  iobuf = list_first_entry ( &pxe_udp.list, struct io_buffer, list );
412  if ( ! iobuf ) {
413  /* No packet received */
414  DBG2 ( "PXENV_UDP_READ\n" );
415  goto no_packet;
416  }
417  list_del ( &iobuf->list );
418 
419  /* Strip pseudo-header */
420  assert ( iob_len ( iobuf ) >= sizeof ( *pshdr ) );
421  pshdr = iobuf->data;
422  iob_pull ( iobuf, sizeof ( *pshdr ) );
423  dest_ip.s_addr = pshdr->dest_ip;
424  d_port = pshdr->d_port;
425  DBG ( "PXENV_UDP_READ" );
426 
427  /* Filter on destination address and/or port */
428  if ( dest_ip_wanted.s_addr &&
429  ( dest_ip_wanted.s_addr != dest_ip.s_addr ) ) {
430  DBG ( " wrong IP %s", inet_ntoa ( dest_ip ) );
431  DBG ( " (wanted %s)\n", inet_ntoa ( dest_ip_wanted ) );
432  goto drop;
433  }
434  if ( d_port_wanted && ( d_port_wanted != d_port ) ) {
435  DBG ( " wrong port %d", htons ( d_port ) );
436  DBG ( " (wanted %d)\n", htons ( d_port_wanted ) );
437  goto drop;
438  }
439 
440  /* Copy packet to buffer and record length */
441  buffer = real_to_user ( pxenv_udp_read->buffer.segment,
442  pxenv_udp_read->buffer.offset );
443  len = iob_len ( iobuf );
444  if ( len > pxenv_udp_read->buffer_size )
445  len = pxenv_udp_read->buffer_size;
446  copy_to_user ( buffer, 0, iobuf->data, len );
447  pxenv_udp_read->buffer_size = len;
448 
449  /* Fill in source/dest information */
450  pxenv_udp_read->src_ip = pshdr->src_ip;
451  pxenv_udp_read->s_port = pshdr->s_port;
452  pxenv_udp_read->dest_ip = pshdr->dest_ip;
453  pxenv_udp_read->d_port = pshdr->d_port;
454 
455  DBG ( " %04x:%04x+%x %s:", pxenv_udp_read->buffer.segment,
456  pxenv_udp_read->buffer.offset, pxenv_udp_read->buffer_size,
457  inet_ntoa ( *( ( struct in_addr * ) &pxenv_udp_read->src_ip ) ));
458  DBG ( "%d<-%s:%d\n", ntohs ( pxenv_udp_read->s_port ),
459  inet_ntoa ( *( ( struct in_addr * ) &pxenv_udp_read->dest_ip ) ),
460  ntohs ( pxenv_udp_read->d_port ) );
461 
462  /* Free I/O buffer */
463  free_iob ( iobuf );
464 
466  return PXENV_EXIT_SUCCESS;
467 
468  drop:
469  free_iob ( iobuf );
470  no_packet:
472  return PXENV_EXIT_FAILURE;
473 }
474 
475 /** PXE UDP API */
476 struct pxe_api_call pxe_udp_api[] __pxe_api_call = {
478  struct s_PXENV_UDP_OPEN ),
480  struct s_PXENV_UDP_CLOSE ),
482  struct s_PXENV_UDP_WRITE ),
484  struct s_PXENV_UDP_READ ),
485 };
486 
487 /**
488  * Discard some cached PXE UDP data
489  *
490  * @ret discarded Number of cached items discarded
491  */
492 static unsigned int pxe_udp_discard ( void ) {
493  struct io_buffer *iobuf;
494  unsigned int discarded = 0;
495 
496  /* Try to discard the oldest received UDP packet */
497  iobuf = list_first_entry ( &pxe_udp.list, struct io_buffer, list );
498  if ( iobuf ) {
499  list_del ( &iobuf->list );
500  free_iob ( iobuf );
501  discarded++;
502  }
503 
504  return discarded;
505 }
506 
507 /** PXE UDP cache discarder */
508 struct cache_discarder pxe_udp_discarder __cache_discarder ( CACHE_NORMAL ) = {
510 };
#define iob_pull(iobuf, len)
Definition: iobuf.h:102
#define PXENV_STATUS_OUT_OF_RESOURCES
Definition: pxe_error.h:25
#define __attribute__(x)
Definition: compiler.h:10
An object interface operation.
Definition: interface.h:17
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
unsigned short uint16_t
Definition: stdint.h:11
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition: interface.c:343
#define iob_put(iobuf, len)
Definition: iobuf.h:120
Data transfer metadata.
Definition: xfer.h:22
#define PXENV_EXIT_FAILURE
An error occurred.
Definition: pxe_types.h:46
A PXE UDP connection.
Definition: pxe_udp.c:57
#define iob_push(iobuf, len)
Definition: iobuf.h:84
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
#define INTF_INIT(descriptor)
Initialise a static object interface.
Definition: interface.h:217
static __always_inline void copy_from_user(void *dest, userptr_t src, off_t src_off, size_t len)
Copy data from user buffer.
Definition: uaccess.h:337
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
A PXE UDP pseudo-header.
Definition: pxe_udp.c:45
Parameter block for pxenv_udp_close()
Definition: pxe_api.h:740
IP4_t dest_ip
Destination IP address.
Definition: pxe_udp.c:51
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition: xfer.c:158
IPv4 socket address.
Definition: in.h:82
#define ntohs(value)
Definition: byteswap.h:136
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER)
Definition: netvsc.h:16
sa_family_t sin_family
Socket address family (part of struct sockaddr)
Definition: in.h:87
Access to external ("user") memory.
struct cache_discarder pxe_udp_discarder __cache_discarder(CACHE_NORMAL)
PXE UDP cache discarder.
Parameter block for pxenv_udp_read()
Definition: pxe_api.h:784
A doubly-linked list entry (or list head)
Definition: list.h:18
#define PXE_API_CALL(_opcode, _entry, _params_type)
Define a PXE API call.
Definition: pxe.h:108
Dynamic memory allocation.
Data transfer interfaces.
#define list_empty(list)
Test whether a list is empty.
Definition: list.h:136
unsigned long tmp
Definition: linux_pci.h:53
#define list_first_entry(list, type, member)
Get the container of the first entry in a list.
Definition: list.h:333
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
#define ENOMEM
Not enough space.
Definition: errno.h:534
UDP_PORT_t d_port
Destination UDP port.
Definition: pxe_api.h:61
UINT16_t PXENV_EXIT_t
A PXE exit code.
Definition: pxe_types.h:44
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition: netdevice.h:658
static unsigned int pxe_udp_discard(void)
Discard some cached PXE UDP data.
Definition: pxe_udp.c:492
Parameter block for pxenv_udp_open()
Definition: pxe_api.h:720
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
An object interface.
Definition: interface.h:124
unsigned int(* discard)(void)
Discard some cached data.
Definition: malloc.h:89
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:93
UINT16_t UDP_PORT_t
A UDP port.
Definition: pxe_types.h:67
static PXENV_EXIT_t pxenv_udp_close(struct s_PXENV_UDP_CLOSE *pxenv_udp_close)
UDP CLOSE.
Definition: pxe_udp.c:229
int udp_open_promisc(struct interface *xfer)
Open a promiscuous UDP connection.
Definition: udp.c:144
static PXENV_EXIT_t pxenv_udp_read(struct s_PXENV_UDP_READ *pxenv_udp_read)
UDP READ.
Definition: pxe_udp.c:396
static void * dest
Definition: strings.h:176
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition: list.h:458
int meta(WINDOW *, bool)
static PXENV_EXIT_t pxenv_udp_write(struct s_PXENV_UDP_WRITE *pxenv_udp_write)
UDP WRITE.
Definition: pxe_udp.c:290
Generalized socket address structure.
Definition: socket.h:96
An object interface descriptor.
Definition: interface.h:55
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
static struct interface_descriptor pxe_udp_xfer_desc
PXE UDP data transfer interface descriptor.
Definition: pxe_udp.c:122
UDP_PORT_t s_port
Source port.
Definition: pxe_udp.c:49
static PXENV_EXIT_t pxenv_udp_open(struct s_PXENV_UDP_OPEN *pxenv_udp_open)
UDP OPEN.
Definition: pxe_udp.c:176
struct net_device * pxe_netdev
Definition: pxe_undi.c:59
IP address structure.
Definition: in.h:39
uint16_t sin_port
TCP/IP port (part of struct sockaddr_tcpip)
Definition: in.h:91
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:155
IP4_t dest_ip
Destination IP address.
Definition: pxe_api.h:59
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:32
static __always_inline void copy_to_user(userptr_t dest, off_t dest_off, const void *src, size_t len)
Copy data to user buffer.
Definition: uaccess.h:324
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:194
char * inet_ntoa(struct in_addr in)
Convert IPv4 address to dotted-quad notation.
Definition: ipv4.c:658
#define PXENV_UDP_READ
PXE API function code for pxenv_udp_read()
Definition: pxe_api.h:781
Processes.
A cache discarder.
Definition: malloc.h:83
#define PXENV_UDP_CLOSE
PXE API function code for pxenv_udp_close()
Definition: pxe_api.h:737
static int pxe_udp_deliver(struct pxe_udp_connection *pxe_udp, struct io_buffer *iobuf, struct xfer_metadata *meta)
Receive PXE UDP data.
Definition: pxe_udp.c:77
#define CACHE_NORMAL
Items with a normal replacement cost.
Definition: malloc.h:104
struct sockaddr_in local
Local address.
Definition: pxe_udp.c:61
struct interface xfer
Data transfer interface to UDP stack.
Definition: pxe_udp.c:59
struct pxe_api_call pxe_udp_api [] __pxe_api_call
PXE UDP API.
Definition: pxe_udp.c:476
#define PXENV_EXIT_SUCCESS
No error occurred.
Definition: pxe_types.h:45
uint32_t s_addr
Definition: in.h:40
#define PXENV_UDP_WRITE
PXE API function code for pxenv_udp_write()
Definition: pxe_api.h:756
Network device management.
struct in_addr sin_addr
IPv4 address.
Definition: in.h:98
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:80
char name[NETDEV_NAME_LEN]
Name of this network device.
Definition: netdevice.h:362
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:40
uint32_t len
Length.
Definition: ena.h:14
A PXE API call.
Definition: pxe.h:81
struct list_head list
List of received packets.
Definition: pxe_udp.c:63
void * data
Start of data.
Definition: iobuf.h:48
void step(void)
Single-step a single process.
Definition: process.c:98
UDP_PORT_t d_port
Destination port.
Definition: pxe_udp.c:53
static struct pxe_udp_connection pxe_udp
The PXE UDP connection.
Definition: pxe_udp.c:126
IP4_t src_ip
Source IP address.
Definition: pxe_udp.c:47
static __always_inline userptr_t real_to_user(unsigned int segment, unsigned int offset)
Convert segment:offset address to user buffer.
Definition: realmode.h:75
UINT32_t IP4_t
An IPv4 address.
Definition: pxe_types.h:60
#define PXENV_STATUS_SUCCESS
Definition: pxe_error.h:19
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
#define LIST_HEAD_INIT(list)
Initialise a static list head.
Definition: list.h:30
int iob_ensure_headroom(struct io_buffer *iobuf, size_t len)
Ensure I/O buffer has sufficient headroom.
Definition: iobuf.c:228
String functions.
int netdev_open(struct net_device *netdev)
Open network device.
Definition: netdevice.c:861
#define PXENV_UDP_OPEN
PXE API function code for pxenv_udp_open()
Definition: pxe_api.h:717
#define htons(value)
Definition: byteswap.h:135
#define PXENV_STATUS(rc)
Derive PXENV_STATUS code from iPXE error number.
Definition: pxe_error.h:121
#define AF_INET
IPv4 Internet addresses.
Definition: socket.h:63
UDP protocol.
#define PXENV_STATUS_FAILURE
Definition: pxe_error.h:20
unsigned long userptr_t
A pointer to a user buffer.
Definition: uaccess.h:33
#define DBG2(...)
Definition: compiler.h:515
static struct interface_operation pxe_udp_xfer_operations[]
PXE UDP data transfer interface operations.
Definition: pxe_udp.c:117
void * memset(void *dest, int character, size_t len) __nonnull
A persistent I/O buffer.
Definition: iobuf.h:33
Parameter block for pxenv_udp_write()
Definition: pxe_api.h:759