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 * txtproto_print() derived from original code by Hannes Gredler
24 * (hannes@juniper.net):
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that: (1) source code
28 * distributions retain the above copyright notice and this paragraph
29 * in its entirety, and (2) distributions including binary code include
30 * the above copyright notice and this paragraph in its entirety in
31 * the documentation or other materials provided with the distribution.
32 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
33 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
34 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
35 * FOR A PARTICULAR PURPOSE.
38 #define NETDISSECT_REWORKED
43 #include <tcpdump-stdinc.h>
55 #include "interface.h"
58 * timestamp display buffer size, the biggest size of both formats is needed
59 * sizeof("0000000000.000000000") > sizeof("00:00:00.000000000")
61 #define TS_BUF_SIZE sizeof("0000000000.000000000")
64 * Print out a null-terminated filename (or other ascii string).
65 * If ep is NULL, assume no truncation check is needed.
66 * Return true if truncated.
69 fn_print(netdissect_options
*ndo
,
70 register const u_char
*s
, register const u_char
*ep
)
75 ret
= 1; /* assume truncated */
76 while (ep
== NULL
|| s
< ep
) {
84 ND_PRINT((ndo
, "M-"));
87 c
^= 0x40; /* DEL to ?, others to alpha */
90 ND_PRINT((ndo
, "%c", c
));
96 * Print out a counted filename (or other ascii string).
97 * If ep is NULL, assume no truncation check is needed.
98 * Return true if truncated.
101 fn_printn(netdissect_options
*ndo
,
102 register const u_char
*s
, register u_int n
, register const u_char
*ep
)
106 while (n
> 0 && (ep
== NULL
|| s
< ep
)) {
109 if (!ND_ISASCII(c
)) {
111 ND_PRINT((ndo
, "M-"));
113 if (!ND_ISPRINT(c
)) {
114 c
^= 0x40; /* DEL to ?, others to alpha */
115 ND_PRINT((ndo
, "^"));
117 ND_PRINT((ndo
, "%c", c
));
119 return (n
== 0) ? 0 : 1;
123 * Print out a null-padded filename (or other ascii string).
124 * If ep is NULL, assume no truncation check is needed.
125 * Return true if truncated.
128 fn_printzp(netdissect_options
*ndo
,
129 register const u_char
*s
, register u_int n
,
130 register const u_char
*ep
)
135 ret
= 1; /* assume truncated */
136 while (n
> 0 && (ep
== NULL
|| s
< ep
)) {
143 if (!ND_ISASCII(c
)) {
145 ND_PRINT((ndo
, "M-"));
147 if (!ND_ISPRINT(c
)) {
148 c
^= 0x40; /* DEL to ?, others to alpha */
149 ND_PRINT((ndo
, "^"));
151 ND_PRINT((ndo
, "%c", c
));
153 return (n
== 0) ? 0 : ret
;
157 * Format the timestamp
160 ts_format(netdissect_options
*ndo
161 #ifndef HAVE_PCAP_SET_TSTAMP_PRECISION
164 , int sec
, int usec
, char *buf
)
168 #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
169 switch (ndo
->ndo_tstamp_precision
) {
171 case PCAP_TSTAMP_PRECISION_MICRO
:
172 format
= "%02d:%02d:%02d.%06u";
175 case PCAP_TSTAMP_PRECISION_NANO
:
176 format
= "%02d:%02d:%02d.%09u";
180 format
= "%02d:%02d:%02d.{unknown}";
184 format
= "%02d:%02d:%02d.%06u";
187 snprintf(buf
, TS_BUF_SIZE
, format
,
188 sec
/ 3600, (sec
% 3600) / 60, sec
% 60, usec
);
194 * Print the timestamp
197 ts_print(netdissect_options
*ndo
,
198 register const struct timeval
*tvp
)
203 static unsigned b_sec
;
204 static unsigned b_usec
;
207 char buf
[TS_BUF_SIZE
];
209 switch (ndo
->ndo_tflag
) {
211 case 0: /* Default */
212 s
= (tvp
->tv_sec
+ thiszone
) % 86400;
213 ND_PRINT((ndo
, "%s ", ts_format(ndo
, s
, tvp
->tv_usec
, buf
)));
216 case 1: /* No time stamp */
219 case 2: /* Unix timeval style */
220 ND_PRINT((ndo
, "%u.%06u ",
221 (unsigned)tvp
->tv_sec
,
222 (unsigned)tvp
->tv_usec
));
225 case 3: /* Microseconds since previous packet */
226 case 5: /* Microseconds since first packet */
228 /* init timestamp for first packet */
229 b_usec
= tvp
->tv_usec
;
233 d_usec
= tvp
->tv_usec
- b_usec
;
234 d_sec
= tvp
->tv_sec
- b_sec
;
241 ND_PRINT((ndo
, "%s ", ts_format(ndo
, d_sec
, d_usec
, buf
)));
243 if (ndo
->ndo_tflag
== 3) { /* set timestamp for last packet */
245 b_usec
= tvp
->tv_usec
;
249 case 4: /* Default + Date */
250 s
= (tvp
->tv_sec
+ thiszone
) % 86400;
251 Time
= (tvp
->tv_sec
+ thiszone
) - s
;
254 ND_PRINT((ndo
, "Date fail "));
256 ND_PRINT((ndo
, "%04d-%02d-%02d %s ",
257 tm
->tm_year
+1900, tm
->tm_mon
+1, tm
->tm_mday
,
258 ts_format(ndo
, s
, tvp
->tv_usec
, buf
)));
264 * Print a relative number of seconds (e.g. hold time, prune timer)
265 * in the form 5m1s. This does no truncation, so 32230861 seconds
266 * is represented as 1y1w1d1h1m1s.
269 relts_print(netdissect_options
*ndo
,
272 static const char *lengths
[] = {"y", "w", "d", "h", "m", "s"};
273 static const int seconds
[] = {31536000, 604800, 86400, 3600, 60, 1};
274 const char **l
= lengths
;
275 const int *s
= seconds
;
278 ND_PRINT((ndo
, "0s"));
282 ND_PRINT((ndo
, "-"));
287 ND_PRINT((ndo
, "%d%s", secs
/ *s
, *l
));
288 secs
-= (secs
/ *s
) * *s
;
296 * this is a generic routine for printing unknown data;
297 * we pass on the linefeed plus indentation string to
298 * get a proper output - returns 0 on error
302 print_unknown_data(netdissect_options
*ndo
, const u_char
*cp
,const char *ident
,int len
)
305 ND_PRINT((ndo
,"%sDissector error: print_unknown_data called with negative length",
309 if (ndo
->ndo_snapend
- cp
< len
)
310 len
= ndo
->ndo_snapend
- cp
;
312 ND_PRINT((ndo
,"%sDissector error: print_unknown_data called with pointer past end of packet",
316 hex_print(ndo
, ident
,cp
,len
);
317 return(1); /* everything is ok */
321 * Convert a token value to a string; use "fmt" if not found.
324 tok2strbuf(register const struct tok
*lp
, register const char *fmt
,
325 register u_int v
, char *buf
, size_t bufsize
)
328 while (lp
->s
!= NULL
) {
337 (void)snprintf(buf
, bufsize
, fmt
, v
);
338 return (const char *)buf
;
342 * Convert a token value to a string; use "fmt" if not found.
345 tok2str(register const struct tok
*lp
, register const char *fmt
,
348 static char buf
[4][128];
354 return tok2strbuf(lp
, fmt
, v
, ret
, sizeof(buf
[0]));
358 * Convert a bit token value to a string; use "fmt" if not found.
359 * this is useful for parsing bitfields, the output strings are seperated
360 * if the s field is positive.
363 bittok2str_internal(register const struct tok
*lp
, register const char *fmt
,
364 register u_int v
, const char *sep
)
366 static char buf
[256]; /* our stringbuffer */
368 register u_int rotbit
; /* this is the bit we rotate through all bitpositions */
369 register u_int tokval
;
370 const char * sepstr
= "";
372 while (lp
!= NULL
&& lp
->s
!= NULL
) {
373 tokval
=lp
->v
; /* load our first value */
375 while (rotbit
!= 0) {
377 * lets AND the rotating bit with our token value
378 * and see if we have got a match
380 if (tokval
== (v
&rotbit
)) {
381 /* ok we have found something */
382 buflen
+=snprintf(buf
+buflen
, sizeof(buf
)-buflen
, "%s%s",
387 rotbit
=rotbit
<<1; /* no match - lets shift and try again */
393 /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
394 (void)snprintf(buf
, sizeof(buf
), fmt
== NULL
? "#%08x" : fmt
, v
);
399 * Convert a bit token value to a string; use "fmt" if not found.
400 * this is useful for parsing bitfields, the output strings are not seperated.
403 bittok2str_nosep(register const struct tok
*lp
, register const char *fmt
,
406 return (bittok2str_internal(lp
, fmt
, v
, ""));
410 * Convert a bit token value to a string; use "fmt" if not found.
411 * this is useful for parsing bitfields, the output strings are comma seperated.
414 bittok2str(register const struct tok
*lp
, register const char *fmt
,
417 return (bittok2str_internal(lp
, fmt
, v
, ", "));
421 * Convert a value to a string using an array; the macro
422 * tok2strary() in <interface.h> is the public interface to
423 * this function and ensures that the second argument is
424 * correct for bounds-checking.
427 tok2strary_internal(register const char **lp
, int n
, register const char *fmt
,
430 static char buf
[128];
432 if (v
>= 0 && v
< n
&& lp
[v
] != NULL
)
436 (void)snprintf(buf
, sizeof(buf
), fmt
, v
);
441 * Convert a 32-bit netmask to prefixlen if possible
442 * the function returns the prefix-len; if plen == -1
443 * then conversion was not possible;
447 mask2plen(uint32_t mask
)
449 uint32_t bitmasks
[33] = {
451 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
452 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
453 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
454 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
455 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
456 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
457 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
458 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
462 /* let's see if we can transform the mask into a prefixlen */
463 while (prefix_len
>= 0) {
464 if (bitmasks
[prefix_len
] == mask
)
473 mask62plen(const u_char
*mask
)
475 u_char bitmasks
[9] = {
477 0x80, 0xc0, 0xe0, 0xf0,
478 0xf8, 0xfc, 0xfe, 0xff
483 for (byte
= 0; byte
< 16; byte
++) {
486 for (bits
= 0; bits
< (sizeof (bitmasks
) / sizeof (bitmasks
[0])); bits
++) {
487 if (mask
[byte
] == bitmasks
[bits
]) {
493 if (mask
[byte
] != 0xff)
501 * Routine to print out information for text-based protocols such as FTP,
502 * HTTP, SMTP, RTSP, SIP, ....
504 #define MAX_TOKEN 128
507 * Fetch a token from a packet, starting at the specified index,
508 * and return the length of the token.
510 * Returns 0 on error; yes, this is indistinguishable from an empty
511 * token, but an "empty token" isn't a valid token - it just means
512 * either a space character at the beginning of the line (this
513 * includes a blank line) or no more tokens remaining on the line.
516 fetch_token(netdissect_options
*ndo
, const u_char
*pptr
, u_int idx
, u_int len
,
517 u_char
*tbuf
, size_t tbuflen
)
521 for (; idx
< len
; idx
++) {
522 if (!ND_TTEST(*(pptr
+ idx
))) {
523 /* ran past end of captured data */
526 if (!isascii(*(pptr
+ idx
))) {
527 /* not an ASCII character */
530 if (isspace(*(pptr
+ idx
))) {
534 if (!isprint(*(pptr
+ idx
))) {
535 /* not part of a command token or response code */
538 if (toklen
+ 2 > tbuflen
) {
539 /* no room for this character and terminating '\0' */
542 tbuf
[toklen
] = *(pptr
+ idx
);
552 * Skip past any white space after the token, until we see
553 * an end-of-line (CR or LF).
555 for (; idx
< len
; idx
++) {
556 if (!ND_TTEST(*(pptr
+ idx
))) {
557 /* ran past end of captured data */
560 if (*(pptr
+ idx
) == '\r' || *(pptr
+ idx
) == '\n') {
564 if (!isascii(*(pptr
+ idx
)) || !isprint(*(pptr
+ idx
))) {
565 /* not a printable ASCII character */
568 if (!isspace(*(pptr
+ idx
))) {
569 /* beginning of next token */
577 * Scan a buffer looking for a line ending - LF or CR-LF.
578 * Return the index of the character after the line ending or 0 if
579 * we encounter a non-ASCII or non-printable character or don't find
583 print_txt_line(netdissect_options
*ndo
, const char *protoname
,
584 const char *prefix
, const u_char
*pptr
, u_int idx
, u_int len
)
591 ND_TCHECK(*(pptr
+idx
));
592 if (*(pptr
+idx
) == '\n') {
594 * LF without CR; end of line.
595 * Skip the LF and print the line, with the
596 * exception of the LF.
598 linelen
= idx
- startidx
;
601 } else if (*(pptr
+idx
) == '\r') {
603 if ((idx
+1) >= len
) {
604 /* not in this packet */
607 ND_TCHECK(*(pptr
+idx
+1));
608 if (*(pptr
+idx
+1) == '\n') {
610 * CR-LF; end of line.
611 * Skip the CR-LF and print the line, with
612 * the exception of the CR-LF.
614 linelen
= idx
- startidx
;
620 * CR followed by something else; treat this
621 * as if it were binary data, and don't print
625 } else if (!isascii(*(pptr
+idx
)) ||
626 (!isprint(*(pptr
+idx
)) && *(pptr
+idx
) != '\t')) {
628 * Not a printable ASCII character and not a tab;
629 * treat this as if it were binary data, and
638 * All printable ASCII, but no line ending after that point
639 * in the buffer; treat this as if it were truncated.
642 linelen
= idx
- startidx
;
643 ND_PRINT((ndo
, "%s%.*s[!%s]", prefix
, (int)linelen
, pptr
+ startidx
,
648 ND_PRINT((ndo
, "%s%.*s", prefix
, (int)linelen
, pptr
+ startidx
));
653 txtproto_print(netdissect_options
*ndo
, const u_char
*pptr
, u_int len
,
654 const char *protoname
, const char **cmds
, u_int flags
)
657 u_char token
[MAX_TOKEN
+1];
664 * This protocol has more than just request and
665 * response lines; see whether this looks like a
666 * request or response.
668 idx
= fetch_token(ndo
, pptr
, 0, len
, token
, sizeof(token
));
670 /* Is this a valid request name? */
671 while ((cmd
= *cmds
++) != NULL
) {
672 if (strcasecmp((const char *)token
, cmd
) == 0) {
680 * No - is this a valid response code (3 digits)?
682 * Is this token the response code, or is the next
683 * token the response code?
685 if (flags
& RESP_CODE_SECOND_TOKEN
) {
687 * Next token - get it.
689 idx
= fetch_token(ndo
, pptr
, idx
, len
, token
,
693 if (isdigit(token
[0]) && isdigit(token
[1]) &&
694 isdigit(token
[2]) && token
[3] == '\0') {
702 * This protocol has only request and response lines
703 * (e.g., FTP, where all the data goes over a
704 * different connection); assume the payload is
705 * a request or response.
710 /* Capitalize the protocol name */
711 for (pnp
= protoname
; *pnp
!= '\0'; pnp
++)
712 ND_PRINT((ndo
, "%c", toupper(*pnp
)));
716 * In non-verbose mode, just print the protocol, followed
717 * by the first line as the request or response info.
719 * In verbose mode, print lines as text until we run out
720 * of characters or see something that's not a
721 * printable-ASCII line.
723 if (ndo
->ndo_vflag
) {
725 * We're going to print all the text lines in the
726 * request or response; just print the length
727 * on the first line of the output.
729 ND_PRINT((ndo
, ", length: %u", len
));
731 idx
< len
&& (eol
= print_txt_line(ndo
, protoname
, "\n\t", pptr
, idx
, len
)) != 0;
736 * Just print the first text line.
738 print_txt_line(ndo
, protoname
, ": ", pptr
, 0, len
);
745 error(const char *fmt
, ...)
749 (void)fprintf(stderr
, "%s: ", program_name
);
751 (void)vfprintf(stderr
, fmt
, ap
);
756 (void)fputc('\n', stderr
);
764 warning(const char *fmt
, ...)
768 (void)fprintf(stderr
, "%s: WARNING: ", program_name
);
770 (void)vfprintf(stderr
, fmt
, ap
);
775 (void)fputc('\n', stderr
);
780 * Copy arg vector into a new buffer, concatenating arguments with spaces.
783 copy_argv(register char **argv
)
786 register u_int len
= 0;
795 len
+= strlen(*p
++) + 1;
797 buf
= (char *)malloc(len
);
799 error("copy_argv: malloc");
803 while ((src
= *p
++) != NULL
) {
804 while ((*dst
++ = *src
++) != '\0')
814 * On Windows, we need to open the file in binary mode, so that
815 * we get all the bytes specified by the size we get from "fstat()".
816 * On UNIX, that's not necessary. O_BINARY is defined on Windows;
817 * we define it as 0 if it's not defined, so it does nothing.
824 read_infile(char *fname
)
826 register int i
, fd
, cc
;
830 fd
= open(fname
, O_RDONLY
|O_BINARY
);
832 error("can't open %s: %s", fname
, pcap_strerror(errno
));
834 if (fstat(fd
, &buf
) < 0)
835 error("can't stat %s: %s", fname
, pcap_strerror(errno
));
837 cp
= malloc((u_int
)buf
.st_size
+ 1);
839 error("malloc(%d) for %s: %s", (u_int
)buf
.st_size
+ 1,
840 fname
, pcap_strerror(errno
));
841 cc
= read(fd
, cp
, (u_int
)buf
.st_size
);
843 error("read %s: %s", fname
, pcap_strerror(errno
));
844 if (cc
!= buf
.st_size
)
845 error("short read %s (%d != %d)", fname
, cc
, (int)buf
.st_size
);
848 /* replace "# comment" with spaces */
849 for (i
= 0; i
< cc
; i
++) {
851 while (i
< cc
&& cp
[i
] != '\n')
859 safeputs(netdissect_options
*ndo
,
860 const u_char
*s
, const u_int maxlen
)
864 while (*s
&& idx
< maxlen
) {
865 safeputchar(ndo
, *s
);
872 safeputchar(netdissect_options
*ndo
,
875 ND_PRINT((ndo
, (c
< 0x80 && ND_ISPRINT(c
)) ? "%c" : "\\0x%02x", c
));
880 * Some compilers try to optimize memcpy(), using the alignment constraint
881 * on the argument pointer type. by using this function, we try to avoid the
885 unaligned_memcpy(void *p
, const void *q
, size_t l
)
890 /* As with memcpy(), so with memcmp(). */
892 unaligned_memcmp(const void *p
, const void *q
, size_t l
)
894 return (memcmp(p
, q
, l
));