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

ICMP ping protocol. More...

#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/refcnt.h>
#include <ipxe/list.h>
#include <ipxe/iobuf.h>
#include <ipxe/tcpip.h>
#include <ipxe/icmp.h>
#include <ipxe/interface.h>
#include <ipxe/xfer.h>
#include <ipxe/open.h>
#include <ipxe/netdevice.h>
#include <ipxe/ping.h>

Go to the source code of this file.

Data Structures

struct  ping_connection
 A ping connection. More...

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
static LIST_HEAD (ping_conns)
 List of registered ping connections.
static struct ping_connectionping_demux (unsigned int port)
 Identify ping connection by local port number.
static int ping_port_available (int port)
 Check if local port number is available.
int ping_rx (struct io_buffer *iobuf, struct sockaddr_tcpip *st_src)
 Process ICMP ping reply.
static struct io_bufferping_alloc_iob (struct ping_connection *ping __unused, size_t len)
 Allocate I/O buffer for ping.
static int ping_deliver (struct ping_connection *ping, struct io_buffer *iobuf, struct xfer_metadata *meta)
 Deliver datagram as I/O buffer.
static void ping_close (struct ping_connection *ping, int rc)
 Close ping connection.
static int ping_open (struct interface *xfer, struct sockaddr *peer, struct sockaddr *local)
 Open a ping connection.

Variables

static struct interface_operation ping_xfer_operations []
 Ping data transfer interface operations.
static struct interface_descriptor ping_xfer_desc
 Ping data transfer interface descriptor.
struct socket_opener
ping_ipv4_socket_opener 
__socket_opener
 Ping IPv4 socket opener.
int ping_sock_echo = PING_SOCK_ECHO
 Linkage hack.

Detailed Description

ICMP ping protocol.

Definition in file ping.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )
static LIST_HEAD ( ping_conns  ) [static]

List of registered ping connections.

static struct ping_connection* ping_demux ( unsigned int  port) [static, read]

Identify ping connection by local port number.

Parameters:
portLocal port number
Return values:
pingPing connection, or NULL

Definition at line 75 of file ping.c.

References ping_connection::list, list_for_each_entry, NULL, ping(), and ping_connection::port.

Referenced by ping_port_available(), and ping_rx().

                                                                 {
        struct ping_connection *ping;

        list_for_each_entry ( ping, &ping_conns, list ) {
                if ( ping->port == port )
                        return ping;
        }
        return NULL;
}
static int ping_port_available ( int  port) [static]

Check if local port number is available.

Parameters:
portLocal port number
Return values:
portLocal port number, or negative error

Definition at line 91 of file ping.c.

References EADDRINUSE, and ping_demux().

Referenced by ping_open().

                                            {

        return ( ping_demux ( port ) ? -EADDRINUSE : port );
}
int ping_rx ( struct io_buffer iobuf,
struct sockaddr_tcpip st_src 
)

Process ICMP ping reply.

Parameters:
iobufI/O buffer
st_srcSource address
Return values:
rcReturn status code

Definition at line 103 of file ping.c.

References assert, io_buffer::data, DBGC, echo(), ENOTCONN, xfer_metadata::flags, free_iob(), icmp_echo::ident, iob_disown, iob_len(), iob_pull, memset(), ntohs, xfer_metadata::offset, ping(), ping_demux(), rc, icmp_echo::sequence, xfer_metadata::src, ping_connection::xfer, xfer_deliver(), and XFER_FL_ABS_OFFSET.

                                                                       {
        struct icmp_echo *echo = iobuf->data;
        struct ping_connection *ping;
        struct xfer_metadata meta;
        int rc;

        /* Sanity check: should already have been checked by ICMP layer */
        assert ( iob_len ( iobuf ) >= sizeof ( *echo ) );

        /* Identify connection */
        ping = ping_demux ( ntohs ( echo->ident ) );
        DBGC ( ping, "PING %p reply id %#04x seq %#04x\n",
               ping, ntohs ( echo->ident ), ntohs ( echo->sequence ) );
        if ( ! ping ) {
                rc = -ENOTCONN;
                goto discard;
        }

        /* Strip header, construct metadata, and pass data to upper layer */
        iob_pull ( iobuf, sizeof ( *echo ) );
        memset ( &meta, 0, sizeof ( meta ) );
        meta.src = ( ( struct sockaddr * ) st_src );
        meta.flags = XFER_FL_ABS_OFFSET;
        meta.offset = ntohs ( echo->sequence );
        return xfer_deliver ( &ping->xfer, iob_disown ( iobuf ), &meta );

 discard:
        free_iob ( iobuf );
        return rc;
}
static struct io_buffer* ping_alloc_iob ( struct ping_connection *ping  __unused,
size_t  len 
) [static, read]

Allocate I/O buffer for ping.

Parameters:
pingPing connection
lenPayload size
Return values:
iobufI/O buffer, or NULL

