]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[icmp] Add support for sending ICMP echo requests
authorMichael Brown <mcb30@ipxe.org>
Mon, 21 Oct 2013 13:10:07 +0000 (14:10 +0100)
committerMichael Brown <mcb30@ipxe.org>
Mon, 21 Oct 2013 14:08:12 +0000 (15:08 +0100)
Merge common functionality between IPv4 and IPv6 ICMP echo handling,
and add support for transmitting ICMP echo requests and delivering
ICMP echo replies to a (not yet implemented) ping_rx() function.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/include/ipxe/errfile.h
src/include/ipxe/icmp.h
src/include/ipxe/icmpv6.h
src/include/ipxe/ndp.h
src/include/ipxe/ping.h [new file with mode: 0644]
src/net/icmp.c
src/net/icmpv4.c [new file with mode: 0644]
src/net/icmpv6.c
src/net/ipv4.c

index c55107a9a0852cedbab99d14ab39f3bd3a7d333e..376f88c2ace921238c9e0334863cf8ae1be96cb1 100644 (file)
@@ -184,7 +184,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #define ERRFILE_slam                   ( ERRFILE_NET | 0x00160000 )
 #define ERRFILE_ib_sma                 ( ERRFILE_NET | 0x00170000 )
 #define ERRFILE_ib_packet              ( ERRFILE_NET | 0x00180000 )
-#define ERRFILE_icmp                   ( ERRFILE_NET | 0x00190000 )
+#define ERRFILE_icmpv4                 ( ERRFILE_NET | 0x00190000 )
 #define ERRFILE_ib_qset                        ( ERRFILE_NET | 0x001a0000 )
 #define ERRFILE_ib_gma                 ( ERRFILE_NET | 0x001b0000 )
 #define ERRFILE_ib_pathrec             ( ERRFILE_NET | 0x001c0000 )
@@ -216,6 +216,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #define ERRFILE_oncrpc_iob             ( ERRFILE_NET | 0x00360000 )
 #define ERRFILE_neighbour              ( ERRFILE_NET | 0x00370000 )
 #define ERRFILE_socket                 ( ERRFILE_NET | 0x00380000 )
+#define ERRFILE_icmp                   ( ERRFILE_NET | 0x00390000 )
 
 #define ERRFILE_image                ( ERRFILE_IMAGE | 0x00000000 )
 #define ERRFILE_elf                  ( ERRFILE_IMAGE | 0x00010000 )
index e402ce40e6d64194075e826e0318e3da7b19fcff..0480ddfaf416a30e5e4c82c2d036ff60c0918db7 100644 (file)
@@ -9,6 +9,12 @@
 
 FILE_LICENCE ( GPL2_OR_LATER );
 
