Line data Source code
1 1 : /** @file
2 : * @brief Network packet capture definitions
3 : *
4 : * Definitions for capturing network packets.
5 : */
6 :
7 : /*
8 : * Copyright (c) 2021 Intel Corporation
9 : *
10 : * SPDX-License-Identifier: Apache-2.0
11 : */
12 :
13 : #ifndef ZEPHYR_INCLUDE_NET_CAPTURE_H_
14 : #define ZEPHYR_INCLUDE_NET_CAPTURE_H_
15 :
16 : #include <zephyr/kernel.h>
17 : #include <zephyr/device.h>
18 :
19 : #ifdef __cplusplus
20 : extern "C" {
21 : #endif
22 :
23 : /**
24 : * @brief Network packet capture support functions
25 : * @defgroup net_capture Network packet capture
26 : * @since 2.6
27 : * @version 0.8.0
28 : * @ingroup networking
29 : * @{
30 : */
31 :
32 : /** @cond INTERNAL_HIDDEN */
33 :
34 : struct net_if;
35 : struct net_pkt;
36 : struct device;
37 :
38 : struct net_capture_interface_api {
39 : /** Cleanup the setup. This will also disable capturing. After this
40 : * call, the setup function can be called again.
41 : */
42 : int (*cleanup)(const struct device *dev);
43 :
44 : /** Enable / start capturing data */
45 : int (*enable)(const struct device *dev, struct net_if *iface);
46 :
47 : /** Disable / stop capturing data */
48 : int (*disable)(const struct device *dev);
49 :
50 : /** Is capturing enabled (returns true) or disabled (returns false).
51 : */
52 : bool (*is_enabled)(const struct device *dev);
53 :
54 : /** Send captured data */
55 : int (*send)(const struct device *dev, struct net_if *iface, struct net_pkt *pkt);
56 : };
57 :
58 : /** @endcond */
59 :
60 : /**
61 : * @brief Setup network packet capturing support.
62 : *
63 : * @param remote_addr The value tells the tunnel remote/outer endpoint
64 : * IP address. The IP address can be either IPv4 or IPv6 address.
65 : * This address is used to select the network interface where the tunnel
66 : * is created.
67 : * @param my_local_addr The local/inner IP address of the tunnel. Can contain
68 : * also port number which is used as UDP source port.
69 : * @param peer_addr The peer/inner IP address of the tunnel. Can contain
70 : * also port number which is used as UDP destination port.
71 : * @param dev Network capture device. This is returned to the caller.
72 : *
73 : * @return 0 if ok, <0 if network packet capture setup failed
74 : */
75 1 : int net_capture_setup(const char *remote_addr, const char *my_local_addr, const char *peer_addr,
76 : const struct device **dev);
77 :
78 : /**
79 : * @brief Cleanup network packet capturing support.
80 : *
81 : * @details This should be called after the capturing is done and resources
82 : * can be released.
83 : *
84 : * @param dev Network capture device. User must allocate using the
85 : * net_capture_setup() function.
86 : *
87 : * @return 0 if ok, <0 if network packet capture cleanup failed
88 : */
89 1 : static inline int net_capture_cleanup(const struct device *dev)
90 : {
91 : #if defined(CONFIG_NET_CAPTURE)
92 : const struct net_capture_interface_api *api =
93 : (const struct net_capture_interface_api *)dev->api;
94 :
95 : return api->cleanup(dev);
96 : #else
97 : ARG_UNUSED(dev);
98 :
99 : return -ENOTSUP;
100 : #endif
101 : }
102 :
103 : /**
104 : * @brief Enable network packet capturing support.
105 : *
106 : * @details This creates tunnel network interface where all the
107 : * captured packets are pushed. The captured network packets are
108 : * placed in UDP packets that are sent to tunnel peer.
109 : *
110 : * @param dev Network capture device
111 : * @param iface Network interface we are starting to capture packets.
112 : *
113 : * @return 0 if ok, <0 if network packet capture enable failed
114 : */
115 1 : static inline int net_capture_enable(const struct device *dev, struct net_if *iface)
116 : {
117 : #if defined(CONFIG_NET_CAPTURE)
118 : const struct net_capture_interface_api *api =
119 : (const struct net_capture_interface_api *)dev->api;
120 :
121 : return api->enable(dev, iface);
122 : #else
123 : ARG_UNUSED(dev);
124 : ARG_UNUSED(iface);
125 :
126 : return -ENOTSUP;
127 : #endif
128 : }
129 :
130 : /**
131 : * @brief Is network packet capture enabled or disabled.
132 : *
133 : * @param dev Network capture device. If set to NULL, then the
134 : * default capture device is used.
135 : *
136 : * @return True if enabled, False if network capture is disabled.
137 : */
138 1 : static inline bool net_capture_is_enabled(const struct device *dev)
139 : {
140 : #if defined(CONFIG_NET_CAPTURE)
141 : const struct net_capture_interface_api *api;
142 :
143 : if (dev == NULL) {
144 : /* TODO: Go through all capture devices instead of one */
145 : dev = device_get_binding("NET_CAPTURE0");
146 : if (dev == NULL) {
147 : return false;
148 : }
149 : }
150 :
151 : api = (const struct net_capture_interface_api *)dev->api;
152 :
153 : return api->is_enabled(dev);
154 : #else
155 : ARG_UNUSED(dev);
156 :
157 : return false;
158 : #endif
159 : }
160 :
161 : /**
162 : * @brief Disable network packet capturing support.
163 : *
164 : * @param dev Network capture device
165 : *
166 : * @return 0 if ok, <0 if network packet capture disable failed
167 : */
168 1 : static inline int net_capture_disable(const struct device *dev)
169 : {
170 : #if defined(CONFIG_NET_CAPTURE)
171 : const struct net_capture_interface_api *api =
172 : (const struct net_capture_interface_api *)dev->api;
173 :
174 : return api->disable(dev);
175 : #else
176 : ARG_UNUSED(dev);
177 :
178 : return -ENOTSUP;
179 : #endif
180 : }
181 :
182 : /** @cond INTERNAL_HIDDEN */
183 :
184 : /**
185 : * @brief Send captured packet.
186 : *
187 : * @param dev Network capture device
188 : * @param iface Network interface the packet is being sent
189 : * @param pkt The network packet that is sent
190 : *
191 : * @return 0 if ok, <0 if network packet capture send failed
192 : */
193 : static inline int net_capture_send(const struct device *dev, struct net_if *iface,
194 : struct net_pkt *pkt)
195 : {
196 : #if defined(CONFIG_NET_CAPTURE)
197 : const struct net_capture_interface_api *api =
198 : (const struct net_capture_interface_api *)dev->api;
199 :
200 : return api->send(dev, iface, pkt);
201 : #else
202 : ARG_UNUSED(dev);
203 : ARG_UNUSED(iface);
204 : ARG_UNUSED(pkt);
205 :
206 : return -ENOTSUP;
207 : #endif
208 : }
209 :
210 : /**
211 : * @brief Check if the network packet needs to be captured or not.
212 : * This is called for every network packet being sent.
213 : *
214 : * @param iface Network interface the packet is being sent
215 : * @param pkt The network packet that is sent
216 : */
217 : #if defined(CONFIG_NET_CAPTURE)
218 : void net_capture_pkt(struct net_if *iface, struct net_pkt *pkt);
219 : #else
220 : static inline void net_capture_pkt(struct net_if *iface, struct net_pkt *pkt)
221 : {
222 : ARG_UNUSED(iface);
223 : ARG_UNUSED(pkt);
224 : }
225 : #endif
226 :
227 : /** @cond INTERNAL_HIDDEN */
228 :
229 : /**
230 : * @brief Special variant for net_capture_pkt() which returns the status
231 : * of the send message.
232 : *
233 : * @param iface Network interface the packet is being sent
234 : * @param pkt The network packet that is sent
235 : *
236 : * @return 0 if captured packet was handled ok, <0 if the capture failed
237 : */
238 : #if defined(CONFIG_NET_CAPTURE)
239 : int net_capture_pkt_with_status(struct net_if *iface, struct net_pkt *pkt);
240 : #else
241 : static inline int net_capture_pkt_with_status(struct net_if *iface, struct net_pkt *pkt)
242 : {
243 : ARG_UNUSED(iface);
244 : ARG_UNUSED(pkt);
245 :
246 : return -ENOTSUP;
247 : }
248 : #endif
249 :
250 : /** @endcond */
251 :
252 : /** The type and direction of the captured data. */
253 : enum net_capture_packet_type {
254 : NET_CAPTURE_HOST, /**< Packet was sent to us by somebody else */
255 : NET_CAPTURE_BROADCAST, /**< Packet was broadcast by somebody else */
256 : NET_CAPTURE_MULTICAST, /**< Packet was multicast, but not broadcast, by somebody else */
257 : NET_CAPTURE_OTHERHOST, /**< Packet was sent by somebody else to somebody else */
258 : NET_CAPTURE_OUTGOING, /**< Packet was sent by us */
259 : };
260 :
261 : #define NET_CAPTURE_LL_ADDRLEN 8 /** Maximum length of a link-layer address */
262 :
263 : /** The context information for cooked mode capture */
264 : struct net_capture_cooked {
265 : /** Link-layer address type */
266 : uint16_t hatype;
267 : /** Link-layer address length */
268 : uint16_t halen;
269 : /** Link-layer address */
270 : uint8_t addr[NET_CAPTURE_LL_ADDRLEN];
271 : };
272 :
273 : /**
274 : * @brief Initialize cooked mode capture context.
275 : *
276 : * @param ctx Cooked context struct allocated by user.
277 : * @param hatype Link-layer address type
278 : * @param halen Link-layer address length (maximum is 8 bytes)
279 : * @param addr Link-layer address
280 : *
281 : * @return 0 if ok, <0 if context initialization failed
282 : */
283 : #if defined(CONFIG_NET_CAPTURE_COOKED_MODE)
284 : int net_capture_cooked_setup(struct net_capture_cooked *ctx,
285 : uint16_t hatype,
286 : uint16_t halen,
287 : uint8_t *addr);
288 : #else
289 : static inline int net_capture_cooked_setup(struct net_capture_cooked *ctx,
290 : uint16_t hatype,
291 : uint16_t halen,
292 : uint8_t *addr)
293 : {
294 : ARG_UNUSED(ctx);
295 : ARG_UNUSED(hatype);
296 : ARG_UNUSED(halen);
297 : ARG_UNUSED(addr);
298 :
299 : return -ENOTSUP;
300 : }
301 : #endif
302 :
303 : /**
304 : * @brief Capture arbitrary data from source that does not have an interface.
305 : * This can be used if you do not have a network interface that
306 : * you want to capture from. For example low level modem device
307 : * below PPP containing HDLC frames, CANBUS data or Bluetooth packets etc.
308 : * The data given to this function should only contain full link
309 : * layer packets so that packet boundary is not lost.
310 : *
311 : * @param ctx Cooked mode capture context.
312 : * @param data Data to capture.
313 : * @param len Length of the data.
314 : * @param type The direction and type of the packet (did we sent it etc).
315 : * @param ptype Protocol type id. These are the ETH_P_* types set in ethernet.h
316 : */
317 : #if defined(CONFIG_NET_CAPTURE_COOKED_MODE)
318 : void net_capture_data(struct net_capture_cooked *ctx,
319 : const uint8_t *data, size_t len,
320 : enum net_capture_packet_type type,
321 : uint16_t ptype);
322 : #else
323 : static inline void net_capture_data(struct net_capture_cooked *ctx,
324 : const uint8_t *data, size_t len,
325 : enum net_capture_packet_type type,
326 : uint16_t ptype)
327 : {
328 : ARG_UNUSED(ctx);
329 : ARG_UNUSED(data);
330 : ARG_UNUSED(len);
331 : ARG_UNUSED(type);
332 : ARG_UNUSED(ptype);
333 : }
334 : #endif
335 :
336 : struct net_capture_info {
337 : const struct device *capture_dev;
338 : struct net_if *capture_iface;
339 : struct net_if *tunnel_iface;
340 : struct sockaddr *peer;
341 : struct sockaddr *local;
342 : bool is_enabled;
343 : };
344 :
345 : /**
346 : * @typedef net_capture_cb_t
347 : * @brief Callback used while iterating over capture devices
348 : *
349 : * @param info Information about capture device
350 : * @param user_data A valid pointer to user data or NULL
351 : */
352 : typedef void (*net_capture_cb_t)(struct net_capture_info *info, void *user_data);
353 :
354 : /**
355 : * @brief Go through all the capture devices in order to get
356 : * information about them. This is mainly useful in
357 : * net-shell to print data about currently active
358 : * captures.
359 : *
360 : * @param cb Callback to call for each capture device
361 : * @param user_data User supplied data
362 : */
363 : #if defined(CONFIG_NET_CAPTURE)
364 : void net_capture_foreach(net_capture_cb_t cb, void *user_data);
365 : #else
366 : static inline void net_capture_foreach(net_capture_cb_t cb, void *user_data)
367 : {
368 : ARG_UNUSED(cb);
369 : ARG_UNUSED(user_data);
370 : }
371 : #endif
372 :
373 : /** @endcond */
374 :
375 : /**
376 : * @}
377 : */
378 :
379 : #ifdef __cplusplus
380 : }
381 : #endif
382 :
383 : #endif /* ZEPHYR_INCLUDE_NET_CAPTURE_H_ */
|