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 
     51 char *ospf_types[] = {
     52 	"umd", 		/* 0 */
     53 	"Hello",	/* 1 */
     54 	"DD",		/* 2 */
     55 	"LSReq",	/* 3 */
     56 	"LSUpd",	/* 4 */
     57 	"LSAck",	/* 5 */
     58 };
     59 
     60 static char *ospf_authtypes[] = {
     61 	"None", 	/* 0 */
     62 	"simple",	/* 1 */
     63 	"md5",		/* 2 */
     64 };
     65 
     66 const struct bits ospf_rla_flag_bits[] = {
     67 	{ RLA_FLAG_B,		"B" },
     68 	{ RLA_FLAG_E,		"E" },
     69 	{ RLA_FLAG_V,		"V" },
     70 	{ RLA_FLAG_W,		"W" },
     71 	{ 0, 			NULL }
     72 };
     73 
     74 const struct bits ospf_db_flags_bits[] = {
     75 	{ OSPF_DB_INIT,		"I" },
     76 	{ OSPF_DB_MORE,		"M" },
     77 	{ OSPF_DB_MASTER,	"MS" },
     78 	{ 0, 			NULL }
     79 };
     80 
     81 const struct bits ospf_option_bits[] = {
     82 	{ OSPF_OPTION_T,	"T" },
     83 	{ OSPF_OPTION_E,	"E" },
     84 	{ OSPF_OPTION_MC,	"MC" },
     85 	{ 0,			NULL }
     86 };
     87 
     88 static int interpret_ospf_hello(int, struct ospfhdr *, int);
     89 static void ospf_print_ls_type(int, uint32_t, struct in_addr, struct in_addr);
     90 static void interpret_ospf_lsa_hdr(int, struct lsa_hdr *);
     91 static int interpret_ospf_lsa(int flags, struct lsa *lsa, uchar_t *);
     92 
     93 char *
     94 ospf_print_bits(const struct bits *bp, uchar_t options)
     95 {
     96 	static char bitstring[32];
     97 
     98 	bitstring[0] = '\0';
     99 	do {
    100 		if (options & bp->bit) {
    101 			strcat(bitstring, bp->str);
    102 			strcat(bitstring, "/");
    103 		}
    104 	} while ((++bp)->bit);
    105 
    106 	/* wipe out the trailing "/" */
    107 	bitstring[strlen(bitstring) - 1] = '\0';
    108 	return (bitstring);
    109 }
    110 
    111 char *
    112 ospf_print_lsa_age(long age)
    113 {
    114 	long sec, mins, hour;
    115 	static char lsa_age[16];
    116 
    117 	sec = age % 60;
    118 	mins = (age / 60) % 60;
    119 	hour = age / 3600;
    120 	if (hour != 0)
    121 		snprintf(lsa_age, sizeof (lsa_age), "%u:%02u:%02u",
    122 		    hour, mins, sec);
    123 	else if (mins != 0)
    124 		snprintf(lsa_age, sizeof (lsa_age), "%u:%02u", mins, sec);
    125 	else
    126 		snprintf(lsa_age, sizeof (lsa_age), "%u", sec);
    127 	return (lsa_age);
    128 }
    129 
    130 static int
    131 interpret_ospf_hello(int flags, struct ospfhdr *op, int fraglen)
    132 {
    133 	struct in_addr *nbr;
    134 	int j;
    135 
    136 	if (fraglen < OSPF_MIN_HEADER_SIZE + OSPF_MIN_HELLO_HEADER_SIZE)
    137 		return (-1); /* truncated packet */
    138 
    139 	if (flags & F_SUM) {
    140 		if (op->ospf_hello.hello_dr.s_addr != 0) {
    141 			(void) sprintf(sum_line, "DR=%s ",
    142 			    inet_ntoa(op->ospf_hello.hello_dr));
    143 		}
    144 		sum_line += strlen(sum_line);
    145 		if (op->ospf_hello.hello_bdr.s_addr != 0) {
    146 			(void) sprintf(sum_line, "BDR=%s ",
    147 			    inet_ntoa(op->ospf_hello.hello_bdr));
    148 		}
    149 		sum_line += strlen(sum_line);
    150 		nbr = op->ospf_hello.hello_neighbor;
    151 		j = 0;
    152 		while ((uchar_t *)nbr < ((uchar_t *)op + fraglen)) {
    153 			if ((uchar_t *)nbr + sizeof (struct in_addr) >
    154 			    ((uchar_t *)op + fraglen))
    155 				return (-1); /* truncated */
    156 			j++;
    157 			++nbr;
    158 		}
    159 		(void) sprintf(sum_line, "%d nbrs", j);
    160 		sum_line += strlen(sum_line);
    161 
    162 	}
    163 	if (flags & F_DTAIL) {
    164 		show_header("OSPF HELLO:  ", "Hello Packet",
    165 		    ntohs(op->ospf_len));
    166 		show_space();
    167 		(void) snprintf(get_line(0, 0), get_line_remain(),
    168 		    "Options = %s", ospf_print_bits(ospf_option_bits,
    169 		    op->ospf_hello.hello_options));
    170 		(void) snprintf(get_line(0, 0), get_line_remain(), "Mask = %s",
    171 		    inet_ntoa(op->ospf_hello.hello_mask));
    172 		(void) snprintf(get_line(0, 0), get_line_remain(),
    173 		    "Hello interval = %d",
    174 		    ntohs(op->ospf_hello.hello_helloint));
    175 		(void) snprintf(get_line(0, 0), get_line_remain(),
    176 		    "Priority = %d", op->ospf_hello.hello_priority);
    177 		(void) snprintf(get_line(0, 0), get_line_remain(),
    178 		    "Dead interval = %u", ntohl(op->ospf_hello.hello_deadint));
    179 		if (op->ospf_hello.hello_dr.s_addr != 0) {
    180 			(void) snprintf(get_line(0, 0), get_line_remain(),
    181 			    "Designated Router = %s",
    182 			    inet_ntoa(op->ospf_hello.hello_dr));
    183 		}
    184 		if (op->ospf_hello.hello_bdr.s_addr != 0) {
    185 			(void) snprintf(get_line(0, 0), get_line_remain(),
    186 			    "Backup Designated Router = %s",
    187 			    inet_ntoa(op->ospf_hello.hello_bdr));
    188 		}
    189 		nbr = op->ospf_hello.hello_neighbor;
    190 		while ((uchar_t *)nbr < ((uchar_t *)op + fraglen)) {
    191 			if ((uchar_t *)nbr + sizeof (struct in_addr) >
    192 			    ((uchar_t *)op + fraglen))
    193 				return (-1); /* truncated */
    194 			(void) snprintf(get_line(0, 0), get_line_remain(),
    195 			    "Neighbor: %s", inet_ntoa(*nbr));
    196 			++nbr;
    197 		}
    198 	}
    199 	return (fraglen);
    200 }
    201 
    202 static void
    203 ospf_print_ls_type(int flags, uint32_t ls_type, struct in_addr ls_stateid,
    204     struct in_addr ls_router)
    205 {
    206 	switch (ls_type) {
    207 	case LS_TYPE_ROUTER:
    208 		if (flags & F_SUM) {
    209 			sprintf(sum_line, " rtr %s ", inet_ntoa(ls_router));
    210 			sum_line += strlen(sum_line);
    211 		}
    212 		if (flags & F_DTAIL) {
    213 			(void) snprintf(get_line(0, 0), get_line_remain(),
    214 			    "Router LSA; Router = %s ", inet_ntoa(ls_router));
    215 		}
    216 		break;
    217 	case LS_TYPE_NETWORK:
    218 		if (flags & F_SUM) {
    219 			sprintf(sum_line, " net dr %s ", inet_ntoa(ls_router));
    220 			sum_line += strlen(sum_line);
    221 			sprintf(sum_line, "if %s ", inet_ntoa(ls_stateid));
    222 			sum_line += strlen(sum_line);
    223 		}
    224 		if (flags & F_DTAIL) {
    225 			(void) snprintf(get_line(0, 0), get_line_remain(),
    226 			    "Network LSA Router = %s ", inet_ntoa(ls_router));
    227 			(void) snprintf(get_line(0, 0), get_line_remain(),
    228 			    "            Interface = %s ",
    229 			    inet_ntoa(ls_stateid));
    230 		}
    231 		break;
    232 	case LS_TYPE_SUM_IP:
    233 		if (flags & F_SUM) {
    234 			sprintf(sum_line, " sum %s ", inet_ntoa(ls_stateid));
    235 			sum_line += strlen(sum_line);
    236 			sprintf(sum_line, "abr %s ", inet_ntoa(ls_router));
    237 			sum_line += strlen(sum_line);
    238 		}
    239 		if (flags & F_DTAIL) {
    240 			(void) snprintf(get_line(0, 0), get_line_remain(),
    241 			    "Summary LSA IP = %s ", inet_ntoa(ls_stateid));
    242 			(void) snprintf(get_line(0, 0), get_line_remain(),
    243 			    "            Area Border Router = %s ",
    244 			    inet_ntoa(ls_router));
    245 		}
    246 		break;
    247 	case LS_TYPE_SUM_ABR:
    248 		if (flags & F_SUM) {
    249 			sprintf(sum_line, "abr %s ", inet_ntoa(ls_stateid));
    250 			sum_line += strlen(sum_line);
    251 			sprintf(sum_line, "asbr %s ", inet_ntoa(ls_router));
    252 			sum_line += strlen(sum_line);
    253 		}
    254 		if (flags & F_DTAIL) {
    255 			(void) snprintf(get_line(0, 0), get_line_remain(),
    256 			    "ASBR Summary abr = %s ", inet_ntoa(ls_stateid));
    257 			(void) snprintf(get_line(0, 0), get_line_remain(),
    258 			    "             asbr = %s ", inet_ntoa(ls_router));
    259 		}
    260 		break;
    261 	case LS_TYPE_ASE:
    262 		if (flags & F_SUM) {
    263 			sprintf(sum_line, " ase %s", inet_ntoa(ls_stateid));
    264 			sum_line += strlen(sum_line);
    265 			sprintf(sum_line, " asbr %s", inet_ntoa(ls_router));
    266 			sum_line += strlen(sum_line);
    267 		}
    268 		if (flags & F_DTAIL) {
    269 			(void) snprintf(get_line(0, 0), get_line_remain(),
    270 			    "AS External LSA ase = %s ", inet_ntoa(ls_stateid));
    271 			(void) snprintf(get_line(0, 0), get_line_remain(),
    272 			    "                asbr = %s ", inet_ntoa(ls_router));
    273 		}
    274 
    275 		break;
    276 	case LS_TYPE_GROUP:
    277 		if (flags & F_SUM) {
    278 			sprintf(sum_line, " group %s", inet_ntoa(ls_stateid));
    279 			sum_line += strlen(sum_line);
    280 			sprintf(sum_line, " rtr %s", inet_ntoa(ls_router));
    281 			sum_line += strlen(sum_line);
    282 		}
    283 		if (flags & F_DTAIL) {
    284 			(void) snprintf(get_line(0, 0), get_line_remain(),
    285 			    "Group LSA %s ", inet_ntoa(ls_stateid));
    286 			(void) snprintf(get_line(0, 0), get_line_remain(),
    287 			    "          rtr = %s ", inet_ntoa(ls_router));
    288 		}
    289 		break;
    290 	default:
    291 		if (flags & F_SUM) {
    292 			sprintf(sum_line, " unknown LSA type %d", ls_type);
    293 			sum_line += strlen(sum_line);
    294 		}
    295 		if (flags & F_DTAIL) {
    296 			(void) snprintf(get_line(0, 0), get_line_remain(),
    297 			    "Unknown LSA type %d", ls_type);
    298 		}
    299 		break;
    300 	}
    301 }
    302 
    303 static void
    304 interpret_ospf_lsa_hdr(int flags, struct lsa_hdr *lsah)
    305 {
    306 	if (flags & F_SUM)
    307 		return;
    308 
    309 	if (flags & F_DTAIL) {
    310 		(void) snprintf(get_line(0, 0), get_line_remain(),
    311 		    "Options = %s",
    312 		    ospf_print_bits(ospf_option_bits, lsah->ls_options));
    313 		(void) snprintf(get_line(0, 0), get_line_remain(),
    314 		    "Sequence = %X ", ntohl(lsah->ls_seq));
    315 		(void) snprintf(get_line(0, 0), get_line_remain(),
    316 		    "Age = %X ", ospf_print_lsa_age(ntohs(lsah->ls_age)));
    317 	}
    318 
    319 	ospf_print_ls_type(flags, lsah->ls_type, lsah->ls_stateid,
    320 	    lsah->ls_router);
    321 
    322 }
    323 
    324 #define	TRUNC(addr)	((uchar_t *)(addr) > fragend)
    325 static int
    326 interpret_ospf_lsa(int flags, struct lsa *lsa, uchar_t *fragend)
    327 {
    328 	uchar_t *ls_end;
    329 	int rla_count, k;
    330 	struct rlalink *rl;
    331 	struct tos_metric *tosp;
    332 	struct in_addr *addr;
    333 	uint32_t *tosmetric;
    334 	struct aslametric *am;
    335 	uint32_t tm;
    336 	int tos, metric;
    337 
    338 	interpret_ospf_lsa_hdr(flags, &lsa->ls_hdr);
    339 
    340 	ls_end = (uchar_t *)lsa + ntohs(lsa->ls_hdr.ls_length);
    341 
    342 	if (TRUNC(ls_end))
    343 		return (-1);
    344 
    345 	switch (lsa->ls_hdr.ls_type) {
    346 
    347 	case LS_TYPE_ROUTER:
    348 		if (TRUNC(&lsa->lsa_un.un_rla.rla_flags))
    349 			return (-1);
    350 
    351 		if (flags & F_DTAIL) {
    352 			(void) ospf_print_bits(ospf_rla_flag_bits,
    353 			    lsa->lsa_un.un_rla.rla_flags);
    354 		}
    355 
    356 		if (TRUNC(&lsa->lsa_un.un_rla.rla_count))
    357 			return (-1);
    358 		rla_count = ntohs(lsa->lsa_un.un_rla.rla_count);
    359 
    360 		rl = lsa->lsa_un.un_rla.rla_link;
    361 		if (TRUNC(rl))
    362 			return (-1);
    363 
    364 		while (rla_count-- != 0) {
    365 			if (TRUNC((uchar_t *)rl + sizeof (*rl)))
    366 				return (-1);
    367 			switch (rl->link_type) {
    368 			case RLA_TYPE_VIRTUAL:
    369 				if (flags & F_DTAIL) {
    370 					(void) snprintf(get_line(0, 0),
    371 					    get_line_remain(), "Virtual Link");
    372 				}
    373 				/* fall through */
    374 			case RLA_TYPE_ROUTER:
    375 				if (flags & F_DTAIL) {
    376 					(void) snprintf(get_line(0, 0),
    377 					    get_line_remain(), "Neighbor = %s",
    378 					    inet_ntoa(rl->link_id));
    379 					(void) snprintf(get_line(0, 0),
    380 					    get_line_remain(), "Interface = %s",
    381 					    inet_ntoa(rl->link_data));
    382 				}
    383 				break;
    384 			case RLA_TYPE_TRANSIT:
    385 				if (flags & F_DTAIL) {
    386 					(void) snprintf(get_line(0, 0),
    387 					    get_line_remain(),
    388 					    "Designated Router = %s",
    389 					    inet_ntoa(rl->link_id));
    390 					(void) snprintf(get_line(0, 0),
    391 					    get_line_remain(), "Interface = %s",
    392 					    inet_ntoa(rl->link_data));
    393 				}
    394 				break;
    395 			case RLA_TYPE_STUB:
    396 				if (flags & F_DTAIL) {
    397 					(void) snprintf(get_line(0, 0),
    398 					    get_line_remain(), "Network = %s",
    399 					    inet_ntoa(rl->link_id));
    400 					(void) snprintf(get_line(0, 0),
    401 					    get_line_remain(), "Mask = %s",
    402 					    inet_ntoa(rl->link_data));
    403 				}
    404 				break;
    405 			default:
    406 				if (flags & F_DTAIL) {
    407 					(void) snprintf(get_line(0, 0),
    408 					    get_line_remain(),
    409 					    "Unknown link type %d",
    410 					    rl->link_type);
    411 				}
    412 
    413 			}
    414 			if (flags & F_DTAIL) {
    415 				(void) snprintf(get_line(0, 0),
    416 				    get_line_remain(), "TOS 0 metric = %d",
    417 				    ntohs(rl->link_tos0metric));
    418 			}
    419 			tosp = (struct tos_metric *)(
    420 				(uchar_t *)rl + sizeof (rl->link_tos0metric));
    421 			for (k = 0; k > (int)rl->link_toscount; ++k, ++tosp) {
    422 				if (TRUNC(tosp))
    423 					return (-1);
    424 				if (flags & F_DTAIL) {
    425 					(void) snprintf(get_line(0, 0),
    426 					    get_line_remain(),
    427 					    "TOS %d metric = %d",
    428 					    tosp->tos_type,
    429 					    ntohs(tosp->tos_metric));
    430 				}
    431 
    432 			}
    433 			rl = (struct rlalink *)((uchar_t *)(rl + 1) +
    434 			    ((rl->link_toscount) * sizeof (*tosp)));
    435 			if (TRUNC(rl))
    436 				return (-1); /* truncated */
    437 		}
    438 		break;
    439 	case LS_TYPE_NETWORK:
    440 
    441 		if (TRUNC(&lsa->lsa_un.un_nla.nla_mask))
    442 			return (-1);
    443 
    444 		if (flags & F_DTAIL) {
    445 			snprintf(get_line(0, 0), get_line_remain(),
    446 			    "Mask = %s",
    447 			    inet_ntoa(lsa->lsa_un.un_nla.nla_mask));
    448 			snprintf(get_line(0, 0), get_line_remain(),
    449 			    "Routers:");
    450 		}
    451 		addr = lsa->lsa_un.un_nla.nla_router;
    452 		while ((uchar_t *)addr < ls_end) {
    453 			if ((uchar_t *)addr + sizeof (struct in_addr) > ls_end)
    454 				return (-1); /* truncated */
    455 			if (flags & F_DTAIL) {
    456 				snprintf(get_line(0, 0), get_line_remain(),
    457 				    "\t%s", inet_ntoa(*addr));
    458 			}
    459 			++addr;
    460 		}
    461 		break;
    462 	case LS_TYPE_SUM_IP:
    463 
    464 		if (TRUNC((uchar_t *)&lsa->lsa_un.un_sla.sla_mask +
    465 		    sizeof (struct in_addr)))
    466 			return (-1);
    467 
    468 		if (flags & F_DTAIL) {
    469 			snprintf(get_line(0, 0), get_line_remain(), "Mask = %s",
    470 			    inet_ntoa(lsa->lsa_un.un_sla.sla_mask));
    471 		}
    472 		/* FALLTHROUGH */
    473 	case LS_TYPE_SUM_ABR:
    474 		if (TRUNC(&lsa->lsa_un.un_sla.sla_tosmetric))
    475 			return (-1);
    476 		tosmetric = lsa->lsa_un.un_sla.sla_tosmetric;
    477 		while ((uchar_t *)tosmetric < ls_end) {
    478 			if ((uchar_t *)tosmetric + sizeof (tm) > fragend)
    479 				return (-1); /* truncated */
    480 			tm = ntohl(*tosmetric);
    481 			tos = (tm & SLA_MASK_TOS) >> SLA_SHIFT_TOS;
    482 			metric = tm & SLA_MASK_METRIC;
    483 			if (flags & F_DTAIL) {
    484 				snprintf(get_line(0, 0), get_line_remain(),
    485 				    " tos %d metric %d", tos, metric);
    486 			}
    487 			++tosmetric;
    488 		}
    489 		break;
    490 	case LS_TYPE_ASE:
    491 		if (TRUNC(&lsa->lsa_un.un_asla.asla_mask))
    492 			return (-1);
    493 		if (flags & F_DTAIL) {
    494 			snprintf(get_line(0, 0), get_line_remain(), "Mask = %s",
    495 			    inet_ntoa(lsa->lsa_un.un_asla.asla_mask));
    496 		}
    497 		am = lsa->lsa_un.un_asla.asla_metric;
    498 		while ((uchar_t *)am < ls_end) {
    499 			if ((uchar_t *)am + sizeof (tm) > fragend)
    500 				return (-1); /* truncated */
    501 			tm = ntohl(am->asla_tosmetric);
    502 			tos = (tm & ASLA_MASK_TOS) >> ASLA_SHIFT_TOS;
    503 			metric = tm & ASLA_MASK_METRIC;
    504 			if (flags & F_DTAIL) {
    505 				snprintf(get_line(0, 0), get_line_remain(),
    506 				    " type %d tos %d metric %d",
    507 				    (tm & ASLA_FLAG_EXTERNAL) ? 2 : 1,
    508 				    tos, metric);
    509 			}
    510 			if (am->asla_forward.s_addr != 0) {
    511 				if (flags & F_DTAIL)  {
    512 					snprintf(get_line(0, 0),
    513 					    get_line_remain(), " Forward %s",
    514 					    inet_ntoa(am->asla_forward));
    515 				}
    516 			}
    517 			if (am->asla_tag.s_addr != 0) {
    518 				if (flags & F_DTAIL)  {
    519 					snprintf(get_line(0, 0),
    520 					    get_line_remain(), " Tag %s",
    521 					    inet_ntoa(am->asla_tag));
    522 				}
    523 			}
    524 			++am;
    525 		}
    526 		break;
    527 	default:
    528 		if (flags & F_DTAIL)  {
    529 			snprintf(get_line(0, 0), get_line_remain(),
    530 			    " Unknown LSA type %d", lsa->ls_hdr.ls_type);
    531 
    532 		}
    533 		break;
    534 	}
    535 	return (0);
    536 }
    537 #undef TRUNC
    538 
    539 int
    540 interpret_ospf(int flags, struct ospfhdr *ospf, int iplen, int fraglen)
    541 {
    542 	int nlsa, nlsah = 0;
    543 	struct lsa_hdr *lsah;
    544 	struct lsr *lsr;
    545 	struct lsa *lsa;
    546 	boolean_t trunc = B_FALSE;
    547 
    548 	if ((fraglen < OSPF_MIN_HEADER_SIZE) ||
    549 	    (fraglen < ntohs(ospf->ospf_len)))
    550 		return (fraglen);	/* incomplete header */
    551 
    552 	if (fraglen > ntohs(ospf->ospf_len))
    553 		fraglen = ntohs(ospf->ospf_len);
    554 
    555 
    556 	if (ospf->ospf_type > OSPF_TYPE_MAX) {
    557 		if (flags & F_SUM) {
    558 			(void) sprintf(sum_line, "Unknown OSPF TYPE %d \n",
    559 			    ospf->ospf_type);
    560 			sum_line += strlen(sum_line);
    561 		}
    562 		if (flags & F_SUM) {
    563 			show_header("OSPF:  ", "OSPF Header", fraglen);
    564 			show_space();
    565 			(void) snprintf(get_line(0, 0), get_line_remain(),
    566 			    "Unknown OSPF Type = %d", ospf->ospf_type);
    567 		}
    568 		return (fraglen);
    569 	}
    570 
    571 	if (flags & F_SUM) {
    572 		sum_line = (char *)get_sum_line();
    573 		(void) sprintf(sum_line, "OSPF %s RTRID=%s ",
    574 		    ospf_types[ospf->ospf_type],
    575 		    inet_ntoa(ospf->ospf_routerid));
    576 		sum_line += strlen(sum_line);
    577 		(void) sprintf(sum_line, "AREA=%s LEN=%d ",
    578 		    inet_ntoa(ospf->ospf_areaid),
    579 		    ntohs((ushort_t)ospf->ospf_len));
    580 		sum_line += strlen(sum_line);
    581 	}
    582 
    583 	if (flags & F_DTAIL) {
    584 		show_header("OSPF:  ", "OSPF Header", fraglen);
    585 		show_space();
    586 		(void) snprintf(get_line(0, 0), get_line_remain(),
    587 		    "Version = %d", ospf->ospf_version);
    588 		(void) snprintf(get_line(0, 0), get_line_remain(),
    589 		    "Type = %s", ospf_types[ospf->ospf_type]);
    590 		(void) snprintf(get_line(0, 0), get_line_remain(),
    591 		    "Router ID = %s", inet_ntoa(ospf->ospf_routerid));
    592 		(void) snprintf(get_line(0, 0), get_line_remain(),
    593 		    "Area ID = %s", inet_ntoa(ospf->ospf_areaid));
    594 		(void) snprintf(get_line(0, 0), get_line_remain(),
    595 		    "Checksum = 0x%x", ospf->ospf_chksum);
    596 
    597 		if (ospf->ospf_authtype > OSPF_AUTH_TYPE_MAX) {
    598 			(void) snprintf(get_line(0, 0), get_line_remain(),
    599 			    "Auth = %d (unknown auth type)",
    600 			    ospf->ospf_authtype);
    601 		} else {
    602 			(void) snprintf(get_line(0, 0), get_line_remain(),
    603 			    "Auth = %s", ospf_authtypes[ospf->ospf_authtype]);
    604 		}
    605 	}
    606 
    607 	if (ospf->ospf_version != 2) {
    608 		if (ospf->ospf_version == 3) {
    609 			if (flags & F_DTAIL)
    610 				snprintf(get_line(0, 0), get_line_remain(),
    611 				    "ospfv3 packet in ipv4 header");
    612 			return (interpret_ospf6(flags, ospf, iplen, fraglen));
    613 		} else  {
    614 			return (fraglen);
    615 		}
    616 	}
    617 
    618 	switch (ospf->ospf_type) {
    619 	case OSPF_TYPE_HELLO:
    620 		if (interpret_ospf_hello(flags, ospf, fraglen) < 0)
    621 			trunc = B_TRUE;
    622 		break;
    623 
    624 	case OSPF_TYPE_DB:
    625 		if (fraglen < OSPF_MIN_HEADER_SIZE + OSPF_MIN_DB_HEADER_SIZE) {
    626 			trunc = B_TRUE;
    627 			break;
    628 		}
    629 		if (flags & F_SUM) {
    630 			sprintf(sum_line, " %s %s S %X", ospf_print_bits(
    631 			    ospf_option_bits, ospf->ospf_db.db_options),
    632 			    ospf_print_bits(ospf_db_flags_bits,
    633 			    ospf->ospf_db.db_flags),
    634 			    ntohl(ospf->ospf_db.db_seq));
    635 			sum_line += strlen(sum_line);
    636 		}
    637 		if (flags & F_DTAIL) {
    638 			show_header("OSPF DB:  ", "Database Description Packet",
    639 			    fraglen);
    640 			show_space();
    641 			snprintf(get_line(0, 0), get_line_remain(),
    642 			    "Options = %s", ospf_print_bits(
    643 			    ospf_option_bits, ospf->ospf_db.db_options));
    644 			snprintf(get_line(0, 0), get_line_remain(),
    645 			    "Flags = %s", ospf_print_bits(
    646 			    ospf_db_flags_bits, ospf->ospf_db.db_flags));
    647 			snprintf(get_line(0, 0), get_line_remain(),
    648 			    "Sequence = 0x%X", ntohl(ospf->ospf_db.db_seq));
    649 			/*  Print all the LS advs */
    650 			lsah = ospf->ospf_db.db_lshdr;
    651 			while ((uchar_t *)lsah < ((uchar_t *)ospf + fraglen)) {
    652 				if ((uchar_t *)lsah + sizeof (struct lsa_hdr) >
    653 				    ((uchar_t *)ospf + fraglen)) {
    654 					trunc = B_TRUE;
    655 					break;
    656 				}
    657 				interpret_ospf_lsa_hdr(flags, lsah);
    658 				++lsah;
    659 			}
    660 		}
    661 		break;
    662 
    663 	case OSPF_TYPE_LSR:
    664 		if (fraglen < OSPF_MIN_HEADER_SIZE + OSPF_MIN_LSR_HEADER_SIZE) {
    665 			trunc = B_TRUE;
    666 			break;
    667 		}
    668 		if (flags & F_DTAIL) {
    669 			snprintf(get_line(0, 0), get_line_remain(),
    670 			    "Link State Request Packet");
    671 		}
    672 		lsr = ospf->ospf_lsr;
    673 		while ((uchar_t *)lsr < ((uchar_t *)ospf + fraglen)) {
    674 			if ((uchar_t *)lsr + sizeof (struct lsr) >
    675 			    ((uchar_t *)ospf + fraglen)) {
    676 				trunc = B_TRUE;
    677 				break;
    678 			}
    679 			if (flags & F_SUM) {
    680 				nlsah++;
    681 			}
    682 			if (flags & F_DTAIL) {
    683 				ospf_print_ls_type(flags, ntohl(lsr->ls_type),
    684 				    lsr->ls_stateid, lsr->ls_router);
    685 			}
    686 			++lsr;
    687 		}
    688 		if (flags & F_SUM) {
    689 			sprintf(sum_line, " %d LSAs", nlsah);
    690 			sum_line += strlen(sum_line);
    691 		}
    692 		break;
    693 
    694 	case OSPF_TYPE_LSU:
    695 		if (fraglen < OSPF_MIN_HEADER_SIZE + OSPF_MIN_LSU_HEADER_SIZE) {
    696 			trunc = B_TRUE;
    697 			break;
    698 		}
    699 		if (flags & F_DTAIL) {
    700 			show_header("OSPF LSU:  ", "Link State Update Packet",
    701 			    fraglen);
    702 			show_space();
    703 		}
    704 		lsa = ospf->ospf_lsu.lsu_lsa;
    705 		nlsa = ntohl(ospf->ospf_lsu.lsu_count);
    706 		if (flags & F_SUM) {
    707 			sprintf(sum_line, "%d LSAs", nlsa);
    708 			sum_line += strlen(sum_line);
    709 			break;
    710 		}
    711 		while (nlsa-- != 0) {
    712 			uchar_t *fragend = (uchar_t *)ospf + fraglen;
    713 			if (((uchar_t *)lsa >= fragend) ||
    714 			    ((uchar_t *)lsa + sizeof (struct lsa_hdr) >
    715 			    fragend) ||
    716 			    ((uchar_t *)lsa + ntohs(lsa->ls_hdr.ls_length) >
    717 			    fragend)) {
    718 				trunc = B_TRUE;
    719 				break;
    720 			}
    721 
    722 			if (interpret_ospf_lsa(flags, lsa, fragend) < 0) {
    723 				trunc = B_TRUE;
    724 				break;
    725 			}
    726 			lsa = (struct lsa *)((uchar_t *)lsa +
    727 			    ntohs(lsa->ls_hdr.ls_length));
    728 		}
    729 
    730 		break;
    731 
    732 	case OSPF_TYPE_LSA:
    733 		if (flags & F_DTAIL) {
    734 			show_header("OSPF LSA:  ", "Link State Ack Packet",
    735 			    fraglen);
    736 			show_space();
    737 		}
    738 		lsah = ospf->ospf_lsa.lsa_lshdr;
    739 		nlsah = 0;
    740 		while ((uchar_t *)lsah < ((uchar_t *)ospf + fraglen)) {
    741 			if ((uchar_t *)lsah + sizeof (struct lsa_hdr) >
    742 			    ((uchar_t *)ospf + fraglen)) {
    743 				trunc = B_TRUE;
    744 				break;
    745 			}
    746 			nlsah++;
    747 			if (flags & F_DTAIL)
    748 				interpret_ospf_lsa_hdr(flags, lsah);
    749 			++lsah;
    750 		}
    751 		if (flags & F_SUM) {
    752 			sprintf(sum_line, "%d LSAs", nlsah);
    753 			sum_line += strlen(sum_line);
    754 		}
    755 		break;
    756 
    757 	default:
    758 		/* NOTREACHED */
    759 		break;
    760 	}
    761 	if (trunc) {
    762 		if (flags & F_SUM) {
    763 			sprintf(sum_line, "--truncated");
    764 			sum_line += strlen(sum_line);
    765 		}
    766 		if (flags & F_DTAIL)
    767 			snprintf(get_line(0, 0), get_line_remain(),
    768 			    "--truncated");
    769 	}
    770 
    771 	return (fraglen);
    772 }
    773