+#include <stdint.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/socket.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/tables.h>
+
 /** An ICMP header */
 struct icmp_header {
        /** Type */
@@ -19,7 +25,49 @@ struct icmp_header {
        uint16_t chksum;
 } __attribute__ (( packed ));
 
-#define ICMP_ECHO_RESPONSE 0
+/** An ICMP echo request/reply */
+struct icmp_echo {
+       /** ICMPv6 header */
+       struct icmp_header icmp;
+       /** Identifier */
+       uint16_t ident;
+       /** Sequence number */
+       uint16_t sequence;
+       /** Data */
+       uint8_t data[0];
+} __attribute__ (( packed ));
+
+/** An ICMP echo protocol */
+struct icmp_echo_protocol {
+       /** Address family */
+       sa_family_t family;
+       /** Request type */
+       uint8_t request;
+       /** Reply type */
+       uint8_t reply;
+       /** TCP/IP protocol */
+       struct tcpip_protocol *tcpip_protocol;
+       /** Include network-layer checksum within packet */
+       int net_checksum;
+};
+
+/** ICMP echo protocol table */
+#define ICMP_ECHO_PROTOCOLS \
+       __table ( struct icmp_echo_protocol, "icmp_echo_protocols" )
+
+/** Declare an ICMP echo protocol */
+#define __icmp_echo_protocol __table_entry ( ICMP_ECHO_PROTOCOLS, 01 )
+
+#define ICMP_ECHO_REPLY 0
 #define ICMP_ECHO_REQUEST 8
 
+extern int icmp_tx_echo_request ( struct io_buffer *iobuf,
+                                 struct sockaddr_tcpip *st_dest );
+
+extern int icmp_rx_echo_request ( struct io_buffer *iobuf,
+                                 struct sockaddr_tcpip *st_src,
+                                 struct icmp_echo_protocol *echo_protocol );
+extern int icmp_rx_echo_reply ( struct io_buffer *iobuf,
+                               struct sockaddr_tcpip *st_src );
+
 #endif /* _IPXE_ICMP_H */
index c8f0be05a4387e4f18a1f4a9e19407f0bfb006b1..c09a71a023fc2608c7d4b4eb78d79808b2672609 100644 (file)
@@ -13,28 +13,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <ipxe/tables.h>
 #include <ipxe/iobuf.h>
 #include <ipxe/netdevice.h>
-
-/** An ICMPv6 header */
-struct icmpv6_header {
-       /** Type */
-       uint8_t type;
-       /** Code */
-       uint8_t code;
-       /** Checksum */
-       uint16_t chksum;
-} __attribute__ (( packed ));
-
-/** An ICMPv6 echo request/reply */
-struct icmpv6_echo {
-       /** ICMPv6 header */
-       struct icmpv6_header icmp;
-       /** Identifier */
-       uint16_t ident;
-       /** Sequence number */
-       uint16_t sequence;
-       /** Data */
-       uint8_t data[0];
-} __attribute__ (( packed ));
+#include <ipxe/icmp.h>
 
 /** An ICMPv6 handler */
 struct icmpv6_handler {
index 7b98637f826a242fe9210f554536227ad848c60a..1f05e9abeb76a82b6acb873a14ad829b7e5e1cfa 100644 (file)
@@ -31,7 +31,7 @@ struct ndp_option {
 /** An NDP header */
 struct ndp_header {
        /** ICMPv6 header */
-       struct icmpv6_header icmp;
+       struct icmp_header icmp;
        /** Flags */
        uint8_t flags;
        /** Reserved */
diff --git a/src/include/ipxe/ping.h b/src/include/ipxe/ping.h
new file mode 100644 (file)
index 0000000..6cd376b
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef _IPXE_PING_H
+#define _IPXE_PING_H
+
+/** @file
+ *
+ * ICMP ping protocol
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <ipxe/iobuf.h>
+#include <ipxe/tcpip.h>
+
+extern int ping_rx ( struct io_buffer *iobuf,
+                    struct sockaddr_tcpip *st_src );
+
+#endif /* _IPXE_PING_H */
index 6142b7483163f73774ccda3f7ffd33b0b5722e06..1bbf8bd30e8f805a23da916c39387dbb8a8978e7 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2009 Michael Brown <mbrown@fensystems.co.uk>.
+ * Copyright (C) 2013 Michael Brown <mbrown@fensystems.co.uk>.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
 FILE_LICENCE ( GPL2_OR_LATER );
 
 #include <string.h>
+#include <byteswap.h>
 #include <errno.h>
 #include <ipxe/iobuf.h>
 #include <ipxe/in.h>
 #include <ipxe/tcpip.h>
+#include <ipxe/ping.h>
+#include <ipxe/crc32.h>
 #include <ipxe/icmp.h>
 
 /** @file
@@ -32,76 +35,192 @@ FILE_LICENCE ( GPL2_OR_LATER );
  *
  */
 
-struct tcpip_protocol icmp_protocol __tcpip_protocol;
+/**
+ * Identify ICMP echo protocol
+ *
+ * @v st_family                Address family
+ * @ret echo_protocol  ICMP echo protocol, or NULL
+ */
+static struct icmp_echo_protocol * icmp_echo_protocol ( sa_family_t family ) {
+       struct icmp_echo_protocol *echo_protocol;
+
+       for_each_table_entry ( echo_protocol, ICMP_ECHO_PROTOCOLS ) {
+               if ( echo_protocol->family == family )
+                       return echo_protocol;
+       }
+       return NULL;
+}
 
 /**
- * Process a received packet
+ *
+ * Determine debugging colour for ICMP debug messages
+ *
+ * @v st_peer          Peer address
+ * @ret col            Debugging colour (for DBGC())
+ */
+static uint32_t icmpcol ( struct sockaddr_tcpip *st_peer ) {
+
+       return crc32_le ( 0, st_peer, sizeof ( *st_peer ) );
+}
+
+/**
+ * Transmit ICMP echo packet
  *
  * @v iobuf            I/O buffer
- * @v netdev           Network device
- * @v st_src           Partially-filled source address
- * @v st_dest          Partially-filled destination address
- * @v pshdr_csum       Pseudo-header checksum
+ * @v st_dest          Destination socket address
+ * @v echo_protocol    ICMP echo protocol
  * @ret rc             Return status code
  */
-static int icmp_rx ( struct io_buffer *iobuf,
-                    struct net_device *netdev __unused,
-                    struct sockaddr_tcpip *st_src,
-                    struct sockaddr_tcpip *st_dest,
-                    uint16_t pshdr_csum __unused ) {
-       struct icmp_header *icmp = iobuf->data;
-       size_t len = iob_len ( iobuf );
-       unsigned int csum;
+static int icmp_tx_echo ( struct io_buffer *iobuf,
+                         struct sockaddr_tcpip *st_dest,
+                         struct icmp_echo_protocol *echo_protocol ) {
+       struct icmp_echo *echo = iobuf->data;
        int rc;
 
-       /* Sanity check */
-       if ( len < sizeof ( *icmp ) ) {
-               DBG ( "ICMP packet too short at %zd bytes (min %zd bytes)\n",
-                     len, sizeof ( *icmp ) );
-               rc = -EINVAL;
-               goto done;
-       }
+       /* Set ICMP type and (re)calculate checksum */
+       echo->icmp.chksum = 0;
+       echo->icmp.chksum = tcpip_chksum ( echo, iob_len ( iobuf ) );
 
-       /* Verify checksum */
-       csum = tcpip_chksum ( icmp, len );
-       if ( csum != 0 ) {
-               DBG ( "ICMP checksum incorrect (is %04x, should be 0000)\n",
-                     csum );
-               DBG_HD ( icmp, len );
-               rc = -EINVAL;
-               goto done;
+       /* Transmit packet */
+       if ( ( rc = tcpip_tx ( iobuf, echo_protocol->tcpip_protocol, NULL,
+                              st_dest, NULL,
+                              ( echo_protocol->net_checksum ?
+                                &echo->icmp.chksum : NULL ) ) ) != 0 )
+               return rc;
+
+       return 0;
+}
+
+/**
+ * Transmit ICMP echo request
+ *
+ * @v iobuf            I/O buffer
+ * @v st_dest          Destination socket address
+ * @ret rc             Return status code
+ */
+int icmp_tx_echo_request ( struct io_buffer *iobuf,
+                          struct sockaddr_tcpip *st_dest ) {
+       struct icmp_echo *echo = iobuf->data;
+       struct icmp_echo_protocol *echo_protocol;
+       int rc;
+
+       /* Identify ICMP echo protocol */
+       echo_protocol = icmp_echo_protocol ( st_dest->st_family );
+       if ( ! echo_protocol ) {
+               DBGC ( icmpcol ( st_dest ), "ICMP TX echo request unknown "
+                      "address family %d\n", st_dest->st_family );
+               free_iob ( iobuf );
+               return -ENOTSUP;
        }
 
-       /* We respond only to pings */
-       if ( icmp->type != ICMP_ECHO_REQUEST ) {
-               DBG ( "ICMP ignoring type %d\n", icmp->type );
-               rc = 0;
-               goto done;
+       /* Set type */
+       echo->icmp.type = echo_protocol->request;
+
+       /* Transmit request */
+       DBGC ( icmpcol ( st_dest ), "ICMP TX echo request id %04x seq %04x\n",
+              ntohs ( echo->ident ), ntohs ( echo->sequence ) );
+       if ( ( rc = icmp_tx_echo ( iobuf, st_dest, echo_protocol ) ) != 0 )
+               return rc;
+
+       return 0;
+}
+
+/**
+ * Transmit ICMP echo reply
+ *
+ * @v iobuf            I/O buffer
+ * @v st_dest          Destination socket address
+ * @ret rc             Return status code
+ */
+static int icmp_tx_echo_reply ( struct io_buffer *iobuf,
+                               struct sockaddr_tcpip *st_dest,
+                               struct icmp_echo_protocol *echo_protocol ) {
+       struct icmp_echo *echo = iobuf->data;
+       int rc;
+
+       /* Set type */
+       echo->icmp.type = echo_protocol->reply;
+
+       /* Transmit reply */
+       DBGC ( icmpcol ( st_dest ), "ICMP TX echo reply id %04x seq %04x\n",
+              ntohs ( echo->ident ), ntohs ( echo->sequence ) );
+       if ( ( rc = icmp_tx_echo ( iobuf, st_dest, echo_protocol ) ) != 0 )
+               return rc;
+
+       return 0;
+}
+
+/**
+ * Process a received ICMP echo request
+ *
+ * @v iobuf            I/O buffer
+ * @v st_src           Source socket address
+ * @v echo_protocol    ICMP echo protocol
+ * @ret rc             Return status code
+ */
+int icmp_rx_echo_request ( struct io_buffer *iobuf,
+                          struct sockaddr_tcpip *st_src,
+                          struct icmp_echo_protocol *echo_protocol ) {
+       struct icmp_echo *echo = iobuf->data;
+       int rc;
+
+       /* Sanity check */
+       if ( iob_len ( iobuf ) < sizeof ( *echo ) ) {
+               DBGC ( icmpcol ( st_src ), "ICMP RX echo request too short at "
+                      "%zd bytes (min %zd bytes)\n",
+                      iob_len ( iobuf ), sizeof ( *echo ) );
+               free_iob ( iobuf );
+               return -EINVAL;
        }
+       DBGC ( icmpcol ( st_src ), "ICMP RX echo request id %04x seq %04x\n",
+              ntohs ( echo->ident ), ntohs ( echo->sequence ) );
 
-       DBG ( "ICMP responding to ping\n" );
+       /* Transmit echo reply */
+       if ( ( rc = icmp_tx_echo_reply ( iobuf, st_src, echo_protocol ) ) != 0 )
+               return rc;
 
-       /* Change type to response and recalculate checksum */
-       icmp->type = ICMP_ECHO_RESPONSE;
-       icmp->chksum = 0;
-       icmp->chksum = tcpip_chksum ( icmp, len );
+       return 0;
+}
 
-       /* Transmit the response */
-       if ( ( rc = tcpip_tx ( iob_disown ( iobuf ), &icmp_protocol, st_dest,
-                              st_src, NULL, NULL ) ) != 0 ) {
-               DBG ( "ICMP could not transmit ping response: %s\n",
-                     strerror ( rc ) );
-               goto done;
+/**
+ * Process a received ICMP echo request
+ *
+ * @v iobuf            I/O buffer
+ * @v st_src           Source socket address
+ * @ret rc             Return status code
+ */
+int icmp_rx_echo_reply ( struct io_buffer *iobuf,
+                        struct sockaddr_tcpip *st_src ) {
+       struct icmp_echo *echo = iobuf->data;
+       int rc;
+
+       /* Sanity check */
+       if ( iob_len ( iobuf ) < sizeof ( *echo ) ) {
+               DBGC ( icmpcol ( st_src ), "ICMP RX echo reply too short at "
+                      "%zd bytes (min %zd bytes)\n",
+                      iob_len ( iobuf ), sizeof ( *echo ) );
+               free_iob ( iobuf );
+               return -EINVAL;
        }
+       DBGC ( icmpcol ( st_src ), "ICMP RX echo reply id %04x seq %04x\n",
+              ntohs ( echo->ident ), ntohs ( echo->sequence ) );
 
- done:
-       free_iob ( iobuf );
-       return rc;
+       /* Deliver to ping protocol */
+       if ( ( rc = ping_rx ( iobuf, st_src ) ) != 0 )
+               return rc;
+
+       return 0;
 }
 
-/** ICMP TCP/IP protocol */
-struct tcpip_protocol icmp_protocol __tcpip_protocol = {
-       .name = "ICMP",
-       .rx = icmp_rx,
-       .tcpip_proto = IP_ICMP,
-};
+/**
+ * Receive ping reply (when no ping protocol is present)
+ *
+ * @v iobuf            I/O buffer
+ * @v st_src           Source socket address
+ * @ret rc             Return status code
+ */
+__weak int ping_rx ( struct io_buffer *iobuf,
+                    struct sockaddr_tcpip *st_src __unused ) {
+       free_iob ( iobuf );
+       return 0;
+}
diff --git a/src/net/icmpv4.c b/src/net/icmpv4.c
new file mode 100644 (file)
index 0000000..996ba14
--- /dev/null
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2013 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER );
+
+#include <string.h>
+#include <errno.h>
+#include <ipxe/iobuf.h>
+#include <ipxe/in.h>
+#include <ipxe/tcpip.h>
+#include <ipxe/icmp.h>
+
+/** @file
+ *
+ * ICMPv4 protocol
+ *
+ */
+
+struct icmp_echo_protocol icmpv4_echo_protocol __icmp_echo_protocol;
+
+/**
+ * Process a received packet
+ *
+ * @v iobuf            I/O buffer
+ * @v netdev           Network device
+ * @v st_src           Partially-filled source address
+ * @v st_dest          Partially-filled destination address
+ * @v pshdr_csum       Pseudo-header checksum
+ * @ret rc             Return status code
+ */
+static int icmpv4_rx ( struct io_buffer *iobuf,
+                      struct net_device *netdev __unused,
+                      struct sockaddr_tcpip *st_src,
+                      struct sockaddr_tcpip *st_dest __unused,
+                      uint16_t pshdr_csum __unused ) {
+       struct icmp_header *icmp = iobuf->data;
+       size_t len = iob_len ( iobuf );
+       unsigned int csum;
+       unsigned int type;
+       int rc;
+
+       /* Sanity check */
+       if ( len < sizeof ( *icmp ) ) {
+               DBG ( "ICMP packet too short at %zd bytes (min %zd bytes)\n",
+                     len, sizeof ( *icmp ) );
+               rc = -EINVAL;
+               goto discard;
+       }
+
+       /* Verify checksum */
+       csum = tcpip_chksum ( icmp, len );
+       if ( csum != 0 ) {
+               DBG ( "ICMP checksum incorrect (is %04x, should be 0000)\n",
+                     csum );
+               DBG_HD ( icmp, len );
+               rc = -EINVAL;
+               goto discard;
+       }
+
+       /* Handle ICMP packet */
+       type = icmp->type;
+       switch ( type ) {
+       case ICMP_ECHO_REQUEST:
+               return icmp_rx_echo_request ( iobuf, st_src,
+                                             &icmpv4_echo_protocol );
+       case ICMP_ECHO_REPLY:
+               return icmp_rx_echo_reply ( iobuf, st_src );
+       default:
+               DBG ( "ICMP ignoring type %d\n", type );
+               rc = 0;
+               break;
+       }
+
+ discard:
+       free_iob ( iobuf );
+       return rc;
+}
+
+/** ICMPv4 TCP/IP protocol */
+struct tcpip_protocol icmpv4_protocol __tcpip_protocol = {
+       .name = "ICMPv4",
+       .rx = icmpv4_rx,
+       .tcpip_proto = IP_ICMP,
+};
+
+/** ICMPv4 echo protocol */
+struct icmp_echo_protocol icmpv4_echo_protocol __icmp_echo_protocol = {
+       .family = AF_INET,
+       .request = ICMP_ECHO_REQUEST,
+       .reply = ICMP_ECHO_REPLY,
+       .tcpip_protocol = &icmpv4_protocol,
+       .net_checksum = 0,
+};
index 54426be8ad2cf8d91631b6f8293346ae6386eb20..479800e7d909d89b797e0b81efdb2913d5884670 100644 (file)
@@ -25,6 +25,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
 #include <ipxe/in.h>
 #include <ipxe/iobuf.h>
 #include <ipxe/tcpip.h>
+#include <ipxe/ping.h>
 #include <ipxe/icmpv6.h>
 
 /** @file
@@ -33,6 +34,8 @@ FILE_LICENCE ( GPL2_OR_LATER );
  *
  */
 
+struct icmp_echo_protocol icmpv6_echo_protocol __icmp_echo_protocol;
+
 /**
  * Process received ICMPv6 echo request packet
  *
@@ -42,50 +45,45 @@ FILE_LICENCE ( GPL2_OR_LATER );
  * @v sin6_dest                Destination socket address
  * @ret rc             Return status code
  */
-static int icmpv6_rx_echo ( struct io_buffer *iobuf,
-                           struct net_device *netdev,
-                           struct sockaddr_in6 *sin6_src,
-                           struct sockaddr_in6 *sin6_dest __unused ) {
+static int icmpv6_rx_echo_request ( struct io_buffer *iobuf,
+                                   struct net_device *netdev __unused,
+                                   struct sockaddr_in6 *sin6_src,
+                                   struct sockaddr_in6 *sin6_dest __unused ) {
        struct sockaddr_tcpip *st_src =
                ( ( struct sockaddr_tcpip * ) sin6_src );
-       struct icmpv6_echo *echo = iobuf->data;
-       size_t len = iob_len ( iobuf );
-       int rc;
 
-       /* Sanity check */
-       if ( iob_len ( iobuf ) < sizeof ( *echo ) ) {
-               DBGC ( netdev, "ICMPv6 echo request too short at %zd bytes "
-                      "(min %zd bytes)\n", iob_len ( iobuf ),
-                      sizeof ( *echo ) );
-               rc = -EINVAL;
-               goto done;
-       }
-       DBGC ( netdev, "ICMPv6 echo request from %s (id %#04x seq %#04x)\n",
-              inet6_ntoa ( &sin6_dest->sin6_addr ), ntohs ( echo->ident ),
-              ntohs ( echo->sequence ) );
-
-       /* Convert echo request to echo reply and recalculate checksum */
-       echo->icmp.type = ICMPV6_ECHO_REPLY;
-       echo->icmp.chksum = 0;
-       echo->icmp.chksum = tcpip_chksum ( echo, len );
-
-       /* Transmit echo reply */
-       if ( ( rc = tcpip_tx ( iob_disown ( iobuf ), &icmpv6_protocol, NULL,
-                              st_src, netdev, &echo->icmp.chksum ) ) != 0 ) {
-               DBGC ( netdev, "ICMPv6 could not transmit reply: %s\n",
-                      strerror ( rc ) );
-               goto done;
-       }
-
- done:
-       free_iob ( iobuf );
-       return rc;
+       return icmp_rx_echo_request ( iobuf, st_src, &icmpv6_echo_protocol );
 }
 
-/** ICMPv6 echo request handlers */
-struct icmpv6_handler icmpv6_echo_handler __icmpv6_handler = {
+/** ICMPv6 echo request handler */
+struct icmpv6_handler icmpv6_echo_request_handler __icmpv6_handler = {
        .type = ICMPV6_ECHO_REQUEST,
-       .rx = icmpv6_rx_echo,
+       .rx = icmpv6_rx_echo_request,
+};
+
+/**
+ * Process received ICMPv6 echo reply packet
+ *
+ * @v iobuf            I/O buffer
+ * @v netdev           Network device
+ * @v sin6_src         Source socket address
+ * @v sin6_dest                Destination socket address
+ * @ret rc             Return status code
+ */
+static int icmpv6_rx_echo_reply ( struct io_buffer *iobuf,
+                                 struct net_device *netdev __unused,
+                                 struct sockaddr_in6 *sin6_src,
+                                 struct sockaddr_in6 *sin6_dest __unused ) {
+       struct sockaddr_tcpip *st_src =
+               ( ( struct sockaddr_tcpip * ) sin6_src );
+
+       return icmp_rx_echo_reply ( iobuf, st_src );
+}
+
+/** ICMPv6 echo reply handler */
+struct icmpv6_handler icmpv6_echo_reply_handler __icmpv6_handler = {
+       .type = ICMPV6_ECHO_REPLY,
+       .rx = icmpv6_rx_echo_reply,
 };
 
 /**
@@ -119,7 +117,7 @@ static int icmpv6_rx ( struct io_buffer *iobuf, struct net_device *netdev,
                       struct sockaddr_tcpip *st_dest, uint16_t pshdr_csum ) {
        struct sockaddr_in6 *sin6_src = ( ( struct sockaddr_in6 * ) st_src );
        struct sockaddr_in6 *sin6_dest = ( ( struct sockaddr_in6 * ) st_dest );
-       struct icmpv6_header *icmp = iobuf->data;
+       struct icmp_header *icmp = iobuf->data;
        size_t len = iob_len ( iobuf );
        struct icmpv6_handler *handler;
        unsigned int csum;
@@ -170,3 +168,12 @@ struct tcpip_protocol icmpv6_protocol __tcpip_protocol = {
        .rx = icmpv6_rx,
        .tcpip_proto = IP_ICMP6,
 };
+
+/** ICMPv6 echo protocol */
+struct icmp_echo_protocol icmpv6_echo_protocol __icmp_echo_protocol = {
+       .family = AF_INET6,
+       .request = ICMPV6_ECHO_REQUEST,
+       .reply = ICMPV6_ECHO_REPLY,
+       .tcpip_protocol = &icmpv6_protocol,
+       .net_checksum = 1,
+};
index 7956d18b2868d90d20e480fc8609e595f39b2937..438fe9ac51732c71121c6c482a1bd26ea6484064 100644 (file)
@@ -669,5 +669,5 @@ struct settings_applicator ipv4_settings_applicator __settings_applicator = {
        .apply = ipv4_create_routes,
 };
 
-/* Drag in ICMP */
-REQUIRE_OBJECT ( icmp );
+/* Drag in ICMPv4 */
+REQUIRE_OBJECT ( icmpv4 );