1 /* 2 * Copyright (c) 1987-1990 The Regents of the University of California. 3 * 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 #ifndef lint 22 char copyright[] = 23 "@(#) Copyright (c) 1987-1990 The Regents of the University of California.\nAll rights reserved.\n"; 24 static char rcsid[] = 25 "@(#)$Header: tcpdump.c,v 1.55 91/05/06 02:10:34 mccanne Exp $ (LBL)"; 26 #endif 27 28 /* 29 * tcpdump - monitor tcp/ip traffic on an ethernet. 30 * 31 * First written in 1987 by Van Jacobson, Lawrence Berkeley Laboratory. 32 * Mercilessly hacked and occasionally improved since then via the 33 * combined efforts of Van, Steve McCanne and Craig Leres of LBL. 34 */ 35 36 #include <stdio.h> 37 #include <signal.h> 38 #include <sys/types.h> 39 #include <sys/time.h> 40 /*#include <sys/timeb.h> */ 41 #include <netinet/in.h> 42 43 #include <net/bpf.h> 44 45 #include "interface.h" 46 #include "savefile.h" 47 #include "addrtoname.h" 48 49 int fflag; /* don't translate "foreign" IP address */ 50 int nflag; /* leave addresses as numbers */ 51 int Nflag; /* remove domains from printed host names */ 52 int pflag; /* don't go promiscuous */ 53 int qflag; /* quick (shorter) output */ 54 int cflag; /* only print 'cnt' packets */ 55 int tflag = 1; /* print packet arrival time */ 56 int eflag; /* print ethernet header */ 57 int vflag; /* verbose */ 58 int xflag; /* print packet in hex */ 59 int Oflag = 1; /* run filter code optimizer */ 60 int Sflag; /* print raw TCP sequence numbers */ 61 62 int dflag; /* print filter code */ 63 64 long thiszone; /* gmt to local correction */ 65 66 static void cleanup(); 67 68 /* Length of saved portion of packet. */ 69 int snaplen = DEFAULT_SNAPLEN; 70 71 static int if_fd = -1; 72 73 struct printer { 74 void (*f)(); 75 int type; 76 }; 77 78 static struct printer printers[] = { 79 { ether_if_print, DLT_EN10MB }, 80 { sl_if_print, DLT_SLIP }, 81 { ppp_if_print, DLT_PPP }, 82 { 0, 0 }, 83 }; 84 85 void 86 (*lookup_printer(type))() 87 int type; 88 { 89 struct printer *p; 90 91 for (p = printers; p->f; ++p) 92 if (type == p->type) 93 return p->f; 94 95 error("unknown data link type %x", type); 96 /* NOTREACHED */ 97 } 98 99 void 100 main(argc, argv) 101 int argc; 102 char **argv; 103 { 104 struct bpf_program *parse(); 105 void bpf_dump(); 106 107 int cnt, i; 108 /* struct timeb zt;*/ 109 struct bpf_program *fcode; 110 int op; 111 void (*printit)(); 112 char *infile = 0; 113 char *cmdbuf; 114 int linktype; 115 int err; 116 117 char *RFileName = 0; /* -r argument */ 118 char *WFileName = 0; /* -w argument */ 119 120 char *device = 0; 121 122 extern char *optarg; 123 extern int optind, opterr; 124 125 opterr = 0; 126 while ((op = getopt(argc, argv, "c:defF:i:lnNOpqr:s:Stvw:xY")) != EOF) 127 switch (op) { 128 case 'c': 129 ++cflag; 130 cnt = atoi(optarg); 131 break; 132 133 case 'd': 134 ++dflag; 135 break; 136 137 case 'e': 138 ++eflag; 139 break; 140 141 case 'f': 142 ++fflag; 143 break; 144 145 case 'F': 146 infile = optarg; 147 break; 148 149 case 'i': 150 device = optarg; 151 break; 152 153 case 'l': 154 setlinebuf(stdout); 155 break; 156 157 case 'n': 158 ++nflag; 159 break; 160 161 case 'N': 162 ++Nflag; 163 break; 164 165 case 'O': 166 Oflag = 0; 167 break; 168 169 case 'p': 170 ++pflag; 171 break; 172 173 case 'q': 174 ++qflag; 175 break; 176 177 case 'r': 178 RFileName = optarg; 179 break; 180 181 case 's': 182 snaplen = atoi(optarg); 183 break; 184 185 case 'S': 186 ++Sflag; 187 break; 188 189 case 't': 190 --tflag; 191 break; 192 193 case 'v': 194 ++vflag; 195 break; 196 197 case 'w': 198 WFileName = optarg; 199 break; 200 #ifdef YYDEBUG 201 case 'Y': 202 { 203 extern int yydebug; 204 yydebug = 1; 205 } 206 break; 207 #endif 208 case 'x': 209 ++xflag; 210 break; 211 212 default: 213 usage(); 214 /* NOTREACHED */ 215 } 216 217 if (tflag > 0) { 218 struct timeval now; 219 struct timezone tz; 220 221 if (gettimeofday(&now, &tz) < 0) { 222 perror("gettimeofday"); 223 exit(1); 224 } 225 thiszone = tz.tz_minuteswest * -60; 226 if (localtime(&now.tv_sec)->tm_isdst) 227 thiszone += 3600; 228 229 /* Machine specific timestamp initialization */ 230 timestampinit(clock_sigfigs()); 231 } 232 233 if (RFileName) { 234 /* 235 * We don't need network access, so set back the user id. 236 */ 237 setuid(getuid()); 238 239 err = sf_read_init(RFileName, &linktype); 240 if (err) 241 sf_err(err); 242 } 243 else { 244 if (device == 0) { 245 device = lookup_device(); 246 if (device == 0) 247 error("can't find any interfaces"); 248 } 249 if_fd = initdevice(device, pflag, &linktype); 250 251 /* 252 * Let user own process after socket has been opened. 253 */ 254 setuid(getuid()); 255 } 256 257 if (infile) 258 cmdbuf = read_infile(infile); 259 else 260 cmdbuf = copy_argv(&argv[optind]); 261 262 fcode = parse(cmdbuf, Oflag, linktype); 263 if (dflag) { 264 bpf_dump(fcode, dflag); 265 exit(0); 266 } 267 268 init_addrtoname(device, fflag); 269 270 (void)signal(SIGTERM, cleanup); 271 (void)signal(SIGINT, cleanup); 272 (void)signal(SIGHUP, cleanup); 273 274 printit = lookup_printer(linktype); 275 276 if (WFileName) { 277 sf_write_init(WFileName, linktype); 278 printit = sf_write; 279 } 280 if (RFileName) { 281 err = sf_read(fcode, cnt, printit); 282 if (err) 283 sf_err(err); 284 } else { 285 fprintf(stderr, "tcpdump: listening on %s\n", device); 286 fflush(stderr); 287 readloop(cnt, if_fd, fcode, printit); 288 } 289 exit(0); 290 } 291 292 /* make a clean exit on interrupts */ 293 static void 294 cleanup() 295 { 296 if (if_fd >= 0) { 297 putc('\n', stderr); 298 wrapup(if_fd); 299 } 300 exit(0); 301 } 302 303 void 304 default_print(sp, length) 305 register u_short *sp; 306 register int length; 307 { 308 register u_int i; 309 register int nshorts; 310 311 nshorts = (unsigned) length / sizeof(u_short); 312 i = 0; 313 while (--nshorts >= 0) { 314 if ((i++ % 8) == 0) 315 (void)printf("\n\t\t\t"); 316 (void)printf(" %04x", ntohs(*sp++)); 317 } 318 if (length & 1) { 319 if ((i % 8) == 0) 320 (void)printf("\n\t\t\t"); 321 (void)printf(" %02x", *(u_char *)sp); 322 } 323 } 324 325 void 326 usage() 327 { 328 (void)fprintf(stderr, "Version %d.%d\n", VERSION_MAJOR, VERSION_MINOR); 329 (void)fprintf(stderr, 330 "Usage: tcpdump [-deflnOpqtvx] [-c count] [-i interface]\n"); 331 (void)fprintf(stderr, 332 "\t\t[-r filename] [-w filename] [expr]\n"); 333 exit(-1); 334 } 335