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(netdissect_options
*ndo
, int sec
, int usec
)
140 static char buf
[sizeof("00:00:00.000000000")];
143 #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
144 switch (ndo
->ndo_tstamp_precision
) {
146 case PCAP_TSTAMP_PRECISION_MICRO
:
147 format
= "%02d:%02d:%02d.%06u";
150 case PCAP_TSTAMP_PRECISION_NANO
:
151 format
= "%02d:%02d:%02d.%09u";
155 format
= "%02d:%02d:%02d.{unknown precision}";
159 format
= "%02d:%02d:%02d.%06u";
162 snprintf(buf
, sizeof(buf
), format
,
163 sec
/ 3600, (sec
% 3600) / 60, sec
% 60, usec
);
169 * Print the timestamp
172 ts_print(netdissect_options
*ndo
,
173 register const struct timeval
*tvp
)
178 static unsigned b_sec
;
179 static unsigned b_usec
;
183 switch (ndo
->ndo_tflag
) {
185 case 0: /* Default */
186 s
= (tvp
->tv_sec
+ thiszone
) % 86400;
187 ND_PRINT((ndo
, "%s ", ts_format(ndo
, s
, tvp
->tv_usec
)));
190 case 1: /* No time stamp */
193 case 2: /* Unix timeval style */
194 ND_PRINT((ndo
, "%u.%06u ",
195 (unsigned)tvp
->tv_sec
,
196 (unsigned)tvp
->tv_usec
));
199 case 3: /* Microseconds since previous packet */
200 case 5: /* Microseconds since first packet */
202 /* init timestamp for first packet */
203 b_usec
= tvp
->tv_usec
;
207 d_usec
= tvp
->tv_usec
- b_usec
;
208 d_sec
= tvp
->tv_sec
- b_sec
;
215 ND_PRINT((ndo
, "%s ", ts_format(ndo
, d_sec
, d_usec
)));
217 if (ndo
->ndo_tflag
== 3) { /* set timestamp for last packet */
219 b_usec
= tvp
->tv_usec
;
223 case 4: /* Default + Date*/
224 s
= (tvp
->tv_sec
+ thiszone
) % 86400;
225 Time
= (tvp
->tv_sec
+ thiszone
) - s
;
228 ND_PRINT((ndo
, "Date fail "));
230 ND_PRINT((ndo
, "%04d-%02d-%02d %s ",
231 tm
->tm_year
+1900, tm
->tm_mon
+1, tm
->tm_mday
,
232 ts_format(ndo
, s
, tvp
->tv_usec
)));
238 * Print a relative number of seconds (e.g. hold time, prune timer)
239 * in the form 5m1s. This does no truncation, so 32230861 seconds
240 * is represented as 1y1w1d1h1m1s.
243 relts_print(netdissect_options
*ndo
,
246 static const char *lengths
[] = {"y", "w", "d", "h", "m", "s"};
247 static const int seconds
[] = {31536000, 604800, 86400, 3600, 60, 1};
248 const char **l
= lengths
;
249 const int *s
= seconds
;
252 ND_PRINT((ndo
, "0s"));
256 ND_PRINT((ndo
, "-"));
261 ND_PRINT((ndo
, "%d%s", secs
/ *s
, *l
));
262 secs
-= (secs
/ *s
) * *s
;
270 * this is a generic routine for printing unknown data;
271 * we pass on the linefeed plus indentation string to
272 * get a proper output - returns 0 on error
276 print_unknown_data(netdissect_options
*ndo
, const u_char
*cp
,const char *ident
,int len
)
279 ND_PRINT((ndo
,"%sDissector error: print_unknown_data called with negative length",
283 if (ndo
->ndo_snapend
- cp
< len
)
284 len
= ndo
->ndo_snapend
- cp
;
286 ND_PRINT((ndo
,"%sDissector error: print_unknown_data called with pointer past end of packet",
290 hex_print(ndo
, ident
,cp
,len
);
291 return(1); /* everything is ok */
295 * Convert a token value to a string; use "fmt" if not found.
298 tok2strbuf(register const struct tok
*lp
, register const char *fmt
,
299 register u_int v
, char *buf
, size_t bufsize
)
302 while (lp
->s
!= NULL
) {
311 (void)snprintf(buf
, bufsize
, fmt
, v
);
312 return (const char *)buf
;
316 * Convert a token value to a string; use "fmt" if not found.
319 tok2str(register const struct tok
*lp
, register const char *fmt
,
322 static char buf
[4][128];
328 return tok2strbuf(lp
, fmt
, v
, ret
, sizeof(buf
[0]));
332 * Convert a bit token value to a string; use "fmt" if not found.
333 * this is useful for parsing bitfields, the output strings are seperated
334 * if the s field is positive.
337 bittok2str_internal(register const struct tok
*lp
, register const char *fmt
,
338 register int v
, register int sep
)
340 static char buf
[256]; /* our stringbuffer */
342 register int rotbit
; /* this is the bit we rotate through all bitpositions */
344 const char * sepstr
= "";
346 while (lp
!= NULL
&& lp
->s
!= NULL
) {
347 tokval
=lp
->v
; /* load our first value */
349 while (rotbit
!= 0) {
351 * lets AND the rotating bit with our token value
352 * and see if we have got a match
354 if (tokval
== (v
&rotbit
)) {
355 /* ok we have found something */
356 buflen
+=snprintf(buf
+buflen
, sizeof(buf
)-buflen
, "%s%s",
358 sepstr
= sep
? ", " : "";
361 rotbit
=rotbit
<<1; /* no match - lets shift and try again */
367 /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
368 (void)snprintf(buf
, sizeof(buf
), fmt
== NULL
? "#%d" : fmt
, v
);
373 * Convert a bit token value to a string; use "fmt" if not found.
374 * this is useful for parsing bitfields, the output strings are not seperated.
377 bittok2str_nosep(register const struct tok
*lp
, register const char *fmt
,
380 return (bittok2str_internal(lp
, fmt
, v
, 0));
384 * Convert a bit token value to a string; use "fmt" if not found.
385 * this is useful for parsing bitfields, the output strings are comma seperated.
388 bittok2str(register const struct tok
*lp
, register const char *fmt
,
391 return (bittok2str_internal(lp
, fmt
, v
, 1));
395 * Convert a value to a string using an array; the macro
396 * tok2strary() in <interface.h> is the public interface to
397 * this function and ensures that the second argument is
398 * correct for bounds-checking.
401 tok2strary_internal(register const char **lp
, int n
, register const char *fmt
,
404 static char buf
[128];
406 if (v
>= 0 && v
< n
&& lp
[v
] != NULL
)
410 (void)snprintf(buf
, sizeof(buf
), fmt
, v
);
415 * Convert a 32-bit netmask to prefixlen if possible
416 * the function returns the prefix-len; if plen == -1
417 * then conversion was not possible;
421 mask2plen(uint32_t mask
)
423 uint32_t bitmasks
[33] = {
425 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
426 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
427 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
428 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
429 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
430 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
431 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
432 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
436 /* let's see if we can transform the mask into a prefixlen */
437 while (prefix_len
>= 0) {
438 if (bitmasks
[prefix_len
] == mask
)
447 mask62plen(const u_char
*mask
)
449 u_char bitmasks
[9] = {
451 0x80, 0xc0, 0xe0, 0xf0,
452 0xf8, 0xfc, 0xfe, 0xff
457 for (byte
= 0; byte
< 16; byte
++) {
460 for (bits
= 0; bits
< (sizeof (bitmasks
) / sizeof (bitmasks
[0])); bits
++) {
461 if (mask
[byte
] == bitmasks
[bits
]) {
467 if (mask
[byte
] != 0xff)
476 error(const char *fmt
, ...)
480 (void)fprintf(stderr
, "%s: ", program_name
);
482 (void)vfprintf(stderr
, fmt
, ap
);
487 (void)fputc('\n', stderr
);
495 warning(const char *fmt
, ...)
499 (void)fprintf(stderr
, "%s: WARNING: ", program_name
);
501 (void)vfprintf(stderr
, fmt
, ap
);
506 (void)fputc('\n', stderr
);
511 * Copy arg vector into a new buffer, concatenating arguments with spaces.
514 copy_argv(register char **argv
)
517 register u_int len
= 0;
526 len
+= strlen(*p
++) + 1;
528 buf
= (char *)malloc(len
);
530 error("copy_argv: malloc");
534 while ((src
= *p
++) != NULL
) {
535 while ((*dst
++ = *src
++) != '\0')
545 * On Windows, we need to open the file in binary mode, so that
546 * we get all the bytes specified by the size we get from "fstat()".
547 * On UNIX, that's not necessary. O_BINARY is defined on Windows;
548 * we define it as 0 if it's not defined, so it does nothing.
555 read_infile(char *fname
)
557 register int i
, fd
, cc
;
561 fd
= open(fname
, O_RDONLY
|O_BINARY
);
563 error("can't open %s: %s", fname
, pcap_strerror(errno
));
565 if (fstat(fd
, &buf
) < 0)
566 error("can't stat %s: %s", fname
, pcap_strerror(errno
));
568 cp
= malloc((u_int
)buf
.st_size
+ 1);
570 error("malloc(%d) for %s: %s", (u_int
)buf
.st_size
+ 1,
571 fname
, pcap_strerror(errno
));
572 cc
= read(fd
, cp
, (u_int
)buf
.st_size
);
574 error("read %s: %s", fname
, pcap_strerror(errno
));
575 if (cc
!= buf
.st_size
)
576 error("short read %s (%d != %d)", fname
, cc
, (int)buf
.st_size
);
579 /* replace "# comment" with spaces */
580 for (i
= 0; i
< cc
; i
++) {
582 while (i
< cc
&& cp
[i
] != '\n')
590 safeputs(netdissect_options
*ndo
,
591 const u_char
*s
, const u_int maxlen
)
595 while (*s
&& idx
< maxlen
) {
596 safeputchar(ndo
, *s
);
603 safeputchar(netdissect_options
*ndo
,
606 ND_PRINT((ndo
, (c
< 0x80 && ND_ISPRINT(c
)) ? "%c" : "\\0x%02x", c
));
611 * Some compilers try to optimize memcpy(), using the alignment constraint
612 * on the argument pointer type. by using this function, we try to avoid the
616 unaligned_memcpy(void *p
, const void *q
, size_t l
)
621 /* As with memcpy(), so with memcmp(). */
623 unaligned_memcmp(const void *p
, const void *q
, size_t l
)
625 return (memcmp(p
, q
, l
));