/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2001-2002 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "snoop.h" #include "snoop_ppp.h" static int interpret_ppp_cp(int, uchar_t *, int, ppp_protoinfo_t *); static int interpret_cp_options(uchar_t *, int, ppp_protoinfo_t *); static int interpret_ppp_chap(int, uchar_t *, int, ppp_protoinfo_t *); static int interpret_ppp_pap(int, uchar_t *, int, ppp_protoinfo_t *); static int interpret_ppp_lqr(int, uchar_t *, int, ppp_protoinfo_t *); static ppp_protoinfo_t *ppp_getprotoinfo(uint16_t); static cp_optinfo_t *ppp_getoptinfo(cp_optinfo_t *, uint16_t); static optformat_func_t opt_format_vendor; static optformat_func_t opt_format_mru; static optformat_func_t opt_format_accm; static optformat_func_t opt_format_authproto; static optformat_func_t opt_format_qualproto; static optformat_func_t opt_format_magicnum; static optformat_func_t opt_format_fcs; static optformat_func_t opt_format_sdp; static optformat_func_t opt_format_nummode; static optformat_func_t opt_format_callback; static optformat_func_t opt_format_mrru; static optformat_func_t opt_format_epdisc; static optformat_func_t opt_format_dce; static optformat_func_t opt_format_linkdisc; static optformat_func_t opt_format_i18n; static optformat_func_t opt_format_ipaddresses; static optformat_func_t opt_format_ipcompproto; static optformat_func_t opt_format_ipaddress; static optformat_func_t opt_format_mobileipv4; static optformat_func_t opt_format_ifaceid; static optformat_func_t opt_format_ipv6compproto; static optformat_func_t opt_format_compoui; static optformat_func_t opt_format_bsdcomp; static optformat_func_t opt_format_staclzs; static optformat_func_t opt_format_mppc; static optformat_func_t opt_format_gandalf; static optformat_func_t opt_format_lzsdcp; static optformat_func_t opt_format_magnalink; static optformat_func_t opt_format_deflate; static optformat_func_t opt_format_encroui; static optformat_func_t opt_format_dese; static optformat_func_t opt_format_muxpid; /* * Many strings below are initialized with "Unknown". */ static char unknown_string[] = "Unknown"; /* * Each known PPP protocol has an associated ppp_protoinfo_t in this array. * Even if we can't decode the protocol (interpret_proto() == NULL), * interpret_ppp() will at least print the protocol's name. There is no * dependency on the ordering of the entries in this array. They have been * ordered such that the most commonly used protocols are near the front. * The array is delimited by a last entry of protocol of type * PPP_PROTO_UNKNOWN. */ static ppp_protoinfo_t protoinfo_array[] = { { PPP_IP, "IP", interpret_ip, NULL, NULL }, { PPP_IPV6, "IPv6", interpret_ipv6, NULL, NULL }, { PPP_COMP, "Compressed Data", NULL, NULL, NULL }, { PPP_OSI, "OSI", NULL, NULL, NULL }, { PPP_AT, "AppleTalk", NULL, NULL, NULL }, { PPP_IPX, "IPX", NULL, NULL, NULL }, { PPP_VJC_COMP, "VJ Compressed TCP", NULL, NULL, NULL }, { PPP_VJC_UNCOMP, "VJ Uncompressed TCP", NULL, NULL, NULL }, { PPP_BRIDGE, "Bridging", NULL, NULL, NULL }, { PPP_802HELLO, "802.1d Hello", NULL, NULL, NULL }, { PPP_MP, "MP", NULL, NULL, NULL }, { PPP_ENCRYPT, "Encryption", NULL, NULL, NULL }, { PPP_ENCRYPTFRAG, "Individual Link Encryption", NULL, NULL, NULL }, { PPP_MUX, "PPP Muxing", NULL, NULL, NULL }, { PPP_COMPFRAG, "Single Link Compressed Data", NULL, NULL, NULL }, { PPP_FULLHDR, "IP Compression", NULL, NULL, NULL }, { PPP_COMPTCP, "IP Compression", NULL, NULL, NULL }, { PPP_COMPNONTCP, "IP Compression", NULL, NULL, NULL }, { PPP_COMPUDP8, "IP Compression", NULL, NULL, NULL }, { PPP_COMPRTP8, "IP Compression", NULL, NULL, NULL }, { PPP_COMPTCPND, "IP Compression", NULL, NULL, NULL }, { PPP_COMPSTATE, "IP Compression", NULL, NULL, NULL }, { PPP_COMPUDP16, "IP Compression", NULL, NULL, NULL }, { PPP_COMPRTP16, "IP Compression", NULL, NULL, NULL }, { PPP_MPLS, "MPLS", NULL, NULL, NULL }, { PPP_MPLSMC, "MPLS M/C", NULL, NULL, NULL }, { PPP_LQR, "LQR", interpret_ppp_lqr, "PPP-LQR: ", "Link Quality Report" }, { PPP_LCP, "LCP", interpret_ppp_cp, "PPP-LCP: ", "Link Control Protocol" }, { PPP_IPCP, "IPCP", interpret_ppp_cp, "PPP-IPCP: ", "IP Control Protocol" }, { PPP_IPV6CP, "IPV6CP", interpret_ppp_cp, "PPP-IPV6CP: ", "IPv6 Control Protocol" }, { PPP_CCP, "CCP", interpret_ppp_cp, "PPP-CCP: ", "Compression Control Protocol" }, { PPP_CCPFRAG, "CCP-Link", interpret_ppp_cp, "PPP-CCP-Link: ", "Per-Link Compression Control Protocol" }, { PPP_ECP, "ECP", interpret_ppp_cp, "PPP-ECP: ", "Encryption Control Protocol" }, { PPP_ECPFRAG, "ECP-Link", interpret_ppp_cp, "PPP-ECP-Link: ", "Per-Link Encryption Control Protocol" }, { PPP_MPLSCP, "MPLSCP", NULL, NULL, NULL }, { PPP_OSINLCP, "OSINLCP", NULL, NULL, NULL }, { PPP_ATCP, "ATCP", NULL, NULL, NULL }, { PPP_IPXCP, "IPXCP", NULL, NULL, NULL }, { PPP_BACP, "BACP", NULL, NULL, NULL }, { PPP_BCP, "BCP", NULL, NULL, NULL }, { PPP_CBCP, "CBCP", NULL, NULL, NULL }, { PPP_BAP, "BAP", NULL, NULL, NULL }, { PPP_CHAP, "CHAP", interpret_ppp_chap, "CHAP: ", "Challenge Handshake Authentication Protocl" }, { PPP_PAP, "PAP", interpret_ppp_pap, "PAP: ", "Password Authentication Protocol" }, { PPP_EAP, "EAP", NULL, NULL, NULL }, { 0, unknown_string, NULL, NULL, NULL } }; static cp_optinfo_t lcp_optinfo[] = { { OPT_LCP_VENDOR, "Vendor-Specific", 6, opt_format_vendor }, { OPT_LCP_MRU, "Maximum-Receive-Unit", 4, opt_format_mru }, { OPT_LCP_ASYNCMAP, "Async-Control-Character-Map", 6, opt_format_accm }, { OPT_LCP_AUTHTYPE, "Authentication-Protocol", 4, opt_format_authproto }, { OPT_LCP_QUALITY, "Quality-Protocol", 4, opt_format_qualproto }, { OPT_LCP_MAGICNUMBER, "Magic-Number", 6, opt_format_magicnum }, { OPT_LCP_PCOMPRESSION, "Protocol-Field-Compression", 2, NULL }, { OPT_LCP_ACCOMPRESSION, "Address-and-Control-Field-Compression", 2, NULL }, { OPT_LCP_FCSALTERN, "FCS-Alternative", 3, opt_format_fcs }, { OPT_LCP_SELFDESCPAD, "Self-Describing-Padding", 3, opt_format_sdp }, { OPT_LCP_NUMBERED, "Numbered-Mode", 3, opt_format_nummode }, { OPT_LCP_MULTILINKPROC, "Multi-Link-Procedure", 2, NULL }, { OPT_LCP_CALLBACK, "Callback", 3, opt_format_callback }, { OPT_LCP_CONNECTTIME, "Connect-Time", 2, NULL }, { OPT_LCP_COMPOUNDFRAMES, "Compound-Frames", 2, NULL }, { OPT_LCP_DATAENCAP, "Nominal-Data-Encapsulation", 2, NULL }, { OPT_LCP_MRRU, "Multilink-MRRU", 4, opt_format_mrru }, { OPT_LCP_SSNHF, "Multilink-Short-Sequence-Number-Header-Format", 2, NULL }, { OPT_LCP_EPDISC, "Multilink-Endpoint-Discriminator", 3, opt_format_epdisc }, { OPT_LCP_DCEIDENT, "DCE-Identifier", 3, opt_format_dce }, { OPT_LCP_MLPLUSPROC, "Multi-Link-Plus-Procedure", 2, NULL }, { OPT_LCP_LINKDISC, "Link Discriminator for BACP", 4, opt_format_linkdisc }, { OPT_LCP_AUTH, "LCP-Authentication-Option", 2, NULL }, { OPT_LCP_COBS, "COBS", 2, NULL }, { OPT_LCP_PFXELISION, "Prefix elision", 2, NULL }, { OPT_LCP_MPHDRFMT, "Multilink header format", 2, NULL }, { OPT_LCP_I18N, "Internationalization", 6, opt_format_i18n }, { OPT_LCP_SDL, "Simple Data Link on SONET/SDH", 2, NULL }, { OPT_LCP_MUXING, "Old PPP Multiplexing", 2, NULL }, { 0, unknown_string, 0, NULL } }; static cp_optinfo_t ipcp_optinfo[] = { { OPT_IPCP_ADDRS, "IP-Addresses", 10, opt_format_ipaddresses }, { OPT_IPCP_COMPRESSTYPE, "IP-Compression-Protocol", 4, opt_format_ipcompproto }, { OPT_IPCP_ADDR, "IP-Address", 6, opt_format_ipaddress }, { OPT_IPCP_MOBILEIPV4, "Mobile-IPv4", 6, opt_format_mobileipv4 }, { OPT_IPCP_DNS1, "Primary DNS Address", 6, opt_format_ipaddress }, { OPT_IPCP_NBNS1, "Primary NBNS Address", 6, opt_format_ipaddress }, { OPT_IPCP_DNS2, "Secondary DNS Address", 6, opt_format_ipaddress }, { OPT_IPCP_NBNS2, "Secondary NBNS Address", 6, opt_format_ipaddress }, { OPT_IPCP_SUBNET, "IP-Subnet", 6, opt_format_ipaddress }, { 0, unknown_string, 0, NULL } }; static cp_optinfo_t ipv6cp_optinfo[] = { { OPT_IPV6CP_IFACEID, "Interface-Identifier", 10, opt_format_ifaceid }, { OPT_IPV6CP_COMPRESSTYPE, "IPv6-Compression-Protocol", 4, opt_format_ipv6compproto }, { 0, unknown_string, 0, NULL } }; static cp_optinfo_t ccp_optinfo[] = { { OPT_CCP_PROPRIETARY, "Proprietary Compression OUI", 6, opt_format_compoui }, { OPT_CCP_PREDICTOR1, "Predictor type 1", 2, NULL }, { OPT_CCP_PREDICTOR2, "Predictor type 2", 2, NULL }, { OPT_CCP_PUDDLEJUMP, "Puddle Jumper", 2, NULL }, { OPT_CCP_HPPPC, "Hewlett-Packard PPC", 2, NULL }, { OPT_CCP_STACLZS, "Stac Electronics LZS", 5, opt_format_staclzs }, { OPT_CCP_MPPC, "Microsoft PPC", 6, opt_format_mppc }, { OPT_CCP_GANDALFFZA, "Gandalf FZA", 3, opt_format_gandalf }, { OPT_CCP_V42BIS, "V.42bis compression", 2, NULL }, { OPT_CCP_BSDCOMP, "BSD LZW Compress", 3, opt_format_bsdcomp }, { OPT_CCP_LZSDCP, "LZS-DCP", 6, opt_format_lzsdcp }, { OPT_CCP_MAGNALINK, "Magnalink", 4, opt_format_magnalink }, { OPT_CCP_DEFLATE, "Deflate", 4, opt_format_deflate }, { 0, unknown_string, 0, NULL } }; static cp_optinfo_t ecp_optinfo[] = { { OPT_ECP_PROPRIETARY, "Proprietary Encryption OUI", 6, opt_format_encroui }, { OPT_ECP_DESE, "DESE", 10, opt_format_dese }, { OPT_ECP_3DESE, "3DESE", 10, opt_format_dese }, { OPT_ECP_DESEBIS, "DESE-bis", 10, opt_format_dese }, { 0, unknown_string, 0, NULL } }; static cp_optinfo_t muxcp_optinfo[] = { { OPT_MUXCP_DEFAULTPID, "Default PID", 4, opt_format_muxpid }, { 0, unknown_string, 0, NULL } }; static char *cp_codearray[] = { "(Vendor Specific)", "(Configure-Request)", "(Configure-Ack)", "(Configure-Nak)", "(Configure-Reject)", "(Terminate-Request)", "(Terminate-Ack)", "(Code-Reject)", "(Protocol-Reject)", "(Echo-Request)", "(Echo-Reply)", "(Discard-Request)", "(Identification)", "(Time-Remaining)", "(Reset-Request)", "(Reset-Ack)" }; #define MAX_CPCODE ((sizeof (cp_codearray) / sizeof (char *)) - 1) static char *pap_codearray[] = { "(Unknown)", "(Authenticate-Request)", "(Authenticate-Ack)", "(Authenticate-Nak)" }; #define MAX_PAPCODE ((sizeof (pap_codearray) / sizeof (char *)) - 1) static char *chap_codearray[] = { "(Unknown)", "(Challenge)", "(Response)", "(Success)", "(Failure)" }; #define MAX_CHAPCODE ((sizeof (chap_codearray) / sizeof (char *)) - 1) int interpret_ppp(int flags, uchar_t *data, int len) { uint16_t protocol; ppp_protoinfo_t *protoinfo; uchar_t *payload = data; if (len < 2) return (len); GETINT16(protocol, payload); len -= sizeof (uint16_t); protoinfo = ppp_getprotoinfo(protocol); if (flags & F_SUM) { (void) sprintf(get_sum_line(), "PPP Protocol=0x%x (%s)", protocol, protoinfo->name); } else { /* F_DTAIL */ show_header("PPP: ", "Point-to-Point Protocol", len); show_space(); (void) sprintf(get_line(0, 0), "Protocol = 0x%x (%s)", protocol, protoinfo->name); show_space(); } if (protoinfo->interpret_proto != NULL) { len = protoinfo->interpret_proto(flags, payload, len, protoinfo); } return (len); } /* * interpret_ppp_cp() - Interpret PPP control protocols. It is convenient * to do some of the decoding of these protocols in a common function since * they share packet formats. This function expects to receive data * starting with the code field. */ static int interpret_ppp_cp(int flags, uchar_t *data, int len, ppp_protoinfo_t *protoinfo) { uint8_t code; uint8_t id; char *codestr; uint16_t length; uchar_t *datap = data; if (len < sizeof (ppp_pkt_t)) return (len); GETINT8(code, datap); GETINT8(id, datap); GETINT16(length, datap); len -= sizeof (ppp_pkt_t); if (code <= MAX_CPCODE) codestr = cp_codearray[code]; else codestr = ""; if (flags & F_SUM) { (void) sprintf(get_sum_line(), "%s%s", protoinfo->prefix, codestr); } else { /* (flags & F_DTAIL) */ show_header(protoinfo->prefix, protoinfo->description, len); show_space(); (void) sprintf(get_line(0, 0), "Code = %d %s", code, codestr); (void) sprintf(get_line(0, 0), "Identifier = %d", id); (void) sprintf(get_line(0, 0), "Length = %d", length); show_space(); len = MIN(len, length - sizeof (ppp_pkt_t)); if (len == 0) return (len); switch (code) { case CODE_VENDOR: { uint32_t magicnum; uint32_t oui; char *ouistr; uint8_t kind; if (len < sizeof (magicnum) + sizeof (oui)) return (len); GETINT32(magicnum, datap); (void) sprintf(get_line(0, 0), "Magic-Number = 0x%08x", magicnum); GETINT32(oui, datap); kind = oui & 0x000000ff; oui >>= 8; ouistr = ether_ouiname(oui); if (ouistr == NULL) ouistr = unknown_string; (void) sprintf(get_line(0, 0), "OUI = 0x%06x (%s)", oui, ouistr); (void) sprintf(get_line(0, 0), "Kind = %d", kind); show_space(); break; } case CODE_CONFREQ: case CODE_CONFACK: case CODE_CONFNAK: case CODE_CONFREJ: /* * The above all contain protocol specific * configuration options. Parse these options. */ interpret_cp_options(datap, len, protoinfo); break; case CODE_TERMREQ: case CODE_TERMACK: /* * The arbitrary data in these two packet types * is almost always plain text. Print it as such. */ (void) sprintf(get_line(0, 0), "Data = %.*s", length - sizeof (ppp_pkt_t), datap); show_space(); break; case CODE_CODEREJ: /* * What follows is the rejected control protocol * packet, starting with the code field. * Conveniently, we can call interpret_ppp_cp() to * decode this. */ prot_nest_prefix = protoinfo->prefix; interpret_ppp_cp(flags, datap, len, protoinfo); prot_nest_prefix = ""; break; case CODE_PROTREJ: /* * We don't print the rejected-protocol field * explicitely. Instead, we cheat and pretend that * the rejected-protocol field is actually the * protocol field in the included PPP packet. This * way, we can invoke interpret_ppp() and have it * treat the included packet normally. */ prot_nest_prefix = protoinfo->prefix; interpret_ppp(flags, datap, len); prot_nest_prefix = ""; break; case CODE_ECHOREQ: case CODE_ECHOREP: case CODE_DISCREQ: case CODE_IDENT: case CODE_TIMEREMAIN: { uint32_t magicnum; char *message_label = "Identification = %.*s"; if (len < sizeof (uint32_t)) break; GETINT32(magicnum, datap); len -= sizeof (uint32_t); (void) sprintf(get_line(0, 0), "Magic-Number = 0x%08x", magicnum); /* * Unless this is an identification or * time-remaining packet, arbitrary data follows * the magic number field. The user can take a * look at the hex dump for enlightenment. */ if (code == CODE_TIMEREMAIN) { uint32_t timeremaining; if (len < sizeof (uint32_t)) break; message_label = "Message = %.*s"; GETINT32(timeremaining, datap); len -= sizeof (uint32_t); (void) sprintf(get_line(0, 0), "Seconds Remaining = %d", timeremaining); } if (code == CODE_IDENT || code == CODE_TIMEREMAIN) { if (len == 0) break; (void) sprintf(get_line(0, 0), message_label, len, datap); } show_space(); break; } /* * Reset-Request and Reset-Ack contain arbitrary data which * the user can sift through using the -x option. */ case CODE_RESETREQ: case CODE_RESETACK: default: break; } } return (len); } /* * interpret_cp_options() decodes control protocol configuration options. * Since each control protocol has a different set of options whose type * numbers overlap, the protoinfo parameter is used to get a handle on * which option set to use for decoding. */ static int interpret_cp_options(uchar_t *optptr, int len, ppp_protoinfo_t *protoinfo) { cp_optinfo_t *optinfo; cp_optinfo_t *optinfo_ptr; uint8_t optlen; uint8_t opttype; switch (protoinfo->proto) { case PPP_LCP: optinfo = lcp_optinfo; break; case PPP_IPCP: optinfo = ipcp_optinfo; break; case PPP_IPV6CP: optinfo = ipv6cp_optinfo; break; case PPP_CCP: optinfo = ccp_optinfo; break; case PPP_ECP: optinfo = ecp_optinfo; break; case PPP_MUXCP: optinfo = muxcp_optinfo; break; default: return (len); break; } if (len >= 2) { (void) sprintf(get_line(0, 0), "%s Configuration Options", protoinfo->name); show_space(); } while (len >= 2) { GETINT8(opttype, optptr); GETINT8(optlen, optptr); optinfo_ptr = ppp_getoptinfo(optinfo, opttype); (void) sprintf(get_line(0, 0), "Option Type = %d (%s)", opttype, optinfo_ptr->opt_name); (void) sprintf(get_line(0, 0), "Option Length = %d", optlen); /* * Don't continue if there isn't enough data to * contain this option, or if this type of option * should contain more data than the length field * claims there is. */ if (optlen > len || optlen < optinfo_ptr->opt_minsize) { (void) sprintf(get_line(0, 0), "Warning: Incomplete Option"); show_space(); break; } if (optinfo_ptr->opt_formatdata != NULL) { optinfo_ptr->opt_formatdata(optptr, MIN(optlen - 2, len - 2)); } len -= optlen; optptr += optlen - 2; show_space(); } return (len); } static int interpret_ppp_chap(int flags, uchar_t *data, int len, ppp_protoinfo_t *protoinfo) { uint8_t code; uint8_t id; char *codestr; uint16_t length; int lengthleft; uchar_t *datap = data; if (len < sizeof (ppp_pkt_t)) return (len); GETINT8(code, datap); GETINT8(id, datap); GETINT8(length, datap); if (code <= MAX_CHAPCODE) codestr = chap_codearray[code]; else codestr = ""; if (flags & F_SUM) { (void) sprintf(get_sum_line(), "%s%s", protoinfo->prefix, codestr); } else { /* (flags & F_DTAIL) */ show_header(protoinfo->prefix, protoinfo->description, len); show_space(); (void) sprintf(get_line(0, 0), "Code = %d %s", code, codestr); (void) sprintf(get_line(0, 0), "Identifier = %d", id); (void) sprintf(get_line(0, 0), "Length = %d", length); show_space(); if (len < length) return (len); lengthleft = len - sizeof (ppp_pkt_t); switch (code) { case CODE_CHALLENGE: case CODE_RESPONSE: { uint8_t value_size; uint16_t peername_size; if (lengthleft < sizeof (value_size)) break; GETINT8(value_size, datap); lengthleft -= sizeof (value_size); (void) sprintf(get_line(0, 0), "Value-Size = %d", value_size); if (lengthleft < sizeof (peername_size)) break; peername_size = MIN(length - sizeof (ppp_pkt_t) - value_size, lengthleft); (void) sprintf(get_line(0, 0), "Name = %.*s", peername_size, datap + value_size); break; } case CODE_SUCCESS: case CODE_FAILURE: { uint16_t message_size = MIN(length - sizeof (ppp_pkt_t), lengthleft); (void) sprintf(get_line(0, 0), "Message = %.*s", message_size, datap); break; } default: break; } } show_space(); len -= length; return (len); } static int interpret_ppp_pap(int flags, uchar_t *data, int len, ppp_protoinfo_t *protoinfo) { uint8_t code; uint8_t id; char *codestr; uint16_t length; int lengthleft; uchar_t *datap = data; if (len < sizeof (ppp_pkt_t)) return (len); GETINT8(code, datap); GETINT8(id, datap); GETINT16(length, datap); lengthleft = len - sizeof (ppp_pkt_t); if (code <= MAX_PAPCODE) codestr = pap_codearray[code]; else codestr = ""; if (flags & F_SUM) { (void) sprintf(get_sum_line(), "%s%s", protoinfo->prefix, codestr); } else { /* (flags & F_DTAIL) */ show_header(protoinfo->prefix, protoinfo->description, len); show_space(); (void) sprintf(get_line(0, 0), "Code = %d %s", code, codestr); (void) sprintf(get_line(0, 0), "Identifier = %d", id); (void) sprintf(get_line(0, 0), "Length = %d", length); show_space(); if (len < length) return (len); switch (code) { case CODE_AUTHREQ: { uint8_t fieldlen; if (lengthleft < sizeof (fieldlen)) break; GETINT8(fieldlen, datap); (void) sprintf(get_line(0, 0), "Peer-Id Length = %d", fieldlen); lengthleft -= sizeof (fieldlen); if (lengthleft < fieldlen) break; (void) sprintf(get_line(0, 0), "Peer-Id = %.*s", fieldlen, datap); lengthleft -= fieldlen; datap += fieldlen; if (lengthleft < sizeof (fieldlen)) break; GETINT8(fieldlen, datap); (void) sprintf(get_line(0, 0), "Password Length = %d", fieldlen); lengthleft -= sizeof (fieldlen); if (lengthleft < fieldlen) break; (void) sprintf(get_line(0, 0), "Password = %.*s", fieldlen, datap); break; } case CODE_AUTHACK: case CODE_AUTHNAK: { uint8_t msglen; if (lengthleft < sizeof (msglen)) break; GETINT8(msglen, datap); (void) sprintf(get_line(0, 0), "Msg-Length = %d", msglen); lengthleft -= sizeof (msglen); if (lengthleft < msglen) break; (void) sprintf(get_line(0, 0), "Message = %.*s", msglen, datap); break; } default: break; } } show_space(); len -= length; return (len); } static int interpret_ppp_lqr(int flags, uchar_t *data, int len, ppp_protoinfo_t *protoinfo) { lqr_pkt_t lqr_pkt; if (len < sizeof (lqr_pkt_t)) return (len); (void) memcpy(&lqr_pkt, data, sizeof (lqr_pkt_t)); if (flags & F_SUM) { (void) sprintf(get_sum_line(), protoinfo->prefix); } else { /* (flags & F_DTAIL) */ show_header(protoinfo->prefix, protoinfo->description, len); show_space(); (void) sprintf(get_line(0, 0), "Magic-Number = 0x%08x", ntohl(lqr_pkt.lqr_magic)); (void) sprintf(get_line(0, 0), "LastOutLQRs = %d", ntohl(lqr_pkt.lqr_lastoutlqrs)); (void) sprintf(get_line(0, 0), "LastOutPackets = %d", ntohl(lqr_pkt.lqr_lastoutpackets)); (void) sprintf(get_line(0, 0), "LastOutOctets = %d", ntohl(lqr_pkt.lqr_lastoutoctets)); (void) sprintf(get_line(0, 0), "PeerInLQRs = %d", ntohl(lqr_pkt.lqr_peerinlqrs)); (void) sprintf(get_line(0, 0), "PeerInPackets = %d", ntohl(lqr_pkt.lqr_peerinpackets)); (void) sprintf(get_line(0, 0), "PeerInDiscards = %d", ntohl(lqr_pkt.lqr_peerindiscards)); (void) sprintf(get_line(0, 0), "PeerInErrors = %d", ntohl(lqr_pkt.lqr_peerinerrors)); (void) sprintf(get_line(0, 0), "PeerInOctets = %d", ntohl(lqr_pkt.lqr_peerinoctets)); (void) sprintf(get_line(0, 0), "PeerOutLQRs = %d", ntohl(lqr_pkt.lqr_peeroutlqrs)); (void) sprintf(get_line(0, 0), "PeerOutPackets = %d", ntohl(lqr_pkt.lqr_peeroutpackets)); (void) sprintf(get_line(0, 0), "PeerOutOctets = %d", ntohl(lqr_pkt.lqr_peeroutoctets)); show_space(); } len -= sizeof (lqr_pkt_t); return (len); } static ppp_protoinfo_t * ppp_getprotoinfo(uint16_t proto) { ppp_protoinfo_t *protoinfo_ptr = &protoinfo_array[0]; while (protoinfo_ptr->proto != proto && protoinfo_ptr->proto != 0) { protoinfo_ptr++; } return (protoinfo_ptr); } static cp_optinfo_t * ppp_getoptinfo(cp_optinfo_t optinfo_list[], uint16_t opt_type) { cp_optinfo_t *optinfo_ptr = &optinfo_list[0]; while (optinfo_ptr->opt_type != opt_type && optinfo_ptr->opt_name != unknown_string) { optinfo_ptr++; } return (optinfo_ptr); } /* * Below are the functions which parse control protocol configuration * options. The first argument to these functions (optdata) points to the * first byte of the option after the length field. The second argument * (size) is the number of bytes in the option after the length field * (length - 2). */ /* * The format of the Vendor-Specific option (rfc2153) is: * * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | OUI * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ... | Kind | Value(s) ... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- */ /*ARGSUSED1*/ static void opt_format_vendor(uchar_t *optdata, uint8_t size) { uint32_t oui; char *ouistr; uint8_t kind; GETINT32(oui, optdata); kind = oui & 0x000000ff; oui >>= 8; ouistr = ether_ouiname(oui); if (ouistr == NULL) ouistr = unknown_string; (void) sprintf(get_line(0, 0), "OUI = 0x%06x (%s)", oui, ouistr); (void) sprintf(get_line(0, 0), "Kind = %d", kind); } /* * The format of the MRU option (rfc1661) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | Maximum-Receive-Unit | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_mru(uchar_t *optdata, uint8_t size) { uint16_t mru; GETINT16(mru, optdata); (void) sprintf(get_line(0, 0), "MRU = %d", mru); } /* * The format of the accm option (rfc1662) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | ACCM * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ACCM (cont) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_accm(uchar_t *optdata, uint8_t size) { uint32_t accm; GETINT32(accm, optdata); (void) sprintf(get_line(0, 0), "ACCM = 0x%08x", accm); } /* * The format of the Authentication-Protocol option (rfc1661) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | Authentication-Protocol | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Data ... * +-+-+-+-+ * * For PAP (rfc1334), there is no data. For CHAP (rfc1994), there is one * byte of data representing the algorithm. */ static void opt_format_authproto(uchar_t *optdata, uint8_t size) { uint16_t proto; ppp_protoinfo_t *auth_protoinfo; GETINT16(proto, optdata); auth_protoinfo = ppp_getprotoinfo(proto); (void) sprintf(get_line(0, 0), "Protocol = 0x%x (%s)", proto, auth_protoinfo->name); switch (proto) { case PPP_CHAP: { uint8_t algo; char *algostr; if (size < sizeof (proto) + sizeof (algo)) return; GETINT8(algo, optdata); switch (algo) { case 5: algostr = "CHAP with MD5"; break; case 128: algostr = "MS-CHAP"; break; case 129: algostr = "MS-CHAP-2"; break; default: algostr = unknown_string; break; } (void) sprintf(get_line(0, 0), "Algorithm = %d (%s)", algo, algostr); break; } default: break; } } /* * The format of the Quality Protocol option (rfc1661) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | Quality-Protocol | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Data ... * +-+-+-+-+ * * For LQR, the data consists of a 4 byte reporting period. */ static void opt_format_qualproto(uchar_t *optdata, uint8_t size) { uint16_t proto; ppp_protoinfo_t *qual_protoinfo; GETINT16(proto, optdata); qual_protoinfo = ppp_getprotoinfo(proto); (void) sprintf(get_line(0, 0), "Protocol = 0x%x (%s)", proto, qual_protoinfo->name); switch (proto) { case PPP_LQR: { uint32_t reporting_period; if (size < sizeof (proto) + sizeof (reporting_period)) return; GETINT32(reporting_period, optdata); (void) sprintf(get_line(0, 0), "Reporting-Period = %d", reporting_period); break; } default: break; } } /* * The format of the Magic Number option (rfc1661) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | Magic-Number * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * Magic-Number (cont) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_magicnum(uchar_t *optdata, uint8_t size) { uint32_t magicnum; GETINT32(magicnum, optdata); (void) sprintf(get_line(0, 0), "Magic Number = 0x%08x", magicnum); } /* * The format of the FCS-Alternatives option (rfc1570) is: * * 0 1 2 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | Options | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_fcs(uchar_t *optdata, uint8_t size) { uint8_t options; GETINT8(options, optdata); (void) sprintf(get_line(0, 0), "Options = 0x%02x", options); (void) sprintf(get_line(0, 0), " %s", getflag(options, 0x01, "NULL FCS", "")); (void) sprintf(get_line(0, 0), " %s", getflag(options, 0x02, "CCITT 16-bit FCS", "")); (void) sprintf(get_line(0, 0), " %s", getflag(options, 0x04, "CCITT 32-bit FCS", "")); } /* * The format of the Self-Describing-Padding option (rfc1570) is: * * 0 1 2 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | Maximum | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_sdp(uchar_t *optdata, uint8_t size) { uint8_t max; GETINT8(max, optdata); (void) sprintf(get_line(0, 0), "Maximum = %d", max); } /* * The format of the Numbered-Mode option (rfc1663) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | Window | Address... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_nummode(uchar_t *optdata, uint8_t size) { uint8_t window; GETINT8(window, optdata); (void) sprintf(get_line(0, 0), "Window = %d", window); } /* * The format of the Callback option (rfc1570) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | Operation | Message ... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ static void opt_format_callback(uchar_t *optdata, uint8_t size) { uint8_t operation; char *opstr; GETINT8(operation, optdata); switch (operation) { case 0: opstr = "User Authentication"; break; case 1: opstr = "Dialing String"; break; case 2: opstr = "Location Identifier"; break; case 3: opstr = "E.164 Number"; break; case 4: opstr = "X.500 Distinguished Name"; break; case 6: opstr = "CBCP Negotiation"; break; default: opstr = unknown_string; break; } (void) sprintf(get_line(0, 0), "Operation = %d (%s)", operation, opstr); if (size > sizeof (operation)) { (void) sprintf(get_line(0, 0), "Message = %.*s", size - sizeof (operation), optdata); } } /* * The format of the Multilink-MRRU option (rfc1990) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 17 | Length = 4 | Max-Receive-Reconstructed-Unit| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_mrru(uchar_t *optdata, uint8_t size) { uint16_t mrru; GETINT16(mrru, optdata); (void) sprintf(get_line(0, 0), "MRRU = %d", mrru); } /* * The format of the Endpoint Discriminator option (rfc1990) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 19 | Length | Class | Address ... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ static void opt_format_epdisc(uchar_t *optdata, uint8_t size) { uint8_t class; char *classstr; uint8_t addrlen = size - sizeof (class); char *addr; GETINT8(class, optdata); switch (class) { case 0: classstr = "Null Class"; break; case 1: classstr = "Locally Assigned Address"; break; case 2: classstr = "IPv4 Address"; break; case 3: classstr = "IEE 802.1 Global MAC Address"; break; case 4: classstr = "PPP Magic-Number Block"; break; case 5: classstr = "Public Switched Network Directory Number"; break; default: classstr = unknown_string; break; } (void) sprintf(get_line(0, 0), "Address Class = %d (%s)", class, classstr); if (addrlen == 0) return; addr = (char *)malloc(addrlen); (void) memcpy(addr, optdata, addrlen); switch (class) { case 2: { char addrstr[INET_ADDRSTRLEN]; if (addrlen != sizeof (in_addr_t)) break; if (inet_ntop(AF_INET, addr, addrstr, INET_ADDRSTRLEN) != NULL) { (void) sprintf(get_line(0, 0), "Address = %s", addrstr); } break; } case 3: { char *addrstr; if (addrlen != sizeof (struct ether_addr)) break; if ((addrstr = ether_ntoa((struct ether_addr *)addr)) != NULL) { (void) sprintf(get_line(0, 0), "Address = %s", addrstr); } break; } case 5: { /* * For this case, the address is supposed to be a plain * text telephone number. */ (void) sprintf(get_line(0, 0), "Address = %.*s", addrlen, addr); } default: break; } free(addr); } /* * The DCE identifier option has the following format (from rfc1976): * * 0 1 2 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | Mode | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_dce(uchar_t *optdata, uint8_t size) { uint8_t mode; char *modestr; GETINT8(mode, optdata); switch (mode) { case 1: modestr = "No Additional Negotiation"; break; case 2: modestr = "Full PPP Negotiation and State Machine"; break; default: modestr = unknown_string; break; } (void) sprintf(get_line(0, 0), "Mode = %d (%s)", mode, modestr); } /* * The format of the Link Discriminator option (rfc2125) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | Link Discriminator | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_linkdisc(uchar_t *optdata, uint8_t size) { uint16_t discrim; GETINT16(discrim, optdata); (void) sprintf(get_line(0, 0), "Link Discriminator = %d", discrim); } /* * The format of the Internationalization option (rfc2484) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | MIBenum * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * MIBenum (cont) | Language-Tag... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ static void opt_format_i18n(uchar_t *optdata, uint8_t size) { uint32_t mibenum; uint8_t taglen; taglen = size - sizeof (mibenum); GETINT32(mibenum, optdata); (void) sprintf(get_line(0, 0), "MIBenum = %d", mibenum); if (taglen > 0) { (void) sprintf(get_line(0, 0), "Language Tag = %.*s", taglen, optdata); } } /* * The format of the obsolete IP-Addresses option (rfc1172) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | Source-IP-Address * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * Source-IP-Address (cont) | Destination-IP-Address * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * Destination-IP-Address (cont) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_ipaddresses(uchar_t *optdata, uint8_t size) { in_addr_t addr; char addrstr[INET_ADDRSTRLEN]; (void) memcpy(&addr, optdata, sizeof (in_addr_t)); if (inet_ntop(AF_INET, &addr, addrstr, INET_ADDRSTRLEN) != NULL) { (void) sprintf(get_line(0, 0), "Source Address = %s", addrstr); } optdata += sizeof (in_addr_t); (void) memcpy(&addr, optdata, sizeof (in_addr_t)); if (inet_ntop(AF_INET, &addr, addrstr, INET_ADDRSTRLEN) != NULL) { (void) sprintf(get_line(0, 0), "Destination Address = %s", addrstr); } } /* * The format of the IP-Compression-Protocol option (rfc1332) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | IP-Compression-Protocol | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Data ... * +-+-+-+-+ * * For VJ Compressed TCP/IP, data consists of: * * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Max-Slot-Id | Comp-Slot-Id | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * For IPHC (rfc2509), data consists of: * * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | TCP_SPACE | NON_TCP_SPACE | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | F_MAX_PERIOD | F_MAX_TIME | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | MAX_HEADER | suboptions... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ static void opt_format_ipcompproto(uchar_t *optdata, uint8_t size) { uint16_t proto; ppp_protoinfo_t *comp_protoinfo; GETINT16(proto, optdata); comp_protoinfo = ppp_getprotoinfo(proto); (void) sprintf(get_line(0, 0), "Protocol = 0x%x (%s)", proto, comp_protoinfo->name); switch (proto) { case PPP_VJC_COMP: { uint8_t maxslotid; uint8_t compslotid; if (size < sizeof (proto) + sizeof (maxslotid) + sizeof (compslotid)) break; GETINT8(maxslotid, optdata); GETINT8(compslotid, optdata); (void) sprintf(get_line(0, 0), "Max-Slot-Id = %d", maxslotid); (void) sprintf(get_line(0, 0), "Comp-Slot Flag = 0x%x", compslotid); break; } case PPP_FULLHDR: { uint16_t tcp_space; uint16_t non_tcp_space; uint16_t f_max_period; uint16_t f_max_time; uint16_t max_header; if (size < sizeof (proto) + sizeof (tcp_space) + sizeof (non_tcp_space) + sizeof (f_max_period) + sizeof (f_max_time) + sizeof (max_header)) break; GETINT16(tcp_space, optdata); GETINT16(non_tcp_space, optdata); GETINT16(f_max_period, optdata); GETINT16(f_max_time, optdata); GETINT16(max_header, optdata); (void) sprintf(get_line(0, 0), "TCP_SPACE = %d", tcp_space); (void) sprintf(get_line(0, 0), "NON_TCP_SPACE = %d", non_tcp_space); (void) sprintf(get_line(0, 0), "F_MAX_PERIOD = %d", f_max_period); (void) sprintf(get_line(0, 0), "F_MAX_TIME = %d", f_max_time); (void) sprintf(get_line(0, 0), "MAX_HEADER = %d octets", max_header); } default: break; } } /* * The format of the IP-Address option (rfc1332) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | IP-Address * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * IP-Address (cont) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_ipaddress(uchar_t *optdata, uint8_t size) { in_addr_t ipaddr; char addrstr[INET_ADDRSTRLEN]; (void) memcpy(&ipaddr, optdata, sizeof (in_addr_t)); if (inet_ntop(AF_INET, &ipaddr, addrstr, INET_ADDRSTRLEN) != NULL) { (void) sprintf(get_line(0, 0), "Address = %s", addrstr); } } /* * The format of the Mobile-IPv4 option (rfc2290) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | Mobile Node's ... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * ... Home Address | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_mobileipv4(uchar_t *optdata, uint8_t size) { in_addr_t ipaddr; char addrstr[INET_ADDRSTRLEN]; (void) memcpy(&ipaddr, optdata, sizeof (in_addr_t)); if (inet_ntop(AF_INET, &ipaddr, addrstr, INET_ADDRSTRLEN) != NULL) { (void) sprintf(get_line(0, 0), "Mobile Node's Home Address = %s", addrstr); } } /* * The format of the Interface-Identifier option (rfc2472) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | Interface-Identifier (MS Bytes) * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * Interface-Identifier (cont) * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * Interface-Identifier (LS Bytes) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_ifaceid(uchar_t *optdata, uint8_t size) { in6_addr_t id; char idstr[INET6_ADDRSTRLEN]; (void) memset(&id, 0, sizeof (in6_addr_t)); (void) memcpy(&id.s6_addr[8], optdata, 8); if (inet_ntop(AF_INET6, &id, idstr, INET6_ADDRSTRLEN) != NULL) { (void) sprintf(get_line(0, 0), "Interface ID = %s", idstr); } } /* * The format of the IPv6-Compression-Protocol option (rfc2472) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | IPv6-Compression-Protocol | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Data ... * +-+-+-+-+ */ static void opt_format_ipv6compproto(uchar_t *optdata, uint8_t size) { uint16_t proto; ppp_protoinfo_t *comp_protoinfo; GETINT16(proto, optdata); comp_protoinfo = ppp_getprotoinfo(proto); (void) sprintf(get_line(0, 0), "Protocol = 0x%x (%s)", proto, comp_protoinfo->name); switch (proto) { case PPP_FULLHDR: { uint16_t tcp_space; uint16_t non_tcp_space; uint16_t f_max_period; uint16_t f_max_time; uint16_t max_header; if (size < sizeof (proto) + sizeof (tcp_space) + sizeof (non_tcp_space) + sizeof (f_max_period) + sizeof (f_max_time) + sizeof (max_header)) return; GETINT16(tcp_space, optdata); GETINT16(non_tcp_space, optdata); GETINT16(f_max_period, optdata); GETINT16(f_max_time, optdata); GETINT16(max_header, optdata); (void) sprintf(get_line(0, 0), "TCP_SPACE = %d", tcp_space); (void) sprintf(get_line(0, 0), "NON_TCP_SPACE = %d", non_tcp_space); (void) sprintf(get_line(0, 0), "F_MAX_PERIOD = %d", f_max_period); (void) sprintf(get_line(0, 0), "F_MAX_TIME = %d", f_max_time); (void) sprintf(get_line(0, 0), "MAX_HEADER = %d octets", max_header); } default: break; } } /* * The format of the Proprietary Compression OUI option (rfc1962) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | OUI ... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * OUI | Subtype | Values... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- */ /*ARGSUSED1*/ static void opt_format_compoui(uchar_t *optdata, uint8_t size) { uint32_t oui; uint8_t subtype; char *ouistr; GETINT32(oui, optdata); subtype = oui & 0x000000ff; oui >>= 8; ouistr = ether_ouiname(oui); if (ouistr == NULL) ouistr = unknown_string; (void) sprintf(get_line(0, 0), "OUI = 0x%06x (%s)", oui, ouistr); (void) sprintf(get_line(0, 0), "Subtype = 0x%x", subtype); } /* * The format of the Stac LZS configuration option (rfc1974) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | History Count | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Check Mode | * +-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_staclzs(uchar_t *optdata, uint8_t size) { uint16_t hcount; uint8_t cmode; GETINT16(hcount, optdata); GETINT8(cmode, optdata); cmode &= 0x07; (void) sprintf(get_line(0, 0), "History Count = %d", hcount); (void) sprintf(get_line(0, 0), "Check Mode = %d", cmode); } /* * The format of MPPC configuration option (rfc2118) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | Supported Bits | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Supported Bits | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_mppc(uchar_t *optdata, uint8_t size) { uint32_t sb; GETINT32(sb, optdata); (void) sprintf(get_line(0, 0), "Supported Bits = 0x%x", sb); } /* * The format of the Gandalf FZA configuration option (rfc1993) is: * * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | History | Version ... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_gandalf(uchar_t *optdata, uint8_t size) { uint8_t history; GETINT8(history, optdata); (void) sprintf(get_line(0, 0), "Maximum History Size = %d bits", history); } /* * The format of the BSD Compress configuration option (rfc1977) is: * * 0 1 2 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | Vers| Dict | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_bsdcomp(uchar_t *optdata, uint8_t size) { uint8_t version; uint8_t codesize; GETINT8(codesize, optdata); version = codesize >> 5; codesize &= 0x1f; (void) sprintf(get_line(0, 0), "Version = 0x%x", version); (void) sprintf(get_line(0, 0), "Maximum Code Size = %d bits", codesize); } /* * The format of the LZS-DCP configuration option (rfc1967) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | History Count | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Check Mode | Process Mode | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_lzsdcp(uchar_t *optdata, uint8_t size) { uint16_t history; uint8_t mode; char *modestr; GETINT16(history, optdata); (void) sprintf(get_line(0, 0), "History Count = %d", history); /* check mode */ GETINT8(mode, optdata); switch (mode) { case 0: modestr = "None"; break; case 1: modestr = "LCB"; break; case 2: modestr = "Sequence Number"; break; case 3: modestr = "Sequence Number + LCB (default)"; break; default: modestr = unknown_string; break; } (void) sprintf(get_line(0, 0), "Check Mode = %d (%s)", mode, modestr); /* process mode */ GETINT8(mode, optdata); switch (mode) { case 0: modestr = "None (default)"; break; case 1: modestr = "Process-Uncompressed"; break; default: modestr = unknown_string; break; } (void) sprintf(get_line(0, 0), "Process Mode = %d (%s)", mode, modestr); } /* * The format of the Magnalink configuration option (rfc1975) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length |FE |P| History | # Contexts | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_magnalink(uchar_t *optdata, uint8_t size) { uint8_t features; uint8_t pflag; uint8_t history; uint8_t contexts; GETINT8(history, optdata); GETINT8(contexts, optdata); features = history >> 6; pflag = (history >> 5) & 0x01; history &= 0x1f; (void) sprintf(get_line(0, 0), "Features = 0x%d", features); (void) sprintf(get_line(0, 0), "Packet Flag = %d", pflag); (void) sprintf(get_line(0, 0), "History Size = %d", history); (void) sprintf(get_line(0, 0), "Contexts = %d", contexts); } /* * The format of the Deflate configuration option (rfc1979) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length |Window | Method| MBZ |Chk| * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_deflate(uchar_t *optdata, uint8_t size) { uint8_t window; uint8_t method; uint8_t chk; GETINT8(method, optdata); window = method >> 4; method &= 0x0f; GETINT8(chk, optdata); chk &= 0x03; (void) sprintf(get_line(0, 0), "Maximum Window Size = %d", window); (void) sprintf(get_line(0, 0), "Compression Method = 0x%x", method); (void) sprintf(get_line(0, 0), "Check Method = 0x%x", chk); } /* * The format of the Proprietary Encryption OUI option (rfc1968) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type | Length | OUI ... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * OUI | Subtype | Values... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- */ /*ARGSUSED1*/ static void opt_format_encroui(uchar_t *optdata, uint8_t size) { uint32_t oui; uint8_t subtype; char *ouistr; GETINT32(oui, optdata); subtype = oui & 0x000000ff; oui >>= 8; ouistr = ether_ouiname(oui); if (ouistr == NULL) ouistr = unknown_string; (void) sprintf(get_line(0, 0), "OUI = 0x%06x (%s)", oui, ouistr); (void) sprintf(get_line(0, 0), "Subtype = 0x%x", subtype); } /* * The format of the DESE, DESE-bis, and 3DESE configuration options * (rfc1969, rfc2419, and rfc2420) are: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 3 | Length | Initial Nonce ... * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_dese(uchar_t *optdata, uint8_t size) { (void) sprintf(get_line(0, 0), "Initial Nonce = 0x%02x%02x%02x%02x%02x%02x%02x%02x", optdata[0], optdata[1], optdata[2], optdata[3], optdata[4], optdata[5], optdata[6], optdata[7]); } /* * The format of the PPPMux Default Protocol Id option * (draft-ietf-pppext-pppmux-02.txt) is: * * 0 1 2 3 * 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 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Type = 1 | Length = 4 | Default PID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /*ARGSUSED1*/ static void opt_format_muxpid(uchar_t *optdata, uint8_t size) { uint16_t defpid; GETINT16(defpid, optdata); (void) sprintf(get_line(0, 0), "Default PID = %d", defpid); }