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