Don't do accounting if decode_ip[v6] fails.
[darkstat] / decode.c
1 /* darkstat 3
2 * copyright (c) 2001-2011 Emil Mikulic.
3 *
4 * decode.c: packet decoding.
5 *
6 * Given a captured packet, decode it and fill out a pktsummary struct which
7 * will be sent to the accounting code in acct.c
8 *
9 * You may use, modify and redistribute this file under the terms of the
10 * GNU General Public License version 2. (see COPYING.GPL)
11 */
12
13 #include "cdefs.h"
14 #include "acct.h"
15 #include "cap.h"
16 #include "decode.h"
17 #include "err.h"
18 #include "opt.h"
19
20 #include <sys/ioctl.h>
21 #include <sys/socket.h>
22 #include <assert.h>
23 #include <pcap.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include <arpa/inet.h> /* inet_ntoa() */
27 #include <net/if.h> /* struct ifreq */
28
29 /* need struct ether_header */
30 #ifdef __NetBSD__ /* works for NetBSD 5.1.2 */
31 # include <netinet/if_ether.h>
32 #else
33 # ifdef __OpenBSD__
34 # include <sys/queue.h>
35 # include <net/if_arp.h>
36 # include <netinet/if_ether.h>
37 # else
38 # ifdef __sun
39 # include <sys/ethernet.h>
40 # define ETHER_HDR_LEN 14
41 # else
42 # ifdef _AIX
43 # include <netinet/if_ether.h>
44 # define ETHER_HDR_LEN 14
45 # else
46 # include <net/ethernet.h>
47 # endif
48 # endif
49 # endif
50 #endif
51
52 #ifndef ETHERTYPE_PPPOE
53 # define ETHERTYPE_PPPOE 0x8864
54 #endif
55 #ifndef ETHERTYPE_IPV6
56 # define ETHERTYPE_IPV6 0x86DD
57 #endif
58
59 #include <netinet/in_systm.h> /* n_long */
60 #include <netinet/ip.h> /* struct ip */
61 #include <netinet/ip6.h> /* struct ip6_hdr */
62 #define __FAVOR_BSD
63 #include <netinet/tcp.h> /* struct tcphdr */
64 #include <netinet/udp.h> /* struct udphdr */
65
66 #ifndef IPV6_VERSION
67 #define IPV6_VERSION 0x60
68 #endif
69
70 #ifndef IPV6_VERSION_MASK
71 #define IPV6_VERSION_MASK 0xf0
72 #endif
73
74 static void decode_ether(u_char *, const struct pcap_pkthdr *,
75 const u_char *);
76 static void decode_loop(u_char *, const struct pcap_pkthdr *,
77 const u_char *);
78 static void decode_null(u_char *, const struct pcap_pkthdr *,
79 const u_char *);
80 static void decode_ppp(u_char *, const struct pcap_pkthdr *,
81 const u_char *);
82 static void decode_pppoe(u_char *, const struct pcap_pkthdr *,
83 const u_char *);
84 static void decode_pppoe_real(const u_char *pdata, const uint32_t len,
85 struct pktsummary *sm);
86 #ifdef DLT_LINUX_SLL
87 static void decode_linux_sll(u_char *, const struct pcap_pkthdr *,
88 const u_char *);
89 #endif
90 static void decode_raw(u_char *, const struct pcap_pkthdr *,
91 const u_char *);
92 static int decode_ip(const u_char *pdata, const uint32_t len,
93 struct pktsummary *sm);
94 static int decode_ipv6(const u_char *pdata, const uint32_t len,
95 struct pktsummary *sm);
96
97 /* Link-type header information */
98 static const struct linkhdr linkhdrs[] = {
99 /* linktype hdrlen handler */
100 { DLT_EN10MB, ETHER_HDR_LEN, decode_ether },
101 { DLT_LOOP, NULL_HDR_LEN, decode_loop },
102 { DLT_NULL, NULL_HDR_LEN, decode_null },
103 { DLT_PPP, PPP_HDR_LEN, decode_ppp },
104 #if defined(__NetBSD__)
105 { DLT_PPP_SERIAL, PPP_HDR_LEN, decode_ppp },
106 #endif
107 { DLT_FDDI, FDDI_HDR_LEN, NULL },
108 { DLT_PPP_ETHER, PPPOE_HDR_LEN, decode_pppoe },
109 #ifdef DLT_LINUX_SLL
110 { DLT_LINUX_SLL, SLL_HDR_LEN, decode_linux_sll },
111 #endif
112 { DLT_RAW, RAW_HDR_LEN, decode_raw },
113 { -1, 0, NULL }
114 };
115
116 /*
117 * Returns a pointer to the linkhdr record matching the given linktype, or
118 * NULL if no matching entry found.
119 */
120 const struct linkhdr *
121 getlinkhdr(const int linktype)
122 {
123 size_t i;
124
125 for (i=0; linkhdrs[i].linktype != -1; i++)
126 if (linkhdrs[i].linktype == linktype)
127 return (&(linkhdrs[i]));
128 return (NULL);
129 }
130
131 /*
132 * Returns the minimum snaplen needed to decode everything up to the TCP/UDP
133 * packet headers. The IPv6 header is normative. The argument lh is not
134 * allowed to be NULL.
135 */
136 int
137 getsnaplen(const struct linkhdr *lh)
138 {
139 return (int)(lh->hdrlen + IPV6_HDR_LEN + MAX(TCP_HDR_LEN, UDP_HDR_LEN));
140 }
141
142 /* Decoding functions. */
143 static void
144 decode_ether(u_char *user _unused_,
145 const struct pcap_pkthdr *pheader,
146 const u_char *pdata)
147 {
148 u_short type;
149 const struct ether_header *hdr = (const struct ether_header *)pdata;
150 struct pktsummary sm;
151 memset(&sm, 0, sizeof(sm));
152 sm.time = pheader->ts.tv_sec;
153
154 if (pheader->caplen < ETHER_HDR_LEN) {
155 verbosef("ether: packet too short (%u bytes)", pheader->caplen);
156 return;
157 }
158
159 #ifdef __sun
160 memcpy(sm.src_mac, hdr->ether_shost.ether_addr_octet, sizeof(sm.src_mac));
161 memcpy(sm.dst_mac, hdr->ether_dhost.ether_addr_octet, sizeof(sm.dst_mac));
162 #else
163 memcpy(sm.src_mac, hdr->ether_shost, sizeof(sm.src_mac));
164 memcpy(sm.dst_mac, hdr->ether_dhost, sizeof(sm.dst_mac));
165 #endif
166
167 type = ntohs( hdr->ether_type );
168 switch (type) {
169 case ETHERTYPE_IP:
170 case ETHERTYPE_IPV6:
171 if (!opt_want_pppoe) {
172 if (decode_ip(pdata + ETHER_HDR_LEN,
173 pheader->caplen - ETHER_HDR_LEN, &sm)) {
174 acct_for(&sm);
175 }
176 } else
177 verbosef("ether: discarded IP packet, expecting PPPoE instead");
178 break;
179 case ETHERTYPE_ARP:
180 /* known protocol, don't complain about it. */
181 break;
182 case ETHERTYPE_PPPOE:
183 if (opt_want_pppoe)
184 decode_pppoe_real(pdata + ETHER_HDR_LEN,
185 pheader->caplen - ETHER_HDR_LEN, &sm);
186 else
187 verbosef("ether: got PPPoE frame: maybe you want --pppoe");
188 break;
189 default:
190 verbosef("ether: unknown protocol (0x%04x)", type);
191 }
192 }
193
194 /* Very similar to decode_null, except on OpenBSD we need to think
195 * about family endianness.
196 */
197 static void
198 decode_loop(u_char *user _unused_,
199 const struct pcap_pkthdr *pheader,
200 const u_char *pdata)
201 {
202 uint32_t family;
203 struct pktsummary sm;
204 memset(&sm, 0, sizeof(sm));
205 sm.time = pheader->ts.tv_sec;
206
207 if (pheader->caplen < NULL_HDR_LEN) {
208 verbosef("loop: packet too short (%u bytes)", pheader->caplen);
209 return;
210 }
211 family = *(const uint32_t *)pdata;
212 #ifdef __OpenBSD__
213 family = ntohl(family);
214 #endif
215 if (family == AF_INET) {
216 if (decode_ip(pdata + NULL_HDR_LEN,
217 pheader->caplen - NULL_HDR_LEN, &sm)) {
218 acct_for(&sm);
219 }
220 }
221 else if (family == AF_INET6) {
222 if (decode_ipv6(pdata + NULL_HDR_LEN,
223 pheader->caplen - NULL_HDR_LEN, &sm)) {
224 acct_for(&sm);
225 }
226 }
227 else
228 verbosef("loop: unknown family (%x)", family);
229 }
230
231 static void
232 decode_null(u_char *user _unused_,
233 const struct pcap_pkthdr *pheader,
234 const u_char *pdata)
235 {
236 uint32_t family;
237 struct pktsummary sm;
238 memset(&sm, 0, sizeof(sm));
239 sm.time = pheader->ts.tv_sec;
240
241 if (pheader->caplen < NULL_HDR_LEN) {
242 verbosef("null: packet too short (%u bytes)", pheader->caplen);
243 return;
244 }
245 family = *(const uint32_t *)pdata;
246 if (family == AF_INET) {
247 if (decode_ip(pdata + NULL_HDR_LEN,
248 pheader->caplen - NULL_HDR_LEN, &sm)) {
249 acct_for(&sm);
250 }
251 }
252 else if (family == AF_INET6) {
253 if (decode_ipv6(pdata + NULL_HDR_LEN,
254 pheader->caplen - NULL_HDR_LEN, &sm)) {
255 acct_for(&sm);
256 }
257 }
258 else
259 verbosef("null: unknown family (%x)", family);
260 }
261
262 static void
263 decode_ppp(u_char *user _unused_,
264 const struct pcap_pkthdr *pheader,
265 const u_char *pdata)
266 {
267 struct pktsummary sm;
268 memset(&sm, 0, sizeof(sm));
269 sm.time = pheader->ts.tv_sec;
270
271 if (pheader->caplen < PPPOE_HDR_LEN) {
272 verbosef("ppp: packet too short (%u bytes)", pheader->caplen);
273 return;
274 }
275
276 if (pdata[2] == 0x00 && pdata[3] == 0x21) {
277 if (decode_ip(pdata + PPP_HDR_LEN, pheader->caplen - PPP_HDR_LEN, &sm)) {
278 acct_for(&sm);
279 }
280 } else
281 verbosef("non-IP PPP packet; ignoring.");
282 }
283
284 static void
285 decode_pppoe(u_char *user _unused_,
286 const struct pcap_pkthdr *pheader,
287 const u_char *pdata)
288 {
289 struct pktsummary sm;
290 memset(&sm, 0, sizeof(sm));
291 sm.time = pheader->ts.tv_sec;
292 decode_pppoe_real(pdata, pheader->caplen, &sm);
293 }
294
295 static void
296 decode_pppoe_real(const u_char *pdata, const uint32_t len,
297 struct pktsummary *sm)
298 {
299 if (len < PPPOE_HDR_LEN) {
300 verbosef("pppoe: packet too short (%u bytes)", len);
301 return;
302 }
303
304 if (pdata[1] != 0x00) {
305 verbosef("pppoe: code = 0x%02x, expecting 0; ignoring.", pdata[1]);
306 return;
307 }
308
309 if ((pdata[6] == 0xc0) && (pdata[7] == 0x21)) return; /* LCP */
310 if ((pdata[6] == 0xc0) && (pdata[7] == 0x25)) return; /* LQR */
311
312 if ((pdata[6] == 0x00) && (pdata[7] == 0x21)) {
313 if (decode_ip(pdata + PPPOE_HDR_LEN, len - PPPOE_HDR_LEN, sm)) {
314 acct_for(sm);
315 }
316 } else
317 verbosef("pppoe: non-IP PPPoE packet (0x%02x%02x); ignoring.",
318 pdata[6], pdata[7]);
319 }
320
321 #ifdef DLT_LINUX_SLL
322 /* very similar to decode_ether ... */
323 static void
324 decode_linux_sll(u_char *user _unused_,
325 const struct pcap_pkthdr *pheader,
326 const u_char *pdata)
327 {
328 const struct sll_header {
329 uint16_t packet_type;
330 uint16_t device_type;
331 uint16_t addr_length;
332 #define SLL_MAX_ADDRLEN 8
333 uint8_t addr[SLL_MAX_ADDRLEN];
334 uint16_t ether_type;
335 } *hdr = (const struct sll_header *)pdata;
336 u_short type;
337 struct pktsummary sm;
338 memset(&sm, 0, sizeof(sm));
339 sm.time = pheader->ts.tv_sec;
340
341 if (pheader->caplen < SLL_HDR_LEN) {
342 verbosef("linux_sll: packet too short (%u bytes)", pheader->caplen);
343 return;
344 }
345
346 type = ntohs(hdr->ether_type);
347 switch (type) {
348 case ETHERTYPE_IP:
349 case ETHERTYPE_IPV6:
350 if (decode_ip(pdata + SLL_HDR_LEN, pheader->caplen - SLL_HDR_LEN, &sm)) {
351 acct_for(&sm);
352 }
353 break;
354 case ETHERTYPE_ARP:
355 /* known protocol, don't complain about it. */
356 break;
357 default:
358 verbosef("linux_sll: unknown protocol (%04x)", type);
359 }
360 }
361 #endif
362
363 static void
364 decode_raw(u_char *user _unused_,
365 const struct pcap_pkthdr *pheader,
366 const u_char *pdata)
367 {
368 struct pktsummary sm;
369 memset(&sm, 0, sizeof(sm));
370 sm.time = pheader->ts.tv_sec;
371
372 if (decode_ip(pdata, pheader->caplen, &sm))
373 acct_for(&sm);
374 }
375
376 static void decode_ip_payload(const u_char *pdata, const uint32_t len,
377 struct pktsummary *sm);
378
379 static int
380 decode_ip(const u_char *pdata, const uint32_t len, struct pktsummary *sm)
381 {
382 const struct ip *hdr = (const struct ip *)pdata;
383
384 if (hdr->ip_v == 6) {
385 /* Redirect parsing of IPv6 packets. */
386 return decode_ipv6(pdata, len, sm);
387 }
388 if (len < IP_HDR_LEN) {
389 verbosef("ip: packet too short (%u bytes)", len);
390 return 0;
391 }
392 if (hdr->ip_v != 4) {
393 verbosef("ip: version %d (expecting 4 or 6)", hdr->ip_v);
394 return 0;
395 }
396
397 sm->len = ntohs(hdr->ip_len);
398 sm->proto = hdr->ip_p;
399
400 sm->src.family = IPv4;
401 sm->src.ip.v4 = hdr->ip_src.s_addr;
402
403 sm->dst.family = IPv4;
404 sm->dst.ip.v4 = hdr->ip_dst.s_addr;
405
406 decode_ip_payload(pdata + IP_HDR_LEN, len - IP_HDR_LEN, sm);
407 return 1;
408 }
409
410 static int
411 decode_ipv6(const u_char *pdata, const uint32_t len, struct pktsummary *sm)
412 {
413 const struct ip6_hdr *hdr = (const struct ip6_hdr *)pdata;
414
415 if (len < IPV6_HDR_LEN) {
416 verbosef("ipv6: packet too short (%u bytes)", len);
417 return 0;
418 }
419
420 if ((hdr->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
421 verbosef("ipv6: bad version (%02x, expecting %02x)",
422 hdr->ip6_vfc & IPV6_VERSION_MASK,
423 IPV6_VERSION);
424 return 0;
425 }
426
427 sm->len = ntohs(hdr->ip6_plen) + IPV6_HDR_LEN;
428 sm->proto = hdr->ip6_nxt;
429
430 sm->src.family = IPv6;
431 memcpy(&sm->src.ip.v6, &hdr->ip6_src, sizeof(sm->src.ip.v6));
432
433 sm->dst.family = IPv6;
434 memcpy(&sm->dst.ip.v6, &hdr->ip6_dst, sizeof(sm->dst.ip.v6));
435
436 /* Ignore this packet if it uses extension headers. */
437 switch (sm->proto) {
438 case 0: /* Hop-by-Hop Options */
439 case IPPROTO_NONE:
440 case IPPROTO_DSTOPTS:
441 case IPPROTO_ROUTING:
442 case IPPROTO_FRAGMENT:
443 case IPPROTO_AH:
444 case IPPROTO_ESP:
445 case 135: /* Mobility */
446 sm->proto = IPPROTO_INVALID; /* don't do proto accounting! */
447 return 1; /* but we have addresses, so host accounting is ok */
448
449 default:
450 decode_ip_payload(pdata + IPV6_HDR_LEN, len - IPV6_HDR_LEN, sm);
451 return 1;
452 }
453 }
454
455 static void
456 decode_ip_payload(const u_char *pdata, const uint32_t len,
457 struct pktsummary *sm)
458 {
459 switch (sm->proto) {
460 case IPPROTO_TCP: {
461 const struct tcphdr *thdr = (const struct tcphdr *)pdata;
462 if (len < TCP_HDR_LEN) {
463 verbosef("tcp: packet too short (%u bytes)", len);
464 sm->proto = IPPROTO_INVALID; /* don't do accounting! */
465 return;
466 }
467 sm->src_port = ntohs(thdr->th_sport);
468 sm->dst_port = ntohs(thdr->th_dport);
469 sm->tcp_flags = thdr->th_flags &
470 (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG);
471 break;
472 }
473
474 case IPPROTO_UDP: {
475 const struct udphdr *uhdr = (const struct udphdr *)pdata;
476 if (len < UDP_HDR_LEN) {
477 verbosef("udp: packet too short (%u bytes)", len);
478 sm->proto = IPPROTO_INVALID; /* don't do accounting! */
479 return;
480 }
481 sm->src_port = ntohs(uhdr->uh_sport);
482 sm->dst_port = ntohs(uhdr->uh_dport);
483 break;
484 }
485
486 case IPPROTO_ICMP:
487 case IPPROTO_IGMP:
488 case IPPROTO_ICMPV6:
489 case IPPROTO_OSPF:
490 /* known protocol, don't complain about it */
491 sm->proto = IPPROTO_INVALID; /* also don't do accounting */
492 break;
493
494 default:
495 verbosef("ip_payload: unknown protocol %d", sm->proto);
496 }
497 }
498
499 /* vim:set ts=3 sw=3 tw=78 expandtab: */