1 | /* Various definitions required for the linux format. They were moved here, |
---|
2 | * because format_linux.c had a lot of header information before the actual |
---|
3 | * code. The linux headers have been copied into here rather than included to |
---|
4 | * support RT on machines that don't have the linux headers (like a mac for |
---|
5 | * example. |
---|
6 | */ |
---|
7 | |
---|
8 | #ifndef FORMAT_LINUX_COMMON_H |
---|
9 | #define FORMAT_LINUX_COMMON_H |
---|
10 | |
---|
11 | #include "libtrace.h" |
---|
12 | #include "libtrace_int.h" |
---|
13 | |
---|
14 | #ifdef HAVE_NETPACKET_PACKET_H |
---|
15 | |
---|
16 | #include <sys/socket.h> |
---|
17 | #include <netpacket/packet.h> |
---|
18 | #include <net/ethernet.h> |
---|
19 | #include <net/if_arp.h> |
---|
20 | |
---|
21 | #include <net/if.h> |
---|
22 | #include <sys/ioctl.h> |
---|
23 | #include <poll.h> |
---|
24 | #include <sys/mman.h> |
---|
25 | |
---|
26 | #include <fcntl.h> |
---|
27 | |
---|
28 | /* MAX_ORDER is defined in linux/mmzone.h. 11 is default for 3.0 kernels. |
---|
29 | * max_order will be decreased by one if the ring buffer fails to allocate. |
---|
30 | * Used to get the correct sized buffers from the kernel. |
---|
31 | */ |
---|
32 | #define MAX_ORDER 11 |
---|
33 | /* Number of frames in the ring used by both TX and TR rings. More frames |
---|
34 | * hopefully means less packet loss, especially if traffic comes in bursts. |
---|
35 | */ |
---|
36 | #define CONF_RING_FRAMES 0x100 |
---|
37 | |
---|
38 | /* The maximum frames allowed to be waiting in the TX_RING before the kernel is |
---|
39 | * notified to write them out. Make sure this is less than CONF_RING_FRAMES. |
---|
40 | * Performance doesn't seem to increase any more when setting this above 10. |
---|
41 | */ |
---|
42 | #define TX_MAX_QUEUE 10 |
---|
43 | |
---|
44 | #else /* HAVE_NETPACKET_PACKET_H */ |
---|
45 | |
---|
46 | /* Need to know what a sockaddr_ll looks like */ |
---|
47 | struct sockaddr_ll { |
---|
48 | uint16_t sll_family; |
---|
49 | uint16_t sll_protocol; |
---|
50 | int32_t sll_ifindex; |
---|
51 | uint16_t sll_hatype; |
---|
52 | uint8_t sll_pkttype; |
---|
53 | uint8_t sll_halen; |
---|
54 | uint8_t sll_addr[8]; |
---|
55 | }; |
---|
56 | |
---|
57 | /* Packet types. */ |
---|
58 | #define PACKET_HOST 0 /* To us. */ |
---|
59 | #define PACKET_BROADCAST 1 /* To all. */ |
---|
60 | #define PACKET_MULTICAST 2 /* To group. */ |
---|
61 | #define PACKET_OTHERHOST 3 /* To someone else. */ |
---|
62 | #define PACKET_OUTGOING 4 /* Originated by us . */ |
---|
63 | #define PACKET_LOOPBACK 5 |
---|
64 | #define PACKET_FASTROUTE 6 |
---|
65 | |
---|
66 | /* Packet socket options. */ |
---|
67 | |
---|
68 | #define PACKET_ADD_MEMBERSHIP 1 |
---|
69 | #define PACKET_DROP_MEMBERSHIP 2 |
---|
70 | #define PACKET_RECV_OUTPUT 3 |
---|
71 | #define PACKET_RX_RING 5 |
---|
72 | #define PACKET_STATISTICS 6 |
---|
73 | |
---|
74 | #endif /* HAVE_NETPACKET_PACKET_H */ |
---|
75 | |
---|
76 | struct tpacket_stats { |
---|
77 | unsigned int tp_packets; |
---|
78 | unsigned int tp_drops; |
---|
79 | }; |
---|
80 | |
---|
81 | typedef enum { TS_NONE, TS_TIMEVAL, TS_TIMESPEC } timestamptype_t; |
---|
82 | |
---|
83 | /* linux/if_packet.h defines. They are here rather than including the header |
---|
84 | * this means that we can interpret a ring frame on a kernel that doesn't |
---|
85 | * support the format directly. |
---|
86 | */ |
---|
87 | #define PACKET_RX_RING 5 |
---|
88 | #define PACKET_VERSION 10 |
---|
89 | #define PACKET_HDRLEN 11 |
---|
90 | #define PACKET_TX_RING 13 |
---|
91 | #define PACKET_FANOUT 18 |
---|
92 | #define TP_STATUS_USER 0x1 |
---|
93 | #define TP_STATUS_SEND_REQUEST 0x1 |
---|
94 | #define TP_STATUS_AVAILABLE 0x0 |
---|
95 | #define TO_TP_HDR2(x) ((struct tpacket2_hdr *) (x)) |
---|
96 | #define TO_TP_HDR3(x) ((struct tpacket3_hdr *) (x)) |
---|
97 | #define TPACKET_ALIGNMENT 16 |
---|
98 | #define TPACKET_ALIGN(x) (((x)+TPACKET_ALIGNMENT-1)&~(TPACKET_ALIGNMENT-1)) |
---|
99 | #define TPACKET2_HDRLEN (TPACKET_ALIGN(sizeof(struct tpacket2_hdr)) + sizeof(struct sockaddr_ll)) |
---|
100 | #define TPACKET3_HDRLEN (TPACKET_ALIGN(sizeof(struct tpacket3_hdr)) + sizeof(struct sockaddr_ll)) |
---|
101 | |
---|
102 | |
---|
103 | /* Since 3.1 kernel we have packet_fanout support */ |
---|
104 | // schedule to socket by skb's rxhash - the implementation is bi-directional |
---|
105 | #define PACKET_FANOUT_HASH 0 |
---|
106 | // schedule round robin |
---|
107 | #define PACKET_FANOUT_LB 1 |
---|
108 | // schedule to the same socket that received the packet |
---|
109 | #define PACKET_FANOUT_CPU 2 |
---|
110 | // Something to do with fragmented packets and hashing problems !! TODO figure out if this needs to be on |
---|
111 | #define PACKET_FANOUT_FLAG_DEFRAG 0x8000 |
---|
112 | /* Included but unused by libtrace since Linux 3.10 */ |
---|
113 | // if one socket if full roll over to the next |
---|
114 | #define PACKET_FANOUT_ROLLOVER 3 |
---|
115 | // This flag makes any other system roll over |
---|
116 | #define PACKET_FANOUT_FLAG_ROLLOVER 0x1000 |
---|
117 | /* Included but unused by libtrace since Linux 3.12 */ |
---|
118 | // schedule random |
---|
119 | #define PACKET_FANOUT_RND 4 |
---|
120 | |
---|
121 | |
---|
122 | enum tpacket_versions { |
---|
123 | TPACKET_V1, |
---|
124 | TPACKET_V2, |
---|
125 | TPACKET_V3 |
---|
126 | }; |
---|
127 | |
---|
128 | struct tpacket2_hdr { |
---|
129 | /* Frame status - in use by kernel or libtrace etc. */ |
---|
130 | uint32_t tp_status; |
---|
131 | /* Wire length */ |
---|
132 | uint32_t tp_len; |
---|
133 | /* Captured length */ |
---|
134 | uint32_t tp_snaplen; |
---|
135 | /* Offset in bytes from frame start to the mac (link layer) header */ |
---|
136 | uint16_t tp_mac; |
---|
137 | /* Offset in bytes from frame start to the net (network layer) header */ |
---|
138 | uint16_t tp_net; |
---|
139 | /* Timestamp */ |
---|
140 | uint32_t tp_sec; |
---|
141 | uint32_t tp_nsec; |
---|
142 | /* Not used VLAN tag control information */ |
---|
143 | uint16_t tp_vlan_tci; |
---|
144 | uint16_t tp_padding; |
---|
145 | }; |
---|
146 | |
---|
147 | struct tpacket_hdr_variant1 { |
---|
148 | uint32_t tp_rxhash; |
---|
149 | uint32_t tp_vlan_tci; |
---|
150 | }; |
---|
151 | |
---|
152 | struct tpacket3_hdr { |
---|
153 | uint32_t tp_next_offset; |
---|
154 | uint32_t tp_sec; |
---|
155 | uint32_t tp_nsec; |
---|
156 | uint32_t tp_snaplen; |
---|
157 | uint32_t tp_len; |
---|
158 | uint32_t tp_status; |
---|
159 | uint16_t tp_mac; |
---|
160 | uint16_t tp_net; |
---|
161 | /* pkt_hdr variants */ |
---|
162 | union { |
---|
163 | struct tpacket_hdr_variant1 hv1; |
---|
164 | }; |
---|
165 | }; |
---|
166 | |
---|
167 | struct tpacket_req { |
---|
168 | unsigned int tp_block_size; /* Minimal size of contiguous block */ |
---|
169 | unsigned int tp_block_nr; /* Number of blocks */ |
---|
170 | unsigned int tp_frame_size; /* Size of frame */ |
---|
171 | unsigned int tp_frame_nr; /* Total number of frames */ |
---|
172 | }; |
---|
173 | |
---|
174 | #ifndef IF_NAMESIZE |
---|
175 | #define IF_NAMESIZE 16 |
---|
176 | #endif |
---|
177 | |
---|
178 | /* A structure we use to hold statistic counters from the network cards |
---|
179 | * as accessed via the /proc/net/dev |
---|
180 | */ |
---|
181 | struct linux_dev_stats { |
---|
182 | char if_name[IF_NAMESIZE]; |
---|
183 | uint64_t rx_bytes; |
---|
184 | uint64_t rx_packets; |
---|
185 | uint64_t rx_errors; |
---|
186 | uint64_t rx_drops; |
---|
187 | uint64_t rx_fifo; |
---|
188 | uint64_t rx_frame; |
---|
189 | uint64_t rx_compressed; |
---|
190 | uint64_t rx_multicast; |
---|
191 | uint64_t tx_bytes; |
---|
192 | uint64_t tx_packets; |
---|
193 | uint64_t tx_errors; |
---|
194 | uint64_t tx_drops; |
---|
195 | uint64_t tx_fifo; |
---|
196 | uint64_t tx_colls; |
---|
197 | uint64_t tx_carrier; |
---|
198 | uint64_t tx_compressed; |
---|
199 | }; |
---|
200 | |
---|
201 | /* Note that this structure is passed over the wire in rt encapsulation, and |
---|
202 | * thus we need to be careful with data sizes. timeval's and timespec's |
---|
203 | * can also change their size on 32/64 machines. |
---|
204 | */ |
---|
205 | struct linux_format_data_t { |
---|
206 | /* The snap length for the capture */ |
---|
207 | int snaplen; |
---|
208 | /* Flag indicating whether the interface should be placed in |
---|
209 | * promiscuous mode */ |
---|
210 | int promisc; |
---|
211 | /* The timestamp format used by the capture */ |
---|
212 | timestamptype_t timestamptype; |
---|
213 | /* A BPF filter that is applied to every captured packet */ |
---|
214 | libtrace_filter_t *filter; |
---|
215 | /* Statistics for the capture process, e.g. dropped packet counts */ |
---|
216 | struct tpacket_stats stats; |
---|
217 | /* Statistics for the NIC rather than the socket */ |
---|
218 | struct linux_dev_stats dev_stats; |
---|
219 | /* Flag indicating whether the statistics are current or not */ |
---|
220 | int stats_valid; |
---|
221 | /* Used to determine buffer size for the ring buffer */ |
---|
222 | uint32_t max_order; |
---|
223 | /* Used for the parallel case, fanout is the mode */ |
---|
224 | uint16_t fanout_flags; |
---|
225 | /* The group lets Linux know which sockets to group together |
---|
226 | * so we use a random here to try avoid collisions */ |
---|
227 | uint16_t fanout_group; |
---|
228 | /* When running in parallel mode this is malloc'd with an array |
---|
229 | * file descriptors from packet fanout will use, here we assume/hope |
---|
230 | * that every ring can get setup the same */ |
---|
231 | libtrace_list_t *per_stream; |
---|
232 | }; |
---|
233 | |
---|
234 | struct linux_format_data_out_t { |
---|
235 | /* The file descriptor used to write the packets */ |
---|
236 | int fd; |
---|
237 | /* The tx ring mmap location */ |
---|
238 | char * tx_ring; |
---|
239 | /* The current frame number within the tx ring */ |
---|
240 | int txring_offset; |
---|
241 | /* The current ring buffer layout */ |
---|
242 | struct tpacket_req req; |
---|
243 | /* Our sockaddr structure, here so we can cache the interface number */ |
---|
244 | struct sockaddr_ll sock_hdr; |
---|
245 | /* The (maximum) number of packets that haven't been written */ |
---|
246 | int queue; |
---|
247 | /* The format this trace is using linuxring or linuxnative */ |
---|
248 | libtrace_rt_types_t format; |
---|
249 | /* Used to determine buffer size for the ring buffer */ |
---|
250 | uint32_t max_order; |
---|
251 | }; |
---|
252 | |
---|
253 | struct linux_per_stream_t { |
---|
254 | /* File descriptor for the memory mapped stream */ |
---|
255 | int fd; |
---|
256 | /* Memory mapped buffer */ |
---|
257 | char *rx_ring; |
---|
258 | /* Offset within the mapped buffer */ |
---|
259 | int rxring_offset; |
---|
260 | /* The ring buffer layout */ |
---|
261 | struct tpacket_req req; |
---|
262 | } ALIGN_STRUCT(CACHE_LINE_SIZE); |
---|
263 | |
---|
264 | #define ZERO_LINUX_STREAM {-1, MAP_FAILED, 0, {0}} |
---|
265 | |
---|
266 | |
---|
267 | /* Format header for encapsulating packets captured using linux native */ |
---|
268 | struct libtrace_linuxnative_header { |
---|
269 | /* Timestamp of the packet, as a timeval */ |
---|
270 | struct { |
---|
271 | uint32_t tv_sec; |
---|
272 | uint32_t tv_usec; |
---|
273 | } tv; |
---|
274 | /* Timestamp of the packet, as a timespec */ |
---|
275 | struct { |
---|
276 | uint32_t tv_sec; |
---|
277 | uint32_t tv_nsec; |
---|
278 | } ts; |
---|
279 | /* The timestamp format used by the process that captured this packet */ |
---|
280 | uint8_t timestamptype; |
---|
281 | /* Wire length */ |
---|
282 | uint32_t wirelen; |
---|
283 | /* Capture length */ |
---|
284 | uint32_t caplen; |
---|
285 | /* The linux native header itself */ |
---|
286 | struct sockaddr_ll hdr; |
---|
287 | }; |
---|
288 | |
---|
289 | /* Helper macros to make addressing data in the above structures easier */ |
---|
290 | #define DATA(x) ((struct linux_format_data_t *)x->format_data) |
---|
291 | #define DATA_OUT(x) ((struct linux_format_data_out_t *)x->format_data) |
---|
292 | #define STREAM_DATA(x) ((struct linux_per_stream_t *)x->data) |
---|
293 | |
---|
294 | #define FORMAT_DATA DATA(libtrace) |
---|
295 | #define FORMAT_DATA_OUT DATA_OUT(libtrace) |
---|
296 | |
---|
297 | #define FORMAT_DATA_HEAD FORMAT_DATA->per_stream->head |
---|
298 | #define FORMAT_DATA_FIRST ((struct linux_per_stream_t *)FORMAT_DATA_HEAD->data) |
---|
299 | |
---|
300 | /* Get the sockaddr_ll structure from a frame */ |
---|
301 | #define GET_SOCKADDR_HDR(x) ((struct sockaddr_ll *) (((char *) (x))\ |
---|
302 | + TPACKET_ALIGN(sizeof(struct tpacket2_hdr)))) |
---|
303 | |
---|
304 | /* Common functions */ |
---|
305 | #ifdef HAVE_NETPACKET_PACKET_H |
---|
306 | int linuxcommon_init_input(libtrace_t *libtrace); |
---|
307 | int linuxcommon_init_output(libtrace_out_t *libtrace); |
---|
308 | int linuxcommon_probe_filename(const char *filename); |
---|
309 | int linuxcommon_config_input(libtrace_t *libtrace, trace_option_t option, |
---|
310 | void *data); |
---|
311 | void linuxcommon_close_input_stream(libtrace_t *libtrace, |
---|
312 | struct linux_per_stream_t *stream); |
---|
313 | int linuxcommon_start_input_stream(libtrace_t *libtrace, |
---|
314 | struct linux_per_stream_t *stream); |
---|
315 | int linuxcommon_pause_input(libtrace_t *libtrace); |
---|
316 | int linuxcommon_get_fd(const libtrace_t *libtrace); |
---|
317 | int linuxcommon_fin_input(libtrace_t *libtrace); |
---|
318 | int linuxcommon_pregister_thread(libtrace_t *libtrace, |
---|
319 | libtrace_thread_t *t, |
---|
320 | bool reading); |
---|
321 | int linuxcommon_pstart_input(libtrace_t *libtrace, |
---|
322 | int (*start_stream)(libtrace_t *, struct linux_per_stream_t*)); |
---|
323 | #endif /* HAVE_NETPACKET_PACKET_H */ |
---|
324 | |
---|
325 | void linuxcommon_get_statistics(libtrace_t *libtrace, libtrace_stat_t *stat); |
---|
326 | |
---|
327 | static inline libtrace_direction_t linuxcommon_get_direction(uint8_t pkttype) |
---|
328 | { |
---|
329 | switch (pkttype) { |
---|
330 | case PACKET_OUTGOING: |
---|
331 | case PACKET_LOOPBACK: |
---|
332 | return TRACE_DIR_OUTGOING; |
---|
333 | case PACKET_OTHERHOST: |
---|
334 | return TRACE_DIR_OTHER; |
---|
335 | default: |
---|
336 | return TRACE_DIR_INCOMING; |
---|
337 | } |
---|
338 | } |
---|
339 | |
---|
340 | static inline libtrace_direction_t |
---|
341 | linuxcommon_set_direction(struct sockaddr_ll * skadr, |
---|
342 | libtrace_direction_t direction) |
---|
343 | { |
---|
344 | switch (direction) { |
---|
345 | case TRACE_DIR_OUTGOING: |
---|
346 | skadr->sll_pkttype = PACKET_OUTGOING; |
---|
347 | return TRACE_DIR_OUTGOING; |
---|
348 | case TRACE_DIR_INCOMING: |
---|
349 | skadr->sll_pkttype = PACKET_HOST; |
---|
350 | return TRACE_DIR_INCOMING; |
---|
351 | case TRACE_DIR_OTHER: |
---|
352 | skadr->sll_pkttype = PACKET_OTHERHOST; |
---|
353 | return TRACE_DIR_OTHER; |
---|
354 | default: |
---|
355 | return -1; |
---|
356 | } |
---|
357 | } |
---|
358 | |
---|
359 | static inline libtrace_linktype_t linuxcommon_get_link_type(uint16_t linktype) |
---|
360 | { |
---|
361 | /* Convert the ARPHRD type into an appropriate libtrace link type */ |
---|
362 | switch (linktype) { |
---|
363 | case LIBTRACE_ARPHRD_ETHER: |
---|
364 | case LIBTRACE_ARPHRD_LOOPBACK: |
---|
365 | return TRACE_TYPE_ETH; |
---|
366 | case LIBTRACE_ARPHRD_PPP: |
---|
367 | return TRACE_TYPE_NONE; |
---|
368 | case LIBTRACE_ARPHRD_IEEE80211_RADIOTAP: |
---|
369 | return TRACE_TYPE_80211_RADIO; |
---|
370 | case LIBTRACE_ARPHRD_IEEE80211: |
---|
371 | return TRACE_TYPE_80211; |
---|
372 | case LIBTRACE_ARPHRD_SIT: |
---|
373 | case LIBTRACE_ARPHRD_NONE: |
---|
374 | return TRACE_TYPE_NONE; |
---|
375 | default: /* shrug, beyond me! */ |
---|
376 | printf("unknown Linux ARPHRD type 0x%04x\n",linktype); |
---|
377 | return (libtrace_linktype_t)~0U; |
---|
378 | } |
---|
379 | } |
---|
380 | |
---|
381 | #ifdef HAVE_NETPACKET_PACKET_H |
---|
382 | /** |
---|
383 | * Converts a socket, either packet_mmap or standard raw socket into a |
---|
384 | * fanout socket. |
---|
385 | * NOTE: This means we can read from the socket with multiple queues, |
---|
386 | * each must be setup (identically) and then this called upon them |
---|
387 | * |
---|
388 | * @return 0 success, -1 error |
---|
389 | */ |
---|
390 | static inline int linuxcommon_to_packet_fanout(libtrace_t *libtrace, |
---|
391 | struct linux_per_stream_t *stream) |
---|
392 | { |
---|
393 | int fanout_opt = ((int)FORMAT_DATA->fanout_flags << 16) | |
---|
394 | (int)FORMAT_DATA->fanout_group; |
---|
395 | if (setsockopt(stream->fd, SOL_PACKET, PACKET_FANOUT, |
---|
396 | &fanout_opt, sizeof(fanout_opt)) == -1) { |
---|
397 | trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, |
---|
398 | "Converting the fd to a socket fanout failed %s", |
---|
399 | libtrace->uridata); |
---|
400 | return -1; |
---|
401 | } |
---|
402 | return 0; |
---|
403 | } |
---|
404 | #endif /* HAVE_NETPACKET_PACKET_H */ |
---|
405 | |
---|
406 | |
---|
407 | #endif /* FORMAT_LINUX_COMMON_H */ |
---|