Expand PMF_FN_* macros.
[netbsd-mini2440.git] / dist / tcpdump / util.c
blob4d4ca51aa825b38f030fbfd4baa9edd74267082e
1 /* $NetBSD$ */
3 /*
4 * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that: (1) source code distributions
9 * retain the above copyright notice and this paragraph in its entirety, (2)
10 * distributions including binary code include the above copyright notice and
11 * this paragraph in its entirety in the documentation or other materials
12 * provided with the distribution, and (3) all advertising materials mentioning
13 * features or use of this software display the following acknowledgement:
14 * ``This product includes software developed by the University of California,
15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16 * the University nor the names of its contributors may be used to endorse
17 * or promote products derived from this software without specific prior
18 * written permission.
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
24 #include <sys/cdefs.h>
25 #ifndef lint
26 #if 0
27 static const char rcsid[] _U_ =
28 "@(#) Header: /tcpdump/master/tcpdump/util.c,v 1.95.2.6 2006/02/08 01:40:09 hannes Exp (LBL)";
29 #else
30 __RCSID("$NetBSD: tcpdump2rcsid.ex,v 1.1 2001/06/25 20:09:58 itojun Exp $");
31 #endif
32 #endif
34 #ifdef HAVE_CONFIG_H
35 #include "config.h"
36 #endif
38 #include <tcpdump-stdinc.h>
40 #include <sys/stat.h>
42 #include <errno.h>
43 #ifdef HAVE_FCNTL_H
44 #include <fcntl.h>
45 #endif
46 #include <pcap.h>
47 #include <stdio.h>
48 #include <stdarg.h>
49 #include <stdlib.h>
50 #include <string.h>
52 #include "interface.h"
55 * Print out a null-terminated filename (or other ascii string).
56 * If ep is NULL, assume no truncation check is needed.
57 * Return true if truncated.
59 int
60 fn_print(register const u_char *s, register const u_char *ep)
62 register int ret;
63 register u_char c;
65 ret = 1; /* assume truncated */
66 while (ep == NULL || s < ep) {
67 c = *s++;
68 if (c == '\0') {
69 ret = 0;
70 break;
72 if (!isascii(c)) {
73 c = toascii(c);
74 putchar('M');
75 putchar('-');
77 if (!isprint(c)) {
78 c ^= 0x40; /* DEL to ?, others to alpha */
79 putchar('^');
81 putchar(c);
83 return(ret);
87 * Print out a counted filename (or other ascii string).
88 * If ep is NULL, assume no truncation check is needed.
89 * Return true if truncated.
91 int
92 fn_printn(register const u_char *s, register u_int n,
93 register const u_char *ep)
95 register u_char c;
97 while (n > 0 && (ep == NULL || s < ep)) {
98 n--;
99 c = *s++;
100 if (!isascii(c)) {
101 c = toascii(c);
102 putchar('M');
103 putchar('-');
105 if (!isprint(c)) {
106 c ^= 0x40; /* DEL to ?, others to alpha */
107 putchar('^');
109 putchar(c);
111 return (n == 0) ? 0 : 1;
115 * Print out a null-padded filename (or other ascii string).
116 * If ep is NULL, assume no truncation check is needed.
117 * Return true if truncated.
120 fn_printzp(register const u_char *s, register u_int n,
121 register const u_char *ep)
123 register int ret;
124 register u_char c;
126 ret = 1; /* assume truncated */
127 while (n > 0 && (ep == NULL || s < ep)) {
128 n--;
129 c = *s++;
130 if (c == '\0') {
131 ret = 0;
132 break;
134 if (!isascii(c)) {
135 c = toascii(c);
136 putchar('M');
137 putchar('-');
139 if (!isprint(c)) {
140 c ^= 0x40; /* DEL to ?, others to alpha */
141 putchar('^');
143 putchar(c);
145 return (n == 0) ? 0 : ret;
149 * Print the timestamp
151 void
152 ts_print(register const struct timeval *tvp)
154 register int s;
155 struct tm *tm;
156 time_t Time;
157 static unsigned b_sec;
158 static unsigned b_usec;
160 switch (tflag) {
162 case 0: /* Default */
163 s = (tvp->tv_sec + thiszone) % 86400;
164 (void)printf("%02d:%02d:%02d.%06u ",
165 s / 3600, (s % 3600) / 60, s % 60,
166 (unsigned)tvp->tv_usec);
167 break;
169 case 1: /* No time stamp */
170 break;
172 case 2: /* Unix timeval style */
173 (void)printf("%u.%06u ",
174 (unsigned)tvp->tv_sec,
175 (unsigned)tvp->tv_usec);
176 break;
178 case 3: /* Microseconds since previous packet */
179 if (b_sec == 0) {
180 printf("000000 ");
181 } else {
182 int d_usec = tvp->tv_usec - b_usec;
183 int d_sec = tvp->tv_sec - b_sec;
185 while (d_usec < 0) {
186 d_usec += 1000000;
187 d_sec--;
189 if (d_sec)
190 printf("%d. ", d_sec);
191 printf("%06d ", d_usec);
193 b_sec = tvp->tv_sec;
194 b_usec = tvp->tv_usec;
195 break;
197 case 4: /* Default + Date*/
198 s = (tvp->tv_sec + thiszone) % 86400;
199 Time = (tvp->tv_sec + thiszone) - s;
200 tm = gmtime (&Time);
201 if (!tm)
202 printf("Date fail ");
203 else
204 printf("%04d-%02d-%02d ",
205 tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
206 printf("%02d:%02d:%02d.%06u ",
207 s / 3600, (s % 3600) / 60, s % 60, (unsigned)tvp->tv_usec);
208 break;
213 * Print a relative number of seconds (e.g. hold time, prune timer)
214 * in the form 5m1s. This does no truncation, so 32230861 seconds
215 * is represented as 1y1w1d1h1m1s.
217 void
218 relts_print(int secs)
220 static const char *lengths[] = {"y", "w", "d", "h", "m", "s"};
221 static const int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
222 const char **l = lengths;
223 const int *s = seconds;
225 if (secs == 0) {
226 (void)printf("0s");
227 return;
229 if (secs < 0) {
230 (void)printf("-");
231 secs = -secs;
233 while (secs > 0) {
234 if (secs >= *s) {
235 (void)printf("%d%s", secs / *s, *l);
236 secs -= (secs / *s) * *s;
238 s++;
239 l++;
244 * this is a generic routine for printing unknown data;
245 * we pass on the linefeed plus indentation string to
246 * get a proper output - returns 0 on error
250 print_unknown_data(const u_char *cp,const char *ident,int len)
252 if (len < 0) {
253 printf("%sDissector error: print_unknown_data called with negative length",
254 ident);
255 return(0);
257 if (snapend - cp < len)
258 len = snapend - cp;
259 if (len < 0) {
260 printf("%sDissector error: print_unknown_data called with pointer past end of packet",
261 ident);
262 return(0);
264 hex_print(ident,cp,len);
265 return(1); /* everything is ok */
269 * Convert a token value to a string; use "fmt" if not found.
271 const char *
272 tok2strbuf(register const struct tok *lp, register const char *fmt,
273 register int v, char *buf, size_t bufsize)
275 if (lp != NULL) {
276 while (lp->s != NULL) {
277 if (lp->v == v)
278 return (lp->s);
279 ++lp;
282 if (fmt == NULL)
283 fmt = "#%d";
285 (void)snprintf(buf, bufsize, fmt, v);
286 return (const char *)buf;
290 * Convert a token value to a string; use "fmt" if not found.
292 const char *
293 tok2str(register const struct tok *lp, register const char *fmt,
294 register int v)
296 static char buf[4][128];
297 static int idx = 0;
298 char *ret;
300 ret = buf[idx];
301 idx = (idx+1) & 3;
302 return tok2strbuf(lp, fmt, v, ret, sizeof(buf[0]));
306 * Convert a bit token value to a string; use "fmt" if not found.
307 * this is useful for parsing bitfields, the output strings are comma seperated
309 char *
310 bittok2str(register const struct tok *lp, register const char *fmt,
311 register int v)
313 static char buf[256]; /* our stringbuffer */
314 int buflen=0;
315 register int rotbit; /* this is the bit we rotate through all bitpositions */
316 register int tokval;
318 while (lp->s != NULL && lp != NULL) {
319 tokval=lp->v; /* load our first value */
320 rotbit=1;
321 while (rotbit != 0) {
323 * lets AND the rotating bit with our token value
324 * and see if we have got a match
326 if (tokval == (v&rotbit)) {
327 /* ok we have found something */
328 buflen+=snprintf(buf+buflen, sizeof(buf)-buflen, "%s, ",lp->s);
329 break;
331 rotbit=rotbit<<1; /* no match - lets shift and try again */
333 lp++;
336 if (buflen != 0) { /* did we find anything */
337 /* yep, set the the trailing zero 2 bytes before to eliminate the last comma & whitespace */
338 buf[buflen-2] = '\0';
339 return (buf);
341 else {
342 /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
343 if (fmt == NULL)
344 fmt = "#%d";
345 (void)snprintf(buf, sizeof(buf), fmt, v);
346 return (buf);
351 * Convert a value to a string using an array; the macro
352 * tok2strary() in <interface.h> is the public interface to
353 * this function and ensures that the second argument is
354 * correct for bounds-checking.
356 const char *
357 tok2strary_internal(register const char **lp, int n, register const char *fmt,
358 register int v)
360 static char buf[128];
362 if (v >= 0 && v < n && lp[v] != NULL)
363 return lp[v];
364 if (fmt == NULL)
365 fmt = "#%d";
366 (void)snprintf(buf, sizeof(buf), fmt, v);
367 return (buf);
371 * Convert a 32-bit netmask to prefixlen if possible
372 * the function returns the prefix-len; if plen == -1
373 * then conversion was not possible;
377 mask2plen (u_int32_t mask)
379 u_int32_t bitmasks[33] = {
380 0x00000000,
381 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
382 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
383 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
384 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
385 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
386 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
387 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
388 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
390 int prefix_len = 32;
392 /* let's see if we can transform the mask into a prefixlen */
393 while (prefix_len >= 0) {
394 if (bitmasks[prefix_len] == mask)
395 break;
396 prefix_len--;
398 return (prefix_len);
401 /* VARARGS */
402 void
403 error(const char *fmt, ...)
405 va_list ap;
407 (void)fprintf(stderr, "%s: ", program_name);
408 va_start(ap, fmt);
409 (void)vfprintf(stderr, fmt, ap);
410 va_end(ap);
411 if (*fmt) {
412 fmt += strlen(fmt);
413 if (fmt[-1] != '\n')
414 (void)fputc('\n', stderr);
416 exit(1);
417 /* NOTREACHED */
420 /* VARARGS */
421 void
422 warning(const char *fmt, ...)
424 va_list ap;
426 (void)fprintf(stderr, "%s: WARNING: ", program_name);
427 va_start(ap, fmt);
428 (void)vfprintf(stderr, fmt, ap);
429 va_end(ap);
430 if (*fmt) {
431 fmt += strlen(fmt);
432 if (fmt[-1] != '\n')
433 (void)fputc('\n', stderr);
438 * Copy arg vector into a new buffer, concatenating arguments with spaces.
440 char *
441 copy_argv(register char **argv)
443 register char **p;
444 register u_int len = 0;
445 char *buf;
446 char *src, *dst;
448 p = argv;
449 if (*p == 0)
450 return 0;
452 while (*p)
453 len += strlen(*p++) + 1;
455 buf = (char *)malloc(len);
456 if (buf == NULL)
457 error("copy_argv: malloc");
459 p = argv;
460 dst = buf;
461 while ((src = *p++) != NULL) {
462 while ((*dst++ = *src++) != '\0')
464 dst[-1] = ' ';
466 dst[-1] = '\0';
468 return buf;
472 * On Windows, we need to open the file in binary mode, so that
473 * we get all the bytes specified by the size we get from "fstat()".
474 * On UNIX, that's not necessary. O_BINARY is defined on Windows;
475 * we define it as 0 if it's not defined, so it does nothing.
477 #ifndef O_BINARY
478 #define O_BINARY 0
479 #endif
481 char *
482 read_infile(char *fname)
484 register int i, fd, cc;
485 register char *cp;
486 struct stat buf;
488 fd = open(fname, O_RDONLY|O_BINARY);
489 if (fd < 0)
490 error("can't open %s: %s", fname, pcap_strerror(errno));
492 if (fstat(fd, &buf) < 0)
493 error("can't stat %s: %s", fname, pcap_strerror(errno));
495 cp = malloc((u_int)buf.st_size + 1);
496 if (cp == NULL)
497 error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1,
498 fname, pcap_strerror(errno));
499 cc = read(fd, cp, (u_int)buf.st_size);
500 if (cc < 0)
501 error("read %s: %s", fname, pcap_strerror(errno));
502 if (cc != buf.st_size)
503 error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
505 close(fd);
506 /* replace "# comment" with spaces */
507 for (i = 0; i < cc; i++) {
508 if (cp[i] == '#')
509 while (i < cc && cp[i] != '\n')
510 cp[i++] = ' ';
512 cp[cc] = '\0';
513 return (cp);
516 void
517 safeputs(const char *s, int maxlen)
519 int idx = 0;
520 while (*s && idx < maxlen) {
521 safeputchar(*s);
522 idx++;
523 s++;
527 void
528 safeputchar(int c)
530 unsigned char ch;
532 ch = (unsigned char)(c & 0xff);
533 if (ch < 0x80 && isprint(ch))
534 printf("%c", ch);
535 else
536 printf("\\%03o", ch);