iPXE
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.
static int pinger_verify (struct pinger *pinger, const void *data)
 Verify payload.
static void pinger_close (struct pinger *pinger, int rc)
 Close pinger.
static void pinger_window_changed (struct pinger *pinger)
 Handle data transfer window change.
static void pinger_expired (struct retry_timer *timer, int over __unused)
 Handle timer expiry.
static int pinger_deliver (struct pinger *pinger, struct io_buffer *iobuf, struct xfer_metadata *meta)
 Handle received data.
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.

Variables

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

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.

Referenced by pinger_deliver().

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

48#define EINFO_EPROTO_LEN __einfo_uniqify ( EINFO_EPROTO, 0x01, \
49 "Incorrect reply length" )

◆ EPROTO_DATA

#define EPROTO_DATA   __einfo_error ( EINFO_EPROTO_DATA )

Definition at line 50 of file pinger.c.

Referenced by pinger_verify().

◆ EINFO_EPROTO_DATA

#define EINFO_EPROTO_DATA
Value:
"Incorrect reply data" )

Definition at line 51 of file pinger.c.

51#define EINFO_EPROTO_DATA __einfo_uniqify ( EINFO_EPROTO, 0x02, \
52 "Incorrect reply data" )

◆ EPROTO_SEQ

#define EPROTO_SEQ   __einfo_error ( EINFO_EPROTO_SEQ )

Definition at line 53 of file pinger.c.

Referenced by pinger_deliver().

◆ EINFO_EPROTO_SEQ

#define EINFO_EPROTO_SEQ
Value:
"Delayed or out-of-sequence reply" )

Definition at line 54 of file pinger.c.

54#define EINFO_EPROTO_SEQ __einfo_uniqify ( EINFO_EPROTO, 0x03, \
55 "Delayed or out-of-sequence reply" )

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ pinger_generate()

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}
unsigned char uint8_t
Definition stdint.h:10
uint8_t data[48]
Additional event data.
Definition ena.h:11
uint8_t bytes[64]
Definition ib_mad.h:5
A pinger.
Definition pinger.c:58
size_t len
Payload length.
Definition pinger.c:73

References bytes, data, and pinger::len.

Referenced by pinger_expired().

◆ pinger_verify()

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}
#define EPROTO_DATA
Definition pinger.c:50

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

Referenced by pinger_deliver().

◆ pinger_close()

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 */
142 intf_shutdown ( &pinger->job, rc );
143}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
void intf_shutdown(struct interface *intf, int rc)
Shut down an object interface.
Definition interface.c:279
void stop_timer(struct retry_timer *timer)
Stop timer.
Definition retry.c:118
struct interface job
Job control interface.
Definition pinger.c:63
struct retry_timer timer
Timer.
Definition pinger.c:68
struct interface xfer
Data transfer interface.
Definition pinger.c:65

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

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
size_t xfer_window(struct interface *intf)
Check flow control window.
Definition xfer.c:117

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

◆ pinger_expired()

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}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
uint8_t meta
Metadata flags.
Definition ena.h:3
#define DBGC(...)
Definition compiler.h:505
#define ETIMEDOUT
Connection timed out.
Definition errno.h:670
void * memset(void *dest, int character, size_t len) __nonnull
#define iob_put(iobuf, len)
Definition iobuf.h:125
static void pinger_generate(struct pinger *pinger, void *data)
Generate payload.
Definition pinger.c:100
static void pinger_close(struct pinger *pinger, int rc)
Close pinger.
Definition pinger.c:135
void start_timer_fixed(struct retry_timer *timer, unsigned long timeout)
Start timer with a specified timeout.
Definition retry.c:65
#define container_of(ptr, type, field)
Get containing structure.
Definition stddef.h:36
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
A persistent I/O buffer.
Definition iobuf.h:38
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
unsigned long timeout
Timeout.
Definition pinger.c:70
void(* callback)(struct sockaddr *src, unsigned int sequence, size_t len, int rc)
Callback function.
Definition pinger.c:90
int rc
Return status.
Definition pinger.c:81
uint16_t sequence
Current sequence number.
Definition pinger.c:75
A timer.
Definition timer.h:29
Data transfer metadata.
Definition xfer.h:23
int xfer_deliver(struct interface *intf, struct io_buffer *iobuf, struct xfer_metadata *meta)
Deliver datagram.
Definition xfer.c:195
struct io_buffer * xfer_alloc_iob(struct interface *intf, size_t len)
Allocate I/O buffer.
Definition xfer.c:159
#define XFER_FL_ABS_OFFSET
Offset is absolute.
Definition xfer.h:48

