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 
26 #include <string.h>
27 #include <byteswap.h>
28 #include <errno.h>
29 #include <ipxe/iobuf.h>
30 #include <ipxe/in.h>
31 #include <ipxe/tcpip.h>
32 #include <ipxe/ping.h>
33 #include <ipxe/crc32.h>
34 #include <ipxe/icmp.h>
35 
36 /** @file
37  *
38  * ICMP protocol
39  *
40  */
41 
42 /**
43  * Identify ICMP echo protocol
44  *
45  * @v st_family Address family
46  * @ret echo_protocol ICMP echo protocol, or NULL
47  */
49  struct icmp_echo_protocol *echo_protocol;
50 
51  for_each_table_entry ( echo_protocol, ICMP_ECHO_PROTOCOLS ) {
52  if ( echo_protocol->family == family )
53  return echo_protocol;
54  }
55  return NULL;
56 }
57 
58 /**
59  *
60  * Determine debugging colour for ICMP debug messages
61  *
62  * @v st_peer Peer address
63  * @ret col Debugging colour (for DBGC())
64  */
65 static uint32_t icmpcol ( struct sockaddr_tcpip *st_peer ) {
66 
67  return crc32_le ( 0, st_peer, sizeof ( *st_peer ) );
68 }
69 
70 /**
71  * Transmit ICMP echo packet
72  *
73  * @v iobuf I/O buffer
74  * @v st_dest Destination socket address
75  * @v echo_protocol ICMP echo protocol
76  * @ret rc Return status code
77  */
78 static int icmp_tx_echo ( struct io_buffer *iobuf,
79  struct sockaddr_tcpip *st_dest,
80  struct icmp_echo_protocol *echo_protocol ) {
81  struct icmp_echo *echo = iobuf->data;
82  int rc;
83 
84  /* Set ICMP type and (re)calculate checksum */
85  echo->icmp.chksum = 0;
86  echo->icmp.chksum = tcpip_chksum ( echo, iob_len ( iobuf ) );
87 
88  /* Transmit packet */
89  if ( ( rc = tcpip_tx ( iobuf, echo_protocol->tcpip_protocol, NULL,
90  st_dest, NULL,
91  ( echo_protocol->net_checksum ?
92  &echo->icmp.chksum : NULL ) ) ) != 0 )
93  return rc;
94 
95  return 0;
96 }
97 
98 /**
99  * Transmit ICMP echo request
100  *
101  * @v iobuf I/O buffer
102  * @v st_dest Destination socket address
103  * @ret rc Return status code
104  */
105 int icmp_tx_echo_request ( struct io_buffer *iobuf,
106  struct sockaddr_tcpip *st_dest ) {
107  struct icmp_echo *echo = iobuf->data;
108  struct icmp_echo_protocol *echo_protocol;
109  int rc;
110 
111  /* Identify ICMP echo protocol */
112  echo_protocol = icmp_echo_protocol ( st_dest->st_family );
113  if ( ! echo_protocol ) {
114  DBGC ( icmpcol ( st_dest ), "ICMP TX echo request unknown "
115  "address family %d\n", st_dest->st_family );
116  free_iob ( iobuf );
117  return -ENOTSUP;
118  }
119 
120  /* Set type */
121  echo->icmp.type = echo_protocol->request;
122 
123  /* Transmit request */
124  DBGC ( icmpcol ( st_dest ), "ICMP TX echo request id %04x seq %04x\n",
125  ntohs ( echo->ident ), ntohs ( echo->sequence ) );
126  if ( ( rc = icmp_tx_echo ( iobuf, st_dest, echo_protocol ) ) != 0 )
127  return rc;
128 
129  return 0;
130 }
131 
132 /**
133  * Transmit ICMP echo reply
134  *
135  * @v iobuf I/O buffer
136  * @v st_dest Destination socket address
137  * @ret rc Return status code
138  */
139 static int icmp_tx_echo_reply ( struct io_buffer *iobuf,
140  struct sockaddr_tcpip *st_dest,
141  struct icmp_echo_protocol *echo_protocol ) {
142  struct icmp_echo *echo = iobuf->data;
143  int rc;
144 
145  /* Set type */
146  echo->icmp.type = echo_protocol->reply;
147 
148  /* Transmit reply */
149  DBGC ( icmpcol ( st_dest ), "ICMP TX echo reply id %04x seq %04x\n",
150  ntohs ( echo->ident ), ntohs ( echo->sequence ) );
151  if ( ( rc = icmp_tx_echo ( iobuf, st_dest, echo_protocol ) ) != 0 )
152  return rc;
153 
154  return 0;
155 }
156 
157 /**
158  * Process a received ICMP echo request
159  *
160  * @v iobuf I/O buffer
161  * @v st_src Source socket address
162  * @v echo_protocol ICMP echo protocol
163  * @ret rc Return status code
164  */
165 int icmp_rx_echo_request ( struct io_buffer *iobuf,
166  struct sockaddr_tcpip *st_src,
167  struct icmp_echo_protocol *echo_protocol ) {
168  struct icmp_echo *echo = iobuf->data;
169  int rc;
170 
171  /* Sanity check */
172  if ( iob_len ( iobuf ) < sizeof ( *echo ) ) {
173  DBGC ( icmpcol ( st_src ), "ICMP RX echo request too short at "
174  "%zd bytes (min %zd bytes)\n",
175  iob_len ( iobuf ), sizeof ( *echo ) );
176  free_iob ( iobuf );
177  return -EINVAL;
178  }
179  DBGC ( icmpcol ( st_src ), "ICMP RX echo request id %04x seq %04x\n",
180  ntohs ( echo->ident ), ntohs ( echo->sequence ) );
181 
182  /* Transmit echo reply */
183  if ( ( rc = icmp_tx_echo_reply ( iobuf, st_src, echo_protocol ) ) != 0 )
184  return rc;
185 
186  return 0;
187 }
188 
189 /**
190  * Process a received ICMP echo request
191  *
192  * @v iobuf I/O buffer
193  * @v st_src Source socket address
194  * @ret rc Return status code
195  */
196 int icmp_rx_echo_reply ( struct io_buffer *iobuf,
197  struct sockaddr_tcpip *st_src ) {
198  struct icmp_echo *echo = iobuf->data;
199  int rc;
200 
201  /* Sanity check */
202  if ( iob_len ( iobuf ) < sizeof ( *echo ) ) {
203  DBGC ( icmpcol ( st_src ), "ICMP RX echo reply too short at "
204  "%zd bytes (min %zd bytes)\n",
205  iob_len ( iobuf ), sizeof ( *echo ) );
206  free_iob ( iobuf );
207  return -EINVAL;
208  }
209  DBGC ( icmpcol ( st_src ), "ICMP RX echo reply id %04x seq %04x\n",
210  ntohs ( echo->ident ), ntohs ( echo->sequence ) );
211 
212  /* Deliver to ping protocol */
213  if ( ( rc = ping_rx ( iobuf, st_src ) ) != 0 )
214  return rc;
215 
216  return 0;
217 }
218 
219 /**
220  * Receive ping reply (when no ping protocol is present)
221  *
222  * @v iobuf I/O buffer
223  * @v st_src Source socket address
224  * @ret rc Return status code
225  */
226 __weak int ping_rx ( struct io_buffer *iobuf,
227  struct sockaddr_tcpip *st_src __unused ) {
228  free_iob ( iobuf );
229  return 0;
230 }
ICMP ping protocol.
#define EINVAL
Invalid argument.
Definition: errno.h:428
int net_checksum
Include network-layer checksum within packet.
Definition: icmp.h:51
TCP/IP socket address.
Definition: tcpip.h:75
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:105
#define ICMP_ECHO_PROTOCOLS
ICMP echo protocol table.
Definition: icmp.h:55
An ICMP echo request/reply.
Definition: icmp.h:29
Error codes.
I/O buffers.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition: iobuf.c:145
sa_family_t st_family
Socket address family (part of struct sockaddr)
Definition: tcpip.h:77
#define DBGC(...)
Definition: compiler.h:505
#define ntohs(value)
Definition: byteswap.h:136
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
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:39
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:139
static struct icmp_echo_protocol * icmp_echo_protocol(sa_family_t family)
Identify ICMP echo protocol.
Definition: icmp.c:48
uint16_t sa_family_t
A socket address family.
Definition: socket.h:85
Transport-network layer interface.
struct tcpip_protocol * tcpip_protocol
TCP/IP protocol.
Definition: icmp.h:49
uint8_t request
Request type.
Definition: icmp.h:45
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition: iobuf.h:151
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition: tables.h:358
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:78
static uint32_t icmpcol(struct sockaddr_tcpip *st_peer)
Determine debugging colour for ICMP debug messages.
Definition: icmp.c:65
#define __unused
Declare a variable or data structure as unused.
Definition: compiler.h:573
An ICMP echo protocol.
Definition: icmp.h:41
void * data
Start of data.
Definition: iobuf.h:44
__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:226
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:43
int icmp_rx_echo_reply(struct io_buffer *iobuf, struct sockaddr_tcpip *st_src)
Process a received ICMP echo request.
Definition: icmp.c:196
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:165
uint8_t reply
Reply type.
Definition: icmp.h:47
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:91
uint16_t tcpip_chksum(const void *data, size_t len)
Calculate TCP/IP checkum.
Definition: tcpip.c:203
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
String functions.
int echo(void)
Definition: kb.c:133
A persistent I/O buffer.
Definition: iobuf.h:32