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