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
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_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 */
66static 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 */
79static 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 */
106int 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 */
140static 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 */
166int 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 */
197int 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}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned int uint32_t
Definition stdint.h:12
u32 crc32_le(u32 seed, const void *data, size_t len)
Calculate 32-bit little-endian CRC checksum.
Definition crc32.c:40
Error codes.
#define __unused
Declare a variable or data structure as unused.
Definition compiler.h:573
#define DBGC(...)
Definition compiler.h:505
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define EINVAL
Invalid argument.
Definition errno.h:429
#define ENOTSUP
Operation not supported.
Definition errno.h:590
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
static struct icmp_echo_protocol * icmp_echo_protocol(sa_family_t family)
Identify ICMP echo protocol.
Definition icmp.c:49
int icmp_tx_echo_request(struct io_buffer *iobuf, struct sockaddr_tcpip *st_dest)
Transmit ICMP echo request.
Definition icmp.c:106
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 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
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
static uint32_t icmpcol(struct sockaddr_tcpip *st_peer)
Determine debugging colour for ICMP debug messages.
Definition icmp.c:66
__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
int icmp_rx_echo_reply(struct io_buffer *iobuf, struct sockaddr_tcpip *st_src)
Process a received ICMP echo request.
Definition icmp.c:197
ICMP protocol.
#define ICMP_ECHO_PROTOCOLS
ICMP echo protocol table.
Definition icmp.h:56
#define ntohs(value)
Definition byteswap.h:137
#define __weak
Declare a function as weak (use before the definition)
Definition compiler.h:219
Transport-network layer interface.
String functions.
void free_iob(struct io_buffer *iobuf)
Free I/O buffer.
Definition iobuf.c:153
I/O buffers.
static size_t iob_len(struct io_buffer *iobuf)
Calculate length of data in an I/O buffer.
Definition iobuf.h:160
int echo(void)
Definition kb.c:133
ICMP ping protocol.
uint16_t sa_family_t
A socket address family.
Definition socket.h:86
An ICMP echo protocol.
Definition icmp.h:42
int net_checksum
Include network-layer checksum within packet.
Definition icmp.h:52
uint8_t reply
Reply type.
Definition icmp.h:48
sa_family_t family
Address family.
Definition icmp.h:44
struct tcpip_protocol * tcpip_protocol
TCP/IP protocol.
Definition icmp.h:50
uint8_t request
Request type.
Definition icmp.h:46
An ICMP echo request/reply.
Definition icmp.h:30
A persistent I/O buffer.
Definition iobuf.h:38
void * data
Start of data.
Definition iobuf.h:53
TCP/IP socket address.
Definition tcpip.h:76
sa_family_t st_family
Socket address family (part of struct sockaddr)
Definition tcpip.h:78
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386
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