iPXE
Data Structures | Macros | Functions | Variables
pinger.c File Reference

ICMP ping sender. More...

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <ipxe/refcnt.h>
#include <ipxe/interface.h>
#include <ipxe/job.h>
#include <ipxe/xfer.h>
#include <ipxe/iobuf.h>
#include <ipxe/open.h>
#include <ipxe/socket.h>
#include <ipxe/retry.h>
#include <ipxe/pinger.h>

Go to the source code of this file.

Data Structures

struct  pinger
 A pinger. More...
 

Macros

#define EPROTO_LEN   __einfo_error ( EINFO_EPROTO_LEN )
 
#define EINFO_EPROTO_LEN
 
#define EPROTO_DATA   __einfo_error ( EINFO_EPROTO_DATA )
 
#define EINFO_EPROTO_DATA
 
#define EPROTO_SEQ   __einfo_error ( EINFO_EPROTO_SEQ )
 
#define EINFO_EPROTO_SEQ
 

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
 FILE_SECBOOT (PERMITTED)
 
static void pinger_generate (struct pinger *pinger, void *data)
 Generate payload. More...
 
static int pinger_verify (struct pinger *pinger, const void *data)
 Verify payload. More...
 
static void pinger_close (struct pinger *pinger, int rc)
 Close pinger. More...
 
static void pinger_window_changed (struct pinger *pinger)
 Handle data transfer window change. More...
 
static void pinger_expired (struct retry_timer *timer, int over __unused)
 Handle timer expiry. More...
 
static int pinger_deliver (struct pinger *pinger, struct io_buffer *iobuf, struct xfer_metadata *meta)
 Handle received data. More...
 
int create_pinger (struct interface *job, const char *hostname, unsigned long timeout, size_t len, unsigned int count, void(*callback)(struct sockaddr *src, unsigned int sequence, size_t len, int rc))
 Create pinger. More...
 

Variables

static struct interface_operation pinger_xfer_op []
 Pinger data transfer interface operations. More...
 
static struct interface_descriptor pinger_xfer_desc
 Pinger data transfer interface descriptor. More...
 
static struct interface_operation pinger_job_op []
 Pinger job control interface operations. More...
 
static struct interface_descriptor pinger_job_desc
 Pinger job control interface descriptor. More...
 

Detailed Description

ICMP ping sender.

Definition in file pinger.c.

Macro Definition Documentation

◆ EPROTO_LEN

#define EPROTO_LEN   __einfo_error ( EINFO_EPROTO_LEN )

Definition at line 47 of file pinger.c.

◆ EINFO_EPROTO_LEN

#define EINFO_EPROTO_LEN
Value:
"Incorrect reply length" )
#define __einfo_uniqify(einfo_base, uniq, desc)
Declare disambiguated error.
Definition: errno.h:181
#define EINFO_EPROTO
Definition: errno.h:626

Definition at line 48 of file pinger.c.

◆ EPROTO_DATA

#define EPROTO_DATA   __einfo_error ( EINFO_EPROTO_DATA )

Definition at line 50 of file pinger.c.

◆ EINFO_EPROTO_DATA

#define EINFO_EPROTO_DATA
Value:
"Incorrect reply data" )
#define __einfo_uniqify(einfo_base, uniq, desc)
Declare disambiguated error.
Definition: errno.h:181
#define EINFO_EPROTO
Definition: errno.h:626

Definition at line 51 of file pinger.c.

◆ EPROTO_SEQ

#define EPROTO_SEQ   __einfo_error ( EINFO_EPROTO_SEQ )

Definition at line 53 of file pinger.c.

◆ EINFO_EPROTO_SEQ

#define EINFO_EPROTO_SEQ
Value:
"Delayed or out-of-sequence reply" )
#define __einfo_uniqify(einfo_base, uniq, desc)
Declare disambiguated error.
Definition: errno.h:181
#define EINFO_EPROTO
Definition: errno.h:626

Definition at line 54 of file pinger.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED  )

◆ pinger_generate()

static void pinger_generate ( struct pinger pinger,
void *  data 
)
static

Generate payload.

Parameters
pingerPinger
dataData buffer

Definition at line 100 of file pinger.c.

