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