/* * pcaputil.c * * Copyright (c) 2000 Dug Song * Copyright (c) 2001 Niels Provos * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #include #include #include #include #include #ifdef BSD #include #endif #include #include "pcapu.h" #include "voip.h" struct event pcapev; int filemode; #ifdef BSD static int bpf_immediate(int fd, int on) { return (ioctl(fd, BIOCIMMEDIATE, &on)); } #endif int pcap_dloff(pcap_t *pd) { int offset = -1; switch (pcap_datalink(pd)) { case DLT_EN10MB: offset = 14; break; case DLT_IEEE802: offset = 22; break; case DLT_FDDI: offset = 21; break; #ifdef DLT_LOOP case DLT_LOOP: #endif case DLT_NULL: offset = 4; break; default: warnx("unsupported datalink type"); break; } return (offset); } void pcap_cb(int fd, short event, void *arg) { struct timeval tv; pcap_t *pd = (pcap_t *)arg; u_char *pkt; struct pcap_pkthdr pkthdr; timerclear (&tv); if ((pkt = (u_char *) pcap_next(pd, &pkthdr)) == NULL) { if (filemode) { fprintf(stderr, "%s: ! add\n", __func__); return; } tv.tv_usec = 10 * 1000; /* 10 ms */ goto out; } voip_sniff((u_char *)pd, &pkthdr, pkt); out: timeout_add(&pcapev, &tv); } pcap_t * pcap_init(char *intf, char *file, char *filter, int snaplen) { pcap_t *pd = NULL; u_int net, mask; struct bpf_program fcode; struct timeval tv; char ebuf[PCAP_ERRBUF_SIZE]; /* Cludge */ if (intf == NULL && (intf = pcap_lookupdev(ebuf)) == NULL) { warnx("%s", ebuf); return (NULL); } if (file == NULL) { #ifdef HAVE_CENSOR pd = pcap_open_live(intf, snaplen, 1, 10, ebuf); if (pd != NULL) fprintf(stderr, "Listening on %s: %s\n", intf, filter); filemode = 0; #else errx(1, "Network mode is not supported use -r option"); #endif } else { pd = pcap_open_offline(file, ebuf); filemode = 1; } if (pd == NULL) { warnx("%s", ebuf); return (NULL); } if (pcap_lookupnet(intf, &net, &mask, ebuf) == -1) { warnx("%s", ebuf); return (NULL); } if (pcap_compile(pd, &fcode, filter, 1, mask) < 0) { pcap_perror(pd, "pcap_compile"); return (NULL); } if (pcap_setfilter(pd, &fcode) == -1) { pcap_perror(pd, "pcap_compile"); return (NULL); } #ifdef BSD if (file == NULL && bpf_immediate(pd->fd, 1) < 0) { perror("ioctl"); return (NULL); } #endif timeout_set(&pcapev, pcap_cb, pd); timerclear(&tv); timeout_add(&pcapev, &tv); return (pd); } /* from tcpdump util.c. */ char * copy_argv(char **argv) { char **p, *buf, *src, *dst; u_int len = 0; p = argv; if (*p == 0) return (0); while (*p) len += strlen(*p++) + 1; if ((buf = (char *)malloc(len)) == NULL) err(1, "copy_argv: malloc"); p = argv; dst = buf; while ((src = *p++) != NULL) { while ((*dst++ = *src++) != '\0') ; dst[-1] = ' '; } dst[-1] = '\0'; return (buf); }