Definition at line 142 of file ping.c.

References alloc_iob(), iob_reserve, and MAX_LL_NET_HEADER_LEN.

                                                                     {
        size_t header_len;
        struct io_buffer *iobuf;

        header_len = ( MAX_LL_NET_HEADER_LEN + sizeof ( struct icmp_echo ) );
        iobuf = alloc_iob ( header_len + len );
        if ( iobuf )
                iob_reserve ( iobuf, header_len );
        return iobuf;
}
static int ping_deliver ( struct ping_connection ping,
struct io_buffer iobuf,
struct xfer_metadata meta 
) [static]

Deliver datagram as I/O buffer.

Parameters:
pingPing connection
iobufI/O buffer
metaData transfer metadata
Return values:
rcReturn status code

Definition at line 161 of file ping.c.

References DBGC, echo(), htons, icmp_tx_echo_request(), icmp_echo::ident, iob_disown, iob_push, memset(), xfer_metadata::offset, ping_connection::peer, ping_connection::port, rc, icmp_echo::sequence, and strerror().

                                                       {
        struct icmp_echo *echo = iob_push ( iobuf, sizeof ( *echo ) );
        int rc;

        /* Construct header */
        memset ( echo, 0, sizeof ( *echo ) );
        echo->ident = htons ( ping->port );
        echo->sequence = htons ( meta->offset );

        /* Transmit echo request */
        if ( ( rc = icmp_tx_echo_request ( iob_disown ( iobuf ),
                                           &ping->peer ) ) != 0 ) {
                DBGC ( ping, "PING %p could not transmit: %s\n",
                       ping, strerror ( rc ) );
                return rc;
        }

        return 0;
}
static void ping_close ( struct ping_connection ping,
int  rc 
) [static]

Close ping connection.

Parameters:
pingPing connection
rcReason for close

Definition at line 188 of file ping.c.

References DBGC, intf_shutdown(), ping_connection::list, list_del, ref_put, ping_connection::refcnt, and ping_connection::xfer.

                                                                {

        /* Close data transfer interface */
        intf_shutdown ( &ping->xfer, rc );

        /* Remove from list of connections and drop list's reference */
        list_del ( &ping->list );
        ref_put ( &ping->refcnt );

        DBGC ( ping, "PING %p closed\n", ping );
}
static int ping_open ( struct interface xfer,
struct sockaddr peer,
struct sockaddr local 
) [static]

Open a ping connection.

Parameters:
xferData transfer interface
peerPeer socket address
localLocal socket address, or NULL
Return values:
rcReturn status code

Definition at line 219 of file ping.c.

References DBGC, ENOMEM, intf_init(), intf_plug_plug(), ping_connection::list, list_add, memcpy(), NULL, ping_connection::peer, ping(), ping_port_available(), ping_connection::port, port, rc, ref_init, ref_put, ping_connection::refcnt, strerror(), tcpip_bind(), ping_connection::xfer, and zalloc().

                                                {
        struct sockaddr_tcpip *st_peer = ( struct sockaddr_tcpip * ) peer;
        struct sockaddr_tcpip *st_local = ( struct sockaddr_tcpip * ) local;
        struct ping_connection *ping;
        int port;
        int rc;

        /* Allocate and initialise structure */
        ping = zalloc ( sizeof ( *ping ) );
        if ( ! ping ) {
                rc = -ENOMEM;
                goto err_alloc;
        }
        DBGC ( ping, "PING %p allocated\n", ping );
        ref_init ( &ping->refcnt, NULL );
        intf_init ( &ping->xfer, &ping_xfer_desc, &ping->refcnt );
        memcpy ( &ping->peer, st_peer, sizeof ( ping->peer ) );

        /* Bind to local port */
        port = tcpip_bind ( st_local, ping_port_available );
        if ( port < 0 ) {
                rc = port;
                DBGC ( ping, "PING %p could not bind: %s\n",
                       ping, strerror ( rc ) );
                goto err_bind;
        }
        ping->port = port;
        DBGC ( ping, "PING %p bound to id %#04x\n", ping, port );

        /* Attach parent interface, transfer reference to connection
         * list, and return
         */
        intf_plug_plug ( &ping->xfer, xfer );
        list_add ( &ping->list, &ping_conns );
        return 0;

 err_bind:
        ref_put ( &ping->refcnt );
 err_alloc:
        return rc;
}

Variable Documentation

Initial value:

Ping data transfer interface operations.

Definition at line 201 of file ping.c.

Initial value:

Ping data transfer interface descriptor.

Definition at line 208 of file ping.c.

struct socket_opener ping_ipv6_socket_opener __socket_opener
Initial value:
 {
        .semantics      = PING_SOCK_ECHO,
        .family         = AF_INET,
        .open           = ping_open,
}

Ping IPv4 socket opener.

Ping IPv6 socket opener.

Definition at line 263 of file ping.c.