1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <stdio.h>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <sys/ethernet.h>
31 #include <sys/vlan.h>
32 #include <net/trill.h>
33 
34 #include <snoop.h>
35 
36 int
interpret_trill(int flags,struct ether_header ** e,char * data,int * alen)37 interpret_trill(int flags, struct ether_header **e, char *data, int *alen)
38 {
39 	trill_header_t *trillhdr;
40 	struct ether_header *inner_ethhdr;
41 	struct ether_vlan_header *inner_ethvlanhdr;
42 	uint16_t ethertype;
43 	int dlen = *alen;
44 	size_t optslen;
45 	size_t trillhdrlen;
46 
47 	if (dlen < sizeof (trill_header_t)) {
48 		(void) snprintf(get_sum_line(), MAXLINE,
49 		    "TRILL (short packet)");
50 		return (0);
51 	}
52 
53 	trillhdr = (trill_header_t *)data;
54 	optslen = GET_TRILL_OPTS_LEN(trillhdr) * sizeof (uint32_t);
55 
56 	if (flags & F_DTAIL) {
57 		show_header("TRILL: ", "TRILL Data Frame", dlen);
58 		show_space();
59 
60 		(void) snprintf(get_line(0, 0), get_line_remain(),
61 		    "Egress nickname = %d",
62 		    ntohs(trillhdr->th_egressnick));
63 		(void) snprintf(get_line(0, 0), get_line_remain(),
64 		    "Ingress nickname = %d",
65 		    ntohs(trillhdr->th_ingressnick));
66 		(void) snprintf(get_line(0, 0), get_line_remain(),
67 		    "Hop count = %d", trillhdr->th_hopcount);
68 		(void) snprintf(get_line(0, 0), get_line_remain(),
69 		    "Multi-destination = %d", trillhdr->th_multidest);
70 		(void) snprintf(get_line(0, 0), get_line_remain(),
71 		    "Options Len = %d bytes", optslen);
72 		show_trailer();
73 	}
74 
75 	trillhdrlen = sizeof (trill_header_t) + optslen;
76 
77 	if (dlen < trillhdrlen) {
78 		(void) snprintf(get_sum_line(), MAXLINE,
79 		    "TRILL (options truncated)");
80 		return (0);
81 	}
82 
83 	dlen -= trillhdrlen;
84 
85 	if (dlen < sizeof (struct ether_header)) {
86 		(void) snprintf(get_sum_line(), MAXLINE,
87 		    "TRILL (missing required inner MAC)");
88 		return (0);
89 	}
90 
91 	inner_ethhdr = (struct ether_header *)(data + trillhdrlen);
92 	if (inner_ethhdr->ether_type != htons(ETHERTYPE_VLAN)) {
93 		(void) snprintf(get_sum_line(), MAXLINE,
94 		    "TRILL (inner VLAN missing; ethertype %X)",
95 		    ntohs(inner_ethhdr->ether_type));
96 		return (0);
97 	}
98 
99 	inner_ethvlanhdr = (struct ether_vlan_header *)inner_ethhdr;
100 	ethertype = ntohs(inner_ethvlanhdr->ether_type);
101 
102 	if (flags & F_SUM) {
103 		(void) snprintf(get_sum_line(), MAXLINE,
104 		    "TRILL D:%d S:%d HC:%d M:%d O:%d L:%d VLAN:%d %s",
105 		    ntohs(trillhdr->th_egressnick),
106 		    ntohs(trillhdr->th_ingressnick),
107 		    trillhdr->th_hopcount,
108 		    trillhdr->th_multidest,
109 		    optslen,
110 		    dlen, VLAN_ID(inner_ethvlanhdr->ether_tci),
111 		    print_ethertype(ethertype));
112 	}
113 
114 	*alen = dlen;
115 	*e = inner_ethhdr;
116 	return (ethertype);
117 }
118