]>
The Tcpdump Group git mirrors - tcpdump/blob - util.c
2 * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3 * The Regents of the University of California. All rights reserved.
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
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.
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)";
31 #include <tcpdump-stdinc.h>
45 #include "interface.h"
47 char * ts_format(register int, register int);
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.
55 fn_print(register const u_char
*s
, register const u_char
*ep
)
60 ret
= 1; /* assume truncated */
61 while (ep
== NULL
|| s
< ep
) {
73 c
^= 0x40; /* DEL to ?, others to alpha */
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.
87 fn_printn(register const u_char
*s
, register u_int n
,
88 register const u_char
*ep
)
92 while (n
> 0 && (ep
== NULL
|| s
< ep
)) {
101 c
^= 0x40; /* DEL to ?, others to alpha */
106 return (n
== 0) ? 0 : 1;
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.
115 fn_printzp(register const u_char
*s
, register u_int n
,
116 register const u_char
*ep
)
121 ret
= 1; /* assume truncated */
122 while (n
> 0 && (ep
== NULL
|| s
< ep
)) {
135 c
^= 0x40; /* DEL to ?, others to alpha */
140 return (n
== 0) ? 0 : ret
;
144 * Format the timestamp
147 ts_format(register int sec
, register int usec
)
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
);
157 * Print the timestamp
160 ts_print(register const struct timeval
*tvp
)
165 static unsigned b_sec
;
166 static unsigned b_usec
;
170 case 0: /* Default */
171 s
= (tvp
->tv_sec
+ thiszone
) % 86400;
172 (void)printf("%s ", ts_format(s
, tvp
->tv_usec
));
175 case 1: /* No time stamp */
178 case 2: /* Unix timeval style */
179 (void)printf("%u.%06u ",
180 (unsigned)tvp
->tv_sec
,
181 (unsigned)tvp
->tv_usec
);
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
;
192 int d_usec
= tvp
->tv_usec
- b_usec
;
193 int d_sec
= tvp
->tv_sec
- b_sec
;
200 (void)printf("%s ", ts_format(d_sec
, d_usec
));
202 if (tflag
== 3) { /* set timestamp for last packet */
204 b_usec
= tvp
->tv_usec
;
208 case 4: /* Default + Date*/
209 s
= (tvp
->tv_sec
+ thiszone
) % 86400;
210 Time
= (tvp
->tv_sec
+ thiszone
) - s
;
213 printf("Date fail ");
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
));
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.
228 relts_print(int secs
)
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
;
245 (void)printf("%d%s", secs
/ *s
, *l
);
246 secs
-= (secs
/ *s
) * *s
;
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
260 print_unknown_data(const u_char
*cp
,const char *ident
,int len
)
263 printf("%sDissector error: print_unknown_data called with negative length",
267 if (snapend
- cp
< len
)
270 printf("%sDissector error: print_unknown_data called with pointer past end of packet",
274 hex_print(ident
,cp
,len
);
275 return(1); /* everything is ok */
279 * Convert a token value to a string; use "fmt" if not found.
282 tok2strbuf(register const struct tok
*lp
, register const char *fmt
,
283 register int v
, char *buf
, size_t bufsize
)
286 while (lp
->s
!= NULL
) {
295 (void)snprintf(buf
, bufsize
, fmt
, v
);
296 return (const char *)buf
;
300 * Convert a token value to a string; use "fmt" if not found.
303 tok2str(register const struct tok
*lp
, register const char *fmt
,
306 static char buf
[4][128];
312 return tok2strbuf(lp
, fmt
, v
, ret
, sizeof(buf
[0]));
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
320 bittok2str(register const struct tok
*lp
, register const char *fmt
,
323 static char buf
[256]; /* our stringbuffer */
325 register int rotbit
; /* this is the bit we rotate through all bitpositions */
328 while (lp
->s
!= NULL
&& lp
!= NULL
) {
329 tokval
=lp
->v
; /* load our first value */
331 while (rotbit
!= 0) {
333 * lets AND the rotating bit with our token value
334 * and see if we have got a match
336 if (tokval
== (v
&rotbit
)) {
337 /* ok we have found something */
338 buflen
+=snprintf(buf
+buflen
, sizeof(buf
)-buflen
, "%s, ",lp
->s
);
341 rotbit
=rotbit
<<1; /* no match - lets shift and try again */
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';
352 /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
355 (void)snprintf(buf
, sizeof(buf
), fmt
, v
);
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.
367 tok2strary_internal(register const char **lp
, int n
, register const char *fmt
,
370 static char buf
[128];
372 if (v
>= 0 && v
< n
&& lp
[v
] != NULL
)
376 (void)snprintf(buf
, sizeof(buf
), fmt
, v
);
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;
387 mask2plen (u_int32_t mask
)
389 u_int32_t bitmasks
[33] = {
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
402 /* let's see if we can transform the mask into a prefixlen */
403 while (prefix_len
>= 0) {
404 if (bitmasks
[prefix_len
] == mask
)
413 error(const char *fmt
, ...)
417 (void)fprintf(stderr
, "%s: ", program_name
);
419 (void)vfprintf(stderr
, fmt
, ap
);
424 (void)fputc('\n', stderr
);
432 warning(const char *fmt
, ...)
436 (void)fprintf(stderr
, "%s: WARNING: ", program_name
);
438 (void)vfprintf(stderr
, fmt
, ap
);
443 (void)fputc('\n', stderr
);
448 * Copy arg vector into a new buffer, concatenating arguments with spaces.
451 copy_argv(register char **argv
)
454 register u_int len
= 0;
463 len
+= strlen(*p
++) + 1;
465 buf
= (char *)malloc(len
);
467 error("copy_argv: malloc");
471 while ((src
= *p
++) != NULL
) {
472 while ((*dst
++ = *src
++) != '\0')
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.
492 read_infile(char *fname
)
494 register int i
, fd
, cc
;
498 fd
= open(fname
, O_RDONLY
|O_BINARY
);
500 error("can't open %s: %s", fname
, pcap_strerror(errno
));
502 if (fstat(fd
, &buf
) < 0)
503 error("can't stat %s: %s", fname
, pcap_strerror(errno
));
505 cp
= malloc((u_int
)buf
.st_size
+ 1);
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
);
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
);
516 /* replace "# comment" with spaces */
517 for (i
= 0; i
< cc
; i
++) {
519 while (i
< cc
&& cp
[i
] != '\n')
527 safeputs(const char *s
)
540 ch
= (unsigned char)(c
& 0xff);
541 if (ch
< 0x80 && isprint(ch
))
544 printf("\\%03o", ch
);