Home | History | Annotate | Download | only in tcpdump
      1 /*
      2  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
      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 #ifndef lint
     23 static const char rcsid[] _U_ =
     24     "@(#) $Header: /tcpdump/master/tcpdump/util.c,v 1.95.2.6 2006/02/08 01:40:09 hannes Exp $ (LBL)";
     25 #endif
     26 
     27 #ifdef HAVE_CONFIG_H
     28 #include "config.h"
     29 #endif
     30 
     31 #include <tcpdump-stdinc.h>
     32 
     33 #include <sys/stat.h>
     34 
     35 #include <errno.h>
     36 #ifdef HAVE_FCNTL_H
     37 #include <fcntl.h>
     38 #endif
     39 #include <pcap.h>
     40 #include <stdio.h>
     41 #include <stdarg.h>
     42 #include <stdlib.h>
     43 #include <string.h>
     44 
     45 #include "interface.h"
     46 
     47 /*
     48  * Print out a null-terminated filename (or other ascii string).
     49  * If ep is NULL, assume no truncation check is needed.
     50  * Return true if truncated.
     51  */
     52 int
     53 fn_print(register const u_char *s, register const u_char *ep)
     54 {
     55 	register int ret;
     56 	register u_char c;
     57 
     58 	ret = 1;			/* assume truncated */
     59 	while (ep == NULL || s < ep) {
     60 		c = *s++;
     61 		if (c == '\0') {
     62 			ret = 0;
     63 			break;
     64 		}
     65 		if (!isascii(c)) {
     66 			c = toascii(c);
     67 			putchar('M');
     68 			putchar('-');
     69 		}
     70 		if (!isprint(c)) {
     71 			c ^= 0x40;	/* DEL to ?, others to alpha */
     72 			putchar('^');
     73 		}
     74 		putchar(c);
     75 	}
     76 	return(ret);
     77 }
     78 
     79 /*
     80  * Print out a counted filename (or other ascii string).
     81  * If ep is NULL, assume no truncation check is needed.
     82  * Return true if truncated.
     83  */
     84 int
     85 fn_printn(register const u_char *s, register u_int n,
     86 	  register const u_char *ep)
     87 {
     88 	register u_char c;
     89 
     90 	while (n > 0 && (ep == NULL || s < ep)) {
     91 		n--;
     92 		c = *s++;
     93 		if (!isascii(c)) {
     94 			c = toascii(c);
     95 			putchar('M');
     96 			putchar('-');
     97 		}
     98 		if (!isprint(c)) {
     99 			c ^= 0x40;	/* DEL to ?, others to alpha */
    100 			putchar('^');
    101 		}
    102 		putchar(c);
    103 	}
    104 	return (n == 0) ? 0 : 1;
    105 }
    106 
    107 /*
    108  * Print out a null-padded filename (or other ascii string).
    109  * If ep is NULL, assume no truncation check is needed.
    110  * Return true if truncated.
    111  */
    112 int
    113 fn_printzp(register const u_char *s, register u_int n,
    114 	  register const u_char *ep)
    115 {
    116 	register int ret;
    117 	register u_char c;
    118 
    119 	ret = 1;			/* assume truncated */
    120 	while (n > 0 && (ep == NULL || s < ep)) {
    121 		n--;
    122 		c = *s++;
    123 		if (c == '\0') {
    124 			ret = 0;
    125 			break;
    126 		}
    127 		if (!isascii(c)) {
    128 			c = toascii(c);
    129 			putchar('M');
    130 			putchar('-');
    131 		}
    132 		if (!isprint(c)) {
    133 			c ^= 0x40;	/* DEL to ?, others to alpha */
    134 			putchar('^');
    135 		}
    136 		putchar(c);
    137 	}
    138 	return (n == 0) ? 0 : ret;
    139 }
    140 
    141 /*
    142  * Print the timestamp
    143  */
    144 void
    145 ts_print(register const struct timeval *tvp)
    146 {
    147 	register int s;
    148 	struct tm *tm;
    149 	time_t Time;
    150 	static unsigned b_sec;
    151 	static unsigned b_usec;
    152 
    153 	switch (tflag) {
    154 
    155 	case 0: /* Default */
    156 		s = (tvp->tv_sec + thiszone) % 86400;
    157 		(void)printf("%02d:%02d:%02d.%06u ",
    158 			     s / 3600, (s % 3600) / 60, s % 60,
    159 			     (unsigned)tvp->tv_usec);
    160 		break;
    161 
    162 	case 1: /* No time stamp */
    163 		break;
    164 
    165 	case 2: /* Unix timeval style */
    166 		(void)printf("%u.%06u ",
    167 			     (unsigned)tvp->tv_sec,
    168 			     (unsigned)tvp->tv_usec);
    169 		break;
    170 
    171 	case 3: /* Microseconds since previous packet */
    172 		if (b_sec == 0) {
    173 			printf("000000 ");
    174 		} else {
    175 			int d_usec = tvp->tv_usec - b_usec;
    176 			int d_sec = tvp->tv_sec - b_sec;
    177 
    178 			while (d_usec < 0) {
    179 				d_usec += 1000000;
    180 				d_sec--;
    181 			}
    182 			if (d_sec)
    183 				printf("%d. ", d_sec);
    184 			printf("%06d ", d_usec);
    185 		}
    186 		b_sec = tvp->tv_sec;
    187 		b_usec = tvp->tv_usec;
    188 		break;
    189 
    190 	case 4: /* Default + Date*/
    191 		s = (tvp->tv_sec + thiszone) % 86400;
    192 		Time = (tvp->tv_sec + thiszone) - s;
    193 		tm = gmtime (&Time);
    194 		if (!tm)
    195 			printf("Date fail  ");
    196 		else
    197 			printf("%04d-%02d-%02d ",
    198 				   tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
    199 		printf("%02d:%02d:%02d.%06u ",
    200 			   s / 3600, (s % 3600) / 60, s % 60, (unsigned)tvp->tv_usec);
    201 		break;
    202 	}
    203 }
    204 
    205 /*
    206  * Print a relative number of seconds (e.g. hold time, prune timer)
    207  * in the form 5m1s.  This does no truncation, so 32230861 seconds
    208  * is represented as 1y1w1d1h1m1s.
    209  */
    210 void
    211 relts_print(int secs)
    212 {
    213 	static const char *lengths[] = {"y", "w", "d", "h", "m", "s"};
    214 	static const int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
    215 	const char **l = lengths;
    216 	const int *s = seconds;
    217 
    218 	if (secs == 0) {
    219 		(void)printf("0s");
    220 		return;
    221 	}
    222 	if (secs < 0) {
    223 		(void)printf("-");
    224 		secs = -secs;
    225 	}
    226 	while (secs > 0) {
    227 		if (secs >= *s) {
    228 			(void)printf("%d%s", secs / *s, *l);
    229 			secs -= (secs / *s) * *s;
    230 		}
    231 		s++;
    232 		l++;
    233 	}
    234 }
    235 
    236 /*
    237  *  this is a generic routine for printing unknown data;
    238  *  we pass on the linefeed plus indentation string to
    239  *  get a proper output - returns 0 on error
    240  */
    241 
    242 int
    243 print_unknown_data(const u_char *cp,const char *ident,int len)
    244 {
    245 	if (len < 0) {
    246 		printf("%sDissector error: print_unknown_data called with negative length",
    247 		    ident);
    248 		return(0);
    249 	}
    250 	if (snapend - cp < len)
    251 		len = snapend - cp;
    252 	if (len < 0) {
    253 		printf("%sDissector error: print_unknown_data called with pointer past end of packet",
    254 		    ident);
    255 		return(0);
    256 	}
    257         hex_print(ident,cp,len);
    258 	return(1); /* everything is ok */
    259 }
    260 
    261 /*
    262  * Convert a token value to a string; use "fmt" if not found.
    263  */
    264 const char *
    265 tok2strbuf(register const struct tok *lp, register const char *fmt,
    266 	   register int v, char *buf, size_t bufsize)
    267 {
    268 	if (lp != NULL) {
    269 		while (lp->s != NULL) {
    270 			if (lp->v == v)
    271 				return (lp->s);
    272 			++lp;
    273 		}
    274 	}
    275 	if (fmt == NULL)
    276 		fmt = "#%d";
    277 
    278 	(void)snprintf(buf, bufsize, fmt, v);
    279 	return (const char *)buf;
    280 }
    281 
    282 /*
    283  * Convert a token value to a string; use "fmt" if not found.
    284  */
    285 const char *
    286 tok2str(register const struct tok *lp, register const char *fmt,
    287 	register int v)
    288 {
    289 	static char buf[4][128];
    290 	static int idx = 0;
    291 	char *ret;
    292 
    293 	ret = buf[idx];
    294 	idx = (idx+1) & 3;
    295 	return tok2strbuf(lp, fmt, v, ret, sizeof(buf[0]));
    296 }
    297 
    298 /*
    299  * Convert a bit token value to a string; use "fmt" if not found.
    300  * this is useful for parsing bitfields, the output strings are comma seperated
    301  */
    302 char *
    303 bittok2str(register const struct tok *lp, register const char *fmt,
    304 	   register int v)
    305 {
    306         static char buf[256]; /* our stringbuffer */
    307         int buflen=0;
    308         register int rotbit; /* this is the bit we rotate through all bitpositions */
    309         register int tokval;
    310 
    311 	while (lp->s != NULL && lp != NULL) {
    312             tokval=lp->v;   /* load our first value */
    313             rotbit=1;
    314             while (rotbit != 0) {
    315                 /*
    316                  * lets AND the rotating bit with our token value
    317                  * and see if we have got a match
    318                  */
    319 		if (tokval == (v&rotbit)) {
    320                     /* ok we have found something */
    321                     buflen+=snprintf(buf+buflen, sizeof(buf)-buflen, "%s, ",lp->s);
    322                     break;
    323                 }
    324                 rotbit=rotbit<<1; /* no match - lets shift and try again */
    325             }
    326             lp++;
    327 	}
    328 
    329         if (buflen != 0) { /* did we find anything */
    330             /* yep, set the the trailing zero 2 bytes before to eliminate the last comma & whitespace */
    331             buf[buflen-2] = '\0';
    332             return (buf);
    333         }
    334         else {
    335             /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
    336             if (fmt == NULL)
    337 		fmt = "#%d";
    338             (void)snprintf(buf, sizeof(buf), fmt, v);
    339             return (buf);
    340         }
    341 }
    342 
    343 /*
    344  * Convert a value to a string using an array; the macro
    345  * tok2strary() in <interface.h> is the public interface to
    346  * this function and ensures that the second argument is
    347  * correct for bounds-checking.
    348  */
    349 const char *
    350 tok2strary_internal(register const char **lp, int n, register const char *fmt,
    351 	register int v)
    352 {
    353 	static char buf[128];
    354 
    355 	if (v >= 0 && v < n && lp[v] != NULL)
    356 		return lp[v];
    357 	if (fmt == NULL)
    358 		fmt = "#%d";
    359 	(void)snprintf(buf, sizeof(buf), fmt, v);
    360 	return (buf);
    361 }
    362 
    363 /*
    364  * Convert a 32-bit netmask to prefixlen if possible
    365  * the function returns the prefix-len; if plen == -1
    366  * then conversion was not possible;
    367  */
    368 
    369 int
    370 mask2plen (u_int32_t mask)
    371 {
    372 	u_int32_t bitmasks[33] = {
    373 		0x00000000,
    374 		0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
    375 		0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
    376 		0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
    377 		0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
    378 		0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
    379 		0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
    380 		0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
    381 		0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
    382 	};
    383 	int prefix_len = 32;
    384 
    385 	/* let's see if we can transform the mask into a prefixlen */
    386 	while (prefix_len >= 0) {
    387 		if (bitmasks[prefix_len] == mask)
    388 			break;
    389 		prefix_len--;
    390 	}
    391 	return (prefix_len);
    392 }
    393 
    394 /* VARARGS */
    395 void
    396 error(const char *fmt, ...)
    397 {
    398 	va_list ap;
    399 
    400 	(void)fprintf(stderr, "%s: ", program_name);
    401 	va_start(ap, fmt);
    402 	(void)vfprintf(stderr, fmt, ap);
    403 	va_end(ap);
    404 	if (*fmt) {
    405 		fmt += strlen(fmt);
    406 		if (fmt[-1] != '\n')
    407 			(void)fputc('\n', stderr);
    408 	}
    409 	exit(1);
    410 	/* NOTREACHED */
    411 }
    412 
    413 /* VARARGS */
    414 void
    415 warning(const char *fmt, ...)
    416 {
    417 	va_list ap;
    418 
    419 	(void)fprintf(stderr, "%s: WARNING: ", program_name);
    420 	va_start(ap, fmt);
    421 	(void)vfprintf(stderr, fmt, ap);
    422 	va_end(ap);
    423 	if (*fmt) {
    424 		fmt += strlen(fmt);
    425 		if (fmt[-1] != '\n')
    426 			(void)fputc('\n', stderr);
    427 	}
    428 }
    429 
    430 /*
    431  * Copy arg vector into a new buffer, concatenating arguments with spaces.
    432  */
    433 char *
    434 copy_argv(register char **argv)
    435 {
    436 	register char **p;
    437 	register u_int len = 0;
    438 	char *buf;
    439 	char *src, *dst;
    440 
    441 	p = argv;
    442 	if (*p == 0)
    443 		return 0;
    444 
    445 	while (*p)
    446 		len += strlen(*p++) + 1;
    447 
    448 	buf = (char *)malloc(len);
    449 	if (buf == NULL)
    450 		error("copy_argv: malloc");
    451 
    452 	p = argv;
    453 	dst = buf;
    454 	while ((src = *p++) != NULL) {
    455 		while ((*dst++ = *src++) != '\0')
    456 			;
    457 		dst[-1] = ' ';
    458 	}
    459 	dst[-1] = '\0';
    460 
    461 	return buf;
    462 }
    463 
    464 /*
    465  * On Windows, we need to open the file in binary mode, so that
    466  * we get all the bytes specified by the size we get from "fstat()".
    467  * On UNIX, that's not necessary.  O_BINARY is defined on Windows;
    468  * we define it as 0 if it's not defined, so it does nothing.
    469  */
    470 #ifndef O_BINARY
    471 #define O_BINARY	0
    472 #endif
    473 
    474 char *
    475 read_infile(char *fname)
    476 {
    477 	register int i, fd, cc;
    478 	register char *cp;
    479 	struct stat buf;
    480 
    481 	fd = open(fname, O_RDONLY|O_BINARY);
    482 	if (fd < 0)
    483 		error("can't open %s: %s", fname, pcap_strerror(errno));
    484 
    485 	if (fstat(fd, &buf) < 0)
    486 		error("can't stat %s: %s", fname, pcap_strerror(errno));
    487 
    488 	cp = malloc((u_int)buf.st_size + 1);
    489 	if (cp == NULL)
    490 		error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1,
    491 			fname, pcap_strerror(errno));
    492 	cc = read(fd, cp, (u_int)buf.st_size);
    493 	if (cc < 0)
    494 		error("read %s: %s", fname, pcap_strerror(errno));
    495 	if (cc != buf.st_size)
    496 		error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
    497 
    498 	close(fd);
    499 	/* replace "# comment" with spaces */
    500 	for (i = 0; i < cc; i++) {
    501 		if (cp[i] == '#')
    502 			while (i < cc && cp[i] != '\n')
    503 				cp[i++] = ' ';
    504 	}
    505 	cp[cc] = '\0';
    506 	return (cp);
    507 }
    508 
    509 void
    510 safeputs(const char *s, int maxlen)
    511 {
    512     int idx = 0;
    513 	while (*s && idx < maxlen) {
    514 		safeputchar(*s);
    515                 idx++;
    516 		s++;
    517 	}
    518 }
    519 
    520 void
    521 safeputchar(int c)
    522 {
    523 	unsigned char ch;
    524 
    525 	ch = (unsigned char)(c & 0xff);
    526 	if (ch < 0x80 && isprint(ch))
    527 		printf("%c", ch);
    528 	else
    529 		printf("\\%03o", ch);
    530 }
    531