iPXE
Data Structures | Functions | Variables
pxe_udp.c File Reference

PXE UDP API. More...

#include <string.h>
#include <byteswap.h>
#include <ipxe/iobuf.h>
#include <ipxe/xfer.h>
#include <ipxe/udp.h>
#include <ipxe/uaccess.h>
#include <ipxe/process.h>
#include <ipxe/netdevice.h>
#include <ipxe/malloc.h>
#include <realmode.h>
#include <pxe.h>

Go to the source code of this file.

Data Structures

struct  pxe_udp_pseudo_header
 A PXE UDP pseudo-header. More...
 
struct  pxe_udp_connection
 A PXE UDP connection. More...
 

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
static int pxe_udp_deliver (struct pxe_udp_connection *pxe_udp, struct io_buffer *iobuf, struct xfer_metadata *meta)
 Receive PXE UDP data. More...
 
static PXENV_EXIT_t pxenv_udp_open (struct s_PXENV_UDP_OPEN *pxenv_udp_open)
 UDP OPEN. More...
 
static PXENV_EXIT_t pxenv_udp_close (struct s_PXENV_UDP_CLOSE *pxenv_udp_close)
 UDP CLOSE. More...
 
static PXENV_EXIT_t pxenv_udp_write (struct s_PXENV_UDP_WRITE *pxenv_udp_write)
 UDP WRITE. More...
 
static PXENV_EXIT_t pxenv_udp_read (struct s_PXENV_UDP_READ *pxenv_udp_read)
 UDP READ. More...
 
static unsigned int pxe_udp_discard (void)
 Discard some cached PXE UDP data. More...
 
struct cache_discarder pxe_udp_discarder __cache_discarder (CACHE_NORMAL)
 PXE UDP cache discarder. More...
 

Variables

static struct interface_operation pxe_udp_xfer_operations []
 PXE UDP data transfer interface operations. More...
 
static struct interface_descriptor pxe_udp_xfer_desc
 PXE UDP data transfer interface descriptor. More...
 
static struct pxe_udp_connection pxe_udp
 The PXE UDP connection. More...
 
struct pxe_api_call pxe_udp_api [] __pxe_api_call
 PXE UDP API. More...
 

Detailed Description

PXE UDP API.

Definition in file pxe_udp.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ pxe_udp_deliver()

static int pxe_udp_deliver ( struct pxe_udp_connection pxe_udp,
struct io_buffer iobuf,
struct xfer_metadata meta 
)
static

Receive PXE UDP data.

Parameters
pxe_udpPXE UDP connection
iobufI/O buffer
metaData transfer metadata
Return values
rcReturn status code

Receives a packet as part of the current pxenv_udp_read() operation.

Definition at line 77 of file pxe_udp.c.

