4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
34 #include <sys/types.h>
37 #include <sys/bufmod.h>
40 #include <sys/socket.h>
42 #include <netinet/in_systm.h>
43 #include <netinet/in.h>
44 #include <netinet/ip.h>
45 #include <netinet/if_ether.h>
46 #include <rpc/types.h>
53 char *src_name
, *dst_name
;
61 #define MIN(a, b) ((a) < (b) ? (a) : (b))
64 static void hexdump(char *, int);
67 * This routine invokes the packet interpreters
68 * on a packet. There's some messing around
69 * setting up a few packet-externals before
70 * starting with the ethernet interpreter.
71 * Yes, we assume here that all packets will
72 * be ethernet packets.
75 process_pkt(struct sb_hdr
*hdrp
, char *pktp
, int num
, int flags
)
83 static struct timeval ptv
;
88 tvp
= &hdrp
->sbh_timestamp
;
91 drops
= hdrp
->sbh_drops
;
92 pktlen
= hdrp
->sbh_msglen
;
96 /* set up externals */
99 tm
= localtime(&tvp
->tv_sec
);
100 pi_time_hour
= tm
->tm_hour
;
101 pi_time_min
= tm
->tm_min
;
102 pi_time_sec
= tm
->tm_sec
;
103 pi_time_usec
= tvp
->tv_usec
;
108 click(hdrp
->sbh_origlen
);
110 (*interface
->interpreter
)(flags
, dlc_header
, hdrp
->sbh_msglen
,
113 show_pktinfo(flags
, num
, src_name
, dst_name
, &ptv
, tvp
, drops
,
117 offset
= MIN(x_offset
, hdrp
->sbh_msglen
);
118 offset
-= (offset
% 2); /* round down */
119 length
= MIN(hdrp
->sbh_msglen
- offset
, x_length
);
121 hexdump(dlc_header
+ offset
, length
);
129 * *************************************************************
130 * The following routines constitute a library
131 * used by the packet interpreters to facilitate
132 * the display of packet data. This library
133 * of routines helps provide a consistent
139 * Display the value of a flag bit in
140 * a byte together with some text that
141 * corresponds to its value - whether
145 getflag(int val
, int mask
, char *s_true
, char *s_false
)
147 static char buff
[80];
151 (void) strcpy(buff
, ".... .... = ");
155 for (p
= &buff
[8]; p
>= buff
; p
--) {
159 set
= val
& mask
& 0x1;
161 (void) strcat(buff
, set
? s_true
: s_false
);
174 char *prot_nest_prefix
= "";
178 show_header(char *pref
, char *str
, int len
)
182 (void) sprintf(get_detail_line(0, len
), "%s%s----- %s -----",
183 prot_nest_prefix
, pref
, str
);
187 xdr_init(char *addr
, int len
)
190 xdrmem_create(&xdrm
, addr
, len
, XDR_DECODE
);
193 /* Note: begin+end are ignored in get_detail_line */
195 get_line(int begin
, int end
)
199 line
= get_detail_line(begin
, end
);
200 (void) strcpy(line
, prot_nest_prefix
);
201 (void) strcat(line
, prot_prefix
);
202 return (line
+ strlen(line
));
206 get_line_remain(void)
208 return (MAXLINE
- strlen(prot_nest_prefix
) - strlen(prot_prefix
));
214 (void) strlcpy(get_line(0, 0), str
, get_line_remain());
218 show_printf(char *fmt
, ...)
223 (void) vsnprintf(get_line(0, 0), get_line_remain(), fmt
, ap
);
232 if (xdr_char(&xdrm
, &s
))
239 showxdr_char(char *fmt
)
245 (void) sprintf(get_line(pos
, getxdr_pos()), fmt
, val
);
254 if (xdr_u_char(&xdrm
, &s
))
261 showxdr_u_char(char *fmt
)
267 val
= getxdr_u_char();
268 (void) sprintf(get_line(pos
, getxdr_pos()), fmt
, val
);
277 if (xdr_short(&xdrm
, &s
))
284 showxdr_short(char *fmt
)
289 val
= getxdr_short();
290 (void) sprintf(get_line(pos
, getxdr_pos()), fmt
, val
);
299 if (xdr_u_short(&xdrm
, &s
))
306 showxdr_u_short(char *fmt
)
312 val
= getxdr_u_short();
313 (void) sprintf(get_line(pos
, getxdr_pos()), fmt
, val
);
322 if (xdr_long(&xdrm
, &l
))
329 showxdr_long(char *fmt
)
335 (void) sprintf(get_line(pos
, getxdr_pos()), fmt
, val
);
344 if (xdr_u_long(&xdrm
, &l
))
351 showxdr_u_long(char *fmt
)
357 val
= getxdr_u_long();
358 (void) sprintf(get_line(pos
, getxdr_pos()), fmt
, val
);
367 if (xdr_longlong_t(&xdrm
, &l
))
374 showxdr_longlong(char *fmt
)
376 int pos
; longlong_t val
;
379 val
= getxdr_longlong();
380 (void) sprintf(get_line(pos
, getxdr_pos()), fmt
, val
);
389 if (xdr_u_longlong_t(&xdrm
, &l
))
396 showxdr_u_longlong(char *fmt
)
398 int pos
; u_longlong_t val
;
401 val
= getxdr_u_longlong();
402 (void) sprintf(get_line(pos
, getxdr_pos()), fmt
, val
);
411 if (xdr_bool(&xdrm
, &b
))
418 showxdr_bool(char *fmt
)
424 (void) sprintf(get_line(pos
, getxdr_pos()), fmt
,
425 val
? "True" : "False");
430 getxdr_opaque(char *p
, int len
)
432 if (xdr_opaque(&xdrm
, p
, len
))
439 getxdr_string(char *p
, /* len+1 bytes or longer */
442 if (xdr_string(&xdrm
, &p
, len
))
449 showxdr_string(int len
, /* XDR length */
452 static int buff_len
= 0;
453 static char *buff
= NULL
;
457 * XDR strings don't necessarily have a trailing null over the
458 * wire. However, the XDR code will put one in for us. Make sure
459 * we have allocated room for it.
463 if ((len
> buff_len
) || (buff_len
== 0)) {
465 if ((buff
= (char *)malloc(len
)) == NULL
)
466 pr_err("showxdr_string: no mem");
470 getxdr_string(buff
, len
);
471 (void) strcpy(buff
+60, "...");
472 (void) sprintf(get_line(pos
, getxdr_pos()), fmt
, buff
);
477 getxdr_bytes(uint_t
*lenp
)
479 static char buff
[1024];
482 if (xdr_bytes(&xdrm
, &p
, lenp
, 1024))
489 getxdr_context(char *p
, int len
)
493 size
= getxdr_u_short();
494 if (((int)size
> 0) && ((int)size
< len
) && getxdr_opaque(p
, size
))
501 showxdr_context(char *fmt
)
504 static char buff
[1024];
508 size
= getxdr_u_short();
509 if (((int)size
> 0) && ((int)size
< 1024) &&
510 getxdr_opaque(buff
, size
)) {
511 (void) sprintf(get_line(pos
, getxdr_pos()), fmt
, buff
);
523 if (xdr_enum(&xdrm
, &e
))
533 if (delta
% 4 != 0 || delta
< 0)
535 /* Check for overflow */
536 pos
= xdr_getpos(&xdrm
);
537 if ((pos
+ delta
) < pos
)
539 /* xdr_setpos() checks for buffer overrun */
540 if (xdr_setpos(&xdrm
, pos
+ delta
) == FALSE
)
547 return (xdr_getpos(&xdrm
));
553 xdr_setpos(&xdrm
, pos
);
559 (void) get_line(0, 0);
573 static char buff
[64];
575 struct tm my_time
; /* private buffer to avoid collision */
576 /* between gmtime and strftime */
580 usec
= getxdr_long();
584 if (sec
< 3600 * 24 * 365) { /* assume not a date */
585 (void) sprintf(buff
, "%d.%06d", sec
, usec
);
588 (void) memcpy(&my_time
, tmp
, sizeof (struct tm
));
589 strftime(buff
, sizeof (buff
), "%d-%h-%y %T.", &my_time
);
590 p
= buff
+ strlen(buff
);
591 (void) sprintf(p
, "%06d GMT", usec
);
597 showxdr_date(char *fmt
)
604 (void) sprintf(get_line(pos
, getxdr_pos()), fmt
, p
);
614 nsec
= getxdr_long();
618 return (format_time(sec
, nsec
));
622 * Format the given time.
625 format_time(int64_t sec
, uint32_t nsec
)
627 static char buff
[64];
629 struct tm my_time
; /* private buffer to avoid collision */
630 /* between gmtime and strftime */
633 if (sec
< 3600 * 24 * 365) {
634 /* assume not a date; includes negative times */
635 (void) sprintf(buff
, "%lld.%06d", sec
, nsec
);
636 } else if (sec
> INT32_MAX
) {
638 * XXX No routines are available yet for formatting 64-bit
641 (void) sprintf(buff
, "%lld.%06d", sec
, nsec
);
643 time_t sec32
= (time_t)sec
;
645 tmp
= gmtime(&sec32
);
646 memcpy(&my_time
, tmp
, sizeof (struct tm
));
647 strftime(buff
, sizeof (buff
), "%d-%h-%y %T.", &my_time
);
648 p
= buff
+ strlen(buff
);
649 (void) sprintf(p
, "%09d GMT", nsec
);
655 showxdr_date_ns(char *fmt
)
661 p
= getxdr_date_ns();
662 (void) sprintf(get_line(pos
, getxdr_pos()), fmt
, p
);
670 static char buff
[64];
671 struct tm my_time
; /* private buffer to avoid collision */
672 /* between gmtime and strftime */
679 if (sec
< 3600 * 24 * 365) { /* assume not a date */
680 (void) sprintf(buff
, "%d", sec
);
683 memcpy(&my_time
, tmp
, sizeof (struct tm
));
684 strftime(buff
, sizeof (buff
), "%d-%h-%y %T", &my_time
);
690 showxdr_time(char *fmt
)
697 (void) sprintf(get_line(pos
, getxdr_pos()), fmt
, p
);
705 static char hbuff
[1024];
707 static char *hexstr
= "0123456789ABCDEF";
716 if (len
< 0 || xdr_opaque(&xdrm
, rbuff
, len
) == FALSE
) {
720 if (len
* 2 > sizeof (hbuff
)) {
722 len
= sizeof (hbuff
) / 2;
726 for (i
= 0; i
< len
; i
++) {
727 hbuff
[j
++] = hexstr
[rbuff
[i
] >> 4 & 0x0f];
728 hbuff
[j
++] = hexstr
[rbuff
[i
] & 0x0f];
732 hbuff
[len
* 2 - strlen("<Too Long>")] = '\0';
733 strcat(hbuff
, "<Too Long>");
741 showxdr_hex(int len
, char *fmt
)
748 (void) sprintf(get_line(pos
, getxdr_pos()), fmt
, p
);
753 hexdump(char *data
, int datalen
)
756 ushort_t
*p16
= (ushort_t
*)data
;
759 int chunk
= 16; /* 16 bytes per line */
763 for (p
= data
; p
< data
+ datalen
; p
+= chunk
) {
764 printf("\t%4d: ", p
- data
);
765 left
= (data
+ datalen
) - p
;
766 len
= MIN(chunk
, left
);
767 for (i
= 0; i
< (len
/ 2); i
++)
768 printf("%04x ", ntohs(*p16
++) & 0xffff);
770 printf("%02x ", *((unsigned char *)p16
));
772 for (i
= 0; i
< (chunk
- left
) / 2; i
++)
776 for (i
= 0; i
< len
; i
++, p8
++)
777 printf("%c", isprint(*p8
) ? *p8
: '.');
785 show_string(const char *str
, int dlen
, int maxlen
)
787 * Prints len bytes from str enclosed in quotes.
788 * If len is negative, length is taken from strlen(str).
789 * No more than maxlen bytes will be printed. Longer
790 * strings are flagged with ".." after the closing quote.
791 * Non-printing characters are converted to C-style escape
792 * codes or octal digits.
796 static char tbuff
[TBSIZE
];
802 len
= dlen
> maxlen
? maxlen
: dlen
;
805 for (p
= str
, pp
= tbuff
; len
; p
++, len
--) {
806 switch (c
= *p
& 0xFF) {
807 case '\n': (void) strcpy(pp
, "\\n"); pp
+= 2; break;
808 case '\b': (void) strcpy(pp
, "\\b"); pp
+= 2; break;
809 case '\t': (void) strcpy(pp
, "\\t"); pp
+= 2; break;
810 case '\r': (void) strcpy(pp
, "\\r"); pp
+= 2; break;
811 case '\f': (void) strcpy(pp
, "\\f"); pp
+= 2; break;
813 if (isascii(c
) && isprint(c
)) {
817 (void) snprintf(pp
, TBSIZE
- (pp
- tbuff
),
819 "\\%03o" : "\\%o", c
);
826 * Check for overflow of temporary buffer. Allow for
827 * the next character to be a \nnn followed by a trailing
828 * null. If not, then just bail with what we have.
830 if (pp
+ 5 >= &tbuff
[TBSIZE
]) {
834 return (printable
> dlen
/ 2 ? tbuff
: "");