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