iPXE
icmp.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2013 Michael Brown <mbrown@fensystems.co.uk>.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of the
7  * License, or any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 FILE_SECBOOT ( PERMITTED );
26 
27 #include <string.h>
28 #include <byteswap.h>
29 #include <errno.h>
30 #include <ipxe/iobuf.h>
31 #include <ipxe/in.h>
32 #include <ipxe/tcpip.h>
33 #include <ipxe/ping.h>
34 #include <ipxe/crc32.h>
35 #include <ipxe/icmp.h>
36 
37 /** @file
38  *
39  * ICMP protocol
40  *
41  */
42 
43 /**
44  * Identify ICMP echo protocol
45  *
46  * @v st_family Address family
47  * @ret echo_protocol ICMP echo protocol, or NULL
48  */
50  struct icmp_echo_protocol *echo_protocol;
51 
52  for_each_table_entry ( echo_protocol, ICMP_ECHO_PROTOCOLS ) {
53  if ( echo_protocol->family == family )
54  return echo_protocol;
55  }
56  return NULL;
57 }
58 
59 /**
60  *
61  * Determine debugging colour for ICMP debug messages
62  *
63  * @v st_peer Peer address
64  * @ret col Debugging colour (for DBGC())
65  */
66 static uint32_t icmpcol ( struct sockaddr_tcpip *st_peer ) {
67 
68  return crc32_le ( 0, st_peer, sizeof ( *st_peer ) );
69 }
70 
71 /**
72  * Transmit ICMP echo packet
73  *
74  * @v iobuf I/O buffer
75  * @v st_dest Destination socket address
76  * @v echo_protocol ICMP echo protocol
77  * @ret rc Return status code
78  */
79 static int icmp_tx_echo ( struct io_buffer *iobuf,
80  struct sockaddr_tcpip *st_dest,
81  struct icmp_echo_protocol *echo_protocol ) {
82  struct icmp_echo *echo = iobuf->data;
83  int rc;
84 
85  /* Set ICMP type and (re)calculate checksum */
86  echo->icmp.chksum = 0;
87  echo->icmp.chksum = tcpip_chksum ( echo, iob_len ( iobuf ) );
88 
89  /* Transmit packet */
90  if ( ( rc = tcpip_tx ( iobuf, echo_protocol->tcpip_protocol, NULL,
91  st_dest, NULL,
92  ( echo_protocol->net_checksum ?
93  &echo->icmp.chksum : NULL ) ) ) != 0 )
94  return rc;
95 
96  return 0;
97 }
98 
99 /**
100  * Transmit ICMP echo request
101  *
102  * @v iobuf I/O buffer
103  * @v st_dest Destination socket address
104  * @ret rc Return status code
105  */
106 int icmp_tx_echo_request ( struct io_buffer *iobuf,
107  struct sockaddr_tcpip *st_dest ) {
108  struct icmp_echo *echo = iobuf->data;
109  struct icmp_echo_protocol *echo_protocol;
110  int rc;
111 
112  /* Identify ICMP echo protocol */
113  echo_protocol = icmp_echo_protocol ( st_dest->st_family );
114  if ( ! echo_protocol ) {
115  DBGC ( icmpcol ( st_dest ), "ICMP TX echo request unknown "
116  "address family %d\n", st_dest->st_family );
117  free_iob ( iobuf );
118  return -ENOTSUP;
119  }
120 
121  /* Set type */
122  echo->icmp.type = echo_protocol->request;
123 
124  /* Transmit request */
125  DBGC ( icmpcol ( st_dest ), "ICMP TX echo request id %04x seq %04x\n",
126  ntohs ( echo->ident ), ntohs ( echo->sequence ) );
127  if ( ( rc = icmp_tx_echo ( iobuf, st_dest, echo_protocol ) ) != 0 )
128  return rc;
129 
130  return 0;
131 }
132 
133 /**
134  * Transmit ICMP echo reply
135  *
136  * @v iobuf I/O buffer
137  * @v st_dest Destination socket address
138  * @ret rc Return status code
139  */
140 static int icmp_tx_echo_reply ( struct io_buffer *iobuf,
141  struct sockaddr_tcpip *st_dest,
142  struct icmp_echo_protocol *echo_protocol ) {
143  struct icmp_echo *echo = iobuf->data;
144  int rc;
145 
146  /* Set type */
147  echo->icmp.type = echo_protocol->reply;
148 
149  /* Transmit reply */
150  DBGC ( icmpcol ( st_dest ), "ICMP TX echo reply id %04x seq %04x\n",
151  ntohs ( echo->ident ), ntohs ( echo->sequence ) );
152  if ( ( rc = icmp_tx_echo ( iobuf, st_dest, echo_protocol ) ) != 0 )
153  return rc;
154 
155  return 0;
156 }
157 
158 /**
159  * Process a received ICMP echo request
160  *
161  * @v iobuf I/O buffer
162  * @v st_src Source socket address
163  * @v echo_protocol ICMP echo protocol
164  * @ret rc Return status code
165  */
166 int icmp_rx_echo_request ( struct io_buffer *iobuf,
167  struct sockaddr_tcpip *st_src,
168  struct icmp_echo_protocol *echo_protocol ) {
169  struct icmp_echo *echo = iobuf->data;
170  int rc;
171 
172  /* Sanity check */
173  if ( iob_len ( iobuf ) < sizeof ( *echo ) ) {
174  DBGC ( icmpcol ( st_src ), "ICMP RX echo request too short at "
175  "%zd bytes (min %zd bytes)\n",
176  iob_len ( iobuf ), sizeof ( *echo ) );
177  free_iob ( iobuf );
178  return -EINVAL;
179  }
180  DBGC ( icmpcol ( st_src ), "ICMP RX echo request id %04x seq %04x\n",
181  ntohs ( echo->ident ), ntohs ( echo->sequence ) );
182 
183  /* Transmit echo reply */
184  if ( ( rc = icmp_tx_echo_reply ( iobuf, st_src, echo_protocol ) ) != 0 )
185  return rc;
186 
187  return 0;
188 }
189 
190 /**
191  * Process a received ICMP echo request
192  *
193  * @v iobuf I/O buffer
194  * @v st_src Source socket address
195  * @ret rc Return status code
196  */
197 int icmp_rx_echo_reply ( struct io_buffer *iobuf,
198  struct sockaddr_tcpip *st_src ) {
199  struct icmp_echo *echo = iobuf->data;
200  int rc;
201 
202  /* Sanity check */
203  if ( iob_len ( iobuf ) < sizeof ( *echo ) ) {
204  DBGC ( icmpcol ( st_src ), "ICMP RX echo reply too short at "
205  "%zd bytes (min %zd bytes)\n",
206  iob_len ( iobuf ), sizeof ( *echo ) );
207  free_iob ( iobuf );
208  return -EINVAL;
209  }
210  DBGC ( icmpcol ( st_src ), "ICMP RX echo reply id %04x seq %04x\n",
211  ntohs ( echo->ident ), ntohs ( echo->sequence ) );
212 
213  /* Deliver to ping protocol */
214  if ( ( rc = ping_rx ( iobuf, st_src ) ) != 0 )
215  return rc;
216 
217  return 0;
218 }
219 
220 /**
221  * Receive ping reply (when no ping protocol is present)
222  *
223  * @v iobuf I/O buffer
224  * @v st_src Source socket address
225  * @ret rc Return status code
226  */
227 __weak int ping_rx ( struct io_buffer *iobuf,
228  struct sockaddr_tcpip *st_src __unused ) {
229  free_iob ( iobuf );
230  return 0;
231 }
ICMP ping protocol.
#define EINVAL
Invalid argument.
Definition: errno.h:429
int net_checksum
Include network-layer checksum within packet.
Definition: icmp.h:52
TCP/IP socket address.
Definition: tcpip.h:76
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
int icmp_tx_echo_request(struct io_buffer *iobuf, struct sockaddr_tcpip *st_dest)
Transmit ICMP echo request.
Definition: icmp.c:106
#define ICMP_ECHO_PROTOCOLS
ICMP echo protocol table.
Definition: icmp.h:56
An ICMP echo request/reply.
Definition: icmp.h:30
Error codes.
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:153
sa_family_t st_family
Socket address family (part of struct sockaddr)
Definition: tcpip.h:78
#define DBGC(...)
Definition: compiler.h:505
#define ntohs(value)
Definition: byteswap.h:137
#define ENOTSUP
Operation not supported.
Definition: errno.h:590
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
u32 crc32_le(u32 seed, const void *data, size_t len)
Calculate 32-bit little-endian CRC checksum.
Definition: crc32.c:40
static int icmp_tx_echo_reply(struct io_buffer *iobuf, struct sockaddr_tcpip *st_dest, struct icmp_echo_protocol *echo_protocol)
Transmit ICMP echo reply.
Definition: icmp.c:140
static struct icmp_echo_protocol * icmp_echo_protocol(sa_family_t family)
Identify ICMP echo protocol.
Definition: icmp.c:49
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
uint16_t sa_family_t
A socket address family.
Definition: socket.h:86
Transport-network layer interface.
struct tcpip_protocol * tcpip_protocol
TCP/IP protocol.
Definition: icmp.h:50
uint8_t request
Request type.
Definition: icmp.h:46
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:160
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:386
unsigned int uint32_t
Definition: stdint.h:12
static int icmp_tx_echo(struct io_buffer *iobuf, struct sockaddr_tcpip *st_dest, struct icmp_echo_protocol *echo_protocol)
Transmit ICMP echo packet.
Definition: icmp.c:79
static uint32_t icmpcol(struct sockaddr_tcpip *st_peer)
Determine debugging colour for ICMP debug messages.
Definition: icmp.c:66
An ICMP echo protocol.
Definition: icmp.h:42
void * data
Start of data.
Definition: iobuf.h:53
__weak int ping_rx(struct io_buffer *iobuf, struct sockaddr_tcpip *st_src __unused)
Receive ping reply (when no ping protocol is present)
Definition: icmp.c:227
ICMP protocol.
#define __weak
Declare a function as weak (use before the definition)
Definition: compiler.h:219
sa_family_t family
Address family.
Definition: icmp.h:44
int icmp_rx_echo_reply(struct io_buffer *iobuf, struct sockaddr_tcpip *st_src)
Process a received ICMP echo request.
Definition: icmp.c:197
int icmp_rx_echo_request(struct io_buffer *iobuf, struct sockaddr_tcpip *st_src, struct icmp_echo_protocol *echo_protocol)
Process a received ICMP echo request.
Definition: icmp.c:166
FILE_SECBOOT(PERMITTED)
uint8_t reply
Reply type.
Definition: icmp.h:48
int tcpip_tx(struct io_buffer *iobuf, struct tcpip_protocol *tcpip_protocol, struct sockaddr_tcpip *st_src, struct sockaddr_tcpip *st_dest, struct net_device *netdev, uint16_t *trans_csum)
Transmit a TCP/IP packet.
Definition: tcpip.c:92
uint16_t tcpip_chksum(const void *data, size_t len)
Calculate TCP/IP checkum.
Definition: tcpip.c:204
#define NULL
NULL pointer (VOID *)
Definition: Base.h:322
String functions.
int echo(void)
Definition: kb.c:133
A persistent I/O buffer.
Definition: iobuf.h:38