Home | History | Annotate | Download | only in snoop
      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