100  {
101  uint8_t *bytes = data;
102  unsigned int i;
103 
104  /* Generate byte sequence */
105  for ( i = 0 ; i < pinger->len ; i++ )
106  bytes[i] = ( i & 0xff );
107 }
size_t len
Payload length.
Definition: pinger.c:73
unsigned char uint8_t
Definition: stdint.h:10
uint8_t data[48]
Additional event data.
Definition: ena.h:22
uint8_t bytes[64]
Definition: ib_mad.h:17
A pinger.
Definition: pinger.c:58

References bytes, data, and pinger::len.

Referenced by pinger_expired().

◆ pinger_verify()

static int pinger_verify ( struct pinger pinger,
const void *  data 
)
static

Verify payload.

Parameters
pingerPinger
dataData buffer
Return values
rcReturn status code

Definition at line 116 of file pinger.c.

116  {
117  const uint8_t *bytes = data;
118  unsigned int i;
119 
120  /* Check byte sequence */
121  for ( i = 0 ; i < pinger->len ; i++ ) {
122  if ( bytes[i] != ( i & 0xff ) )
123  return -EPROTO_DATA;
124  }
125 
126  return 0;
127 }
size_t len
Payload length.
Definition: pinger.c:73
#define EPROTO_DATA
Definition: pinger.c:50
unsigned char uint8_t
Definition: stdint.h:10
uint8_t data[48]
Additional event data.
Definition: ena.h:22
uint8_t bytes[64]
Definition: ib_mad.h:17
A pinger.
Definition: pinger.c:58

References bytes, data, EPROTO_DATA, and pinger::len.

Referenced by pinger_deliver().

◆ pinger_close()

static void pinger_close ( struct pinger pinger,
int  rc 
)
static

Close pinger.

Parameters
pingerPinger
rcReason for close

Definition at line 135 of file pinger.c.

