Home | History | Annotate | Download | only in snoop
      1  0  stevel /*
      2  0  stevel  * CDDL HEADER START
      3  0  stevel  *
      4  0  stevel  * The contents of this file are subject to the terms of the
      5  0  stevel  * Common Development and Distribution License, Version 1.0 only
      6  0  stevel  * (the "License").  You may not use this file except in compliance
      7  0  stevel  * with the License.
      8  0  stevel  *
      9  0  stevel  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
     10  0  stevel  * or http://www.opensolaris.org/os/licensing.
     11  0  stevel  * See the License for the specific language governing permissions
     12  0  stevel  * and limitations under the License.
     13  0  stevel  *
     14  0  stevel  * When distributing Covered Code, include this CDDL HEADER in each
     15  0  stevel  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     16  0  stevel  * If applicable, add the following below this CDDL HEADER, with the
     17  0  stevel  * fields enclosed by brackets "[]" replaced with your own identifying
     18  0  stevel  * information: Portions Copyright [yyyy] [name of copyright owner]
     19  0  stevel  *
     20  0  stevel  * CDDL HEADER END
     21  0  stevel  */
     22  0  stevel /*
     23  0  stevel  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
     24  0  stevel  * Use is subject to license terms.
     25  0  stevel  */
     26  0  stevel 
     27  0  stevel #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28  0  stevel 
     29  0  stevel #include <stdio.h>
     30  0  stevel #include <string.h>
     31  0  stevel #include <sys/types.h>
     32  0  stevel #include <sys/socket.h>
     33  0  stevel #include <net/if.h>
     34  0  stevel #include <sys/stropts.h>
     35  0  stevel #include <sys/sysmacros.h>
     36  0  stevel #include <netinet/in_systm.h>
     37  0  stevel #include <netinet/in.h>
     38  0  stevel #include <netinet/ip.h>
     39  0  stevel #include <netinet/igmp.h>
     40  0  stevel #include <inet/ip.h>
     41  0  stevel #include <arpa/inet.h>
     42  0  stevel #include <netdb.h>
     43  0  stevel #include "snoop.h"
     44  0  stevel 
     45  0  stevel static void interpret_igmpv3qry(struct igmp *, int);
     46  0  stevel static void interpret_igmpv3rpt(struct igmp *, int);
     47  0  stevel 
     48  0  stevel 
     49  0  stevel /*ARGSUSED*/
     50  0  stevel void
     51  0  stevel interpret_igmp(int flags, char *data, int iplen, int ilen)
     52  0  stevel {
     53  0  stevel 	const char *pt;
     54  0  stevel 	char *line;
     55  0  stevel 	struct igmp *igmp = (struct igmp *)data;
     56  0  stevel 	char addrstr[INET_ADDRSTRLEN];
     57  0  stevel 
     58  0  stevel 	if (ilen < IGMP_MINLEN) {
     59  0  stevel 		/* incomplete header */
     60  0  stevel 		line = get_sum_line();
     61  0  stevel 		(void) snprintf(line, MAXLINE, "Malformed IGMP packet");
     62  0  stevel 		return;
     63  0  stevel 	}
     64  0  stevel 
     65  0  stevel 	switch (igmp->igmp_type) {
     66  0  stevel 	case IGMP_MEMBERSHIP_QUERY:
     67  0  stevel 		if (ilen == IGMP_MINLEN) {
     68  0  stevel 			if (igmp->igmp_code == 0)
     69  0  stevel 				pt = "v1 membership query";
     70  0  stevel 			else
     71  0  stevel 				pt = "v2 membership query";
     72  0  stevel 		} else if (ilen >= IGMP_V3_QUERY_MINLEN) {
     73  0  stevel 			pt = "v3 membership query";
     74  0  stevel 		} else {
     75  0  stevel 			pt = "Unknown membership query";
     76  0  stevel 		}
     77  0  stevel 		break;
     78  0  stevel 	case IGMP_V1_MEMBERSHIP_REPORT:
     79  0  stevel 		pt = "v1 membership report";
     80  0  stevel 		break;
     81  0  stevel 	case IGMP_V2_MEMBERSHIP_REPORT:
     82  0  stevel 		pt = "v2 membership report";
     83  0  stevel 		break;
     84  0  stevel 	case IGMP_V3_MEMBERSHIP_REPORT:
     85  0  stevel 		pt = "v3 membership report";
     86  0  stevel 		break;
     87  0  stevel 	case IGMP_V2_LEAVE_GROUP:
     88  0  stevel 		pt = "v2 leave group";
     89  0  stevel 		break;
     90  0  stevel 
     91  0  stevel 	default:
     92  0  stevel 		pt = "Unknown";
     93  0  stevel 		break;
     94  0  stevel 	}
     95  0  stevel 
     96  0  stevel 	if (flags & F_SUM) {
     97  0  stevel 		line = get_sum_line();
     98  0  stevel 		(void) snprintf(line, MAXLINE, "IGMP %s", pt);
     99  0  stevel 	}
    100  0  stevel 
    101  0  stevel 	if (flags & F_DTAIL) {
    102  0  stevel 		show_header("IGMP:  ", "IGMP Header", ilen);
    103  0  stevel 		show_space();
    104  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    105  0  stevel 		    "Type = %d (%s)", igmp->igmp_type, pt);
    106  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    107  0  stevel 		    "Max Response Time = %d", igmp->igmp_code);
    108  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    109  0  stevel 		    "Checksum = %x", ntohs(igmp->igmp_cksum));
    110  0  stevel 
    111  0  stevel 		if (igmp->igmp_type == IGMP_MEMBERSHIP_QUERY &&
    112  0  stevel 		    ilen >= IGMP_V3_QUERY_MINLEN) {
    113  0  stevel 			interpret_igmpv3qry(igmp, ilen);
    114  0  stevel 		} else if (igmp->igmp_type == IGMP_V3_MEMBERSHIP_REPORT) {
    115  0  stevel 			interpret_igmpv3rpt(igmp, ilen);
    116  0  stevel 		} else {
    117  0  stevel 			(void) snprintf(get_line(0, 0), get_line_remain(),
    118  0  stevel 			    "Group = %s",
    119  0  stevel 			    inet_ntop(AF_INET, &igmp->igmp_group.s_addr,
    120  0  stevel 			    addrstr, INET_ADDRSTRLEN));
    121  0  stevel 		}
    122  0  stevel 
    123  0  stevel 		show_space();
    124  0  stevel 	}
    125  0  stevel }
    126  0  stevel 
    127  0  stevel static void
    128  0  stevel interpret_igmpv3qry(struct igmp *igmp, int ilen)
    129  0  stevel {
    130  0  stevel 	struct igmp3q *qry;
    131  0  stevel 	struct in_addr *src;
    132  0  stevel 	int rem = ilen;
    133  0  stevel 	int srccnt;
    134  0  stevel 	char addrstr[INET_ADDRSTRLEN];
    135  0  stevel 
    136  0  stevel 	if (ilen < sizeof (*qry)) {
    137  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    138  0  stevel 		    "Malformed IGMP Query");
    139  0  stevel 		return;
    140  0  stevel 	}
    141  0  stevel 
    142  0  stevel 	qry = (struct igmp3q *)igmp;
    143  0  stevel 	rem -= sizeof (*qry);
    144  0  stevel 	srccnt = ntohs(qry->igmp3q_numsrc);
    145  0  stevel 	(void) snprintf(get_line(0, 0), get_line_remain(),
    146  0  stevel 	    "Group = %s", inet_ntop(AF_INET, &qry->igmp3q_group, addrstr,
    147  0  stevel 	    INET_ADDRSTRLEN));
    148  0  stevel 	(void) snprintf(get_line(0, 0), get_line_remain(),
    149  0  stevel 	    "%d Source Address%s:", srccnt, (srccnt == 1) ? "" : "es");
    150  0  stevel 
    151  0  stevel 	src = (struct in_addr *)&qry[1];
    152  0  stevel 	while (srccnt > 0 && rem >= sizeof (*src)) {
    153  0  stevel 		rem -= sizeof (*src);
    154  0  stevel 
    155  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(), "    %s",
    156  0  stevel 		    inet_ntop(AF_INET, &src->s_addr, addrstr, INET_ADDRSTRLEN));
    157  0  stevel 
    158  0  stevel 		srccnt--;
    159  0  stevel 		src++;
    160  0  stevel 	}
    161  0  stevel }
    162  0  stevel 
    163  0  stevel #define	MAX_IGMPV3_REPORT_TYPE	6
    164  0  stevel 
    165  0  stevel const char *igmpv3rpt_types[] = {
    166  0  stevel 	"<unknown>",
    167  0  stevel 	"MODE_IS_INCLUDE",
    168  0  stevel 	"MODE_IS_EXCLUDE",
    169  0  stevel 	"CHANGE_TO_INCLUDE",
    170  0  stevel 	"CHANGE_TO_EXCLUDE",
    171  0  stevel 	"ALLOW_NEW_SOURCES",
    172  0  stevel 	"BLOCK_OLD_SOURCES",
    173  0  stevel };
    174  0  stevel 
    175  0  stevel static void
    176  0  stevel interpret_igmpv3rpt(struct igmp *igmp, int ilen)
    177  0  stevel {
    178  0  stevel 	struct igmp3r *rpt;
    179  0  stevel 	struct grphdr *grh;
    180  0  stevel 	struct in_addr *src;
    181  0  stevel 	int rem = ilen, auxlen;
    182  0  stevel 	uint16_t grhcnt, srccnt;
    183  0  stevel 	char addrstr[INET_ADDRSTRLEN];
    184  0  stevel 
    185  0  stevel 	if (ilen < sizeof (*rpt)) {
    186  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    187  0  stevel 		    "Malformed IGMPv3 Report");
    188  0  stevel 		return;
    189  0  stevel 	}
    190  0  stevel 
    191  0  stevel 	rpt = (struct igmp3r *)igmp;
    192  0  stevel 	grh = (struct grphdr *)&rpt[1];
    193  0  stevel 	grhcnt = ntohs(rpt->igmp3r_numrec);
    194  0  stevel 	(void) snprintf(get_line(0, 0), get_line_remain(),
    195  0  stevel 	    "%d Group Record%s:", grhcnt, (grhcnt == 1) ? "" : "s");
    196  0  stevel 	rem -= sizeof (*rpt);
    197  0  stevel 	while (grhcnt > 0 && rem >= sizeof (*grh)) {
    198  0  stevel 		rem -= sizeof (*grh);
    199  0  stevel 
    200  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    201  0  stevel 		    "Group = %s  type = %s", inet_ntop(AF_INET,
    202  0  stevel 		    &grh->grphdr_group.s_addr, addrstr, INET_ADDRSTRLEN),
    203  0  stevel 		    (grh->grphdr_type > MAX_IGMPV3_REPORT_TYPE) ?
    204  0  stevel 		    "<unknown>" : igmpv3rpt_types[grh->grphdr_type]);
    205  0  stevel 		srccnt = ntohs(grh->grphdr_numsrc);
    206  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    207  0  stevel 		    "%d Source Address%s:", srccnt, (srccnt == 1) ? "" : "es");
    208  0  stevel 
    209  0  stevel 		src = (struct in_addr *)&grh[1];
    210  0  stevel 		while (srccnt > 0 && rem >= sizeof (*src)) {
    211  0  stevel 			rem -= sizeof (*src);
    212  0  stevel 
    213  0  stevel 			(void) snprintf(get_line(0, 0), get_line_remain(),
    214  0  stevel 			    "    %s", inet_ntop(AF_INET, &src->s_addr, addrstr,
    215  0  stevel 			    INET_ADDRSTRLEN));
    216  0  stevel 
    217  0  stevel 			srccnt--;
    218  0  stevel 			src++;
    219  0  stevel 		}
    220  0  stevel 
    221  0  stevel 		grhcnt--;
    222  0  stevel 		auxlen = grh->grphdr_auxlen * 4;
    223  0  stevel 		rem -= auxlen;
    224  0  stevel 		grh = (struct grphdr *)((uint8_t *)src + auxlen);
    225  0  stevel 	}
    226  0  stevel }
    227