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