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 2004 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 <ctype.h>
     31  0  stevel #include <string.h>
     32  0  stevel #include <fcntl.h>
     33  0  stevel #include <string.h>
     34  0  stevel #include <sys/types.h>
     35  0  stevel #include <sys/time.h>
     36  0  stevel #include <sys/socket.h>
     37  0  stevel #include <sys/sockio.h>
     38  0  stevel #include <net/if.h>
     39  0  stevel #include <netinet/in_systm.h>
     40  0  stevel #include <netinet/in.h>
     41  0  stevel #include <netinet/ip.h>
     42  0  stevel #include <netinet/if_ether.h>
     43  0  stevel #include <arpa/inet.h>
     44  0  stevel #include "snoop.h"
     45  0  stevel #include "snoop_ospf.h"
     46  0  stevel #include "snoop_ospf6.h"
     47  0  stevel 
     48  0  stevel extern char *dlc_header;
     49  0  stevel static char *sum_line;
     50  0  stevel extern const struct bits ospf_db_flags_bits[];
     51  0  stevel extern const struct bits ospf_rla_flag_bits[];
     52  0  stevel extern const struct bits ospf_option_bits[];
     53  0  stevel 
     54  0  stevel const struct bits ospf6_option_bits[] = {
     55  0  stevel 	{ OSPF_OPTION_V6,	"V6" },
     56  0  stevel 	{ OSPF_OPTION_E,	"E" },
     57  0  stevel 	{ OSPF_OPTION_MC,	"MC" },
     58  0  stevel 	{ OSPF_OPTION_N,	"N" },
     59  0  stevel 	{ OSPF_OPTION_R,	"R" },
     60  0  stevel 	{ OSPF_OPTION_DC,	"DC" },
     61  0  stevel 	{ 0,			NULL }
     62  0  stevel };
     63  0  stevel 
     64  0  stevel /*
     65  0  stevel  * return a printable string in dotted-decimal notation
     66  0  stevel  * for id.
     67  0  stevel  */
     68  0  stevel static char *
     69  0  stevel print_ipaddr(uint32_t id)
     70  0  stevel {
     71  0  stevel 	struct in_addr tmp;
     72  0  stevel 
     73  0  stevel 	tmp.s_addr = id;
     74  0  stevel 	return (inet_ntoa(tmp));
     75  0  stevel }
     76  0  stevel 
     77  0  stevel static int
     78  0  stevel interpret_ospf6_hello(int flags, struct ospf6hdr *op, int fraglen)
     79  0  stevel {
     80  0  stevel 	uint32_t *nbr;
     81  0  stevel 	int j;
     82  0  stevel 
     83  0  stevel 	if (fraglen < OSPF6_MIN_HEADER_SIZE + OSPF_MIN_HELLO_HEADER_SIZE)
     84  0  stevel 		return (-1); /* truncated packet */
     85  0  stevel 
     86  0  stevel 	if (flags & F_SUM) {
     87  0  stevel 		if (op->ospf6_hello.hello_dr != 0) {
     88  0  stevel 			(void) sprintf(sum_line, "DR=%s ",
     89  0  stevel 			    print_ipaddr(op->ospf6_hello.hello_dr));
     90  0  stevel 		}
     91  0  stevel 		sum_line += strlen(sum_line);
     92  0  stevel 		if (op->ospf6_hello.hello_bdr != 0) {
     93  0  stevel 			(void) sprintf(sum_line, "BDR=%s ",
     94  0  stevel 			    print_ipaddr(op->ospf6_hello.hello_bdr));
     95  0  stevel 		}
     96  0  stevel 		sum_line += strlen(sum_line);
     97  0  stevel 		j = 0;
     98  0  stevel 		nbr = op->ospf6_hello.hello_neighbor;
     99  0  stevel 		while ((uchar_t *)nbr < ((uchar_t *)op + fraglen)) {
    100  0  stevel 			if ((uchar_t *)nbr + sizeof (struct in_addr) >
    101  0  stevel 			    ((uchar_t *)op + fraglen))
    102  0  stevel 				return (-1); /* truncated */
    103  0  stevel 			++nbr;
    104  0  stevel 			j++;
    105  0  stevel 		}
    106  0  stevel 		(void) sprintf(sum_line, "%d nbrs", j);
    107  0  stevel 		sum_line += strlen(sum_line);
    108  0  stevel 
    109  0  stevel 	}
    110  0  stevel 	if (flags & F_DTAIL) {
    111  0  stevel 		show_header("OSPF HELLO:  ", "Hello Packet",
    112  0  stevel 		    ntohs(op->ospf6_len));
    113  0  stevel 		show_space();
    114  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    115  0  stevel 		    "Options = %s", ospf_print_bits(ospf6_option_bits,
    116  0  stevel 		    op->ospf6_hello.hello6_options));
    117  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    118  0  stevel 		    "Interface ID = %s",
    119  0  stevel 		    print_ipaddr(op->ospf6_hello.hello_ifid));
    120  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    121  0  stevel 		    "Hello interval = %d",
    122  0  stevel 		    ntohs(op->ospf6_hello.hello_helloint));
    123  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    124  0  stevel 		    "Priority = %d", op->ospf6_hello.hello6_priority);
    125  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    126  0  stevel 		    "Dead interval = %u", ntohl(op->ospf6_hello.hello_deadint));
    127  0  stevel 		if (op->ospf6_hello.hello_dr != 0) {
    128  0  stevel 			(void) snprintf(get_line(0, 0), get_line_remain(),
    129  0  stevel 			    "Designated Router = %s",
    130  0  stevel 			    print_ipaddr(op->ospf6_hello.hello_dr));
    131  0  stevel 		}
    132  0  stevel 		if (op->ospf6_hello.hello_bdr != 0) {
    133  0  stevel 			(void) snprintf(get_line(0, 0), get_line_remain(),
    134  0  stevel 			    "Backup Designated Router = %s",
    135  0  stevel 			    print_ipaddr(op->ospf6_hello.hello_bdr));
    136  0  stevel 		}
    137  0  stevel 		nbr = op->ospf6_hello.hello_neighbor;
    138  0  stevel 		while ((uchar_t *)nbr < ((uchar_t *)op + fraglen)) {
    139  0  stevel 			if ((uchar_t *)nbr + sizeof (struct in_addr) >
    140  0  stevel 			    ((uchar_t *)op + fraglen))
    141  0  stevel 				return (-1); /* truncated */
    142  0  stevel 			(void) snprintf(get_line(0, 0), get_line_remain(),
    143  0  stevel 			    "Neigbor: %s", print_ipaddr(*nbr));
    144  0  stevel 			++nbr;
    145  0  stevel 		}
    146  0  stevel 	}
    147  0  stevel 	return (fraglen);
    148  0  stevel }
    149  0  stevel 
    150  0  stevel static void
    151  0  stevel ospf6_print_ls_type(int flags, uint_t ls6_type, uint32_t ls6_stateid,
    152  0  stevel     uint32_t ls6_router)
    153  0  stevel {
    154  0  stevel 	char scope[15];
    155  0  stevel 
    156  0  stevel 	if (flags & F_SUM)
    157  0  stevel 		return;
    158  0  stevel 
    159  0  stevel 	switch (ls6_type & LS6_SCOPE_MASK) {
    160  0  stevel 	case LS6_SCOPE_LINKLOCAL:
    161  0  stevel 		snprintf(scope, sizeof (scope), "linklocal");
    162  0  stevel 		break;
    163  0  stevel 	case LS6_SCOPE_AREA:
    164  0  stevel 		snprintf(scope, sizeof (scope), "area");
    165  0  stevel 		break;
    166  0  stevel 	case LS6_SCOPE_AS:
    167  0  stevel 		snprintf(scope, sizeof (scope), "AS");
    168  0  stevel 		break;
    169  0  stevel 	default:
    170  0  stevel 		snprintf(scope, sizeof (scope), "");
    171  0  stevel 		break;
    172  0  stevel 	}
    173  0  stevel 	switch (ls6_type & LS_TYPE_MASK) {
    174  0  stevel 	case LS_TYPE_ROUTER:
    175  0  stevel 		if (flags & F_DTAIL) {
    176  0  stevel 			(void) snprintf(get_line(0, 0), get_line_remain(),
    177  0  stevel 			    "%s Router = %s", scope, print_ipaddr(ls6_router));
    178  0  stevel 		}
    179  0  stevel 		break;
    180  0  stevel 	case LS_TYPE_NETWORK:
    181  0  stevel 		if (flags & F_DTAIL) {
    182  0  stevel 			(void) snprintf(get_line(0, 0), get_line_remain(),
    183  0  stevel 			    "%s Net DR %s IF %s", scope,
    184  0  stevel 			    print_ipaddr(ls6_router),
    185  0  stevel 			    print_ipaddr(ls6_stateid));
    186  0  stevel 		}
    187  0  stevel 		break;
    188  0  stevel 	case LS_TYPE_INTER_AP:
    189  0  stevel 		if (flags & F_DTAIL) {
    190  0  stevel 			(void) snprintf(get_line(0, 0), get_line_remain(),
    191  0  stevel 			    "%s Inter-area-prefix = %s ABR %s", scope,
    192  0  stevel 			    print_ipaddr(ls6_stateid),
    193  0  stevel 			    print_ipaddr(ls6_router));
    194  0  stevel 		}
    195  0  stevel 		break;
    196  0  stevel 	case LS_TYPE_INTER_AR:
    197  0  stevel 		if (flags & F_DTAIL) {
    198  0  stevel 			(void) snprintf(get_line(0, 0), get_line_remain(),
    199  0  stevel 			    "%s Inter-area-router = %s Router %s", scope,
    200  0  stevel 			    print_ipaddr(ls6_router),
    201  0  stevel 			    print_ipaddr(ls6_stateid));
    202  0  stevel 		}
    203  0  stevel 		break;
    204  0  stevel 	case LS_TYPE_ASE:
    205  0  stevel 		if (flags & F_DTAIL) {
    206  0  stevel 			(void) snprintf(get_line(0, 0), get_line_remain(),
    207  0  stevel 			    "%s ASE = %s ASBR %s", scope,
    208  0  stevel 			    print_ipaddr(ls6_stateid),
    209  0  stevel 			    print_ipaddr(ls6_router));
    210  0  stevel 		}
    211  0  stevel 		break;
    212  0  stevel 	case LS_TYPE_GROUP:
    213  0  stevel 		if (flags & F_DTAIL) {
    214  0  stevel 			(void) snprintf(get_line(0, 0), get_line_remain(),
    215  0  stevel 			    "%s group = %s Router %s", scope,
    216  0  stevel 			    print_ipaddr(ls6_stateid),
    217  0  stevel 			    print_ipaddr(ls6_router));
    218  0  stevel 		}
    219  0  stevel 		break;
    220  0  stevel 	case LS_TYPE_TYPE7:
    221  0  stevel 		if (flags & F_DTAIL) {
    222  0  stevel 			(void) snprintf(get_line(0, 0), get_line_remain(),
    223  0  stevel 			    "%s Type 7 = %s Router %s", scope,
    224  0  stevel 			    print_ipaddr(ls6_stateid),
    225  0  stevel 			    print_ipaddr(ls6_router));
    226  0  stevel 		}
    227  0  stevel 		break;
    228  0  stevel 	case LS_TYPE_LINK:
    229  0  stevel 		if (flags & F_DTAIL) {
    230  0  stevel 			(void) snprintf(get_line(0, 0), get_line_remain(),
    231  0  stevel 			    "%s link = %s Router %s", scope,
    232  0  stevel 			    print_ipaddr(ls6_stateid),
    233  0  stevel 			    print_ipaddr(ls6_router));
    234  0  stevel 		}
    235  0  stevel 		break;
    236  0  stevel 	case LS_TYPE_INTRA_AP:
    237  0  stevel 		if (flags & F_DTAIL) {
    238  0  stevel 			(void) snprintf(get_line(0, 0), get_line_remain(),
    239  0  stevel 			    "%s Inter-area-prefix = %s Router %s", scope,
    240  0  stevel 			    print_ipaddr(ls6_stateid),
    241  0  stevel 			    print_ipaddr(ls6_router));
    242  0  stevel 		}
    243  0  stevel 		break;
    244  0  stevel 	default:
    245  0  stevel 		if (flags & F_DTAIL) {
    246  0  stevel 			(void) snprintf(get_line(0, 0), get_line_remain(),
    247  0  stevel 			    "%s Unknown type = 0x%x", ls6_type);
    248  0  stevel 		}
    249  0  stevel 		break;
    250  0  stevel 	}
    251  0  stevel }
    252  0  stevel 
    253  0  stevel static int
    254  0  stevel ospf6_print_lsaprefix(int flags, struct lsa6_prefix *lpfx)
    255  0  stevel {
    256  0  stevel 	int k;
    257  0  stevel 	struct in6_addr prefix;
    258  0  stevel 	char prefixstr[INET6_ADDRSTRLEN];
    259  0  stevel 
    260  0  stevel 	k = (lpfx->lsa6_plen + 31)/32;
    261  0  stevel 	if (k * 4 > sizeof (struct in6_addr)) {
    262  0  stevel 		if (flags & F_SUM) {
    263  0  stevel 			sprintf(sum_line, "Unknown prefix len %d",
    264  0  stevel 			    lpfx->lsa6_plen);
    265  0  stevel 			sum_line += strlen(sum_line);
    266  0  stevel 		}
    267  0  stevel 		if (flags & F_DTAIL) {
    268  0  stevel 			(void) snprintf(get_line(0, 0), get_line_remain(),
    269  0  stevel 			    "Unknown prefix len %d", lpfx->lsa6_plen);
    270  0  stevel 		}
    271  0  stevel 	}
    272  0  stevel 	memset((void *)&prefix, 0, sizeof (prefix));
    273  0  stevel 	memcpy((void *)&prefix, lpfx->lsa6_pfx, k * 4);
    274  0  stevel 	(void) inet_ntop(AF_INET6, (char *)&prefix, prefixstr,
    275  0  stevel 	    INET6_ADDRSTRLEN);
    276  0  stevel 	if (flags & F_SUM) {
    277  0  stevel 		sprintf(sum_line, "%s/%d", prefixstr, lpfx->lsa6_plen);
    278  0  stevel 		sum_line += strlen(sum_line);
    279  0  stevel 	}
    280  0  stevel 	if (flags & F_DTAIL) {
    281  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    282  0  stevel 		    "%s/%d", prefixstr, lpfx->lsa6_plen);
    283  0  stevel 	}
    284  0  stevel 	if (lpfx->lsa6_popt != 0) {
    285  0  stevel 		if (flags & F_SUM) {
    286  0  stevel 			sprintf(sum_line, "(opt = %x)", lpfx->lsa6_popt);
    287  0  stevel 			sum_line += strlen(sum_line);
    288  0  stevel 		}
    289  0  stevel 		if (flags & F_DTAIL) {
    290  0  stevel 			(void) snprintf(get_line(0, 0), get_line_remain(),
    291  0  stevel 			    "(opt = %x)", lpfx->lsa6_popt);
    292  0  stevel 		}
    293  0  stevel 	}
    294  0  stevel 	return (sizeof (*lpfx) - 4 + k * 4);
    295  0  stevel }
    296  0  stevel 
    297  0  stevel static void
    298  0  stevel interpret_ospf6_lsa_hdr(int flags, struct lsa6_hdr *lsah)
    299  0  stevel {
    300  0  stevel 	if (flags & F_SUM)
    301  0  stevel 		return;
    302  0  stevel 
    303  0  stevel 	if (flags & F_DTAIL) {
    304  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    305  0  stevel 		    "Sequence = %X ", ntohl(lsah->ls6_seq));
    306  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    307  0  stevel 		    "Age = %X ", ospf_print_lsa_age(ntohl(lsah->ls6_age)));
    308  0  stevel 	}
    309  0  stevel 
    310  0  stevel 	ospf6_print_ls_type(flags, lsah->ls6_type, lsah->ls6_stateid,
    311  0  stevel 	    lsah->ls6_router);
    312  0  stevel 
    313  0  stevel }
    314  0  stevel 
    315  0  stevel #define	TRUNC(addr)	((uchar_t *)(addr) > fragend)
    316  0  stevel static int
    317  0  stevel interpret_ospf6_lsa(int flags, struct lsa6 *lsa, uchar_t *fragend)
    318  0  stevel {
    319  0  stevel 	uchar_t *ls_end;
    320  0  stevel 	int  k, j;
    321  0  stevel 	struct rla6link *rl;
    322  0  stevel 	uint32_t *addr;
    323  0  stevel 	struct lsa6_prefix *lpfx;
    324  0  stevel 	struct llsa *llsa;
    325  0  stevel 	char addrstr[INET6_ADDRSTRLEN];
    326  0  stevel 
    327  0  stevel 	interpret_ospf6_lsa_hdr(flags, &lsa->ls6_hdr);
    328  0  stevel 
    329  0  stevel 	ls_end = (uchar_t *)lsa + ntohs(lsa->ls6_hdr.ls6_length);
    330  0  stevel 
    331  0  stevel 	if (TRUNC(ls_end))
    332  0  stevel 		return (-1);
    333  0  stevel 
    334  0  stevel 	switch (ntohs(lsa->ls6_hdr.ls6_type)) {
    335  0  stevel 
    336  0  stevel 	case LS_TYPE_ROUTER|LS6_SCOPE_AREA:
    337  0  stevel 		if (TRUNC(&lsa->lsa_un.un_rla.rla6_flags))
    338  0  stevel 			return (-1);
    339  0  stevel 
    340  0  stevel 		(void) ospf_print_bits(ospf_rla_flag_bits,
    341  0  stevel 		    lsa->lsa_un.un_rla.rla6_flags);
    342  0  stevel 
    343  0  stevel 		if (TRUNC(&lsa->lsa_un.un_rla.rla6_options))
    344  0  stevel 			return (-1);
    345  0  stevel 		(void) ospf_print_bits(ospf_option_bits,
    346  0  stevel 		    ntohl(lsa->lsa_un.un_rla.rla6_options));
    347  0  stevel 
    348  0  stevel 		rl = lsa->lsa_un.un_rla.rla_link;
    349  0  stevel 		if (TRUNC(rl))
    350  0  stevel 			return (-1);
    351  0  stevel 
    352  0  stevel 		while (rl + sizeof (*rl) <= (struct rla6link *)ls_end) {
    353  0  stevel 			if (TRUNC((uchar_t *)rl + sizeof (*rl)))
    354  0  stevel 				return (-1);
    355  0  stevel 			if (flags & F_SUM) {
    356  0  stevel 				sprintf(sum_line, "{");		/* } (ctags) */
    357  0  stevel 				sum_line += strlen(sum_line);
    358  0  stevel 			}
    359  0  stevel 			switch (rl->link_type) {
    360  0  stevel 			case RLA_TYPE_VIRTUAL:
    361  0  stevel 				if (flags & F_SUM) {
    362  0  stevel 					sprintf(sum_line, "virt ");
    363  0  stevel 					sum_line += strlen(sum_line);
    364  0  stevel 				}
    365  0  stevel 				if (flags & F_DTAIL) {
    366  0  stevel 					(void) snprintf(get_line(0, 0),
    367  0  stevel 					    get_line_remain(), "Virtual Link");
    368  0  stevel 				}
    369  0  stevel 				/* FALLTHROUGH */
    370  0  stevel 			case RLA_TYPE_ROUTER:
    371  0  stevel 				if (flags & F_SUM) {
    372  0  stevel 					sprintf(sum_line, "nbrid %s",
    373  0  stevel 					    print_ipaddr(rl->link_nrtid));
    374  0  stevel 					sum_line += strlen(sum_line);
    375  0  stevel 					sprintf(sum_line, " nbrif %s",
    376  0  stevel 					    print_ipaddr(rl->link_nifid));
    377  0  stevel 					sum_line += strlen(sum_line);
    378  0  stevel 					sprintf(sum_line, " if %s",
    379  0  stevel 					    print_ipaddr(rl->link_ifid));
    380  0  stevel 					sum_line += strlen(sum_line);
    381  0  stevel 				}
    382  0  stevel 				if (flags & F_DTAIL) {
    383  0  stevel 					(void) snprintf(get_line(0, 0),
    384  0  stevel 					    get_line_remain(), "Neighbor = %s",
    385  0  stevel 					    print_ipaddr(rl->link_nrtid));
    386  0  stevel 					(void) snprintf(get_line(0, 0),
    387  0  stevel 					    get_line_remain(),
    388  0  stevel 					    "Interface = %s id %s",
    389  0  stevel 					    print_ipaddr(rl->link_nifid),
    390  0  stevel 					    print_ipaddr(rl->link_ifid));
    391  0  stevel 				}
    392  0  stevel 				break;
    393  0  stevel 			case RLA_TYPE_TRANSIT:
    394  0  stevel 				if (flags & F_SUM) {
    395  0  stevel 					sprintf(sum_line, "dr %s",
    396  0  stevel 					    print_ipaddr(rl->link_nrtid));
    397  0  stevel 					sum_line += strlen(sum_line);
    398  0  stevel 					sprintf(sum_line, " drif %s",
    399  0  stevel 					    print_ipaddr(rl->link_nifid));
    400  0  stevel 					sum_line += strlen(sum_line);
    401  0  stevel 					sprintf(sum_line, " if %s",
    402  0  stevel 					    print_ipaddr(rl->link_ifid));
    403  0  stevel 					sum_line += strlen(sum_line);
    404  0  stevel 				}
    405  0  stevel 				if (flags & F_DTAIL) {
    406  0  stevel 					(void) snprintf(get_line(0, 0),
    407  0  stevel 					    get_line_remain(),
    408  0  stevel 					    "Designated Router = %s",
    409  0  stevel 					    print_ipaddr(rl->link_nrtid));
    410  0  stevel 					(void) snprintf(get_line(0, 0),
    411  0  stevel 					    get_line_remain(),
    412  0  stevel 					    "DR Interface = %s id %s",
    413  0  stevel 					    print_ipaddr(rl->link_nifid),
    414  0  stevel 					    print_ipaddr(rl->link_ifid));
    415  0  stevel 				}
    416  0  stevel 				break;
    417  0  stevel 			default:
    418  0  stevel 				if (flags & F_SUM) {
    419  0  stevel 					sprintf(sum_line,
    420  0  stevel 					    "Unknown link type %d",
    421  0  stevel 					    rl->link_type);
    422  0  stevel 					sum_line += strlen(sum_line);
    423  0  stevel 				}
    424  0  stevel 				if (flags & F_DTAIL) {
    425  0  stevel 					(void) snprintf(get_line(0, 0),
    426  0  stevel 					    get_line_remain(),
    427  0  stevel 					    "Unknown link type %d",
    428  0  stevel 					    rl->link_type);
    429  0  stevel 				}
    430  0  stevel 
    431  0  stevel 			}
    432  0  stevel 			if (flags & F_SUM) {
    433  0  stevel 				sprintf(sum_line, " metric %d",
    434  0  stevel 				    ntohs(rl->link_metric));
    435  0  stevel 				sum_line += strlen(sum_line);
    436  0  stevel 			}
    437  0  stevel 			if (flags & F_DTAIL) {
    438  0  stevel 				(void) snprintf(get_line(0, 0),
    439  0  stevel 				    get_line_remain(), " metric = %d",
    440  0  stevel 				    ntohs(rl->link_metric));
    441  0  stevel 			}
    442  0  stevel 			if (flags & F_SUM) { 			/* { (ctags) */
    443  0  stevel 				sprintf(sum_line,  " }");
    444  0  stevel 				sum_line += strlen(sum_line);
    445  0  stevel 			}
    446  0  stevel 			rl++;
    447  0  stevel 			if ((uchar_t *)rl > fragend)
    448  0  stevel 				return (-1); /* truncated */
    449  0  stevel 		}
    450  0  stevel 		break;
    451  0  stevel 	case LS_TYPE_NETWORK | LS6_SCOPE_AREA:
    452  0  stevel 
    453  0  stevel 		if (TRUNC(&lsa->lsa_un.un_nla.nla_options))
    454  0  stevel 			return (-1);
    455  0  stevel 
    456  0  stevel 		(void) ospf_print_bits(ospf6_option_bits,
    457  0  stevel 		    ntohl(lsa->lsa_un.un_nla.nla_options));
    458  0  stevel 
    459  0  stevel 		if (flags & F_SUM) {
    460  0  stevel 			sprintf(sum_line, " rtrs");
    461  0  stevel 			sum_line += strlen(sum_line);
    462  0  stevel 		}
    463  0  stevel 		if (flags & F_DTAIL) {
    464  0  stevel 			snprintf(get_line(0, 0), get_line_remain(),
    465  0  stevel 			    "Routers:");
    466  0  stevel 		}
    467  0  stevel 		addr = lsa->lsa_un.un_nla.nla_router;
    468  0  stevel 		while ((uchar_t *)addr < ls_end) {
    469  0  stevel 			if ((uchar_t *)addr + sizeof (struct in_addr) > ls_end)
    470  0  stevel 				return (-1); /* truncated */
    471  0  stevel 			if (flags & F_SUM) {
    472  0  stevel 				sprintf(sum_line, " %s", print_ipaddr(*addr));
    473  0  stevel 				sum_line += strlen(sum_line);
    474  0  stevel 			}
    475  0  stevel 			if (flags & F_DTAIL) {
    476  0  stevel 				snprintf(get_line(0, 0), get_line_remain(),
    477  0  stevel 				    "\t%s", print_ipaddr(*addr));
    478  0  stevel 			}
    479  0  stevel 			++addr;
    480  0  stevel 		}
    481  0  stevel 		break;
    482  0  stevel 	case LS_TYPE_INTER_AP | LS6_SCOPE_AREA:
    483  0  stevel 
    484  0  stevel 		if (TRUNC(&lsa->lsa_un.un_inter_ap.inter_ap_metric))
    485  0  stevel 			return (-1);
    486  0  stevel 
    487  0  stevel 		if (flags & F_SUM) {
    488  0  stevel 			sprintf(sum_line, " metric %s",
    489  0  stevel 			    ntohl(lsa->lsa_un.un_inter_ap.inter_ap_metric) &
    490  0  stevel 			    SLA_MASK_METRIC);
    491  0  stevel 			sum_line += strlen(sum_line);
    492  0  stevel 		}
    493  0  stevel 		if (flags & F_DTAIL) {
    494  0  stevel 			snprintf(get_line(0, 0), get_line_remain(),
    495  0  stevel 			    "Metric = %s",
    496  0  stevel 			    ntohl(lsa->lsa_un.un_inter_ap.inter_ap_metric) &
    497  0  stevel 			    SLA_MASK_METRIC);
    498  0  stevel 		}
    499  0  stevel 		lpfx = lsa->lsa_un.un_inter_ap.inter_ap_prefix;
    500  0  stevel 		if (lpfx > (struct lsa6_prefix *)ls_end)
    501  0  stevel 			return (-1);
    502  0  stevel 		while (lpfx + sizeof (*lpfx) <= (struct lsa6_prefix *)ls_end) {
    503  0  stevel 			k = ospf6_print_lsaprefix(flags, lpfx);
    504  0  stevel 			lpfx = (struct lsa6_prefix *)(((uchar_t *)lpfx) + k);
    505  0  stevel 			if (lpfx > (struct lsa6_prefix *)ls_end)
    506  0  stevel 				return (-1);
    507  0  stevel 		}
    508  0  stevel 		break;
    509  0  stevel 	case LS_TYPE_LINK:
    510  0  stevel 		llsa = &lsa->lsa_un.un_llsa;
    511  0  stevel 		if (TRUNC(llsa->llsa_options))
    512  0  stevel 			return (-1);
    513  0  stevel 		ospf_print_bits(ospf6_option_bits, ntohl(llsa->llsa_options));
    514  0  stevel 		if (TRUNC(llsa->llsa_nprefix))
    515  0  stevel 			return (-1);
    516  0  stevel 		(void) inet_ntop(AF_INET6, &llsa->llsa_lladdr,
    517  0  stevel 		    addrstr, INET6_ADDRSTRLEN);
    518  0  stevel 		if (flags & F_SUM)  {
    519  0  stevel 			sprintf(sum_line, " pri %d lladdr %s npref %d",
    520  0  stevel 			    ntohl(llsa->llsa_priority), addrstr,
    521  0  stevel 			    ntohl(llsa->llsa_nprefix));
    522  0  stevel 			sum_line += strlen(sum_line);
    523  0  stevel 		}
    524  0  stevel 		if (flags & F_DTAIL)  {
    525  0  stevel 			snprintf(get_line(0, 0), get_line_remain(),
    526  0  stevel 			    "Priority %d", ntohl(llsa->llsa_priority));
    527  0  stevel 			snprintf(get_line(0, 0), get_line_remain(),
    528  0  stevel 			    "Link Local addr %d", addrstr);
    529  0  stevel 			snprintf(get_line(0, 0), get_line_remain(),
    530  0  stevel 			    "npref %d", ntohl(llsa->llsa_nprefix));
    531  0  stevel 		}
    532  0  stevel 		lpfx = llsa->llsa_prefix;
    533  0  stevel 		for (j = 0; j < ntohl(llsa->llsa_nprefix); j++) {
    534  0  stevel 			if (TRUNC(lpfx))
    535  0  stevel 				return (-1);
    536  0  stevel 			k = ospf6_print_lsaprefix(flags, lpfx);
    537  0  stevel 			lpfx = (struct lsa6_prefix *)(((uchar_t *)lpfx) + k);
    538  0  stevel 		}
    539  0  stevel 		break;
    540  0  stevel 
    541  0  stevel 	case LS_TYPE_INTRA_AP | LS6_SCOPE_AREA:
    542  0  stevel 		if (TRUNC(&lsa->lsa_un.un_intra_ap.intra_ap_rtid))
    543  0  stevel 			return (-1);
    544  0  stevel 		ospf6_print_ls_type(flags,
    545  0  stevel 		    ntohs(lsa->lsa_un.un_intra_ap.intra_ap_lstype),
    546  0  stevel 		    lsa->lsa_un.un_intra_ap.intra_ap_lsid,
    547  0  stevel 		    lsa->lsa_un.un_intra_ap.intra_ap_rtid);
    548  0  stevel 		if (TRUNC(&lsa->lsa_un.un_intra_ap.intra_ap_nprefix))
    549  0  stevel 			return (-1);
    550  0  stevel 		if (flags & F_SUM) {
    551  0  stevel 			sprintf(sum_line, " npref %d",
    552  0  stevel 			    ntohs(lsa->lsa_un.un_intra_ap.intra_ap_nprefix));
    553  0  stevel 			sum_line += strlen(sum_line);
    554  0  stevel 		}
    555  0  stevel 		if (flags & F_DTAIL) {
    556  0  stevel 			snprintf(get_line(0, 0), get_line_remain(), "NPref %d",
    557  0  stevel 			    ntohs(lsa->lsa_un.un_intra_ap.intra_ap_nprefix));
    558  0  stevel 		}
    559  0  stevel 
    560  0  stevel 		lpfx = lsa->lsa_un.un_intra_ap.intra_ap_prefix;
    561  0  stevel 		for (j = 0;
    562  0  stevel 		    j < ntohs(lsa->lsa_un.un_intra_ap.intra_ap_nprefix); j++) {
    563  0  stevel 			if (TRUNC(lpfx))
    564  0  stevel 				return (-1);
    565  0  stevel 			k = ospf6_print_lsaprefix(flags, lpfx);
    566  0  stevel 			lpfx = (struct lsa6_prefix *)(((uchar_t *)lpfx) + k);
    567  0  stevel 		}
    568  0  stevel 		break;
    569  0  stevel 
    570  0  stevel 	default:
    571  0  stevel 		if (flags & F_SUM)  {
    572  0  stevel 			sprintf(sum_line, " Unknown LSA type (%d)",
    573  0  stevel 			    lsa->ls6_hdr.ls6_type);
    574  0  stevel 			sum_line += strlen(sum_line);
    575  0  stevel 		}
    576  0  stevel 		if (flags & F_DTAIL)  {
    577  0  stevel 			snprintf(get_line(0, 0), get_line_remain(),
    578  0  stevel 			    " Unknown LSA type %d", lsa->ls6_hdr.ls6_type);
    579  0  stevel 
    580  0  stevel 		}
    581  0  stevel 		break;
    582  0  stevel 	}
    583  0  stevel 	return (0);
    584  0  stevel }
    585  0  stevel #undef TRUNC
    586  0  stevel int
    587  0  stevel interpret_ospf6(int flags, struct ospf6hdr *ospf, int iplen, int fraglen)
    588  0  stevel {
    589  0  stevel 	boolean_t trunc = B_FALSE;
    590  0  stevel 	struct lsa6_hdr *lsah;
    591  0  stevel 	struct lsr6 *lsr;
    592  0  stevel 	struct lsa6 *lsa;
    593  0  stevel 	int nlsa, nlsah;
    594  0  stevel 
    595  0  stevel 	if ((fraglen < OSPF6_MIN_HEADER_SIZE) ||
    596  0  stevel 	    (fraglen < ntohs(ospf->ospf6_len)))
    597  0  stevel 		return (fraglen);	/* incomplete header */
    598  0  stevel 
    599  0  stevel 	if (ospf->ospf6_version != 3) {
    600  0  stevel 		if (ospf->ospf6_version == 2) {
    601  0  stevel 			if (flags & F_DTAIL)
    602  0  stevel 				snprintf(get_line(0, 0), get_line_remain(),
    603  0  stevel 				    "ospfv2 packet in ipv6 header");
    604  0  stevel 			return (interpret_ospf(flags, ospf, iplen, fraglen));
    605  0  stevel 		} else  {
    606  0  stevel 			return (fraglen);
    607  0  stevel 		}
    608  0  stevel 	}
    609  0  stevel 
    610  0  stevel 	if (fraglen > ntohs(ospf->ospf6_len))
    611  0  stevel 		fraglen = ntohs(ospf->ospf6_len);
    612  0  stevel 
    613  0  stevel 	if (ospf->ospf6_type > OSPF_TYPE_MAX) {
    614  0  stevel 		if (flags & F_SUM) {
    615  0  stevel 			(void) sprintf(sum_line, "Unknown OSPF TYPE %d \n",
    616  0  stevel 			    ospf->ospf6_type);
    617  0  stevel 			sum_line += strlen(sum_line);
    618  0  stevel 		}
    619  0  stevel 		if (flags & F_SUM) {
    620  0  stevel 			show_header("OSPFv3:  ", "OSPFv3 Header", fraglen);
    621  0  stevel 			show_space();
    622  0  stevel 			(void) snprintf(get_line(0, 0), get_line_remain(),
    623  0  stevel 			    "Unknown OSPF Type = %d", ospf->ospf6_type);
    624  0  stevel 		}
    625  0  stevel 		return (fraglen);
    626  0  stevel 	}
    627  0  stevel 
    628  0  stevel 	if (flags & F_SUM) {
    629  0  stevel 		sum_line = (char *)get_sum_line();
    630  0  stevel 		(void) sprintf(sum_line, "OSPFv3 %s RTRID=%s ",
    631  0  stevel 		    ospf_types[ospf->ospf6_type],
    632  0  stevel 		    print_ipaddr(ospf->ospf6_routerid));
    633  0  stevel 		sum_line += strlen(sum_line);
    634  0  stevel 		(void) sprintf(sum_line, "AREA=%s LEN=%d instance %u ",
    635  0  stevel 		    print_ipaddr(ospf->ospf6_areaid),
    636  0  stevel 		    ntohs((ushort_t)ospf->ospf6_len), ospf->ospf6_instanceid);
    637  0  stevel 		sum_line += strlen(sum_line);
    638  0  stevel 	}
    639  0  stevel 
    640  0  stevel 	if (flags & F_DTAIL) {
    641  0  stevel 		show_header("OSPFv3:  ", "OSPF Header", fraglen);
    642  0  stevel 		show_space();
    643  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    644  0  stevel 		    "Version = %d", ospf->ospf6_version);
    645  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    646  0  stevel 		    "Type = %s", ospf_types[ospf->ospf6_type]);
    647  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    648  0  stevel 		    "Router ID = %s", print_ipaddr(ospf->ospf6_routerid));
    649  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    650  0  stevel 		    "Area ID = %s", print_ipaddr(ospf->ospf6_areaid));
    651  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    652  0  stevel 		    "Checksum = 0x%x", ospf->ospf6_chksum);
    653  0  stevel 		(void) snprintf(get_line(0, 0), get_line_remain(),
    654  0  stevel 		    "Instance = %u", ospf->ospf6_instanceid);
    655  0  stevel 	}
    656  0  stevel 
    657  0  stevel 	switch (ospf->ospf6_type) {
    658  0  stevel 	case OSPF_TYPE_HELLO:
    659  0  stevel 		if (interpret_ospf6_hello(flags, ospf, fraglen) < 0)
    660  0  stevel 			trunc = B_TRUE;
    661  0  stevel 		break;
    662  0  stevel 
    663  0  stevel 	case OSPF_TYPE_DB:
    664  0  stevel 		if (fraglen < OSPF6_MIN_HEADER_SIZE +
    665  0  stevel 		    OSPF6_MIN_DB_HEADER_SIZE) {
    666  0  stevel 			trunc = B_TRUE;
    667  0  stevel 			break;
    668  0  stevel 		}
    669  0  stevel 		if (flags & F_SUM) {
    670  0  stevel 			sprintf(sum_line, " %s %s mtu %u S %X", ospf_print_bits(
    671  0  stevel 			    ospf6_option_bits,
    672  0  stevel 			    ntohl(ospf->ospf6_db.db_options)),
    673  0  stevel 			    ospf_print_bits(ospf_db_flags_bits,
    674  0  stevel 			    ospf->ospf6_db.db_flags),
    675  0  stevel 			    ntohs(ospf->ospf6_db.db_mtu),
    676  0  stevel 			    ntohl(ospf->ospf6_db.db_seq));
    677  0  stevel 			sum_line += strlen(sum_line);
    678  0  stevel 		}
    679  0  stevel 		if (flags & F_DTAIL) {
    680  0  stevel 			show_header("OSPF DB:  ", "Database Description Packet",
    681  0  stevel 			    fraglen);
    682  0  stevel 			show_space();
    683  0  stevel 			snprintf(get_line(0, 0), get_line_remain(),
    684  0  stevel 			    "Options = %s", ospf_print_bits(
    685  0  stevel 			    ospf6_option_bits, ospf->ospf6_db.db_options));
    686  0  stevel 			snprintf(get_line(0, 0), get_line_remain(),
    687  0  stevel 			    "Flags = %s", ospf_print_bits(
    688  0  stevel 			    ospf_db_flags_bits, ospf->ospf6_db.db_flags));
    689  0  stevel 			snprintf(get_line(0, 0), get_line_remain(),
    690  0  stevel 			    "MTU = %u", ntohl(ospf->ospf6_db.db_seq));
    691  0  stevel 			snprintf(get_line(0, 0), get_line_remain(),
    692  0  stevel 			    "Sequence = 0x%X", ntohl(ospf->ospf6_db.db_seq));
    693  0  stevel 			/*  Print all the LS advs */
    694  0  stevel 			lsah = ospf->ospf6_db.db_lshdr;
    695  0  stevel 			while ((uchar_t *)lsah < ((uchar_t *)ospf + fraglen)) {
    696  0  stevel 				if ((uchar_t *)lsah + sizeof (struct lsa6_hdr) >
    697  0  stevel 				    ((uchar_t *)ospf + fraglen)) {
    698  0  stevel 					trunc = B_TRUE;
    699  0  stevel 					break;
    700  0  stevel 				}
    701  0  stevel 				interpret_ospf6_lsa_hdr(flags, lsah);
    702  0  stevel 				++lsah;
    703  0  stevel 			}
    704  0  stevel 		}
    705  0  stevel 		break;
    706  0  stevel 
    707  0  stevel 	case OSPF_TYPE_LSR:
    708  0  stevel 		if (fraglen < OSPF6_MIN_HEADER_SIZE +
    709  0  stevel 		    OSPF_MIN_LSR_HEADER_SIZE) {
    710  0  stevel 			trunc = B_TRUE;
    711  0  stevel 			break;
    712  0  stevel 		}
    713  0  stevel 		if (flags & F_DTAIL) {
    714  0  stevel 			show_header("OSPF LSR:  ", "Link State Request Packet",
    715  0  stevel 			    fraglen);
    716  0  stevel 			show_space();
    717  0  stevel 		}
    718  0  stevel 		lsr = ospf->ospf6_lsr;
    719  0  stevel 		nlsah = 0;
    720  0  stevel 		while ((uchar_t *)lsr < ((uchar_t *)ospf + fraglen)) {
    721  0  stevel 			if ((uchar_t *)lsr + sizeof (struct lsr6) >
    722  0  stevel 			    ((uchar_t *)ospf + fraglen)) {
    723  0  stevel 				trunc = B_TRUE;
    724  0  stevel 				break;
    725  0  stevel 			}
    726  0  stevel 			nlsah++;
    727  0  stevel 			if (flags & F_DTAIL) {
    728  0  stevel 				ospf6_print_ls_type(flags, ntohl(lsr->ls_type),
    729  0  stevel 				    lsr->ls_stateid, lsr->ls_router);
    730  0  stevel 			}
    731  0  stevel 			++lsr;
    732  0  stevel 		}
    733  0  stevel 		if (flags & F_SUM) {
    734  0  stevel 			sprintf(sum_line, "%d LSAs", nlsah);
    735  0  stevel 			sum_line += strlen(sum_line);
    736  0  stevel 		}
    737  0  stevel 		break;
    738  0  stevel 
    739  0  stevel 	case OSPF_TYPE_LSU:
    740  0  stevel 		if (fraglen < OSPF6_MIN_HEADER_SIZE +
    741  0  stevel 		    OSPF_MIN_LSU_HEADER_SIZE) {
    742  0  stevel 			trunc = B_TRUE;
    743  0  stevel 			break;
    744  0  stevel 		}
    745  0  stevel 		if (flags & F_DTAIL) {
    746  0  stevel 			show_header("OSPF LSU:  ", "Link State Update Packet",
    747  0  stevel 			    fraglen);
    748  0  stevel 			show_space();
    749  0  stevel 		}
    750  0  stevel 		lsa = ospf->ospf6_lsu.lsu_lsa;
    751  0  stevel 		nlsa = ntohl(ospf->ospf6_lsu.lsu_count);
    752  0  stevel 		if (flags & F_SUM) {
    753  0  stevel 			sprintf(sum_line, "%d LSAs", nlsa);
    754  0  stevel 			sum_line += strlen(sum_line);
    755  0  stevel 			break;
    756  0  stevel 		}
    757  0  stevel 		while (nlsa-- != 0) {
    758  0  stevel 			uchar_t *fragend = (uchar_t *)ospf + fraglen;
    759  0  stevel 			if (((uchar_t *)lsa >= fragend) ||
    760  0  stevel 			    ((uchar_t *)lsa + sizeof (struct lsa_hdr) >
    761  0  stevel 			    fragend) ||
    762  0  stevel 			    ((uchar_t *)lsa + ntohs(lsa->ls6_hdr.ls6_length) >
    763  0  stevel 			    fragend)) {
    764  0  stevel 				trunc = B_TRUE;
    765  0  stevel 				break;
    766  0  stevel 			}
    767  0  stevel 
    768  0  stevel 			if (interpret_ospf6_lsa(flags, lsa, fragend) < 0) {
    769  0  stevel 				trunc = B_TRUE;
    770  0  stevel 				break;
    771  0  stevel 			}
    772  0  stevel 			lsa = (struct lsa6 *)((uchar_t *)lsa +
    773  0  stevel 			    ntohs(lsa->ls6_hdr.ls6_length));
    774  0  stevel 		}
    775  0  stevel 		break;
    776  0  stevel 
    777  0  stevel 	case OSPF_TYPE_LSA:
    778  0  stevel 		if (flags & F_DTAIL) {
    779  0  stevel 			show_header("OSPF LSA:  ", "Link State Ack Packet",
    780  0  stevel 			    fraglen);
    781  0  stevel 			show_space();
    782  0  stevel 		}
    783  0  stevel 		lsah = ospf->ospf6_lsa.lsa_lshdr;
    784  0  stevel 		nlsah = 0;
    785  0  stevel 		while ((uchar_t *)lsah < ((uchar_t *)ospf + fraglen)) {
    786  0  stevel 			if ((uchar_t *)lsah + sizeof (struct lsa6_hdr) >
    787  0  stevel 			    ((uchar_t *)ospf + fraglen)) {
    788  0  stevel 				trunc = B_TRUE;
    789  0  stevel 				break;
    790  0  stevel 			}
    791  0  stevel 			nlsah++;
    792  0  stevel 			if (flags & F_DTAIL)
    793  0  stevel 				interpret_ospf6_lsa_hdr(flags, lsah);
    794  0  stevel 			++lsah;
    795  0  stevel 		}
    796  0  stevel 		if (flags & F_SUM) {
    797  0  stevel 			sprintf(sum_line, "%d LSAs", nlsah);
    798  0  stevel 			sum_line += strlen(sum_line);
    799  0  stevel 		}
    800  0  stevel 		break;
    801  0  stevel 
    802  0  stevel 	default:
    803  0  stevel 		/* NOTREACHED */
    804  0  stevel 		break;
    805  0  stevel 	}
    806  0  stevel 	if (trunc) {
    807  0  stevel 		if (flags & F_SUM)
    808  0  stevel 			sprintf(sum_line, "--truncated");
    809  0  stevel 		if (flags & F_DTAIL)
    810  0  stevel 			snprintf(get_line(0, 0), get_line_remain(),
    811  0  stevel 			    "--truncated");
    812  0  stevel 	}
    813  0  stevel 
    814  0  stevel 	return (fraglen);
    815  0  stevel }
    816