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