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 * Print out a null-terminated filename (or other ascii string).
59 * If ep is NULL, assume no truncation check is needed.
60 * Return true if truncated.
63 fn_print(netdissect_options
*ndo
,
64 register const u_char
*s
, register const u_char
*ep
)
69 ret
= 1; /* assume truncated */
70 while (ep
== NULL
|| s
< ep
) {
78 ND_PRINT((ndo
, "M-"));
81 c
^= 0x40; /* DEL to ?, others to alpha */
84 ND_PRINT((ndo
, "%c", c
));
90 * Print out a counted filename (or other ascii string).
91 * If ep is NULL, assume no truncation check is needed.
92 * Return true if truncated.
95 fn_printn(netdissect_options
*ndo
,
96 register const u_char
*s
, register u_int n
, register const u_char
*ep
)
100 while (n
> 0 && (ep
== NULL
|| s
< ep
)) {
103 if (!ND_ISASCII(c
)) {
105 ND_PRINT((ndo
, "M-"));
107 if (!ND_ISPRINT(c
)) {
108 c
^= 0x40; /* DEL to ?, others to alpha */
109 ND_PRINT((ndo
, "^"));
111 ND_PRINT((ndo
, "%c", c
));
113 return (n
== 0) ? 0 : 1;
117 * Print out a null-padded filename (or other ascii string).
118 * If ep is NULL, assume no truncation check is needed.
119 * Return true if truncated.
122 fn_printzp(netdissect_options
*ndo
,
123 register const u_char
*s
, register u_int n
,
124 register const u_char
*ep
)
129 ret
= 1; /* assume truncated */
130 while (n
> 0 && (ep
== NULL
|| s
< ep
)) {
137 if (!ND_ISASCII(c
)) {
139 ND_PRINT((ndo
, "M-"));
141 if (!ND_ISPRINT(c
)) {
142 c
^= 0x40; /* DEL to ?, others to alpha */
143 ND_PRINT((ndo
, "^"));
145 ND_PRINT((ndo
, "%c", c
));
147 return (n
== 0) ? 0 : ret
;
151 * Format the timestamp
154 ts_format(netdissect_options
*ndo
155 #ifndef HAVE_PCAP_SET_TSTAMP_PRECISION
160 static char buf
[sizeof("00:00:00.000000000")];
163 #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
164 switch (ndo
->ndo_tstamp_precision
) {
166 case PCAP_TSTAMP_PRECISION_MICRO
:
167 format
= "%02d:%02d:%02d.%06u";
170 case PCAP_TSTAMP_PRECISION_NANO
:
171 format
= "%02d:%02d:%02d.%09u";
175 format
= "%02d:%02d:%02d.{unknown precision}";
179 format
= "%02d:%02d:%02d.%06u";
182 snprintf(buf
, sizeof(buf
), format
,
183 sec
/ 3600, (sec
% 3600) / 60, sec
% 60, usec
);
189 * Print the timestamp
192 ts_print(netdissect_options
*ndo
,
193 register const struct timeval
*tvp
)
198 static unsigned b_sec
;
199 static unsigned b_usec
;
203 switch (ndo
->ndo_tflag
) {
205 case 0: /* Default */
206 s
= (tvp
->tv_sec
+ thiszone
) % 86400;
207 ND_PRINT((ndo
, "%s ", ts_format(ndo
, s
, tvp
->tv_usec
)));
210 case 1: /* No time stamp */
213 case 2: /* Unix timeval style */
214 ND_PRINT((ndo
, "%u.%06u ",
215 (unsigned)tvp
->tv_sec
,
216 (unsigned)tvp
->tv_usec
));
219 case 3: /* Microseconds since previous packet */
220 case 5: /* Microseconds since first packet */
222 /* init timestamp for first packet */
223 b_usec
= tvp
->tv_usec
;
227 d_usec
= tvp
->tv_usec
- b_usec
;
228 d_sec
= tvp
->tv_sec
- b_sec
;
235 ND_PRINT((ndo
, "%s ", ts_format(ndo
, d_sec
, d_usec
)));
237 if (ndo
->ndo_tflag
== 3) { /* set timestamp for last packet */
239 b_usec
= tvp
->tv_usec
;
243 case 4: /* Default + Date*/
244 s
= (tvp
->tv_sec
+ thiszone
) % 86400;
245 Time
= (tvp
->tv_sec
+ thiszone
) - s
;
248 ND_PRINT((ndo
, "Date fail "));
250 ND_PRINT((ndo
, "%04d-%02d-%02d %s ",
251 tm
->tm_year
+1900, tm
->tm_mon
+1, tm
->tm_mday
,
252 ts_format(ndo
, s
, tvp
->tv_usec
)));
258 * Print a relative number of seconds (e.g. hold time, prune timer)
259 * in the form 5m1s. This does no truncation, so 32230861 seconds
260 * is represented as 1y1w1d1h1m1s.
263 relts_print(netdissect_options
*ndo
,
266 static const char *lengths
[] = {"y", "w", "d", "h", "m", "s"};
267 static const int seconds
[] = {31536000, 604800, 86400, 3600, 60, 1};
268 const char **l
= lengths
;
269 const int *s
= seconds
;
272 ND_PRINT((ndo
, "0s"));
276 ND_PRINT((ndo
, "-"));
281 ND_PRINT((ndo
, "%d%s", secs
/ *s
, *l
));
282 secs
-= (secs
/ *s
) * *s
;
290 * this is a generic routine for printing unknown data;
291 * we pass on the linefeed plus indentation string to
292 * get a proper output - returns 0 on error
296 print_unknown_data(netdissect_options
*ndo
, const u_char
*cp
,const char *ident
,int len
)
299 ND_PRINT((ndo
,"%sDissector error: print_unknown_data called with negative length",
303 if (ndo
->ndo_snapend
- cp
< len
)
304 len
= ndo
->ndo_snapend
- cp
;
306 ND_PRINT((ndo
,"%sDissector error: print_unknown_data called with pointer past end of packet",
310 hex_print(ndo
, ident
,cp
,len
);
311 return(1); /* everything is ok */
315 * Convert a token value to a string; use "fmt" if not found.
318 tok2strbuf(register const struct tok
*lp
, register const char *fmt
,
319 register u_int v
, char *buf
, size_t bufsize
)
322 while (lp
->s
!= NULL
) {
331 (void)snprintf(buf
, bufsize
, fmt
, v
);
332 return (const char *)buf
;
336 * Convert a token value to a string; use "fmt" if not found.
339 tok2str(register const struct tok
*lp
, register const char *fmt
,
342 static char buf
[4][128];
348 return tok2strbuf(lp
, fmt
, v
, ret
, sizeof(buf
[0]));
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 seperated
354 * if the s field is positive.
357 bittok2str_internal(register const struct tok
*lp
, register const char *fmt
,
358 register int v
, register int sep
)
360 static char buf
[256]; /* our stringbuffer */
362 register int rotbit
; /* this is the bit we rotate through all bitpositions */
364 const char * sepstr
= "";
366 while (lp
!= NULL
&& lp
->s
!= NULL
) {
367 tokval
=lp
->v
; /* load our first value */
369 while (rotbit
!= 0) {
371 * lets AND the rotating bit with our token value
372 * and see if we have got a match
374 if (tokval
== (v
&rotbit
)) {
375 /* ok we have found something */
376 buflen
+=snprintf(buf
+buflen
, sizeof(buf
)-buflen
, "%s%s",
378 sepstr
= sep
? ", " : "";
381 rotbit
=rotbit
<<1; /* no match - lets shift and try again */
387 /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
388 (void)snprintf(buf
, sizeof(buf
), fmt
== NULL
? "#%d" : fmt
, v
);
393 * Convert a bit token value to a string; use "fmt" if not found.
394 * this is useful for parsing bitfields, the output strings are not seperated.
397 bittok2str_nosep(register const struct tok
*lp
, register const char *fmt
,
400 return (bittok2str_internal(lp
, fmt
, v
, 0));
404 * Convert a bit token value to a string; use "fmt" if not found.
405 * this is useful for parsing bitfields, the output strings are comma seperated.
408 bittok2str(register const struct tok
*lp
, register const char *fmt
,
411 return (bittok2str_internal(lp
, fmt
, v
, 1));
415 * Convert a value to a string using an array; the macro
416 * tok2strary() in <interface.h> is the public interface to
417 * this function and ensures that the second argument is
418 * correct for bounds-checking.
421 tok2strary_internal(register const char **lp
, int n
, register const char *fmt
,
424 static char buf
[128];
426 if (v
>= 0 && v
< n
&& lp
[v
] != NULL
)
430 (void)snprintf(buf
, sizeof(buf
), fmt
, v
);
435 * Convert a 32-bit netmask to prefixlen if possible
436 * the function returns the prefix-len; if plen == -1
437 * then conversion was not possible;
441 mask2plen(uint32_t mask
)
443 uint32_t bitmasks
[33] = {
445 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
446 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
447 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
448 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
449 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
450 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
451 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
452 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
456 /* let's see if we can transform the mask into a prefixlen */
457 while (prefix_len
>= 0) {
458 if (bitmasks
[prefix_len
] == mask
)
467 mask62plen(const u_char
*mask
)
469 u_char bitmasks
[9] = {
471 0x80, 0xc0, 0xe0, 0xf0,
472 0xf8, 0xfc, 0xfe, 0xff
477 for (byte
= 0; byte
< 16; byte
++) {
480 for (bits
= 0; bits
< (sizeof (bitmasks
) / sizeof (bitmasks
[0])); bits
++) {
481 if (mask
[byte
] == bitmasks
[bits
]) {
487 if (mask
[byte
] != 0xff)
495 * Routine to print out information for text-based protocols such as FTP,
496 * HTTP, SMTP, RTSP, SIP, ....
498 #define MAX_TOKEN 128
501 * Fetch a token from a packet, starting at the specified index,
502 * and return the length of the token.
504 * Returns 0 on error; yes, this is indistinguishable from an empty
505 * token, but an "empty token" isn't a valid token - it just means
506 * either a space character at the beginning of the line (this
507 * includes a blank line) or no more tokens remaining on the line.
510 fetch_token(netdissect_options
*ndo
, const u_char
*pptr
, u_int idx
, u_int len
,
511 u_char
*tbuf
, size_t tbuflen
)
515 for (; idx
< len
; idx
++) {
516 if (!ND_TTEST(*(pptr
+ idx
))) {
517 /* ran past end of captured data */
520 if (!isascii(*(pptr
+ idx
))) {
521 /* not an ASCII character */
524 if (isspace(*(pptr
+ idx
))) {
528 if (!isprint(*(pptr
+ idx
))) {
529 /* not part of a command token or response code */
532 if (toklen
+ 2 > tbuflen
) {
533 /* no room for this character and terminating '\0' */
536 tbuf
[toklen
] = *(pptr
+ idx
);
546 * Skip past any white space after the token, until we see
547 * an end-of-line (CR or LF).
549 for (; idx
< len
; idx
++) {
550 if (!ND_TTEST(*(pptr
+ idx
))) {
551 /* ran past end of captured data */
554 if (*(pptr
+ idx
) == '\r' || *(pptr
+ idx
) == '\n') {
558 if (!isascii(*(pptr
+ idx
)) || !isprint(*(pptr
+ idx
))) {
559 /* not a printable ASCII character */
562 if (!isspace(*(pptr
+ idx
))) {
563 /* beginning of next token */
571 * Scan a buffer looking for a line ending - LF or CR-LF.
572 * Return the index of the character after the line ending or 0 if
573 * we encounter a non-ASCII or non-printable character or don't find
577 print_txt_line(netdissect_options
*ndo
, const char *protoname
,
578 const char *prefix
, const u_char
*pptr
, u_int idx
, u_int len
)
585 ND_TCHECK(*(pptr
+idx
));
586 if (*(pptr
+idx
) == '\n') {
588 * LF without CR; end of line.
589 * Skip the LF and print the line, with the
590 * exception of the LF.
592 linelen
= idx
- startidx
;
595 } else if (*(pptr
+idx
) == '\r') {
597 if ((idx
+1) >= len
) {
598 /* not in this packet */
601 ND_TCHECK(*(pptr
+idx
+1));
602 if (*(pptr
+idx
+1) == '\n') {
604 * CR-LF; end of line.
605 * Skip the CR-LF and print the line, with
606 * the exception of the CR-LF.
608 linelen
= idx
- startidx
;
614 * CR followed by something else; treat this
615 * as if it were binary data, and don't print
619 } else if (!isascii(*(pptr
+idx
)) ||
620 (!isprint(*(pptr
+idx
)) && *(pptr
+idx
) != '\t')) {
622 * Not a printable ASCII character and not a tab;
623 * treat this as if it were binary data, and
632 * All printable ASCII, but no line ending after that point
633 * in the buffer; treat this as if it were truncated.
636 linelen
= idx
- startidx
;
637 ND_PRINT((ndo
, "%s%.*s[!%s]", prefix
, (int)linelen
, pptr
+ startidx
,
642 ND_PRINT((ndo
, "%s%.*s", prefix
, (int)linelen
, pptr
+ startidx
));
647 txtproto_print(netdissect_options
*ndo
, const u_char
*pptr
, u_int len
,
648 const char *protoname
, const char **cmds
, u_int flags
)
651 u_char token
[MAX_TOKEN
+1];
658 * This protocol has more than just request and
659 * response lines; see whether this looks like a
660 * request or response.
662 idx
= fetch_token(ndo
, pptr
, 0, len
, token
, sizeof(token
));
664 /* Is this a valid request name? */
665 while ((cmd
= *cmds
++) != NULL
) {
666 if (strcasecmp((const char *)token
, cmd
) == 0) {
674 * No - is this a valid response code (3 digits)?
676 * Is this token the response code, or is the next
677 * token the response code?
679 if (flags
& RESP_CODE_SECOND_TOKEN
) {
681 * Next token - get it.
683 idx
= fetch_token(ndo
, pptr
, idx
, len
, token
,
687 if (isdigit(token
[0]) && isdigit(token
[1]) &&
688 isdigit(token
[2]) && token
[3] == '\0') {
696 * This protocol has only request and response lines
697 * (e.g., FTP, where all the data goes over a
698 * different connection); assume the payload is
699 * a request or response.
704 /* Capitalize the protocol name */
705 for (pnp
= protoname
; *pnp
!= '\0'; pnp
++)
706 ND_PRINT((ndo
, "%c", toupper(*pnp
)));
710 * In non-verbose mode, just print the protocol, followed
711 * by the first line as the request or response info.
713 * In verbose mode, print lines as text until we run out
714 * of characters or see something that's not a
715 * printable-ASCII line.
717 if (ndo
->ndo_vflag
) {
719 * We're going to print all the text lines in the
720 * request or response; just print the length
721 * on the first line of the output.
723 ND_PRINT((ndo
, ", length: %u", len
));
725 idx
< len
&& (eol
= print_txt_line(ndo
, protoname
, "\n\t", pptr
, idx
, len
)) != 0;
730 * Just print the first text line.
732 print_txt_line(ndo
, protoname
, ": ", pptr
, 0, len
);
739 error(const char *fmt
, ...)
743 (void)fprintf(stderr
, "%s: ", program_name
);
745 (void)vfprintf(stderr
, fmt
, ap
);
750 (void)fputc('\n', stderr
);
758 warning(const char *fmt
, ...)
762 (void)fprintf(stderr
, "%s: WARNING: ", program_name
);
764 (void)vfprintf(stderr
, fmt
, ap
);
769 (void)fputc('\n', stderr
);
774 * Copy arg vector into a new buffer, concatenating arguments with spaces.
777 copy_argv(register char **argv
)
780 register u_int len
= 0;
789 len
+= strlen(*p
++) + 1;
791 buf
= (char *)malloc(len
);
793 error("copy_argv: malloc");
797 while ((src
= *p
++) != NULL
) {
798 while ((*dst
++ = *src
++) != '\0')
808 * On Windows, we need to open the file in binary mode, so that
809 * we get all the bytes specified by the size we get from "fstat()".
810 * On UNIX, that's not necessary. O_BINARY is defined on Windows;
811 * we define it as 0 if it's not defined, so it does nothing.
818 read_infile(char *fname
)
820 register int i
, fd
, cc
;
824 fd
= open(fname
, O_RDONLY
|O_BINARY
);
826 error("can't open %s: %s", fname
, pcap_strerror(errno
));
828 if (fstat(fd
, &buf
) < 0)
829 error("can't stat %s: %s", fname
, pcap_strerror(errno
));
831 cp
= malloc((u_int
)buf
.st_size
+ 1);
833 error("malloc(%d) for %s: %s", (u_int
)buf
.st_size
+ 1,
834 fname
, pcap_strerror(errno
));
835 cc
= read(fd
, cp
, (u_int
)buf
.st_size
);
837 error("read %s: %s", fname
, pcap_strerror(errno
));
838 if (cc
!= buf
.st_size
)
839 error("short read %s (%d != %d)", fname
, cc
, (int)buf
.st_size
);
842 /* replace "# comment" with spaces */
843 for (i
= 0; i
< cc
; i
++) {
845 while (i
< cc
&& cp
[i
] != '\n')
853 safeputs(netdissect_options
*ndo
,
854 const u_char
*s
, const u_int maxlen
)
858 while (*s
&& idx
< maxlen
) {
859 safeputchar(ndo
, *s
);
866 safeputchar(netdissect_options
*ndo
,
869 ND_PRINT((ndo
, (c
< 0x80 && ND_ISPRINT(c
)) ? "%c" : "\\0x%02x", c
));
874 * Some compilers try to optimize memcpy(), using the alignment constraint
875 * on the argument pointer type. by using this function, we try to avoid the
879 unaligned_memcpy(void *p
, const void *q
, size_t l
)
884 /* As with memcpy(), so with memcmp(). */
886 unaligned_memcmp(const void *p
, const void *q
, size_t l
)
888 return (memcmp(p
, q
, l
));