135  {
136 
137  /* Stop timer */
138  stop_timer ( &pinger->timer );
139 
140  /* Shut down interfaces */
141  intf_shutdown ( &pinger->xfer, rc );
142  intf_shutdown ( &pinger->job, rc );
143 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition: interface.c:279
struct interface xfer
Data transfer interface.
Definition: pinger.c:65
struct interface job
Job control interface.
Definition: pinger.c:63
struct retry_timer timer
Timer.
Definition: pinger.c:68
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition: retry.c:118
A pinger.
Definition: pinger.c:58

References intf_shutdown(), pinger::job, rc, stop_timer(), pinger::timer, and pinger::xfer.

Referenced by create_pinger(), pinger_deliver(), and pinger_expired().

◆ pinger_window_changed()

static void pinger_window_changed ( struct pinger pinger)
static

Handle data transfer window change.

Parameters
pingerPinger

Definition at line 150 of file pinger.c.

150  {
151 
152  /* Do nothing if timer is already running */
153  if ( timer_running ( &pinger->timer ) )
154  return;
155 
156  /* Start timer when window opens for the first time */
157  if ( xfer_window ( &pinger->xfer ) )
159 }
static void start_timer_nodelay(struct retry_timer *timer)
Start timer with no delay.
Definition: retry.h:100
struct interface xfer
Data transfer interface.
Definition: pinger.c:65
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition: xfer.c:117
struct retry_timer timer
Timer.
Definition: pinger.c:68
A pinger.
Definition: pinger.c:58

References start_timer_nodelay(), pinger::timer, pinger::xfer, and xfer_window().

◆ pinger_expired()

static void pinger_expired ( struct retry_timer timer,
int over  __unused 
)
static

Handle timer expiry.

Parameters
timerTimer
overFailure indicator

Definition at line 167 of file pinger.c.

167  {
168  struct pinger *pinger = container_of ( timer, struct pinger, timer );
169  struct xfer_metadata meta;
170  struct io_buffer *iobuf;
171  int rc;
172 
173  /* If no response has been received, notify the callback function */
174  if ( pinger->pending && pinger->callback )
176 
177  /* Check for termination */
178  if ( pinger->remaining && ( --pinger->remaining == 0 ) ) {
180  return;
181  }
182 
183  /* Increase sequence number */
184  pinger->sequence++;
185 
186  /* Restart timer. Do this before attempting to transmit, in
187  * case the transmission attempt fails.
188  */
190  pinger->pending = 1;
191 
192  /* Allocate I/O buffer */
193  iobuf = xfer_alloc_iob ( &pinger->xfer, pinger->len );
194  if ( ! iobuf ) {
195  DBGC ( pinger, "PINGER %p could not allocate I/O buffer\n",
196  pinger );
197  return;
198  }
199 
200  /* Generate payload */
201  pinger_generate ( pinger, iob_put ( iobuf, pinger->len ) );
202 
203  /* Generate metadata */
204  memset ( &meta, 0, sizeof ( meta ) );
205  meta.flags = XFER_FL_ABS_OFFSET;
206  meta.offset = pinger->sequence;
207 
208  /* Transmit packet */
209  if ( ( rc = xfer_deliver ( &pinger->xfer, iobuf, &meta ) ) != 0 ) {
210  DBGC ( pinger, "PINGER %p could not transmit: %s\n",
211  pinger, strerror ( rc ) );
212  return;
213  }
214 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define iob_put(iobuf, len)
Definition: iobuf.h:125
Data transfer metadata.
Definition: xfer.h:23
struct interface xfer
Data transfer interface.
Definition: pinger.c:65
#define XFER_FL_ABS_OFFSET
Offset is absolute.
Definition: xfer.h:48
size_t len
Payload length.
Definition: pinger.c:73
#define DBGC(...)
Definition: compiler.h:505
void(* callback)(struct sockaddr *src, unsigned int sequence, size_t len, int rc)
Callback function.
Definition: pinger.c:90
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition: xfer.c:159
uint16_t sequence
Current sequence number.
Definition: pinger.c:75
A timer.
Definition: timer.h:29
int rc
Return status.
Definition: pinger.c:81
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:36
struct retry_timer timer
Timer.
Definition: pinger.c:68
static void pinger_close(struct pinger *pinger, int rc)
Close pinger.
Definition: pinger.c:135
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:195
unsigned long timeout
Timeout.
Definition: pinger.c:70
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition: retry.c:65
static void pinger_generate(struct pinger *pinger, void *data)
Generate payload.
Definition: pinger.c:100
uint8_t meta
Metadata flags.
Definition: ena.h:14
unsigned int remaining
Number of remaining expiry events (zero to continue indefinitely)
Definition: pinger.c:79
int pending
Response for current sequence number is still pending.
Definition: pinger.c:77
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
#define ETIMEDOUT
Connection timed out.
Definition: errno.h:670
A pinger.
Definition: pinger.c:58
void * memset(void *dest, int character, size_t len) __nonnull
A persistent I/O buffer.
Definition: iobuf.h:38

References pinger::callback, container_of, DBGC, ETIMEDOUT, iob_put, pinger::len, memset(), meta, NULL, pinger::pending, pinger_close(), pinger_generate(), pinger::rc, rc, pinger::remaining, pinger::sequence, start_timer_fixed(), strerror(), pinger::timeout, pinger::timer, pinger::xfer, xfer_alloc_iob(), xfer_deliver(), and XFER_FL_ABS_OFFSET.

Referenced by create_pinger().

◆ pinger_deliver()

static int pinger_deliver ( struct pinger pinger,
struct io_buffer iobuf,
struct xfer_metadata meta 
)
static

Handle received data.

Parameters
pingerPinger
iobufI/O buffer
metaData transfer metadata
Return values
rcReturn status code

Definition at line 224 of file pinger.c.

225  {
226  size_t len = iob_len ( iobuf );
227  uint16_t sequence = meta->offset;
228  int terminate = 0;
229  int rc;
230 
231  /* Clear response pending flag, if applicable */
232  if ( sequence == pinger->sequence )
233  pinger->pending = 0;
234 
235  /* Check for errors */
236  if ( len != pinger->len ) {
237  /* Incorrect length: terminate immediately if we are
238  * not pinging indefinitely.
239  */
240  DBGC ( pinger, "PINGER %p received incorrect length %zd "
241  "(expected %zd)\n", pinger, len, pinger->len );
242  rc = -EPROTO_LEN;
243  terminate = ( pinger->remaining != 0 );
244  } else if ( ( rc = pinger_verify ( pinger, iobuf->data ) ) != 0 ) {
245  /* Incorrect data: terminate immediately if we are not
246  * pinging indefinitely.
247  */
248  DBGC ( pinger, "PINGER %p received incorrect data:\n", pinger );
249  DBGC_HDA ( pinger, 0, iobuf->data, iob_len ( iobuf ) );
250  terminate = ( pinger->remaining != 0 );
251  } else if ( sequence != pinger->sequence ) {
252  /* Incorrect sequence number (probably a delayed response):
253  * report via callback but otherwise ignore.
254  */
255  DBGC ( pinger, "PINGER %p received sequence %d (expected %d)\n",
256  pinger, sequence, pinger->sequence );
257  rc = -EPROTO_SEQ;
258  terminate = 0;
259  } else {
260  /* Success: record that a packet was successfully received,
261  * and terminate if we expect to send no further packets.
262  */
263  rc = 0;
264  pinger->rc = 0;
265  terminate = ( pinger->remaining == 1 );
266  }
267 
268  /* Discard I/O buffer */
269  free_iob ( iobuf );
270 
271  /* Notify callback function, if applicable */
272  if ( pinger->callback )
273  pinger->callback ( meta->src, sequence, len, rc );
274 
275  /* Terminate if applicable */
276  if ( terminate )
277  pinger_close ( pinger, rc );
278 
279  return rc;
280 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
unsigned short uint16_t
Definition: stdint.h:11
size_t len
Payload length.
Definition: pinger.c:73
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:153
#define DBGC(...)
Definition: compiler.h:505
void(* callback)(struct sockaddr *src, unsigned int sequence, size_t len, int rc)
Callback function.
Definition: pinger.c:90
#define EPROTO_SEQ
Definition: pinger.c:53
uint16_t sequence
Current sequence number.
Definition: pinger.c:75
int rc
Return status.
Definition: pinger.c:81
static int pinger_verify(struct pinger *pinger, const void *data)
Verify payload.
Definition: pinger.c:116
#define DBGC_HDA(...)
Definition: compiler.h:506
ring len
Length.
Definition: dwmac.h:231
#define EPROTO_LEN
Definition: pinger.c:47
static void pinger_close(struct pinger *pinger, int rc)
Close pinger.
Definition: pinger.c:135
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:160
void * data
Start of data.
Definition: iobuf.h:53
uint8_t meta
Metadata flags.
Definition: ena.h:14
unsigned int remaining
Number of remaining expiry events (zero to continue indefinitely)
Definition: pinger.c:79
int pending
Response for current sequence number is still pending.
Definition: pinger.c:77
A pinger.
Definition: pinger.c:58

References pinger::callback, io_buffer::data, DBGC, DBGC_HDA, EPROTO_LEN, EPROTO_SEQ, free_iob(), iob_len(), pinger::len, len, meta, pinger::pending, pinger_close(), pinger_verify(), pinger::rc, rc, pinger::remaining, and pinger::sequence.

◆ create_pinger()

int create_pinger ( struct interface job,
const char *  hostname,
unsigned long  timeout,
size_t  len,
unsigned int  count,
void(*)(struct sockaddr *src, unsigned int sequence, size_t len, int rc callback 
)

Create pinger.

Parameters
jobJob control interface
hostnameHostname to ping
timeoutTimeout (in ticks)
lenPayload length
countNumber of packets to send (or zero for no limit)
callbackCallback function (or NULL)
Return values
rcReturn status code

Definition at line 313 of file pinger.c.

317  {
318  struct pinger *pinger;
319  int rc;
320 
321  /* Sanity check */
322  if ( ! timeout )
323  return -EINVAL;
324 
325  /* Allocate and initialise structure */
326  pinger = zalloc ( sizeof ( *pinger ) );
327  if ( ! pinger )
328  return -ENOMEM;
329  ref_init ( &pinger->refcnt, NULL );
332  timer_init ( &pinger->timer, pinger_expired, &pinger->refcnt );
334  pinger->len = len;
335  pinger->remaining = ( count ? ( count + 1 /* Initial packet */ ) : 0 );
337  pinger->rc = -ETIMEDOUT;
338 
339  /* Open socket */
341  hostname, NULL ) ) != 0 ) {
342  DBGC ( pinger, "PINGER %p could not open socket: %s\n",
343  pinger, strerror ( rc ) );
344  goto err;
345  }
346 
347  /* Attach parent interface, mortalise self, and return */
348  intf_plug_plug ( &pinger->job, job );
349  ref_put ( &pinger->refcnt );
350  return 0;
351 
352  err:
353  pinger_close ( pinger, rc );
354  ref_put ( &pinger->refcnt );
355  return rc;
356 }
#define EINVAL
Invalid argument.
Definition: errno.h:429
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct refcnt refcnt
Reference count.
Definition: pinger.c:60
struct interface xfer
Data transfer interface.
Definition: pinger.c:65
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:65
size_t len
Payload length.
Definition: pinger.c:73
#define DBGC(...)
Definition: compiler.h:505
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition: interface.c:108
void(* callback)(struct sockaddr *src, unsigned int sequence, size_t len, int rc)
Callback function.
Definition: pinger.c:90
static void pinger_expired(struct retry_timer *timer, int over __unused)
Handle timer expiry.
Definition: pinger.c:167
int rc
Return status.
Definition: pinger.c:81
#define ENOMEM
Not enough space.
Definition: errno.h:535
#define SOCK_ECHO
Definition: socket.h:35
struct interface job
Job control interface.
Definition: pinger.c:63
ring len
Length.
Definition: dwmac.h:231
static unsigned int count
Number of entries.
Definition: dwmac.h:225
struct retry_timer timer
Timer.
Definition: pinger.c:68
static void pinger_close(struct pinger *pinger, int rc)
Close pinger.
Definition: pinger.c:135
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:79
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:662
unsigned long timeout
Timeout.
Definition: pinger.c:70
void timeout(int)
static struct interface_descriptor pinger_xfer_desc
Pinger data transfer interface descriptor.
Definition: pinger.c:290
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition: interface.h:204
static struct interface_descriptor pinger_job_desc
Pinger job control interface descriptor.
Definition: pinger.c:299
unsigned int remaining
Number of remaining expiry events (zero to continue indefinitely)
Definition: pinger.c:79
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
#define ETIMEDOUT
Connection timed out.
Definition: errno.h:670
A pinger.
Definition: pinger.c:58
int xfer_open_named_socket(struct interface *xfer, int semantics, struct sockaddr *peer, const char *name, struct sockaddr *local)
Open named socket.
Definition: resolv.c:403
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:107

References pinger::callback, count, DBGC, EINVAL, ENOMEM, ETIMEDOUT, intf_init(), intf_plug_plug(), pinger::job, pinger::len, len, NULL, pinger_close(), pinger_expired(), pinger_job_desc, pinger_xfer_desc, pinger::rc, rc, ref_init, ref_put, pinger::refcnt, pinger::remaining, SOCK_ECHO, strerror(), pinger::timeout, timeout(), pinger::timer, pinger::xfer, xfer_open_named_socket(), and zalloc().

Referenced by ping().

Variable Documentation

◆ pinger_xfer_op

struct interface_operation pinger_xfer_op[]
static
Initial value:
= {
}
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition: xfer.c:147
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:250
static int pinger_deliver(struct pinger *pinger, struct io_buffer *iobuf, struct xfer_metadata *meta)
Handle received data.
Definition: pinger.c:224
static void pinger_window_changed(struct pinger *pinger)
Handle data transfer window change.
Definition: pinger.c:150
static void pinger_close(struct pinger *pinger, int rc)
Close pinger.
Definition: pinger.c:135
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:33
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:195
A pinger.
Definition: pinger.c:58

Pinger data transfer interface operations.

Definition at line 283 of file pinger.c.

◆ pinger_xfer_desc

struct interface_descriptor pinger_xfer_desc
static
Initial value:
=
struct interface xfer
Data transfer interface.
Definition: pinger.c:65
static struct interface_operation pinger_xfer_op[]
Pinger data transfer interface operations.
Definition: pinger.c:283
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:81
A pinger.
Definition: pinger.c:58

Pinger data transfer interface descriptor.

Definition at line 290 of file pinger.c.

Referenced by create_pinger().

◆ pinger_job_op

struct interface_operation pinger_job_op[]
static
Initial value:
= {
}
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:250
static void pinger_close(struct pinger *pinger, int rc)
Close pinger.
Definition: pinger.c:135
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:33
A pinger.
Definition: pinger.c:58

Pinger job control interface operations.

Definition at line 294 of file pinger.c.

◆ pinger_job_desc

struct interface_descriptor pinger_job_desc
static
Initial value:
=
static struct interface_operation pinger_job_op[]
Pinger job control interface operations.
Definition: pinger.c:294
struct interface job
Job control interface.
Definition: pinger.c:63
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:81
A pinger.
Definition: pinger.c:58

Pinger job control interface descriptor.

Definition at line 299 of file pinger.c.

Referenced by create_pinger().