1 /* 2 * Copyright (c) 1993, 1994, 1995, 1996, 1998 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that: (1) source code distributions 7 * retain the above copyright notice and this paragraph in its entirety, (2) 8 * distributions including binary code include the above copyright notice and 9 * this paragraph in its entirety in the documentation or other materials 10 * provided with the distribution, and (3) all advertising materials mentioning 11 * features or use of this software display the following acknowledgement: 12 * ``This product includes software developed by the University of California, 13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14 * the University nor the names of its contributors may be used to endorse 15 * or promote products derived from this software without specific prior 16 * written permission. 17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20 */ 21 #ifndef lint 22 static const char rcsid[] = 23 "@(#) $Header: /tcpdump/master/libpcap/pcap-bpf.c,v 1.32 1999/10/19 15:18:30 itojun Exp $ (LBL)"; 24 #endif 25 26 #include <sys/param.h> /* optionally get BSD define */ 27 #include <sys/time.h> 28 #include <sys/timeb.h> 29 #include <sys/socket.h> 30 #include <sys/file.h> 31 #include <sys/ioctl.h> 32 33 #include <net/if.h> 34 35 #include <ctype.h> 36 #include <errno.h> 37 #include <netdb.h> 38 #include <stdio.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #include <unistd.h> 42 43 #include "pcap-int.h" 44 45 #include "gnuc.h" 46 #ifdef HAVE_OS_PROTO_H 47 #include "os-proto.h" 48 #endif 49 50 #include "gencode.h" 51 52 int 53 pcap_stats(pcap_t *p, struct pcap_stat *ps) 54 { 55 struct bpf_stat s; 56 57 if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) { 58 sprintf(p->errbuf, "BIOCGSTATS: %s", pcap_strerror(errno)); 59 return (-1); 60 } 61 62 ps->ps_recv = s.bs_recv; 63 ps->ps_drop = s.bs_drop; 64 return (0); 65 } 66 67 int 68 pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 69 { 70 int cc; 71 int n = 0; 72 register u_char *bp, *ep; 73 74 again: 75 cc = p->cc; 76 if (p->cc == 0) { 77 cc = read(p->fd, (char *)p->buffer, p->bufsize); 78 if (cc < 0) { 79 /* Don't choke when we get ptraced */ 80 switch (errno) { 81 82 case EINTR: 83 goto again; 84 85 case EWOULDBLOCK: 86 return (0); 87 #if defined(sun) && !defined(BSD) 88 /* 89 * Due to a SunOS bug, after 2^31 bytes, the kernel 90 * file offset overflows and read fails with EINVAL. 91 * The lseek() to 0 will fix things. 92 */ 93 case EINVAL: 94 if (lseek(p->fd, 0L, SEEK_CUR) + 95 p->bufsize < 0) { 96 (void)lseek(p->fd, 0L, SEEK_SET); 97 goto again; 98 } 99 /* fall through */ 100 #endif 101 } 102 sprintf(p->errbuf, "read: %s", pcap_strerror(errno)); 103 return (-1); 104 } 105 bp = p->buffer; 106 } else 107 bp = p->bp; 108 109 /* 110 * Loop through each packet. 111 */ 112 #define bhp ((struct bpf_hdr *)bp) 113 ep = bp + cc; 114 while (bp < ep) { 115 register int caplen, hdrlen; 116 caplen = bhp->bh_caplen; 117 hdrlen = bhp->bh_hdrlen; 118 /* 119 * XXX A bpf_hdr matches a pcap_pkthdr. 120 */ 121 (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen); 122 bp += BPF_WORDALIGN(caplen + hdrlen); 123 if (++n >= cnt && cnt > 0) { 124 p->bp = bp; 125 p->cc = ep - bp; 126 return (n); 127 } 128 } 129 #undef bhp 130 p->cc = 0; 131 return (n); 132 } 133 134 static inline int 135 bpf_open(pcap_t *p, char *errbuf) 136 { 137 int fd; 138 int n = 0; 139 char device[sizeof "/dev/bpf000"]; 140 141 /* 142 * Go through all the minors and find one that isn't in use. 143 */ 144 do { 145 (void)sprintf(device, "/dev/bpf%d", n++); 146 fd = open(device, O_RDONLY); 147 } while (fd < 0 && errno == EBUSY); 148 149 /* 150 * XXX better message for all minors used 151 */ 152 if (fd < 0) 153 sprintf(errbuf, "%s: %s", device, pcap_strerror(errno)); 154 155 return (fd); 156 } 157 158 pcap_t * 159 pcap_open_live(char *device, int snaplen, int promisc, int to_ms, char *ebuf) 160 { 161 int fd; 162 struct ifreq ifr; 163 struct bpf_version bv; 164 u_int v; 165 pcap_t *p; 166 167 p = (pcap_t *)malloc(sizeof(*p)); 168 if (p == NULL) { 169 sprintf(ebuf, "malloc: %s", pcap_strerror(errno)); 170 return (NULL); 171 } 172 bzero(p, sizeof(*p)); 173 fd = bpf_open(p, ebuf); 174 if (fd < 0) 175 goto bad; 176 177 p->fd = fd; 178 p->snapshot = snaplen; 179 180 if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) { 181 sprintf(ebuf, "BIOCVERSION: %s", pcap_strerror(errno)); 182 goto bad; 183 } 184 if (bv.bv_major != BPF_MAJOR_VERSION || 185 bv.bv_minor < BPF_MINOR_VERSION) { 186 sprintf(ebuf, "kernel bpf filter out of date"); 187 goto bad; 188 } 189 v = 32768; /* XXX this should be a user-accessible hook */ 190 /* Ignore the return value - this is because the call fails on 191 * BPF systems that don't have kernel malloc. And if the call 192 * fails, it's no big deal, we just continue to use the standard 193 * buffer size. 194 */ 195 (void) ioctl(fd, BIOCSBLEN, (caddr_t)&v); 196 197 (void)strncpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 198 if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) { 199 sprintf(ebuf, "%s: %s", device, pcap_strerror(errno)); 200 goto bad; 201 } 202 /* Get the data link layer type. */ 203 if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) { 204 sprintf(ebuf, "BIOCGDLT: %s", pcap_strerror(errno)); 205 goto bad; 206 } 207 #ifdef __OpenBSD__ 208 switch (v) { 209 case DLT_LOOP: 210 v = DLT_NULL; 211 break; 212 } 213 #endif 214 #if _BSDI_VERSION - 0 >= 199510 215 /* The SLIP and PPP link layer header changed in BSD/OS 2.1 */ 216 switch (v) { 217 218 case DLT_SLIP: 219 v = DLT_SLIP_BSDOS; 220 break; 221 222 case DLT_PPP: 223 v = DLT_PPP_BSDOS; 224 break; 225 226 case 11: /*DLT_FR*/ 227 v = DLT_RAW; /*XXX*/ 228 break; 229 230 case 12: /*DLT_C_HDLC*/ 231 v = DLT_CHDLC; 232 break; 233 } 234 #endif 235 p->linktype = v; 236 237 /* set timeout */ 238 if (to_ms != 0) { 239 struct timeval to; 240 to.tv_sec = to_ms / 1000; 241 to.tv_usec = (to_ms * 1000) % 1000000; 242 if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) { 243 sprintf(ebuf, "BIOCSRTIMEOUT: %s", 244 pcap_strerror(errno)); 245 goto bad; 246 } 247 } 248 if (promisc) 249 /* set promiscuous mode, okay if it fails */ 250 (void)ioctl(p->fd, BIOCPROMISC, NULL); 251 252 if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) { 253 sprintf(ebuf, "BIOCGBLEN: %s", pcap_strerror(errno)); 254 goto bad; 255 } 256 p->bufsize = v; 257 p->buffer = (u_char *)malloc(p->bufsize); 258 if (p->buffer == NULL) { 259 sprintf(ebuf, "malloc: %s", pcap_strerror(errno)); 260 goto bad; 261 } 262 263 return (p); 264 bad: 265 (void)close(fd); 266 free(p); 267 return (NULL); 268 } 269 270 int 271 pcap_setfilter(pcap_t *p, struct bpf_program *fp) 272 { 273 /* 274 * It looks that BPF code generated by gen_protochain() is not 275 * compatible with some of kernel BPF code (for example BSD/OS 3.1). 276 * Take a safer side for now. 277 */ 278 if (no_optimize) 279 p->fcode = *fp; 280 else if (p->sf.rfile != NULL) 281 p->fcode = *fp; 282 else if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) { 283 sprintf(p->errbuf, "BIOCSETF: %s", pcap_strerror(errno)); 284 return (-1); 285 } 286 return (0); 287 } 288