dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.sbin / snoop / snoop_display.c
blobc4ff25f5a24efbba386e186c75dc1cc269ded826
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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.
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <ctype.h>
31 #include <string.h>
32 #include <fcntl.h>
33 #include <string.h>
34 #include <sys/types.h>
35 #include <time.h>
36 #include <sys/time.h>
37 #include <sys/bufmod.h>
38 #include <setjmp.h>
39 #include <stdarg.h>
40 #include <sys/socket.h>
41 #include <net/if.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>
47 #include <rpc/xdr.h>
48 #include <inttypes.h>
50 #include "snoop.h"
52 char *dlc_header;
53 char *src_name, *dst_name;
54 int pi_frame;
55 int pi_time_hour;
56 int pi_time_min;
57 int pi_time_sec;
58 int pi_time_usec;
60 #ifndef MIN
61 #define MIN(a, b) ((a) < (b) ? (a) : (b))
62 #endif
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.
74 void
75 process_pkt(struct sb_hdr *hdrp, char *pktp, int num, int flags)
77 int drops, pktlen;
78 struct timeval *tvp;
79 struct tm *tm;
80 extern int x_offset;
81 extern int x_length;
82 int offset, length;
83 static struct timeval ptv;
85 if (hdrp == NULL)
86 return;
88 tvp = &hdrp->sbh_timestamp;
89 if (ptv.tv_sec == 0)
90 ptv = *tvp;
91 drops = hdrp->sbh_drops;
92 pktlen = hdrp->sbh_msglen;
93 if (pktlen <= 0)
94 return;
96 /* set up externals */
97 dlc_header = pktp;
98 pi_frame = num;
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;
105 src_name = "?";
106 dst_name = "*";
108 click(hdrp->sbh_origlen);
110 (*interface->interpreter)(flags, dlc_header, hdrp->sbh_msglen,
111 hdrp->sbh_origlen);
113 show_pktinfo(flags, num, src_name, dst_name, &ptv, tvp, drops,
114 hdrp->sbh_origlen);
116 if (x_offset >= 0) {
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);
124 ptv = *tvp;
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
134 * "look and feel".
139 * Display the value of a flag bit in
140 * a byte together with some text that
141 * corresponds to its value - whether
142 * true or false.
144 char *
145 getflag(int val, int mask, char *s_true, char *s_false)
147 static char buff[80];
148 char *p;
149 int set;
151 (void) strcpy(buff, ".... .... = ");
152 if (s_false == NULL)
153 s_false = s_true;
155 for (p = &buff[8]; p >= buff; p--) {
156 if (*p == ' ')
157 p--;
158 if (mask & 0x1) {
159 set = val & mask & 0x1;
160 *p = set ? '1':'0';
161 (void) strcat(buff, set ? s_true: s_false);
162 break;
164 mask >>= 1;
165 val >>= 1;
167 return (buff);
170 XDR xdrm;
171 jmp_buf xdr_err;
172 int xdr_totlen;
173 char *prot_prefix;
174 char *prot_nest_prefix = "";
175 char *prot_title;
177 void
178 show_header(char *pref, char *str, int len)
180 prot_prefix = pref;
181 prot_title = str;
182 (void) sprintf(get_detail_line(0, len), "%s%s----- %s -----",
183 prot_nest_prefix, pref, str);
186 void
187 xdr_init(char *addr, int len)
189 xdr_totlen = len;
190 xdrmem_create(&xdrm, addr, len, XDR_DECODE);
193 /* Note: begin+end are ignored in get_detail_line */
194 char *
195 get_line(int begin, int end)
197 char *line;
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));
211 void
212 show_line(char *str)
214 (void) strlcpy(get_line(0, 0), str, get_line_remain());
217 void
218 show_printf(char *fmt, ...)
220 va_list ap;
222 va_start(ap, fmt);
223 (void) vsnprintf(get_line(0, 0), get_line_remain(), fmt, ap);
224 va_end(ap);
227 char
228 getxdr_char()
230 char s;
232 if (xdr_char(&xdrm, &s))
233 return (s);
234 longjmp(xdr_err, 1);
235 /* NOTREACHED */
238 char
239 showxdr_char(char *fmt)
241 int pos; char val;
243 pos = getxdr_pos();
244 val = getxdr_char();
245 (void) sprintf(get_line(pos, getxdr_pos()), fmt, val);
246 return (val);
249 uchar_t
250 getxdr_u_char()
252 uchar_t s;
254 if (xdr_u_char(&xdrm, &s))
255 return (s);
256 longjmp(xdr_err, 1);
257 /* NOTREACHED */
260 uchar_t
261 showxdr_u_char(char *fmt)
263 int pos;
264 uchar_t val;
266 pos = getxdr_pos();
267 val = getxdr_u_char();
268 (void) sprintf(get_line(pos, getxdr_pos()), fmt, val);
269 return (val);
272 short
273 getxdr_short()
275 short s;
277 if (xdr_short(&xdrm, &s))
278 return (s);
279 longjmp(xdr_err, 1);
280 /* NOTREACHED */
283 short
284 showxdr_short(char *fmt)
286 int pos; short val;
288 pos = getxdr_pos();
289 val = getxdr_short();
290 (void) sprintf(get_line(pos, getxdr_pos()), fmt, val);
291 return (val);
294 ushort_t
295 getxdr_u_short()
297 ushort_t s;
299 if (xdr_u_short(&xdrm, &s))
300 return (s);
301 longjmp(xdr_err, 1);
302 /* NOTREACHED */
305 ushort_t
306 showxdr_u_short(char *fmt)
308 int pos;
309 ushort_t val;
311 pos = getxdr_pos();
312 val = getxdr_u_short();
313 (void) sprintf(get_line(pos, getxdr_pos()), fmt, val);
314 return (val);
317 long
318 getxdr_long()
320 long l;
322 if (xdr_long(&xdrm, &l))
323 return (l);
324 longjmp(xdr_err, 1);
325 /* NOTREACHED */
328 long
329 showxdr_long(char *fmt)
331 int pos; long val;
333 pos = getxdr_pos();
334 val = getxdr_long();
335 (void) sprintf(get_line(pos, getxdr_pos()), fmt, val);
336 return (val);
339 ulong_t
340 getxdr_u_long()
342 ulong_t l;
344 if (xdr_u_long(&xdrm, &l))
345 return (l);
346 longjmp(xdr_err, 1);
347 /* NOTREACHED */
350 ulong_t
351 showxdr_u_long(char *fmt)
353 int pos;
354 ulong_t val;
356 pos = getxdr_pos();
357 val = getxdr_u_long();
358 (void) sprintf(get_line(pos, getxdr_pos()), fmt, val);
359 return (val);
362 longlong_t
363 getxdr_longlong()
365 longlong_t l;
367 if (xdr_longlong_t(&xdrm, &l))
368 return (l);
369 longjmp(xdr_err, 1);
370 /* NOTREACHED */
373 longlong_t
374 showxdr_longlong(char *fmt)
376 int pos; longlong_t val;
378 pos = getxdr_pos();
379 val = getxdr_longlong();
380 (void) sprintf(get_line(pos, getxdr_pos()), fmt, val);
381 return (val);
384 u_longlong_t
385 getxdr_u_longlong()
387 u_longlong_t l;
389 if (xdr_u_longlong_t(&xdrm, &l))
390 return (l);
391 longjmp(xdr_err, 1);
392 /* NOTREACHED */
395 u_longlong_t
396 showxdr_u_longlong(char *fmt)
398 int pos; u_longlong_t val;
400 pos = getxdr_pos();
401 val = getxdr_u_longlong();
402 (void) sprintf(get_line(pos, getxdr_pos()), fmt, val);
403 return (val);
406 bool_t
407 getxdr_bool()
409 bool_t b;
411 if (xdr_bool(&xdrm, &b))
412 return (b);
413 longjmp(xdr_err, 1);
414 /* NOTREACHED */
417 bool_t
418 showxdr_bool(char *fmt)
420 int pos; bool_t val;
422 pos = getxdr_pos();
423 val = getxdr_bool();
424 (void) sprintf(get_line(pos, getxdr_pos()), fmt,
425 val ? "True" : "False");
426 return (val);
429 char *
430 getxdr_opaque(char *p, int len)
432 if (xdr_opaque(&xdrm, p, len))
433 return (p);
434 longjmp(xdr_err, 1);
435 /* NOTREACHED */
438 char *
439 getxdr_string(char *p, /* len+1 bytes or longer */
440 int len)
442 if (xdr_string(&xdrm, &p, len))
443 return (p);
444 longjmp(xdr_err, 1);
445 /* NOTREACHED */
448 char *
449 showxdr_string(int len, /* XDR length */
450 char *fmt)
452 static int buff_len = 0;
453 static char *buff = NULL;
454 int pos;
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.
461 len++;
463 if ((len > buff_len) || (buff_len == 0)) {
464 free(buff);
465 if ((buff = (char *)malloc(len)) == NULL)
466 pr_err("showxdr_string: no mem");
467 buff_len = len;
469 pos = getxdr_pos();
470 getxdr_string(buff, len);
471 (void) strcpy(buff+60, "...");
472 (void) sprintf(get_line(pos, getxdr_pos()), fmt, buff);
473 return (buff);
476 char *
477 getxdr_bytes(uint_t *lenp)
479 static char buff[1024];
480 char *p = buff;
482 if (xdr_bytes(&xdrm, &p, lenp, 1024))
483 return (buff);
484 longjmp(xdr_err, 1);
485 /* NOTREACHED */
488 char *
489 getxdr_context(char *p, int len)
491 ushort_t size;
493 size = getxdr_u_short();
494 if (((int)size > 0) && ((int)size < len) && getxdr_opaque(p, size))
495 return (p);
496 longjmp(xdr_err, 1);
497 /* NOTREACHED */
500 char *
501 showxdr_context(char *fmt)
503 ushort_t size;
504 static char buff[1024];
505 int pos;
507 pos = getxdr_pos();
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);
512 return (buff);
514 longjmp(xdr_err, 1);
515 /* NOTREACHED */
518 enum_t
519 getxdr_enum()
521 enum_t e;
523 if (xdr_enum(&xdrm, &e))
524 return (e);
525 longjmp(xdr_err, 1);
526 /* NOTREACHED */
529 void
530 xdr_skip(int delta)
532 uint_t pos;
533 if (delta % 4 != 0 || delta < 0)
534 longjmp(xdr_err, 1);
535 /* Check for overflow */
536 pos = xdr_getpos(&xdrm);
537 if ((pos + delta) < pos)
538 longjmp(xdr_err, 1);
539 /* xdr_setpos() checks for buffer overrun */
540 if (xdr_setpos(&xdrm, pos + delta) == FALSE)
541 longjmp(xdr_err, 1);
545 getxdr_pos()
547 return (xdr_getpos(&xdrm));
550 void
551 setxdr_pos(int pos)
553 xdr_setpos(&xdrm, pos);
556 void
557 show_space()
559 (void) get_line(0, 0);
562 void
563 show_trailer()
565 show_space();
568 char *
569 getxdr_date()
571 time_t sec;
572 int usec;
573 static char buff[64];
574 char *p;
575 struct tm my_time; /* private buffer to avoid collision */
576 /* between gmtime and strftime */
577 struct tm *tmp;
579 sec = getxdr_long();
580 usec = getxdr_long();
581 if (sec == -1)
582 return ("-1 ");
584 if (sec < 3600 * 24 * 365) { /* assume not a date */
585 (void) sprintf(buff, "%d.%06d", sec, usec);
586 } else {
587 tmp = gmtime(&sec);
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);
593 return (buff);
596 char *
597 showxdr_date(char *fmt)
599 int pos;
600 char *p;
602 pos = getxdr_pos();
603 p = getxdr_date();
604 (void) sprintf(get_line(pos, getxdr_pos()), fmt, p);
605 return (p);
608 char *
609 getxdr_date_ns(void)
611 time_t sec, nsec;
613 sec = getxdr_long();
614 nsec = getxdr_long();
615 if (sec == -1)
616 return ("-1 ");
617 else
618 return (format_time(sec, nsec));
622 * Format the given time.
624 char *
625 format_time(int64_t sec, uint32_t nsec)
627 static char buff[64];
628 char *p;
629 struct tm my_time; /* private buffer to avoid collision */
630 /* between gmtime and strftime */
631 struct tm *tmp;
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
639 * times.
641 (void) sprintf(buff, "%lld.%06d", sec, nsec);
642 } else {
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);
651 return (buff);
654 char *
655 showxdr_date_ns(char *fmt)
657 int pos;
658 char *p;
660 pos = getxdr_pos();
661 p = getxdr_date_ns();
662 (void) sprintf(get_line(pos, getxdr_pos()), fmt, p);
663 return (p);
666 char *
667 getxdr_time()
669 time_t sec;
670 static char buff[64];
671 struct tm my_time; /* private buffer to avoid collision */
672 /* between gmtime and strftime */
673 struct tm *tmp;
675 sec = getxdr_long();
676 if (sec == -1)
677 return ("-1 ");
679 if (sec < 3600 * 24 * 365) { /* assume not a date */
680 (void) sprintf(buff, "%d", sec);
681 } else {
682 tmp = gmtime(&sec);
683 memcpy(&my_time, tmp, sizeof (struct tm));
684 strftime(buff, sizeof (buff), "%d-%h-%y %T", &my_time);
686 return (buff);
689 char *
690 showxdr_time(char *fmt)
692 int pos;
693 char *p;
695 pos = getxdr_pos();
696 p = getxdr_time();
697 (void) sprintf(get_line(pos, getxdr_pos()), fmt, p);
698 return (p);
701 char *
702 getxdr_hex(int len)
704 int i, j;
705 static char hbuff[1024];
706 char rbuff[1024];
707 static char *hexstr = "0123456789ABCDEF";
708 char toobig = 0;
710 if (len == 0) {
711 hbuff[0] = '\0';
712 return (hbuff);
714 if (len > 1024)
715 len = 1024;
716 if (len < 0 || xdr_opaque(&xdrm, rbuff, len) == FALSE) {
717 longjmp(xdr_err, 1);
720 if (len * 2 > sizeof (hbuff)) {
721 toobig++;
722 len = sizeof (hbuff) / 2;
725 j = 0;
726 for (i = 0; i < len; i++) {
727 hbuff[j++] = hexstr[rbuff[i] >> 4 & 0x0f];
728 hbuff[j++] = hexstr[rbuff[i] & 0x0f];
731 if (toobig) {
732 hbuff[len * 2 - strlen("<Too Long>")] = '\0';
733 strcat(hbuff, "<Too Long>");
734 } else
735 hbuff[j] = '\0';
737 return (hbuff);
740 char *
741 showxdr_hex(int len, char *fmt)
743 int pos;
744 char *p;
746 pos = getxdr_pos();
747 p = getxdr_hex(len);
748 (void) sprintf(get_line(pos, getxdr_pos()), fmt, p);
749 return (p);
752 static void
753 hexdump(char *data, int datalen)
755 char *p;
756 ushort_t *p16 = (ushort_t *)data;
757 char *p8 = data;
758 int i, left, len;
759 int chunk = 16; /* 16 bytes per line */
761 printf("\n");
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);
769 if (len % 2) {
770 printf("%02x ", *((unsigned char *)p16));
772 for (i = 0; i < (chunk - left) / 2; i++)
773 printf(" ");
775 printf(" ");
776 for (i = 0; i < len; i++, p8++)
777 printf("%c", isprint(*p8) ? *p8 : '.');
778 printf("\n");
781 printf("\n");
784 char *
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.
795 #define TBSIZE 256
796 static char tbuff[TBSIZE];
797 const char *p;
798 char *pp;
799 int printable = 0;
800 int c, len;
802 len = dlen > maxlen ? maxlen : dlen;
803 dlen = len;
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;
812 default:
813 if (isascii(c) && isprint(c)) {
814 *pp++ = c;
815 printable++;
816 } else {
817 (void) snprintf(pp, TBSIZE - (pp - tbuff),
818 isdigit(*(p + 1)) ?
819 "\\%03o" : "\\%o", c);
820 pp += strlen(pp);
822 break;
824 *pp = '\0';
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]) {
831 break;
834 return (printable > dlen / 2 ? tbuff : "");