• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
fn_print(register const u_char * s,register const u_char * ep)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
fn_printn(register const u_char * s,register u_int n,register const u_char * ep)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
fn_printzp(register const u_char * s,register u_int n,register const u_char * ep)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
ts_print(register const struct timeval * tvp)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
relts_print(int secs)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
print_unknown_data(const u_char * cp,const char * ident,int len)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 *
tok2strbuf(register const struct tok * lp,register const char * fmt,register int v,char * buf,size_t bufsize)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 *
tok2str(register const struct tok * lp,register const char * fmt,register int v)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 *
bittok2str(register const struct tok * lp,register const char * fmt,register int v)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 *
tok2strary_internal(register const char ** lp,int n,register const char * fmt,register int v)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
mask2plen(u_int32_t mask)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
error(const char * fmt,...)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
warning(const char * fmt,...)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 *
copy_argv(register char ** argv)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 *
read_infile(char * fname)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
safeputs(const char * s,int maxlen)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
safeputchar(int c)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