1353141Sphilip/* 2353141Sphilip * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 3353141Sphilip * The Regents of the University of California. All rights reserved. 4353141Sphilip * 5353141Sphilip * Redistribution and use in source and binary forms, with or without 6353141Sphilip * modification, are permitted provided that: (1) source code distributions 7353141Sphilip * retain the above copyright notice and this paragraph in its entirety, (2) 8353141Sphilip * distributions including binary code include the above copyright notice and 9353141Sphilip * this paragraph in its entirety in the documentation or other materials 10353141Sphilip * provided with the distribution, and (3) all advertising materials mentioning 11353141Sphilip * features or use of this software display the following acknowledgement: 12353141Sphilip * ``This product includes software developed by the University of California, 13353141Sphilip * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14353141Sphilip * the University nor the names of its contributors may be used to endorse 15353141Sphilip * or promote products derived from this software without specific prior 16353141Sphilip * written permission. 17353141Sphilip * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18353141Sphilip * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19353141Sphilip * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20353141Sphilip */ 21353141Sphilip 22353141Sphilip#include "varattrs.h" 23353141Sphilip 24353141Sphilip#ifndef lint 25353141Sphilipstatic const char copyright[] _U_ = 26353141Sphilip "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\ 27353141SphilipThe Regents of the University of California. All rights reserved.\n"; 28353141Sphilip#endif 29353141Sphilip 30353141Sphilip#ifdef HAVE_CONFIG_H 31353141Sphilip#include <config.h> 32353141Sphilip#endif 33353141Sphilip 34353141Sphilip#include <pcap.h> 35353141Sphilip#include <stdio.h> 36353141Sphilip#include <stdlib.h> 37353141Sphilip#include <string.h> 38353141Sphilip#include <stdarg.h> 39353141Sphilip#ifdef _WIN32 40353141Sphilip #include "getopt.h" 41353141Sphilip #include "unix.h" 42353141Sphilip#else 43353141Sphilip #include <unistd.h> 44353141Sphilip#endif 45353141Sphilip#include <fcntl.h> 46353141Sphilip#include <errno.h> 47353141Sphilip#ifdef _WIN32 48353141Sphilip #include <winsock2.h> 49353141Sphilip #include <ws2tcpip.h> 50353141Sphilip#else 51353141Sphilip #include <sys/socket.h> 52353141Sphilip #include <arpa/inet.h> 53353141Sphilip#endif 54353141Sphilip#include <sys/types.h> 55353141Sphilip#include <sys/stat.h> 56353141Sphilip 57353141Sphilip#include "pcap/funcattrs.h" 58353141Sphilip 59353141Sphilip#ifdef BDEBUG 60353141Sphilip/* 61353141Sphilip * We have pcap_set_optimizer_debug() and pcap_set_print_dot_graph() in 62353141Sphilip * libpcap; declare them (they're not declared by any libpcap header, 63353141Sphilip * because they're special hacks, only available if libpcap was configured 64353141Sphilip * to include them, and only intended for use by libpcap developers trying 65353141Sphilip * to debug the optimizer for filter expressions). 66353141Sphilip */ 67353141SphilipPCAP_API void pcap_set_optimizer_debug(int); 68353141SphilipPCAP_API void pcap_set_print_dot_graph(int); 69353141Sphilip#endif 70353141Sphilip 71353141Sphilipstatic char *program_name; 72353141Sphilip 73353141Sphilip/* Forwards */ 74353141Sphilipstatic void PCAP_NORETURN usage(void); 75353141Sphilipstatic void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2); 76353141Sphilipstatic void warn(const char *, ...) PCAP_PRINTFLIKE(1, 2); 77353141Sphilip 78353141Sphilip/* 79353141Sphilip * On Windows, we need to open the file in binary mode, so that 80353141Sphilip * we get all the bytes specified by the size we get from "fstat()". 81353141Sphilip * On UNIX, that's not necessary. O_BINARY is defined on Windows; 82353141Sphilip * we define it as 0 if it's not defined, so it does nothing. 83353141Sphilip */ 84353141Sphilip#ifndef O_BINARY 85353141Sphilip#define O_BINARY 0 86353141Sphilip#endif 87353141Sphilip 88353141Sphilipstatic char * 89353141Sphilipread_infile(char *fname) 90353141Sphilip{ 91353141Sphilip register int i, fd, cc; 92353141Sphilip register char *cp; 93353141Sphilip struct stat buf; 94353141Sphilip 95353141Sphilip fd = open(fname, O_RDONLY|O_BINARY); 96353141Sphilip if (fd < 0) 97353141Sphilip error("can't open %s: %s", fname, pcap_strerror(errno)); 98353141Sphilip 99353141Sphilip if (fstat(fd, &buf) < 0) 100353141Sphilip error("can't stat %s: %s", fname, pcap_strerror(errno)); 101353141Sphilip 102353141Sphilip cp = malloc((u_int)buf.st_size + 1); 103353141Sphilip if (cp == NULL) 104353141Sphilip error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1, 105353141Sphilip fname, pcap_strerror(errno)); 106353141Sphilip cc = read(fd, cp, (u_int)buf.st_size); 107353141Sphilip if (cc < 0) 108353141Sphilip error("read %s: %s", fname, pcap_strerror(errno)); 109353141Sphilip if (cc != buf.st_size) 110353141Sphilip error("short read %s (%d != %d)", fname, cc, (int)buf.st_size); 111353141Sphilip 112353141Sphilip close(fd); 113353141Sphilip /* replace "# comment" with spaces */ 114353141Sphilip for (i = 0; i < cc; i++) { 115353141Sphilip if (cp[i] == '#') 116353141Sphilip while (i < cc && cp[i] != '\n') 117353141Sphilip cp[i++] = ' '; 118353141Sphilip } 119353141Sphilip cp[cc] = '\0'; 120353141Sphilip return (cp); 121353141Sphilip} 122353141Sphilip 123353141Sphilip/* VARARGS */ 124353141Sphilipstatic void 125353141Sphiliperror(const char *fmt, ...) 126353141Sphilip{ 127353141Sphilip va_list ap; 128353141Sphilip 129353141Sphilip (void)fprintf(stderr, "%s: ", program_name); 130353141Sphilip va_start(ap, fmt); 131353141Sphilip (void)vfprintf(stderr, fmt, ap); 132353141Sphilip va_end(ap); 133353141Sphilip if (*fmt) { 134353141Sphilip fmt += strlen(fmt); 135353141Sphilip if (fmt[-1] != '\n') 136353141Sphilip (void)fputc('\n', stderr); 137353141Sphilip } 138353141Sphilip exit(1); 139353141Sphilip /* NOTREACHED */ 140353141Sphilip} 141353141Sphilip 142353141Sphilip/* VARARGS */ 143353141Sphilipstatic void 144353141Sphilipwarn(const char *fmt, ...) 145353141Sphilip{ 146353141Sphilip va_list ap; 147353141Sphilip 148353141Sphilip (void)fprintf(stderr, "%s: WARNING: ", program_name); 149353141Sphilip va_start(ap, fmt); 150353141Sphilip (void)vfprintf(stderr, fmt, ap); 151353141Sphilip va_end(ap); 152353141Sphilip if (*fmt) { 153353141Sphilip fmt += strlen(fmt); 154353141Sphilip if (fmt[-1] != '\n') 155353141Sphilip (void)fputc('\n', stderr); 156353141Sphilip } 157353141Sphilip} 158353141Sphilip 159353141Sphilip/* 160353141Sphilip * Copy arg vector into a new buffer, concatenating arguments with spaces. 161353141Sphilip */ 162353141Sphilipstatic char * 163353141Sphilipcopy_argv(register char **argv) 164353141Sphilip{ 165353141Sphilip register char **p; 166353141Sphilip register u_int len = 0; 167353141Sphilip char *buf; 168353141Sphilip char *src, *dst; 169353141Sphilip 170353141Sphilip p = argv; 171353141Sphilip if (*p == 0) 172353141Sphilip return 0; 173353141Sphilip 174353141Sphilip while (*p) 175353141Sphilip len += strlen(*p++) + 1; 176353141Sphilip 177353141Sphilip buf = (char *)malloc(len); 178353141Sphilip if (buf == NULL) 179353141Sphilip error("copy_argv: malloc"); 180353141Sphilip 181353141Sphilip p = argv; 182353141Sphilip dst = buf; 183353141Sphilip while ((src = *p++) != NULL) { 184353141Sphilip while ((*dst++ = *src++) != '\0') 185353141Sphilip ; 186353141Sphilip dst[-1] = ' '; 187353141Sphilip } 188353141Sphilip dst[-1] = '\0'; 189353141Sphilip 190353141Sphilip return buf; 191353141Sphilip} 192353141Sphilip 193353141Sphilipint 194353141Sphilipmain(int argc, char **argv) 195353141Sphilip{ 196353141Sphilip char *cp; 197353141Sphilip int op; 198353141Sphilip int dflag; 199353141Sphilip int gflag; 200353141Sphilip char *infile; 201353141Sphilip int Oflag; 202353141Sphilip long snaplen; 203353141Sphilip char *p; 204353141Sphilip int dlt; 205353141Sphilip int have_fcode = 0; 206353141Sphilip bpf_u_int32 netmask = PCAP_NETMASK_UNKNOWN; 207353141Sphilip char *cmdbuf; 208353141Sphilip pcap_t *pd; 209353141Sphilip struct bpf_program fcode; 210353141Sphilip 211353141Sphilip#ifdef _WIN32 212353141Sphilip if (pcap_wsockinit() != 0) 213353141Sphilip return 1; 214353141Sphilip#endif /* _WIN32 */ 215353141Sphilip 216353141Sphilip dflag = 1; 217353141Sphilip gflag = 0; 218353141Sphilip 219353141Sphilip infile = NULL; 220353141Sphilip Oflag = 1; 221353141Sphilip snaplen = 68; 222353141Sphilip 223353141Sphilip if ((cp = strrchr(argv[0], '/')) != NULL) 224353141Sphilip program_name = cp + 1; 225353141Sphilip else 226353141Sphilip program_name = argv[0]; 227353141Sphilip 228353141Sphilip opterr = 0; 229353141Sphilip while ((op = getopt(argc, argv, "dF:gm:Os:")) != -1) { 230353141Sphilip switch (op) { 231353141Sphilip 232353141Sphilip case 'd': 233353141Sphilip ++dflag; 234353141Sphilip break; 235353141Sphilip 236353141Sphilip case 'g': 237353141Sphilip#ifdef BDEBUG 238353141Sphilip ++gflag; 239353141Sphilip#else 240353141Sphilip error("libpcap and filtertest not built with optimizer debugging enabled"); 241353141Sphilip#endif 242353141Sphilip break; 243353141Sphilip 244353141Sphilip case 'F': 245353141Sphilip infile = optarg; 246353141Sphilip break; 247353141Sphilip 248353141Sphilip case 'O': 249353141Sphilip Oflag = 0; 250353141Sphilip break; 251353141Sphilip 252353141Sphilip case 'm': { 253353141Sphilip bpf_u_int32 addr; 254353141Sphilip 255353141Sphilip switch (inet_pton(AF_INET, optarg, &addr)) { 256353141Sphilip 257353141Sphilip case 0: 258353141Sphilip error("invalid netmask %s", optarg); 259353141Sphilip break; 260353141Sphilip 261353141Sphilip case -1: 262353141Sphilip error("invalid netmask %s: %s", optarg, 263353141Sphilip pcap_strerror(errno)); 264353141Sphilip break; 265353141Sphilip 266353141Sphilip case 1: 267353141Sphilip netmask = addr; 268353141Sphilip break; 269353141Sphilip } 270353141Sphilip break; 271353141Sphilip } 272353141Sphilip 273353141Sphilip case 's': { 274353141Sphilip char *end; 275353141Sphilip 276353141Sphilip snaplen = strtol(optarg, &end, 0); 277353141Sphilip if (optarg == end || *end != '\0' 278353141Sphilip || snaplen < 0 || snaplen > 65535) 279353141Sphilip error("invalid snaplen %s", optarg); 280353141Sphilip else if (snaplen == 0) 281353141Sphilip snaplen = 65535; 282353141Sphilip break; 283353141Sphilip } 284353141Sphilip 285353141Sphilip default: 286353141Sphilip usage(); 287353141Sphilip /* NOTREACHED */ 288353141Sphilip } 289353141Sphilip } 290353141Sphilip 291353141Sphilip if (optind >= argc) { 292353141Sphilip usage(); 293353141Sphilip /* NOTREACHED */ 294353141Sphilip } 295353141Sphilip 296353141Sphilip dlt = pcap_datalink_name_to_val(argv[optind]); 297353141Sphilip if (dlt < 0) { 298353141Sphilip dlt = (int)strtol(argv[optind], &p, 10); 299353141Sphilip if (p == argv[optind] || *p != '\0') 300353141Sphilip error("invalid data link type %s", argv[optind]); 301353141Sphilip } 302353141Sphilip 303353141Sphilip if (infile) 304353141Sphilip cmdbuf = read_infile(infile); 305353141Sphilip else 306353141Sphilip cmdbuf = copy_argv(&argv[optind+1]); 307353141Sphilip 308353141Sphilip#ifdef BDEBUG 309353141Sphilip pcap_set_optimizer_debug(dflag); 310353141Sphilip pcap_set_print_dot_graph(gflag); 311353141Sphilip#endif 312353141Sphilip 313353141Sphilip pd = pcap_open_dead(dlt, snaplen); 314353141Sphilip if (pd == NULL) 315353141Sphilip error("Can't open fake pcap_t"); 316353141Sphilip 317353141Sphilip if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) 318353141Sphilip error("%s", pcap_geterr(pd)); 319353141Sphilip 320353141Sphilip have_fcode = 1; 321353141Sphilip if (!bpf_validate(fcode.bf_insns, fcode.bf_len)) 322353141Sphilip warn("Filter doesn't pass validation"); 323353141Sphilip 324353141Sphilip#ifdef BDEBUG 325353141Sphilip if (cmdbuf != NULL) { 326353141Sphilip // replace line feed with space 327353141Sphilip for (cp = cmdbuf; *cp != '\0'; ++cp) { 328353141Sphilip if (*cp == '\r' || *cp == '\n') { 329353141Sphilip *cp = ' '; 330353141Sphilip } 331353141Sphilip } 332353141Sphilip // only show machine code if BDEBUG defined, since dflag > 3 333353141Sphilip printf("machine codes for filter: %s\n", cmdbuf); 334353141Sphilip } else 335353141Sphilip printf("machine codes for empty filter:\n"); 336353141Sphilip#endif 337353141Sphilip 338353141Sphilip bpf_dump(&fcode, dflag); 339353141Sphilip free(cmdbuf); 340353141Sphilip if (have_fcode) 341353141Sphilip pcap_freecode (&fcode); 342353141Sphilip pcap_close(pd); 343353141Sphilip exit(0); 344353141Sphilip} 345353141Sphilip 346353141Sphilipstatic void 347353141Sphilipusage(void) 348353141Sphilip{ 349353141Sphilip (void)fprintf(stderr, "%s, with %s\n", program_name, 350353141Sphilip pcap_lib_version()); 351353141Sphilip (void)fprintf(stderr, 352353141Sphilip#ifdef BDEBUG 353353141Sphilip "Usage: %s [-dgO] [ -F file ] [ -m netmask] [ -s snaplen ] dlt [ expression ]\n", 354353141Sphilip#else 355353141Sphilip "Usage: %s [-dO] [ -F file ] [ -m netmask] [ -s snaplen ] dlt [ expression ]\n", 356353141Sphilip#endif 357353141Sphilip program_name); 358353141Sphilip exit(1); 359353141Sphilip} 360