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)
 
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 46 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:180
#define EINFO_EPROTO
Definition: errno.h:625

Definition at line 47 of file pinger.c.

◆ EPROTO_DATA

#define EPROTO_DATA   __einfo_error ( EINFO_EPROTO_DATA )

Definition at line 49 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:180
#define EINFO_EPROTO
Definition: errno.h:625

Definition at line 50 of file pinger.c.

◆ EPROTO_SEQ

#define EPROTO_SEQ   __einfo_error ( EINFO_EPROTO_SEQ )

Definition at line 52 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:180
#define EINFO_EPROTO
Definition: errno.h:625

Definition at line 53 of file pinger.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ pinger_generate()

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

Generate payload.

Parameters
pingerPinger
dataData buffer

Definition at line 99 of file pinger.c.

99  {
100  uint8_t *bytes = data;
101  unsigned int i;
102 
103  /* Generate byte sequence */
104  for ( i = 0 ; i < pinger->len ; i++ )
105  bytes[i] = ( i & 0xff );
106 }
size_t len
Payload length.
Definition: pinger.c:72
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:16
A pinger.
Definition: pinger.c:57

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 115 of file pinger.c.

115  {
116  const uint8_t *bytes = data;
117  unsigned int i;
118 
119  /* Check byte sequence */
120  for ( i = 0 ; i < pinger->len ; i++ ) {
121  if ( bytes[i] != ( i & 0xff ) )
122  return -EPROTO_DATA;
123  }
124 
125  return 0;
126 }
size_t len
Payload length.
Definition: pinger.c:72
#define EPROTO_DATA
Definition: pinger.c:49
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:16
A pinger.
Definition: pinger.c:57

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 134 of file pinger.c.

134  {
135 
136  /* Stop timer */
137  stop_timer ( &pinger->timer );
138 
139  /* Shut down interfaces */
140  intf_shutdown ( &pinger->xfer, rc );
141  intf_shutdown ( &pinger->job, rc );
142 }
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:278
struct interface xfer
Data transfer interface.
Definition: pinger.c:64
struct interface job
Job control interface.
Definition: pinger.c:62
struct retry_timer timer
Timer.
Definition: pinger.c:67
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition: retry.c:117
A pinger.
Definition: pinger.c:57

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 149 of file pinger.c.

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

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 166 of file pinger.c.

166  {
167  struct pinger *pinger = container_of ( timer, struct pinger, timer );
168  struct xfer_metadata meta;
169  struct io_buffer *iobuf;
170  int rc;
171 
172  /* If no response has been received, notify the callback function */
173  if ( pinger->pending && pinger->callback )
175 
176  /* Check for termination */
177  if ( pinger->remaining && ( --pinger->remaining == 0 ) ) {
179  return;
180  }
181 
182  /* Increase sequence number */
183  pinger->sequence++;
184 
185  /* Restart timer. Do this before attempting to transmit, in
186  * case the transmission attempt fails.
187  */
189  pinger->pending = 1;
190 
191  /* Allocate I/O buffer */
192  iobuf = xfer_alloc_iob ( &pinger->xfer, pinger->len );
193  if ( ! iobuf ) {
194  DBGC ( pinger, "PINGER %p could not allocate I/O buffer\n",
195  pinger );
196  return;
197  }
198 
199  /* Generate payload */
200  pinger_generate ( pinger, iob_put ( iobuf, pinger->len ) );
201 
202  /* Generate metadata */
203  memset ( &meta, 0, sizeof ( meta ) );
204  meta.flags = XFER_FL_ABS_OFFSET;
205  meta.offset = pinger->sequence;
206 
207  /* Transmit packet */
208  if ( ( rc = xfer_deliver ( &pinger->xfer, iobuf, &meta ) ) != 0 ) {
209  DBGC ( pinger, "PINGER %p could not transmit: %s\n",
210  pinger, strerror ( rc ) );
211  return;
212  }
213 }
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
struct interface xfer
Data transfer interface.
Definition: pinger.c:64
#define XFER_FL_ABS_OFFSET
Offset is absolute.
Definition: xfer.h:47
size_t len
Payload length.
Definition: pinger.c:72
#define DBGC(...)
Definition: compiler.h:505
void(* callback)(struct sockaddr *src, unsigned int sequence, size_t len, int rc)
Callback function.
Definition: pinger.c:89
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition: xfer.c:158
uint16_t sequence
Current sequence number.
Definition: pinger.c:74
A timer.
Definition: timer.h:28
int rc
Return status.
Definition: pinger.c:80
#define container_of(ptr, type, field)
Get containing structure.
Definition: stddef.h:35
struct retry_timer timer
Timer.
Definition: pinger.c:67
static void pinger_close(struct pinger *pinger, int rc)
Close pinger.
Definition: pinger.c:134
int meta(WINDOW *, bool)
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition: xfer.c:194
unsigned long timeout
Timeout.
Definition: pinger.c:69
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition: retry.c:64
static void pinger_generate(struct pinger *pinger, void *data)
Generate payload.
Definition: pinger.c:99
unsigned int remaining
Number of remaining expiry events (zero to continue indefinitely)
Definition: pinger.c:78
int pending
Response for current sequence number is still pending.
Definition: pinger.c:76
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
#define ETIMEDOUT
Connection timed out.
Definition: errno.h:669
A pinger.
Definition: pinger.c:57
void * memset(void *dest, int character, size_t len) __nonnull
A persistent I/O buffer.
Definition: iobuf.h:33

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 223 of file pinger.c.