79  {
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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define iob_push(iobuf, len)
Definition: iobuf.h:84
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
A PXE UDP pseudo-header.
Definition: pxe_udp.c:45
IP4_t dest_ip
Destination IP address.
Definition: pxe_udp.c:51
IPv4 socket address.
Definition: in.h:82
sa_family_t sin_family
Socket address family (part of struct sockaddr)
Definition: in.h:87
#define ENOMEM
Not enough space.
Definition: errno.h:534
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
#define list_add_tail(new, head)
Add a new entry to the tail of a list.
Definition: list.h:93
int meta(WINDOW *, bool)
UDP_PORT_t s_port
Source port.
Definition: pxe_udp.c:49
uint16_t sin_port
TCP/IP port (part of struct sockaddr_tcpip)
Definition: in.h:91
uint32_t s_addr
Definition: in.h:40
struct in_addr sin_addr
IPv4 address.
Definition: in.h:98
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:40
struct list_head list
List of received packets.
Definition: pxe_udp.c:63
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
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
int iob_ensure_headroom(struct io_buffer *iobuf, size_t len)
Ensure I/O buffer has sufficient headroom.
Definition: iobuf.c:228
#define AF_INET
IPv4 Internet addresses.
Definition: socket.h:63

References AF_INET, assert(), pxe_udp_pseudo_header::d_port, DBG, pxe_udp_pseudo_header::dest_ip, ENOMEM, free_iob(), iob_ensure_headroom(), iob_push, pxe_udp_connection::list, io_buffer::list, list_add_tail, meta(), pxe_udp, rc, in_addr::s_addr, pxe_udp_pseudo_header::s_port, sockaddr_in::sin_addr, sockaddr_in::sin_family, sockaddr_in::sin_port, and pxe_udp_pseudo_header::src_ip.

◆ pxenv_udp_open()

static PXENV_EXIT_t pxenv_udp_open ( struct s_PXENV_UDP_OPEN pxenv_udp_open)
static

UDP OPEN.

Parameters
pxenv_udp_openPointer to a struct s_PXENV_UDP_OPEN
s_PXENV_UDP_OPEN::src_ipIP address of this station, or 0.0.0.0
Return values
PXENV_EXIT_SUCCESSAlways
s_PXENV_UDP_OPEN::StatusPXE status code
Exceptions
PXENV_STATUS_UDP_OPENUDP connection already open
PXENV_STATUS_OUT_OF_RESOURCESCould not open connection

Prepares the PXE stack for communication using pxenv_udp_write() and pxenv_udp_read().

The IP address supplied in s_PXENV_UDP_OPEN::src_ip will be recorded and used as the local station's IP address for all further communication, including communication by means other than pxenv_udp_write() and pxenv_udp_read(). (If s_PXENV_UDP_OPEN::src_ip is 0.0.0.0, the local station's IP address will remain unchanged.)

You can only have one open UDP connection at a time. This is not a meaningful restriction, since pxenv_udp_write() and pxenv_udp_read() allow you to specify arbitrary local and remote ports and an arbitrary remote address for each packet. According to the PXE specifiation, you cannot have a UDP connection open at the same time as a TFTP connection; this restriction does not apply to Etherboot.

On x86, you must set the s_PXE::StatusCallout field to a nonzero value before calling this function in protected mode. You cannot call this function with a 32-bit stack segment. (See the relevant implementation note for more details.)

Note
The PXE specification does not make it clear whether the IP address supplied in s_PXENV_UDP_OPEN::src_ip should be used only for this UDP connection, or retained for all future communication. The latter seems more consistent with typical PXE stack behaviour.
Etherboot currently ignores the s_PXENV_UDP_OPEN::src_ip parameter.

Definition at line 176 of file pxe_udp.c.

