summaryrefslogtreecommitdiffstats
path: root/src/net/icmpv4.c
diff options
context:
space:
mode:
authorMichael Brown2013-10-21 15:10:07 +0200
committerMichael Brown2013-10-21 16:08:12 +0200
commit5c2ffc26cc9b73ef60cbd123cd90f499dc01bbc2 (patch)
tree5dc77a8f4b54549e1468ecf93d1cd5cc454f6e60 /src/net/icmpv4.c
parent[resolv] Use sock_aton() to allow parsing of arbitrary numeric addresses (diff)
downloadipxe-5c2ffc26cc9b73ef60cbd123cd90f499dc01bbc2.tar.gz
ipxe-5c2ffc26cc9b73ef60cbd123cd90f499dc01bbc2.tar.xz
ipxe-5c2ffc26cc9b73ef60cbd123cd90f499dc01bbc2.zip
[icmp] Add support for sending ICMP echo requests
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>
Diffstat (limited to 'src/net/icmpv4.c')
-rw-r--r--src/net/icmpv4.c109
1 files changed, 109 insertions, 0 deletions
diff --git a/src/net/icmpv4.c b/src/net/icmpv4.c
new file mode 100644
index 00000000..996ba149
--- /dev/null
+++ b/src/net/icmpv4.c
@@ -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,
+};