224  {
225  size_t len = iob_len ( iobuf );
226  uint16_t sequence = meta->offset;
227  int terminate = 0;
228  int rc;
229 
230  /* Clear response pending flag, if applicable */
231  if ( sequence == pinger->sequence )
232  pinger->pending = 0;
233 
234  /* Check for errors */
235  if ( len != pinger->len ) {
236  /* Incorrect length: terminate immediately if we are
237  * not pinging indefinitely.
238  */
239  DBGC ( pinger, "PINGER %p received incorrect length %zd "
240  "(expected %zd)\n", pinger, len, pinger->len );
241  rc = -EPROTO_LEN;
242  terminate = ( pinger->remaining != 0 );
243  } else if ( ( rc = pinger_verify ( pinger, iobuf->data ) ) != 0 ) {
244  /* Incorrect data: terminate immediately if we are not
245  * pinging indefinitely.
246  */
247  DBGC ( pinger, "PINGER %p received incorrect data:\n", pinger );
248  DBGC_HDA ( pinger, 0, iobuf->data, iob_len ( iobuf ) );
249  terminate = ( pinger->remaining != 0 );
250  } else if ( sequence != pinger->sequence ) {
251  /* Incorrect sequence number (probably a delayed response):
252  * report via callback but otherwise ignore.
253  */
254  DBGC ( pinger, "PINGER %p received sequence %d (expected %d)\n",
255  pinger, sequence, pinger->sequence );
256  rc = -EPROTO_SEQ;
257  terminate = 0;
258  } else {
259  /* Success: record that a packet was successfully received,
260  * and terminate if we expect to send no further packets.
261  */
262  rc = 0;
263  pinger->rc = 0;
264  terminate = ( pinger->remaining == 1 );
265  }
266 
267  /* Discard I/O buffer */
268  free_iob ( iobuf );
269 
270  /* Notify callback function, if applicable */
271  if ( pinger->callback )
272  pinger->callback ( meta->src, sequence, len, rc );
273 
274  /* Terminate if applicable */
275  if ( terminate )
276  pinger_close ( pinger, rc );
277 
278  return rc;
279 }
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:72
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:146
#define DBGC(...)
Definition: compiler.h:505
void(* callback)(struct sockaddr *src, unsigned int sequence, size_t len, int rc)
Callback function.
Definition: pinger.c:89
#define EPROTO_SEQ
Definition: pinger.c:52
uint16_t sequence
Current sequence number.
Definition: pinger.c:74
int rc
Return status.
Definition: pinger.c:80
static int pinger_verify(struct pinger *pinger, const void *data)
Verify payload.
Definition: pinger.c:115
#define DBGC_HDA(...)
Definition: compiler.h:506
#define EPROTO_LEN
Definition: pinger.c:46
static void pinger_close(struct pinger *pinger, int rc)
Close pinger.
Definition: pinger.c:134
int meta(WINDOW *, bool)
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:155
uint32_t len
Length.
Definition: ena.h:14
void * data
Start of data.
Definition: iobuf.h:48
unsigned int remaining
Number of remaining expiry events (zero to continue indefinitely)
Definition: pinger.c:78
int pending
Response for current sequence number is still pending.
Definition: pinger.c:76
A pinger.
Definition: pinger.c:57

References pinger::callback, io_buffer::data, DBGC, DBGC_HDA, EPROTO_LEN, EPROTO_SEQ, free_iob(), iob_len(), len, pinger::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 312 of file pinger.c.

