Ignore IPv6 packets with extension headers.
[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 void decode_ip(const u_char *pdata, const uint32_t len,
93 struct pktsummary *sm);
94 static void 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 decode_ip(pdata + ETHER_HDR_LEN,
173 pheader->caplen - ETHER_HDR_LEN, &sm);
174 acct_for(&sm);
175 } else
176 verbosef("ether: discarded IP packet, expecting PPPoE instead");
177 break;
178 case ETHERTYPE_ARP:
179 /* known protocol, don't complain about it. */
180 break;
181 case ETHERTYPE_PPPOE:
182 if (opt_want_pppoe)
183 decode_pppoe_real(pdata + ETHER_HDR_LEN,
184 pheader->caplen - ETHER_HDR_LEN, &sm);
185 else
186 verbosef("ether: got PPPoE frame: maybe you want --pppoe");
187 break;
188 default:
189 verbosef("ether: unknown protocol (0x%04x)", type);
190 }
191 }
192
193 /* Very similar to decode_null, except on OpenBSD we need to think
194 * about family endianness.
195 */
196 static void
197 decode_loop(u_char *user _unused_,
198 const struct pcap_pkthdr *pheader,
199 const u_char *pdata)
200 {
201 uint32_t family;
202 struct pktsummary sm;
203 memset(&sm, 0, sizeof(sm));
204
205 if (pheader->caplen < NULL_HDR_LEN) {
206 verbosef("loop: packet too short (%u bytes)", pheader->caplen);
207 return;
208 }
209 family = *(const uint32_t *)pdata;
210 #ifdef __OpenBSD__
211 family = ntohl(family);
212 #endif
213 if (family == AF_INET) {
214 decode_ip(pdata + NULL_HDR_LEN, pheader->caplen - NULL_HDR_LEN, &sm);
215 sm.time = pheader->ts.tv_sec;
216 acct_for(&sm);
217 }
218 else if (family == AF_INET6) {
219 decode_ipv6(pdata + NULL_HDR_LEN, pheader->caplen - NULL_HDR_LEN, &sm);
220 sm.time = pheader->ts.tv_sec;
221 acct_for(&sm);
222 }
223 else
224 verbosef("loop: unknown family (%x)", family);
225 }
226
227 static void
228 decode_null(u_char *user _unused_,
229 const struct pcap_pkthdr *pheader,
230 const u_char *pdata)
231 {
232 uint32_t family;
233 struct pktsummary sm;
234 memset(&sm, 0, sizeof(sm));
235
236 if (pheader->caplen < NULL_HDR_LEN) {
237 verbosef("null: packet too short (%u bytes)", pheader->caplen);
238 return;
239 }
240 family = *(const uint32_t *)pdata;
241 if (family == AF_INET) {
242 decode_ip(pdata + NULL_HDR_LEN, pheader->caplen - NULL_HDR_LEN, &sm);
243 sm.time = pheader->ts.tv_sec;
244 acct_for(&sm);
245 }
246 else if (family == AF_INET6) {
247 decode_ipv6(pdata + NULL_HDR_LEN, pheader->caplen - NULL_HDR_LEN, &sm);
248 sm.time = pheader->ts.tv_sec;
249 acct_for(&sm);
250 }
251 else
252 verbosef("null: unknown family (%x)", family);
253 }
254
255 static void
256 decode_ppp(u_char *user _unused_,
257 const struct pcap_pkthdr *pheader,
258 const u_char *pdata)
259 {
260 struct pktsummary sm;
261 memset(&sm, 0, sizeof(sm));
262
263 if (pheader->caplen < PPPOE_HDR_LEN) {
264 verbosef("ppp: packet too short (%u bytes)", pheader->caplen);
265 return;
266 }
267
268 if (pdata[2] == 0x00 && pdata[3] == 0x21) {
269 decode_ip(pdata + PPP_HDR_LEN, pheader->caplen - PPP_HDR_LEN, &sm);
270 sm.time = pheader->ts.tv_sec;
271 acct_for(&sm);
272 } else
273 verbosef("non-IP PPP packet; ignoring.");
274 }
275
276 static void
277 decode_pppoe(u_char *user _unused_,
278 const struct pcap_pkthdr *pheader,
279 const u_char *pdata)
280 {
281 struct pktsummary sm;
282 memset(&sm, 0, sizeof(sm));
283 sm.time = pheader->ts.tv_sec;
284 decode_pppoe_real(pdata, pheader->caplen, &sm);
285 }
286
287 static void
288 decode_pppoe_real(const u_char *pdata, const uint32_t len,
289 struct pktsummary *sm)
290 {
291 if (len < PPPOE_HDR_LEN) {
292 verbosef("pppoe: packet too short (%u bytes)", len);
293 return;
294 }
295
296 if (pdata[1] != 0x00) {
297 verbosef("pppoe: code = 0x%02x, expecting 0; ignoring.", pdata[1]);
298 return;
299 }
300
301 if ((pdata[6] == 0xc0) && (pdata[7] == 0x21)) return; /* LCP */
302 if ((pdata[6] == 0xc0) && (pdata[7] == 0x25)) return; /* LQR */
303
304 if ((pdata[6] == 0x00) && (pdata[7] == 0x21)) {
305 decode_ip(pdata + PPPOE_HDR_LEN, len - PPPOE_HDR_LEN, sm);
306 acct_for(sm);
307 } else
308 verbosef("pppoe: non-IP PPPoE packet (0x%02x%02x); ignoring.",
309 pdata[6], pdata[7]);
310 }
311
312 #ifdef DLT_LINUX_SLL
313 /* very similar to decode_ether ... */
314 static void
315 decode_linux_sll(u_char *user _unused_,
316 const struct pcap_pkthdr *pheader,
317 const u_char *pdata)
318 {
319 const struct sll_header {
320 uint16_t packet_type;
321 uint16_t device_type;
322 uint16_t addr_length;
323 #define SLL_MAX_ADDRLEN 8
324 uint8_t addr[SLL_MAX_ADDRLEN];
325 uint16_t ether_type;
326 } *hdr = (const struct sll_header *)pdata;
327 u_short type;
328 struct pktsummary sm;
329 memset(&sm, 0, sizeof(sm));
330
331 if (pheader->caplen < SLL_HDR_LEN) {
332 verbosef("linux_sll: packet too short (%u bytes)", pheader->caplen);
333 return;
334 }
335
336 type = ntohs( hdr->ether_type );
337 switch (type) {
338 case ETHERTYPE_IP:
339 case ETHERTYPE_IPV6:
340 decode_ip(pdata + SLL_HDR_LEN, pheader->caplen - SLL_HDR_LEN, &sm);
341 sm.time = pheader->ts.tv_sec;
342 acct_for(&sm);
343 break;
344 case ETHERTYPE_ARP:
345 /* known protocol, don't complain about it. */
346 break;
347 default:
348 verbosef("linux_sll: unknown protocol (%04x)", type);
349 }
350 }
351 #endif
352
353 static void
354 decode_raw(u_char *user _unused_,
355 const struct pcap_pkthdr *pheader,
356 const u_char *pdata)
357 {
358 struct pktsummary sm;
359 memset(&sm, 0, sizeof(sm));
360
361 decode_ip(pdata, pheader->caplen, &sm);
362 sm.time = pheader->ts.tv_sec;
363 acct_for(&sm);
364 }
365
366 static void decode_ip_payload(const u_char *pdata, const uint32_t len,
367 struct pktsummary *sm);
368
369 static void
370 decode_ip(const u_char *pdata, const uint32_t len, struct pktsummary *sm)
371 {
372 const struct ip *hdr = (const struct ip *)pdata;
373
374 if (hdr->ip_v == 6) {
375 /* Redirect parsing of IPv6 packets. */
376 decode_ipv6(pdata, len, sm);
377 return;
378 }
379 if (len < IP_HDR_LEN) {
380 verbosef("ip: packet too short (%u bytes)", len);
381 return;
382 }
383 if (hdr->ip_v != 4) {
384 verbosef("ip: version %d (expecting 4 or 6)", hdr->ip_v);
385 return;
386 }
387
388 sm->len = ntohs(hdr->ip_len);
389 sm->proto = hdr->ip_p;
390
391 sm->src.family = IPv4;
392 sm->src.ip.v4 = hdr->ip_src.s_addr;
393
394 sm->dst.family = IPv4;
395 sm->dst.ip.v4 = hdr->ip_dst.s_addr;
396
397 decode_ip_payload(pdata + IP_HDR_LEN, len - IP_HDR_LEN, sm);
398 }
399
400 static void
401 decode_ipv6(const u_char *pdata, const uint32_t len, struct pktsummary *sm)
402 {
403 const struct ip6_hdr *hdr = (const struct ip6_hdr *)pdata;
404
405 if (len < IPV6_HDR_LEN) {
406 verbosef("ipv6: packet too short (%u bytes)", len);
407 return;
408 }
409
410 if ((hdr->ip6_vfc & IPV6_VERSION_MASK) != IPV6_VERSION) {
411 verbosef("ipv6: bad version (%02x, expecting %02x)",
412 hdr->ip6_vfc & IPV6_VERSION_MASK,
413 IPV6_VERSION);
414 return;
415 }
416
417 sm->len = ntohs(hdr->ip6_plen) + IPV6_HDR_LEN;
418 sm->proto = hdr->ip6_nxt;
419
420 sm->src.family = IPv6;
421 memcpy(&sm->src.ip.v6, &hdr->ip6_src, sizeof(sm->src.ip.v6));
422
423 sm->dst.family = IPv6;
424 memcpy(&sm->dst.ip.v6, &hdr->ip6_dst, sizeof(sm->dst.ip.v6));
425
426 /* Ignore this packet if it uses extension headers. */
427 switch (sm->proto) {
428 case 0: /* Hop-by-Hop Options */
429 case IPPROTO_NONE:
430 case IPPROTO_DSTOPTS:
431 case IPPROTO_ROUTING:
432 case IPPROTO_FRAGMENT:
433 case IPPROTO_AH:
434 case IPPROTO_ESP:
435 case 135: /* Mobility */
436 sm->proto = IPPROTO_INVALID; /* don't do accounting! */
437 return;
438
439 default:
440 decode_ip_payload(pdata + IPV6_HDR_LEN, len - IPV6_HDR_LEN, sm);
441 }
442 }
443
444 static void
445 decode_ip_payload(const u_char *pdata, const uint32_t len,
446 struct pktsummary *sm)
447 {
448 switch (sm->proto) {
449 case IPPROTO_TCP: {
450 const struct tcphdr *thdr = (const struct tcphdr *)pdata;
451 if (len < TCP_HDR_LEN) {
452 verbosef("tcp: packet too short (%u bytes)", len);
453 sm->proto = IPPROTO_INVALID; /* don't do accounting! */
454 return;
455 }
456 sm->src_port = ntohs(thdr->th_sport);
457 sm->dst_port = ntohs(thdr->th_dport);
458 sm->tcp_flags = thdr->th_flags &
459 (TH_FIN|TH_SYN|TH_RST|TH_PUSH|TH_ACK|TH_URG);
460 break;
461 }
462
463 case IPPROTO_UDP: {
464 const struct udphdr *uhdr = (const struct udphdr *)pdata;
465 if (len < UDP_HDR_LEN) {
466 verbosef("udp: packet too short (%u bytes)", len);
467 sm->proto = IPPROTO_INVALID; /* don't do accounting! */
468 return;
469 }
470 sm->src_port = ntohs(uhdr->uh_sport);
471 sm->dst_port = ntohs(uhdr->uh_dport);
472 break;
473 }
474
475 case IPPROTO_ICMP:
476 case IPPROTO_IGMP:
477 case IPPROTO_ICMPV6:
478 case IPPROTO_OSPF:
479 /* known protocol, don't complain about it */
480 sm->proto = IPPROTO_INVALID; /* also don't do accounting */
481 break;
482
483 default:
484 verbosef("ip: unknown protocol %d", sm->proto);
485 }
486 }
487
488 /* vim:set ts=3 sw=3 tw=78 expandtab: */