1230832Sgnn/* 2230832Sgnn * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 3230832Sgnn * The Regents of the University of California. All rights reserved. 4230832Sgnn * 5230832Sgnn * Redistribution and use in source and binary forms, with or without 6230832Sgnn * modification, are permitted provided that: (1) source code distributions 7230832Sgnn * retain the above copyright notice and this paragraph in its entirety, (2) 8230832Sgnn * distributions including binary code include the above copyright notice and 9230832Sgnn * this paragraph in its entirety in the documentation or other materials 10230832Sgnn * provided with the distribution, and (3) all advertising materials mentioning 11230832Sgnn * features or use of this software display the following acknowledgement: 12230832Sgnn * ``This product includes software developed by the University of California, 13230832Sgnn * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 14230832Sgnn * the University nor the names of its contributors may be used to endorse 15230832Sgnn * or promote products derived from this software without specific prior 16230832Sgnn * written permission. 17230832Sgnn * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 18230832Sgnn * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 19230832Sgnn * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 20230832Sgnn */ 21230832Sgnn 22230832Sgnn#ifndef lint 23230832Sgnnstatic const char copyright[] = 24230832Sgnn "@(#) Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000\n\ 25230832SgnnThe Regents of the University of California. All rights reserved.\n"; 26230832Sgnn#endif 27230832Sgnn 28230832Sgnn#include <pcap.h> 29230832Sgnn#include <stdio.h> 30230832Sgnn#include <stdlib.h> 31230832Sgnn#include <string.h> 32230832Sgnn#include <stdarg.h> 33230832Sgnn#include <unistd.h> 34230832Sgnn#include <errno.h> 35230832Sgnn#include <sys/types.h> 36230832Sgnn#include <sys/select.h> 37230832Sgnn#include <poll.h> 38230832Sgnn 39230832Sgnnchar *program_name; 40230832Sgnn 41230832Sgnn/* Forwards */ 42230832Sgnnstatic void countme(u_char *, const struct pcap_pkthdr *, const u_char *); 43230832Sgnnstatic void usage(void) __attribute__((noreturn)); 44230832Sgnnstatic void error(const char *, ...); 45230832Sgnnstatic void warning(const char *, ...); 46230832Sgnnstatic char *copy_argv(char **); 47230832Sgnn 48230832Sgnnstatic pcap_t *pd; 49230832Sgnn 50230832Sgnnextern int optind; 51230832Sgnnextern int opterr; 52230832Sgnnextern char *optarg; 53230832Sgnn 54230832Sgnnint 55230832Sgnnmain(int argc, char **argv) 56230832Sgnn{ 57230832Sgnn register int op; 58230832Sgnn bpf_u_int32 localnet, netmask; 59230832Sgnn register char *cp, *cmdbuf, *device; 60230832Sgnn struct bpf_program fcode; 61230832Sgnn char ebuf[PCAP_ERRBUF_SIZE]; 62230832Sgnn int status; 63230832Sgnn int packet_count; 64230832Sgnn 65230832Sgnn device = NULL; 66230832Sgnn if ((cp = strrchr(argv[0], '/')) != NULL) 67230832Sgnn program_name = cp + 1; 68230832Sgnn else 69230832Sgnn program_name = argv[0]; 70230832Sgnn 71230832Sgnn opterr = 0; 72230832Sgnn while ((op = getopt(argc, argv, "i:")) != -1) { 73230832Sgnn switch (op) { 74230832Sgnn 75230832Sgnn case 'i': 76230832Sgnn device = optarg; 77230832Sgnn break; 78230832Sgnn 79230832Sgnn default: 80230832Sgnn usage(); 81230832Sgnn /* NOTREACHED */ 82230832Sgnn } 83230832Sgnn } 84230832Sgnn 85230832Sgnn if (device == NULL) { 86230832Sgnn device = pcap_lookupdev(ebuf); 87230832Sgnn if (device == NULL) 88230832Sgnn error("%s", ebuf); 89230832Sgnn } 90230832Sgnn *ebuf = '\0'; 91230832Sgnn pd = pcap_open_live(device, 65535, 0, 1000, ebuf); 92230832Sgnn if (pd == NULL) 93230832Sgnn error("%s", ebuf); 94230832Sgnn else if (*ebuf) 95230832Sgnn warning("%s", ebuf); 96230832Sgnn if (pcap_lookupnet(device, &localnet, &netmask, ebuf) < 0) { 97230832Sgnn localnet = 0; 98230832Sgnn netmask = 0; 99230832Sgnn warning("%s", ebuf); 100230832Sgnn } 101230832Sgnn cmdbuf = copy_argv(&argv[optind]); 102230832Sgnn 103230832Sgnn if (pcap_compile(pd, &fcode, cmdbuf, 1, netmask) < 0) 104230832Sgnn error("%s", pcap_geterr(pd)); 105230832Sgnn 106230832Sgnn if (pcap_setfilter(pd, &fcode) < 0) 107230832Sgnn error("%s", pcap_geterr(pd)); 108230832Sgnn if (pcap_setnonblock(pd, 1, ebuf) == -1) 109230832Sgnn error("pcap_setnonblock failed: %s", ebuf); 110230832Sgnn printf("Listening on %s\n", device); 111230832Sgnn for (;;) { 112230832Sgnn packet_count = 0; 113230832Sgnn status = pcap_dispatch(pd, -1, countme, 114230832Sgnn (u_char *)&packet_count); 115230832Sgnn if (status < 0) 116230832Sgnn break; 117230832Sgnn if (status != 0) { 118230832Sgnn printf("%d packets seen, %d packets counted after pcap_dispatch returns\n", 119230832Sgnn status, packet_count); 120230832Sgnn } 121230832Sgnn } 122230832Sgnn if (status == -2) { 123230832Sgnn /* 124230832Sgnn * We got interrupted, so perhaps we didn't 125230832Sgnn * manage to finish a line we were printing. 126230832Sgnn * Print an extra newline, just in case. 127230832Sgnn */ 128230832Sgnn putchar('\n'); 129230832Sgnn } 130230832Sgnn (void)fflush(stdout); 131230832Sgnn if (status == -1) { 132230832Sgnn /* 133230832Sgnn * Error. Report it. 134230832Sgnn */ 135230832Sgnn (void)fprintf(stderr, "%s: pcap_loop: %s\n", 136230832Sgnn program_name, pcap_geterr(pd)); 137230832Sgnn } 138230832Sgnn pcap_close(pd); 139230832Sgnn exit(status == -1 ? 1 : 0); 140230832Sgnn} 141230832Sgnn 142230832Sgnnstatic void 143230832Sgnncountme(u_char *user, const struct pcap_pkthdr *h, const u_char *sp) 144230832Sgnn{ 145230832Sgnn int *counterp = (int *)user; 146230832Sgnn 147230832Sgnn (*counterp)++; 148230832Sgnn} 149230832Sgnn 150230832Sgnnstatic void 151230832Sgnnusage(void) 152230832Sgnn{ 153230832Sgnn (void)fprintf(stderr, "Usage: %s [ -sptn ] [ -i interface ] [expression]\n", 154230832Sgnn program_name); 155230832Sgnn exit(1); 156230832Sgnn} 157230832Sgnn 158230832Sgnn/* VARARGS */ 159230832Sgnnstatic void 160230832Sgnnerror(const char *fmt, ...) 161230832Sgnn{ 162230832Sgnn va_list ap; 163230832Sgnn 164230832Sgnn (void)fprintf(stderr, "%s: ", program_name); 165230832Sgnn va_start(ap, fmt); 166230832Sgnn (void)vfprintf(stderr, fmt, ap); 167230832Sgnn va_end(ap); 168230832Sgnn if (*fmt) { 169230832Sgnn fmt += strlen(fmt); 170230832Sgnn if (fmt[-1] != '\n') 171230832Sgnn (void)fputc('\n', stderr); 172230832Sgnn } 173230832Sgnn exit(1); 174230832Sgnn /* NOTREACHED */ 175230832Sgnn} 176230832Sgnn 177230832Sgnn/* VARARGS */ 178230832Sgnnstatic void 179230832Sgnnwarning(const char *fmt, ...) 180230832Sgnn{ 181230832Sgnn va_list ap; 182230832Sgnn 183230832Sgnn (void)fprintf(stderr, "%s: WARNING: ", program_name); 184230832Sgnn va_start(ap, fmt); 185230832Sgnn (void)vfprintf(stderr, fmt, ap); 186230832Sgnn va_end(ap); 187230832Sgnn if (*fmt) { 188230832Sgnn fmt += strlen(fmt); 189230832Sgnn if (fmt[-1] != '\n') 190230832Sgnn (void)fputc('\n', stderr); 191230832Sgnn } 192230832Sgnn} 193230832Sgnn 194230832Sgnn/* 195230832Sgnn * Copy arg vector into a new buffer, concatenating arguments with spaces. 196230832Sgnn */ 197230832Sgnnstatic char * 198230832Sgnncopy_argv(register char **argv) 199230832Sgnn{ 200230832Sgnn register char **p; 201230832Sgnn register u_int len = 0; 202230832Sgnn char *buf; 203230832Sgnn char *src, *dst; 204230832Sgnn 205230832Sgnn p = argv; 206230832Sgnn if (*p == 0) 207230832Sgnn return 0; 208230832Sgnn 209230832Sgnn while (*p) 210230832Sgnn len += strlen(*p++) + 1; 211230832Sgnn 212230832Sgnn buf = (char *)malloc(len); 213230832Sgnn if (buf == NULL) 214230832Sgnn error("copy_argv: malloc"); 215230832Sgnn 216230832Sgnn p = argv; 217230832Sgnn dst = buf; 218230832Sgnn while ((src = *p++) != NULL) { 219230832Sgnn while ((*dst++ = *src++) != '\0') 220230832Sgnn ; 221230832Sgnn dst[-1] = ' '; 222230832Sgnn } 223230832Sgnn dst[-1] = '\0'; 224230832Sgnn 225230832Sgnn return buf; 226230832Sgnn} 227