316  {
317  struct pinger *pinger;
318  int rc;
319 
320  /* Sanity check */
321  if ( ! timeout )
322  return -EINVAL;
323 
324  /* Allocate and initialise structure */
325  pinger = zalloc ( sizeof ( *pinger ) );
326  if ( ! pinger )
327  return -ENOMEM;
328  ref_init ( &pinger->refcnt, NULL );
331  timer_init ( &pinger->timer, pinger_expired, &pinger->refcnt );
333  pinger->len = len;
334  pinger->remaining = ( count ? ( count + 1 /* Initial packet */ ) : 0 );
336  pinger->rc = -ETIMEDOUT;
337 
338  /* Open socket */
340  hostname, NULL ) ) != 0 ) {
341  DBGC ( pinger, "PINGER %p could not open socket: %s\n",
342  pinger, strerror ( rc ) );
343  goto err;
344  }
345 
346  /* Attach parent interface, mortalise self, and return */
347  intf_plug_plug ( &pinger->job, job );
348  ref_put ( &pinger->refcnt );
349  return 0;
350 
351  err:
352  pinger_close ( pinger, rc );
353  ref_put ( &pinger->refcnt );
354  return rc;
355 }
#define EINVAL
Invalid argument.
Definition: errno.h:428
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
struct refcnt refcnt
Reference count.
Definition: pinger.c:59
struct interface xfer
Data transfer interface.
Definition: pinger.c:64
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition: refcnt.h:64
size_t len
Payload length.
Definition: pinger.c:72
#define DBGC(...)
Definition: compiler.h:505
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition: interface.c:107
void(* callback)(struct sockaddr *src, unsigned int sequence, size_t len, int rc)
Callback function.
Definition: pinger.c:89
static void pinger_expired(struct retry_timer *timer, int over __unused)
Handle timer expiry.
Definition: pinger.c:166
int rc
Return status.
Definition: pinger.c:80
#define ENOMEM
Not enough space.
Definition: errno.h:534
#define SOCK_ECHO
Definition: socket.h:34
struct interface job
Job control interface.
Definition: pinger.c:62
struct retry_timer timer
Timer.
Definition: pinger.c:67
static void pinger_close(struct pinger *pinger, int rc)
Close pinger.
Definition: pinger.c:134
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
void * zalloc(size_t size)
Allocate cleared memory.
Definition: malloc.c:624
unsigned long timeout
Timeout.
Definition: pinger.c:69
uint32_t len
Length.
Definition: ena.h:14
uint16_t count
Number of entries.
Definition: ena.h:22
void timeout(int)
static struct interface_descriptor pinger_xfer_desc
Pinger data transfer interface descriptor.
Definition: pinger.c:289
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition: interface.h:203
static struct interface_descriptor pinger_job_desc
Pinger job control interface descriptor.
Definition: pinger.c:298
unsigned int remaining
Number of remaining expiry events (zero to continue indefinitely)
Definition: pinger.c:78
#define NULL
NULL pointer (VOID *)
Definition: Base.h:321
#define ETIMEDOUT
Connection timed out.
Definition: errno.h:669
A pinger.
Definition: pinger.c:57
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:402
#define ref_put(refcnt)
Drop reference to object.
Definition: refcnt.h:106

References pinger::callback, count, DBGC, EINVAL, ENOMEM, ETIMEDOUT, intf_init(), intf_plug_plug(), pinger::job, len, pinger::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:146
void intf_close(struct interface *intf, int rc)
Close an object interface.
Definition: interface.c:249
static int pinger_deliver(struct pinger *pinger, struct io_buffer *iobuf, struct xfer_metadata *meta)
Handle received data.
Definition: pinger.c:223
static void pinger_window_changed(struct pinger *pinger)
Handle data transfer window change.
Definition: pinger.c:149
static void pinger_close(struct pinger *pinger, int rc)
Close pinger.
Definition: pinger.c:134
#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
A pinger.
Definition: pinger.c:57

Pinger data transfer interface operations.

Definition at line 282 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:64
static struct interface_operation pinger_xfer_op[]
Pinger data transfer interface operations.
Definition: pinger.c:282
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:80
A pinger.
Definition: pinger.c:57

Pinger data transfer interface descriptor.

Definition at line 289 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:249
static void pinger_close(struct pinger *pinger, int rc)
Close pinger.
Definition: pinger.c:134
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition: interface.h:32
A pinger.
Definition: pinger.c:57

Pinger job control interface operations.

Definition at line 293 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:293
struct interface job
Job control interface.
Definition: pinger.c:62
#define INTF_DESC(object_type, intf, operations)
Define an object interface descriptor.
Definition: interface.h:80
A pinger.
Definition: pinger.c:57

Pinger job control interface descriptor.

Definition at line 298 of file pinger.c.

Referenced by create_pinger().