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