]>
The Tcpdump Group git mirrors - tcpdump/blob - util.c
12a15023e6d2a6145aa22f508585e11eb624da26
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 */
324 while (lp
!= NULL
&& lp
->s
!= NULL
) {
325 tokval
=lp
->v
; /* load our first value */
327 while (rotbit
!= 0) {
329 * lets AND the rotating bit with our token value
330 * and see if we have got a match
332 if (tokval
== (v
&rotbit
)) {
333 /* ok we have found something */
334 buflen
+=snprintf(buf
+buflen
, sizeof(buf
)-buflen
, "%s%s",
335 lp
->s
, sep
? ", " : "");
338 rotbit
=rotbit
<<1; /* no match - lets shift and try again */
343 /* user didn't want string seperation - no need to cut off trailing seperators */
348 if (buflen
!= 0) { /* did we find anything */
349 /* yep, set the trailing zero 2 bytes before to eliminate the last comma & whitespace */
350 buf
[buflen
-2] = '\0';
354 /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
357 (void)snprintf(buf
, sizeof(buf
), fmt
, v
);
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 not seperated.
367 bittok2str_nosep(register const struct tok
*lp
, register const char *fmt
,
370 return (bittok2str_internal(lp
, fmt
, v
, 0));
374 * Convert a bit token value to a string; use "fmt" if not found.
375 * this is useful for parsing bitfields, the output strings are comma seperated.
378 bittok2str(register const struct tok
*lp
, register const char *fmt
,
381 return (bittok2str_internal(lp
, fmt
, v
, 1));
385 * Convert a value to a string using an array; the macro
386 * tok2strary() in <interface.h> is the public interface to
387 * this function and ensures that the second argument is
388 * correct for bounds-checking.
391 tok2strary_internal(register const char **lp
, int n
, register const char *fmt
,
394 static char buf
[128];
396 if (v
>= 0 && v
< n
&& lp
[v
] != NULL
)
400 (void)snprintf(buf
, sizeof(buf
), fmt
, v
);
405 * Convert a 32-bit netmask to prefixlen if possible
406 * the function returns the prefix-len; if plen == -1
407 * then conversion was not possible;
411 mask2plen(uint32_t mask
)
413 uint32_t bitmasks
[33] = {
415 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
416 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
417 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
418 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
419 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
420 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
421 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
422 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
426 /* let's see if we can transform the mask into a prefixlen */
427 while (prefix_len
>= 0) {
428 if (bitmasks
[prefix_len
] == mask
)
437 mask62plen(const u_char
*mask
)
439 u_char bitmasks
[9] = {
441 0x80, 0xc0, 0xe0, 0xf0,
442 0xf8, 0xfc, 0xfe, 0xff
447 for (byte
= 0; byte
< 16; byte
++) {
450 for (bits
= 0; bits
< (sizeof (bitmasks
) / sizeof (bitmasks
[0])); bits
++) {
451 if (mask
[byte
] == bitmasks
[bits
]) {
457 if (mask
[byte
] != 0xff)
466 error(const char *fmt
, ...)
470 (void)fprintf(stderr
, "%s: ", program_name
);
472 (void)vfprintf(stderr
, fmt
, ap
);
477 (void)fputc('\n', stderr
);
485 warning(const char *fmt
, ...)
489 (void)fprintf(stderr
, "%s: WARNING: ", program_name
);
491 (void)vfprintf(stderr
, fmt
, ap
);
496 (void)fputc('\n', stderr
);
501 * Copy arg vector into a new buffer, concatenating arguments with spaces.
504 copy_argv(register char **argv
)
507 register u_int len
= 0;
516 len
+= strlen(*p
++) + 1;
518 buf
= (char *)malloc(len
);
520 error("copy_argv: malloc");
524 while ((src
= *p
++) != NULL
) {
525 while ((*dst
++ = *src
++) != '\0')
535 * On Windows, we need to open the file in binary mode, so that
536 * we get all the bytes specified by the size we get from "fstat()".
537 * On UNIX, that's not necessary. O_BINARY is defined on Windows;
538 * we define it as 0 if it's not defined, so it does nothing.
545 read_infile(char *fname
)
547 register int i
, fd
, cc
;
551 fd
= open(fname
, O_RDONLY
|O_BINARY
);
553 error("can't open %s: %s", fname
, pcap_strerror(errno
));
555 if (fstat(fd
, &buf
) < 0)
556 error("can't stat %s: %s", fname
, pcap_strerror(errno
));
558 cp
= malloc((u_int
)buf
.st_size
+ 1);
560 error("malloc(%d) for %s: %s", (u_int
)buf
.st_size
+ 1,
561 fname
, pcap_strerror(errno
));
562 cc
= read(fd
, cp
, (u_int
)buf
.st_size
);
564 error("read %s: %s", fname
, pcap_strerror(errno
));
565 if (cc
!= buf
.st_size
)
566 error("short read %s (%d != %d)", fname
, cc
, (int)buf
.st_size
);
569 /* replace "# comment" with spaces */
570 for (i
= 0; i
< cc
; i
++) {
572 while (i
< cc
&& cp
[i
] != '\n')
580 safeputs(netdissect_options
*ndo
,
581 const u_char
*s
, const u_int maxlen
)
585 while (*s
&& idx
< maxlen
) {
586 safeputchar(ndo
, *s
);
593 safeputchar(netdissect_options
*ndo
,
596 ND_PRINT((ndo
, (c
< 0x80 && ND_ISPRINT(c
)) ? "%c" : "\\0x%02x", c
));
601 * Some compilers try to optimize memcpy(), using the alignment constraint
602 * on the argument pointer type. by using this function, we try to avoid the
606 unaligned_memcpy(void *p
, const void *q
, size_t l
)
611 /* As with memcpy(), so with memcmp(). */
613 unaligned_memcmp(const void *p
, const void *q
, size_t l
)
615 return (memcmp(p
, q
, l
));