1 /*
2  * Copyright (c) 2023 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /** @file icmp.h
8  *
9  * @defgroup icmp Send and receive IPv4 or IPv6 ICMP Echo Request messages.
10  * @ingroup networking
11  * @{
12  * @brief ICMP sending and receiving.
13  */
14 
15 #ifndef ZEPHYR_INCLUDE_NET_ICMP_H_
16 #define ZEPHYR_INCLUDE_NET_ICMP_H_
17 
18 #include <stddef.h>
19 
20 #include <zephyr/kernel.h>
21 #include <zephyr/types.h>
22 #include <zephyr/net/net_ip.h>
23 #include <zephyr/net/net_if.h>
24 #include <zephyr/net/net_pkt.h>
25 
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29 
30 #define NET_ICMPV4_ECHO_REQUEST 8
31 #define NET_ICMPV4_ECHO_REPLY   0
32 #define NET_ICMPV6_ECHO_REQUEST 128
33 #define NET_ICMPV6_ECHO_REPLY   129
34 
35 struct net_icmp_ctx;
36 struct net_icmp_ip_hdr;
37 struct net_icmp_ping_params;
38 
39 /**
40  * @typedef net_icmp_handler_t
41  * @brief Handler function that is called when ICMP response is received.
42  *
43  * @param ctx ICMP context to use.
44  * @param pkt Received ICMP response network packet.
45  * @param ip_hdr IP header of the packet.
46  * @param icmp_hdr ICMP header of the packet.
47  * @param user_data A valid pointer to user data or NULL
48  */
49 typedef int (*net_icmp_handler_t)(struct net_icmp_ctx *ctx,
50 				  struct net_pkt *pkt,
51 				  struct net_icmp_ip_hdr *ip_hdr,
52 				  struct net_icmp_hdr *icmp_hdr,
53 				  void *user_data);
54 
55 /**
56  * @typedef net_icmp_offload_ping_handler_t
57  * @brief Handler function that is called when an Echo-Request is sent
58  *        to offloaded device. This handler is typically setup by the
59  *        device driver so that it can catch the ping request and send
60  *        it to the offloaded device.
61  *
62  * @param ctx ICMP context used in this request.
63  * @param iface Network interface, can be set to NULL in which case the
64  *        interface is selected according to destination address.
65  * @param dst IP address of the target host.
66  * @param params Echo-Request specific parameters. May be NULL in which case
67  *        suitable default parameters are used.
68  * @param user_data User supplied opaque data passed to the handler. May be NULL.
69  *
70  */
71 typedef int (*net_icmp_offload_ping_handler_t)(struct net_icmp_ctx *ctx,
72 					       struct net_if *iface,
73 					       struct sockaddr *dst,
74 					       struct net_icmp_ping_params *params,
75 					       void *user_data);
76 
77 /**
78  * @brief ICMP context structure.
79  */
80 struct net_icmp_ctx {
81 	/** List node */
82 	sys_snode_t node;
83 
84 	/** ICMP response handler */
85 	net_icmp_handler_t handler;
86 
87 	/** Network interface where the ICMP request was sent */
88 	struct net_if *iface;
89 
90 	/** Opaque user supplied data */
91 	void *user_data;
92 
93 	/** ICMP type of the response we are waiting */
94 	uint8_t type;
95 
96 	/** ICMP code of the response type we are waiting */
97 	uint8_t code;
98 };
99 
100 /**
101  * @brief Struct presents either IPv4 or IPv6 header in ICMP response message.
102  */
103 struct net_icmp_ip_hdr {
104 	union {
105 		/** IPv4 header in response message. */
106 		struct net_ipv4_hdr *ipv4;
107 
108 		/** IPv6 header in response message. */
109 		struct net_ipv6_hdr *ipv6;
110 	};
111 
112 	/** Is the header IPv4 or IPv6 one. Value of either AF_INET or AF_INET6 */
113 	sa_family_t family;
114 };
115 
116 /**
117  * @brief Struct presents parameters that are needed when sending
118  *        Echo-Request (ping) messages.
119  */
120 struct net_icmp_ping_params {
121 	/** An identifier to aid in matching Echo Replies to this Echo Request.
122 	 * May be zero.
123 	 */
124 	uint16_t identifier;
125 
126 	/** A sequence number to aid in matching Echo Replies to this
127 	 * Echo Request. May be zero.
128 	 */
129 	uint16_t sequence;
130 
131 	/** Can be either IPv4 Type-of-service field value, or IPv6 Traffic
132 	 * Class field value. Represents combined DSCP and ECN values.
133 	 */
134 	uint8_t tc_tos;
135 
136 	/** Network packet priority. */
137 	int priority;
138 
139 	/* Arbitrary payload data that will be included in the Echo Reply
140 	 * verbatim. May be NULL.
141 	 */
142 	const void *data;
143 
144 	/** Size of the Payload Data in bytes. May be zero. In case data
145 	 * pointer is NULL, the function will generate the payload up to
146 	 * the requested size.
147 	 */
148 	size_t data_size;
149 };
150 
151 /**
152  * @brief Initialize the ICMP context structure. Must be called before
153  *        ICMP messages can be sent. This will register handler to the
154  *        system.
155  *
156  * @param ctx ICMP context used in this request.
157  * @param type Type of ICMP message we are handling.
158  * @param code Code of ICMP message we are handling.
159  * @param handler Callback function that is called when a response is received.
160  */
161 int net_icmp_init_ctx(struct net_icmp_ctx *ctx, uint8_t type, uint8_t code,
162 		      net_icmp_handler_t handler);
163 
164 /**
165  * @brief Cleanup the ICMP context structure. This will unregister the ICMP handler
166  *        from the system.
167  *
168  * @param ctx ICMP context used in this request.
169  */
170 int net_icmp_cleanup_ctx(struct net_icmp_ctx *ctx);
171 
172 /**
173  * @brief Send ICMP echo request message.
174  *
175  * @param ctx ICMP context used in this request.
176  * @param iface Network interface, can be set to NULL in which case the
177  *        interface is selected according to destination address.
178  * @param dst IP address of the target host.
179  * @param params Echo-Request specific parameters. May be NULL in which case
180  *        suitable default parameters are used.
181  * @param user_data User supplied opaque data passed to the handler. May be NULL.
182  *
183  * @return Return 0 if the sending succeed, <0 otherwise.
184  */
185 int net_icmp_send_echo_request(struct net_icmp_ctx *ctx,
186 			       struct net_if *iface,
187 			       struct sockaddr *dst,
188 			       struct net_icmp_ping_params *params,
189 			       void *user_data);
190 
191 /**
192  * @brief ICMP offload context structure.
193  */
194 struct net_icmp_offload {
195 	/** List node */
196 	sys_snode_t node;
197 
198 	/**
199 	 * ICMP response handler. Currently there is only one handler.
200 	 * This means that one offloaded ping request/response can be going
201 	 * on at the same time.
202 	 */
203 	net_icmp_handler_t handler;
204 
205 	/** ICMP offloaded ping handler */
206 	net_icmp_offload_ping_handler_t ping_handler;
207 
208 	/** Offloaded network interface */
209 	struct net_if *iface;
210 };
211 
212 /**
213  * @brief Register a handler function that is called when an Echo-Request
214  *        is sent to the offloaded device. This function is typically
215  *        called by a device driver so that it can do the actual offloaded
216  *        ping call.
217  *
218  * @param ctx ICMP offload context used for this interface.
219  * @param iface Network interface of the offloaded device.
220  * @param ping_handler Function to be called when offloaded ping request is done.
221  *
222  * @return Return 0 if the register succeed, <0 otherwise.
223  */
224 int net_icmp_register_offload_ping(struct net_icmp_offload *ctx,
225 				   struct net_if *iface,
226 				   net_icmp_offload_ping_handler_t ping_handler);
227 
228 /**
229  * @brief Unregister the offload handler.
230  *
231  * @param ctx ICMP offload context used for this interface.
232  *
233  * @return Return 0 if the call succeed, <0 otherwise.
234  */
235 int net_icmp_unregister_offload_ping(struct net_icmp_offload *ctx);
236 
237 /**
238  * @brief Get a ICMP response handler function for an offloaded device.
239  *        When a ping response is received by the driver, it should call
240  *        the handler function with proper parameters so that the ICMP response
241  *        is received by the net stack.
242  *
243  * @param ctx ICMP offload context used in this request.
244  * @param resp_handler Function to be called when offloaded ping response
245  *        is received by the offloaded driver. The ICMP response handler
246  *        function is returned and the caller should call it when appropriate.
247  *
248  * @return Return 0 if the call succeed, <0 otherwise.
249  */
250 int net_icmp_get_offload_rsp_handler(struct net_icmp_offload *ctx,
251 				     net_icmp_handler_t *resp_handler);
252 
253 #ifdef __cplusplus
254 }
255 #endif
256 
257 #endif /* ZEPHYR_INCLUDE_NET_ICMP_H */
258 
259 /**@}  */
260