Upgrade to tcpdump-4.0.0.
[dragonfly.git] / contrib / 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.109 2007-01-29 09:59:42 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 seperated
320  * if the s field is positive.
321  */
322 static char *
323 bittok2str_internal(register const struct tok *lp, register const char *fmt,
324            register int v, register int sep)
325 {
326         static char buf[256]; /* our stringbuffer */
327         int buflen=0;
328         register int rotbit; /* this is the bit we rotate through all bitpositions */
329         register int tokval;
330
331         while (lp->s != NULL && lp != NULL) {
332             tokval=lp->v;   /* load our first value */
333             rotbit=1;
334             while (rotbit != 0) {
335                 /*
336                  * lets AND the rotating bit with our token value
337                  * and see if we have got a match
338                  */
339                 if (tokval == (v&rotbit)) {
340                     /* ok we have found something */
341                     buflen+=snprintf(buf+buflen, sizeof(buf)-buflen, "%s%s",
342                                      lp->s, sep ? ", " : "");
343                     break;
344                 }
345                 rotbit=rotbit<<1; /* no match - lets shift and try again */
346             }
347             lp++;
348         }
349
350         /* user didn't want string seperation - no need to cut off trailing seperators */
351         if (!sep) {
352             return (buf);
353         }
354
355         if (buflen != 0) { /* did we find anything */
356             /* yep, set the the trailing zero 2 bytes before to eliminate the last comma & whitespace */
357             buf[buflen-2] = '\0';
358             return (buf);
359         }
360         else {
361             /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
362             if (fmt == NULL)
363                 fmt = "#%d";
364             (void)snprintf(buf, sizeof(buf), fmt, v);
365             return (buf);
366         }
367 }
368
369 /*
370  * Convert a bit token value to a string; use "fmt" if not found.
371  * this is useful for parsing bitfields, the output strings are not seperated.
372  */
373 char *
374 bittok2str_nosep(register const struct tok *lp, register const char *fmt,
375            register int v)
376 {
377     return (bittok2str_internal(lp, fmt, v, 0));
378 }
379
380 /*
381  * Convert a bit token value to a string; use "fmt" if not found.
382  * this is useful for parsing bitfields, the output strings are comma seperated.
383  */
384 char *
385 bittok2str(register const struct tok *lp, register const char *fmt,
386            register int v)
387 {
388     return (bittok2str_internal(lp, fmt, v, 1));
389 }
390
391 /*
392  * Convert a value to a string using an array; the macro
393  * tok2strary() in <interface.h> is the public interface to
394  * this function and ensures that the second argument is
395  * correct for bounds-checking.
396  */
397 const char *
398 tok2strary_internal(register const char **lp, int n, register const char *fmt,
399         register int v)
400 {
401         static char buf[128];
402
403         if (v >= 0 && v < n && lp[v] != NULL)
404                 return lp[v];
405         if (fmt == NULL)
406                 fmt = "#%d";
407         (void)snprintf(buf, sizeof(buf), fmt, v);
408         return (buf);
409 }
410
411 /*
412  * Convert a 32-bit netmask to prefixlen if possible
413  * the function returns the prefix-len; if plen == -1
414  * then conversion was not possible;
415  */
416
417 int
418 mask2plen (u_int32_t mask)
419 {
420         u_int32_t bitmasks[33] = {
421                 0x00000000,
422                 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
423                 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
424                 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
425                 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
426                 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
427                 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
428                 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
429                 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
430         };
431         int prefix_len = 32;
432
433         /* let's see if we can transform the mask into a prefixlen */
434         while (prefix_len >= 0) {
435                 if (bitmasks[prefix_len] == mask)
436                         break;
437                 prefix_len--;
438         }
439         return (prefix_len);
440 }
441
442 /* VARARGS */
443 void
444 error(const char *fmt, ...)
445 {
446         va_list ap;
447
448         (void)fprintf(stderr, "%s: ", program_name);
449         va_start(ap, fmt);
450         (void)vfprintf(stderr, fmt, ap);
451         va_end(ap);
452         if (*fmt) {
453                 fmt += strlen(fmt);
454                 if (fmt[-1] != '\n')
455                         (void)fputc('\n', stderr);
456         }
457         exit(1);
458         /* NOTREACHED */
459 }
460
461 /* VARARGS */
462 void
463 warning(const char *fmt, ...)
464 {
465         va_list ap;
466
467         (void)fprintf(stderr, "%s: WARNING: ", program_name);
468         va_start(ap, fmt);
469         (void)vfprintf(stderr, fmt, ap);
470         va_end(ap);
471         if (*fmt) {
472                 fmt += strlen(fmt);
473                 if (fmt[-1] != '\n')
474                         (void)fputc('\n', stderr);
475         }
476 }
477
478 /*
479  * Copy arg vector into a new buffer, concatenating arguments with spaces.
480  */
481 char *
482 copy_argv(register char **argv)
483 {
484         register char **p;
485         register u_int len = 0;
486         char *buf;
487         char *src, *dst;
488
489         p = argv;
490         if (*p == 0)
491                 return 0;
492
493         while (*p)
494                 len += strlen(*p++) + 1;
495
496         buf = (char *)malloc(len);
497         if (buf == NULL)
498                 error("copy_argv: malloc");
499
500         p = argv;
501         dst = buf;
502         while ((src = *p++) != NULL) {
503                 while ((*dst++ = *src++) != '\0')
504                         ;
505                 dst[-1] = ' ';
506         }
507         dst[-1] = '\0';
508
509         return buf;
510 }
511
512 /*
513  * On Windows, we need to open the file in binary mode, so that
514  * we get all the bytes specified by the size we get from "fstat()".
515  * On UNIX, that's not necessary.  O_BINARY is defined on Windows;
516  * we define it as 0 if it's not defined, so it does nothing.
517  */
518 #ifndef O_BINARY
519 #define O_BINARY        0
520 #endif
521
522 char *
523 read_infile(char *fname)
524 {
525         register int i, fd, cc;
526         register char *cp;
527         struct stat buf;
528
529         fd = open(fname, O_RDONLY|O_BINARY);
530         if (fd < 0)
531                 error("can't open %s: %s", fname, pcap_strerror(errno));
532
533         if (fstat(fd, &buf) < 0)
534                 error("can't stat %s: %s", fname, pcap_strerror(errno));
535
536         cp = malloc((u_int)buf.st_size + 1);
537         if (cp == NULL)
538                 error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1,
539                         fname, pcap_strerror(errno));
540         cc = read(fd, cp, (u_int)buf.st_size);
541         if (cc < 0)
542                 error("read %s: %s", fname, pcap_strerror(errno));
543         if (cc != buf.st_size)
544                 error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
545
546         close(fd);
547         /* replace "# comment" with spaces */
548         for (i = 0; i < cc; i++) {
549                 if (cp[i] == '#')
550                         while (i < cc && cp[i] != '\n')
551                                 cp[i++] = ' ';
552         }
553         cp[cc] = '\0';
554         return (cp);
555 }
556
557 void
558 safeputs(const char *s, int maxlen)
559 {
560         int idx = 0;
561
562         while (*s && idx < maxlen) {
563                 safeputchar(*s);
564                 idx++;
565                 s++;
566         }
567 }
568
569 void
570 safeputchar(int c)
571 {
572         unsigned char ch;
573
574         ch = (unsigned char)(c & 0xff);
575         if (ch < 0x80 && isprint(ch))
576                 printf("%c", ch);
577         else
578                 printf("\\0x%02x", ch);
579 }