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  410  kcpoon  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
     24  410  kcpoon  * 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 <fcntl.h>
     31    0  stevel #include <sys/socket.h>
     32    0  stevel #include <netinet/in.h>
     33    0  stevel #include <protocols/routed.h>
     34    0  stevel #include <string.h>
     35    0  stevel #include <arpa/inet.h>
     36    0  stevel #include "snoop.h"
     37    0  stevel #include "snoop_mip.h"
     38    0  stevel 
     39    0  stevel /*
     40    0  stevel  * This defines the length of internal, unbounded buffers. We set
     41    0  stevel  * this to be MAXLINE (the maximum verbose display line length) -
     42    0  stevel  * 64, which should be enough for all necessary descriptions.
     43    0  stevel  */
     44    0  stevel #define	BUFLEN	MAXLINE - 64
     45    0  stevel 
     46    0  stevel extern char *dlc_header;
     47    0  stevel extern char *addrtoname();
     48    0  stevel 
     49  410  kcpoon enum EXT_TYPE { ADV, REG };
     50    0  stevel 
     51    0  stevel /*
     52    0  stevel  * This defines the interface for all extention interpreter
     53    0  stevel  * functions. The function will be called with following
     54    0  stevel  * parameters:
     55    0  stevel  *
     56    0  stevel  * type:	IN	The type code for this extention
     57    0  stevel  * len		IN	The length of the payload (i.e. the
     58    0  stevel  *			length field in an extension header)
     59    0  stevel  * payload	IN	A pointer to the beginning of the
     60    0  stevel  *			extension payload
     61    0  stevel  */
     62    0  stevel typedef void interpreter_f(uint8_t type, uint8_t len, uchar_t *payload);
     63    0  stevel 
     64    0  stevel struct ext_dispatch {
     65    0  stevel 	uint8_t type;
     66    0  stevel 	interpreter_f *pfunc;
     67    0  stevel };
     68    0  stevel 
     69    0  stevel /* Description structure -- maps type to description */
     70    0  stevel struct ext_desc {
     71    0  stevel 	uint8_t type;
     72    0  stevel 	const char *desc;
     73    0  stevel };
     74    0  stevel 
     75    0  stevel /*
     76    0  stevel  * Interpreter function prototypes for both adv and reg. These
     77    0  stevel  * all must implement the interpret_f interface defined above.
     78    0  stevel  */
     79    0  stevel static void spi_ext(uint8_t, uint8_t, uchar_t *);
     80    0  stevel static void key_ext(uint8_t, uint8_t, uchar_t *);
     81    0  stevel static void trav_ext(uint8_t, uint8_t, uchar_t *);
     82    0  stevel static void empty_ext(uint8_t, uint8_t, uchar_t *);
     83    0  stevel static void nai_ext(uint8_t, uint8_t, uchar_t *);
     84    0  stevel static void chall_ext(uint8_t, uint8_t, uchar_t *);
     85    0  stevel static void ma_ext(uint8_t, uint8_t, uchar_t *);
     86    0  stevel static void prefix_ext(uint8_t, uint8_t, uchar_t *);
     87    0  stevel static void unk_ext(uint8_t, uint8_t, uchar_t *);
     88    0  stevel 
     89    0  stevel /* R E G I S T R A T I O N */
     90    0  stevel 
     91    0  stevel #define	REG_TBL_LEN	10	/* update this when adding to the table */
     92    0  stevel 
     93    0  stevel /* Reg: type to description mapping table */
     94    0  stevel static struct ext_desc reg_desc[] = {
     95    0  stevel 	MN_HA_AUTH,	"(Mobile-Home Authentication Extension)",
     96    0  stevel 	MN_FA_AUTH,	"(Mobile-Foreign Authentication Extension",
     97    0  stevel 	FA_HA_AUTH,	"(Foreign-Home Authentication Extension)",
     98    0  stevel 	GEN_AUTH,	"(Generalized Authentication Extension)",
     99    0  stevel 	MN_HA_KEY,	"(Mobile-Home Key Extension)",
    100    0  stevel 	MN_FA_KEY,	"(Mobile-Foreign Key Extension)",
    101    0  stevel 	MN_HA_TRAVERSE,	"(Firewall Traversal Extension)",
    102    0  stevel 	ENCAP_DELIV,	"(Encapsulating Delivery Style Extension)",
    103    0  stevel 	MN_NAI,		"(Mobile Node Network Access Identifier)",
    104    0  stevel 	FA_CHALLENGE,	"(Mobile-Foreign Agent Challenge)",
    105    0  stevel 	0,		"(Unrecognized Extension)"
    106    0  stevel };
    107    0  stevel 
    108    0  stevel #define	GENAUTH_TBL_LEN	1	/* update this when adding to the table */
    109    0  stevel 
    110    0  stevel /* Subtypes for Generic Authentication Extension type (type 36) */
    111    0  stevel static struct ext_desc genauth_desc[] = {
    112    0  stevel 	GEN_AUTH_MN_AAA,	"(MN-AAA Authentication Subtype)",
    113    0  stevel 	0,			"(Unrecognized Subtype)"
    114    0  stevel };
    115    0  stevel 
    116    0  stevel /* Reg: type to function mapping table */
    117    0  stevel static struct ext_dispatch reg_dispatch[] = {
    118    0  stevel 	MN_HA_AUTH,	spi_ext,
    119    0  stevel 	MN_FA_AUTH,	spi_ext,
    120    0  stevel 	FA_HA_AUTH,	spi_ext,
    121    0  stevel 	GEN_AUTH,	spi_ext,
    122    0  stevel 	MN_HA_KEY,	key_ext,
    123    0  stevel 	MN_FA_KEY,	key_ext,
    124    0  stevel 	MN_HA_TRAVERSE,	trav_ext,
    125    0  stevel 	ENCAP_DELIV,	empty_ext,
    126    0  stevel 	MN_NAI,		nai_ext,
    127    0  stevel 	FA_CHALLENGE,	chall_ext,
    128    0  stevel 	0,		unk_ext
    129    0  stevel };
    130    0  stevel 
    131    0  stevel /* A D V E R T I S E M E N T */
    132    0  stevel 
    133    0  stevel #define	ADV_TBL_LEN	5	/* update this when adding to the table */
    134    0  stevel 
    135    0  stevel /* Adv: type to description mapping table */
    136    0  stevel static struct ext_desc adv_desc[] = {
    137    0  stevel 	ICMP_ADV_MSG_PADDING_EXT,	"(Padding)",
    138    0  stevel 	ICMP_ADV_MSG_MOBILITY_AGT_EXT,	"(Mobility Agent Extension)",
    139    0  stevel 	ICMP_ADV_MSG_PREFIX_LENGTH_EXT,	"(Prefix Lengths)",
    140    0  stevel 	ICMP_ADV_MSG_FA_CHALLENGE,	"(Foreign Agent Challenge)",
    141    0  stevel 	ICMP_ADV_MSG_FA_NAI,		"(Foreign Agent NAI)",
    142    0  stevel 	0,				"(Unrecognized Extension)"
    143    0  stevel };
    144    0  stevel 
    145    0  stevel /* Adv: type to function mapping table */
    146    0  stevel static struct ext_dispatch adv_dispatch[] = {
    147    0  stevel 	ICMP_ADV_MSG_PADDING_EXT,	NULL,	/* never called */
    148    0  stevel 	ICMP_ADV_MSG_MOBILITY_AGT_EXT,	ma_ext,
    149    0  stevel 	ICMP_ADV_MSG_PREFIX_LENGTH_EXT,	prefix_ext,
    150    0  stevel 	ICMP_ADV_MSG_FA_CHALLENGE,	chall_ext,
    151    0  stevel 	ICMP_ADV_MSG_FA_NAI,		nai_ext,
    152    0  stevel 	0,				unk_ext
    153    0  stevel };
    154    0  stevel 
    155    0  stevel #define	GETSPI(payload, hi, low) \
    156    0  stevel 	(void) memcpy(&hi, payload, sizeof (hi)); \
    157    0  stevel 	(void) memcpy(&low, payload + sizeof (hi), sizeof (low))
    158    0  stevel 
    159    0  stevel static void dumphex(uchar_t *payload, int payload_len, char *buf, char *msg) {
    160    0  stevel 	int index;
    161    0  stevel 
    162    0  stevel 	for (index = 0; index < payload_len; index++) {
    163    0  stevel 		(void) sprintf(&buf[index * 3], " %.2x", payload[index]);
    164    0  stevel 	}
    165    0  stevel 
    166    0  stevel 	(void) sprintf(get_line((char *)payload-dlc_header, 1), msg, buf);
    167    0  stevel }
    168    0  stevel 
    169    0  stevel static const char *get_desc(struct ext_desc table[], uint8_t type, int max) {
    170    0  stevel 	int i;
    171    0  stevel 
    172    0  stevel 	for (i = 0; i < max && table[i].type != type; i++)
    173    0  stevel 	    /* NO_OP */;
    174    0  stevel 
    175    0  stevel 	return (table[i].desc);
    176    0  stevel }
    177    0  stevel 
    178    0  stevel /*
    179    0  stevel  * The following is an accessor for the description table, used by
    180    0  stevel  * snoop_icmp.c. This maintains the encapsulation of the internal
    181    0  stevel  * description table.
    182    0  stevel  */
    183    0  stevel const char *get_mip_adv_desc(uint8_t type) {
    184    0  stevel 	return (get_desc(adv_desc, type, ADV_TBL_LEN));
    185    0  stevel }
    186    0  stevel 
    187    0  stevel static interpreter_f *get_interpreter(struct ext_dispatch table[],
    188    0  stevel 				uint8_t type,
    189    0  stevel 				int max) {
    190    0  stevel 	int i;
    191    0  stevel 
    192    0  stevel 	for (i = 0; i < max && table[i].type != type; i++)
    193    0  stevel 	    /* NO_OP */;
    194    0  stevel 
    195    0  stevel 	return (table[i].pfunc);
    196    0  stevel }
    197    0  stevel 
    198    0  stevel static int
    199    0  stevel interpret_extensions(uchar_t *ext,
    200    0  stevel 			int regext_size,
    201    0  stevel 			enum EXT_TYPE etype) {
    202    0  stevel 
    203    0  stevel 	int curr_size  =  regext_size; /* remaining total for all exts */
    204    0  stevel 	exthdr_t *exthdr;
    205    0  stevel 	gen_exthdr_t *gen_exthdr;
    206    0  stevel 	const char *st;
    207    0  stevel 	uchar_t	*p;
    208    0  stevel 	interpreter_f *f;
    209    0  stevel 	uint8_t	ext_type;
    210    0  stevel 	uint16_t ext_len;
    211    0  stevel 	uint_t ext_hdrlen;
    212    0  stevel 
    213    0  stevel 	show_space();
    214    0  stevel 	exthdr = (exthdr_t *)ALIGN(ext);
    215    0  stevel 
    216    0  stevel 
    217    0  stevel 	do {
    218    0  stevel 	    ext_type = exthdr->type;
    219    0  stevel 	    if (ext_type == GEN_AUTH) {
    220    0  stevel 		gen_exthdr = (gen_exthdr_t *)exthdr;
    221    0  stevel 		ext_hdrlen = sizeof (gen_exthdr_t);
    222    0  stevel 		ext_len = ntohs(gen_exthdr->length);
    223    0  stevel 	    } else {
    224    0  stevel 		ext_hdrlen = sizeof (exthdr_t);
    225    0  stevel 		ext_len = exthdr->length;
    226    0  stevel 	    }
    227    0  stevel 
    228    0  stevel 	    if (!((etype == ADV && ext_type == ICMP_ADV_MSG_PADDING_EXT &&
    229    0  stevel 		curr_size >= 1) ||
    230    0  stevel 		curr_size >= ext_hdrlen + ext_len))
    231    0  stevel 		    break;
    232    0  stevel 
    233    0  stevel 	    /* Print description for this extension */
    234    0  stevel 	    if (etype == ADV) {
    235    0  stevel 		st = get_desc(adv_desc, ext_type, ADV_TBL_LEN);
    236    0  stevel 	    } else /* REG */ {
    237    0  stevel 		st = get_desc(reg_desc, ext_type, REG_TBL_LEN);
    238    0  stevel 	    }
    239    0  stevel 
    240    0  stevel 	    (void) sprintf(get_line((char *)exthdr-dlc_header, 1),
    241    0  stevel 			"Extension header type = %d  %s", ext_type, st);
    242    0  stevel 
    243    0  stevel 	    if (ext_type == GEN_AUTH) {
    244    0  stevel 		st = get_desc(genauth_desc, gen_exthdr->subtype,
    245    0  stevel 		    GENAUTH_TBL_LEN);
    246    0  stevel 		(void) sprintf(get_line((char *)exthdr-dlc_header, 1),
    247    0  stevel 		    "Subtype = %d %s", gen_exthdr->subtype, st);
    248    0  stevel 	    }
    249    0  stevel 
    250    0  stevel 	    /* Special case for 1-byte padding */
    251    0  stevel 	    if (etype == ADV && ext_type == ICMP_ADV_MSG_PADDING_EXT) {
    252    0  stevel 		exthdr = (exthdr_t *)((uchar_t *)exthdr + 1);
    253    0  stevel 		curr_size--;
    254    0  stevel 		continue;
    255    0  stevel 	    }
    256    0  stevel 
    257    0  stevel 	    (void) sprintf(get_line((char *)&exthdr->length-dlc_header, 1),
    258    0  stevel 			"Length = %d", ext_len);
    259    0  stevel 
    260    0  stevel 	    /* Parse out the extension's payload */
    261    0  stevel 	    p = (uchar_t *)exthdr + ext_hdrlen;
    262    0  stevel 	    curr_size -= (ext_hdrlen + ext_len);
    263    0  stevel 
    264    0  stevel 	    if (etype == ADV) {
    265    0  stevel 		f = get_interpreter(adv_dispatch, ext_type, ADV_TBL_LEN);
    266    0  stevel 	    } else /* REG */ {
    267    0  stevel 		f = get_interpreter(reg_dispatch, ext_type, REG_TBL_LEN);
    268    0  stevel 	    }
    269    0  stevel 
    270    0  stevel 	    f(ext_type, ext_len, p);
    271    0  stevel 
    272    0  stevel 	    show_space();
    273    0  stevel 	    exthdr = (exthdr_t *)(p + ext_len);
    274    0  stevel 	} while (B_TRUE);
    275    0  stevel 
    276    0  stevel 	return (0);
    277    0  stevel }
    278    0  stevel 
    279    0  stevel void interpret_icmp_mip_ext(uchar_t *p, int len) {
    280    0  stevel 	show_space();
    281    0  stevel 	show_header("ICMP:  ", " MIP Advertisement Extensions ", len);
    282    0  stevel 	show_space();
    283    0  stevel 
    284    0  stevel 	interpret_extensions(p, len, ADV);
    285    0  stevel }
    286    0  stevel 
    287    0  stevel void
    288    0  stevel interpret_mip_cntrlmsg(int flags, uchar_t *msg, int fraglen) {
    289    0  stevel 	char		*pt, *pc = NULL;
    290    0  stevel 	char		*line;
    291    0  stevel 	regreq_t	rreq[1];
    292    0  stevel 	regrep_t	rrep[1];
    293    0  stevel 	int		regext_size;
    294    0  stevel 	uchar_t		*regext_data;
    295    0  stevel 	struct in_addr	addr_temp;
    296    0  stevel 
    297    0  stevel 
    298    0  stevel 	/* First byte of the message should be the type */
    299    0  stevel 	switch (*msg) {
    300    0  stevel 	case REG_TYPE_REQ:
    301    0  stevel 		if (fraglen < sizeof (regreq_t))
    302    0  stevel 			return;
    303    0  stevel 		pt = (flags & F_DTAIL ? "registration request ":"reg rqst ");
    304    0  stevel 
    305    0  stevel 		(void) memcpy(rreq, msg, sizeof (*rreq));
    306    0  stevel 		regext_size = fraglen - sizeof (regreq_t);
    307    0  stevel 		regext_data = msg + sizeof (*rreq);
    308    0  stevel 		break;
    309    0  stevel 	case REG_TYPE_REP:
    310    0  stevel 		if (fraglen < sizeof (regrep_t))
    311    0  stevel 			return;
    312    0  stevel 		pt = (flags & F_DTAIL ? "registration reply ":"reg reply ");
    313    0  stevel 
    314    0  stevel 		(void) memcpy(rrep, msg, sizeof (*rrep));
    315    0  stevel 		regext_size = fraglen - sizeof (regrep_t);
    316    0  stevel 		regext_data = msg + sizeof (*rrep);
    317    0  stevel 
    318    0  stevel 		switch (rrep->code) {
    319    0  stevel 		case  REPLY_CODE_ACK:
    320    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL)) ?
    321    0  stevel 			    "OK" : "OK code 0";
    322    0  stevel 			break;
    323    0  stevel 		case  REPLY_CODE_ACK_NO_SIMULTANEOUS:
    324    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    325    0  stevel 			    "OK simultaneous bindings" : "OK code 1";
    326    0  stevel 			break;
    327    0  stevel 		case  REPLY_CODE_FA_NACK_UNSPECIFIED:
    328    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    329    0  stevel 			    "FA denial: unspecified":"FA denial: code 64";
    330    0  stevel 			break;
    331    0  stevel 		case  REPLY_CODE_FA_NACK_PROHIBITED:
    332    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    333    0  stevel 			    "FA denial: prohibited":"FA denial: code 65";
    334    0  stevel 			break;
    335    0  stevel 		case  REPLY_CODE_FA_NACK_RESOURCES:
    336    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    337    0  stevel 			    "FA denial: no resources":"FA denial: code 66";
    338    0  stevel 			break;
    339    0  stevel 		case  REPLY_CODE_FA_NACK_MN_AUTH:
    340    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    341    0  stevel 			    "FA denial: MN auth failed":"FA denial: code 67";
    342    0  stevel 			break;
    343    0  stevel 		case  REPLY_CODE_FA_NACK_HA_AUTH:
    344    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    345    0  stevel 			    "FA denial: HA auth failed":
    346    0  stevel 			    "FA denial: code 68";
    347    0  stevel 			break;
    348    0  stevel 		case  REPLY_CODE_FA_NACK_LIFETIME:
    349    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    350    0  stevel 			    "FA denial: lifetime":"FA denial: code 69";
    351    0  stevel 			break;
    352    0  stevel 		case  REPLY_CODE_FA_NACK_BAD_REQUEST:
    353    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    354    0  stevel 			    "FA denial: bad request": "FA: code 70";
    355    0  stevel 			break;
    356    0  stevel 		case  REPLY_CODE_FA_NACK_BAD_REPLY:
    357    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    358    0  stevel 			    "FA denial: bad Reply":"FA denial: code 71";
    359    0  stevel 			break;
    360    0  stevel 		case  REPLY_CODE_FA_NACK_ENCAP_UNAVAILABLE:
    361    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    362    0  stevel 			    "FA denial: encapsulation":"FA denial: code 72";
    363    0  stevel 			break;
    364    0  stevel 		case  REPLY_CODE_FA_NACK_VJ_UNAVAILABLE:
    365    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    366    0  stevel 			    "FA denial: VJ compression":"FA denial: code 73";
    367    0  stevel 			break;
    368    0  stevel 		case  REPLY_CODE_FA_NACK_BIDIR_TUNNEL_UNAVAILABLE:
    369    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    370    0  stevel 			    "FA denial: reverse tunnel unavailable":
    371    0  stevel 				"FA denial: code 74";
    372    0  stevel 			break;
    373    0  stevel 		case  REPLY_CODE_FA_NACK_BIDIR_TUNNEL_NO_TBIT:
    374    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    375    0  stevel 			    "FA denial: reverse tunnel: missing T-bit":
    376    0  stevel 				"FA denial: code 75";
    377    0  stevel 			break;
    378    0  stevel 		case  REPLY_CODE_FA_NACK_BIDIR_TUNNEL_TOO_DISTANT:
    379    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    380    0  stevel 			    "FA denial: reverse tunnel: too distant":
    381    0  stevel 				"FA denial: code 76";
    382    0  stevel 			break;
    383    0  stevel 		case  REPLY_CODE_FA_NACK_ICMP_HA_NET_UNREACHABLE:
    384    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    385    0  stevel 			    "FA denial: home network unreachable":
    386    0  stevel 			    "FA denial: code 80";
    387    0  stevel 			break;
    388    0  stevel 		case  REPLY_CODE_FA_NACK_ICMP_HA_HOST_UNREACHABLE:
    389    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    390    0  stevel 			    "FA denial: HA host unreachable":
    391    0  stevel 			    "FA denial: code 81";
    392    0  stevel 			break;
    393    0  stevel 		case  REPLY_CODE_FA_NACK_ICMP_HA_PORT_UNREACHABLE:
    394    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    395    0  stevel 			    "FA denial: HA port unreachable":
    396    0  stevel 			    "FA denial: code 82";
    397    0  stevel 			break;
    398    0  stevel 		case  REPLY_CODE_FA_NACK_ICMP_HA_UNREACHABLE:
    399    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    400    0  stevel 			    "FA denial: HA unreachable":"FA denial: code 88";
    401    0  stevel 			break;
    402    0  stevel 		case REPLY_CODE_FA_NACK_UNIQUE_HOMEADDR_REQD:
    403    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    404    0  stevel 			    "FA denial: Unique Home Addr Required":
    405    0  stevel 				"FA denial: code 96";
    406    0  stevel 			break;
    407    0  stevel 		case REPLY_CODE_FA_NACK_MISSING_NAI:
    408    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    409    0  stevel 			    "FA denial: Missing NAI":
    410    0  stevel 				"FA denial: code 97";
    411    0  stevel 			break;
    412    0  stevel 		case REPLY_CODE_FA_NACK_MISSING_HOME_AGENT:
    413    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    414    0  stevel 			    "FA denial: Missing Home Agent":
    415    0  stevel 				"FA denial: code 98";
    416    0  stevel 			break;
    417    0  stevel 		case REPLY_CODE_FA_NACK_UNKNOWN_CHALLENGE:
    418    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    419    0  stevel 			    "FA denial: Unknown Challenge":
    420    0  stevel 				"FA denial: code 104";
    421    0  stevel 			break;
    422    0  stevel 		case REPLY_CODE_FA_NACK_MISSING_CHALLENGE:
    423    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    424    0  stevel 			    "FA denial: Missing Challenge":
    425    0  stevel 				"FA denial: code 105";
    426    0  stevel 			break;
    427    0  stevel 		case REPLY_CODE_FA_NACK_MISSING_MN_FA:
    428    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    429    0  stevel 			    "FA denial: Missing Mobile-Foreign Key Extension":
    430    0  stevel 				"FA denial: code 106";
    431    0  stevel 			break;
    432    0  stevel 		case  REPLY_CODE_HA_NACK_UNSPECIFIED:
    433    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    434    0  stevel 			    "HA denial: unspecified":"HA denial: code 128";
    435    0  stevel 			break;
    436    0  stevel 		case  REPLY_CODE_HA_NACK_PROHIBITED:
    437    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    438    0  stevel 			    "HA denial: prohibited":"HA denial: code 129";
    439    0  stevel 			break;
    440    0  stevel 		case  REPLY_CODE_HA_NACK_RESOURCES:
    441    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    442    0  stevel 			    "HA denial: no resources":"HA denial: code 130";
    443    0  stevel 			break;
    444    0  stevel 		case  REPLY_CODE_HA_NACK_MN_AUTH:
    445    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    446    0  stevel 			    "HA denial: MN auth failed":"HA denial: code 131";
    447    0  stevel 			break;
    448    0  stevel 		case  REPLY_CODE_HA_NACK_FA_AUTH:
    449    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    450    0  stevel 			    "HA denial: FA auth failed":"HA denial: code 132";
    451    0  stevel 			break;
    452    0  stevel 		case  REPLY_CODE_HA_NACK_ID_MISMATCH:
    453    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    454    0  stevel 			    "HA denial: ID mismatch":"HA denial: code 133";
    455    0  stevel 			break;
    456    0  stevel 		case  REPLY_CODE_HA_NACK_BAD_REQUEST:
    457    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    458    0  stevel 			    "HA denial: bad request":"HA denial: code 134";
    459    0  stevel 			break;
    460    0  stevel 		case  REPLY_CODE_HA_NACK_TOO_MANY_BINDINGS:
    461    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    462    0  stevel 			    "HA denial: too many bindings":
    463    0  stevel 			    "HA denial: code 135";
    464    0  stevel 			break;
    465    0  stevel 		case  REPLY_CODE_HA_NACK_BAD_HA_ADDRESS:
    466    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    467    0  stevel 			    "HA denial: bad HA address":"HA denial: code 136";
    468    0  stevel 			break;
    469    0  stevel 		case  REPLY_CODE_HA_NACK_BIDIR_TUNNEL_UNAVAILABLE:
    470    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    471    0  stevel 			    "HA denial: no reverse tunnel":
    472    0  stevel 			    "HA denial: code 137";
    473    0  stevel 			break;
    474    0  stevel 		case  REPLY_CODE_HA_NACK_BIDIR_TUNNEL_NO_TBIT:
    475    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    476    0  stevel 			    "HA denial: reverse tunnel: no T-bit":
    477    0  stevel 			    "HA denial: code 138";
    478    0  stevel 			break;
    479    0  stevel 		case  REPLY_CODE_HA_NACK_BIDIR_ENCAP_UNAVAILABLE:
    480    0  stevel 			pc = ((flags & F_ALLSUM) || (flags & F_DTAIL))?
    481    0  stevel 			    "HA denial: encapsulation unavailable":
    482    0  stevel 			    "HA denial: code 139";
    483    0  stevel 			break;
    484    0  stevel 		default:
    485    0  stevel 			pc = "?";
    486    0  stevel 			break;
    487    0  stevel 		}
    488    0  stevel 		break;
    489    0  stevel 
    490    0  stevel 	default :
    491    0  stevel 		break;
    492    0  stevel 	}
    493    0  stevel 	if (flags & F_SUM) {
    494    0  stevel 		line = get_sum_line();
    495    0  stevel 
    496    0  stevel 		if (pc != NULL)
    497    0  stevel 			(void) sprintf(line, "Mobile IP %s(%s)", pt, pc);
    498    0  stevel 		else
    499    0  stevel 			(void) sprintf(line, "Mobile IP %s", pt);
    500    0  stevel 	}
    501    0  stevel 
    502    0  stevel 	if (flags & F_DTAIL) {
    503    0  stevel 		show_header("MIP:  ", "Mobile IP Header", fraglen);
    504    0  stevel 		show_space();
    505    0  stevel 
    506    0  stevel 		if (*msg == REG_TYPE_REQ) {
    507    0  stevel 			(void) sprintf(get_line((char *)&rreq -
    508    0  stevel 			    dlc_header, 1), "Registration header type = %s",
    509    0  stevel 			    pt);
    510    0  stevel 			(void) sprintf(get_line(
    511    0  stevel 			    (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1),
    512    0  stevel 			    "%d... .... = %s simultaneous bindings  ",
    513    0  stevel 			    (rreq->Simultaneous_registration == 1)? 1 : 0,
    514    0  stevel 			    (rreq->Simultaneous_registration == 1)? "":"no");
    515    0  stevel 			(void) sprintf(get_line(
    516    0  stevel 			    (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1),
    517    0  stevel 			    ".%d.. .... = %s broadcast datagrams ",
    518    0  stevel 			    (rreq->Broadcasts_desired == 1) ?  1 : 0,
    519    0  stevel 			    (rreq->Broadcasts_desired == 1) ? "":"no");
    520    0  stevel 			(void) sprintf(get_line(
    521    0  stevel 			    (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1),
    522    0  stevel 			    "..%d. .... = %s decapsulation by MN",
    523    0  stevel 			    (rreq->Decapsulation_done_locally == 1) ? 1 : 0,
    524    0  stevel 			    (rreq->Decapsulation_done_locally == 1) ?
    525    0  stevel 				"" : "no");
    526    0  stevel 			(void) sprintf(get_line(
    527    0  stevel 			    (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1),
    528    0  stevel 			    "...%d .... = %s minimum encapsulation ",
    529    0  stevel 			    (rreq->Minimal_encap_desired == 1) ? 1 : 0,
    530    0  stevel 			    (rreq->Minimal_encap_desired == 1) ? "" : "no");
    531    0  stevel 			(void) sprintf(get_line(
    532    0  stevel 			    (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1),
    533    0  stevel 			    ".... %d... = %s GRE encapsulation ",
    534    0  stevel 			    (rreq->GRE_encap_desired == 1) ? 1 : 0,
    535    0  stevel 			    (rreq->GRE_encap_desired == 1) ? "" : "no");
    536    0  stevel 			(void) sprintf(get_line(
    537    0  stevel 			    (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1),
    538    0  stevel 			    ".... .%d.. = %s VJ hdr Compression ",
    539    0  stevel 			    (rreq->VJ_compression_desired == 1) ? 1 : 0,
    540    0  stevel 			    (rreq->VJ_compression_desired == 1) ? "" : "no");
    541    0  stevel 			(void) sprintf(get_line(
    542    0  stevel 			    (char *)(((uchar_t *)&rreq) + 1) - dlc_header, 1),
    543    0  stevel 			    ".... ..%d. = %s reverse tunnel",
    544    0  stevel 			    (rreq->BiDirectional_Tunnel_desired == 1) ? 1 : 0,
    545    0  stevel 			    (rreq->BiDirectional_Tunnel_desired == 1) ?
    546    0  stevel 				"" : "no");
    547    0  stevel 			if (ntohs(rreq->lifetime) == 0xffff) {
    548    0  stevel 				(void) sprintf(get_line(
    549    0  stevel 				    (char *)&rreq->lifetime - dlc_header, 1),
    550    0  stevel 				    "Life Time = 0xFFFF (infinity)");
    551    0  stevel 			} else if (ntohs(rreq->lifetime) == 0) {
    552    0  stevel 				(void) sprintf(get_line(
    553    0  stevel 				    (char *)&rreq->lifetime - dlc_header, 1),
    554    0  stevel 				    "Life Time = 0 "
    555    0  stevel 				    "(request for de-registration)");
    556    0  stevel 			} else {
    557    0  stevel 				(void) sprintf(get_line(
    558    0  stevel 				    (char *)&rreq->lifetime - dlc_header, 1),
    559    0  stevel 				    "Life time = %d seconds",
    560    0  stevel 				    ntohs(rreq->lifetime));
    561    0  stevel 			}
    562    0  stevel 			addr_temp.s_addr = rreq->home_addr;
    563    0  stevel 			(void) sprintf(get_line(
    564    0  stevel 			    (char *)&rreq->home_addr - dlc_header, 1),
    565    0  stevel 			    "Home address = %s, %s",
    566    0  stevel 			    inet_ntoa(addr_temp),
    567    0  stevel 			    addrtoname(AF_INET, &addr_temp));
    568    0  stevel 			addr_temp.s_addr = rreq->home_agent_addr;
    569    0  stevel 			(void) sprintf(get_line(
    570    0  stevel 			    (char *)&rreq->home_agent_addr - dlc_header, 1),
    571    0  stevel 			    "Home Agent address = %s, %s",
    572    0  stevel 			    inet_ntoa(addr_temp),
    573    0  stevel 			    addrtoname(AF_INET, &addr_temp));
    574    0  stevel 			addr_temp.s_addr = rreq->care_of_addr;
    575    0  stevel 			(void) sprintf(get_line(
    576    0  stevel 			    (char *)&rreq->care_of_addr - dlc_header, 1),
    577    0  stevel 			    "Care of address = %s, %s",
    578    0  stevel 			    inet_ntoa(addr_temp),
    579    0  stevel 			    addrtoname(AF_INET, &addr_temp));
    580    0  stevel 			(void) sprintf(get_line(
    581    0  stevel 			    (char *)&rreq->identification - dlc_header, 1),
    582    0  stevel 			    "Identification = 0x%x-%x",
    583    0  stevel 			    ntohl(rreq->identification.high_bits),
    584    0  stevel 			    ntohl(rreq->identification.low_bits));
    585    0  stevel 		} else if (*msg == REG_TYPE_REP) {
    586    0  stevel 			(void) sprintf(
    587    0  stevel 			    get_line((char *)&rrep->type - dlc_header, 1),
    588    0  stevel 			    "Registration header type = %d (%s)",
    589    0  stevel 			    (int)rrep->type, pt);
    590    0  stevel 			(void) sprintf(get_line((char *)&rrep - dlc_header, 1),
    591    0  stevel 			    "Code = %d %s", (int)rrep->code, pc);
    592    0  stevel 			if (ntohs(rrep->lifetime) == 0xffff) {
    593    0  stevel 				(void) sprintf(get_line(
    594    0  stevel 				    (char *)&rrep->lifetime - dlc_header, 1),
    595    0  stevel 				    "Life time = 0xFFFF (infinity)");
    596    0  stevel 			} else if (ntohs(rrep->lifetime) == 0) {
    597    0  stevel 				(void) sprintf(get_line(
    598    0  stevel 				    (char *)&rrep->lifetime - dlc_header, 1),
    599    0  stevel 				    ((rrep->code == REPLY_CODE_ACK) ||
    600    0  stevel 				    (rrep->code ==
    601    0  stevel 					REPLY_CODE_ACK_NO_SIMULTANEOUS))?
    602    0  stevel 				    "Life time = 0 (de-registeration success)" :
    603    0  stevel 				    "Life time = 0 (de-registration failed)");
    604    0  stevel 			} else {
    605    0  stevel 				(void) sprintf(get_line(
    606    0  stevel 				    (char *)&rrep->lifetime - dlc_header, 1),
    607    0  stevel 				    "Life time = %d seconds",
    608    0  stevel 				    ntohs(rrep->lifetime));
    609    0  stevel 			}
    610    0  stevel 			addr_temp.s_addr = rrep->home_addr;
    611    0  stevel 			(void) sprintf(
    612    0  stevel 			    get_line((char *)&rrep->home_addr - dlc_header, 1),
    613    0  stevel 			    "Home address = %s, %s",
    614    0  stevel 			    inet_ntoa(addr_temp),
    615    0  stevel 			    addrtoname(AF_INET, &addr_temp));
    616    0  stevel 			addr_temp.s_addr = rrep->home_agent_addr;
    617    0  stevel 			(void) sprintf(get_line(
    618    0  stevel 			    (char *)&rrep->home_agent_addr - dlc_header, 1),
    619    0  stevel 			    "Home Agent address = %s, %s",
    620    0  stevel 			    inet_ntoa(addr_temp),
    621    0  stevel 			    addrtoname(AF_INET, &addr_temp));
    622    0  stevel 			(void) sprintf(get_line(
    623    0  stevel 			    (char *)&rrep->identification - dlc_header, 1),
    624    0  stevel 			    "Identification = 0x%x-%x",
    625    0  stevel 			    ntohl(rrep->identification.high_bits),
    626    0  stevel 			    ntohl(rrep->identification.low_bits));
    627    0  stevel 		}
    628    0  stevel 		fraglen = interpret_extensions(regext_data, regext_size, REG);
    629    0  stevel 	}
    630    0  stevel }
    631    0  stevel 
    632    0  stevel /*ARGSUSED*/
    633    0  stevel static void spi_ext(uint8_t type, uint8_t this_ext_len, uchar_t *p) {
    634    0  stevel 	uint16_t spi_hi, spi_low;
    635    0  stevel 	char	auth_prn_str[BUFLEN];
    636    0  stevel 
    637    0  stevel 	/* SPI */
    638    0  stevel 	GETSPI(p, spi_hi, spi_low);
    639    0  stevel 	(void) sprintf(get_line((char *)p - dlc_header, 1),
    640    0  stevel 			"Security Parameter Index = 0x%x%x",
    641    0  stevel 			ntohs(spi_hi), ntohs(spi_low));
    642    0  stevel 	p += sizeof (spi_hi) + sizeof (spi_low);
    643    0  stevel 	this_ext_len -= sizeof (spi_hi) + sizeof (spi_low);
    644    0  stevel 
    645    0  stevel 	/* The rest is the authenticator; dump it in hex */
    646    0  stevel 	dumphex(p,
    647    0  stevel 		/* don't write past our string buffer ... */
    648    0  stevel 		(this_ext_len*3 > BUFLEN ? BUFLEN : this_ext_len),
    649    0  stevel 		auth_prn_str,
    650    0  stevel 		"Authenticator = %s");
    651    0  stevel }
    652    0  stevel 
    653    0  stevel static void key_ext(uint8_t type, uint8_t this_ext_len, uchar_t *p) {
    654    0  stevel 	uint16_t alg, spi_hi, spi_low;
    655    0  stevel 	char *alg_string;
    656    0  stevel 	char *hafa = (type == MN_HA_KEY ? "HA" : "FA");
    657    0  stevel 	char sec_msg[32];
    658    0  stevel 	char auth_prn_str[BUFLEN];
    659    0  stevel 
    660    0  stevel 	/* Algorithm Type */
    661    0  stevel 	(void) memcpy(&alg, p, sizeof (alg));
    662    0  stevel 	alg = ntohs(alg);
    663    0  stevel 	switch (alg) {
    664    0  stevel 	case KEY_ALG_NONE:
    665    0  stevel 	    alg_string = "None";
    666    0  stevel 	    break;
    667    0  stevel 	case SA_MD5_MODE_PREF_SUF:
    668    0  stevel 	    alg_string = "MD5/prefix+suffix";
    669    0  stevel 	    break;
    670    0  stevel 	case SA_HMAC_MD5:
    671    0  stevel 	    alg_string = "HMAC MD5";
    672    0  stevel 	    break;
    673    0  stevel 	default:
    674    0  stevel 	    alg_string = "Unknown";
    675    0  stevel 	    break;
    676    0  stevel 	}
    677    0  stevel 	(void) sprintf(get_line((char *)p-dlc_header, 1),
    678    0  stevel 			"Algorithm = 0x%x: %s", alg, alg_string);
    679    0  stevel 	p += sizeof (alg);
    680    0  stevel 	this_ext_len -= sizeof (alg);
    681    0  stevel 
    682    0  stevel 	/* AAA SPI */
    683    0  stevel 	GETSPI(p, spi_hi, spi_low);
    684    0  stevel 	(void) sprintf(get_line((char *)p - dlc_header, 1),
    685    0  stevel 			"AAA Security Parameter Index = 0x%x%x",
    686    0  stevel 			ntohs(spi_hi), ntohs(spi_low));
    687    0  stevel 	p += sizeof (spi_hi) + sizeof (spi_low);
    688    0  stevel 	this_ext_len -= sizeof (spi_hi) + sizeof (spi_low);
    689    0  stevel 
    690    0  stevel 	/* HA / FA SPI */
    691    0  stevel 	GETSPI(p, spi_hi, spi_low);
    692    0  stevel 	(void) sprintf(get_line((char *)p - dlc_header, 1),
    693    0  stevel 			"%s Security Parameter Index = 0x%x%x",
    694    0  stevel 			hafa, ntohs(spi_hi), ntohs(spi_low));
    695    0  stevel 	p += sizeof (spi_hi) + sizeof (spi_low);
    696    0  stevel 	this_ext_len -= sizeof (spi_hi) + sizeof (spi_low);
    697    0  stevel 
    698    0  stevel 	/* The rest is the security info; dump it in hex */
    699    0  stevel 	sprintf(sec_msg, "%s Security Info = %%s", hafa);
    700    0  stevel 	dumphex(p,
    701    0  stevel 		/* don't write past our string buffer ... */
    702    0  stevel 		(this_ext_len*3 > BUFLEN ? BUFLEN : this_ext_len),
    703    0  stevel 		auth_prn_str,
    704    0  stevel 		sec_msg);
    705    0  stevel }
    706    0  stevel 
    707    0  stevel /*ARGSUSED*/
    708    0  stevel static void trav_ext(uint8_t type, uint8_t this_ext_len, uchar_t *p) {
    709    0  stevel 	struct in_addr addr_temp;
    710    0  stevel 
    711    0  stevel 	/* skip reserved */
    712    0  stevel 	p += 2;
    713    0  stevel 	this_ext_len -= 2;
    714    0  stevel 
    715    0  stevel 	/* Mobile-Home Traversal Address */
    716    0  stevel 	(void) memcpy(&(addr_temp.s_addr), p, sizeof (addr_temp.s_addr));
    717    0  stevel 	(void) sprintf(get_line((char *)p-dlc_header, 1),
    718    0  stevel 			"Mobile-Home Traversal Address= %s, %s",
    719    0  stevel 			inet_ntoa(addr_temp),
    720    0  stevel 			addrtoname(AF_INET, &addr_temp));
    721    0  stevel 	p += sizeof (addr_temp.s_addr);
    722    0  stevel 	this_ext_len -= sizeof (addr_temp.s_addr);
    723    0  stevel 
    724    0  stevel 	/* Home-Mobile Traversal Address */
    725    0  stevel 	(void) memcpy(&(addr_temp.s_addr), p, sizeof (addr_temp.s_addr));
    726    0  stevel 	(void) sprintf(get_line((char *)p-dlc_header, 1),
    727    0  stevel 			"Home-Mobile Traversal Address= %s, %s",
    728    0  stevel 			inet_ntoa(addr_temp),
    729    0  stevel 			addrtoname(AF_INET, &addr_temp));
    730    0  stevel }
    731    0  stevel 
    732    0  stevel /*ARGSUSED*/
    733    0  stevel static void empty_ext(uint8_t type, uint8_t this_ext_len, uchar_t *p) {
    734    0  stevel 	/* no payload */
    735    0  stevel }
    736    0  stevel 
    737    0  stevel /*ARGSUSED*/
    738    0  stevel static void nai_ext(uint8_t type, uint8_t this_ext_len, uchar_t *p) {
    739    0  stevel 	/* payload points to the NAI */
    740    0  stevel 	char *desc = "Network Access Identifier = ";
    741    0  stevel 	size_t desclen = strlen(desc) + 1 + this_ext_len;
    742    0  stevel 
    743    0  stevel 	(void) snprintf(get_line((char *)p-dlc_header, 1),
    744    0  stevel 			desclen > MAXLINE ? MAXLINE : desclen,
    745    0  stevel 			"%s%s", desc, p);
    746    0  stevel }
    747    0  stevel 
    748    0  stevel /*ARGSUSED*/
    749    0  stevel static void chall_ext(uint8_t type, uint8_t this_ext_len, uchar_t *p) {
    750    0  stevel 	char	auth_prn_str[BUFLEN];
    751    0  stevel 
    752    0  stevel 	/* payload points to the challenge */
    753    0  stevel 	dumphex(p,
    754    0  stevel 		/* don't write past our string buffer ... */
    755    0  stevel 		(this_ext_len*3 > BUFLEN ? BUFLEN / 3 : this_ext_len),
    756    0  stevel 		auth_prn_str,
    757    0  stevel 		"Challenge = %s");
    758    0  stevel }
    759    0  stevel 
    760    0  stevel /*ARGSUSED*/
    761    0  stevel static void ma_ext(uint8_t type, uint8_t this_ext_len, uchar_t *p) {
    762    0  stevel 	mobagtadvext_t adv_ext[1];
    763    0  stevel 	int i, len;
    764    0  stevel 	struct in_addr temp_addr;
    765    0  stevel 
    766    0  stevel 	(void) memcpy(adv_ext, p - sizeof (exthdr_t), sizeof (*adv_ext));
    767    0  stevel 	(void) sprintf(get_line(0, 0), "Sequence number = %d",
    768    0  stevel 			ntohs(adv_ext->sequence_num));
    769    0  stevel 	(void) sprintf(get_line(0, 0),
    770    0  stevel 			"Registration lifetime = %d seconds",
    771    0  stevel 			ntohs(adv_ext->reg_lifetime));
    772    0  stevel 	if (adv_ext->reg_bit) {
    773    0  stevel 	    (void) sprintf(get_line(0, 0),
    774    0  stevel 				"1... .... = registration required "
    775    0  stevel 				"through FA");
    776    0  stevel 	} else {
    777    0  stevel 	    (void) sprintf(get_line(0, 0),
    778    0  stevel 				"0... .... = registration not required "
    779    0  stevel 				"through FA");
    780    0  stevel 	}
    781    0  stevel 	if (adv_ext->busy_bit) {
    782    0  stevel 	    (void) sprintf(get_line(0, 0), ".1.. .... = FA busy");
    783    0  stevel 	} else {
    784    0  stevel 	    (void) sprintf(get_line(0, 0), ".0.. .... = FA not busy");
    785    0  stevel 	}
    786    0  stevel 	if (adv_ext->ha_bit) {
    787    0  stevel 	    (void) sprintf(get_line(0, 0), "..1. .... = node is HA");
    788    0  stevel 	} else {
    789    0  stevel 	    (void) sprintf(get_line(0, 0), "..0. .... = node not HA");
    790    0  stevel 	}
    791    0  stevel 	if (adv_ext->fa_bit) {
    792    0  stevel 	    (void) sprintf(get_line(0, 0), "...1 .... = node is FA ");
    793    0  stevel 	} else {
    794    0  stevel 	    (void) sprintf(get_line(0, 0), "...0 .... = node not FA ");
    795    0  stevel 	}
    796    0  stevel 	if (adv_ext->minencap_bit) {
    797    0  stevel 	    (void) sprintf(get_line(0, 0), ".... 1... = minimal encapsulation "
    798    0  stevel 							"supported");
    799    0  stevel 	} else {
    800    0  stevel 	    (void) sprintf(get_line(0, 0),
    801    0  stevel 				".... 0... = no minimal encapsulation");
    802    0  stevel 	}
    803    0  stevel 	if (adv_ext->greencap_bit) {
    804    0  stevel 	    (void) sprintf(get_line(0, 0),
    805    0  stevel 				".... .1.. =  GRE encapsulation supported");
    806    0  stevel 	} else {
    807    0  stevel 	    (void) sprintf(get_line(0, 0),
    808    0  stevel 				".... .0.. = no GRE encapsulation");
    809    0  stevel 	}
    810    0  stevel 	if (adv_ext->vanjacob_hdr_comp_bit) {
    811    0  stevel 	    (void) sprintf(get_line(0, 0),
    812    0  stevel 				".... ..1. = VJ header compression");
    813    0  stevel 	} else {
    814    0  stevel 	    (void) sprintf(get_line(0, 0),
    815    0  stevel 				".... ..0. = no VJ header compression");
    816    0  stevel 	}
    817    0  stevel 	if (adv_ext->reverse_tunnel_bit) {
    818    0  stevel 	    (void) sprintf(get_line(0, 0),
    819    0  stevel 				".... ...1 = reverse tunneling supported");
    820    0  stevel 	} else {
    821    0  stevel 	    (void) sprintf(get_line(0, 0),
    822    0  stevel 				".... ...0 = no reverse tunneling");
    823    0  stevel 	}
    824    0  stevel 	(void) sprintf(get_line(0, 0),
    825    0  stevel 			"Reserved Byte = 0x%x", adv_ext->reserved);
    826    0  stevel 
    827    0  stevel 	/* Parse out COA's */
    828    0  stevel 	p += sizeof (*adv_ext);
    829    0  stevel 	len = this_ext_len + sizeof (exthdr_t);
    830    0  stevel 	/* this_ext_len is unsigned, and here we need a signed number */
    831    0  stevel 	len -= sizeof (*adv_ext);
    832    0  stevel 
    833    0  stevel 	for (i = 0; len >= sizeof (temp_addr.s_addr); i++) {
    834    0  stevel 	    memcpy(&(temp_addr.s_addr), p - sizeof (exthdr_t),
    835    0  stevel 		sizeof (temp_addr.s_addr));
    836    0  stevel 
    837    0  stevel 	    (void) sprintf(get_line(0, 0),
    838    0  stevel 				"Care of address-%d = %s, %s", i,
    839    0  stevel 				inet_ntoa(temp_addr),
    840    0  stevel 				addrtoname(AF_INET, &temp_addr));
    841    0  stevel 
    842    0  stevel 	    p += sizeof (temp_addr);
    843    0  stevel 	    len -= sizeof (temp_addr);
    844    0  stevel 	}
    845    0  stevel }
    846    0  stevel 
    847    0  stevel /*ARGSUSED*/
    848    0  stevel static void prefix_ext(uint8_t type, uint8_t this_ext_len, uchar_t *p) {
    849    0  stevel 	int i;
    850    0  stevel 
    851    0  stevel 	for (i = 0; i < this_ext_len; i++) {
    852    0  stevel 	    (void) sprintf(get_line(0, 0),
    853    0  stevel 				"Prefix length of router address[%d] "
    854    0  stevel 				"= %d bits",
    855    0  stevel 				i, p[i]);
    856    0  stevel 	}
    857    0  stevel }
    858    0  stevel 
    859    0  stevel /*ARGSUSED*/
    860    0  stevel static void unk_ext(uint8_t type, uint8_t this_ext_len, uchar_t *p) {
    861    0  stevel 	char	auth_prn_str[BUFLEN];
    862    0  stevel 
    863    0  stevel 	/* Unknown extension; just dump the rest of the payload */
    864    0  stevel 	dumphex(p,
    865    0  stevel 		/* don't write past our string buffer ... */
    866    0  stevel 		(this_ext_len*3 > BUFLEN ? BUFLEN : this_ext_len),
    867    0  stevel 		auth_prn_str,
    868    0  stevel 		"Payload = %s");
    869    0  stevel }
    870