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