176  {
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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition: interface.c:343
#define PXENV_EXIT_FAILURE
An error occurred.
Definition: pxe_types.h:46
static int netdev_is_open(struct net_device *netdev)
Check whether or not network device is open.
Definition: netdevice.h:658
int udp_open_promisc(struct interface *xfer)
Open a promiscuous UDP connection.
Definition: udp.c:144
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
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
char * inet_ntoa(struct in_addr in)
Convert IPv4 address to dotted-quad notation.
Definition: ipv4.c:658
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
#define PXENV_EXIT_SUCCESS
No error occurred.
Definition: pxe_types.h:45
uint32_t s_addr
Definition: in.h:40
struct in_addr sin_addr
IPv4 address.
Definition: in.h:98
char name[NETDEV_NAME_LEN]
Name of this network device.
Definition: netdevice.h:362
static struct pxe_udp_connection pxe_udp
The PXE UDP connection.
Definition: pxe_udp.c:126
#define PXENV_STATUS_SUCCESS
Definition: pxe_error.h:19
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
int netdev_open(struct net_device *netdev)
Open network device.
Definition: netdevice.c:861
#define PXENV_STATUS(rc)
Derive PXENV_STATUS code from iPXE error number.
Definition: pxe_error.h:121

References DBG, inet_ntoa(), intf_restart(), pxe_udp_connection::local, net_device::name, netdev_is_open(), netdev_open(), pxe_netdev, pxe_udp, PXENV_EXIT_FAILURE, PXENV_EXIT_SUCCESS, PXENV_STATUS, PXENV_STATUS_SUCCESS, rc, in_addr::s_addr, sockaddr_in::sin_addr, strerror(), udp_open_promisc(), and pxe_udp_connection::xfer.

◆ pxenv_udp_close()

static PXENV_EXIT_t pxenv_udp_close ( struct s_PXENV_UDP_CLOSE pxenv_udp_close)
static

UDP CLOSE.

Parameters
pxenv_udp_closePointer to a struct s_PXENV_UDP_CLOSE
Return values
PXENV_EXIT_SUCCESSAlways
s_PXENV_UDP_CLOSE::StatusPXE status code
Exceptions
None-

Closes a UDP connection opened with pxenv_udp_open().

You can only have one open UDP connection at a time. You cannot have a UDP connection open at the same time as a TFTP connection. You cannot use pxenv_udp_close() to close a TFTP connection; use pxenv_tftp_close() instead.

On x86, you must set the s_PXE::StatusCallout field to a nonzero value before calling this function in protected mode. You cannot call this function with a 32-bit stack segment. (See the relevant implementation note for more details.)

Definition at line 229 of file pxe_udp.c.

229  {
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 }
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition: interface.c:343
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
unsigned long tmp
Definition: linux_pci.h:53
#define list_del(list)
Delete an entry from a list.
Definition: list.h:119
static PXENV_EXIT_t pxenv_udp_close(struct s_PXENV_UDP_CLOSE *pxenv_udp_close)
UDP CLOSE.
Definition: pxe_udp.c:229
#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
struct interface xfer
Data transfer interface to UDP stack.
Definition: pxe_udp.c:59
#define PXENV_EXIT_SUCCESS
No error occurred.
Definition: pxe_types.h:45
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:40
struct list_head list
List of received packets.
Definition: pxe_udp.c:63
static struct pxe_udp_connection pxe_udp
The PXE UDP connection.
Definition: pxe_udp.c:126
#define PXENV_STATUS_SUCCESS
Definition: pxe_error.h:19
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
A persistent I/O buffer.
Definition: iobuf.h:33

References DBG, free_iob(), intf_restart(), pxe_udp_connection::list, io_buffer::list, list_del, list_for_each_entry_safe, pxe_udp, PXENV_EXIT_SUCCESS, PXENV_STATUS_SUCCESS, tmp, and pxe_udp_connection::xfer.

◆ pxenv_udp_write()

static PXENV_EXIT_t pxenv_udp_write ( struct s_PXENV_UDP_WRITE pxenv_udp_write)
static

UDP WRITE.

Parameters
pxenv_udp_writePointer to a struct s_PXENV_UDP_WRITE
s_PXENV_UDP_WRITE::ipDestination IP address
s_PXENV_UDP_WRITE::gwRelay agent IP address, or 0.0.0.0
s_PXENV_UDP_WRITE::src_portSource UDP port, or 0
s_PXENV_UDP_WRITE::dst_portDestination UDP port
s_PXENV_UDP_WRITE::buffer_sizeLength of the UDP payload
s_PXENV_UDP_WRITE::bufferAddress of the UDP payload
Return values
PXENV_EXIT_SUCCESSPacket was transmitted successfully
PXENV_EXIT_FAILUREPacket could not be transmitted
s_PXENV_UDP_WRITE::StatusPXE status code
Exceptions
PXENV_STATUS_UDP_CLOSEDUDP connection is not open
PXENV_STATUS_UNDI_TRANSMIT_ERRORCould not transmit packet

Transmits a single UDP packet. A valid IP and UDP header will be prepended to the payload in s_PXENV_UDP_WRITE::buffer; the buffer should not contain precomputed IP and UDP headers, nor should it contain space allocated for these headers. The first byte of the buffer will be transmitted as the first byte following the UDP header.

If s_PXENV_UDP_WRITE::gw is 0.0.0.0, normal IP routing will take place. See the relevant implementation note for more details.

If s_PXENV_UDP_WRITE::src_port is 0, port 2069 will be used.

You must have opened a UDP connection with pxenv_udp_open() before calling pxenv_udp_write().

On x86, you must set the s_PXE::StatusCallout field to a nonzero value before calling this function in protected mode. You cannot call this function with a 32-bit stack segment. (See the relevant implementation note for more details.)

Note
Etherboot currently ignores the s_PXENV_UDP_WRITE::gw parameter.

Definition at line 290 of file pxe_udp.c.

290  {
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 }
#define PXENV_STATUS_OUT_OF_RESOURCES
Definition: pxe_error.h:25
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#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
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
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
static void * dest
Definition: strings.h:176
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
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
struct net_device * pxe_netdev
Definition: pxe_undi.c:59
uint16_t sin_port
TCP/IP port (part of struct sockaddr_tcpip)
Definition: in.h:91
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
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
#define PXENV_EXIT_SUCCESS
No error occurred.
Definition: pxe_types.h:45
uint32_t len
Length.
Definition: ena.h:14
static struct pxe_udp_connection pxe_udp
The PXE UDP connection.
Definition: pxe_udp.c:126
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
#define PXENV_STATUS_SUCCESS
Definition: pxe_error.h:19
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
#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
unsigned long userptr_t
A pointer to a user buffer.
Definition: uaccess.h:33
void * memset(void *dest, int character, size_t len) __nonnull
A persistent I/O buffer.
Definition: iobuf.h:33

References AF_INET, buffer, copy_from_user(), DBG, dest, htons, inet_ntoa(), iob_put, len, pxe_udp_connection::local, memset(), meta(), ntohs, pxe_netdev, pxe_udp, PXENV_EXIT_FAILURE, PXENV_EXIT_SUCCESS, PXENV_STATUS, PXENV_STATUS_OUT_OF_RESOURCES, PXENV_STATUS_SUCCESS, rc, real_to_user(), sockaddr_in::sin_port, strerror(), pxe_udp_connection::xfer, xfer_alloc_iob(), and xfer_deliver().

◆ pxenv_udp_read()

static PXENV_EXIT_t pxenv_udp_read ( struct s_PXENV_UDP_READ pxenv_udp_read)
static

UDP READ.

Parameters
pxenv_udp_readPointer to a struct s_PXENV_UDP_READ
s_PXENV_UDP_READ::dest_ipDestination IP address, or 0.0.0.0
s_PXENV_UDP_READ::d_portDestination UDP port, or 0
s_PXENV_UDP_READ::buffer_sizeSize of the UDP payload buffer
s_PXENV_UDP_READ::bufferAddress of the UDP payload buffer
Return values
PXENV_EXIT_SUCCESSA packet has been received
PXENV_EXIT_FAILURENo packet has been received
s_PXENV_UDP_READ::StatusPXE status code
s_PXENV_UDP_READ::src_ipSource IP address
s_PXENV_UDP_READ::dest_ipDestination IP address
s_PXENV_UDP_READ::s_portSource UDP port
s_PXENV_UDP_READ::d_portDestination UDP port
s_PXENV_UDP_READ::buffer_sizeLength of UDP payload
Exceptions
PXENV_STATUS_UDP_CLOSEDUDP connection is not open
PXENV_STATUS_FAILURENo packet was ready to read

Receive a single UDP packet. This is a non-blocking call; if no packet is ready to read, the call will return instantly with s_PXENV_UDP_READ::Status==PXENV_STATUS_FAILURE.

If s_PXENV_UDP_READ::dest_ip is 0.0.0.0, UDP packets addressed to any IP address will be accepted and may be returned to the caller.

If s_PXENV_UDP_READ::d_port is 0, UDP packets addressed to any UDP port will be accepted and may be returned to the caller.

You must have opened a UDP connection with pxenv_udp_open() before calling pxenv_udp_read().

On x86, you must set the s_PXE::StatusCallout field to a nonzero value before calling this function in protected mode. You cannot call this function with a 32-bit stack segment. (See the relevant implementation note for more details.)

Note
The PXE specification (version 2.1) does not state that we should fill in s_PXENV_UDP_READ::dest_ip and s_PXENV_UDP_READ::d_port, but Microsoft Windows' NTLDR program expects us to do so, and will fail if we don't.

Definition at line 396 of file pxe_udp.c.

396  {
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 }
#define iob_pull(iobuf, len)
Definition: iobuf.h:102
unsigned short uint16_t
Definition: stdint.h:11
#define PXENV_EXIT_FAILURE
An error occurred.
Definition: pxe_types.h:46
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
A PXE UDP pseudo-header.
Definition: pxe_udp.c:45
IP4_t dest_ip
Destination IP address.
Definition: pxe_udp.c:51
#define ntohs(value)
Definition: byteswap.h:136
uint32_t buffer
Buffer index (or NETVSC_RNDIS_NO_BUFFER)
Definition: netvsc.h:16
#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
UDP_PORT_t d_port
Destination UDP port.
Definition: pxe_api.h:61
assert((readw(&hdr->flags) &(GTF_reading|GTF_writing))==0)
static PXENV_EXIT_t pxenv_udp_read(struct s_PXENV_UDP_READ *pxenv_udp_read)
UDP READ.
Definition: pxe_udp.c:396
UDP_PORT_t s_port
Source port.
Definition: pxe_udp.c:49
IP address structure.
Definition: in.h:39
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
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
char * inet_ntoa(struct in_addr in)
Convert IPv4 address to dotted-quad notation.
Definition: ipv4.c:658
#define PXENV_EXIT_SUCCESS
No error occurred.
Definition: pxe_types.h:45
uint32_t s_addr
Definition: in.h:40
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:40
uint32_t len
Length.
Definition: ena.h:14
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
#define PXENV_STATUS_SUCCESS
Definition: pxe_error.h:19
#define DBG(...)
Print a debugging message.
Definition: compiler.h:498
#define htons(value)
Definition: byteswap.h:135
#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
A persistent I/O buffer.
Definition: iobuf.h:33

References assert(), buffer, copy_to_user(), pxe_udp_pseudo_header::d_port, d_port, io_buffer::data, DBG, DBG2, pxe_udp_pseudo_header::dest_ip, dest_ip, free_iob(), htons, inet_ntoa(), iob_len(), iob_pull, len, pxe_udp_connection::list, io_buffer::list, list_del, list_empty, list_first_entry, ntohs, pxe_udp, PXENV_EXIT_FAILURE, PXENV_EXIT_SUCCESS, PXENV_STATUS_FAILURE, PXENV_STATUS_SUCCESS, real_to_user(), in_addr::s_addr, pxe_udp_pseudo_header::s_port, pxe_udp_pseudo_header::src_ip, and step().

◆ pxe_udp_discard()

static unsigned int pxe_udp_discard ( void  )
static

Discard some cached PXE UDP data.

Return values
discardedNumber of cached items discarded

Definition at line 492 of file pxe_udp.c.

492  {
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 }
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
#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
struct list_head list
List of which this buffer is a member.
Definition: iobuf.h:40
struct list_head list
List of received packets.
Definition: pxe_udp.c:63
static struct pxe_udp_connection pxe_udp
The PXE UDP connection.
Definition: pxe_udp.c:126
A persistent I/O buffer.
Definition: iobuf.h:33

References free_iob(), pxe_udp_connection::list, io_buffer::list, list_del, list_first_entry, and pxe_udp.

◆ __cache_discarder()

struct cache_discarder pxe_udp_discarder __cache_discarder ( CACHE_NORMAL  )

PXE UDP cache discarder.

Variable Documentation

◆ pxe_udp_xfer_operations

struct interface_operation pxe_udp_xfer_operations[]
static
Initial value:
= {
}
A PXE UDP connection.
Definition: pxe_udp.c:57
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:32
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:194
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

PXE UDP data transfer interface operations.

Definition at line 117 of file pxe_udp.c.

◆ pxe_udp_xfer_desc

struct interface_descriptor pxe_udp_xfer_desc
static
Initial value:
=
A PXE UDP connection.
Definition: pxe_udp.c:57
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:80
static struct interface_operation pxe_udp_xfer_operations[]
PXE UDP data transfer interface operations.
Definition: pxe_udp.c:117

PXE UDP data transfer interface descriptor.

Definition at line 122 of file pxe_udp.c.

◆ pxe_udp

struct pxe_udp_connection pxe_udp
static
Initial value:
= {
.local = {
.sin_family = AF_INET,
},
}
#define INTF_INIT(descriptor)
Initialise a static object interface.
Definition: interface.h:217
static struct interface_descriptor pxe_udp_xfer_desc
PXE UDP data transfer interface descriptor.
Definition: pxe_udp.c:122
struct list_head list
List of received packets.
Definition: pxe_udp.c:63
static struct pxe_udp_connection pxe_udp
The PXE UDP connection.
Definition: pxe_udp.c:126
#define LIST_HEAD_INIT(list)
Initialise a static list head.
Definition: list.h:30
#define AF_INET
IPv4 Internet addresses.
Definition: socket.h:63

The PXE UDP connection.

Definition at line 126 of file pxe_udp.c.

Referenced by pxe_udp_deliver(), pxe_udp_discard(), pxenv_udp_close(), pxenv_udp_open(), pxenv_udp_read(), and pxenv_udp_write().

◆ __pxe_api_call

struct pxe_api_call pxe_udp_api [] __pxe_api_call
Initial value:
= {
struct s_PXENV_UDP_OPEN ),
struct s_PXENV_UDP_READ ),
}
Parameter block for pxenv_udp_close()
Definition: pxe_api.h:740
Parameter block for pxenv_udp_read()
Definition: pxe_api.h:784
#define PXE_API_CALL(_opcode, _entry, _params_type)
Define a PXE API call.
Definition: pxe.h:108
Parameter block for pxenv_udp_open()
Definition: pxe_api.h:720
static PXENV_EXIT_t pxenv_udp_close(struct s_PXENV_UDP_CLOSE *pxenv_udp_close)
UDP CLOSE.
Definition: pxe_udp.c:229
static PXENV_EXIT_t pxenv_udp_read(struct s_PXENV_UDP_READ *pxenv_udp_read)
UDP READ.
Definition: pxe_udp.c:396
static PXENV_EXIT_t pxenv_udp_write(struct s_PXENV_UDP_WRITE *pxenv_udp_write)
UDP WRITE.
Definition: pxe_udp.c:290
static PXENV_EXIT_t pxenv_udp_open(struct s_PXENV_UDP_OPEN *pxenv_udp_open)
UDP OPEN.
Definition: pxe_udp.c:176
#define PXENV_UDP_READ
PXE API function code for pxenv_udp_read()
Definition: pxe_api.h:781
#define PXENV_UDP_CLOSE
PXE API function code for pxenv_udp_close()
Definition: pxe_api.h:737
#define PXENV_UDP_WRITE
PXE API function code for pxenv_udp_write()
Definition: pxe_api.h:756
#define PXENV_UDP_OPEN
PXE API function code for pxenv_udp_open()
Definition: pxe_api.h:717
Parameter block for pxenv_udp_write()
Definition: pxe_api.h:759

PXE UDP API.

Definition at line 476 of file pxe_udp.c.