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 <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...
 

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 76 of file pxe_udp.c.

78  {
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 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define iob_push(iobuf, len)
Definition: iobuf.h:80
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:145
A PXE UDP pseudo-header.
Definition: pxe_udp.c:44
IP4_t dest_ip
Destination IP address.
Definition: pxe_udp.c:50
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:48
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:39
struct list_head list
List of received packets.
Definition: pxe_udp.c:62
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
#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:183
#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 175 of file pxe_udp.c.

175  {
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 }
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:337
#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:652
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:175
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:60
struct interface xfer
Data transfer interface to UDP stack.
Definition: pxe_udp.c:58
#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:358
static struct pxe_udp_connection pxe_udp
The PXE UDP connection.
Definition: pxe_udp.c:125
#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:767
#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 228 of file pxe_udp.c.

228  {
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 }
void intf_restart(struct interface *intf, int rc)
Shut down and restart an object interface.
Definition: interface.c:337
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:145
#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:228
#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
uint8_t * tmp
Definition: entropy.h:156
struct interface xfer
Data transfer interface to UDP stack.
Definition: pxe_udp.c:58
#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:39
struct list_head list
List of received packets.
Definition: pxe_udp.c:62
static struct pxe_udp_connection pxe_udp
The PXE UDP connection.
Definition: pxe_udp.c:125
#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:32

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 289 of file pxe_udp.c.

289  {
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 }
#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:116
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: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
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:289
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:193
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:60
struct interface xfer
Data transfer interface to UDP stack.
Definition: pxe_udp.c:58
#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:125
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:32

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 395 of file pxe_udp.c.

395  {
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 }
#define iob_pull(iobuf, len)
Definition: iobuf.h:98
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:145
A PXE UDP pseudo-header.
Definition: pxe_udp.c:44
IP4_t dest_ip
Destination IP address.
Definition: pxe_udp.c:50
#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:395
UDP_PORT_t s_port
Source port.
Definition: pxe_udp.c:48
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:151
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:39
uint32_t len
Length.
Definition: ena.h:14
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
#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:32

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().

Variable Documentation

◆ pxe_udp_xfer_operations

struct interface_operation pxe_udp_xfer_operations[]
static
Initial value:
= {
}
A PXE UDP connection.
Definition: pxe_udp.c:56
#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:193
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

PXE UDP data transfer interface operations.

Definition at line 116 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:56
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:65
static struct interface_operation pxe_udp_xfer_operations[]
PXE UDP data transfer interface operations.
Definition: pxe_udp.c:116

PXE UDP data transfer interface descriptor.

Definition at line 121 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:187
static struct interface_descriptor pxe_udp_xfer_desc
PXE UDP data transfer interface descriptor.
Definition: pxe_udp.c:121
struct list_head list
List of received packets.
Definition: pxe_udp.c:62
static struct pxe_udp_connection pxe_udp
The PXE UDP connection.
Definition: pxe_udp.c:125
#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 125 of file pxe_udp.c.

Referenced by pxe_udp_deliver(), 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:228
static PXENV_EXIT_t pxenv_udp_read(struct s_PXENV_UDP_READ *pxenv_udp_read)
UDP READ.
Definition: pxe_udp.c:395
static PXENV_EXIT_t pxenv_udp_write(struct s_PXENV_UDP_WRITE *pxenv_udp_write)
UDP WRITE.
Definition: pxe_udp.c:289
static PXENV_EXIT_t pxenv_udp_open(struct s_PXENV_UDP_OPEN *pxenv_udp_open)
UDP OPEN.
Definition: pxe_udp.c:175
#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 475 of file pxe_udp.c.