dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / cmd-inet / usr.sbin / snoop / snoop_ether.c
blob332069508ccd7ab20902f969d4c1e5fb9cd86bf3
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 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stddef.h>
30 #include <fcntl.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <sys/time.h>
34 #include <sys/sysmacros.h>
35 #include <sys/socket.h>
36 #include <net/if.h>
37 #include <netinet/in_systm.h>
38 #include <netinet/in.h>
39 #include <netinet/ip.h>
40 #include <netinet/if_ether.h>
41 #include <sys/ib/clients/ibd/ibd.h>
42 #include <sys/ethernet.h>
43 #include <sys/vlan.h>
44 #include <sys/zone.h>
45 #include <inet/iptun.h>
46 #include <sys/byteorder.h>
47 #include <limits.h>
48 #include <inet/ip.h>
49 #include <inet/ip6.h>
50 #include <net/trill.h>
52 #include "at.h"
53 #include "snoop.h"
55 static headerlen_fn_t ether_header_len, fddi_header_len, tr_header_len,
56 ib_header_len, ipnet_header_len, ipv4_header_len, ipv6_header_len;
57 static interpreter_fn_t interpret_ether, interpret_fddi, interpret_tr,
58 interpret_ib, interpret_ipnet, interpret_iptun;
59 static void addr_copy_swap(struct ether_addr *, struct ether_addr *);
60 static int tr_machdr_len(char *, int *, int *);
62 interface_t *interface;
63 interface_t INTERFACES[] = {
65 /* IEEE 802.3 CSMA/CD network */
66 { DL_CSMACD, 1550, 12, 2, ETHERTYPE_IP, ETHERTYPE_IPV6,
67 ether_header_len, interpret_ether, B_TRUE },
69 /* Ethernet Bus */
70 { DL_ETHER, 1550, 12, 2, ETHERTYPE_IP, ETHERTYPE_IPV6,
71 ether_header_len, interpret_ether, B_TRUE },
73 /* Fiber Distributed data interface */
74 { DL_FDDI, 4500, 19, 2, ETHERTYPE_IP, ETHERTYPE_IPV6,
75 fddi_header_len, interpret_fddi, B_FALSE },
77 /* Token Ring interface */
78 { DL_TPR, 17800, 0, 2, ETHERTYPE_IP, ETHERTYPE_IPV6,
79 tr_header_len, interpret_tr, B_FALSE },
81 /* Infiniband */
82 { DL_IB, 4096, 0, 2, ETHERTYPE_IP, ETHERTYPE_IPV6,
83 ib_header_len, interpret_ib, B_TRUE },
85 /* ipnet */
86 { DL_IPNET, INT_MAX, 1, 1, IPV4_VERSION, IPV6_VERSION,
87 ipnet_header_len, interpret_ipnet, B_TRUE },
89 /* IPv4 tunnel */
90 { DL_IPV4, 0, 9, 1, IPPROTO_ENCAP, IPPROTO_IPV6,
91 ipv4_header_len, interpret_iptun, B_FALSE },
93 /* IPv6 tunnel */
94 { DL_IPV6, 0, 40, 1, IPPROTO_ENCAP, IPPROTO_IPV6,
95 ipv6_header_len, interpret_iptun, B_FALSE },
97 /* 6to4 tunnel */
98 { DL_6TO4, 0, 9, 1, IPPROTO_ENCAP, IPPROTO_IPV6,
99 ipv4_header_len, interpret_iptun, B_FALSE },
101 { (uint_t)-1, 0, 0, 0, 0, 0, NULL, B_FALSE }
104 /* externals */
105 extern char *dlc_header;
106 extern int pi_frame;
107 extern int pi_time_hour;
108 extern int pi_time_min;
109 extern int pi_time_sec;
110 extern int pi_time_usec;
112 char *printether();
113 char *print_ethertype();
114 static char *print_etherinfo();
116 char *print_fc();
117 char *print_smttype();
118 char *print_smtclass();
120 struct ether_addr ether_broadcast = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
121 static char *data; /* current data buffer */
122 static int datalen; /* current data buffer length */
123 static const struct ether_addr all_isis_rbridges = ALL_ISIS_RBRIDGES;
125 uint_t
126 interpret_ether(int flags, char *header, int elen, int origlen)
128 struct ether_header *e = (struct ether_header *)header;
129 uchar_t *off, *ieeestart;
130 int len;
131 int ieee8023 = 0;
132 extern char *dst_name;
133 int ethertype;
134 struct ether_vlan_extinfo *evx = NULL;
135 int blen = MAX(origlen, ETHERMTU);
136 boolean_t trillpkt = B_FALSE;
137 uint16_t tci = 0;
139 if (data != NULL && datalen != 0 && datalen < blen) {
140 free(data);
141 data = NULL;
142 datalen = 0;
144 if (!data) {
145 data = (char *)malloc(blen);
146 if (!data)
147 pr_err("Warning: malloc failure");
148 datalen = blen;
150 inner_pkt:
151 if (origlen < 14) {
152 if (flags & F_SUM) {
153 (void) sprintf(get_sum_line(),
154 "RUNT (short packet - %d bytes)",
155 origlen);
157 if (flags & F_DTAIL)
158 show_header("RUNT: ", "Short packet", origlen);
159 return (elen);
161 if (elen < 14)
162 return (elen);
164 if (memcmp(&e->ether_dhost, &ether_broadcast,
165 sizeof (struct ether_addr)) == 0)
166 dst_name = "(broadcast)";
167 else if (e->ether_dhost.ether_addr_octet[0] & 1)
168 dst_name = "(multicast)";
170 ethertype = ntohs(e->ether_type);
173 * The 14 byte ether header screws up alignment
174 * of the rest of the packet for 32 bit aligned
175 * architectures like SPARC. Alas, we have to copy
176 * the rest of the packet in order to align it.
178 len = elen - sizeof (struct ether_header);
179 off = (uchar_t *)(e + 1);
181 if (ethertype == ETHERTYPE_VLAN) {
182 if (origlen < sizeof (struct ether_vlan_header)) {
183 if (flags & F_SUM) {
184 (void) sprintf(get_sum_line(),
185 "RUNT (short VLAN packet - %d bytes)",
186 origlen);
188 if (flags & F_DTAIL) {
189 show_header("RUNT: ", "Short VLAN packet",
190 origlen);
192 return (elen);
194 if (len < sizeof (struct ether_vlan_extinfo))
195 return (elen);
197 evx = (struct ether_vlan_extinfo *)off;
198 off += sizeof (struct ether_vlan_extinfo);
199 len -= sizeof (struct ether_vlan_extinfo);
201 ethertype = ntohs(evx->ether_type);
202 tci = ntohs(evx->ether_tci);
205 if (ethertype <= 1514) {
207 * Fake out the IEEE 802.3 packets.
208 * Should be DSAP=0xAA, SSAP=0xAA, control=0x03
209 * then three padding bytes of zero (OUI),
210 * followed by a normal ethernet-type packet.
212 ieee8023 = ethertype;
213 ieeestart = off;
214 if (off[0] == 0xAA && off[1] == 0xAA) {
215 ethertype = ntohs(*(ushort_t *)(off + 6));
216 off += 8;
217 len -= 8;
218 } else {
219 ethertype = 0;
220 off += 3;
221 len -= 3;
225 if (flags & F_SUM) {
227 * Set the flag that says don't display VLAN information.
228 * If it needs to change, that will be done later if the
229 * packet is VLAN tagged and if snoop is in its default
230 * summary mode.
232 set_vlan_id(0);
233 if (evx == NULL) {
234 if (ethertype == 0 && ieee8023 > 0) {
235 (void) sprintf(get_sum_line(),
236 "ETHER 802.3 SSAP %02X DSAP %02X, "
237 "size=%d bytes", ieeestart[0], ieeestart[1],
238 origlen);
239 } else {
240 (void) sprintf(get_sum_line(),
241 "ETHER Type=%04X (%s), size=%d bytes",
242 ethertype, print_ethertype(ethertype),
243 origlen);
245 } else {
246 if (ethertype == 0 && ieee8023 > 0) {
247 (void) sprintf(get_sum_line(),
248 "ETHER 802.3 SSAP %02X DSAP %02X, "
249 "VLAN ID=%hu, size=%d bytes", ieeestart[0],
250 ieeestart[1], VLAN_ID(tci), origlen);
251 } else {
252 (void) sprintf(get_sum_line(),
253 "ETHER Type=%04X (%s), VLAN ID=%hu, "
254 "size=%d bytes", ethertype,
255 print_ethertype(ethertype), VLAN_ID(tci),
256 origlen);
259 if (!(flags & F_ALLSUM))
260 set_vlan_id(VLAN_ID(tci));
264 if (flags & F_DTAIL) {
265 show_header("ETHER: ", "Ether Header", elen);
266 show_space();
267 if (!trillpkt) {
268 (void) sprintf(get_line(0, 0),
269 "Packet %d arrived at %d:%02d:%d.%05d",
270 pi_frame,
271 pi_time_hour, pi_time_min, pi_time_sec,
272 pi_time_usec / 10);
273 (void) sprintf(get_line(0, 0),
274 "Packet size = %d bytes",
275 elen, elen);
277 (void) sprintf(get_line(0, 6),
278 "Destination = %s, %s",
279 printether(&e->ether_dhost),
280 print_etherinfo(&e->ether_dhost));
281 (void) sprintf(get_line(6, 6),
282 "Source = %s, %s",
283 printether(&e->ether_shost),
284 print_etherinfo(&e->ether_shost));
285 if (evx != NULL) {
286 (void) sprintf(get_line(0, 0),
287 "VLAN ID = %hu", VLAN_ID(tci));
288 (void) sprintf(get_line(0, 0),
289 "VLAN Priority = %hu", VLAN_PRI(tci));
291 if (ieee8023 > 0) {
292 (void) sprintf(get_line(12, 2),
293 "IEEE 802.3 length = %d bytes", ieee8023);
294 /* Print LLC only for non-TCP/IP packets */
295 if (ethertype == 0) {
296 (void) snprintf(get_line(0, 0),
297 get_line_remain(),
298 "SSAP = %02X, DSAP = %02X, CTRL = %02X",
299 ieeestart[0], ieeestart[1], ieeestart[2]);
302 if (ethertype != 0 || ieee8023 == 0)
303 (void) sprintf(get_line(12, 2),
304 "Ethertype = %04X (%s)",
305 ethertype, print_ethertype(ethertype));
306 show_space();
310 * We cannot trust the length field in the header to be correct.
311 * But we should continue to process the packet. Then user can
312 * notice something funny in the header.
313 * Go to the next protocol layer only if data have been
314 * copied.
316 if (len > 0 && (off + len <= (uchar_t *)e + elen)) {
317 (void) memmove(data, off, len);
319 if (!trillpkt && ethertype == ETHERTYPE_TRILL) {
320 ethertype = interpret_trill(flags, &e, data, &len);
321 /* Decode inner Ethernet frame */
322 if (ethertype != 0) {
323 evx = NULL;
324 trillpkt = B_TRUE;
325 (void) memmove(data, e, len);
326 e = (struct ether_header *)data;
327 origlen = len;
328 elen = len;
329 goto inner_pkt;
333 switch (ethertype) {
334 case ETHERTYPE_IP:
335 (void) interpret_ip(flags, (struct ip *)data, len);
336 break;
337 /* Just in case it is decided to add this type */
338 case ETHERTYPE_IPV6:
339 (void) interpret_ipv6(flags, (ip6_t *)data, len);
340 break;
341 case ETHERTYPE_ARP:
342 case ETHERTYPE_REVARP:
343 interpret_arp(flags, (struct arphdr *)data, len);
344 break;
345 case ETHERTYPE_PPPOED:
346 case ETHERTYPE_PPPOES:
347 (void) interpret_pppoe(flags, (poep_t *)data, len);
348 break;
349 case ETHERTYPE_AARP: /* AppleTalk */
350 interpret_aarp(flags, data, len);
351 break;
352 case ETHERTYPE_AT:
353 interpret_at(flags, (struct ddp_hdr *)data, len);
354 break;
355 case 0:
356 if (ieee8023 == 0)
357 break;
358 switch (ieeestart[0]) {
359 case 0xFE:
360 interpret_isis(flags, data, len,
361 memcmp(&e->ether_dhost, &all_isis_rbridges,
362 sizeof (struct ether_addr)) == 0);
363 break;
364 case 0x42:
365 interpret_bpdu(flags, data, len);
366 break;
368 break;
372 return (elen);
376 * Return the length of the ethernet header. In the case
377 * where we have a VLAN tagged packet, return the length of
378 * the ethernet header plus the length of the VLAN tag.
380 * INPUTS: e - A buffer pointer. Passing a NULL pointer
381 * is not allowed, e must be non-NULL.
382 * OUTPUTS: Return the size of an untagged ethernet header
383 * if the packet is not VLAN tagged, and the size
384 * of an untagged ethernet header plus the size of
385 * a VLAN header otherwise.
387 uint_t
388 ether_header_len(char *e, size_t msgsize)
390 uint16_t ether_type = 0;
392 if (msgsize < sizeof (struct ether_header))
393 return (0);
395 e += (offsetof(struct ether_header, ether_type));
397 GETINT16(ether_type, e);
399 if (ether_type == (uint16_t)ETHERTYPE_VLAN) {
400 return (sizeof (struct ether_vlan_header));
401 } else {
402 return (sizeof (struct ether_header));
408 * Table of Ethertypes.
409 * Some of the more popular entries
410 * are at the beginning of the table
411 * to reduce search time.
413 struct ether_type {
414 int e_type;
415 char *e_name;
416 } ether_type [] = {
417 ETHERTYPE_IP, "IP",
418 ETHERTYPE_ARP, "ARP",
419 ETHERTYPE_REVARP, "RARP",
420 ETHERTYPE_IPV6, "IPv6",
421 ETHERTYPE_PPPOED, "PPPoE Discovery",
422 ETHERTYPE_PPPOES, "PPPoE Session",
423 ETHERTYPE_TRILL, "TRILL",
424 /* end of popular entries */
425 ETHERTYPE_PUP, "Xerox PUP",
426 0x0201, "Xerox PUP",
427 0x0400, "Nixdorf",
428 0x0600, "Xerox NS IDP",
429 0x0601, "XNS Translation",
430 0x0801, "X.75 Internet",
431 0x0802, "NBS Internet",
432 0x0803, "ECMA Internet",
433 0x0804, "CHAOSnet",
434 0x0805, "X.25 Level 3",
435 0x0807, "XNS Compatibility",
436 0x081C, "Symbolics Private",
437 0x0888, "Xyplex",
438 0x0889, "Xyplex",
439 0x088A, "Xyplex",
440 0x0900, "Ungermann-Bass network debugger",
441 0x0A00, "Xerox IEEE802.3 PUP",
442 0x0A01, "Xerox IEEE802.3 PUP Address Translation",
443 0x0BAD, "Banyan Systems",
444 0x0BAF, "Banyon VINES Echo",
445 0x1000, "Berkeley Trailer negotiation",
446 0x1000, "IP trailer (0)",
447 0x1001, "IP trailer (1)",
448 0x1002, "IP trailer (2)",
449 0x1003, "IP trailer (3)",
450 0x1004, "IP trailer (4)",
451 0x1005, "IP trailer (5)",
452 0x1006, "IP trailer (6)",
453 0x1007, "IP trailer (7)",
454 0x1008, "IP trailer (8)",
455 0x1009, "IP trailer (9)",
456 0x100a, "IP trailer (10)",
457 0x100b, "IP trailer (11)",
458 0x100c, "IP trailer (12)",
459 0x100d, "IP trailer (13)",
460 0x100e, "IP trailer (14)",
461 0x100f, "IP trailer (15)",
462 0x1234, "DCA - Multicast",
463 0x1600, "VALID system protocol",
464 0x1989, "Aviator",
465 0x3C00, "3Com NBP virtual circuit datagram",
466 0x3C01, "3Com NBP System control datagram",
467 0x3C02, "3Com NBP Connect request (virtual cct)",
468 0x3C03, "3Com NBP Connect response",
469 0x3C04, "3Com NBP Connect complete",
470 0x3C05, "3Com NBP Close request (virtual cct)",
471 0x3C06, "3Com NBP Close response",
472 0x3C07, "3Com NBP Datagram (like XNS IDP)",
473 0x3C08, "3Com NBP Datagram broadcast",
474 0x3C09, "3Com NBP Claim NetBIOS name",
475 0x3C0A, "3Com NBP Delete Netbios name",
476 0x3C0B, "3Com NBP Remote adaptor status request",
477 0x3C0C, "3Com NBP Remote adaptor response",
478 0x3C0D, "3Com NBP Reset",
479 0x4242, "PCS Basic Block Protocol",
480 0x4321, "THD - Diddle",
481 0x5208, "BBN Simnet Private",
482 0x6000, "DEC unass, experimental",
483 0x6001, "DEC Dump/Load",
484 0x6002, "DEC Remote Console",
485 0x6003, "DECNET Phase IV, DNA Routing",
486 0x6004, "DEC LAT",
487 0x6005, "DEC Diagnostic",
488 0x6006, "DEC customer protocol",
489 0x6007, "DEC Local Area VAX Cluster (LAVC)",
490 0x6008, "DEC unass (AMBER?)",
491 0x6009, "DEC unass (MUMPS?)",
492 0x6010, "3Com",
493 0x6011, "3Com",
494 0x6012, "3Com",
495 0x6013, "3Com",
496 0x6014, "3Com",
497 0x7000, "Ungermann-Bass download",
498 0x7001, "Ungermann-Bass NIUs",
499 0x7002, "Ungermann-Bass diagnostic/loopback",
500 0x7003, "Ungermann-Bass ? (NMC to/from UB Bridge)",
501 0x7005, "Ungermann-Bass Bridge Spanning Tree",
502 0x7007, "OS/9 Microware",
503 0x7009, "OS/9 Net?",
504 0x7020, "Sintrom",
505 0x7021, "Sintrom",
506 0x7022, "Sintrom",
507 0x7023, "Sintrom",
508 0x7024, "Sintrom",
509 0x7025, "Sintrom",
510 0x7026, "Sintrom",
511 0x7027, "Sintrom",
512 0x7028, "Sintrom",
513 0x7029, "Sintrom",
514 0x8003, "Cronus VLN",
515 0x8004, "Cronus Direct",
516 0x8005, "HP Probe protocol",
517 0x8006, "Nestar",
518 0x8008, "AT&T/Stanford Univ",
519 0x8010, "Excelan",
520 0x8013, "SGI diagnostic",
521 0x8014, "SGI network games",
522 0x8015, "SGI reserved",
523 0x8016, "SGI XNS NameServer, bounce server",
524 0x8019, "Apollo DOMAIN",
525 0x802E, "Tymshare",
526 0x802F, "Tigan,",
527 0x8036, "Aeonic Systems",
528 0x8037, "IPX (Novell Netware)",
529 0x8038, "DEC LanBridge Management",
530 0x8039, "DEC unass (DSM/DTP?)",
531 0x803A, "DEC unass (Argonaut Console?)",
532 0x803B, "DEC unass (VAXELN?)",
533 0x803C, "DEC unass (NMSV? DNA Naming Service?)",
534 0x803D, "DEC Ethernet CSMA/CD Encryption Protocol",
535 0x803E, "DEC unass (DNA Time Service?)",
536 0x803F, "DEC LAN Traffic Monitor Protocol",
537 0x8040, "DEC unass (NetBios Emulator?)",
538 0x8041, "DEC unass (MS/DOS?, Local Area System Transport?)",
539 0x8042, "DEC unass",
540 0x8044, "Planning Research Corp.",
541 0x8046, "AT&T",
542 0x8047, "AT&T",
543 0x8049, "ExperData",
544 0x805B, "VMTP",
545 0x805C, "Stanford V Kernel, version 6.0",
546 0x805D, "Evans & Sutherland",
547 0x8060, "Little Machines",
548 0x8062, "Counterpoint",
549 0x8065, "University of Mass. at Amherst",
550 0x8066, "University of Mass. at Amherst",
551 0x8067, "Veeco Integrated Automation",
552 0x8068, "General Dynamics",
553 0x8069, "AT&T",
554 0x806A, "Autophon",
555 0x806C, "ComDesign",
556 0x806D, "Compugraphic Corp",
557 0x806E, "Landmark",
558 0x806F, "Landmark",
559 0x8070, "Landmark",
560 0x8071, "Landmark",
561 0x8072, "Landmark",
562 0x8073, "Landmark",
563 0x8074, "Landmark",
564 0x8075, "Landmark",
565 0x8076, "Landmark",
566 0x8077, "Landmark",
567 0x807A, "Matra",
568 0x807B, "Dansk Data Elektronik",
569 0x807C, "Merit Internodal",
570 0x807D, "Vitalink",
571 0x807E, "Vitalink",
572 0x807F, "Vitalink",
573 0x8080, "Vitalink TransLAN III Management",
574 0x8081, "Counterpoint",
575 0x8082, "Counterpoint",
576 0x8083, "Counterpoint",
577 0x8088, "Xyplex",
578 0x8089, "Xyplex",
579 0x808A, "Xyplex",
580 0x809B, "EtherTalk (AppleTalk over Ethernet)",
581 0x809C, "Datability",
582 0x809D, "Datability",
583 0x809E, "Datability",
584 0x809F, "Spider Systems",
585 0x80A3, "Nixdorf",
586 0x80A4, "Siemens Gammasonics",
587 0x80C0, "DCA Data Exchange Cluster",
588 0x80C6, "Pacer Software",
589 0x80C7, "Applitek Corp",
590 0x80C8, "Intergraph",
591 0x80C9, "Intergraph",
592 0x80CB, "Intergraph",
593 0x80CC, "Intergraph",
594 0x80CA, "Intergraph",
595 0x80CD, "Harris Corp",
596 0x80CE, "Harris Corp",
597 0x80CF, "Taylor Instrument",
598 0x80D0, "Taylor Instrument",
599 0x80D1, "Taylor Instrument",
600 0x80D2, "Taylor Instrument",
601 0x80D3, "Rosemount Corp",
602 0x80D4, "Rosemount Corp",
603 0x80D5, "IBM SNA Services over Ethernet",
604 0x80DD, "Varian Associates",
605 0x80DE, "TRFS",
606 0x80DF, "TRFS",
607 0x80E0, "Allen-Bradley",
608 0x80E1, "Allen-Bradley",
609 0x80E2, "Allen-Bradley",
610 0x80E3, "Allen-Bradley",
611 0x80E4, "Datability",
612 0x80F2, "Retix",
613 0x80F3, "AARP (Appletalk)",
614 0x80F4, "Kinetics",
615 0x80F5, "Kinetics",
616 0x80F7, "Apollo",
617 0x80FF, "Wellfleet Communications",
618 0x8102, "Wellfleet Communications",
619 0x8107, "Symbolics Private",
620 0x8108, "Symbolics Private",
621 0x8109, "Symbolics Private",
622 0x812B, "Talaris",
623 0x8130, "Waterloo",
624 0x8131, "VG Lab",
625 0x8137, "Novell (old) NetWare IPX",
626 0x8138, "Novell",
627 0x814C, "SNMP over Ethernet",
628 0x817D, "XTP",
629 0x81D6, "Lantastic",
630 0x8888, "HP LanProbe test?",
631 0x9000, "Loopback",
632 0x9001, "3Com, XNS Systems Management",
633 0x9002, "3Com, TCP/IP Systems Management",
634 0x9003, "3Com, loopback detection",
635 0xAAAA, "DECNET (VAX 6220 DEBNI)",
636 0xFF00, "BBN VITAL-LanBridge cache wakeups",
637 0, "",
640 char *
641 print_fc(uint_t type)
644 switch (type) {
645 case 0x50: return ("LLC");
646 case 0x4f: return ("SMT NSA");
647 case 0x41: return ("SMT Info");
648 default: return ("Unknown");
652 char *
653 print_smtclass(uint_t type)
655 switch (type) {
656 case 0x01: return ("NIF");
657 case 0x02: return ("SIF Conf");
658 case 0x03: return ("SIF Oper");
659 case 0x04: return ("ECF");
660 case 0x05: return ("RAF");
661 case 0x06: return ("RDF");
662 case 0x07: return ("SRF");
663 case 0x08: return ("PMF Get");
664 case 0x09: return ("PMF Change");
665 case 0x0a: return ("PMF Add");
666 case 0x0b: return ("PMF Remove");
667 case 0xff: return ("ESF");
668 default: return ("Unknown");
672 char *
673 print_smttype(uint_t type)
675 switch (type) {
676 case 0x01: return ("Announce");
677 case 0x02: return ("Request");
678 case 0x03: return ("Response");
679 default: return ("Unknown");
683 char *
684 print_ethertype(int type)
686 int i;
688 for (i = 0; ether_type[i].e_type; i++)
689 if (type == ether_type[i].e_type)
690 return (ether_type[i].e_name);
691 if (type < 1500)
692 return ("LLC/802.3");
694 return ("Unknown");
697 #define MAX_RDFLDS 14 /* changed to 14 from 8 as per IEEE */
698 #define TR_FN_ADDR 0x80 /* dest addr is functional */
699 #define TR_SR_ADDR 0x80 /* MAC utilizes source route */
700 #define ACFCDASA_LEN 14 /* length of AC|FC|DA|SA */
701 #define TR_MAC_MASK 0xc0
702 #define TR_AC 0x00 /* Token Ring access control */
703 #define TR_LLC_FC 0x40 /* Token Ring llc frame control */
704 #define LSAP_SNAP 0xaa
705 #define LLC_SNAP_HDR_LEN 8
706 #define LLC_HDR1_LEN 3 /* DON'T use sizeof(struct llc_hdr1) */
707 #define CNTL_LLC_UI 0x03 /* un-numbered information packet */
710 * Source Routing Route Information field.
712 struct tr_ri {
713 #if defined(_BIT_FIELDS_HTOL)
714 uchar_t rt:3; /* routing type */
715 uchar_t len:5; /* length */
716 uchar_t dir:1; /* direction bit */
717 uchar_t mtu:3; /* largest frame */
718 uchar_t res:4; /* reserved */
719 #elif defined(_BIT_FIELDS_LTOH)
720 uchar_t len:5; /* length */
721 uchar_t rt:3; /* routing type */
722 uchar_t res:4; /* reserved */
723 uchar_t mtu:3; /* largest frame */
724 uchar_t dir:1; /* direction bit */
725 #endif
727 * In little endian machine, the ring field has to be stored in a
728 * ushort_t type. This implies that it is not possible to have a
729 * layout of bit field to represent bridge and ring.
731 * If the compiler uses _BIT_FIELDS_HTOL and it is a big endian
732 * machine, the following bit field definition will work.
734 * struct tr_rd {
735 * ushort_t bridge:4;
736 * ushort_t ring:12;
737 * } rd[MAX_RDFLDS];
739 * If the compiler uses _BIT_FIELDS_LTOH and it is a big endian
740 * machine, the definition can be changed to
742 * struct tr_rd {
743 * ushort_t bridge:4;
744 * ushort_t ring:12;
745 * } rd[MAX_RDFLDS];
747 * With little endian machine, we need to use 2 macroes. For
748 * simplicity, since the macroes work for both big and little
749 * endian machines, we will not use bit fields for the
750 * definition.
752 #define bridge(route) (ntohs((ushort_t)(route)) & 0x0F)
753 #define ring(route) (ntohs((ushort_t)(route)) >> 4)
755 ushort_t rd[MAX_RDFLDS]; /* route designator fields */
758 struct tr_header {
759 uchar_t ac;
760 uchar_t fc;
761 struct ether_addr dhost;
762 struct ether_addr shost;
763 struct tr_ri ri;
766 struct llc_snap_hdr {
767 uchar_t d_lsap; /* destination service access point */
768 uchar_t s_lsap; /* source link service access point */
769 uchar_t control; /* short control field */
770 uchar_t org[3]; /* Ethernet style organization field */
771 ushort_t type; /* Ethernet style type field */
774 struct ether_addr tokenbroadcastaddr2 = {
775 0xc0, 0x00, 0xff, 0xff, 0xff, 0xff
778 int Mtutab[] = {516, 1470, 2052, 4472, 8144, 11407, 17800};
780 char *
781 print_sr(struct tr_ri *rh)
783 int hops, ii;
784 static char line[512];
786 sprintf(line, "TR Source Route dir=%d, mtu=%d",
787 rh->dir, Mtutab[rh->mtu]);
789 hops = (int)(rh->len - 2) / (int)2;
791 if (hops) {
792 sprintf(line+strlen(line), ", Route: ");
793 for (ii = 0; ii < hops; ii++) {
794 if (! bridge(rh->rd[ii])) {
795 sprintf(line+strlen(line), "(%d)",
796 ring(rh->rd[ii]));
797 } else {
798 sprintf(line+strlen(line), "(%d)%d",
799 ring(rh->rd[ii]), bridge(rh->rd[ii]));
803 return (&line[0]);
806 uint_t
807 interpret_tr(int flags, caddr_t e, int elen, int origlen)
809 struct tr_header *mh;
810 struct tr_ri *rh;
811 uchar_t fc;
812 struct llc_snap_hdr *snaphdr;
813 char *off;
814 int maclen, len;
815 boolean_t data_copied = B_FALSE;
816 extern char *dst_name, *src_name;
817 int ethertype;
818 int is_llc = 0, is_snap = 0, source_routing = 0;
819 int blen = MAX(origlen, 17800);
821 if (data != NULL && datalen != 0 && datalen < blen) {
822 free(data);
823 data = NULL;
824 datalen = 0;
826 if (!data) {
827 data = (char *)malloc(blen);
828 if (!data)
829 pr_err("Warning: malloc failure");
830 datalen = blen;
833 if (origlen < ACFCDASA_LEN) {
834 if (flags & F_SUM) {
835 (void) sprintf(get_sum_line(),
836 "RUNT (short packet - %d bytes)",
837 origlen);
839 if (flags & F_DTAIL)
840 show_header("RUNT: ", "Short packet", origlen);
841 return (elen);
843 if (elen < ACFCDASA_LEN)
844 return (elen);
846 mh = (struct tr_header *)e;
847 rh = (struct tr_ri *)&mh->ri;
848 fc = mh->fc;
850 if (is_llc = tr_machdr_len(e, &maclen, &source_routing)) {
851 snaphdr = (struct llc_snap_hdr *)(e + maclen);
852 if (snaphdr->d_lsap == LSAP_SNAP &&
853 snaphdr->s_lsap == LSAP_SNAP &&
854 snaphdr->control == CNTL_LLC_UI) {
855 is_snap = 1;
859 if (memcmp(&mh->dhost, &ether_broadcast,
860 sizeof (struct ether_addr)) == 0)
861 dst_name = "(broadcast)";
862 else if (memcmp(&mh->dhost, &tokenbroadcastaddr2,
863 sizeof (struct ether_addr)) == 0)
864 dst_name = "(mac broadcast)";
865 else if (mh->dhost.ether_addr_octet[0] & TR_FN_ADDR)
866 dst_name = "(functional)";
868 if (is_snap)
869 ethertype = ntohs(snaphdr->type);
870 else {
871 src_name = print_etherinfo(&mh->shost);
872 dst_name = print_etherinfo(&mh->dhost);
876 * The 14 byte ether header screws up alignment
877 * of the rest of the packet for 32 bit aligned
878 * architectures like SPARC. Alas, we have to copy
879 * the rest of the packet in order to align it.
881 if (is_llc) {
882 if (is_snap) {
883 len = elen - (maclen + LLC_SNAP_HDR_LEN);
884 off = (char *)(e + maclen + LLC_SNAP_HDR_LEN);
885 } else {
886 len = elen - (maclen + LLC_HDR1_LEN);
887 off = (char *)(e + maclen + LLC_HDR1_LEN);
889 } else {
890 len = elen - maclen;
891 off = (char *)(e + maclen);
894 if (len > 0 && (off + len <= (char *)e + elen)) {
895 (void) memcpy(data, off, len);
896 data_copied = B_TRUE;
899 if (flags & F_SUM) {
900 if (source_routing)
901 sprintf(get_sum_line(), print_sr(rh));
903 if (is_llc) {
904 if (is_snap) {
905 (void) sprintf(get_sum_line(), "TR LLC w/SNAP "
906 "Type=%04X (%s), size=%d bytes",
907 ethertype,
908 print_ethertype(ethertype),
909 origlen);
910 } else {
911 (void) sprintf(get_sum_line(), "TR LLC, but no "
912 "SNAP encoding, size = %d bytes",
913 origlen);
915 } else {
916 (void) sprintf(get_sum_line(),
917 "TR MAC FC=%02X (%s), size = %d bytes",
918 fc, print_fc(fc), origlen);
922 if (flags & F_DTAIL) {
923 show_header("TR: ", "TR Header", elen);
924 show_space();
925 (void) sprintf(get_line(0, 0),
926 "Packet %d arrived at %d:%02d:%d.%05d",
927 pi_frame,
928 pi_time_hour, pi_time_min, pi_time_sec,
929 pi_time_usec / 10);
930 (void) sprintf(get_line(0, 0),
931 "Packet size = %d bytes",
932 elen);
933 (void) sprintf(get_line(0, 1),
934 "Frame Control = %02x (%s)",
935 fc, print_fc(fc));
936 (void) sprintf(get_line(2, 6),
937 "Destination = %s, %s",
938 printether(&mh->dhost),
939 print_etherinfo(&mh->dhost));
940 (void) sprintf(get_line(8, 6),
941 "Source = %s, %s",
942 printether(&mh->shost),
943 print_etherinfo(&mh->shost));
945 if (source_routing)
946 sprintf(get_line(ACFCDASA_LEN, rh->len), print_sr(rh));
948 if (is_llc) {
949 (void) sprintf(get_line(maclen, 1),
950 "Dest Service Access Point = %02x",
951 snaphdr->d_lsap);
952 (void) sprintf(get_line(maclen+1, 1),
953 "Source Service Access Point = %02x",
954 snaphdr->s_lsap);
955 (void) sprintf(get_line(maclen+2, 1),
956 "Control = %02x",
957 snaphdr->control);
958 if (is_snap) {
959 (void) sprintf(get_line(maclen+3, 3),
960 "SNAP Protocol Id = %02x%02x%02x",
961 snaphdr->org[0], snaphdr->org[1],
962 snaphdr->org[2]);
966 if (is_snap) {
967 (void) sprintf(get_line(maclen+6, 2),
968 "SNAP Type = %04X (%s)",
969 ethertype, print_ethertype(ethertype));
972 show_space();
975 /* go to the next protocol layer */
976 if (is_snap && data_copied) {
977 switch (ethertype) {
978 case ETHERTYPE_IP:
979 (void) interpret_ip(flags, (struct ip *)data, len);
980 break;
981 /* Just in case it is decided to add this type */
982 case ETHERTYPE_IPV6:
983 (void) interpret_ipv6(flags, (ip6_t *)data, len);
984 break;
985 case ETHERTYPE_ARP:
986 case ETHERTYPE_REVARP:
987 interpret_arp(flags, (struct arphdr *)data, len);
988 break;
989 case ETHERTYPE_AARP: /* AppleTalk */
990 interpret_aarp(flags, data, len);
991 break;
992 case ETHERTYPE_AT:
993 interpret_at(flags, (struct ddp_hdr *)data, len);
994 break;
995 default:
996 break;
1000 return (elen);
1005 * stuffs length of mac and ri fields into *lenp
1006 * returns:
1007 * 0: mac frame
1008 * 1: llc frame
1010 static int
1011 tr_machdr_len(char *e, int *lenp, int *source_routing)
1013 struct tr_header *mh;
1014 struct tr_ri *rh;
1015 uchar_t fc;
1017 mh = (struct tr_header *)e;
1018 rh = (struct tr_ri *)&mh->ri;
1019 fc = mh->fc;
1021 if (mh->shost.ether_addr_octet[0] & TR_SR_ADDR) {
1022 *lenp = ACFCDASA_LEN + rh->len;
1023 *source_routing = 1;
1024 } else {
1025 *lenp = ACFCDASA_LEN;
1026 *source_routing = 0;
1029 if ((fc & TR_MAC_MASK) == 0)
1030 return (0); /* it's a MAC frame */
1031 else
1032 return (1); /* it's an LLC frame */
1035 uint_t
1036 tr_header_len(char *e, size_t msgsize)
1038 struct llc_snap_hdr *snaphdr;
1039 int len = 0, source_routing;
1041 if (tr_machdr_len(e, &len, &source_routing) == 0)
1042 return (len); /* it's a MAC frame */
1044 if (msgsize < sizeof (struct llc_snap_hdr))
1045 return (0);
1047 snaphdr = (struct llc_snap_hdr *)(e + len);
1048 if (snaphdr->d_lsap == LSAP_SNAP &&
1049 snaphdr->s_lsap == LSAP_SNAP &&
1050 snaphdr->control == CNTL_LLC_UI)
1051 len += LLC_SNAP_HDR_LEN; /* it's a SNAP frame */
1052 else
1053 len += LLC_HDR1_LEN;
1055 return (len);
1058 struct fddi_header {
1059 uchar_t fc;
1060 struct ether_addr dhost, shost;
1061 uchar_t dsap, ssap, ctl, proto_id[3];
1062 ushort_t type;
1065 uint_t
1066 interpret_fddi(int flags, caddr_t e, int elen, int origlen)
1068 struct fddi_header fhdr, *f = &fhdr;
1069 char *off;
1070 int len;
1071 boolean_t data_copied = B_FALSE;
1072 extern char *dst_name, *src_name;
1073 int ethertype;
1074 int is_llc = 0, is_smt = 0, is_snap = 0;
1075 int blen = MAX(origlen, 4500);
1077 if (data != NULL && datalen != 0 && datalen < blen) {
1078 free(data);
1079 data = NULL;
1080 datalen = 0;
1082 if (!data) {
1083 data = (char *)malloc(blen);
1084 if (!data)
1085 pr_err("Warning: malloc failure");
1086 datalen = blen;
1089 if (origlen < 13) {
1090 if (flags & F_SUM) {
1091 (void) sprintf(get_sum_line(),
1092 "RUNT (short packet - %d bytes)",
1093 origlen);
1095 if (flags & F_DTAIL)
1096 show_header("RUNT: ", "Short packet", origlen);
1097 return (elen);
1099 if (elen < 13)
1100 return (elen);
1102 (void) memcpy(&f->fc, e, sizeof (f->fc));
1103 addr_copy_swap(&f->dhost, (struct ether_addr *)(e+1));
1104 addr_copy_swap(&f->shost, (struct ether_addr *)(e+7));
1106 if ((f->fc&0x50) == 0x50) {
1107 is_llc = 1;
1108 (void) memcpy(&f->dsap, e+13, sizeof (f->dsap));
1109 (void) memcpy(&f->ssap, e+14, sizeof (f->ssap));
1110 (void) memcpy(&f->ctl, e+15, sizeof (f->ctl));
1111 if (f->dsap == 0xaa && f->ssap == 0xaa) {
1112 is_snap = 1;
1113 (void) memcpy(&f->proto_id, e+16, sizeof (f->proto_id));
1114 (void) memcpy(&f->type, e+19, sizeof (f->type));
1116 } else {
1117 if ((f->fc&0x41) == 0x41 || (f->fc&0x4f) == 0x4f) {
1118 is_smt = 1;
1123 if (memcmp(&f->dhost, &ether_broadcast,
1124 sizeof (struct ether_addr)) == 0)
1125 dst_name = "(broadcast)";
1126 else if (f->dhost.ether_addr_octet[0] & 0x01)
1127 dst_name = "(multicast)";
1129 if (is_snap)
1130 ethertype = ntohs(f->type);
1131 else {
1132 src_name = print_etherinfo(&f->shost);
1133 dst_name = print_etherinfo(&f->dhost);
1137 * The 14 byte ether header screws up alignment
1138 * of the rest of the packet for 32 bit aligned
1139 * architectures like SPARC. Alas, we have to copy
1140 * the rest of the packet in order to align it.
1142 if (is_llc) {
1143 if (is_snap) {
1144 len = elen - 21;
1145 off = (char *)(e + 21);
1146 } else {
1147 len = elen - 16;
1148 off = (char *)(e + 16);
1150 } else {
1151 len = elen - 13;
1152 off = (char *)(e + 13);
1155 if (len > 0 && (off + len <= (char *)e + elen)) {
1156 (void) memcpy(data, off, len);
1157 data_copied = B_TRUE;
1160 if (flags & F_SUM) {
1161 if (is_llc) {
1162 if (is_snap) {
1163 (void) sprintf(get_sum_line(),
1164 "FDDI LLC Type=%04X (%s), size = %d bytes",
1165 ethertype,
1166 print_ethertype(ethertype),
1167 origlen);
1168 } else {
1169 (void) sprintf(get_sum_line(), "LLC, but no "
1170 "SNAP encoding, size = %d bytes",
1171 origlen);
1173 } else if (is_smt) {
1174 (void) sprintf(get_sum_line(), "SMT Type=%02X (%s), "
1175 "Class = %02X (%s), size = %d bytes",
1176 *(uchar_t *)(data+1), print_smttype(*(data+1)),
1177 *data, print_smtclass(*data), origlen);
1178 } else {
1179 (void) sprintf(get_sum_line(),
1180 "FC=%02X (%s), size = %d bytes",
1181 f->fc, print_fc(f->fc), origlen);
1185 if (flags & F_DTAIL) {
1186 show_header("FDDI: ", "FDDI Header", elen);
1187 show_space();
1188 (void) sprintf(get_line(0, 0),
1189 "Packet %d arrived at %d:%02d:%d.%05d",
1190 pi_frame,
1191 pi_time_hour, pi_time_min, pi_time_sec,
1192 pi_time_usec / 10);
1193 (void) sprintf(get_line(0, 0),
1194 "Packet size = %d bytes",
1195 elen, elen);
1196 (void) sprintf(get_line(0, 6),
1197 "Destination = %s, %s",
1198 printether(&f->dhost),
1199 print_etherinfo(&f->dhost));
1200 (void) sprintf(get_line(6, 6),
1201 "Source = %s, %s",
1202 printether(&f->shost),
1203 print_etherinfo(&f->shost));
1205 if (is_llc) {
1206 (void) sprintf(get_line(12, 2),
1207 "Frame Control = %02x (%s)",
1208 f->fc, print_fc(f->fc));
1209 (void) sprintf(get_line(12, 2),
1210 "Dest Service Access Point = %02x",
1211 f->dsap);
1212 (void) sprintf(get_line(12, 2),
1213 "Source Service Access Point = %02x",
1214 f->ssap);
1215 (void) sprintf(get_line(12, 2),
1216 "Control = %02x",
1217 f->ctl);
1218 if (is_snap) {
1219 (void) sprintf(get_line(12, 2),
1220 "Protocol Id = %02x%02x%02x",
1221 f->proto_id[0], f->proto_id[1],
1222 f->proto_id[2]);
1224 } else if (is_smt) {
1225 (void) sprintf(get_line(12, 2),
1226 "Frame Control = %02x (%s)",
1227 f->fc, print_fc(f->fc));
1228 (void) sprintf(get_line(12, 2),
1229 "Class = %02x (%s)",
1230 (uchar_t)*data, print_smtclass(*data));
1231 (void) sprintf(get_line(12, 2),
1232 "Type = %02x (%s)",
1233 *(uchar_t *)(data+1), print_smttype(*(data+1)));
1234 } else {
1235 (void) sprintf(get_line(12, 2),
1236 "FC=%02X (%s), size = %d bytes",
1237 f->fc, print_fc(f->fc), origlen);
1240 if (is_snap) {
1241 (void) sprintf(get_line(12, 2),
1242 "LLC Type = %04X (%s)",
1243 ethertype, print_ethertype(ethertype));
1246 show_space();
1249 /* go to the next protocol layer */
1250 if (is_llc && is_snap && f->ctl == 0x03 && data_copied) {
1251 switch (ethertype) {
1252 case ETHERTYPE_IP:
1253 (void) interpret_ip(flags, (struct ip *)data, len);
1254 break;
1255 /* Just in case it is decided to add this type */
1256 case ETHERTYPE_IPV6:
1257 (void) interpret_ipv6(flags, (ip6_t *)data, len);
1258 break;
1259 case ETHERTYPE_ARP:
1260 case ETHERTYPE_REVARP:
1261 interpret_arp(flags, (struct arphdr *)data, len);
1262 break;
1263 default:
1264 break;
1269 return (elen);
1272 uint_t
1273 fddi_header_len(char *e, size_t msgsize)
1275 struct fddi_header fhdr, *f = &fhdr;
1277 if (msgsize < sizeof (struct fddi_header))
1278 return (0);
1280 (void) memcpy(&f->fc, e, sizeof (f->fc));
1281 (void) memcpy(&f->dhost, e+1, sizeof (struct ether_addr));
1282 (void) memcpy(&f->shost, e+7, sizeof (struct ether_addr));
1284 if ((f->fc&0x50) == 0x50) {
1285 (void) memcpy(&f->dsap, e+13, sizeof (f->dsap));
1286 (void) memcpy(&f->ssap, e+14, sizeof (f->ssap));
1287 (void) memcpy(&f->ctl, e+15, sizeof (f->ctl));
1288 if (f->dsap == 0xaa && f->ssap == 0xaa) {
1289 return (21);
1291 return (16);
1292 } else {
1293 if ((f->fc&0x41) == 0x41 || (f->fc&0x4f) == 0x4f) {
1294 return (13);
1297 /* Return the default FDDI header length. */
1298 return (13);
1302 * Print the given Ethernet address
1304 char *
1305 printether(struct ether_addr *p)
1307 static char buf[256];
1309 sprintf(buf, "%x:%x:%x:%x:%x:%x",
1310 p->ether_addr_octet[0],
1311 p->ether_addr_octet[1],
1312 p->ether_addr_octet[2],
1313 p->ether_addr_octet[3],
1314 p->ether_addr_octet[4],
1315 p->ether_addr_octet[5]);
1317 return (buf);
1321 * Table of Ethernet Address Assignments
1322 * Some of the more popular entries
1323 * are at the beginning of the table
1324 * to reduce search time. Note that the
1325 * e-block's are stored in host byte-order.
1327 struct block_type {
1328 int e_block;
1329 char *e_name;
1330 } ether_block [] = {
1331 0x080020, "Sun",
1332 0x0000C6, "HP",
1333 0x08002B, "DEC",
1334 0x00000F, "NeXT",
1335 0x00000C, "Cisco",
1336 0x080069, "Silicon Graphics",
1337 0x000069, "Silicon Graphics",
1338 0x0000A7, "Network Computing Devices (NCD X-terminal)",
1339 0x08005A, "IBM",
1340 0x0000AC, "Apollo",
1341 0x0180C2, "Standard MAC Group Address",
1342 /* end of popular entries */
1343 0x000002, "BBN",
1344 0x000010, "Sytek",
1345 0x000011, "Tektronix",
1346 0x000018, "Webster (?)",
1347 0x00001B, "Novell",
1348 0x00001D, "Cabletron",
1349 0x000020, "DIAB (Data Industrier AB)",
1350 0x000021, "SC&C",
1351 0x000022, "Visual Technology",
1352 0x000029, "IMC",
1353 0x00002A, "TRW",
1354 0x00003D, "AT&T",
1355 0x000049, "Apricot Ltd.",
1356 0x000055, "AT&T",
1357 0x00005A, "S & Koch",
1358 0x00005A, "Xerox 806 (unregistered)",
1359 0x00005E, "U.S. Department of Defense (IANA)",
1360 0x000065, "Network General",
1361 0x00006B, "MIPS",
1362 0x000077, "MIPS",
1363 0x000079, "NetWare (?)",
1364 0x00007A, "Ardent",
1365 0x00007B, "Research Machines",
1366 0x00007D, "Harris (3M) (old)",
1367 0x000080, "Imagen(?)",
1368 0x000081, "Synoptics",
1369 0x000084, "Aquila (?)",
1370 0x000086, "Gateway (?)",
1371 0x000089, "Cayman Systems Gatorbox",
1372 0x000093, "Proteon",
1373 0x000094, "Asante",
1374 0x000098, "Cross Com",
1375 0x00009F, "Ameristar Technology",
1376 0x0000A2, "Wellfleet",
1377 0x0000A3, "Network Application Technology",
1378 0x0000A4, "Acorn",
1379 0x0000A6, "Network General",
1380 0x0000A7, "Network Computing Devices (NCD X-terminal)",
1381 0x0000A9, "Network Systems",
1382 0x0000AA, "Xerox",
1383 0x0000B3, "CIMLinc",
1384 0x0000B5, "Datability Terminal Server",
1385 0x0000B7, "Dove Fastnet",
1386 0x0000BC, "Allen-Bradley",
1387 0x0000C0, "Western Digital",
1388 0x0000C8, "Altos",
1389 0x0000C9, "Emulex Terminal Server",
1390 0x0000D0, "Develcon Electronics, Ltd.",
1391 0x0000D1, "Adaptec Inc. Nodem product",
1392 0x0000D7, "Dartmouth College (NED Router)",
1393 0x0000DD, "Gould",
1394 0x0000DE, "Unigraph",
1395 0x0000E2, "Acer Counterpoint",
1396 0x0000E8, "Accton Technology Corporation",
1397 0x0000EE, "Network Designers Limited(?)",
1398 0x0000EF, "Alantec",
1399 0x0000F3, "Gandalf",
1400 0x0000FD, "High Level Hardware (Orion, UK)",
1401 0x000143, "IEEE 802",
1402 0x001700, "Kabel",
1403 0x004010, "Sonic",
1404 0x00608C, "3Com",
1405 0x00800F, "SMC",
1406 0x008019, "Dayna Communications Etherprint product",
1407 0x00802D, "Xylogics, Inc. Annex terminal servers",
1408 0x008035, "Technology Works",
1409 0x008087, "Okidata",
1410 0x00808C, "Frontier Software Development",
1411 0x0080C7, "Xircom Inc.",
1412 0x0080D0, "Computer Products International",
1413 0x0080D3, "Shiva Appletalk-Ethernet interface",
1414 0x0080D4, "Chase Limited",
1415 0x0080F1, "Opus",
1416 0x00AA00, "Intel",
1417 0x00B0D0, "Computer Products International",
1418 0x00DD00, "Ungermann-Bass",
1419 0x00DD01, "Ungermann-Bass",
1420 0x00EFE5, "IBM (3Com card)",
1421 0x020406, "BBN",
1422 0x026060, "3Com",
1423 0x026086, "Satelcom MegaPac (UK)",
1424 0x02E6D3, "Bus-Tech, Inc. (BTI)",
1425 0x080001, "Computer Vision",
1426 0x080002, "3Com (Formerly Bridge)",
1427 0x080003, "ACC (Advanced Computer Communications)",
1428 0x080005, "Symbolics",
1429 0x080007, "Apple",
1430 0x080008, "BBN",
1431 0x080009, "Hewlett-Packard",
1432 0x08000A, "Nestar Systems",
1433 0x08000B, "Unisys",
1434 0x08000D, "ICL",
1435 0x08000E, "NCR",
1436 0x080010, "AT&T",
1437 0x080011, "Tektronix, Inc.",
1438 0x080017, "NSC",
1439 0x08001A, "Data General",
1440 0x08001B, "Data General",
1441 0x08001E, "Apollo",
1442 0x080022, "NBI",
1443 0x080025, "CDC",
1444 0x080026, "Norsk Data (Nord)",
1445 0x080027, "PCS Computer Systems GmbH",
1446 0x080028, "TI Explorer",
1447 0x08002E, "Metaphor",
1448 0x08002F, "Prime Computer",
1449 0x080036, "Intergraph CAE stations",
1450 0x080037, "Fujitsu-Xerox",
1451 0x080038, "Bull",
1452 0x080039, "Spider Systems",
1453 0x08003B, "Torus Systems",
1454 0x08003E, "Motorola VME bus processor module",
1455 0x080041, "DCA Digital Comm. Assoc.",
1456 0x080046, "Sony",
1457 0x080047, "Sequent",
1458 0x080049, "Univation",
1459 0x08004C, "Encore",
1460 0x08004E, "BICC",
1461 0x080056, "Stanford University",
1462 0x080057, "Evans & Sutherland (?)",
1463 0x080067, "Comdesign",
1464 0x080068, "Ridge",
1465 0x08006A, "ATTst (?)",
1466 0x08006E, "Excelan",
1467 0x080075, "DDE (Danish Data Elektronik A/S)",
1468 0x080077, "TSL (now Retix)",
1469 0x08007C, "Vitalink TransLAN III",
1470 0x080080, "XIOS",
1471 0x080081, "Crosfield Electronics",
1472 0x080086, "Imagen/QMS",
1473 0x080087, "Xyplex terminal server",
1474 0x080089, "Kinetics AppleTalk-Ethernet interface",
1475 0x08008B, "Pyramid",
1476 0x08008D, "XyVision",
1477 0x080090, "Retix Inc Bridge",
1478 0x10005A, "IBM",
1479 0x1000D4, "DEC",
1480 0x400003, "NetWare",
1481 0x800010, "AT&T",
1482 0xAA0004, "DEC (DECNET)",
1483 0xC00000, "SMC",
1484 0, "",
1488 * The oui argument should be in host byte-order to conform with
1489 * the above array's values.
1491 char *
1492 ether_ouiname(uint32_t oui)
1494 uint_t i;
1496 for (i = 0; ether_block[i].e_block != 0; i++)
1497 if (oui == ether_block[i].e_block)
1498 return (ether_block[i].e_name);
1500 return (NULL);
1504 * Print the additional Ethernet address info
1506 static char *
1507 print_etherinfo(struct ether_addr *eaddr)
1509 uint_t addr = 0;
1510 char *p = (char *)&addr + 1;
1511 char *ename;
1513 (void) memcpy(p, eaddr, 3);
1515 if (memcmp(eaddr, &ether_broadcast, sizeof (struct ether_addr)) == 0)
1516 return ("(broadcast)");
1518 addr = ntohl(addr); /* make it right for little-endians */
1519 ename = ether_ouiname(addr);
1521 if (ename != NULL)
1522 return (ename);
1523 else
1524 return ((eaddr->ether_addr_octet[0] & 1) ? "(multicast)" : "");
1527 static uchar_t endianswap[] = {
1528 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
1529 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
1530 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1531 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
1532 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
1533 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1534 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
1535 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1536 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1537 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1538 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1539 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1540 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1541 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1542 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1543 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1544 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1545 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1546 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1547 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1548 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1549 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1550 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1551 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1552 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1553 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1554 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1555 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1556 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1557 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1558 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1559 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
1562 static void
1563 addr_copy_swap(struct ether_addr *pd, struct ether_addr *ps)
1565 pd->ether_addr_octet[0] = endianswap[ps->ether_addr_octet[0]];
1566 pd->ether_addr_octet[1] = endianswap[ps->ether_addr_octet[1]];
1567 pd->ether_addr_octet[2] = endianswap[ps->ether_addr_octet[2]];
1568 pd->ether_addr_octet[3] = endianswap[ps->ether_addr_octet[3]];
1569 pd->ether_addr_octet[4] = endianswap[ps->ether_addr_octet[4]];
1570 pd->ether_addr_octet[5] = endianswap[ps->ether_addr_octet[5]];
1573 /* ARGSUSED */
1574 uint_t
1575 ib_header_len(char *hdr, size_t msgsize)
1577 return (IPOIB_HDRSIZE);
1580 static uint_t
1581 interpret_ib(int flags, char *header, int elen, int origlen)
1583 struct ipoib_header *hdr = (struct ipoib_header *)header;
1584 char *off;
1585 int len;
1586 unsigned short ethertype;
1587 int blen = MAX(origlen, 4096);
1589 if (data != NULL && datalen != 0 && datalen < blen) {
1590 free(data);
1591 data = NULL;
1592 datalen = 0;
1594 if (data == NULL) {
1595 data = malloc(blen);
1596 if (data == NULL)
1597 pr_err("Warning: malloc failure");
1598 datalen = blen;
1600 if (origlen < IPOIB_HDRSIZE) {
1601 if (flags & F_SUM)
1602 (void) snprintf(get_sum_line(), MAXLINE,
1603 "RUNT (short packet - %d bytes)", origlen);
1604 if (flags & F_DTAIL)
1605 show_header("RUNT: ", "Short packet", origlen);
1606 return (elen);
1608 if (elen < IPOIB_HDRSIZE)
1609 return (elen);
1612 * It is not possible to understand just by looking
1613 * at the header whether this was a broad/multi cast
1614 * packet; thus dst_name is not updated.
1616 ethertype = ntohs(hdr->ipoib_type);
1617 len = elen - IPOIB_HDRSIZE;
1618 off = (char *)(hdr + 1);
1619 (void) memcpy(data, off, len);
1621 if (flags & F_SUM) {
1622 (void) snprintf(get_sum_line(), MAXLINE,
1623 "IPIB Type=%04X (%s), size = %d bytes",
1624 ethertype,
1625 print_ethertype(ethertype),
1626 origlen);
1629 if (flags & F_DTAIL) {
1630 show_header("IPIB: ", "IPIB Header", elen);
1631 show_space();
1632 (void) snprintf(get_line(0, 0), get_line_remain(),
1633 "Packet %d arrived at %d:%02d:%d.%02d",
1634 pi_frame, pi_time_hour, pi_time_min,
1635 pi_time_sec, pi_time_usec / 10000);
1636 (void) snprintf(get_line(0, 0), get_line_remain(),
1637 "Packet size = %d bytes", elen, elen);
1638 (void) snprintf(get_line(0, 2), get_line_remain(),
1639 "Ethertype = %04X (%s)", ethertype,
1640 print_ethertype(ethertype));
1641 show_space();
1644 /* Go to the next protocol layer */
1645 switch (ethertype) {
1646 case ETHERTYPE_IP:
1647 (void) interpret_ip(flags, (struct ip *)data, len);
1648 break;
1649 case ETHERTYPE_IPV6:
1650 (void) interpret_ipv6(flags, (ip6_t *)data, len);
1651 break;
1652 case ETHERTYPE_ARP:
1653 case ETHERTYPE_REVARP:
1654 interpret_arp(flags, (struct arphdr *)data, len);
1655 break;
1658 return (elen);
1661 /* ARGSUSED */
1662 uint_t
1663 ipnet_header_len(char *hdr, size_t msgsize)
1665 return (sizeof (dl_ipnetinfo_t));
1668 #define MAX_UINT64_STR 22
1669 static uint_t
1670 interpret_ipnet(int flags, char *header, int elen, int origlen)
1672 dl_ipnetinfo_t dl;
1673 size_t len = elen - sizeof (dl_ipnetinfo_t);
1674 char *off = (char *)header + sizeof (dl_ipnetinfo_t);
1675 int blen = MAX(origlen, 8252);
1676 char szone[MAX_UINT64_STR];
1677 char dzone[MAX_UINT64_STR];
1679 (void) memcpy(&dl, header, sizeof (dl));
1680 if (data != NULL && datalen != 0 && datalen < blen) {
1681 free(data);
1682 data = NULL;
1683 datalen = 0;
1685 if (data == NULL) {
1686 data = (char *)malloc(blen);
1687 if (!data)
1688 pr_err("Warning: malloc failure");
1689 datalen = blen;
1692 if (dl.dli_zsrc == ALL_ZONES)
1693 sprintf(szone, "Unknown");
1694 else
1695 sprintf(szone, "%lu", BE_32(dl.dli_zsrc));
1697 if (dl.dli_zdst == ALL_ZONES)
1698 sprintf(dzone, "Unknown");
1699 else
1700 sprintf(dzone, "%lu", BE_32(dl.dli_zdst));
1702 if (flags & F_SUM) {
1703 (void) snprintf(get_sum_line(), MAXLINE,
1704 "IPNET src zone %s dst zone %s", szone, dzone);
1707 if (flags & F_DTAIL) {
1708 show_header("IPNET: ", "IPNET Header", elen);
1709 show_space();
1710 (void) sprintf(get_line(0, 0),
1711 "Packet %d arrived at %d:%02d:%d.%05d",
1712 pi_frame,
1713 pi_time_hour, pi_time_min, pi_time_sec,
1714 pi_time_usec / 10);
1715 (void) sprintf(get_line(0, 0),
1716 "Packet size = %d bytes",
1717 elen);
1718 (void) snprintf(get_line(0, 0), get_line_remain(),
1719 "dli_version = %d", dl.dli_version);
1720 (void) snprintf(get_line(0, 0), get_line_remain(),
1721 "dli_family = %d", dl.dli_family);
1722 (void) snprintf(get_line(0, 2), get_line_remain(),
1723 "dli_zsrc = %s", szone);
1724 (void) snprintf(get_line(0, 2), get_line_remain(),
1725 "dli_zdst = %s", dzone);
1726 show_space();
1728 memcpy(data, off, len);
1730 switch (dl.dli_family) {
1731 case AF_INET:
1732 (void) interpret_ip(flags, (struct ip *)data, len);
1733 break;
1734 case AF_INET6:
1735 (void) interpret_ipv6(flags, (ip6_t *)data, len);
1736 break;
1737 default:
1738 break;
1741 return (0);
1744 uint_t
1745 ipv4_header_len(char *hdr, size_t msgsize)
1747 return (msgsize < sizeof (ipha_t) ? 0 : IPH_HDR_LENGTH((ipha_t *)hdr));
1751 * The header length needs to include all potential extension headers, as the
1752 * caller expects to use this length as an offset to the inner network layer
1753 * header to be used as a filter offset. IPsec headers aren't passed up here,
1754 * and neither are fragmentation headers.
1756 uint_t
1757 ipv6_header_len(char *hdr, size_t msgsize)
1759 ip6_t *ip6hdr = (ip6_t *)hdr;
1760 ip6_hbh_t *exthdr;
1761 uint_t hdrlen = sizeof (ip6_t), exthdrlen;
1762 char *pptr;
1763 uint8_t nxt;
1765 if (msgsize < sizeof (ip6_t))
1766 return (0);
1768 nxt = ip6hdr->ip6_nxt;
1769 pptr = (char *)(ip6hdr + 1);
1771 while (nxt != IPPROTO_ENCAP && nxt != IPPROTO_IPV6) {
1772 switch (nxt) {
1773 case IPPROTO_HOPOPTS:
1774 case IPPROTO_DSTOPTS:
1775 case IPPROTO_ROUTING:
1776 if (msgsize < hdrlen + sizeof (ip6_hbh_t))
1777 return (0);
1778 exthdr = (ip6_hbh_t *)pptr;
1779 exthdrlen = 8 + exthdr->ip6h_len * 8;
1780 hdrlen += exthdrlen;
1781 pptr += exthdrlen;
1782 nxt = exthdr->ip6h_nxt;
1783 break;
1784 default:
1786 * This is garbage, there's no way to know where the
1787 * inner IP header is.
1789 return (0);
1793 return (hdrlen);
1796 /* ARGSUSED */
1797 uint_t
1798 interpret_iptun(int flags, char *header, int elen, int origlen)
1800 (void) interpret_ip(flags, (struct ip *)header, elen);
1801 return (elen);