References __unused, 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()

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 )
278
279 return rc;
280}
unsigned short uint16_t
Definition stdint.h:11
ring len
Length.
Definition dwmac.h:226
#define DBGC_HDA(...)
Definition compiler.h:506
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
#define EPROTO_SEQ
Definition pinger.c:53
static int pinger_verify(struct pinger *pinger, const void *data)
Verify payload.
Definition pinger.c:116
#define EPROTO_LEN
Definition pinger.c:47
void * data
Start of data.
Definition iobuf.h:53

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(* callback )(struct sockaddr *src, unsigned int sequence, size_t len, int rc) )

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 */
349 ref_put ( &pinger->refcnt );
350 return 0;
351
352 err:
354 ref_put ( &pinger->refcnt );
355 return rc;
356}
void timeout(int)
#define SOCK_ECHO
Definition socket.h:35
static unsigned int count
Number of entries.
Definition dwmac.h:220
#define EINVAL
Invalid argument.
Definition errno.h:429
#define ENOMEM
Not enough space.
Definition errno.h:535
void intf_plug_plug(struct interface *a, struct interface *b)
Plug two object interfaces together.
Definition interface.c:108
static void intf_init(struct interface *intf, struct interface_descriptor *desc, struct refcnt *refcnt)
Initialise an object interface.
Definition interface.h:204
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:662
static struct interface_descriptor pinger_xfer_desc
Pinger data transfer interface descriptor.
Definition pinger.c:290
static struct interface_descriptor pinger_job_desc
Pinger job control interface descriptor.
Definition pinger.c:299
static void pinger_expired(struct retry_timer *timer, int over __unused)
Handle timer expiry.
Definition pinger.c:167
#define ref_put(refcnt)
Drop reference to object.
Definition refcnt.h:107
#define ref_init(refcnt, free)
Initialise a reference counter.
Definition refcnt.h:65
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
struct refcnt refcnt
Reference count.
Definition pinger.c:60

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, src, 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 intf_close(struct interface *intf, int rc)
Close an object interface.
Definition interface.c:250
#define INTF_OP(op_type, object_type, op_func)
Define an object interface operation.
Definition interface.h:33
static void pinger_window_changed(struct pinger *pinger)
Handle data transfer window change.
Definition pinger.c:150
static int pinger_deliver(struct pinger *pinger, struct io_buffer *iobuf, struct xfer_metadata *meta)
Handle received data.
Definition pinger.c:224
void xfer_window_changed(struct interface *intf)
Report change of flow control window.
Definition xfer.c:147

Pinger data transfer interface operations.

Definition at line 283 of file pinger.c.

283 {
286 INTF_OP ( intf_close, struct pinger *, pinger_close ),
287};

◆ pinger_xfer_desc

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

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:
= {
}

Pinger job control interface operations.

Definition at line 294 of file pinger.c.

294 {
295 INTF_OP ( intf_close, struct pinger *, pinger_close ),
296};

◆ pinger_job_desc

struct interface_descriptor pinger_job_desc
static
Initial value:
=
INTF_DESC ( struct pinger, job, pinger_job_op )
static struct interface_operation pinger_job_op[]
Pinger job control interface operations.
Definition pinger.c:294

Pinger job control interface descriptor.

Definition at line 299 of file pinger.c.

Referenced by create_pinger().