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 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