1/* 2 * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 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 22#include "varattrs.h" 23 24#ifndef lint 25static const char copyright[] _U_ = 26 "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\ 27The Regents of the University of California. All rights reserved.\n"; 28#endif 29 30#ifdef HAVE_CONFIG_H 31#include <config.h> 32#endif 33 34#include <pcap.h> 35#include <stdio.h> 36#include <stdlib.h> 37#include <string.h> 38#include <stdarg.h> 39#ifdef _WIN32 40 #include "getopt.h" 41 #include "unix.h" 42#else 43 #include <unistd.h> 44#endif 45#include <fcntl.h> 46#include <errno.h> 47#ifdef _WIN32 48 #include <winsock2.h> 49 #include <ws2tcpip.h> 50#else 51 #include <sys/socket.h> 52 #include <arpa/inet.h> 53#endif 54#include <sys/types.h> 55#include <sys/stat.h> 56 57#include "pcap/funcattrs.h" 58 59#ifdef BDEBUG 60/* 61 * We have pcap_set_optimizer_debug() and pcap_set_print_dot_graph() in 62 * libpcap; declare them (they're not declared by any libpcap header, 63 * because they're special hacks, only available if libpcap was configured 64 * to include them, and only intended for use by libpcap developers trying 65 * to debug the optimizer for filter expressions). 66 */ 67PCAP_API void pcap_set_optimizer_debug(int); 68PCAP_API void pcap_set_print_dot_graph(int); 69#endif 70 71static char *program_name; 72 73/* Forwards */ 74static void PCAP_NORETURN usage(void); 75static void PCAP_NORETURN error(const char *, ...) PCAP_PRINTFLIKE(1, 2); 76static void warn(const char *, ...) PCAP_PRINTFLIKE(1, 2); 77 78/* 79 * On Windows, we need to open the file in binary mode, so that 80 * we get all the bytes specified by the size we get from "fstat()". 81 * On UNIX, that's not necessary. O_BINARY is defined on Windows; 82 * we define it as 0 if it's not defined, so it does nothing. 83 */ 84#ifndef O_BINARY 85#define O_BINARY 0 86#endif 87 88static char * 89read_infile(char *fname) 90{ 91 register int i, fd, cc; 92 register char *cp; 93 struct stat buf; 94 95 fd = open(fname, O_RDONLY|O_BINARY); 96 if (fd < 0) 97 error("can't open %s: %s", fname, pcap_strerror(errno)); 98 99 if (fstat(fd, &buf) < 0) 100 error("can't stat %s: %s", fname, pcap_strerror(errno)); 101 102 cp = malloc((u_int)buf.st_size + 1); 103 if (cp == NULL) 104 error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1, 105 fname, pcap_strerror(errno)); 106 cc = read(fd, cp, (u_int)buf.st_size); 107 if (cc < 0) 108 error("read %s: %s", fname, pcap_strerror(errno)); 109 if (cc != buf.st_size) 110 error("short read %s (%d != %d)", fname, cc, (int)buf.st_size); 111 112 close(fd); 113 /* replace "# comment" with spaces */ 114 for (i = 0; i < cc; i++) { 115 if (cp[i] == '#') 116 while (i < cc && cp[i] != '\n') 117 cp[i++] = ' '; 118 } 119 cp[cc] = '\0'; 120 return (cp); 121} 122 123/* VARARGS */ 124static void 125error(const char *fmt, ...) 126{ 127 va_list ap; 128 129 (void)fprintf(stderr, "%s: ", program_name); 130 va_start(ap, fmt); 131 (void)vfprintf(stderr, fmt, ap); 132 va_end(ap); 133 if (*fmt) { 134 fmt += strlen(fmt); 135 if (fmt[-1] != '\n') 136 (void)fputc('\n', stderr); 137 } 138 exit(1); 139 /* NOTREACHED */ 140} 141 142/* VARARGS */ 143static void 144warn(const char *fmt, ...) 145{ 146 va_list ap; 147 148 (void)fprintf(stderr, "%s: WARNING: ", program_name); 149 va_start(ap, fmt); 150 (void)vfprintf(stderr, fmt, ap); 151 va_end(ap); 152 if (*fmt) { 153 fmt += strlen(fmt); 154 if (fmt[-1] != '\n') 155 (void)fputc('\n', stderr); 156 } 157} 158 159/* 160 * Copy arg vector into a new buffer, concatenating arguments with spaces. 161 */ 162static char * 163copy_argv(register char **argv) 164{ 165 register char **p; 166 register u_int len = 0; 167 char *buf; 168 char *src, *dst; 169 170 p = argv; 171 if (*p == 0) 172 return 0; 173 174 while (*p) 175 len += strlen(*p++) + 1; 176 177 buf = (char *)malloc(len); 178 if (buf == NULL) 179 error("copy_argv: malloc"); 180 181 p = argv; 182 dst = buf; 183 while ((src = *p++) != NULL) { 184 while ((*dst++ = *src++) != '\0') 185 ; 186 dst[-1] = ' '; 187 } 188 dst[-1] = '\0'; 189 190 return buf; 191} 192 193int 194main(int argc, char **argv) 195{ 196 char *cp; 197 int op; 198 int dflag; 199 int gflag; 200 char *infile; 201 int Oflag; 202 long snaplen; 203 char *p; 204 int dlt; 205 int have_fcode = 0; 206 bpf_u_int32 netmask = PCAP_NETMASK_UNKNOWN; 207 char *cmdbuf; 208 pcap_t *pd; 209 struct bpf_program fcode; 210 211#ifdef _WIN32 212 if (pcap_wsockinit() != 0) 213 return 1; 214#endif /* _WIN32 */ 215 216 dflag = 1; 217 gflag = 0; 218 219 infile = NULL; 220 Oflag = 1; 221 snaplen = 68; 222 223 if ((cp = strrchr(argv[0], '/')) != NULL) 224 program_name = cp + 1; 225 else 226 program_name = argv[0]; 227 228 opterr = 0; 229 while ((op = getopt(argc, argv, "dF:gm:Os:")) != -1) { 230 switch (op) { 231 232 case 'd': 233 ++dflag; 234 break; 235 236 case 'g': 237#ifdef BDEBUG 238 ++gflag; 239#else 240 error("libpcap and filtertest not built with optimizer debugging enabled"); 241#endif 242 break; 243 244 case 'F': 245 infile = optarg; 246 break; 247 248 case 'O': 249 Oflag = 0; 250 break; 251 252 case 'm': { 253 bpf_u_int32 addr; 254 255 switch (inet_pton(AF_INET, optarg, &addr)) { 256 257 case 0: 258 error("invalid netmask %s", optarg); 259 break; 260 261 case -1: 262 error("invalid netmask %s: %s", optarg, 263 pcap_strerror(errno)); 264 break; 265 266 case 1: 267 netmask = addr; 268 break; 269 } 270 break; 271 } 272 273 case 's': { 274 char *end; 275 276 snaplen = strtol(optarg, &end, 0); 277 if (optarg == end || *end != '\0' 278 || snaplen < 0 || snaplen > 65535) 279 error("invalid snaplen %s", optarg); 280 else if (snaplen == 0) 281 snaplen = 65535; 282 break; 283 } 284 285 default: 286 usage(); 287 /* NOTREACHED */ 288 } 289 } 290 291 if (optind >= argc) { 292 usage(); 293 /* NOTREACHED */ 294 } 295 296 dlt = pcap_datalink_name_to_val(argv[optind]); 297 if (dlt < 0) { 298 dlt = (int)strtol(argv[optind], &p, 10); 299 if (p == argv[optind] || *p != '\0') 300 error("invalid data link type %s", argv[optind]); 301 } 302 303 if (infile) 304 cmdbuf = read_infile(infile); 305 else 306 cmdbuf = copy_argv(&argv[optind+1]); 307 308#ifdef BDEBUG 309 pcap_set_optimizer_debug(dflag); 310 pcap_set_print_dot_graph(gflag); 311#endif 312 313 pd = pcap_open_dead(dlt, snaplen); 314 if (pd == NULL) 315 error("Can't open fake pcap_t"); 316 317 if (pcap_compile(pd, &fcode, cmdbuf, Oflag, netmask) < 0) 318 error("%s", pcap_geterr(pd)); 319 320 have_fcode = 1; 321 if (!bpf_validate(fcode.bf_insns, fcode.bf_len)) 322 warn("Filter doesn't pass validation"); 323 324#ifdef BDEBUG 325 if (cmdbuf != NULL) { 326 // replace line feed with space 327 for (cp = cmdbuf; *cp != '\0'; ++cp) { 328 if (*cp == '\r' || *cp == '\n') { 329 *cp = ' '; 330 } 331 } 332 // only show machine code if BDEBUG defined, since dflag > 3 333 printf("machine codes for filter: %s\n", cmdbuf); 334 } else 335 printf("machine codes for empty filter:\n"); 336#endif 337 338 bpf_dump(&fcode, dflag); 339 free(cmdbuf); 340 if (have_fcode) 341 pcap_freecode (&fcode); 342 pcap_close(pd); 343 exit(0); 344} 345 346static void 347usage(void) 348{ 349 (void)fprintf(stderr, "%s, with %s\n", program_name, 350 pcap_lib_version()); 351 (void)fprintf(stderr, 352#ifdef BDEBUG 353 "Usage: %s [-dgO] [ -F file ] [ -m netmask] [ -s snaplen ] dlt [ expression ]\n", 354#else 355 "Usage: %s [-dO] [ -F file ] [ -m netmask] [ -s snaplen ] dlt [ expression ]\n", 356#endif 357 program_name); 358 exit(1); 359} 360