#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/sysmacros.h>
#include <net/ppp_defs.h>
#include <net/ppp-comp.h>
#include <net/if.h>
#include <netinet/in.h>
#include <netinet/if_ether.h>
#include <arpa/inet.h>
#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;
static char unknown_string[] = "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 {
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);
}
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 {
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:
interpret_cp_options(datap, len, protoinfo);
break;
case CODE_TERMREQ:
case CODE_TERMACK:
(void) sprintf(get_line(0, 0), "Data = %.*s",
length - sizeof (ppp_pkt_t), datap);
show_space();
break;
case CODE_CODEREJ:
prot_nest_prefix = protoinfo->prefix;
interpret_ppp_cp(flags, datap, len, protoinfo);
prot_nest_prefix = "";
break;
case CODE_PROTREJ:
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);
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;
}
case CODE_RESETREQ:
case CODE_RESETACK:
default:
break;
}
}
return (len);
}
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);
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 {
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 {
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 {
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);
}
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);
}
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);
}
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);
}
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;
}
}
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;
}
}
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);
}
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", ""));
}
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);
}
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);
}
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);
}
}
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);
}
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: {
(void) sprintf(get_line(0, 0), "Address = %.*s", addrlen,
addr);
}
default:
break;
}
free(addr);
}
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);
}
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);
}
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);
}
}
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);
}
}
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;
}
}
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);
}
}
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);
}
}
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);
}
}
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;
}
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
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);
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);
}
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);
}
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);
}
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);
}
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]);
}
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);
}