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 2001-2002 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 <stdlib.h>
     31  0  stevel #include <string.h>
     32  0  stevel #include <sys/types.h>
     33  0  stevel #include <sys/socket.h>
     34  0  stevel #include <sys/sysmacros.h>
     35  0  stevel #include <net/ppp_defs.h>
     36  0  stevel #include <net/ppp-comp.h>
     37  0  stevel #include <net/if.h>
     38  0  stevel #include <netinet/in.h>
     39  0  stevel #include <netinet/if_ether.h>
     40  0  stevel #include <arpa/inet.h>
     41  0  stevel #include "snoop.h"
     42  0  stevel #include "snoop_ppp.h"
     43  0  stevel 
     44  0  stevel static int interpret_ppp_cp(int, uchar_t *, int, ppp_protoinfo_t *);
     45  0  stevel static int interpret_cp_options(uchar_t *, int, ppp_protoinfo_t *);
     46  0  stevel static int interpret_ppp_chap(int, uchar_t *, int, ppp_protoinfo_t *);
     47  0  stevel static int interpret_ppp_pap(int, uchar_t *, int, ppp_protoinfo_t *);
     48  0  stevel static int interpret_ppp_lqr(int, uchar_t *, int, ppp_protoinfo_t *);
     49  0  stevel static ppp_protoinfo_t *ppp_getprotoinfo(uint16_t);
     50  0  stevel static cp_optinfo_t *ppp_getoptinfo(cp_optinfo_t *, uint16_t);
     51  0  stevel static optformat_func_t opt_format_vendor;
     52  0  stevel static optformat_func_t opt_format_mru;
     53  0  stevel static optformat_func_t opt_format_accm;
     54  0  stevel static optformat_func_t opt_format_authproto;
     55  0  stevel static optformat_func_t opt_format_qualproto;
     56  0  stevel static optformat_func_t opt_format_magicnum;
     57  0  stevel static optformat_func_t opt_format_fcs;
     58  0  stevel static optformat_func_t opt_format_sdp;
     59  0  stevel static optformat_func_t opt_format_nummode;
     60  0  stevel static optformat_func_t opt_format_callback;
     61  0  stevel static optformat_func_t opt_format_mrru;
     62  0  stevel static optformat_func_t opt_format_epdisc;
     63  0  stevel static optformat_func_t opt_format_dce;
     64  0  stevel static optformat_func_t opt_format_linkdisc;
     65  0  stevel static optformat_func_t opt_format_i18n;
     66  0  stevel static optformat_func_t opt_format_ipaddresses;
     67  0  stevel static optformat_func_t opt_format_ipcompproto;
     68  0  stevel static optformat_func_t opt_format_ipaddress;
     69  0  stevel static optformat_func_t opt_format_mobileipv4;
     70  0  stevel static optformat_func_t opt_format_ifaceid;
     71  0  stevel static optformat_func_t opt_format_ipv6compproto;
     72  0  stevel static optformat_func_t opt_format_compoui;
     73  0  stevel static optformat_func_t opt_format_bsdcomp;
     74  0  stevel static optformat_func_t opt_format_staclzs;
     75  0  stevel static optformat_func_t opt_format_mppc;
     76  0  stevel static optformat_func_t opt_format_gandalf;
     77  0  stevel static optformat_func_t opt_format_lzsdcp;
     78  0  stevel static optformat_func_t opt_format_magnalink;
     79  0  stevel static optformat_func_t opt_format_deflate;
     80  0  stevel static optformat_func_t opt_format_encroui;
     81  0  stevel static optformat_func_t opt_format_dese;
     82  0  stevel static optformat_func_t opt_format_muxpid;
     83  0  stevel 
     84  0  stevel /*
     85  0  stevel  * Many strings below are initialized with "Unknown".
     86  0  stevel  */
     87  0  stevel static char unknown_string[] = "Unknown";
     88  0  stevel 
     89  0  stevel /*
     90  0  stevel  * Each known PPP protocol has an associated ppp_protoinfo_t in this array.
     91  0  stevel  * Even if we can't decode the protocol (interpret_proto() == NULL),
     92  0  stevel  * interpret_ppp() will at least print the protocol's name.  There is no
     93  0  stevel  * dependency on the ordering of the entries in this array.  They have been
     94  0  stevel  * ordered such that the most commonly used protocols are near the front.
     95  0  stevel  * The array is delimited by a last entry of protocol of type
     96  0  stevel  * PPP_PROTO_UNKNOWN.
     97  0  stevel  */
     98  0  stevel static ppp_protoinfo_t protoinfo_array[] = {
     99  0  stevel 	{ PPP_IP,	"IP",		interpret_ip,	NULL,	NULL },
    100  0  stevel 	{ PPP_IPV6,	"IPv6",		interpret_ipv6,	NULL,	NULL },
    101  0  stevel 	{ PPP_COMP,	"Compressed Data",	NULL,	NULL,	NULL },
    102  0  stevel 	{ PPP_OSI,	"OSI",			NULL,	NULL,	NULL },
    103  0  stevel 	{ PPP_AT,	"AppleTalk",		NULL,	NULL,	NULL },
    104  0  stevel 	{ PPP_IPX,	"IPX",			NULL,	NULL,	NULL },
    105  0  stevel 	{ PPP_VJC_COMP,	"VJ Compressed TCP",    NULL,	NULL,	NULL },
    106  0  stevel 	{ PPP_VJC_UNCOMP, "VJ Uncompressed TCP", NULL,	NULL,	NULL },
    107  0  stevel 	{ PPP_BRIDGE,	"Bridging",		NULL,	NULL,	NULL },
    108  0  stevel 	{ PPP_802HELLO,	"802.1d Hello",		NULL,	NULL,	NULL },
    109  0  stevel 	{ PPP_MP,	"MP",			NULL,	NULL,	NULL },
    110  0  stevel 	{ PPP_ENCRYPT,	"Encryption",		NULL,	NULL,	NULL },
    111  0  stevel 	{ PPP_ENCRYPTFRAG, "Individual Link Encryption", NULL,	NULL,	NULL },
    112  0  stevel 	{ PPP_MUX,	"PPP Muxing",		NULL,	NULL,	NULL },
    113  0  stevel 	{ PPP_COMPFRAG,	"Single Link Compressed Data",	NULL,	NULL,	NULL },
    114  0  stevel 	{ PPP_FULLHDR,	"IP Compression",	NULL,	NULL,	NULL },
    115  0  stevel 	{ PPP_COMPTCP,	"IP Compression",	NULL,	NULL,	NULL },
    116  0  stevel 	{ PPP_COMPNONTCP, "IP Compression",	NULL,	NULL,	NULL },
    117  0  stevel 	{ PPP_COMPUDP8,	"IP Compression",	NULL,	NULL,	NULL },
    118  0  stevel 	{ PPP_COMPRTP8,	"IP Compression",	NULL,	NULL,	NULL },
    119  0  stevel 	{ PPP_COMPTCPND, "IP Compression",	NULL,	NULL,	NULL },
    120  0  stevel 	{ PPP_COMPSTATE, "IP Compression",	NULL,	NULL,	NULL },
    121  0  stevel 	{ PPP_COMPUDP16, "IP Compression",	NULL,	NULL,	NULL },
    122  0  stevel 	{ PPP_COMPRTP16, "IP Compression",	NULL,	NULL,	NULL },
    123  0  stevel 	{ PPP_MPLS,	"MPLS",			NULL,	NULL,	NULL },
    124  0  stevel 	{ PPP_MPLSMC,	"MPLS M/C",		NULL,	NULL,	NULL },
    125  0  stevel 	{ PPP_LQR,	"LQR",		interpret_ppp_lqr,	"PPP-LQR:  ",
    126  0  stevel 	    "Link Quality Report" },
    127  0  stevel 	{ PPP_LCP,	"LCP",		interpret_ppp_cp,	"PPP-LCP:  ",
    128  0  stevel 	    "Link Control Protocol" },
    129  0  stevel 	{ PPP_IPCP,	"IPCP",		interpret_ppp_cp,	"PPP-IPCP: ",
    130  0  stevel 	    "IP Control Protocol" },
    131  0  stevel 	{ PPP_IPV6CP,	"IPV6CP",	interpret_ppp_cp,	"PPP-IPV6CP:  ",
    132  0  stevel 	    "IPv6 Control Protocol" },
    133  0  stevel 	{ PPP_CCP,	"CCP",		interpret_ppp_cp,	"PPP-CCP:  ",
    134  0  stevel 	    "Compression Control Protocol" },
    135  0  stevel 	{ PPP_CCPFRAG,	"CCP-Link",	interpret_ppp_cp, "PPP-CCP-Link:  ",
    136  0  stevel 	    "Per-Link Compression Control Protocol" },
    137  0  stevel 	{ PPP_ECP,	"ECP",		interpret_ppp_cp,	"PPP-ECP:  ",
    138  0  stevel 	    "Encryption Control Protocol" },
    139  0  stevel 	{ PPP_ECPFRAG,	"ECP-Link",	interpret_ppp_cp, "PPP-ECP-Link:  ",
    140  0  stevel 	    "Per-Link Encryption Control Protocol" },
    141  0  stevel 	{ PPP_MPLSCP,	"MPLSCP",		NULL,	NULL,	NULL },
    142  0  stevel 	{ PPP_OSINLCP,	"OSINLCP",		NULL,	NULL,	NULL },
    143  0  stevel 	{ PPP_ATCP,	"ATCP",			NULL,	NULL,	NULL },
    144  0  stevel 	{ PPP_IPXCP,	"IPXCP",		NULL,	NULL,	NULL },
    145  0  stevel 	{ PPP_BACP,	"BACP",			NULL,	NULL,	NULL },
    146  0  stevel 	{ PPP_BCP,	"BCP",			NULL,	NULL,	NULL },
    147  0  stevel 	{ PPP_CBCP,	"CBCP",			NULL,	NULL,	NULL },
    148  0  stevel 	{ PPP_BAP,	"BAP",			NULL,	NULL,	NULL },
    149  0  stevel 	{ PPP_CHAP,	"CHAP",		interpret_ppp_chap,	"CHAP:  ",
    150  0  stevel 	    "Challenge Handshake Authentication Protocl" },
    151  0  stevel 	{ PPP_PAP,	"PAP",		interpret_ppp_pap,	"PAP:   ",
    152  0  stevel 	    "Password Authentication Protocol" },
    153  0  stevel 	{ PPP_EAP,	"EAP",			NULL,	NULL,	NULL },
    154  0  stevel 	{ 0,		unknown_string,		NULL,	NULL,	NULL }
    155  0  stevel };
    156  0  stevel 
    157  0  stevel static cp_optinfo_t lcp_optinfo[] = {
    158  0  stevel 	{ OPT_LCP_VENDOR,	"Vendor-Specific",		6,
    159  0  stevel 	    opt_format_vendor },
    160  0  stevel 	{ OPT_LCP_MRU,		"Maximum-Receive-Unit",		4,
    161  0  stevel 	    opt_format_mru },
    162  0  stevel 	{ OPT_LCP_ASYNCMAP,	"Async-Control-Character-Map",	6,
    163  0  stevel 	    opt_format_accm },
    164  0  stevel 	{ OPT_LCP_AUTHTYPE,	"Authentication-Protocol",	4,
    165  0  stevel 	    opt_format_authproto },
    166  0  stevel 	{ OPT_LCP_QUALITY,	"Quality-Protocol",		4,
    167  0  stevel 	    opt_format_qualproto },
    168  0  stevel 	{ OPT_LCP_MAGICNUMBER,	"Magic-Number",			6,
    169  0  stevel 	    opt_format_magicnum },
    170  0  stevel 	{ OPT_LCP_PCOMPRESSION,	"Protocol-Field-Compression",	2,	NULL },
    171  0  stevel 	{ OPT_LCP_ACCOMPRESSION, "Address-and-Control-Field-Compression", 2,
    172  0  stevel 	    NULL },
    173  0  stevel 	{ OPT_LCP_FCSALTERN,	"FCS-Alternative",		3,
    174  0  stevel 	    opt_format_fcs },
    175  0  stevel 	{ OPT_LCP_SELFDESCPAD,	"Self-Describing-Padding",	3,
    176  0  stevel 	    opt_format_sdp },
    177  0  stevel 	{ OPT_LCP_NUMBERED,	"Numbered-Mode",		3,
    178  0  stevel 	    opt_format_nummode },
    179  0  stevel 	{ OPT_LCP_MULTILINKPROC, "Multi-Link-Procedure",	2,	NULL },
    180  0  stevel 	{ OPT_LCP_CALLBACK,	"Callback",			3,
    181  0  stevel 	    opt_format_callback },
    182  0  stevel 	{ OPT_LCP_CONNECTTIME,	"Connect-Time",			2,	NULL },
    183  0  stevel 	{ OPT_LCP_COMPOUNDFRAMES, "Compound-Frames",		2,	NULL },
    184  0  stevel 	{ OPT_LCP_DATAENCAP,	"Nominal-Data-Encapsulation",	2,	NULL },
    185  0  stevel 	{ OPT_LCP_MRRU,		"Multilink-MRRU",		4,
    186  0  stevel 	    opt_format_mrru },
    187  0  stevel 	{ OPT_LCP_SSNHF,	"Multilink-Short-Sequence-Number-Header-Format",
    188  0  stevel 	    2, NULL },
    189  0  stevel 	{ OPT_LCP_EPDISC,	"Multilink-Endpoint-Discriminator",	3,
    190  0  stevel 	    opt_format_epdisc },
    191  0  stevel 	{ OPT_LCP_DCEIDENT,	"DCE-Identifier",		3,
    192  0  stevel 	    opt_format_dce },
    193  0  stevel 	{ OPT_LCP_MLPLUSPROC,	"Multi-Link-Plus-Procedure",	2,	NULL },
    194  0  stevel 	{ OPT_LCP_LINKDISC,	"Link Discriminator for BACP",	4,
    195  0  stevel 	    opt_format_linkdisc },
    196  0  stevel 	{ OPT_LCP_AUTH,		"LCP-Authentication-Option",	2,	NULL },
    197  0  stevel 	{ OPT_LCP_COBS,		"COBS",				2,	NULL },
    198  0  stevel 	{ OPT_LCP_PFXELISION,	"Prefix elision",		2,	NULL },
    199  0  stevel 	{ OPT_LCP_MPHDRFMT,	"Multilink header format",	2,	NULL },
    200  0  stevel 	{ OPT_LCP_I18N,		"Internationalization",		6,
    201  0  stevel 	    opt_format_i18n },
    202  0  stevel 	{ OPT_LCP_SDL,		"Simple Data Link on SONET/SDH", 2,	NULL },
    203  0  stevel 	{ OPT_LCP_MUXING,	"Old PPP Multiplexing",		2,	NULL },
    204  0  stevel 	{ 0,			unknown_string,			0,	NULL }
    205  0  stevel };
    206  0  stevel 
    207  0  stevel static cp_optinfo_t ipcp_optinfo[] = {
    208  0  stevel 	{ OPT_IPCP_ADDRS,	"IP-Addresses",			10,
    209  0  stevel 	    opt_format_ipaddresses },
    210  0  stevel 	{ OPT_IPCP_COMPRESSTYPE, "IP-Compression-Protocol",	4,
    211  0  stevel 	    opt_format_ipcompproto },
    212  0  stevel 	{ OPT_IPCP_ADDR,	"IP-Address",			6,
    213  0  stevel 	    opt_format_ipaddress },
    214  0  stevel 	{ OPT_IPCP_MOBILEIPV4,	"Mobile-IPv4",			6,
    215  0  stevel 	    opt_format_mobileipv4 },
    216  0  stevel 	{ OPT_IPCP_DNS1,	"Primary DNS Address",		6,
    217  0  stevel 	    opt_format_ipaddress },
    218  0  stevel 	{ OPT_IPCP_NBNS1,	"Primary NBNS Address",		6,
    219  0  stevel 	    opt_format_ipaddress },
    220  0  stevel 	{ OPT_IPCP_DNS2,	"Secondary DNS Address", 	6,
    221  0  stevel 	    opt_format_ipaddress },
    222  0  stevel 	{ OPT_IPCP_NBNS2,	"Secondary NBNS Address",	6,
    223  0  stevel 	    opt_format_ipaddress },
    224  0  stevel 	{ OPT_IPCP_SUBNET,	"IP-Subnet",			6,
    225  0  stevel 	    opt_format_ipaddress },
    226  0  stevel 	{ 0,			unknown_string,			0,	NULL }
    227  0  stevel };
    228  0  stevel 
    229  0  stevel static cp_optinfo_t ipv6cp_optinfo[] = {
    230  0  stevel 	{ OPT_IPV6CP_IFACEID,	"Interface-Identifier",		10,
    231  0  stevel 	    opt_format_ifaceid },
    232  0  stevel 	{ OPT_IPV6CP_COMPRESSTYPE, "IPv6-Compression-Protocol",	4,
    233  0  stevel 	    opt_format_ipv6compproto },
    234  0  stevel 	{ 0,			unknown_string,			0,	NULL }
    235  0  stevel };
    236  0  stevel 
    237  0  stevel static cp_optinfo_t ccp_optinfo[] = {
    238  0  stevel 	{ OPT_CCP_PROPRIETARY,	"Proprietary Compression OUI",	6,
    239  0  stevel 	    opt_format_compoui },
    240  0  stevel 	{ OPT_CCP_PREDICTOR1,	"Predictor type 1",		2,	NULL },
    241  0  stevel 	{ OPT_CCP_PREDICTOR2,	"Predictor type 2",		2,	NULL },
    242  0  stevel 	{ OPT_CCP_PUDDLEJUMP,	"Puddle Jumper",		2,	NULL },
    243  0  stevel 	{ OPT_CCP_HPPPC,	"Hewlett-Packard PPC",		2,	NULL },
    244  0  stevel 	{ OPT_CCP_STACLZS,	"Stac Electronics LZS",		5,
    245  0  stevel 	    opt_format_staclzs },
    246  0  stevel 	{ OPT_CCP_MPPC,		"Microsoft PPC",		6,
    247  0  stevel 	    opt_format_mppc },
    248  0  stevel 	{ OPT_CCP_GANDALFFZA,	"Gandalf FZA",			3,
    249  0  stevel 	    opt_format_gandalf },
    250  0  stevel 	{ OPT_CCP_V42BIS,	"V.42bis compression",		2,
    251  0  stevel 	    NULL },
    252  0  stevel 	{ OPT_CCP_BSDCOMP,	"BSD LZW Compress",		3,
    253  0  stevel 	    opt_format_bsdcomp },
    254  0  stevel 	{ OPT_CCP_LZSDCP,	"LZS-DCP",			6,
    255  0  stevel 	    opt_format_lzsdcp },
    256  0  stevel 	{ OPT_CCP_MAGNALINK,	"Magnalink",			4,
    257  0  stevel 	    opt_format_magnalink },
    258  0  stevel 	{ OPT_CCP_DEFLATE,	"Deflate",			4,
    259  0  stevel 	    opt_format_deflate },
    260  0  stevel 	{ 0,			unknown_string,			0,	NULL }
    261  0  stevel };
    262  0  stevel 
    263  0  stevel static cp_optinfo_t ecp_optinfo[] = {
    264  0  stevel 	{ OPT_ECP_PROPRIETARY,	"Proprietary Encryption OUI",	6,
    265  0  stevel 	    opt_format_encroui },
    266  0  stevel 	{ OPT_ECP_DESE,		"DESE",				10,
    267  0  stevel 	    opt_format_dese },
    268  0  stevel 	{ OPT_ECP_3DESE,	"3DESE",			10,
    269  0  stevel 	    opt_format_dese },
    270  0  stevel 	{ OPT_ECP_DESEBIS,	"DESE-bis",			10,
    271  0  stevel 	    opt_format_dese },
    272  0  stevel 	{ 0,			unknown_string,			0,	NULL }
    273  0  stevel };
    274  0  stevel 
    275  0  stevel static cp_optinfo_t muxcp_optinfo[] = {
    276  0  stevel 	{ OPT_MUXCP_DEFAULTPID,	"Default PID",			4,
    277  0  stevel 	    opt_format_muxpid },
    278  0  stevel 	{ 0,			unknown_string,			0,	NULL }
    279  0  stevel };
    280  0  stevel 
    281  0  stevel static char *cp_codearray[] = {
    282  0  stevel 	"(Vendor Specific)",
    283  0  stevel 	"(Configure-Request)",
    284  0  stevel 	"(Configure-Ack)",
    285  0  stevel 	"(Configure-Nak)",
    286  0  stevel 	"(Configure-Reject)",
    287  0  stevel 	"(Terminate-Request)",
    288  0  stevel 	"(Terminate-Ack)",
    289  0  stevel 	"(Code-Reject)",
    290  0  stevel 	"(Protocol-Reject)",
    291  0  stevel 	"(Echo-Request)",
    292  0  stevel 	"(Echo-Reply)",
    293  0  stevel 	"(Discard-Request)",
    294  0  stevel 	"(Identification)",
    295  0  stevel 	"(Time-Remaining)",
    296  0  stevel 	"(Reset-Request)",
    297  0  stevel 	"(Reset-Ack)"
    298  0  stevel };
    299  0  stevel #define	MAX_CPCODE	((sizeof (cp_codearray) / sizeof (char *)) - 1)
    300  0  stevel 
    301  0  stevel static char *pap_codearray[] = {
    302  0  stevel 	"(Unknown)",
    303  0  stevel 	"(Authenticate-Request)",
    304  0  stevel 	"(Authenticate-Ack)",
    305  0  stevel 	"(Authenticate-Nak)"
    306  0  stevel };
    307  0  stevel #define	MAX_PAPCODE	((sizeof (pap_codearray) / sizeof (char *)) - 1)
    308  0  stevel 
    309  0  stevel static char *chap_codearray[] = {
    310  0  stevel 	"(Unknown)",
    311  0  stevel 	"(Challenge)",
    312  0  stevel 	"(Response)",
    313  0  stevel 	"(Success)",
    314  0  stevel 	"(Failure)"
    315  0  stevel };
    316  0  stevel #define	MAX_CHAPCODE	((sizeof (chap_codearray) / sizeof (char *)) - 1)
    317  0  stevel 
    318  0  stevel 
    319  0  stevel int
    320  0  stevel interpret_ppp(int flags, uchar_t *data, int len)
    321  0  stevel {
    322  0  stevel 	uint16_t protocol;
    323  0  stevel 	ppp_protoinfo_t *protoinfo;
    324  0  stevel 	uchar_t *payload = data;
    325  0  stevel 
    326  0  stevel 	if (len < 2)
    327  0  stevel 		return (len);
    328  0  stevel 
    329  0  stevel 	GETINT16(protocol, payload);
    330  0  stevel 	len -= sizeof (uint16_t);
    331  0  stevel 
    332  0  stevel 	protoinfo = ppp_getprotoinfo(protocol);
    333  0  stevel 
    334  0  stevel 	if (flags & F_SUM) {
    335  0  stevel 		(void) sprintf(get_sum_line(),
    336  0  stevel 		    "PPP Protocol=0x%x (%s)", protocol, protoinfo->name);
    337  0  stevel 	} else { /* F_DTAIL */
    338  0  stevel 		show_header("PPP:    ", "Point-to-Point Protocol", len);
    339  0  stevel 		show_space();
    340  0  stevel 		(void) sprintf(get_line(0, 0), "Protocol = 0x%x (%s)",
    341  0  stevel 		    protocol, protoinfo->name);
    342  0  stevel 		show_space();
    343  0  stevel 	}
    344  0  stevel 
    345  0  stevel 	if (protoinfo->interpret_proto != NULL) {
    346  0  stevel 		len = protoinfo->interpret_proto(flags, payload, len,
    347  0  stevel 		    protoinfo);
    348  0  stevel 	}
    349  0  stevel 
    350  0  stevel 	return (len);
    351  0  stevel }
    352  0  stevel 
    353  0  stevel /*
    354  0  stevel  * interpret_ppp_cp() - Interpret PPP control protocols.  It is convenient
    355  0  stevel  * to do some of the decoding of these protocols in a common function since
    356  0  stevel  * they share packet formats.  This function expects to receive data
    357  0  stevel  * starting with the code field.
    358  0  stevel  */
    359  0  stevel static int
    360  0  stevel interpret_ppp_cp(int flags, uchar_t *data, int len, ppp_protoinfo_t *protoinfo)
    361  0  stevel {
    362  0  stevel 	uint8_t code;
    363  0  stevel 	uint8_t id;
    364  0  stevel 	char *codestr;
    365  0  stevel 	uint16_t length;
    366  0  stevel 	uchar_t *datap = data;
    367  0  stevel 
    368  0  stevel 	if (len < sizeof (ppp_pkt_t))
    369  0  stevel 		return (len);
    370  0  stevel 
    371  0  stevel 	GETINT8(code, datap);
    372  0  stevel 	GETINT8(id, datap);
    373  0  stevel 	GETINT16(length, datap);
    374  0  stevel 
    375  0  stevel 	len -= sizeof (ppp_pkt_t);
    376  0  stevel 
    377  0  stevel 	if (code <= MAX_CPCODE)
    378  0  stevel 		codestr = cp_codearray[code];
    379  0  stevel 	else
    380  0  stevel 		codestr = "";
    381  0  stevel 
    382  0  stevel 	if (flags & F_SUM) {
    383  0  stevel 		(void) sprintf(get_sum_line(),
    384  0  stevel 		    "%s%s", protoinfo->prefix, codestr);
    385  0  stevel 	} else { /* (flags & F_DTAIL) */
    386  0  stevel 		show_header(protoinfo->prefix, protoinfo->description, len);
    387  0  stevel 		show_space();
    388  0  stevel 
    389  0  stevel 		(void) sprintf(get_line(0, 0), "Code = %d %s", code, codestr);
    390  0  stevel 		(void) sprintf(get_line(0, 0), "Identifier = %d", id);
    391  0  stevel 		(void) sprintf(get_line(0, 0), "Length = %d", length);
    392  0  stevel 
    393  0  stevel 		show_space();
    394  0  stevel 
    395  0  stevel 		len = MIN(len, length - sizeof (ppp_pkt_t));
    396  0  stevel 		if (len == 0)
    397  0  stevel 			return (len);
    398  0  stevel 
    399  0  stevel 		switch (code) {
    400  0  stevel 		case CODE_VENDOR: {
    401  0  stevel 			uint32_t magicnum;
    402  0  stevel 			uint32_t oui;
    403  0  stevel 			char *ouistr;
    404  0  stevel 			uint8_t kind;
    405  0  stevel 
    406  0  stevel 			if (len < sizeof (magicnum) + sizeof (oui))
    407  0  stevel 				return (len);
    408  0  stevel 
    409  0  stevel 			GETINT32(magicnum, datap);
    410  0  stevel 			(void) sprintf(get_line(0, 0), "Magic-Number = 0x%08x",
    411  0  stevel 			    magicnum);
    412  0  stevel 
    413  0  stevel 			GETINT32(oui, datap);
    414  0  stevel 			kind = oui & 0x000000ff;
    415  0  stevel 			oui >>= 8;
    416  0  stevel 
    417  0  stevel 			ouistr = ether_ouiname(oui);
    418  0  stevel 			if (ouistr == NULL)
    419  0  stevel 				ouistr = unknown_string;
    420  0  stevel 
    421  0  stevel 			(void) sprintf(get_line(0, 0), "OUI = 0x%06x (%s)",
    422  0  stevel 			    oui, ouistr);
    423  0  stevel 			(void) sprintf(get_line(0, 0), "Kind = %d", kind);
    424  0  stevel 			show_space();
    425  0  stevel 			break;
    426  0  stevel 		}
    427  0  stevel 
    428  0  stevel 		case CODE_CONFREQ:
    429  0  stevel 		case CODE_CONFACK:
    430  0  stevel 		case CODE_CONFNAK:
    431  0  stevel 		case CODE_CONFREJ:
    432  0  stevel 			/*
    433  0  stevel 			 * The above all contain protocol specific
    434  0  stevel 			 * configuration options.  Parse these options.
    435  0  stevel 			 */
    436  0  stevel 			interpret_cp_options(datap, len, protoinfo);
    437  0  stevel 			break;
    438  0  stevel 
    439  0  stevel 		case CODE_TERMREQ:
    440  0  stevel 		case CODE_TERMACK:
    441  0  stevel 			/*
    442  0  stevel 			 * The arbitrary data in these two packet types
    443  0  stevel 			 * is almost always plain text.  Print it as such.
    444  0  stevel 			 */
    445  0  stevel 			(void) sprintf(get_line(0, 0), "Data = %.*s",
    446  0  stevel 			    length - sizeof (ppp_pkt_t), datap);
    447  0  stevel 			show_space();
    448  0  stevel 			break;
    449  0  stevel 
    450  0  stevel 		case CODE_CODEREJ:
    451  0  stevel 			/*
    452  0  stevel 			 * What follows is the rejected control protocol
    453  0  stevel 			 * packet, starting with the code field.
    454  0  stevel 			 * Conveniently, we can call interpret_ppp_cp() to
    455  0  stevel 			 * decode this.
    456  0  stevel 			 */
    457  0  stevel 			prot_nest_prefix = protoinfo->prefix;
    458  0  stevel 			interpret_ppp_cp(flags, datap, len, protoinfo);
    459  0  stevel 			prot_nest_prefix = "";
    460  0  stevel 			break;
    461  0  stevel 
    462  0  stevel 		case CODE_PROTREJ:
    463  0  stevel 			/*
    464  0  stevel 			 * We don't print the rejected-protocol field
    465  0  stevel 			 * explicitely.  Instead, we cheat and pretend that
    466  0  stevel 			 * the rejected-protocol field is actually the
    467  0  stevel 			 * protocol field in the included PPP packet.  This
    468  0  stevel 			 * way, we can invoke interpret_ppp() and have it
    469  0  stevel 			 * treat the included packet normally.
    470  0  stevel 			 */
    471  0  stevel 			prot_nest_prefix = protoinfo->prefix;
    472  0  stevel 			interpret_ppp(flags, datap, len);
    473  0  stevel 			prot_nest_prefix = "";
    474  0  stevel 			break;
    475  0  stevel 
    476  0  stevel 		case CODE_ECHOREQ:
    477  0  stevel 		case CODE_ECHOREP:
    478  0  stevel 		case CODE_DISCREQ:
    479  0  stevel 		case CODE_IDENT:
    480  0  stevel 		case CODE_TIMEREMAIN: {
    481  0  stevel 			uint32_t magicnum;
    482  0  stevel 			char *message_label = "Identification = %.*s";
    483  0  stevel 
    484  0  stevel 			if (len < sizeof (uint32_t))
    485  0  stevel 				break;
    486  0  stevel 
    487  0  stevel 			GETINT32(magicnum, datap);
    488  0  stevel 			len -= sizeof (uint32_t);
    489  0  stevel 			(void) sprintf(get_line(0, 0), "Magic-Number = 0x%08x",
    490  0  stevel 			    magicnum);
    491  0  stevel 			/*
    492  0  stevel 			 * Unless this is an identification or
    493  0  stevel 			 * time-remaining packet, arbitrary data follows
    494  0  stevel 			 * the magic number field.  The user can take a
    495  0  stevel 			 * look at the hex dump for enlightenment.
    496  0  stevel 			 */
    497  0  stevel 			if (code == CODE_TIMEREMAIN) {
    498  0  stevel 				uint32_t timeremaining;
    499  0  stevel 
    500  0  stevel 				if (len < sizeof (uint32_t))
    501  0  stevel 					break;
    502  0  stevel 
    503  0  stevel 				message_label = "Message = %.*s";
    504  0  stevel 
    505  0  stevel 				GETINT32(timeremaining, datap);
    506  0  stevel 				len -= sizeof (uint32_t);
    507  0  stevel 				(void) sprintf(get_line(0, 0),
    508  0  stevel 				    "Seconds Remaining = %d", timeremaining);
    509  0  stevel 			}
    510  0  stevel 
    511  0  stevel 			if (code == CODE_IDENT || code == CODE_TIMEREMAIN) {
    512  0  stevel 				if (len == 0)
    513  0  stevel 					break;
    514  0  stevel 
    515  0  stevel 				(void) sprintf(get_line(0, 0), message_label,
    516  0  stevel 				    len, datap);
    517  0  stevel 			}
    518  0  stevel 			show_space();
    519  0  stevel 			break;
    520  0  stevel 		}
    521  0  stevel 
    522  0  stevel 		/*
    523  0  stevel 		 * Reset-Request and Reset-Ack contain arbitrary data which
    524  0  stevel 		 * the user can sift through using the -x option.
    525  0  stevel 		 */
    526  0  stevel 		case CODE_RESETREQ:
    527  0  stevel 		case CODE_RESETACK:
    528  0  stevel 		default:
    529  0  stevel 			break;
    530  0  stevel 		}
    531  0  stevel 	}
    532  0  stevel 	return (len);
    533  0  stevel }
    534  0  stevel 
    535  0  stevel 
    536  0  stevel /*
    537  0  stevel  * interpret_cp_options() decodes control protocol configuration options.
    538  0  stevel  * Since each control protocol has a different set of options whose type
    539  0  stevel  * numbers overlap, the protoinfo parameter is used to get a handle on
    540  0  stevel  * which option set to use for decoding.
    541  0  stevel  */
    542  0  stevel static int
    543  0  stevel interpret_cp_options(uchar_t *optptr, int len, ppp_protoinfo_t *protoinfo)
    544  0  stevel {
    545  0  stevel 	cp_optinfo_t *optinfo;
    546  0  stevel 	cp_optinfo_t *optinfo_ptr;
    547  0  stevel 	uint8_t optlen;
    548  0  stevel 	uint8_t opttype;
    549  0  stevel 
    550  0  stevel 	switch (protoinfo->proto) {
    551  0  stevel 	case PPP_LCP:
    552  0  stevel 		optinfo = lcp_optinfo;
    553  0  stevel 		break;
    554  0  stevel 	case PPP_IPCP:
    555  0  stevel 		optinfo = ipcp_optinfo;
    556  0  stevel 		break;
    557  0  stevel 	case PPP_IPV6CP:
    558  0  stevel 		optinfo = ipv6cp_optinfo;
    559  0  stevel 		break;
    560  0  stevel 	case PPP_CCP:
    561  0  stevel 		optinfo = ccp_optinfo;
    562  0  stevel 		break;
    563  0  stevel 	case PPP_ECP:
    564  0  stevel 		optinfo = ecp_optinfo;
    565  0  stevel 		break;
    566  0  stevel 	case PPP_MUXCP:
    567  0  stevel 		optinfo = muxcp_optinfo;
    568  0  stevel 		break;
    569  0  stevel 	default:
    570  0  stevel 		return (len);
    571  0  stevel 		break;
    572  0  stevel 	}
    573  0  stevel 
    574  0  stevel 	if (len >= 2) {
    575  0  stevel 		(void) sprintf(get_line(0, 0), "%s Configuration Options",
    576  0  stevel 		    protoinfo->name);
    577  0  stevel 		show_space();
    578  0  stevel 	}
    579  0  stevel 
    580  0  stevel 	while (len >= 2) {
    581  0  stevel 		GETINT8(opttype, optptr);
    582  0  stevel 		GETINT8(optlen, optptr);
    583  0  stevel 
    584  0  stevel 		optinfo_ptr = ppp_getoptinfo(optinfo, opttype);
    585  0  stevel 
    586  0  stevel 		(void) sprintf(get_line(0, 0), "Option Type = %d (%s)", opttype,
    587  0  stevel 		    optinfo_ptr->opt_name);
    588  0  stevel 		(void) sprintf(get_line(0, 0), "Option Length = %d", optlen);
    589  0  stevel 
    590  0  stevel 		/*
    591  0  stevel 		 * Don't continue if there isn't enough data to
    592  0  stevel 		 * contain this option, or if this type of option
    593  0  stevel 		 * should contain more data than the length field
    594  0  stevel 		 * claims there is.
    595  0  stevel 		 */
    596  0  stevel 		if (optlen > len || optlen < optinfo_ptr->opt_minsize) {
    597  0  stevel 			(void) sprintf(get_line(0, 0),
    598  0  stevel 			    "Warning: Incomplete Option");
    599  0  stevel 			show_space();
    600  0  stevel 			break;
    601  0  stevel 		}
    602  0  stevel 
    603  0  stevel 		if (optinfo_ptr->opt_formatdata != NULL) {
    604  0  stevel 			optinfo_ptr->opt_formatdata(optptr,
    605  0  stevel 			    MIN(optlen - 2, len - 2));
    606  0  stevel 		}
    607  0  stevel 
    608  0  stevel 		len -= optlen;
    609  0  stevel 		optptr += optlen - 2;
    610  0  stevel 
    611  0  stevel 		show_space();
    612  0  stevel 	}
    613  0  stevel 
    614  0  stevel 	return (len);
    615  0  stevel }
    616  0  stevel 
    617  0  stevel static int
    618  0  stevel interpret_ppp_chap(int flags, uchar_t *data, int len,
    619  0  stevel     ppp_protoinfo_t *protoinfo)
    620  0  stevel {
    621  0  stevel 	uint8_t code;
    622  0  stevel 	uint8_t id;
    623  0  stevel 	char *codestr;
    624  0  stevel 	uint16_t length;
    625  0  stevel 	int lengthleft;
    626  0  stevel 	uchar_t *datap = data;
    627  0  stevel 
    628  0  stevel 
    629  0  stevel 	if (len < sizeof (ppp_pkt_t))
    630  0  stevel 		return (len);
    631  0  stevel 
    632  0  stevel 	GETINT8(code, datap);
    633  0  stevel 	GETINT8(id, datap);
    634  0  stevel 	GETINT8(length, datap);
    635  0  stevel 
    636  0  stevel 	if (code <= MAX_CHAPCODE)
    637  0  stevel 		codestr = chap_codearray[code];
    638  0  stevel 	else
    639  0  stevel 		codestr = "";
    640  0  stevel 
    641  0  stevel 	if (flags & F_SUM) {
    642  0  stevel 		(void) sprintf(get_sum_line(),
    643  0  stevel 		    "%s%s", protoinfo->prefix, codestr);
    644  0  stevel 	} else { /* (flags & F_DTAIL) */
    645  0  stevel 		show_header(protoinfo->prefix, protoinfo->description, len);
    646  0  stevel 		show_space();
    647  0  stevel 
    648  0  stevel 		(void) sprintf(get_line(0, 0), "Code = %d %s", code, codestr);
    649  0  stevel 		(void) sprintf(get_line(0, 0), "Identifier = %d", id);
    650  0  stevel 		(void) sprintf(get_line(0, 0), "Length = %d", length);
    651  0  stevel 
    652  0  stevel 		show_space();
    653  0  stevel 
    654  0  stevel 		if (len < length)
    655  0  stevel 			return (len);
    656  0  stevel 
    657  0  stevel 		lengthleft = len - sizeof (ppp_pkt_t);
    658  0  stevel 
    659  0  stevel 		switch (code) {
    660  0  stevel 		case CODE_CHALLENGE:
    661  0  stevel 		case CODE_RESPONSE: {
    662  0  stevel 			uint8_t value_size;
    663  0  stevel 			uint16_t peername_size;
    664  0  stevel 
    665  0  stevel 			if (lengthleft < sizeof (value_size))
    666  0  stevel 				break;
    667  0  stevel 
    668  0  stevel 			GETINT8(value_size, datap);
    669  0  stevel 			lengthleft -= sizeof (value_size);
    670  0  stevel 			(void) sprintf(get_line(0, 0), "Value-Size = %d",
    671  0  stevel 			    value_size);
    672  0  stevel 
    673  0  stevel 			if (lengthleft < sizeof (peername_size))
    674  0  stevel 				break;
    675  0  stevel 			peername_size = MIN(length - sizeof (ppp_pkt_t) -
    676  0  stevel 			    value_size, lengthleft);
    677  0  stevel 			(void) sprintf(get_line(0, 0), "Name = %.*s",
    678  0  stevel 			    peername_size, datap + value_size);
    679  0  stevel 
    680  0  stevel 			break;
    681  0  stevel 		}
    682  0  stevel 		case CODE_SUCCESS:
    683  0  stevel 		case CODE_FAILURE: {
    684  0  stevel 			uint16_t message_size = MIN(length - sizeof (ppp_pkt_t),
    685  0  stevel 			    lengthleft);
    686  0  stevel 
    687  0  stevel 			(void) sprintf(get_line(0, 0), "Message = %.*s",
    688  0  stevel 			    message_size, datap);
    689  0  stevel 			break;
    690  0  stevel 		}
    691  0  stevel 		default:
    692  0  stevel 			break;
    693  0  stevel 		}
    694  0  stevel 	}
    695  0  stevel 
    696  0  stevel 	show_space();
    697  0  stevel 	len -= length;
    698  0  stevel 	return (len);
    699  0  stevel }
    700  0  stevel 
    701  0  stevel static int
    702  0  stevel interpret_ppp_pap(int flags, uchar_t *data, int len,
    703  0  stevel     ppp_protoinfo_t *protoinfo)
    704  0  stevel {
    705  0  stevel 	uint8_t code;
    706  0  stevel 	uint8_t id;
    707  0  stevel 	char *codestr;
    708  0  stevel 	uint16_t length;
    709  0  stevel 	int lengthleft;
    710  0  stevel 	uchar_t *datap = data;
    711  0  stevel 
    712  0  stevel 	if (len < sizeof (ppp_pkt_t))
    713  0  stevel 		return (len);
    714  0  stevel 
    715  0  stevel 	GETINT8(code, datap);
    716  0  stevel 	GETINT8(id, datap);
    717  0  stevel 	GETINT16(length, datap);
    718  0  stevel 
    719  0  stevel 	lengthleft = len - sizeof (ppp_pkt_t);
    720  0  stevel 
    721  0  stevel 	if (code <= MAX_PAPCODE)
    722  0  stevel 		codestr = pap_codearray[code];
    723  0  stevel 	else
    724  0  stevel 		codestr = "";
    725  0  stevel 
    726  0  stevel 	if (flags & F_SUM) {
    727  0  stevel 		(void) sprintf(get_sum_line(),
    728  0  stevel 		    "%s%s", protoinfo->prefix, codestr);
    729  0  stevel 	} else { /* (flags & F_DTAIL) */
    730  0  stevel 		show_header(protoinfo->prefix, protoinfo->description, len);
    731  0  stevel 		show_space();
    732  0  stevel 
    733  0  stevel 		(void) sprintf(get_line(0, 0), "Code = %d %s", code, codestr);
    734  0  stevel 		(void) sprintf(get_line(0, 0), "Identifier = %d", id);
    735  0  stevel 		(void) sprintf(get_line(0, 0), "Length = %d", length);
    736  0  stevel 
    737  0  stevel 		show_space();
    738  0  stevel 
    739  0  stevel 		if (len < length)
    740  0  stevel 			return (len);
    741  0  stevel 
    742  0  stevel 		switch (code) {
    743  0  stevel 		case CODE_AUTHREQ: {
    744  0  stevel 			uint8_t fieldlen;
    745  0  stevel 
    746  0  stevel 			if (lengthleft < sizeof (fieldlen))
    747  0  stevel 				break;
    748  0  stevel 			GETINT8(fieldlen, datap);
    749  0  stevel 			(void) sprintf(get_line(0, 0), "Peer-Id Length = %d",
    750  0  stevel 			    fieldlen);
    751  0  stevel 			lengthleft -= sizeof (fieldlen);
    752  0  stevel 
    753  0  stevel 			if (lengthleft < fieldlen)
    754  0  stevel 				break;
    755  0  stevel 			(void) sprintf(get_line(0, 0), "Peer-Id = %.*s",
    756  0  stevel 			    fieldlen, datap);
    757  0  stevel 			lengthleft -= fieldlen;
    758  0  stevel 
    759  0  stevel 			datap += fieldlen;
    760  0  stevel 
    761  0  stevel 			if (lengthleft < sizeof (fieldlen))
    762  0  stevel 				break;
    763  0  stevel 			GETINT8(fieldlen, datap);
    764  0  stevel 			(void) sprintf(get_line(0, 0), "Password Length = %d",
    765  0  stevel 			    fieldlen);
    766  0  stevel 			lengthleft -= sizeof (fieldlen);
    767  0  stevel 
    768  0  stevel 			if (lengthleft < fieldlen)
    769  0  stevel 				break;
    770  0  stevel 			(void) sprintf(get_line(0, 0), "Password = %.*s",
    771  0  stevel 			    fieldlen, datap);
    772  0  stevel 
    773  0  stevel 			break;
    774  0  stevel 		}
    775  0  stevel 		case CODE_AUTHACK:
    776  0  stevel 		case CODE_AUTHNAK: {
    777  0  stevel 			uint8_t msglen;
    778  0  stevel 
    779  0  stevel 			if (lengthleft < sizeof (msglen))
    780  0  stevel 				break;
    781  0  stevel 			GETINT8(msglen, datap);
    782  0  stevel 			(void) sprintf(get_line(0, 0), "Msg-Length = %d",
    783  0  stevel 			    msglen);
    784  0  stevel 			lengthleft -= sizeof (msglen);
    785  0  stevel 
    786  0  stevel 			if (lengthleft < msglen)
    787  0  stevel 				break;
    788  0  stevel 			(void) sprintf(get_line(0, 0), "Message = %.*s",
    789  0  stevel 			    msglen, datap);
    790  0  stevel 
    791  0  stevel 			break;
    792  0  stevel 		}
    793  0  stevel 		default:
    794  0  stevel 			break;
    795  0  stevel 		}
    796  0  stevel 	}
    797  0  stevel 
    798  0  stevel 	show_space();
    799  0  stevel 	len -= length;
    800  0  stevel 	return (len);
    801  0  stevel }
    802  0  stevel 
    803  0  stevel 
    804  0  stevel static int
    805  0  stevel interpret_ppp_lqr(int flags, uchar_t *data, int len,
    806  0  stevel     ppp_protoinfo_t *protoinfo)
    807  0  stevel {
    808  0  stevel 	lqr_pkt_t lqr_pkt;
    809  0  stevel 	if (len < sizeof (lqr_pkt_t))
    810  0  stevel 		return (len);
    811  0  stevel 
    812  0  stevel 	(void) memcpy(&lqr_pkt, data, sizeof (lqr_pkt_t));
    813  0  stevel 
    814  0  stevel 	if (flags & F_SUM) {
    815  0  stevel 		(void) sprintf(get_sum_line(), protoinfo->prefix);
    816  0  stevel 	} else { /* (flags & F_DTAIL) */
    817  0  stevel 		show_header(protoinfo->prefix, protoinfo->description, len);
    818  0  stevel 		show_space();
    819  0  stevel 
    820  0  stevel 		(void) sprintf(get_line(0, 0), "Magic-Number =   0x%08x",
    821  0  stevel 		    ntohl(lqr_pkt.lqr_magic));
    822  0  stevel 		(void) sprintf(get_line(0, 0), "LastOutLQRs =    %d",
    823  0  stevel 		    ntohl(lqr_pkt.lqr_lastoutlqrs));
    824  0  stevel 		(void) sprintf(get_line(0, 0), "LastOutPackets = %d",
    825  0  stevel 		    ntohl(lqr_pkt.lqr_lastoutpackets));
    826  0  stevel 		(void) sprintf(get_line(0, 0), "LastOutOctets =  %d",
    827  0  stevel 		    ntohl(lqr_pkt.lqr_lastoutoctets));
    828  0  stevel 		(void) sprintf(get_line(0, 0), "PeerInLQRs =     %d",
    829  0  stevel 		    ntohl(lqr_pkt.lqr_peerinlqrs));
    830  0  stevel 		(void) sprintf(get_line(0, 0), "PeerInPackets =  %d",
    831  0  stevel 		    ntohl(lqr_pkt.lqr_peerinpackets));
    832  0  stevel 		(void) sprintf(get_line(0, 0), "PeerInDiscards = %d",
    833  0  stevel 		    ntohl(lqr_pkt.lqr_peerindiscards));
    834  0  stevel 		(void) sprintf(get_line(0, 0), "PeerInErrors =   %d",
    835  0  stevel 		    ntohl(lqr_pkt.lqr_peerinerrors));
    836  0  stevel 		(void) sprintf(get_line(0, 0), "PeerInOctets =   %d",
    837  0  stevel 		    ntohl(lqr_pkt.lqr_peerinoctets));
    838  0  stevel 		(void) sprintf(get_line(0, 0), "PeerOutLQRs =    %d",
    839  0  stevel 		    ntohl(lqr_pkt.lqr_peeroutlqrs));
    840  0  stevel 		(void) sprintf(get_line(0, 0), "PeerOutPackets = %d",
    841  0  stevel 		    ntohl(lqr_pkt.lqr_peeroutpackets));
    842  0  stevel 		(void) sprintf(get_line(0, 0), "PeerOutOctets =  %d",
    843  0  stevel 		    ntohl(lqr_pkt.lqr_peeroutoctets));
    844  0  stevel 
    845  0  stevel 		show_space();
    846  0  stevel 	}
    847  0  stevel 
    848  0  stevel 	len -= sizeof (lqr_pkt_t);
    849  0  stevel 	return (len);
    850  0  stevel }
    851  0  stevel 
    852  0  stevel static ppp_protoinfo_t *
    853  0  stevel ppp_getprotoinfo(uint16_t proto)
    854  0  stevel {
    855  0  stevel 	ppp_protoinfo_t *protoinfo_ptr = &protoinfo_array[0];
    856  0  stevel 
    857  0  stevel 	while (protoinfo_ptr->proto != proto && protoinfo_ptr->proto != 0) {
    858  0  stevel 		protoinfo_ptr++;
    859  0  stevel 	}
    860  0  stevel 
    861  0  stevel 	return (protoinfo_ptr);
    862  0  stevel }
    863  0  stevel 
    864  0  stevel 
    865  0  stevel static cp_optinfo_t *
    866  0  stevel ppp_getoptinfo(cp_optinfo_t optinfo_list[], uint16_t opt_type)
    867  0  stevel {
    868  0  stevel 	cp_optinfo_t *optinfo_ptr = &optinfo_list[0];
    869  0  stevel 
    870  0  stevel 	while (optinfo_ptr->opt_type != opt_type &&
    871  0  stevel 	    optinfo_ptr->opt_name != unknown_string) {
    872  0  stevel 		optinfo_ptr++;
    873  0  stevel 	}
    874  0  stevel 
    875  0  stevel 	return (optinfo_ptr);
    876  0  stevel }
    877  0  stevel 
    878  0  stevel 
    879  0  stevel /*
    880  0  stevel  * Below are the functions which parse control protocol configuration
    881  0  stevel  * options.  The first argument to these functions (optdata) points to the
    882  0  stevel  * first byte of the option after the length field.  The second argument
    883  0  stevel  * (size) is the number of bytes in the option after the length field
    884  0  stevel  * (length - 2).
    885  0  stevel  */
    886  0  stevel 
    887  0  stevel /*
    888  0  stevel  * The format of the Vendor-Specific option (rfc2153) is:
    889  0  stevel  *
    890  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    891  0  stevel  * |     Type      |    Length     |              OUI
    892  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    893  0  stevel  *        ...      |     Kind      |  Value(s) ...
    894  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
    895  0  stevel  */
    896  0  stevel /*ARGSUSED1*/
    897  0  stevel static void
    898  0  stevel opt_format_vendor(uchar_t *optdata, uint8_t size)
    899  0  stevel {
    900  0  stevel 	uint32_t oui;
    901  0  stevel 	char *ouistr;
    902  0  stevel 	uint8_t kind;
    903  0  stevel 
    904  0  stevel 	GETINT32(oui, optdata);
    905  0  stevel 	kind = oui & 0x000000ff;
    906  0  stevel 	oui >>= 8;
    907  0  stevel 
    908  0  stevel 	ouistr = ether_ouiname(oui);
    909  0  stevel 	if (ouistr == NULL)
    910  0  stevel 		ouistr = unknown_string;
    911  0  stevel 
    912  0  stevel 	(void) sprintf(get_line(0, 0), "OUI = 0x%06x (%s)", oui, ouistr);
    913  0  stevel 	(void) sprintf(get_line(0, 0), "Kind = %d", kind);
    914  0  stevel }
    915  0  stevel 
    916  0  stevel /*
    917  0  stevel  * The format of the MRU option (rfc1661) is:
    918  0  stevel  *
    919  0  stevel  *  0                   1                   2                   3
    920  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    921  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    922  0  stevel  * |     Type      |    Length     |      Maximum-Receive-Unit     |
    923  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    924  0  stevel  */
    925  0  stevel /*ARGSUSED1*/
    926  0  stevel static void
    927  0  stevel opt_format_mru(uchar_t *optdata, uint8_t size)
    928  0  stevel {
    929  0  stevel 	uint16_t mru;
    930  0  stevel 
    931  0  stevel 	GETINT16(mru, optdata);
    932  0  stevel 	(void) sprintf(get_line(0, 0), "MRU = %d", mru);
    933  0  stevel }
    934  0  stevel 
    935  0  stevel /*
    936  0  stevel  * The format of the accm option (rfc1662) is:
    937  0  stevel  *
    938  0  stevel  *  0                   1                   2                   3
    939  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    940  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    941  0  stevel  * |     Type      |    Length     |               ACCM
    942  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    943  0  stevel  *           ACCM (cont)           |
    944  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    945  0  stevel  */
    946  0  stevel /*ARGSUSED1*/
    947  0  stevel static void
    948  0  stevel opt_format_accm(uchar_t *optdata, uint8_t size)
    949  0  stevel {
    950  0  stevel 	uint32_t accm;
    951  0  stevel 
    952  0  stevel 	GETINT32(accm, optdata);
    953  0  stevel 	(void) sprintf(get_line(0, 0), "ACCM = 0x%08x", accm);
    954  0  stevel }
    955  0  stevel 
    956  0  stevel /*
    957  0  stevel  * The format of the Authentication-Protocol option (rfc1661) is:
    958  0  stevel  *
    959  0  stevel  *  0                   1                   2                   3
    960  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    961  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    962  0  stevel  * |     Type      |    Length     |     Authentication-Protocol   |
    963  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    964  0  stevel  * |    Data ...
    965  0  stevel  * +-+-+-+-+
    966  0  stevel  *
    967  0  stevel  * For PAP (rfc1334), there is no data.  For CHAP (rfc1994), there is one
    968  0  stevel  * byte of data representing the algorithm.
    969  0  stevel  */
    970  0  stevel static void
    971  0  stevel opt_format_authproto(uchar_t *optdata, uint8_t size)
    972  0  stevel {
    973  0  stevel 	uint16_t proto;
    974  0  stevel 	ppp_protoinfo_t *auth_protoinfo;
    975  0  stevel 
    976  0  stevel 	GETINT16(proto, optdata);
    977  0  stevel 
    978  0  stevel 	auth_protoinfo = ppp_getprotoinfo(proto);
    979  0  stevel 
    980  0  stevel 	(void) sprintf(get_line(0, 0), "Protocol = 0x%x (%s)", proto,
    981  0  stevel 	    auth_protoinfo->name);
    982  0  stevel 
    983  0  stevel 	switch (proto) {
    984  0  stevel 	case PPP_CHAP: {
    985  0  stevel 		uint8_t algo;
    986  0  stevel 		char *algostr;
    987  0  stevel 
    988  0  stevel 		if (size < sizeof (proto) + sizeof (algo))
    989  0  stevel 			return;
    990  0  stevel 
    991  0  stevel 		GETINT8(algo, optdata);
    992  0  stevel 		switch (algo) {
    993  0  stevel 		case 5:
    994  0  stevel 			algostr = "CHAP with MD5";
    995  0  stevel 			break;
    996  0  stevel 		case 128:
    997  0  stevel 			algostr = "MS-CHAP";
    998  0  stevel 			break;
    999  0  stevel 		case 129:
   1000  0  stevel 			algostr = "MS-CHAP-2";
   1001  0  stevel 			break;
   1002  0  stevel 		default:
   1003  0  stevel 			algostr = unknown_string;
   1004  0  stevel 			break;
   1005  0  stevel 		}
   1006  0  stevel 		(void) sprintf(get_line(0, 0), "Algorithm = %d (%s)", algo,
   1007  0  stevel 		    algostr);
   1008  0  stevel 		break;
   1009  0  stevel 	}
   1010  0  stevel 	default:
   1011  0  stevel 		break;
   1012  0  stevel 	}
   1013  0  stevel }
   1014  0  stevel 
   1015  0  stevel /*
   1016  0  stevel  * The format of the Quality Protocol option (rfc1661) is:
   1017  0  stevel  *
   1018  0  stevel  *  0                   1                   2                   3
   1019  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1020  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1021  0  stevel  * |     Type      |    Length     |        Quality-Protocol       |
   1022  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1023  0  stevel  * |    Data ...
   1024  0  stevel  * +-+-+-+-+
   1025  0  stevel  *
   1026  0  stevel  * For LQR, the data consists of a 4 byte reporting period.
   1027  0  stevel  */
   1028  0  stevel static void
   1029  0  stevel opt_format_qualproto(uchar_t *optdata, uint8_t size)
   1030  0  stevel {
   1031  0  stevel 	uint16_t proto;
   1032  0  stevel 	ppp_protoinfo_t *qual_protoinfo;
   1033  0  stevel 
   1034  0  stevel 	GETINT16(proto, optdata);
   1035  0  stevel 
   1036  0  stevel 	qual_protoinfo = ppp_getprotoinfo(proto);
   1037  0  stevel 
   1038  0  stevel 	(void) sprintf(get_line(0, 0), "Protocol = 0x%x (%s)", proto,
   1039  0  stevel 	    qual_protoinfo->name);
   1040  0  stevel 
   1041  0  stevel 	switch (proto) {
   1042  0  stevel 	case PPP_LQR: {
   1043  0  stevel 		uint32_t reporting_period;
   1044  0  stevel 
   1045  0  stevel 		if (size < sizeof (proto) + sizeof (reporting_period))
   1046  0  stevel 			return;
   1047  0  stevel 
   1048  0  stevel 		GETINT32(reporting_period, optdata);
   1049  0  stevel 		(void) sprintf(get_line(0, 0), "Reporting-Period = %d",
   1050  0  stevel 		    reporting_period);
   1051  0  stevel 		break;
   1052  0  stevel 	}
   1053  0  stevel 	default:
   1054  0  stevel 		break;
   1055  0  stevel 	}
   1056  0  stevel }
   1057  0  stevel 
   1058  0  stevel /*
   1059  0  stevel  * The format of the Magic Number option (rfc1661) is:
   1060  0  stevel  *
   1061  0  stevel  *  0                   1                   2                   3
   1062  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1063  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1064  0  stevel  * |     Type      |    Length     |          Magic-Number
   1065  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1066  0  stevel  *       Magic-Number (cont)       |
   1067  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1068  0  stevel  */
   1069  0  stevel /*ARGSUSED1*/
   1070  0  stevel static void
   1071  0  stevel opt_format_magicnum(uchar_t *optdata, uint8_t size)
   1072  0  stevel {
   1073  0  stevel 	uint32_t magicnum;
   1074  0  stevel 
   1075  0  stevel 	GETINT32(magicnum, optdata);
   1076  0  stevel 	(void) sprintf(get_line(0, 0), "Magic Number = 0x%08x", magicnum);
   1077  0  stevel }
   1078  0  stevel 
   1079  0  stevel /*
   1080  0  stevel  * The format of the FCS-Alternatives option (rfc1570) is:
   1081  0  stevel  *
   1082  0  stevel  *  0                   1                   2
   1083  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
   1084  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1085  0  stevel  * |     Type      |    Length     |    Options    |
   1086  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1087  0  stevel  */
   1088  0  stevel /*ARGSUSED1*/
   1089  0  stevel static void
   1090  0  stevel opt_format_fcs(uchar_t *optdata, uint8_t size)
   1091  0  stevel {
   1092  0  stevel 	uint8_t options;
   1093  0  stevel 
   1094  0  stevel 	GETINT8(options, optdata);
   1095  0  stevel 
   1096  0  stevel 	(void) sprintf(get_line(0, 0), "Options = 0x%02x", options);
   1097  0  stevel 	(void) sprintf(get_line(0, 0), "     %s",
   1098  0  stevel 	    getflag(options, 0x01, "NULL FCS", ""));
   1099  0  stevel 	(void) sprintf(get_line(0, 0), "     %s",
   1100  0  stevel 	    getflag(options, 0x02, "CCITT 16-bit FCS", ""));
   1101  0  stevel 	(void) sprintf(get_line(0, 0), "     %s",
   1102  0  stevel 	    getflag(options, 0x04, "CCITT 32-bit FCS", ""));
   1103  0  stevel }
   1104  0  stevel 
   1105  0  stevel /*
   1106  0  stevel  * The format of the Self-Describing-Padding option (rfc1570) is:
   1107  0  stevel  *
   1108  0  stevel  *  0                   1                   2
   1109  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
   1110  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1111  0  stevel  * |     Type      |    Length     |    Maximum    |
   1112  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1113  0  stevel  */
   1114  0  stevel /*ARGSUSED1*/
   1115  0  stevel static void
   1116  0  stevel opt_format_sdp(uchar_t *optdata, uint8_t size)
   1117  0  stevel {
   1118  0  stevel 	uint8_t max;
   1119  0  stevel 
   1120  0  stevel 	GETINT8(max, optdata);
   1121  0  stevel 
   1122  0  stevel 	(void) sprintf(get_line(0, 0), "Maximum = %d", max);
   1123  0  stevel }
   1124  0  stevel 
   1125  0  stevel /*
   1126  0  stevel  * The format of the Numbered-Mode option (rfc1663) is:
   1127  0  stevel  *
   1128  0  stevel  *  0                   1                   2                   3
   1129  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1130  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1131  0  stevel  * |     Type      |     Length    |    Window     |   Address...
   1132  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1133  0  stevel  */
   1134  0  stevel /*ARGSUSED1*/
   1135  0  stevel static void
   1136  0  stevel opt_format_nummode(uchar_t *optdata, uint8_t size)
   1137  0  stevel {
   1138  0  stevel 	uint8_t window;
   1139  0  stevel 
   1140  0  stevel 	GETINT8(window, optdata);
   1141  0  stevel 	(void) sprintf(get_line(0, 0), "Window = %d", window);
   1142  0  stevel }
   1143  0  stevel 
   1144  0  stevel /*
   1145  0  stevel  * The format of the Callback option (rfc1570) is:
   1146  0  stevel  *
   1147  0  stevel  *  0                   1                   2                   3
   1148  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1149  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1150  0  stevel  * |     Type      |    Length     |   Operation   |  Message ...
   1151  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1152  0  stevel  */
   1153  0  stevel static void
   1154  0  stevel opt_format_callback(uchar_t *optdata, uint8_t size)
   1155  0  stevel {
   1156  0  stevel 	uint8_t operation;
   1157  0  stevel 	char *opstr;
   1158  0  stevel 
   1159  0  stevel 	GETINT8(operation, optdata);
   1160  0  stevel 	switch (operation) {
   1161  0  stevel 	case 0:
   1162  0  stevel 		opstr = "User Authentication";
   1163  0  stevel 		break;
   1164  0  stevel 	case 1:
   1165  0  stevel 		opstr = "Dialing String";
   1166  0  stevel 		break;
   1167  0  stevel 	case 2:
   1168  0  stevel 		opstr = "Location Identifier";
   1169  0  stevel 		break;
   1170  0  stevel 	case 3:
   1171  0  stevel 		opstr = "E.164 Number";
   1172  0  stevel 		break;
   1173  0  stevel 	case 4:
   1174  0  stevel 		opstr = "X.500 Distinguished Name";
   1175  0  stevel 		break;
   1176  0  stevel 	case 6:
   1177  0  stevel 		opstr = "CBCP Negotiation";
   1178  0  stevel 		break;
   1179  0  stevel 	default:
   1180  0  stevel 		opstr = unknown_string;
   1181  0  stevel 		break;
   1182  0  stevel 	}
   1183  0  stevel 
   1184  0  stevel 	(void) sprintf(get_line(0, 0), "Operation = %d (%s)", operation, opstr);
   1185  0  stevel 
   1186  0  stevel 	if (size > sizeof (operation)) {
   1187  0  stevel 		(void) sprintf(get_line(0, 0), "Message = %.*s",
   1188  0  stevel 		    size - sizeof (operation), optdata);
   1189  0  stevel 	}
   1190  0  stevel }
   1191  0  stevel 
   1192  0  stevel /*
   1193  0  stevel  * The format of the Multilink-MRRU option (rfc1990) is:
   1194  0  stevel  *
   1195  0  stevel  *  0                   1                   2                   3
   1196  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1197  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1198  0  stevel  * |   Type = 17   |   Length = 4  | Max-Receive-Reconstructed-Unit|
   1199  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1200  0  stevel  */
   1201  0  stevel /*ARGSUSED1*/
   1202  0  stevel static void
   1203  0  stevel opt_format_mrru(uchar_t *optdata, uint8_t size)
   1204  0  stevel {
   1205  0  stevel 	uint16_t mrru;
   1206  0  stevel 
   1207  0  stevel 	GETINT16(mrru, optdata);
   1208  0  stevel 	(void) sprintf(get_line(0, 0), "MRRU = %d", mrru);
   1209  0  stevel }
   1210  0  stevel 
   1211  0  stevel /*
   1212  0  stevel  * The format of the Endpoint Discriminator option (rfc1990) is:
   1213  0  stevel  *
   1214  0  stevel  *  0                   1                   2                   3
   1215  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1216  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1217  0  stevel  * |   Type = 19   |     Length    |    Class      |  Address ...
   1218  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1219  0  stevel  */
   1220  0  stevel static void
   1221  0  stevel opt_format_epdisc(uchar_t *optdata, uint8_t size)
   1222  0  stevel {
   1223  0  stevel 	uint8_t class;
   1224  0  stevel 	char *classstr;
   1225  0  stevel 	uint8_t addrlen = size - sizeof (class);
   1226  0  stevel 	char *addr;
   1227  0  stevel 
   1228  0  stevel 	GETINT8(class, optdata);
   1229  0  stevel 
   1230  0  stevel 	switch (class) {
   1231  0  stevel 	case 0:
   1232  0  stevel 		classstr = "Null Class";
   1233  0  stevel 		break;
   1234  0  stevel 	case 1:
   1235  0  stevel 		classstr = "Locally Assigned Address";
   1236  0  stevel 		break;
   1237  0  stevel 	case 2:
   1238  0  stevel 		classstr = "IPv4 Address";
   1239  0  stevel 		break;
   1240  0  stevel 	case 3:
   1241  0  stevel 		classstr = "IEE 802.1 Global MAC Address";
   1242  0  stevel 		break;
   1243  0  stevel 	case 4:
   1244  0  stevel 		classstr = "PPP Magic-Number Block";
   1245  0  stevel 		break;
   1246  0  stevel 	case 5:
   1247  0  stevel 		classstr = "Public Switched Network Directory Number";
   1248  0  stevel 		break;
   1249  0  stevel 	default:
   1250  0  stevel 		classstr = unknown_string;
   1251  0  stevel 		break;
   1252  0  stevel 	}
   1253  0  stevel 
   1254  0  stevel 	(void) sprintf(get_line(0, 0), "Address Class = %d (%s)", class,
   1255  0  stevel 	    classstr);
   1256  0  stevel 
   1257  0  stevel 	if (addrlen == 0)
   1258  0  stevel 		return;
   1259  0  stevel 
   1260  0  stevel 	addr = (char *)malloc(addrlen);
   1261  0  stevel 	(void) memcpy(addr, optdata, addrlen);
   1262  0  stevel 	switch (class) {
   1263  0  stevel 	case 2: {
   1264  0  stevel 		char addrstr[INET_ADDRSTRLEN];
   1265  0  stevel 
   1266  0  stevel 		if (addrlen != sizeof (in_addr_t))
   1267  0  stevel 			break;
   1268  0  stevel 		if (inet_ntop(AF_INET, addr, addrstr, INET_ADDRSTRLEN) !=
   1269  0  stevel 		    NULL) {
   1270  0  stevel 			(void) sprintf(get_line(0, 0), "Address = %s", addrstr);
   1271  0  stevel 		}
   1272  0  stevel 		break;
   1273  0  stevel 	}
   1274  0  stevel 	case 3: {
   1275  0  stevel 		char *addrstr;
   1276  0  stevel 
   1277  0  stevel 		if (addrlen != sizeof (struct ether_addr))
   1278  0  stevel 			break;
   1279  0  stevel 		if ((addrstr = ether_ntoa((struct ether_addr *)addr)) != NULL) {
   1280  0  stevel 			(void) sprintf(get_line(0, 0), "Address = %s", addrstr);
   1281  0  stevel 		}
   1282  0  stevel 		break;
   1283  0  stevel 	}
   1284  0  stevel 	case 5: {
   1285  0  stevel 		/*
   1286  0  stevel 		 * For this case, the address is supposed to be a plain
   1287  0  stevel 		 * text telephone number.
   1288  0  stevel 		 */
   1289  0  stevel 		(void) sprintf(get_line(0, 0), "Address = %.*s", addrlen,
   1290  0  stevel 		    addr);
   1291  0  stevel 	}
   1292  0  stevel 	default:
   1293  0  stevel 		break;
   1294  0  stevel 	}
   1295  0  stevel 
   1296  0  stevel 	free(addr);
   1297  0  stevel }
   1298  0  stevel 
   1299  0  stevel /*
   1300  0  stevel  * The DCE identifier option has the following format (from rfc1976):
   1301  0  stevel  *
   1302  0  stevel  *     0                   1                   2
   1303  0  stevel  *     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
   1304  0  stevel  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1305  0  stevel  *    |     Type      |    Length     |      Mode     |
   1306  0  stevel  *    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1307  0  stevel  */
   1308  0  stevel /*ARGSUSED1*/
   1309  0  stevel static void
   1310  0  stevel opt_format_dce(uchar_t *optdata, uint8_t size)
   1311  0  stevel {
   1312  0  stevel 	uint8_t mode;
   1313  0  stevel 	char *modestr;
   1314  0  stevel 
   1315  0  stevel 	GETINT8(mode, optdata);
   1316  0  stevel 	switch (mode) {
   1317  0  stevel 	case 1:
   1318  0  stevel 		modestr = "No Additional Negotiation";
   1319  0  stevel 		break;
   1320  0  stevel 	case 2:
   1321  0  stevel 		modestr = "Full PPP Negotiation and State Machine";
   1322  0  stevel 		break;
   1323  0  stevel 	default:
   1324  0  stevel 		modestr = unknown_string;
   1325  0  stevel 		break;
   1326  0  stevel 	}
   1327  0  stevel 	(void) sprintf(get_line(0, 0), "Mode = %d (%s)", mode, modestr);
   1328  0  stevel }
   1329  0  stevel 
   1330  0  stevel /*
   1331  0  stevel  * The format of the Link Discriminator option (rfc2125) is:
   1332  0  stevel  *
   1333  0  stevel  *  0                   1                   2                   3
   1334  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1335  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1336  0  stevel  * |     Type      |     Length    |       Link Discriminator      |
   1337  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1338  0  stevel  */
   1339  0  stevel /*ARGSUSED1*/
   1340  0  stevel static void
   1341  0  stevel opt_format_linkdisc(uchar_t *optdata, uint8_t size)
   1342  0  stevel {
   1343  0  stevel 	uint16_t discrim;
   1344  0  stevel 
   1345  0  stevel 	GETINT16(discrim, optdata);
   1346  0  stevel 
   1347  0  stevel 	(void) sprintf(get_line(0, 0), "Link Discriminator = %d", discrim);
   1348  0  stevel }
   1349  0  stevel 
   1350  0  stevel 
   1351  0  stevel /*
   1352  0  stevel  * The format of the Internationalization option (rfc2484) is:
   1353  0  stevel  *
   1354  0  stevel  *  0                   1                   2                   3
   1355  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1356  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1357  0  stevel  * |     Type      |    Length     |          MIBenum
   1358  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1359  0  stevel  *           MIBenum (cont)        |        Language-Tag...
   1360  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1361  0  stevel  */
   1362  0  stevel static void
   1363  0  stevel opt_format_i18n(uchar_t *optdata, uint8_t size)
   1364  0  stevel {
   1365  0  stevel 	uint32_t mibenum;
   1366  0  stevel 	uint8_t taglen;
   1367  0  stevel 
   1368  0  stevel 	taglen = size - sizeof (mibenum);
   1369  0  stevel 
   1370  0  stevel 	GETINT32(mibenum, optdata);
   1371  0  stevel 	(void) sprintf(get_line(0, 0), "MIBenum = %d", mibenum);
   1372  0  stevel 
   1373  0  stevel 	if (taglen > 0) {
   1374  0  stevel 		(void) sprintf(get_line(0, 0), "Language Tag = %.*s", taglen,
   1375  0  stevel 		    optdata);
   1376  0  stevel 	}
   1377  0  stevel }
   1378  0  stevel 
   1379  0  stevel /*
   1380  0  stevel  * The format of the obsolete IP-Addresses option (rfc1172) is:
   1381  0  stevel  *
   1382  0  stevel  *  0                   1                   2                   3
   1383  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1384  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1385  0  stevel  * |     Type      |    Length     |     Source-IP-Address
   1386  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1387  0  stevel  *   Source-IP-Address (cont)      |  Destination-IP-Address
   1388  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1389  0  stevel  *  Destination-IP-Address (cont)  |
   1390  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1391  0  stevel  */
   1392  0  stevel /*ARGSUSED1*/
   1393  0  stevel static void
   1394  0  stevel opt_format_ipaddresses(uchar_t *optdata, uint8_t size)
   1395  0  stevel {
   1396  0  stevel 	in_addr_t addr;
   1397  0  stevel 	char addrstr[INET_ADDRSTRLEN];
   1398  0  stevel 
   1399  0  stevel 	(void) memcpy(&addr, optdata, sizeof (in_addr_t));
   1400  0  stevel 	if (inet_ntop(AF_INET, &addr, addrstr, INET_ADDRSTRLEN) != NULL) {
   1401  0  stevel 		(void) sprintf(get_line(0, 0), "Source Address =      %s",
   1402  0  stevel 		    addrstr);
   1403  0  stevel 	}
   1404  0  stevel 
   1405  0  stevel 	optdata += sizeof (in_addr_t);
   1406  0  stevel 
   1407  0  stevel 	(void) memcpy(&addr, optdata, sizeof (in_addr_t));
   1408  0  stevel 	if (inet_ntop(AF_INET, &addr, addrstr, INET_ADDRSTRLEN) != NULL) {
   1409  0  stevel 		(void) sprintf(get_line(0, 0), "Destination Address = %s",
   1410  0  stevel 		    addrstr);
   1411  0  stevel 	}
   1412  0  stevel }
   1413  0  stevel 
   1414  0  stevel /*
   1415  0  stevel  * The format of the IP-Compression-Protocol option (rfc1332) is:
   1416  0  stevel  *
   1417  0  stevel  *  0                   1                   2                   3
   1418  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1419  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1420  0  stevel  * |     Type      |    Length     |     IP-Compression-Protocol   |
   1421  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1422  0  stevel  * |    Data ...
   1423  0  stevel  * +-+-+-+-+
   1424  0  stevel  *
   1425  0  stevel  * For VJ Compressed TCP/IP, data consists of:
   1426  0  stevel  *
   1427  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1428  0  stevel  * |  Max-Slot-Id  | Comp-Slot-Id  |
   1429  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1430  0  stevel  *
   1431  0  stevel  * For IPHC (rfc2509), data consists of:
   1432  0  stevel  *
   1433  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1434  0  stevel  * |           TCP_SPACE           |         NON_TCP_SPACE         |
   1435  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1436  0  stevel  * |         F_MAX_PERIOD          |          F_MAX_TIME           |
   1437  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1438  0  stevel  * |           MAX_HEADER          |          suboptions...
   1439  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1440  0  stevel  */
   1441  0  stevel static void
   1442  0  stevel opt_format_ipcompproto(uchar_t *optdata, uint8_t size)
   1443  0  stevel {
   1444  0  stevel 	uint16_t proto;
   1445  0  stevel 	ppp_protoinfo_t *comp_protoinfo;
   1446  0  stevel 
   1447  0  stevel 	GETINT16(proto, optdata);
   1448  0  stevel 
   1449  0  stevel 	comp_protoinfo = ppp_getprotoinfo(proto);
   1450  0  stevel 
   1451  0  stevel 	(void) sprintf(get_line(0, 0), "Protocol = 0x%x (%s)", proto,
   1452  0  stevel 	    comp_protoinfo->name);
   1453  0  stevel 
   1454  0  stevel 	switch (proto) {
   1455  0  stevel 	case PPP_VJC_COMP: {
   1456  0  stevel 		uint8_t maxslotid;
   1457  0  stevel 		uint8_t compslotid;
   1458  0  stevel 
   1459  0  stevel 		if (size < sizeof (proto) + sizeof (maxslotid) +
   1460  0  stevel 		    sizeof (compslotid))
   1461  0  stevel 			break;
   1462  0  stevel 
   1463  0  stevel 		GETINT8(maxslotid, optdata);
   1464  0  stevel 		GETINT8(compslotid, optdata);
   1465  0  stevel 		(void) sprintf(get_line(0, 0), "Max-Slot-Id = %d", maxslotid);
   1466  0  stevel 		(void) sprintf(get_line(0, 0), "Comp-Slot Flag = 0x%x",
   1467  0  stevel 		    compslotid);
   1468  0  stevel 		break;
   1469  0  stevel 	}
   1470  0  stevel 	case PPP_FULLHDR: {
   1471  0  stevel 		uint16_t tcp_space;
   1472  0  stevel 		uint16_t non_tcp_space;
   1473  0  stevel 		uint16_t f_max_period;
   1474  0  stevel 		uint16_t f_max_time;
   1475  0  stevel 		uint16_t max_header;
   1476  0  stevel 
   1477  0  stevel 		if (size < sizeof (proto) + sizeof (tcp_space) +
   1478  0  stevel 		    sizeof (non_tcp_space) + sizeof (f_max_period) +
   1479  0  stevel 		    sizeof (f_max_time) + sizeof (max_header))
   1480  0  stevel 			break;
   1481  0  stevel 
   1482  0  stevel 		GETINT16(tcp_space, optdata);
   1483  0  stevel 		GETINT16(non_tcp_space, optdata);
   1484  0  stevel 		GETINT16(f_max_period, optdata);
   1485  0  stevel 		GETINT16(f_max_time, optdata);
   1486  0  stevel 		GETINT16(max_header, optdata);
   1487  0  stevel 
   1488  0  stevel 		(void) sprintf(get_line(0, 0), "TCP_SPACE = %d", tcp_space);
   1489  0  stevel 		(void) sprintf(get_line(0, 0), "NON_TCP_SPACE = %d",
   1490  0  stevel 		    non_tcp_space);
   1491  0  stevel 		(void) sprintf(get_line(0, 0), "F_MAX_PERIOD = %d",
   1492  0  stevel 		    f_max_period);
   1493  0  stevel 		(void) sprintf(get_line(0, 0), "F_MAX_TIME = %d", f_max_time);
   1494  0  stevel 		(void) sprintf(get_line(0, 0), "MAX_HEADER = %d octets",
   1495  0  stevel 		    max_header);
   1496  0  stevel 	}
   1497  0  stevel 	default:
   1498  0  stevel 		break;
   1499  0  stevel 	}
   1500  0  stevel }
   1501  0  stevel 
   1502  0  stevel /*
   1503  0  stevel  * The format of the IP-Address option (rfc1332) is:
   1504  0  stevel  *
   1505  0  stevel  *  0                   1                   2                   3
   1506  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1507  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1508  0  stevel  * |     Type      |    Length     |           IP-Address
   1509  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1510  0  stevel  *         IP-Address (cont)       |
   1511  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1512  0  stevel  */
   1513  0  stevel /*ARGSUSED1*/
   1514  0  stevel static void
   1515  0  stevel opt_format_ipaddress(uchar_t *optdata, uint8_t size)
   1516  0  stevel {
   1517  0  stevel 	in_addr_t ipaddr;
   1518  0  stevel 	char addrstr[INET_ADDRSTRLEN];
   1519  0  stevel 
   1520  0  stevel 	(void) memcpy(&ipaddr, optdata, sizeof (in_addr_t));
   1521  0  stevel 	if (inet_ntop(AF_INET, &ipaddr, addrstr, INET_ADDRSTRLEN) != NULL) {
   1522  0  stevel 		(void) sprintf(get_line(0, 0), "Address = %s", addrstr);
   1523  0  stevel 	}
   1524  0  stevel }
   1525  0  stevel 
   1526  0  stevel /*
   1527  0  stevel  * The format of the Mobile-IPv4 option (rfc2290) is:
   1528  0  stevel  *
   1529  0  stevel  *  0                   1                   2                   3
   1530  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1531  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1532  0  stevel  * |     Type      |    Length     |         Mobile Node's ...
   1533  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1534  0  stevel  *       ...  Home Address         |
   1535  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1536  0  stevel  */
   1537  0  stevel /*ARGSUSED1*/
   1538  0  stevel static void
   1539  0  stevel opt_format_mobileipv4(uchar_t *optdata, uint8_t size)
   1540  0  stevel {
   1541  0  stevel 	in_addr_t ipaddr;
   1542  0  stevel 	char addrstr[INET_ADDRSTRLEN];
   1543  0  stevel 
   1544  0  stevel 	(void) memcpy(&ipaddr, optdata, sizeof (in_addr_t));
   1545  0  stevel 	if (inet_ntop(AF_INET, &ipaddr, addrstr, INET_ADDRSTRLEN) != NULL) {
   1546  0  stevel 		(void) sprintf(get_line(0, 0),
   1547  0  stevel 		    "Mobile Node's Home Address = %s", addrstr);
   1548  0  stevel 	}
   1549  0  stevel }
   1550  0  stevel 
   1551  0  stevel /*
   1552  0  stevel  * The format of the Interface-Identifier option (rfc2472) is:
   1553  0  stevel  *
   1554  0  stevel  * 0                   1                   2                   3
   1555  0  stevel  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1556  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1557  0  stevel  * |     Type      |    Length     | Interface-Identifier (MS Bytes)
   1558  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1559  0  stevel  *                      Interface-Identifier (cont)
   1560  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1561  0  stevel  * Interface-Identifier (LS Bytes) |
   1562  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1563  0  stevel  */
   1564  0  stevel /*ARGSUSED1*/
   1565  0  stevel static void
   1566  0  stevel opt_format_ifaceid(uchar_t *optdata, uint8_t size)
   1567  0  stevel {
   1568  0  stevel 	in6_addr_t id;
   1569  0  stevel 	char idstr[INET6_ADDRSTRLEN];
   1570  0  stevel 
   1571  0  stevel 	(void) memset(&id, 0, sizeof (in6_addr_t));
   1572  0  stevel 	(void) memcpy(&id.s6_addr[8], optdata, 8);
   1573  0  stevel 
   1574  0  stevel 	if (inet_ntop(AF_INET6, &id, idstr, INET6_ADDRSTRLEN) != NULL) {
   1575  0  stevel 		(void) sprintf(get_line(0, 0), "Interface ID = %s", idstr);
   1576  0  stevel 	}
   1577  0  stevel }
   1578  0  stevel 
   1579  0  stevel /*
   1580  0  stevel  * The format of the IPv6-Compression-Protocol option (rfc2472) is:
   1581  0  stevel  *
   1582  0  stevel  * 0                   1                   2                   3
   1583  0  stevel  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1584  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1585  0  stevel  * |     Type      |    Length     |   IPv6-Compression-Protocol   |
   1586  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1587  0  stevel  * |    Data ...
   1588  0  stevel  * +-+-+-+-+
   1589  0  stevel  */
   1590  0  stevel static void
   1591  0  stevel opt_format_ipv6compproto(uchar_t *optdata, uint8_t size)
   1592  0  stevel {
   1593  0  stevel 	uint16_t proto;
   1594  0  stevel 	ppp_protoinfo_t *comp_protoinfo;
   1595  0  stevel 
   1596  0  stevel 	GETINT16(proto, optdata);
   1597  0  stevel 
   1598  0  stevel 	comp_protoinfo = ppp_getprotoinfo(proto);
   1599  0  stevel 
   1600  0  stevel 	(void) sprintf(get_line(0, 0), "Protocol = 0x%x (%s)", proto,
   1601  0  stevel 	    comp_protoinfo->name);
   1602  0  stevel 
   1603  0  stevel 	switch (proto) {
   1604  0  stevel 	case PPP_FULLHDR: {
   1605  0  stevel 		uint16_t tcp_space;
   1606  0  stevel 		uint16_t non_tcp_space;
   1607  0  stevel 		uint16_t f_max_period;
   1608  0  stevel 		uint16_t f_max_time;
   1609  0  stevel 		uint16_t max_header;
   1610  0  stevel 
   1611  0  stevel 		if (size < sizeof (proto) + sizeof (tcp_space) +
   1612  0  stevel 		    sizeof (non_tcp_space) + sizeof (f_max_period) +
   1613  0  stevel 		    sizeof (f_max_time) + sizeof (max_header))
   1614  0  stevel 			return;
   1615  0  stevel 
   1616  0  stevel 		GETINT16(tcp_space, optdata);
   1617  0  stevel 		GETINT16(non_tcp_space, optdata);
   1618  0  stevel 		GETINT16(f_max_period, optdata);
   1619  0  stevel 		GETINT16(f_max_time, optdata);
   1620  0  stevel 		GETINT16(max_header, optdata);
   1621  0  stevel 
   1622  0  stevel 		(void) sprintf(get_line(0, 0), "TCP_SPACE = %d", tcp_space);
   1623  0  stevel 		(void) sprintf(get_line(0, 0), "NON_TCP_SPACE = %d",
   1624  0  stevel 		    non_tcp_space);
   1625  0  stevel 		(void) sprintf(get_line(0, 0), "F_MAX_PERIOD = %d",
   1626  0  stevel 		    f_max_period);
   1627  0  stevel 		(void) sprintf(get_line(0, 0), "F_MAX_TIME = %d", f_max_time);
   1628  0  stevel 		(void) sprintf(get_line(0, 0), "MAX_HEADER = %d octets",
   1629  0  stevel 		    max_header);
   1630  0  stevel 	}
   1631  0  stevel 	default:
   1632  0  stevel 		break;
   1633  0  stevel 	}
   1634  0  stevel }
   1635  0  stevel 
   1636  0  stevel /*
   1637  0  stevel  * The format of the Proprietary Compression OUI option (rfc1962) is:
   1638  0  stevel  *
   1639  0  stevel  *  0                   1                   2                   3
   1640  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1641  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1642  0  stevel  * |     Type      |    Length     |       OUI ...
   1643  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1644  0  stevel  *       OUI       |    Subtype    |  Values...
   1645  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
   1646  0  stevel  */
   1647  0  stevel /*ARGSUSED1*/
   1648  0  stevel static void
   1649  0  stevel opt_format_compoui(uchar_t *optdata, uint8_t size)
   1650  0  stevel {
   1651  0  stevel 	uint32_t oui;
   1652  0  stevel 	uint8_t subtype;
   1653  0  stevel 	char *ouistr;
   1654  0  stevel 
   1655  0  stevel 	GETINT32(oui, optdata);
   1656  0  stevel 	subtype = oui & 0x000000ff;
   1657  0  stevel 	oui >>= 8;
   1658  0  stevel 
   1659  0  stevel 	ouistr = ether_ouiname(oui);
   1660  0  stevel 	if (ouistr == NULL)
   1661  0  stevel 		ouistr = unknown_string;
   1662  0  stevel 	(void) sprintf(get_line(0, 0), "OUI = 0x%06x (%s)", oui, ouistr);
   1663  0  stevel 	(void) sprintf(get_line(0, 0), "Subtype = 0x%x", subtype);
   1664  0  stevel }
   1665  0  stevel 
   1666  0  stevel /*
   1667  0  stevel  * The format of the Stac LZS configuration option (rfc1974) is:
   1668  0  stevel  *
   1669  0  stevel  *  0                   1                   2                   3
   1670  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1671  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1672  0  stevel  * |     Type      |    Length     |        History Count          |
   1673  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1674  0  stevel  * |   Check Mode  |
   1675  0  stevel  * +-+-+-+-+-+-+-+-+
   1676  0  stevel  */
   1677  0  stevel /*ARGSUSED1*/
   1678  0  stevel static void
   1679  0  stevel opt_format_staclzs(uchar_t *optdata, uint8_t size)
   1680  0  stevel {
   1681  0  stevel 	uint16_t hcount;
   1682  0  stevel 	uint8_t cmode;
   1683  0  stevel 
   1684  0  stevel 	GETINT16(hcount, optdata);
   1685  0  stevel 	GETINT8(cmode, optdata);
   1686  0  stevel 
   1687  0  stevel 	cmode &= 0x07;
   1688  0  stevel 
   1689  0  stevel 	(void) sprintf(get_line(0, 0), "History Count = %d", hcount);
   1690  0  stevel 	(void) sprintf(get_line(0, 0), "Check Mode = %d", cmode);
   1691  0  stevel }
   1692  0  stevel 
   1693  0  stevel /*
   1694  0  stevel  * The format of MPPC configuration option (rfc2118) is:
   1695  0  stevel  *
   1696  0  stevel  *  0                   1                   2                   3
   1697  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1698  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1699  0  stevel  * |     Type      |    Length     |        Supported Bits         |
   1700  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1701  0  stevel  * |       Supported Bits          |
   1702  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1703  0  stevel  */
   1704  0  stevel /*ARGSUSED1*/
   1705  0  stevel static void
   1706  0  stevel opt_format_mppc(uchar_t *optdata, uint8_t size)
   1707  0  stevel {
   1708  0  stevel 	uint32_t sb;
   1709  0  stevel 
   1710  0  stevel 	GETINT32(sb, optdata);
   1711  0  stevel 
   1712  0  stevel 	(void) sprintf(get_line(0, 0), "Supported Bits = 0x%x", sb);
   1713  0  stevel }
   1714  0  stevel 
   1715  0  stevel /*
   1716  0  stevel  * The format of the Gandalf FZA configuration option (rfc1993) is:
   1717  0  stevel  *
   1718  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1719  0  stevel  * |     Type      |    Length     |   History   |    Version ...
   1720  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1721  0  stevel  */
   1722  0  stevel /*ARGSUSED1*/
   1723  0  stevel static void
   1724  0  stevel opt_format_gandalf(uchar_t *optdata, uint8_t size)
   1725  0  stevel {
   1726  0  stevel 	uint8_t history;
   1727  0  stevel 
   1728  0  stevel 	GETINT8(history, optdata);
   1729  0  stevel 	(void) sprintf(get_line(0, 0), "Maximum History Size = %d bits",
   1730  0  stevel 	    history);
   1731  0  stevel }
   1732  0  stevel 
   1733  0  stevel /*
   1734  0  stevel  * The format of the BSD Compress configuration option (rfc1977) is:
   1735  0  stevel  *
   1736  0  stevel  *  0                   1                   2
   1737  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
   1738  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1739  0  stevel  * |     Type      |    Length     | Vers|   Dict  |
   1740  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1741  0  stevel  */
   1742  0  stevel /*ARGSUSED1*/
   1743  0  stevel static void
   1744  0  stevel opt_format_bsdcomp(uchar_t *optdata, uint8_t size)
   1745  0  stevel {
   1746  0  stevel 	uint8_t version;
   1747  0  stevel 	uint8_t codesize;
   1748  0  stevel 
   1749  0  stevel 	GETINT8(codesize, optdata);
   1750  0  stevel 
   1751  0  stevel 	version = codesize >> 5;
   1752  0  stevel 	codesize &= 0x1f;
   1753  0  stevel 
   1754  0  stevel 	(void) sprintf(get_line(0, 0), "Version = 0x%x", version);
   1755  0  stevel 	(void) sprintf(get_line(0, 0), "Maximum Code Size = %d bits", codesize);
   1756  0  stevel }
   1757  0  stevel 
   1758  0  stevel /*
   1759  0  stevel  * The format of the LZS-DCP configuration option (rfc1967) is:
   1760  0  stevel  *
   1761  0  stevel  *  0                   1                   2                   3
   1762  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1763  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1764  0  stevel  * |     Type      |    Length     |        History Count          |
   1765  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1766  0  stevel  * |   Check Mode  | Process Mode  |
   1767  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1768  0  stevel  */
   1769  0  stevel /*ARGSUSED1*/
   1770  0  stevel static void
   1771  0  stevel opt_format_lzsdcp(uchar_t *optdata, uint8_t size)
   1772  0  stevel {
   1773  0  stevel 	uint16_t history;
   1774  0  stevel 	uint8_t mode;
   1775  0  stevel 	char *modestr;
   1776  0  stevel 
   1777  0  stevel 	GETINT16(history, optdata);
   1778  0  stevel 	(void) sprintf(get_line(0, 0), "History Count = %d", history);
   1779  0  stevel 
   1780  0  stevel 	/* check mode */
   1781  0  stevel 	GETINT8(mode, optdata);
   1782  0  stevel 	switch (mode) {
   1783  0  stevel 	case 0:
   1784  0  stevel 		modestr = "None";
   1785  0  stevel 		break;
   1786  0  stevel 	case 1:
   1787  0  stevel 		modestr = "LCB";
   1788  0  stevel 		break;
   1789  0  stevel 	case 2:
   1790  0  stevel 		modestr = "Sequence Number";
   1791  0  stevel 		break;
   1792  0  stevel 	case 3:
   1793  0  stevel 		modestr = "Sequence Number + LCB (default)";
   1794  0  stevel 		break;
   1795  0  stevel 	default:
   1796  0  stevel 		modestr = unknown_string;
   1797  0  stevel 		break;
   1798  0  stevel 	}
   1799  0  stevel 	(void) sprintf(get_line(0, 0), "Check Mode = %d (%s)", mode, modestr);
   1800  0  stevel 
   1801  0  stevel 	/* process mode */
   1802  0  stevel 	GETINT8(mode, optdata);
   1803  0  stevel 	switch (mode) {
   1804  0  stevel 	case 0:
   1805  0  stevel 		modestr = "None (default)";
   1806  0  stevel 		break;
   1807  0  stevel 	case 1:
   1808  0  stevel 		modestr = "Process-Uncompressed";
   1809  0  stevel 		break;
   1810  0  stevel 	default:
   1811  0  stevel 		modestr = unknown_string;
   1812  0  stevel 		break;
   1813  0  stevel 	}
   1814  0  stevel 	(void) sprintf(get_line(0, 0), "Process Mode = %d (%s)", mode, modestr);
   1815  0  stevel 
   1816  0  stevel }
   1817  0  stevel 
   1818  0  stevel /*
   1819  0  stevel  * The format of the Magnalink configuration option (rfc1975) is:
   1820  0  stevel  *
   1821  0  stevel  *  0                   1                   2                   3
   1822  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1823  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1824  0  stevel  * |     Type      |    Length     |FE |P| History |  # Contexts   |
   1825  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1826  0  stevel  */
   1827  0  stevel /*ARGSUSED1*/
   1828  0  stevel static void
   1829  0  stevel opt_format_magnalink(uchar_t *optdata, uint8_t size)
   1830  0  stevel {
   1831  0  stevel 	uint8_t features;
   1832  0  stevel 	uint8_t pflag;
   1833  0  stevel 	uint8_t history;
   1834  0  stevel 	uint8_t contexts;
   1835  0  stevel 
   1836  0  stevel 	GETINT8(history, optdata);
   1837  0  stevel 	GETINT8(contexts, optdata);
   1838  0  stevel 
   1839  0  stevel 	features = history >> 6;
   1840  0  stevel 	pflag = (history >> 5) & 0x01;
   1841  0  stevel 	history &= 0x1f;
   1842  0  stevel 
   1843  0  stevel 	(void) sprintf(get_line(0, 0), "Features = 0x%d", features);
   1844  0  stevel 	(void) sprintf(get_line(0, 0), "Packet Flag = %d", pflag);
   1845  0  stevel 	(void) sprintf(get_line(0, 0), "History Size = %d", history);
   1846  0  stevel 	(void) sprintf(get_line(0, 0), "Contexts = %d", contexts);
   1847  0  stevel }
   1848  0  stevel 
   1849  0  stevel /*
   1850  0  stevel  * The format of the Deflate configuration option (rfc1979) is:
   1851  0  stevel  *
   1852  0  stevel  *  0                   1                   2                   3
   1853  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1854  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1855  0  stevel  * |     Type      |    Length     |Window | Method|    MBZ    |Chk|
   1856  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1857  0  stevel  */
   1858  0  stevel /*ARGSUSED1*/
   1859  0  stevel static void
   1860  0  stevel opt_format_deflate(uchar_t *optdata, uint8_t size)
   1861  0  stevel {
   1862  0  stevel 	uint8_t window;
   1863  0  stevel 	uint8_t method;
   1864  0  stevel 	uint8_t chk;
   1865  0  stevel 
   1866  0  stevel 	GETINT8(method, optdata);
   1867  0  stevel 	window = method >> 4;
   1868  0  stevel 	method &= 0x0f;
   1869  0  stevel 
   1870  0  stevel 	GETINT8(chk, optdata);
   1871  0  stevel 	chk &= 0x03;
   1872  0  stevel 
   1873  0  stevel 	(void) sprintf(get_line(0, 0), "Maximum Window Size = %d", window);
   1874  0  stevel 	(void) sprintf(get_line(0, 0), "Compression Method = 0x%x", method);
   1875  0  stevel 	(void) sprintf(get_line(0, 0), "Check Method = 0x%x", chk);
   1876  0  stevel }
   1877  0  stevel 
   1878  0  stevel /*
   1879  0  stevel  * The format of the Proprietary Encryption OUI option (rfc1968) is:
   1880  0  stevel  *
   1881  0  stevel  * 0                   1                   2                   3
   1882  0  stevel  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1883  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1884  0  stevel  * |     Type      |    Length     |       OUI ...
   1885  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1886  0  stevel  *       OUI       |    Subtype    |  Values...
   1887  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
   1888  0  stevel  */
   1889  0  stevel /*ARGSUSED1*/
   1890  0  stevel static void
   1891  0  stevel opt_format_encroui(uchar_t *optdata, uint8_t size)
   1892  0  stevel {
   1893  0  stevel 	uint32_t oui;
   1894  0  stevel 	uint8_t subtype;
   1895  0  stevel 	char *ouistr;
   1896  0  stevel 
   1897  0  stevel 	GETINT32(oui, optdata);
   1898  0  stevel 	subtype = oui & 0x000000ff;
   1899  0  stevel 	oui >>= 8;
   1900  0  stevel 
   1901  0  stevel 	ouistr = ether_ouiname(oui);
   1902  0  stevel 	if (ouistr == NULL)
   1903  0  stevel 		ouistr = unknown_string;
   1904  0  stevel 	(void) sprintf(get_line(0, 0), "OUI = 0x%06x (%s)", oui, ouistr);
   1905  0  stevel 	(void) sprintf(get_line(0, 0), "Subtype = 0x%x", subtype);
   1906  0  stevel }
   1907  0  stevel 
   1908  0  stevel /*
   1909  0  stevel  * The format of the DESE, DESE-bis, and 3DESE configuration options
   1910  0  stevel  * (rfc1969, rfc2419, and rfc2420) are:
   1911  0  stevel  *
   1912  0  stevel  * 0                   1                   2                   3
   1913  0  stevel  * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1914  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1915  0  stevel  * |   Type = 3    |    Length     |         Initial Nonce ...
   1916  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1917  0  stevel  */
   1918  0  stevel /*ARGSUSED1*/
   1919  0  stevel static void
   1920  0  stevel opt_format_dese(uchar_t *optdata, uint8_t size)
   1921  0  stevel {
   1922  0  stevel 	(void) sprintf(get_line(0, 0),
   1923  0  stevel 	    "Initial Nonce = 0x%02x%02x%02x%02x%02x%02x%02x%02x",
   1924  0  stevel 	    optdata[0], optdata[1], optdata[2], optdata[3], optdata[4],
   1925  0  stevel 	    optdata[5], optdata[6], optdata[7]);
   1926  0  stevel }
   1927  0  stevel 
   1928  0  stevel /*
   1929  0  stevel  * The format of the PPPMux Default Protocol Id option
   1930  0  stevel  * (draft-ietf-pppext-pppmux-02.txt) is:
   1931  0  stevel  *
   1932  0  stevel  *  0                   1                   2                   3
   1933  0  stevel  *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
   1934  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1935  0  stevel  * |   Type = 1    |   Length = 4  |        Default PID            |
   1936  0  stevel  * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   1937  0  stevel  */
   1938  0  stevel /*ARGSUSED1*/
   1939  0  stevel static void
   1940  0  stevel opt_format_muxpid(uchar_t *optdata, uint8_t size)
   1941  0  stevel {
   1942  0  stevel 	uint16_t defpid;
   1943  0  stevel 
   1944  0  stevel 	GETINT16(defpid, optdata);
   1945  0  stevel 	(void) sprintf(get_line(0, 0), "Default PID = %d", defpid);
   1946  0  stevel }
   1947