1 /* darkstat 3
2  * copyright (c) 2001-2014 Emil Mikulic.
3  *
4  * cap.c: capture packets, and hand them off to decode and acct.
5  *
6  * You may use, modify and redistribute this file under the terms of the
7  * GNU General Public License version 2. (see COPYING.GPL)
8  */
9 
10 #include "acct.h"
11 #include "cdefs.h"
12 #include "cap.h"
13 #include "config.h"
14 #include "conv.h"
15 #include "decode.h"
16 #include "err.h"
17 #include "hosts_db.h"
18 #include "localip.h"
19 #include "now.h"
20 #include "opt.h"
21 #include "queue.h"
22 #include "str.h"
23 
24 #include <sys/ioctl.h>
25 #include <sys/types.h>
26 #include <sys/socket.h>
27 #include <sys/wait.h>
28 #ifdef HAVE_SYS_FILIO_H
29 # include <sys/filio.h> /* Solaris' FIONBIO hides here */
30 #endif
31 #include <assert.h>
32 #include <pcap.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <unistd.h>
37 
38 char *title_interfaces = NULL; /* for html.c */
39 
40 /* The cap process life-cycle:
41  *  - cap_add_ifname() one or more times
42  *  - cap_add_filter() zero or more times
43  *  - cap_start() once to start listening
44  * Once per main loop:
45  *  - cap_fd_set() to update the select() set
46  *  - cap_poll() to read from ready pcap fds
47  * Shutdown:
48  *  - cap_stop()
49  */
50 
51 struct strnode {
52    STAILQ_ENTRY(strnode) entries;
53    const char *str;
54 };
55 
56 struct cap_iface {
57    STAILQ_ENTRY(cap_iface) entries;
58 
59    const char *name;
60    const char *filter;
61    pcap_t *pcap;
62    int fd;
63    const struct linkhdr *linkhdr;
64    struct local_ips local_ips;
65 };
66 
67 static STAILQ_HEAD(cli_ifnames_head, strnode) cli_ifnames =
68    STAILQ_HEAD_INITIALIZER(cli_ifnames);
69 
70 static STAILQ_HEAD(cli_filters_head, strnode) cli_filters =
71    STAILQ_HEAD_INITIALIZER(cli_filters);
72 
73 static STAILQ_HEAD(cap_ifs_head, cap_iface) cap_ifs =
74    STAILQ_HEAD_INITIALIZER(cap_ifs);
75 
76 /* The read timeout passed to pcap_open_live() */
77 #define CAP_TIMEOUT_MSEC 500
78 
cap_add_ifname(const char * ifname)79 void cap_add_ifname(const char *ifname) {
80    struct strnode *n = xmalloc(sizeof(*n));
81    n->str = ifname;
82    STAILQ_INSERT_TAIL(&cli_ifnames, n, entries);
83 }
84 
cap_add_filter(const char * filter)85 void cap_add_filter(const char *filter) {
86    struct strnode *n = xmalloc(sizeof(*n));
87    n->str = filter;
88    STAILQ_INSERT_TAIL(&cli_filters, n, entries);
89 }
90 
cap_set_filter(pcap_t * pcap,const char * filter)91 static void cap_set_filter(pcap_t *pcap, const char *filter) {
92    struct bpf_program prog;
93    char *tmp_filter;
94 
95    if (filter == NULL)
96       return;
97 
98    tmp_filter = xstrdup(filter);
99    if (pcap_compile(
100          pcap,
101          &prog,
102          tmp_filter,
103          1,          /* optimize */
104          0)          /* netmask */
105          == -1)
106       errx(1, "pcap_compile(): %s", pcap_geterr(pcap));
107 
108    if (pcap_setfilter(pcap, &prog) == -1)
109       errx(1, "pcap_setfilter(): %s", pcap_geterr(pcap));
110 
111    pcap_freecode(&prog);
112    free(tmp_filter);
113 }
114 
115 /* Start capturing on just one interface. Called from cap_start(). */
cap_start_one(struct cap_iface * iface,const int promisc)116 static void cap_start_one(struct cap_iface *iface, const int promisc) {
117    char errbuf[PCAP_ERRBUF_SIZE], *tmp_device;
118    int linktype, snaplen, waited;
119 
120    /* pcap wants a non-const interface name string */
121    tmp_device = xstrdup(iface->name);
122    if (iface->filter)
123       verbosef("capturing on interface '%s' with filter '%s'",
124          tmp_device, iface->filter);
125    else
126       verbosef("capturing on interface '%s' with no filter", tmp_device);
127 
128    /* Open packet capture descriptor. */
129    waited = 0;
130    for (;;) {
131       errbuf[0] = '\0'; /* zero length string */
132       iface->pcap = pcap_open_live(
133          tmp_device,
134          1,          /* snaplen, irrelevant at this point */
135          0,          /* promisc, also irrelevant */
136          CAP_TIMEOUT_MSEC,
137          errbuf);
138       if (iface->pcap != NULL)
139          break; /* success! */
140 
141       if ((opt_wait_secs != -1) && strstr(errbuf, "device is not up")) {
142          if ((opt_wait_secs > 0) && (waited >= opt_wait_secs))
143             errx(1, "waited %d secs, giving up: pcap_open_live(): %s",
144                waited, errbuf);
145 
146          verbosef("waited %d secs, interface is not up", waited);
147          sleep(1);
148          waited++;
149       }
150       else errx(1, "pcap_open_live(): %s", errbuf);
151    }
152 
153    /* Work out the linktype and what snaplen we need. */
154    linktype = pcap_datalink(iface->pcap);
155    verbosef("linktype is %d", linktype);
156    if ((linktype == DLT_EN10MB) && opt_want_macs)
157       hosts_db_show_macs = 1;
158    iface->linkhdr = getlinkhdr(linktype);
159    if (iface->linkhdr == NULL)
160       errx(1, "unknown linktype %d", linktype);
161    if (iface->linkhdr->decoder == NULL)
162       errx(1, "no decoder for linktype %d", linktype);
163    snaplen = getsnaplen(iface->linkhdr);
164    if (opt_want_pppoe) {
165       snaplen += PPPOE_HDR_LEN;
166       if (linktype != DLT_EN10MB)
167          errx(1, "can't do PPPoE decoding on a non-Ethernet linktype");
168    }
169    verbosef("calculated snaplen minimum %d", snaplen);
170 #ifdef linux
171    /* FIXME: actually due to libpcap moving to mmap (!!!)
172     * work out which version and fix the way we do capture
173     * on linux:
174     */
175 
176    /* Ubuntu 9.04 has a problem where requesting snaplen <= 60 will
177     * give us 42 bytes, and we need at least 54 for TCP headers.
178     *
179     * Hack to set minimum snaplen to tcpdump's default:
180     */
181    snaplen = MAX(snaplen, 96);
182 #endif
183    if (opt_want_snaplen > -1)
184       snaplen = opt_want_snaplen;
185    verbosef("using snaplen %d", snaplen);
186 
187    /* Close and re-open pcap to use the new snaplen. */
188    pcap_close(iface->pcap);
189    errbuf[0] = '\0'; /* zero length string */
190    iface->pcap = pcap_open_live(
191       tmp_device,
192       snaplen,
193       promisc,
194       CAP_TIMEOUT_MSEC,
195       errbuf);
196 
197    if (iface->pcap == NULL)
198       errx(1, "pcap_open_live(): %s", errbuf);
199 
200    if (errbuf[0] != '\0') /* not zero length anymore -> warning */
201       warnx("pcap_open_live() warning: %s", errbuf);
202 
203    free(tmp_device);
204 
205    if (promisc)
206       verbosef("capturing in promiscuous mode");
207    else
208       verbosef("capturing in non-promiscuous mode");
209 
210    cap_set_filter(iface->pcap, iface->filter);
211    iface->fd = pcap_fileno(iface->pcap);
212 
213    /* set non-blocking */
214 #ifdef linux
215    if (pcap_setnonblock(iface->pcap, 1, errbuf) == -1)
216       errx(1, "pcap_setnonblock(): %s", errbuf);
217 #else
218    {
219       int one = 1;
220       if (ioctl(iface->fd, FIONBIO, &one) == -1)
221          err(1, "ioctl(iface->fd, FIONBIO)");
222    }
223 #endif
224 
225 #ifdef BIOCSETWF
226    {
227       /* Deny all writes to the socket */
228       struct bpf_insn bpf_wfilter[] = { BPF_STMT(BPF_RET+BPF_K, 0) };
229       int wf_len = sizeof(bpf_wfilter) / sizeof(struct bpf_insn);
230       struct bpf_program pr;
231 
232       pr.bf_len = wf_len;
233       pr.bf_insns = bpf_wfilter;
234 
235       if (ioctl(iface->fd, BIOCSETWF, &pr) == -1)
236          err(1, "ioctl(iface->fd, BIOCSETFW)");
237       verbosef("filtered out BPF writes");
238    }
239 #endif
240 
241 #ifdef BIOCLOCK
242    /* set "locked" flag (no reset) */
243    if (ioctl(iface->fd, BIOCLOCK) == -1)
244       err(1, "ioctl(iface->fd, BIOCLOCK)");
245    verbosef("locked down BPF for security");
246 #endif
247 }
248 
cap_start(const int promisc)249 void cap_start(const int promisc) {
250    struct str *ifs = str_make();
251 
252    assert(STAILQ_EMPTY(&cap_ifs));
253    if (STAILQ_EMPTY(&cli_ifnames))
254       errx(1, "no interfaces specified");
255 
256    /* For each ifname */
257    while (!STAILQ_EMPTY(&cli_ifnames)) {
258       struct strnode *ifname, *filter = NULL;
259       struct cap_iface *iface = xmalloc(sizeof(*iface));
260 
261       ifname = STAILQ_FIRST(&cli_ifnames);
262       STAILQ_REMOVE_HEAD(&cli_ifnames, entries);
263 
264       if (!STAILQ_EMPTY(&cli_filters)) {
265          filter = STAILQ_FIRST(&cli_filters);
266          STAILQ_REMOVE_HEAD(&cli_filters, entries);
267       }
268 
269       iface->name = ifname->str;
270       iface->filter = (filter == NULL) ? NULL : filter->str;
271       iface->pcap = NULL;
272       iface->fd = -1;
273       iface->linkhdr = NULL;
274       localip_init(&iface->local_ips);
275       STAILQ_INSERT_TAIL(&cap_ifs, iface, entries);
276       cap_start_one(iface, promisc);
277 
278       free(ifname);
279       if (filter) free(filter);
280 
281       if (str_len(ifs) == 0)
282          str_append(ifs, iface->name);
283       else
284          str_appendf(ifs, ", %s", iface->name);
285    }
286    verbosef("all capture interfaces prepared");
287 
288    /* Deallocate extra filters, if any. */
289    while (!STAILQ_EMPTY(&cli_filters)) {
290       struct strnode *filter = STAILQ_FIRST(&cli_filters);
291 
292       verbosef("ignoring extraneous filter '%s'", filter->str);
293       STAILQ_REMOVE_HEAD(&cli_filters, entries);
294       free(filter);
295    }
296 
297    str_appendn(ifs, "", 1); /* NUL terminate */
298    {
299       size_t _;
300       str_extract(ifs, &_, &title_interfaces);
301    }
302 }
303 
304 #ifdef linux
305 # define _unused_on_linux_ _unused_
306 # define _unused_otherwise_
307 #else
308 # define _unused_on_linux_
309 # define _unused_otherwise_ _unused_
310 #endif
311 
312 /*
313  * Set pcap_fd in the given fd_set.
314  */
cap_fd_set(fd_set * read_set _unused_on_linux_,int * max_fd _unused_on_linux_,struct timeval * timeout _unused_otherwise_,int * need_timeout)315 void cap_fd_set(fd_set *read_set _unused_on_linux_,
316                 int *max_fd _unused_on_linux_,
317                 struct timeval *timeout _unused_otherwise_,
318                 int *need_timeout) {
319    assert(*need_timeout == 0); /* we're first to get a shot at the fd_set */
320 
321 #ifdef linux
322    /*
323     * Linux's BPF is immediate, so don't select() as it will lead to horrible
324     * performance.  Instead, use a timeout for buffering.
325     */
326    *need_timeout = 1;
327    timeout->tv_sec = 0;
328    timeout->tv_usec = CAP_TIMEOUT_MSEC * 1000;
329 #else
330    {
331       struct cap_iface *iface;
332       STAILQ_FOREACH(iface, &cap_ifs, entries) {
333          /* We have a BSD-like BPF, we can select() on it. */
334          FD_SET(iface->fd, read_set);
335          *max_fd = MAX(*max_fd, iface->fd);
336       }
337    }
338 #endif
339 }
340 
341 unsigned int cap_pkts_recv = 0, cap_pkts_drop = 0;
342 
cap_stats_update(void)343 static void cap_stats_update(void) {
344    struct cap_iface *iface;
345 
346    cap_pkts_recv = 0;
347    cap_pkts_drop = 0;
348    STAILQ_FOREACH(iface, &cap_ifs, entries) {
349       struct pcap_stat ps;
350       if (pcap_stats(iface->pcap, &ps) != 0) {
351          warnx("pcap_stats('%s'): %s", iface->name, pcap_geterr(iface->pcap));
352          return;
353       }
354       cap_pkts_recv += ps.ps_recv;
355       cap_pkts_drop += ps.ps_drop;
356    }
357 }
358 
359 /* Print hexdump of received packet to stdout, for debugging. */
hexdump(const u_char * buf,const uint32_t len,const struct linkhdr * linkhdr)360 static void hexdump(const u_char *buf,
361                     const uint32_t len,
362                     const struct linkhdr *linkhdr) {
363    uint32_t i, col;
364 
365    printf("packet of %u bytes:\n", len);
366    for (i=0, col=0; i<len; i++) {
367       if (col == 0) printf(" ");
368       printf("%02x", buf[i]);
369       if (i+1 == linkhdr->hdrlen)
370          printf("|"); /* marks end of link headers (e.g. ethernet) */
371       else
372          printf(" ");
373       col += 3;
374       if (col >= 72) {
375          printf("\n");
376          col = 0;
377       }
378    }
379    if (col != 0) printf("\n");
380    printf("\n");
381 }
382 
383 /* Callback function for pcap_dispatch() which chains to the decoder specified
384  * in the linkhdr struct.
385  */
callback(u_char * user,const struct pcap_pkthdr * pheader,const u_char * pdata)386 static void callback(u_char *user,
387                      const struct pcap_pkthdr *pheader,
388                      const u_char *pdata) {
389    const struct cap_iface * const iface = (struct cap_iface *)user;
390    struct pktsummary sm;
391 
392    if (opt_want_hexdump)
393       hexdump(pdata, pheader->caplen, iface->linkhdr);
394    memset(&sm, 0, sizeof(sm));
395    if (iface->linkhdr->decoder(pheader, pdata, &sm))
396       acct_for(&sm, &iface->local_ips);
397 }
398 
399 /* Process any packets currently in the capture buffer.
400  * Returns 0 on error (usually means the interface went down).
401  */
cap_poll(fd_set * read_set _unused_on_linux_)402 int cap_poll(fd_set *read_set _unused_on_linux_) {
403    struct cap_iface *iface;
404    static int told = 0;
405 
406    STAILQ_FOREACH(iface, &cap_ifs, entries) {
407       /* Once per capture poll, check our IP address.  It's used in accounting
408        * for traffic graphs.
409        */
410       localip_update(iface->name, &iface->local_ips);
411       if (!told && iface->local_ips.num_addrs == 0) {
412          verbosef("interface '%s' has no addresses, "
413                   "your graphs will be blank",
414                   iface->name);
415          verbosef("please read the darkstat manpage, "
416                   "and consider using the -l option");
417          told = 1;
418       }
419 
420       for (;;) {
421          struct timespec t;
422          int ret;
423 
424          timer_start(&t);
425          ret = pcap_dispatch(
426                iface->pcap,
427                -1, /* count = entire buffer */
428                callback,
429                (u_char*)iface); /* user = struct to pass to callback */
430          timer_stop(&t,
431                     2 * CAP_TIMEOUT_MSEC * 1000000,
432                     "pcap_dispatch took too long");
433 
434          if (ret < 0) {
435             warnx("pcap_dispatch('%s'): %s",
436                iface->name, pcap_geterr(iface->pcap));
437             return 0;
438          }
439 
440 #if 0 /* debugging */
441          verbosef("iface '%s' got %d pkts", iface->name, ret);
442 #endif
443 
444 #ifdef linux
445          /* keep looping until we've dispatched all the outstanding packets */
446          if (ret == 0)
447             break;
448 #else
449          /* we get them all on the first shot */
450          break;
451 #endif
452       }
453    }
454    cap_stats_update();
455    return 1;
456 }
457 
cap_stop(void)458 void cap_stop(void) {
459    while (!STAILQ_EMPTY(&cap_ifs)) {
460       struct cap_iface *iface = STAILQ_FIRST(&cap_ifs);
461 
462       STAILQ_REMOVE_HEAD(&cap_ifs, entries);
463       pcap_close(iface->pcap);
464       localip_free(&iface->local_ips);
465       free(iface);
466    }
467    free(title_interfaces);
468    title_interfaces = NULL;
469 }
470 
471 /* This is only needed by the DNS child. In the main process, the deallocation
472  * happens in cap_start().
473  */
cap_free_args(void)474 void cap_free_args(void) {
475    while (!STAILQ_EMPTY(&cli_ifnames)) {
476       struct strnode *ifname = STAILQ_FIRST(&cli_ifnames);
477       STAILQ_REMOVE_HEAD(&cli_ifnames, entries);
478       free(ifname);
479    }
480 
481    while (!STAILQ_EMPTY(&cli_filters)) {
482       struct strnode *filter = STAILQ_FIRST(&cli_filters);
483       STAILQ_REMOVE_HEAD(&cli_filters, entries);
484       free(filter);
485    }
486 }
487 
488 /* Run through entire capfile. */
cap_from_file(const char * capfile)489 void cap_from_file(const char *capfile) {
490    char errbuf[PCAP_ERRBUF_SIZE];
491    int linktype, ret;
492    struct cap_iface iface;
493 
494    iface.name = NULL;
495    iface.filter = NULL;
496    iface.pcap = NULL;
497    iface.fd = -1;
498    iface.linkhdr = NULL;
499    localip_init(&iface.local_ips);
500 
501    /* Process cmdline filters. */
502    if (!STAILQ_EMPTY(&cli_filters))
503       iface.filter = STAILQ_FIRST(&cli_filters)->str;
504    while (!STAILQ_EMPTY(&cli_filters)) {
505       struct strnode *n = STAILQ_FIRST(&cli_filters);
506       STAILQ_REMOVE_HEAD(&cli_filters, entries);
507       free(n);
508    }
509 
510    /* Open packet capture descriptor. */
511    errbuf[0] = '\0'; /* zero length string */
512    iface.pcap = pcap_open_offline(capfile, errbuf);
513 
514    if (iface.pcap == NULL)
515       errx(1, "pcap_open_offline(): %s", errbuf);
516 
517    if (errbuf[0] != '\0') /* not zero length anymore -> warning */
518       warnx("pcap_open_offline() warning: %s", errbuf);
519 
520    /* Work out the linktype. */
521    linktype = pcap_datalink(iface.pcap);
522    iface.linkhdr = getlinkhdr(linktype);
523    if (iface.linkhdr == NULL)
524       errx(1, "unknown linktype %d", linktype);
525    if (iface.linkhdr->decoder == NULL)
526       errx(1, "no decoder for linktype %d", linktype);
527 
528    cap_set_filter(iface.pcap, iface.filter);
529 
530    /* Process file. */
531    ret = pcap_dispatch(
532          iface.pcap,
533          -1,               /* count, -1 = entire buffer */
534          callback,
535          (u_char*)&iface); /* user */
536 
537    if (ret < 0)
538       errx(1, "pcap_dispatch(): %s", pcap_geterr(iface.pcap));
539 
540    localip_free(&iface.local_ips);
541    pcap_close(iface.pcap);
542 }
543 
544 /* vim:set ts=3 sw=3 tw=78 expandtab: */
545