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.
42 #include <tcpdump-stdinc.h>
54 #include "interface.h"
56 int32_t thiszone
; /* seconds offset from gmt to local time */
59 * Print out a null-terminated filename (or other ascii string).
60 * If ep is NULL, assume no truncation check is needed.
61 * Return true if truncated.
64 fn_print(netdissect_options
*ndo
,
65 register const u_char
*s
, register const u_char
*ep
)
70 ret
= 1; /* assume truncated */
71 while (ep
== NULL
|| s
< ep
) {
79 ND_PRINT((ndo
, "M-"));
82 c
^= 0x40; /* DEL to ?, others to alpha */
85 ND_PRINT((ndo
, "%c", c
));
91 * Print out a counted filename (or other ascii string).
92 * If ep is NULL, assume no truncation check is needed.
93 * Return true if truncated.
96 fn_printn(netdissect_options
*ndo
,
97 register const u_char
*s
, register u_int n
, register const u_char
*ep
)
101 while (n
> 0 && (ep
== NULL
|| s
< ep
)) {
104 if (!ND_ISASCII(c
)) {
106 ND_PRINT((ndo
, "M-"));
108 if (!ND_ISPRINT(c
)) {
109 c
^= 0x40; /* DEL to ?, others to alpha */
110 ND_PRINT((ndo
, "^"));
112 ND_PRINT((ndo
, "%c", c
));
114 return (n
== 0) ? 0 : 1;
118 * Print out a null-padded filename (or other ascii string).
119 * If ep is NULL, assume no truncation check is needed.
120 * Return true if truncated.
123 fn_printzp(netdissect_options
*ndo
,
124 register const u_char
*s
, register u_int n
,
125 register const u_char
*ep
)
130 ret
= 1; /* assume truncated */
131 while (n
> 0 && (ep
== NULL
|| s
< ep
)) {
138 if (!ND_ISASCII(c
)) {
140 ND_PRINT((ndo
, "M-"));
142 if (!ND_ISPRINT(c
)) {
143 c
^= 0x40; /* DEL to ?, others to alpha */
144 ND_PRINT((ndo
, "^"));
146 ND_PRINT((ndo
, "%c", c
));
148 return (n
== 0) ? 0 : ret
;
152 * Format the timestamp
155 ts_format(netdissect_options
*ndo
156 #ifndef HAVE_PCAP_SET_TSTAMP_PRECISION
161 static char buf
[sizeof("00:00:00.000000000")];
164 #ifdef HAVE_PCAP_SET_TSTAMP_PRECISION
165 switch (ndo
->ndo_tstamp_precision
) {
167 case PCAP_TSTAMP_PRECISION_MICRO
:
168 format
= "%02d:%02d:%02d.%06u";
171 case PCAP_TSTAMP_PRECISION_NANO
:
172 format
= "%02d:%02d:%02d.%09u";
176 format
= "%02d:%02d:%02d.{unknown precision}";
180 format
= "%02d:%02d:%02d.%06u";
183 snprintf(buf
, sizeof(buf
), format
,
184 sec
/ 3600, (sec
% 3600) / 60, sec
% 60, usec
);
190 * Print the timestamp
193 ts_print(netdissect_options
*ndo
,
194 register const struct timeval
*tvp
)
199 static unsigned b_sec
;
200 static unsigned b_usec
;
204 switch (ndo
->ndo_tflag
) {
206 case 0: /* Default */
207 s
= (tvp
->tv_sec
+ thiszone
) % 86400;
208 ND_PRINT((ndo
, "%s ", ts_format(ndo
, s
, tvp
->tv_usec
)));
211 case 1: /* No time stamp */
214 case 2: /* Unix timeval style */
215 ND_PRINT((ndo
, "%u.%06u ",
216 (unsigned)tvp
->tv_sec
,
217 (unsigned)tvp
->tv_usec
));
220 case 3: /* Microseconds since previous packet */
221 case 5: /* Microseconds since first packet */
223 /* init timestamp for first packet */
224 b_usec
= tvp
->tv_usec
;
228 d_usec
= tvp
->tv_usec
- b_usec
;
229 d_sec
= tvp
->tv_sec
- b_sec
;
236 ND_PRINT((ndo
, "%s ", ts_format(ndo
, d_sec
, d_usec
)));
238 if (ndo
->ndo_tflag
== 3) { /* set timestamp for last packet */
240 b_usec
= tvp
->tv_usec
;
244 case 4: /* Default + Date*/
245 s
= (tvp
->tv_sec
+ thiszone
) % 86400;
246 Time
= (tvp
->tv_sec
+ thiszone
) - s
;
249 ND_PRINT((ndo
, "Date fail "));
251 ND_PRINT((ndo
, "%04d-%02d-%02d %s ",
252 tm
->tm_year
+1900, tm
->tm_mon
+1, tm
->tm_mday
,
253 ts_format(ndo
, s
, tvp
->tv_usec
)));
259 * Print a relative number of seconds (e.g. hold time, prune timer)
260 * in the form 5m1s. This does no truncation, so 32230861 seconds
261 * is represented as 1y1w1d1h1m1s.
264 relts_print(netdissect_options
*ndo
,
267 static const char *lengths
[] = {"y", "w", "d", "h", "m", "s"};
268 static const int seconds
[] = {31536000, 604800, 86400, 3600, 60, 1};
269 const char **l
= lengths
;
270 const int *s
= seconds
;
273 ND_PRINT((ndo
, "0s"));
277 ND_PRINT((ndo
, "-"));
282 ND_PRINT((ndo
, "%d%s", secs
/ *s
, *l
));
283 secs
-= (secs
/ *s
) * *s
;
291 * this is a generic routine for printing unknown data;
292 * we pass on the linefeed plus indentation string to
293 * get a proper output - returns 0 on error
297 print_unknown_data(netdissect_options
*ndo
, const u_char
*cp
,const char *ident
,int len
)
300 ND_PRINT((ndo
,"%sDissector error: print_unknown_data called with negative length",
304 if (ndo
->ndo_snapend
- cp
< len
)
305 len
= ndo
->ndo_snapend
- cp
;
307 ND_PRINT((ndo
,"%sDissector error: print_unknown_data called with pointer past end of packet",
311 hex_print(ndo
, ident
,cp
,len
);
312 return(1); /* everything is ok */
316 * Convert a token value to a string; use "fmt" if not found.
319 tok2strbuf(register const struct tok
*lp
, register const char *fmt
,
320 register u_int v
, char *buf
, size_t bufsize
)
323 while (lp
->s
!= NULL
) {
332 (void)snprintf(buf
, bufsize
, fmt
, v
);
333 return (const char *)buf
;
337 * Convert a token value to a string; use "fmt" if not found.
340 tok2str(register const struct tok
*lp
, register const char *fmt
,
343 static char buf
[4][128];
349 return tok2strbuf(lp
, fmt
, v
, ret
, sizeof(buf
[0]));
353 * Convert a bit token value to a string; use "fmt" if not found.
354 * this is useful for parsing bitfields, the output strings are seperated
355 * if the s field is positive.
358 bittok2str_internal(register const struct tok
*lp
, register const char *fmt
,
359 register u_int v
, const char *sep
)
361 static char buf
[256]; /* our stringbuffer */
363 register u_int rotbit
; /* this is the bit we rotate through all bitpositions */
364 register u_int tokval
;
365 const char * sepstr
= "";
367 while (lp
!= NULL
&& lp
->s
!= NULL
) {
368 tokval
=lp
->v
; /* load our first value */
370 while (rotbit
!= 0) {
372 * lets AND the rotating bit with our token value
373 * and see if we have got a match
375 if (tokval
== (v
&rotbit
)) {
376 /* ok we have found something */
377 buflen
+=snprintf(buf
+buflen
, sizeof(buf
)-buflen
, "%s%s",
382 rotbit
=rotbit
<<1; /* no match - lets shift and try again */
388 /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
389 (void)snprintf(buf
, sizeof(buf
), fmt
== NULL
? "#%08x" : fmt
, v
);
394 * Convert a bit token value to a string; use "fmt" if not found.
395 * this is useful for parsing bitfields, the output strings are not seperated.
398 bittok2str_nosep(register const struct tok
*lp
, register const char *fmt
,
401 return (bittok2str_internal(lp
, fmt
, v
, ""));
405 * Convert a bit token value to a string; use "fmt" if not found.
406 * this is useful for parsing bitfields, the output strings are comma seperated.
409 bittok2str(register const struct tok
*lp
, register const char *fmt
,
412 return (bittok2str_internal(lp
, fmt
, v
, ", "));
416 * Convert a value to a string using an array; the macro
417 * tok2strary() in <interface.h> is the public interface to
418 * this function and ensures that the second argument is
419 * correct for bounds-checking.
422 tok2strary_internal(register const char **lp
, int n
, register const char *fmt
,
425 static char buf
[128];
427 if (v
>= 0 && v
< n
&& lp
[v
] != NULL
)
431 (void)snprintf(buf
, sizeof(buf
), fmt
, v
);
436 * Convert a 32-bit netmask to prefixlen if possible
437 * the function returns the prefix-len; if plen == -1
438 * then conversion was not possible;
442 mask2plen(uint32_t mask
)
444 uint32_t bitmasks
[33] = {
446 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
447 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
448 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
449 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
450 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
451 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
452 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
453 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
457 /* let's see if we can transform the mask into a prefixlen */
458 while (prefix_len
>= 0) {
459 if (bitmasks
[prefix_len
] == mask
)
468 mask62plen(const u_char
*mask
)
470 u_char bitmasks
[9] = {
472 0x80, 0xc0, 0xe0, 0xf0,
473 0xf8, 0xfc, 0xfe, 0xff
478 for (byte
= 0; byte
< 16; byte
++) {
481 for (bits
= 0; bits
< (sizeof (bitmasks
) / sizeof (bitmasks
[0])); bits
++) {
482 if (mask
[byte
] == bitmasks
[bits
]) {
488 if (mask
[byte
] != 0xff)
496 * Routine to print out information for text-based protocols such as FTP,
497 * HTTP, SMTP, RTSP, SIP, ....
499 #define MAX_TOKEN 128
502 * Fetch a token from a packet, starting at the specified index,
503 * and return the length of the token.
505 * Returns 0 on error; yes, this is indistinguishable from an empty
506 * token, but an "empty token" isn't a valid token - it just means
507 * either a space character at the beginning of the line (this
508 * includes a blank line) or no more tokens remaining on the line.
511 fetch_token(netdissect_options
*ndo
, const u_char
*pptr
, u_int idx
, u_int len
,
512 u_char
*tbuf
, size_t tbuflen
)
516 for (; idx
< len
; idx
++) {
517 if (!ND_TTEST(*(pptr
+ idx
))) {
518 /* ran past end of captured data */
521 if (!isascii(*(pptr
+ idx
))) {
522 /* not an ASCII character */
525 if (isspace(*(pptr
+ idx
))) {
529 if (!isprint(*(pptr
+ idx
))) {
530 /* not part of a command token or response code */
533 if (toklen
+ 2 > tbuflen
) {
534 /* no room for this character and terminating '\0' */
537 tbuf
[toklen
] = *(pptr
+ idx
);
547 * Skip past any white space after the token, until we see
548 * an end-of-line (CR or LF).
550 for (; idx
< len
; idx
++) {
551 if (!ND_TTEST(*(pptr
+ idx
))) {
552 /* ran past end of captured data */
555 if (*(pptr
+ idx
) == '\r' || *(pptr
+ idx
) == '\n') {
559 if (!isascii(*(pptr
+ idx
)) || !isprint(*(pptr
+ idx
))) {
560 /* not a printable ASCII character */
563 if (!isspace(*(pptr
+ idx
))) {
564 /* beginning of next token */
572 * Scan a buffer looking for a line ending - LF or CR-LF.
573 * Return the index of the character after the line ending or 0 if
574 * we encounter a non-ASCII or non-printable character or don't find
578 print_txt_line(netdissect_options
*ndo
, const char *protoname
,
579 const char *prefix
, const u_char
*pptr
, u_int idx
, u_int len
)
586 ND_TCHECK(*(pptr
+idx
));
587 if (*(pptr
+idx
) == '\n') {
589 * LF without CR; end of line.
590 * Skip the LF and print the line, with the
591 * exception of the LF.
593 linelen
= idx
- startidx
;
596 } else if (*(pptr
+idx
) == '\r') {
598 if ((idx
+1) >= len
) {
599 /* not in this packet */
602 ND_TCHECK(*(pptr
+idx
+1));
603 if (*(pptr
+idx
+1) == '\n') {
605 * CR-LF; end of line.
606 * Skip the CR-LF and print the line, with
607 * the exception of the CR-LF.
609 linelen
= idx
- startidx
;
615 * CR followed by something else; treat this
616 * as if it were binary data, and don't print
620 } else if (!isascii(*(pptr
+idx
)) ||
621 (!isprint(*(pptr
+idx
)) && *(pptr
+idx
) != '\t')) {
623 * Not a printable ASCII character and not a tab;
624 * treat this as if it were binary data, and
633 * All printable ASCII, but no line ending after that point
634 * in the buffer; treat this as if it were truncated.
637 linelen
= idx
- startidx
;
638 ND_PRINT((ndo
, "%s%.*s[!%s]", prefix
, (int)linelen
, pptr
+ startidx
,
643 ND_PRINT((ndo
, "%s%.*s", prefix
, (int)linelen
, pptr
+ startidx
));
648 txtproto_print(netdissect_options
*ndo
, const u_char
*pptr
, u_int len
,
649 const char *protoname
, const char **cmds
, u_int flags
)
652 u_char token
[MAX_TOKEN
+1];
659 * This protocol has more than just request and
660 * response lines; see whether this looks like a
661 * request or response.
663 idx
= fetch_token(ndo
, pptr
, 0, len
, token
, sizeof(token
));
665 /* Is this a valid request name? */
666 while ((cmd
= *cmds
++) != NULL
) {
667 if (strcasecmp((const char *)token
, cmd
) == 0) {
675 * No - is this a valid response code (3 digits)?
677 * Is this token the response code, or is the next
678 * token the response code?
680 if (flags
& RESP_CODE_SECOND_TOKEN
) {
682 * Next token - get it.
684 idx
= fetch_token(ndo
, pptr
, idx
, len
, token
,
688 if (isdigit(token
[0]) && isdigit(token
[1]) &&
689 isdigit(token
[2]) && token
[3] == '\0') {
697 * This protocol has only request and response lines
698 * (e.g., FTP, where all the data goes over a
699 * different connection); assume the payload is
700 * a request or response.
705 /* Capitalize the protocol name */
706 for (pnp
= protoname
; *pnp
!= '\0'; pnp
++)
707 ND_PRINT((ndo
, "%c", toupper(*pnp
)));
711 * In non-verbose mode, just print the protocol, followed
712 * by the first line as the request or response info.
714 * In verbose mode, print lines as text until we run out
715 * of characters or see something that's not a
716 * printable-ASCII line.
718 if (ndo
->ndo_vflag
) {
720 * We're going to print all the text lines in the
721 * request or response; just print the length
722 * on the first line of the output.
724 ND_PRINT((ndo
, ", length: %u", len
));
726 idx
< len
&& (eol
= print_txt_line(ndo
, protoname
, "\n\t", pptr
, idx
, len
)) != 0;
731 * Just print the first text line.
733 print_txt_line(ndo
, protoname
, ": ", pptr
, 0, len
);
739 safeputs(netdissect_options
*ndo
,
740 const u_char
*s
, const u_int maxlen
)
744 while (*s
&& idx
< maxlen
) {
745 safeputchar(ndo
, *s
);
752 safeputchar(netdissect_options
*ndo
,
755 ND_PRINT((ndo
, (c
< 0x80 && ND_ISPRINT(c
)) ? "%c" : "\\0x%02x", c
));
760 * Some compilers try to optimize memcpy(), using the alignment constraint
761 * on the argument pointer type. by using this function, we try to avoid the
765 unaligned_memcpy(void *p
, const void *q
, size_t l
)
770 /* As with memcpy(), so with memcmp(). */
772 unaligned_memcmp(const void *p
, const void *q
, size_t l
)
774 return (memcmp(p
, q
, l
));