1 /* $OpenBSD: pcap-bpf.c,v 1.20 2006/03/26 20:58:51 djm 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 24 #include <sys/param.h> /* optionally get BSD define */ 25 #include <sys/time.h> 26 #include <sys/timeb.h> 27 #include <sys/socket.h> 28 #include <sys/ioctl.h> 29 30 #include <net/if.h> 31 32 #include <ctype.h> 33 #include <errno.h> 34 #include <fcntl.h> 35 #include <netdb.h> 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <string.h> 39 #include <unistd.h> 40 41 #include "pcap-int.h" 42 43 #ifdef HAVE_OS_PROTO_H 44 #include "os-proto.h" 45 #endif 46 47 #include "gencode.h" 48 49 int 50 pcap_stats(pcap_t *p, struct pcap_stat *ps) 51 { 52 struct bpf_stat s; 53 54 if (ioctl(p->fd, BIOCGSTATS, (caddr_t)&s) < 0) { 55 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCGSTATS: %s", 56 pcap_strerror(errno)); 57 return (-1); 58 } 59 60 ps->ps_recv = s.bs_recv; 61 ps->ps_drop = s.bs_drop; 62 return (0); 63 } 64 65 int 66 pcap_read(pcap_t *p, int cnt, pcap_handler callback, u_char *user) 67 { 68 int cc; 69 int n = 0; 70 register u_char *bp, *ep; 71 72 again: 73 /* 74 * Has "pcap_breakloop()" been called? 75 */ 76 if (p->break_loop) { 77 /* 78 * Yes - clear the flag that indicates that it 79 * has, and return -2 to indicate that we were 80 * told to break out of the loop. 81 */ 82 p->break_loop = 0; 83 return (-2); 84 } 85 86 cc = p->cc; 87 if (p->cc == 0) { 88 cc = read(p->fd, (char *)p->buffer, p->bufsize); 89 if (cc < 0) { 90 /* Don't choke when we get ptraced */ 91 switch (errno) { 92 93 case EINTR: 94 goto again; 95 96 case EWOULDBLOCK: 97 return (0); 98 #if defined(sun) && !defined(BSD) 99 /* 100 * Due to a SunOS bug, after 2^31 bytes, the kernel 101 * file offset overflows and read fails with EINVAL. 102 * The lseek() to 0 will fix things. 103 */ 104 case EINVAL: 105 if (lseek(p->fd, 0L, SEEK_CUR) + 106 p->bufsize < 0) { 107 (void)lseek(p->fd, 0L, SEEK_SET); 108 goto again; 109 } 110 /* FALLTHROUGH */ 111 #endif 112 } 113 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "read: %s", 114 pcap_strerror(errno)); 115 return (-1); 116 } 117 bp = p->buffer; 118 } else 119 bp = p->bp; 120 121 /* 122 * Loop through each packet. 123 */ 124 #define bhp ((struct bpf_hdr *)bp) 125 ep = bp + cc; 126 while (bp < ep) { 127 register int caplen, hdrlen; 128 129 /* 130 * Has "pcap_breakloop()" been called? 131 * If so, return immediately - if we haven't read any 132 * packets, clear the flag and return -2 to indicate 133 * that we were told to break out of the loop, otherwise 134 * leave the flag set, so that the *next* call will break 135 * out of the loop without having read any packets, and 136 * return the number of packets we've processed so far. 137 */ 138 if (p->break_loop) { 139 if (n == 0) { 140 p->break_loop = 0; 141 return (-2); 142 } else { 143 p->bp = bp; 144 p->cc = ep - bp; 145 return (n); 146 } 147 } 148 149 caplen = bhp->bh_caplen; 150 hdrlen = bhp->bh_hdrlen; 151 /* 152 * XXX A bpf_hdr matches a pcap_pkthdr. 153 */ 154 (*callback)(user, (struct pcap_pkthdr*)bp, bp + hdrlen); 155 bp += BPF_WORDALIGN(caplen + hdrlen); 156 if (++n >= cnt && cnt > 0) { 157 p->bp = bp; 158 p->cc = ep - bp; 159 return (n); 160 } 161 } 162 #undef bhp 163 p->cc = 0; 164 return (n); 165 } 166 167 int 168 pcap_inject(pcap_t *p, const void *buf, size_t len) 169 { 170 return (write(p->fd, buf, len)); 171 } 172 173 int 174 pcap_sendpacket(pcap_t *p, const u_char *buf, int size) 175 { 176 return (pcap_inject(p, buf, size) == -1 ? -1 : 0); 177 } 178 179 /* ARGSUSED */ 180 static __inline int 181 bpf_open(pcap_t *p, char *errbuf) 182 { 183 int fd; 184 int n = 0; 185 char device[sizeof "/dev/bpf0000000000"]; 186 187 /* 188 * Go through all the minors and find one that isn't in use. 189 */ 190 do { 191 (void)snprintf(device, sizeof device, "/dev/bpf%d", n++); 192 fd = open(device, O_RDWR); 193 if (fd < 0 && errno == EACCES) 194 fd = open(device, O_RDONLY); 195 } while (fd < 0 && errno == EBUSY); 196 197 /* 198 * XXX better message for all minors used 199 */ 200 if (fd < 0) 201 snprintf(errbuf, PCAP_ERRBUF_SIZE, "%s: %s", 202 device, pcap_strerror(errno)); 203 204 return (fd); 205 } 206 207 pcap_t * 208 pcap_open_live(const char *device, int snaplen, int promisc, int to_ms, 209 char *ebuf) 210 { 211 int fd; 212 struct ifreq ifr; 213 struct bpf_version bv; 214 u_int v; 215 pcap_t *p; 216 struct bpf_dltlist bdl; 217 218 bzero(&bdl, sizeof(bdl)); 219 p = (pcap_t *)malloc(sizeof(*p)); 220 if (p == NULL) { 221 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", 222 pcap_strerror(errno)); 223 return (NULL); 224 } 225 bzero(p, sizeof(*p)); 226 fd = bpf_open(p, ebuf); 227 if (fd < 0) 228 goto bad; 229 230 p->fd = fd; 231 p->snapshot = snaplen; 232 233 if (ioctl(fd, BIOCVERSION, (caddr_t)&bv) < 0) { 234 snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCVERSION: %s", 235 pcap_strerror(errno)); 236 goto bad; 237 } 238 if (bv.bv_major != BPF_MAJOR_VERSION || 239 bv.bv_minor < BPF_MINOR_VERSION) { 240 snprintf(ebuf, PCAP_ERRBUF_SIZE, 241 "kernel bpf filter out of date"); 242 goto bad; 243 } 244 #if 0 245 /* Just use the kernel default */ 246 v = 32768; /* XXX this should be a user-accessible hook */ 247 /* Ignore the return value - this is because the call fails on 248 * BPF systems that don't have kernel malloc. And if the call 249 * fails, it's no big deal, we just continue to use the standard 250 * buffer size. 251 */ 252 (void) ioctl(fd, BIOCSBLEN, (caddr_t)&v); 253 #endif 254 255 (void)strlcpy(ifr.ifr_name, device, sizeof(ifr.ifr_name)); 256 if (ioctl(fd, BIOCSETIF, (caddr_t)&ifr) < 0) { 257 snprintf(ebuf, PCAP_ERRBUF_SIZE, "%s: %s", 258 device, pcap_strerror(errno)); 259 goto bad; 260 } 261 /* Get the data link layer type. */ 262 if (ioctl(fd, BIOCGDLT, (caddr_t)&v) < 0) { 263 snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGDLT: %s", 264 pcap_strerror(errno)); 265 goto bad; 266 } 267 #if _BSDI_VERSION - 0 >= 199510 268 /* The SLIP and PPP link layer header changed in BSD/OS 2.1 */ 269 switch (v) { 270 271 case DLT_SLIP: 272 v = DLT_SLIP_BSDOS; 273 break; 274 275 case DLT_PPP: 276 v = DLT_PPP_BSDOS; 277 break; 278 } 279 #endif 280 p->linktype = v; 281 282 /* 283 * We know the default link type -- now determine all the DLTs 284 * this interface supports. If this fails with EINVAL, it's 285 * not fatal; we just don't get to use the feature later. 286 */ 287 if (ioctl(fd, BIOCGDLTLIST, (caddr_t)&bdl) == 0) { 288 bdl.bfl_list = (u_int *) calloc(bdl.bfl_len + 1, sizeof(u_int)); 289 if (bdl.bfl_list == NULL) { 290 (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", 291 pcap_strerror(errno)); 292 goto bad; 293 } 294 295 if (ioctl(fd, BIOCGDLTLIST, (caddr_t)&bdl) < 0) { 296 (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, 297 "BIOCGDLTLIST: %s", pcap_strerror(errno)); 298 goto bad; 299 } 300 p->dlt_count = bdl.bfl_len; 301 p->dlt_list = bdl.bfl_list; 302 } else { 303 if (errno != EINVAL) { 304 (void)snprintf(ebuf, PCAP_ERRBUF_SIZE, 305 "BIOCGDLTLIST: %s", pcap_strerror(errno)); 306 goto bad; 307 } 308 } 309 310 /* set timeout */ 311 if (to_ms != 0) { 312 struct timeval to; 313 to.tv_sec = to_ms / 1000; 314 to.tv_usec = (to_ms * 1000) % 1000000; 315 if (ioctl(p->fd, BIOCSRTIMEOUT, (caddr_t)&to) < 0) { 316 snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCSRTIMEOUT: %s", 317 pcap_strerror(errno)); 318 goto bad; 319 } 320 } 321 if (promisc) 322 /* set promiscuous mode, okay if it fails */ 323 (void)ioctl(p->fd, BIOCPROMISC, NULL); 324 325 if (ioctl(fd, BIOCGBLEN, (caddr_t)&v) < 0) { 326 snprintf(ebuf, PCAP_ERRBUF_SIZE, "BIOCGBLEN: %s", 327 pcap_strerror(errno)); 328 goto bad; 329 } 330 p->bufsize = v; 331 p->buffer = (u_char *)malloc(p->bufsize); 332 if (p->buffer == NULL) { 333 snprintf(ebuf, PCAP_ERRBUF_SIZE, "malloc: %s", 334 pcap_strerror(errno)); 335 goto bad; 336 } 337 338 return (p); 339 bad: 340 if (fd >= 0) 341 (void)close(fd); 342 free(bdl.bfl_list); 343 free(p); 344 return (NULL); 345 } 346 347 int 348 pcap_setfilter(pcap_t *p, struct bpf_program *fp) 349 { 350 size_t buflen; 351 /* 352 * It looks that BPF code generated by gen_protochain() is not 353 * compatible with some of kernel BPF code (for example BSD/OS 3.1). 354 * Take a safer side for now. 355 */ 356 if (no_optimize || (p->sf.rfile != NULL)){ 357 if (p->fcode.bf_insns != NULL) 358 pcap_freecode(&p->fcode); 359 buflen = sizeof(*fp->bf_insns) * fp->bf_len; 360 p->fcode.bf_len = fp->bf_len; 361 p->fcode.bf_insns = malloc(buflen); 362 if (p->fcode.bf_insns == NULL) { 363 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "malloc: %s", 364 pcap_strerror(errno)); 365 return (-1); 366 } 367 memcpy(p->fcode.bf_insns, fp->bf_insns, buflen); 368 } else if (ioctl(p->fd, BIOCSETF, (caddr_t)fp) < 0) { 369 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSETF: %s", 370 pcap_strerror(errno)); 371 return (-1); 372 } 373 return (0); 374 } 375 376 int 377 pcap_setdirection(pcap_t *p, pcap_direction_t d) 378 { 379 u_int dirfilt; 380 381 switch (d) { 382 case PCAP_D_INOUT: 383 dirfilt = 0; 384 break; 385 case PCAP_D_IN: 386 dirfilt = BPF_DIRECTION_OUT; 387 break; 388 case PCAP_D_OUT: 389 dirfilt = BPF_DIRECTION_IN; 390 break; 391 default: 392 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "Invalid direction"); 393 return (-1); 394 } 395 if (ioctl(p->fd, BIOCSDIRFILT, &dirfilt) < 0) { 396 snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "BIOCSDIRFILT: %s", 397 pcap_strerror(errno)); 398 return (-1); 399 } 400 return (0); 401 } 402 403 int 404 pcap_set_datalink(pcap_t *p, int dlt) 405 { 406 int i; 407 408 if (p->dlt_count == 0) { 409 /* 410 * We couldn't fetch the list of DLTs, or we don't 411 * have a "set datalink" operation, which means 412 * this platform doesn't support changing the 413 * DLT for an interface. Check whether the new 414 * DLT is the one this interface supports. 415 */ 416 if (p->linktype != dlt) 417 goto unsupported; 418 419 /* 420 * It is, so there's nothing we need to do here. 421 */ 422 return (0); 423 } 424 for (i = 0; i < p->dlt_count; i++) 425 if (p->dlt_list[i] == dlt) 426 break; 427 if (i >= p->dlt_count) 428 goto unsupported; 429 if (ioctl(p->fd, BIOCSDLT, &dlt) == -1) { 430 (void) snprintf(p->errbuf, sizeof(p->errbuf), 431 "Cannot set DLT %d: %s", dlt, strerror(errno)); 432 return (-1); 433 } 434 p->linktype = dlt; 435 return (0); 436 437 unsupported: 438 (void) snprintf(p->errbuf, sizeof(p->errbuf), 439 "DLT %d is not one of the DLTs supported by this device", 440 dlt); 441 return (-1); 442 } 443 444