]>
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.
22 #define NETDISSECT_REWORKED
27 #include <tcpdump-stdinc.h>
39 #include "interface.h"
42 * Print out a null-terminated filename (or other ascii string).
43 * If ep is NULL, assume no truncation check is needed.
44 * Return true if truncated.
47 fn_print(netdissect_options
*ndo
,
48 register const u_char
*s
, register const u_char
*ep
)
53 ret
= 1; /* assume truncated */
54 while (ep
== NULL
|| s
< ep
) {
62 ND_PRINT((ndo
, "M-"));
65 c
^= 0x40; /* DEL to ?, others to alpha */
68 ND_PRINT((ndo
, "%c", c
));
74 * Print out a counted filename (or other ascii string).
75 * If ep is NULL, assume no truncation check is needed.
76 * Return true if truncated.
79 fn_printn(netdissect_options
*ndo
,
80 register const u_char
*s
, register u_int n
, register const u_char
*ep
)
84 while (n
> 0 && (ep
== NULL
|| s
< ep
)) {
89 ND_PRINT((ndo
, "M-"));
92 c
^= 0x40; /* DEL to ?, others to alpha */
95 ND_PRINT((ndo
, "%c", c
));
97 return (n
== 0) ? 0 : 1;
101 * Print out a null-padded filename (or other ascii string).
102 * If ep is NULL, assume no truncation check is needed.
103 * Return true if truncated.
106 fn_printzp(netdissect_options
*ndo
,
107 register const u_char
*s
, register u_int n
,
108 register const u_char
*ep
)
113 ret
= 1; /* assume truncated */
114 while (n
> 0 && (ep
== NULL
|| s
< ep
)) {
121 if (!ND_ISASCII(c
)) {
123 ND_PRINT((ndo
, "M-"));
125 if (!ND_ISPRINT(c
)) {
126 c
^= 0x40; /* DEL to ?, others to alpha */
127 ND_PRINT((ndo
, "^"));
129 ND_PRINT((ndo
, "%c", c
));
131 return (n
== 0) ? 0 : ret
;
135 * Format the timestamp
138 ts_format(register int sec
, register int usec
)
140 static char buf
[sizeof("00:00:00.000000")];
141 (void)snprintf(buf
, sizeof(buf
), "%02d:%02d:%02d.%06u",
142 sec
/ 3600, (sec
% 3600) / 60, sec
% 60, usec
);
148 * Print the timestamp
151 ts_print(netdissect_options
*ndo
,
152 register const struct timeval
*tvp
)
157 static unsigned b_sec
;
158 static unsigned b_usec
;
162 switch (ndo
->ndo_tflag
) {
164 case 0: /* Default */
165 s
= (tvp
->tv_sec
+ thiszone
) % 86400;
166 ND_PRINT((ndo
, "%s ", ts_format(s
, tvp
->tv_usec
)));
169 case 1: /* No time stamp */
172 case 2: /* Unix timeval style */
173 ND_PRINT((ndo
, "%u.%06u ",
174 (unsigned)tvp
->tv_sec
,
175 (unsigned)tvp
->tv_usec
));
178 case 3: /* Microseconds since previous packet */
179 case 5: /* Microseconds since first packet */
181 /* init timestamp for first packet */
182 b_usec
= tvp
->tv_usec
;
186 d_usec
= tvp
->tv_usec
- b_usec
;
187 d_sec
= tvp
->tv_sec
- b_sec
;
194 ND_PRINT((ndo
, "%s ", ts_format(d_sec
, d_usec
)));
196 if (ndo
->ndo_tflag
== 3) { /* set timestamp for last packet */
198 b_usec
= tvp
->tv_usec
;
202 case 4: /* Default + Date*/
203 s
= (tvp
->tv_sec
+ thiszone
) % 86400;
204 Time
= (tvp
->tv_sec
+ thiszone
) - s
;
207 ND_PRINT((ndo
, "Date fail "));
209 ND_PRINT((ndo
, "%04d-%02d-%02d %s ",
210 tm
->tm_year
+1900, tm
->tm_mon
+1, tm
->tm_mday
,
211 ts_format(s
, tvp
->tv_usec
)));
217 * Print a relative number of seconds (e.g. hold time, prune timer)
218 * in the form 5m1s. This does no truncation, so 32230861 seconds
219 * is represented as 1y1w1d1h1m1s.
222 relts_print(netdissect_options
*ndo
,
225 static const char *lengths
[] = {"y", "w", "d", "h", "m", "s"};
226 static const int seconds
[] = {31536000, 604800, 86400, 3600, 60, 1};
227 const char **l
= lengths
;
228 const int *s
= seconds
;
231 ND_PRINT((ndo
, "0s"));
235 ND_PRINT((ndo
, "-"));
240 ND_PRINT((ndo
, "%d%s", secs
/ *s
, *l
));
241 secs
-= (secs
/ *s
) * *s
;
249 * this is a generic routine for printing unknown data;
250 * we pass on the linefeed plus indentation string to
251 * get a proper output - returns 0 on error
255 print_unknown_data(netdissect_options
*ndo
, const u_char
*cp
,const char *ident
,int len
)
258 ND_PRINT((ndo
,"%sDissector error: print_unknown_data called with negative length",
262 if (ndo
->ndo_snapend
- cp
< len
)
263 len
= ndo
->ndo_snapend
- cp
;
265 ND_PRINT((ndo
,"%sDissector error: print_unknown_data called with pointer past end of packet",
269 hex_print(ndo
, ident
,cp
,len
);
270 return(1); /* everything is ok */
274 * Convert a token value to a string; use "fmt" if not found.
277 tok2strbuf(register const struct tok
*lp
, register const char *fmt
,
278 register u_int v
, char *buf
, size_t bufsize
)
281 while (lp
->s
!= NULL
) {
290 (void)snprintf(buf
, bufsize
, fmt
, v
);
291 return (const char *)buf
;
295 * Convert a token value to a string; use "fmt" if not found.
298 tok2str(register const struct tok
*lp
, register const char *fmt
,
301 static char buf
[4][128];
307 return tok2strbuf(lp
, fmt
, v
, ret
, sizeof(buf
[0]));
311 * Convert a bit token value to a string; use "fmt" if not found.
312 * this is useful for parsing bitfields, the output strings are seperated
313 * if the s field is positive.
316 bittok2str_internal(register const struct tok
*lp
, register const char *fmt
,
317 register int v
, register int sep
)
319 static char buf
[256]; /* our stringbuffer */
321 register int rotbit
; /* this is the bit we rotate through all bitpositions */
323 const char * sepstr
= "";
325 while (lp
!= NULL
&& lp
->s
!= NULL
) {
326 tokval
=lp
->v
; /* load our first value */
328 while (rotbit
!= 0) {
330 * lets AND the rotating bit with our token value
331 * and see if we have got a match
333 if (tokval
== (v
&rotbit
)) {
334 /* ok we have found something */
335 buflen
+=snprintf(buf
+buflen
, sizeof(buf
)-buflen
, "%s%s",
337 sepstr
= sep
? ", " : "";
340 rotbit
=rotbit
<<1; /* no match - lets shift and try again */
346 /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
347 (void)snprintf(buf
, sizeof(buf
), fmt
== NULL
? "#%d" : fmt
, v
);
352 * Convert a bit token value to a string; use "fmt" if not found.
353 * this is useful for parsing bitfields, the output strings are not seperated.
356 bittok2str_nosep(register const struct tok
*lp
, register const char *fmt
,
359 return (bittok2str_internal(lp
, fmt
, v
, 0));
363 * Convert a bit token value to a string; use "fmt" if not found.
364 * this is useful for parsing bitfields, the output strings are comma seperated.
367 bittok2str(register const struct tok
*lp
, register const char *fmt
,
370 return (bittok2str_internal(lp
, fmt
, v
, 1));
374 * Convert a value to a string using an array; the macro
375 * tok2strary() in <interface.h> is the public interface to
376 * this function and ensures that the second argument is
377 * correct for bounds-checking.
380 tok2strary_internal(register const char **lp
, int n
, register const char *fmt
,
383 static char buf
[128];
385 if (v
>= 0 && v
< n
&& lp
[v
] != NULL
)
389 (void)snprintf(buf
, sizeof(buf
), fmt
, v
);
394 * Convert a 32-bit netmask to prefixlen if possible
395 * the function returns the prefix-len; if plen == -1
396 * then conversion was not possible;
400 mask2plen(uint32_t mask
)
402 uint32_t bitmasks
[33] = {
404 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
405 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
406 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
407 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
408 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
409 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
410 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
411 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
415 /* let's see if we can transform the mask into a prefixlen */
416 while (prefix_len
>= 0) {
417 if (bitmasks
[prefix_len
] == mask
)
426 mask62plen(const u_char
*mask
)
428 u_char bitmasks
[9] = {
430 0x80, 0xc0, 0xe0, 0xf0,
431 0xf8, 0xfc, 0xfe, 0xff
436 for (byte
= 0; byte
< 16; byte
++) {
439 for (bits
= 0; bits
< (sizeof (bitmasks
) / sizeof (bitmasks
[0])); bits
++) {
440 if (mask
[byte
] == bitmasks
[bits
]) {
446 if (mask
[byte
] != 0xff)
455 error(const char *fmt
, ...)
459 (void)fprintf(stderr
, "%s: ", program_name
);
461 (void)vfprintf(stderr
, fmt
, ap
);
466 (void)fputc('\n', stderr
);
474 warning(const char *fmt
, ...)
478 (void)fprintf(stderr
, "%s: WARNING: ", program_name
);
480 (void)vfprintf(stderr
, fmt
, ap
);
485 (void)fputc('\n', stderr
);
490 * Copy arg vector into a new buffer, concatenating arguments with spaces.
493 copy_argv(register char **argv
)
496 register u_int len
= 0;
505 len
+= strlen(*p
++) + 1;
507 buf
= (char *)malloc(len
);
509 error("copy_argv: malloc");
513 while ((src
= *p
++) != NULL
) {
514 while ((*dst
++ = *src
++) != '\0')
524 * On Windows, we need to open the file in binary mode, so that
525 * we get all the bytes specified by the size we get from "fstat()".
526 * On UNIX, that's not necessary. O_BINARY is defined on Windows;
527 * we define it as 0 if it's not defined, so it does nothing.
534 read_infile(char *fname
)
536 register int i
, fd
, cc
;
540 fd
= open(fname
, O_RDONLY
|O_BINARY
);
542 error("can't open %s: %s", fname
, pcap_strerror(errno
));
544 if (fstat(fd
, &buf
) < 0)
545 error("can't stat %s: %s", fname
, pcap_strerror(errno
));
547 cp
= malloc((u_int
)buf
.st_size
+ 1);
549 error("malloc(%d) for %s: %s", (u_int
)buf
.st_size
+ 1,
550 fname
, pcap_strerror(errno
));
551 cc
= read(fd
, cp
, (u_int
)buf
.st_size
);
553 error("read %s: %s", fname
, pcap_strerror(errno
));
554 if (cc
!= buf
.st_size
)
555 error("short read %s (%d != %d)", fname
, cc
, (int)buf
.st_size
);
558 /* replace "# comment" with spaces */
559 for (i
= 0; i
< cc
; i
++) {
561 while (i
< cc
&& cp
[i
] != '\n')
569 safeputs(netdissect_options
*ndo
,
570 const u_char
*s
, const u_int maxlen
)
574 while (*s
&& idx
< maxlen
) {
575 safeputchar(ndo
, *s
);
582 safeputchar(netdissect_options
*ndo
,
585 ND_PRINT((ndo
, (c
< 0x80 && ND_ISPRINT(c
)) ? "%c" : "\\0x%02x", c
));
590 * Some compilers try to optimize memcpy(), using the alignment constraint
591 * on the argument pointer type. by using this function, we try to avoid the
595 unaligned_memcpy(void *p
, const void *q
, size_t l
)
600 /* As with memcpy(), so with memcmp(). */
602 unaligned_memcmp(const void *p
, const void *q
, size_t l
)
604 return (memcmp(p
, q
, l
));