117680Spst/* 239300Sfenner * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 317680Spst * The Regents of the University of California. All rights reserved. 417680Spst * 517680Spst * Redistribution and use in source and binary forms, with or without 617680Spst * modification, are permitted provided that: (1) source code distributions 717680Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817680Spst * distributions including binary code include the above copyright notice and 917680Spst * this paragraph in its entirety in the documentation or other materials 1017680Spst * provided with the distribution, and (3) all advertising materials mentioning 1117680Spst * features or use of this software display the following acknowledgement: 1217680Spst * ``This product includes software developed by the University of California, 1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417680Spst * the University nor the names of its contributors may be used to endorse 1517680Spst * or promote products derived from this software without specific prior 1617680Spst * written permission. 1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2053146Sbrian * 2175118Sfenner * Extensively modified by Motonori Shindo (mshindo@mshindo.net) for more 2275118Sfenner * complete PPP support. 2375118Sfenner * 2453146Sbrian * $FreeBSD: releng/11.0/contrib/tcpdump/print-ppp.c 285275 2015-07-08 16:19:32Z pkelsey $ 2517680Spst */ 2617680Spst 2775118Sfenner/* 2875118Sfenner * TODO: 2975118Sfenner * o resolve XXX as much as possible 3075118Sfenner * o MP support 3175118Sfenner * o BAP support 3275118Sfenner */ 3375118Sfenner 34276788Sdelphij#define NETDISSECT_REWORKED 3556896Sfenner#ifdef HAVE_CONFIG_H 3656896Sfenner#include "config.h" 3756896Sfenner#endif 3856896Sfenner 39127675Sbms#include <tcpdump-stdinc.h> 4017680Spst 4175118Sfenner#ifdef __bsdi__ 4275118Sfenner#include <net/slcompress.h> 4375118Sfenner#include <net/if_ppp.h> 4417680Spst#endif 4517680Spst 46146778Ssam#include <stdlib.h> 4717680Spst 4817680Spst#include "interface.h" 4956896Sfenner#include "extract.h" 5017680Spst#include "addrtoname.h" 5139300Sfenner#include "ppp.h" 5275118Sfenner#include "chdlc.h" 5375118Sfenner#include "ethertype.h" 54146778Ssam#include "oui.h" 5517680Spst 5675118Sfenner/* 5775118Sfenner * The following constatns are defined by IANA. Please refer to 5875118Sfenner * http://www.isi.edu/in-notes/iana/assignments/ppp-numbers 5975118Sfenner * for the up-to-date information. 6075118Sfenner */ 6117680Spst 62127675Sbms/* Protocol Codes defined in ppp.h */ 6317692Spst 64276788Sdelphijstatic const struct tok ppptype2str[] = { 65127675Sbms { PPP_IP, "IP" }, 66127675Sbms { PPP_OSI, "OSI" }, 67127675Sbms { PPP_NS, "NS" }, 68127675Sbms { PPP_DECNET, "DECNET" }, 69127675Sbms { PPP_APPLE, "APPLE" }, 70127675Sbms { PPP_IPX, "IPX" }, 71146778Ssam { PPP_VJC, "VJC IP" }, 72146778Ssam { PPP_VJNC, "VJNC IP" }, 73127675Sbms { PPP_BRPDU, "BRPDU" }, 74127675Sbms { PPP_STII, "STII" }, 75127675Sbms { PPP_VINES, "VINES" }, 76127675Sbms { PPP_MPLS_UCAST, "MPLS" }, 77127675Sbms { PPP_MPLS_MCAST, "MPLS" }, 78146778Ssam { PPP_COMP, "Compressed"}, 79146778Ssam { PPP_ML, "MLPPP"}, 80146778Ssam { PPP_IPV6, "IP6"}, 81127675Sbms 82127675Sbms { PPP_HELLO, "HELLO" }, 83127675Sbms { PPP_LUXCOM, "LUXCOM" }, 84127675Sbms { PPP_SNS, "SNS" }, 85127675Sbms { PPP_IPCP, "IPCP" }, 86127675Sbms { PPP_OSICP, "OSICP" }, 87127675Sbms { PPP_NSCP, "NSCP" }, 88127675Sbms { PPP_DECNETCP, "DECNETCP" }, 89127675Sbms { PPP_APPLECP, "APPLECP" }, 90127675Sbms { PPP_IPXCP, "IPXCP" }, 91127675Sbms { PPP_STIICP, "STIICP" }, 92127675Sbms { PPP_VINESCP, "VINESCP" }, 93146778Ssam { PPP_IPV6CP, "IP6CP" }, 94127675Sbms { PPP_MPLSCP, "MPLSCP" }, 95127675Sbms 96127675Sbms { PPP_LCP, "LCP" }, 97127675Sbms { PPP_PAP, "PAP" }, 98127675Sbms { PPP_LQM, "LQM" }, 99127675Sbms { PPP_CHAP, "CHAP" }, 100146778Ssam { PPP_EAP, "EAP" }, 101146778Ssam { PPP_SPAP, "SPAP" }, 102146778Ssam { PPP_SPAP_OLD, "Old-SPAP" }, 103127675Sbms { PPP_BACP, "BACP" }, 104127675Sbms { PPP_BAP, "BAP" }, 105146778Ssam { PPP_MPCP, "MLPPP-CP" }, 106276788Sdelphij { PPP_CCP, "CCP" }, 107127675Sbms { 0, NULL } 108127675Sbms}; 109127675Sbms 110127675Sbms/* Control Protocols (LCP/IPCP/CCP etc.) Codes defined in RFC 1661 */ 111127675Sbms 11275118Sfenner#define CPCODES_VEXT 0 /* Vendor-Specific (RFC2153) */ 11375118Sfenner#define CPCODES_CONF_REQ 1 /* Configure-Request */ 11475118Sfenner#define CPCODES_CONF_ACK 2 /* Configure-Ack */ 11575118Sfenner#define CPCODES_CONF_NAK 3 /* Configure-Nak */ 11675118Sfenner#define CPCODES_CONF_REJ 4 /* Configure-Reject */ 11775118Sfenner#define CPCODES_TERM_REQ 5 /* Terminate-Request */ 11875118Sfenner#define CPCODES_TERM_ACK 6 /* Terminate-Ack */ 11975118Sfenner#define CPCODES_CODE_REJ 7 /* Code-Reject */ 12075118Sfenner#define CPCODES_PROT_REJ 8 /* Protocol-Reject (LCP only) */ 12175118Sfenner#define CPCODES_ECHO_REQ 9 /* Echo-Request (LCP only) */ 12275118Sfenner#define CPCODES_ECHO_RPL 10 /* Echo-Reply (LCP only) */ 12375118Sfenner#define CPCODES_DISC_REQ 11 /* Discard-Request (LCP only) */ 124127675Sbms#define CPCODES_ID 12 /* Identification (LCP only) RFC1570 */ 125127675Sbms#define CPCODES_TIME_REM 13 /* Time-Remaining (LCP only) RFC1570 */ 126127675Sbms#define CPCODES_RESET_REQ 14 /* Reset-Request (CCP only) RFC1962 */ 12775118Sfenner#define CPCODES_RESET_REP 15 /* Reset-Reply (CCP only) */ 12838638Sthepish 129276788Sdelphijstatic const struct tok cpcodes[] = { 130127675Sbms {CPCODES_VEXT, "Vendor-Extension"}, /* RFC2153 */ 131127675Sbms {CPCODES_CONF_REQ, "Conf-Request"}, 132127675Sbms {CPCODES_CONF_ACK, "Conf-Ack"}, 133127675Sbms {CPCODES_CONF_NAK, "Conf-Nack"}, 134127675Sbms {CPCODES_CONF_REJ, "Conf-Reject"}, 135127675Sbms {CPCODES_TERM_REQ, "Term-Request"}, 136127675Sbms {CPCODES_TERM_ACK, "Term-Ack"}, 137127675Sbms {CPCODES_CODE_REJ, "Code-Reject"}, 138127675Sbms {CPCODES_PROT_REJ, "Prot-Reject"}, 139127675Sbms {CPCODES_ECHO_REQ, "Echo-Request"}, 140127675Sbms {CPCODES_ECHO_RPL, "Echo-Reply"}, 141127675Sbms {CPCODES_DISC_REQ, "Disc-Req"}, 142127675Sbms {CPCODES_ID, "Ident"}, /* RFC1570 */ 143127675Sbms {CPCODES_TIME_REM, "Time-Rem"}, /* RFC1570 */ 144127675Sbms {CPCODES_RESET_REQ, "Reset-Req"}, /* RFC1962 */ 145127675Sbms {CPCODES_RESET_REP, "Reset-Ack"}, /* RFC1962 */ 146127675Sbms {0, NULL} 14738638Sthepish}; 14838638Sthepish 14975118Sfenner/* LCP Config Options */ 15075118Sfenner 15138638Sthepish#define LCPOPT_VEXT 0 15238638Sthepish#define LCPOPT_MRU 1 15338638Sthepish#define LCPOPT_ACCM 2 15438638Sthepish#define LCPOPT_AP 3 15538638Sthepish#define LCPOPT_QP 4 15638638Sthepish#define LCPOPT_MN 5 15775118Sfenner#define LCPOPT_DEP6 6 15838638Sthepish#define LCPOPT_PFC 7 15938638Sthepish#define LCPOPT_ACFC 8 16075118Sfenner#define LCPOPT_FCSALT 9 16175118Sfenner#define LCPOPT_SDP 10 16275118Sfenner#define LCPOPT_NUMMODE 11 16375118Sfenner#define LCPOPT_DEP12 12 16475118Sfenner#define LCPOPT_CBACK 13 16575118Sfenner#define LCPOPT_DEP14 14 16675118Sfenner#define LCPOPT_DEP15 15 16775118Sfenner#define LCPOPT_DEP16 16 16875118Sfenner#define LCPOPT_MLMRRU 17 16975118Sfenner#define LCPOPT_MLSSNHF 18 17075118Sfenner#define LCPOPT_MLED 19 17175118Sfenner#define LCPOPT_PROP 20 17275118Sfenner#define LCPOPT_DCEID 21 17375118Sfenner#define LCPOPT_MPP 22 17475118Sfenner#define LCPOPT_LD 23 17575118Sfenner#define LCPOPT_LCPAOPT 24 17675118Sfenner#define LCPOPT_COBS 25 17775118Sfenner#define LCPOPT_PE 26 17875118Sfenner#define LCPOPT_MLHF 27 17975118Sfenner#define LCPOPT_I18N 28 18075118Sfenner#define LCPOPT_SDLOS 29 18175118Sfenner#define LCPOPT_PPPMUX 30 18238638Sthepish 18375118Sfenner#define LCPOPT_MIN LCPOPT_VEXT 18475118Sfenner#define LCPOPT_MAX LCPOPT_PPPMUX 18538638Sthepish 18675118Sfennerstatic const char *lcpconfopts[] = { 18775118Sfenner "Vend-Ext", /* (0) */ 18875118Sfenner "MRU", /* (1) */ 18975118Sfenner "ACCM", /* (2) */ 19075118Sfenner "Auth-Prot", /* (3) */ 19175118Sfenner "Qual-Prot", /* (4) */ 19275118Sfenner "Magic-Num", /* (5) */ 19375118Sfenner "deprecated(6)", /* used to be a Quality Protocol */ 19475118Sfenner "PFC", /* (7) */ 19575118Sfenner "ACFC", /* (8) */ 19675118Sfenner "FCS-Alt", /* (9) */ 19775118Sfenner "SDP", /* (10) */ 19875118Sfenner "Num-Mode", /* (11) */ 19975118Sfenner "deprecated(12)", /* used to be a Multi-Link-Procedure*/ 20075118Sfenner "Call-Back", /* (13) */ 20175118Sfenner "deprecated(14)", /* used to be a Connect-Time */ 20275118Sfenner "deprecated(15)", /* used to be a Compund-Frames */ 20375118Sfenner "deprecated(16)", /* used to be a Nominal-Data-Encap */ 20475118Sfenner "MRRU", /* (17) */ 205146778Ssam "12-Bit seq #", /* (18) */ 20675118Sfenner "End-Disc", /* (19) */ 20775118Sfenner "Proprietary", /* (20) */ 20875118Sfenner "DCE-Id", /* (21) */ 20975118Sfenner "MP+", /* (22) */ 21075118Sfenner "Link-Disc", /* (23) */ 21175118Sfenner "LCP-Auth-Opt", /* (24) */ 21275118Sfenner "COBS", /* (25) */ 21375118Sfenner "Prefix-elision", /* (26) */ 21475118Sfenner "Multilink-header-Form",/* (27) */ 21575118Sfenner "I18N", /* (28) */ 21675118Sfenner "SDL-over-SONET/SDH", /* (29) */ 21775118Sfenner "PPP-Muxing", /* (30) */ 21838638Sthepish}; 21938638Sthepish 22075118Sfenner/* ECP - to be supported */ 22175118Sfenner 22275118Sfenner/* CCP Config Options */ 22375118Sfenner 22475118Sfenner#define CCPOPT_OUI 0 /* RFC1962 */ 22575118Sfenner#define CCPOPT_PRED1 1 /* RFC1962 */ 22675118Sfenner#define CCPOPT_PRED2 2 /* RFC1962 */ 22775118Sfenner#define CCPOPT_PJUMP 3 /* RFC1962 */ 22875118Sfenner/* 4-15 unassigned */ 22975118Sfenner#define CCPOPT_HPPPC 16 /* RFC1962 */ 23075118Sfenner#define CCPOPT_STACLZS 17 /* RFC1974 */ 23175118Sfenner#define CCPOPT_MPPC 18 /* RFC2118 */ 23275118Sfenner#define CCPOPT_GFZA 19 /* RFC1962 */ 23375118Sfenner#define CCPOPT_V42BIS 20 /* RFC1962 */ 23475118Sfenner#define CCPOPT_BSDCOMP 21 /* RFC1977 */ 23575118Sfenner/* 22 unassigned */ 23675118Sfenner#define CCPOPT_LZSDCP 23 /* RFC1967 */ 23775118Sfenner#define CCPOPT_MVRCA 24 /* RFC1975 */ 23875118Sfenner#define CCPOPT_DEC 25 /* RFC1976 */ 23975118Sfenner#define CCPOPT_DEFLATE 26 /* RFC1979 */ 24075118Sfenner/* 27-254 unassigned */ 24175118Sfenner#define CCPOPT_RESV 255 /* RFC1962 */ 24275118Sfenner 243276788Sdelphijstatic const struct tok ccpconfopts_values[] = { 244147904Ssam { CCPOPT_OUI, "OUI" }, 245147904Ssam { CCPOPT_PRED1, "Pred-1" }, 246147904Ssam { CCPOPT_PRED2, "Pred-2" }, 247147904Ssam { CCPOPT_PJUMP, "Puddle" }, 248147904Ssam { CCPOPT_HPPPC, "HP-PPC" }, 249147904Ssam { CCPOPT_STACLZS, "Stac-LZS" }, 250147904Ssam { CCPOPT_MPPC, "MPPC" }, 251147904Ssam { CCPOPT_GFZA, "Gand-FZA" }, 252147904Ssam { CCPOPT_V42BIS, "V.42bis" }, 253147904Ssam { CCPOPT_BSDCOMP, "BSD-Comp" }, 254147904Ssam { CCPOPT_LZSDCP, "LZS-DCP" }, 255147904Ssam { CCPOPT_MVRCA, "MVRCA" }, 256147904Ssam { CCPOPT_DEC, "DEC" }, 257147904Ssam { CCPOPT_DEFLATE, "Deflate" }, 258147904Ssam { CCPOPT_RESV, "Reserved"}, 259147904Ssam {0, NULL} 26075118Sfenner}; 26175118Sfenner 26275118Sfenner/* BACP Config Options */ 26375118Sfenner 26475118Sfenner#define BACPOPT_FPEER 1 /* RFC2125 */ 26575118Sfenner 266276788Sdelphijstatic const struct tok bacconfopts_values[] = { 267147904Ssam { BACPOPT_FPEER, "Favored-Peer" }, 268147904Ssam {0, NULL} 269147904Ssam}; 270147904Ssam 271147904Ssam 27275118Sfenner/* SDCP - to be supported */ 27375118Sfenner 27475118Sfenner/* IPCP Config Options */ 27575118Sfenner#define IPCPOPT_2ADDR 1 /* RFC1172, RFC1332 (deprecated) */ 27675118Sfenner#define IPCPOPT_IPCOMP 2 /* RFC1332 */ 27775118Sfenner#define IPCPOPT_ADDR 3 /* RFC1332 */ 27875118Sfenner#define IPCPOPT_MOBILE4 4 /* RFC2290 */ 27975118Sfenner#define IPCPOPT_PRIDNS 129 /* RFC1877 */ 28075118Sfenner#define IPCPOPT_PRINBNS 130 /* RFC1877 */ 28175118Sfenner#define IPCPOPT_SECDNS 131 /* RFC1877 */ 28275118Sfenner#define IPCPOPT_SECNBNS 132 /* RFC1877 */ 28375118Sfenner 284276788Sdelphijstatic const struct tok ipcpopt_values[] = { 285146778Ssam { IPCPOPT_2ADDR, "IP-Addrs" }, 286146778Ssam { IPCPOPT_IPCOMP, "IP-Comp" }, 287146778Ssam { IPCPOPT_ADDR, "IP-Addr" }, 288146778Ssam { IPCPOPT_MOBILE4, "Home-Addr" }, 289146778Ssam { IPCPOPT_PRIDNS, "Pri-DNS" }, 290146778Ssam { IPCPOPT_PRINBNS, "Pri-NBNS" }, 291146778Ssam { IPCPOPT_SECDNS, "Sec-DNS" }, 292146778Ssam { IPCPOPT_SECNBNS, "Sec-NBNS" }, 293146778Ssam { 0, NULL } 294146778Ssam}; 295146778Ssam 296172686Smlaier#define IPCPOPT_IPCOMP_HDRCOMP 0x61 /* rfc3544 */ 297172686Smlaier#define IPCPOPT_IPCOMP_MINLEN 14 298146778Ssam 299276788Sdelphijstatic const struct tok ipcpopt_compproto_values[] = { 300172686Smlaier { PPP_VJC, "VJ-Comp" }, 301172686Smlaier { IPCPOPT_IPCOMP_HDRCOMP, "IP Header Compression" }, 302172686Smlaier { 0, NULL } 303172686Smlaier}; 304172686Smlaier 305276788Sdelphijstatic const struct tok ipcpopt_compproto_subopt_values[] = { 306172686Smlaier { 1, "RTP-Compression" }, 307172686Smlaier { 2, "Enhanced RTP-Compression" }, 308172686Smlaier { 0, NULL } 309172686Smlaier}; 310172686Smlaier 311146778Ssam/* IP6CP Config Options */ 312146778Ssam#define IP6CP_IFID 1 313146778Ssam 314276788Sdelphijstatic const struct tok ip6cpopt_values[] = { 315146778Ssam { IP6CP_IFID, "Interface-ID" }, 316146778Ssam { 0, NULL } 317146778Ssam}; 318146778Ssam 31975118Sfenner/* ATCP - to be supported */ 32075118Sfenner/* OSINLCP - to be supported */ 32175118Sfenner/* BVCP - to be supported */ 32275118Sfenner/* BCP - to be supported */ 32375118Sfenner/* IPXCP - to be supported */ 324127675Sbms/* MPLSCP - to be supported */ 32575118Sfenner 32675118Sfenner/* Auth Algorithms */ 32775118Sfenner 32875118Sfenner/* 0-4 Reserved (RFC1994) */ 32975118Sfenner#define AUTHALG_CHAPMD5 5 /* RFC1994 */ 33075118Sfenner#define AUTHALG_MSCHAP1 128 /* RFC2433 */ 33175118Sfenner#define AUTHALG_MSCHAP2 129 /* RFC2795 */ 33275118Sfenner 333276788Sdelphijstatic const struct tok authalg_values[] = { 334146778Ssam { AUTHALG_CHAPMD5, "MD5" }, 335146778Ssam { AUTHALG_MSCHAP1, "MS-CHAPv1" }, 336146778Ssam { AUTHALG_MSCHAP2, "MS-CHAPv2" }, 337146778Ssam { 0, NULL } 338146778Ssam}; 339146778Ssam 34075118Sfenner/* FCS Alternatives - to be supported */ 34175118Sfenner 34275118Sfenner/* Multilink Endpoint Discriminator (RFC1717) */ 34375118Sfenner#define MEDCLASS_NULL 0 /* Null Class */ 34475118Sfenner#define MEDCLASS_LOCAL 1 /* Locally Assigned */ 34575118Sfenner#define MEDCLASS_IPV4 2 /* Internet Protocol (IPv4) */ 34675118Sfenner#define MEDCLASS_MAC 3 /* IEEE 802.1 global MAC address */ 34775118Sfenner#define MEDCLASS_MNB 4 /* PPP Magic Number Block */ 34875118Sfenner#define MEDCLASS_PSNDN 5 /* Public Switched Network Director Number */ 34975118Sfenner 35075118Sfenner/* PPP LCP Callback */ 35175118Sfenner#define CALLBACK_AUTH 0 /* Location determined by user auth */ 35275118Sfenner#define CALLBACK_DSTR 1 /* Dialing string */ 35375118Sfenner#define CALLBACK_LID 2 /* Location identifier */ 35475118Sfenner#define CALLBACK_E164 3 /* E.164 number */ 35575118Sfenner#define CALLBACK_X500 4 /* X.500 distinguished name */ 35675118Sfenner#define CALLBACK_CBCP 6 /* Location is determined during CBCP nego */ 35775118Sfenner 358276788Sdelphijstatic const struct tok ppp_callback_values[] = { 359147904Ssam { CALLBACK_AUTH, "UserAuth" }, 360147904Ssam { CALLBACK_DSTR, "DialString" }, 361147904Ssam { CALLBACK_LID, "LocalID" }, 362147904Ssam { CALLBACK_E164, "E.164" }, 363147904Ssam { CALLBACK_X500, "X.500" }, 364147904Ssam { CALLBACK_CBCP, "CBCP" }, 365147904Ssam { 0, NULL } 366147904Ssam}; 367147904Ssam 36838638Sthepish/* CHAP */ 36938638Sthepish 37038638Sthepish#define CHAP_CHAL 1 37138638Sthepish#define CHAP_RESP 2 37238638Sthepish#define CHAP_SUCC 3 37338638Sthepish#define CHAP_FAIL 4 37438638Sthepish 375276788Sdelphijstatic const struct tok chapcode_values[] = { 376146778Ssam { CHAP_CHAL, "Challenge" }, 377146778Ssam { CHAP_RESP, "Response" }, 378146778Ssam { CHAP_SUCC, "Success" }, 379146778Ssam { CHAP_FAIL, "Fail" }, 380146778Ssam { 0, NULL} 38138638Sthepish}; 38238638Sthepish 38338638Sthepish/* PAP */ 38438638Sthepish 38538638Sthepish#define PAP_AREQ 1 38638638Sthepish#define PAP_AACK 2 38738638Sthepish#define PAP_ANAK 3 38838638Sthepish 389276788Sdelphijstatic const struct tok papcode_values[] = { 390146778Ssam { PAP_AREQ, "Auth-Req" }, 391146778Ssam { PAP_AACK, "Auth-ACK" }, 392146778Ssam { PAP_ANAK, "Auth-NACK" }, 393146778Ssam { 0, NULL } 39438638Sthepish}; 39538638Sthepish 39675118Sfenner/* BAP */ 39775118Sfenner#define BAP_CALLREQ 1 39875118Sfenner#define BAP_CALLRES 2 39975118Sfenner#define BAP_CBREQ 3 40075118Sfenner#define BAP_CBRES 4 40175118Sfenner#define BAP_LDQREQ 5 40275118Sfenner#define BAP_LDQRES 6 40375118Sfenner#define BAP_CSIND 7 40475118Sfenner#define BAP_CSRES 8 40538638Sthepish 406276788Sdelphijstatic int print_lcp_config_options(netdissect_options *, const u_char *p, int); 407276788Sdelphijstatic int print_ipcp_config_options(netdissect_options *, const u_char *p, int); 408276788Sdelphijstatic int print_ip6cp_config_options(netdissect_options *, const u_char *p, int); 409276788Sdelphijstatic int print_ccp_config_options(netdissect_options *, const u_char *p, int); 410276788Sdelphijstatic int print_bacp_config_options(netdissect_options *, const u_char *p, int); 411276788Sdelphijstatic void handle_ppp(netdissect_options *, u_int proto, const u_char *p, int length); 41238638Sthepish 41375118Sfenner/* generic Control Protocol (e.g. LCP, IPCP, CCP, etc.) handler */ 41456896Sfennerstatic void 415276788Sdelphijhandle_ctrl_proto(netdissect_options *ndo, 416276788Sdelphij u_int proto, const u_char *pptr, int length) 41717680Spst{ 418127675Sbms const char *typestr; 41975118Sfenner u_int code, len; 420276788Sdelphij int (*pfunc)(netdissect_options *, const u_char *, int); 42138638Sthepish int x, j; 422127675Sbms const u_char *tptr; 42317680Spst 424127675Sbms tptr=pptr; 42532149Spst 426146778Ssam typestr = tok2str(ppptype2str, "unknown ctrl-proto (0x%04x)", proto); 427276788Sdelphij ND_PRINT((ndo, "%s, ", typestr)); 42832149Spst 429127675Sbms if (length < 4) /* FIXME weak boundary checking */ 430127675Sbms goto trunc; 431276788Sdelphij ND_TCHECK2(*tptr, 2); 43275118Sfenner 433127675Sbms code = *tptr++; 43475118Sfenner 435276788Sdelphij ND_PRINT((ndo, "%s (0x%02x), id %u, length %u", 436276788Sdelphij tok2str(cpcodes, "Unknown Opcode",code), 437276788Sdelphij code, 438276788Sdelphij *tptr++, /* ID */ 439276788Sdelphij length + 2)); 440147904Ssam 441276788Sdelphij if (!ndo->ndo_vflag) 442276788Sdelphij return; 443276788Sdelphij 444147904Ssam if (length <= 4) 445147904Ssam return; /* there may be a NULL confreq etc. */ 446147904Ssam 447276788Sdelphij ND_TCHECK2(*tptr, 2); 448127675Sbms len = EXTRACT_16BITS(tptr); 449127675Sbms tptr += 2; 450127675Sbms 451276788Sdelphij ND_PRINT((ndo, "\n\tencoded length %u (=Option(s) length %u)", len, len - 4)); 45275118Sfenner 453276788Sdelphij if (ndo->ndo_vflag > 1) 454276788Sdelphij print_unknown_data(ndo, pptr - 2, "\n\t", 6); 455147904Ssam 456147904Ssam 45775118Sfenner switch (code) { 45875118Sfenner case CPCODES_VEXT: 45975118Sfenner if (length < 11) 46075118Sfenner break; 461276788Sdelphij ND_TCHECK2(*tptr, 4); 462276788Sdelphij ND_PRINT((ndo, "\n\t Magic-Num 0x%08x", EXTRACT_32BITS(tptr))); 463127675Sbms tptr += 4; 464276788Sdelphij ND_TCHECK2(*tptr, 3); 465276788Sdelphij ND_PRINT((ndo, " Vendor: %s (%u)", 466146778Ssam tok2str(oui_values,"Unknown",EXTRACT_24BITS(tptr)), 467276788Sdelphij EXTRACT_24BITS(tptr))); 46875118Sfenner /* XXX: need to decode Kind and Value(s)? */ 46975118Sfenner break; 47075118Sfenner case CPCODES_CONF_REQ: 47175118Sfenner case CPCODES_CONF_ACK: 47275118Sfenner case CPCODES_CONF_NAK: 47375118Sfenner case CPCODES_CONF_REJ: 47475118Sfenner x = len - 4; /* Code(1), Identifier(1) and Length(2) */ 47556896Sfenner do { 47675118Sfenner switch (proto) { 47775118Sfenner case PPP_LCP: 47875118Sfenner pfunc = print_lcp_config_options; 47956896Sfenner break; 48075118Sfenner case PPP_IPCP: 48175118Sfenner pfunc = print_ipcp_config_options; 48275118Sfenner break; 483146778Ssam case PPP_IPV6CP: 484146778Ssam pfunc = print_ip6cp_config_options; 485146778Ssam break; 48675118Sfenner case PPP_CCP: 48775118Sfenner pfunc = print_ccp_config_options; 48875118Sfenner break; 48975118Sfenner case PPP_BACP: 49075118Sfenner pfunc = print_bacp_config_options; 49175118Sfenner break; 49275118Sfenner default: 49375118Sfenner /* 494146778Ssam * No print routine for the options for 495146778Ssam * this protocol. 49675118Sfenner */ 49775118Sfenner pfunc = NULL; 49875118Sfenner break; 49975118Sfenner } 500140744Sbms 501146778Ssam if (pfunc == NULL) /* catch the above null pointer if unknown CP */ 502146778Ssam break; 503276788Sdelphij 504276788Sdelphij if ((j = (*pfunc)(ndo, tptr, len)) == 0) 50575118Sfenner break; 50656896Sfenner x -= j; 507127675Sbms tptr += j; 50856896Sfenner } while (x > 0); 50956896Sfenner break; 51032149Spst 51175118Sfenner case CPCODES_TERM_REQ: 51275118Sfenner case CPCODES_TERM_ACK: 51375118Sfenner /* XXX: need to decode Data? */ 51456896Sfenner break; 51575118Sfenner case CPCODES_CODE_REJ: 51675118Sfenner /* XXX: need to decode Rejected-Packet? */ 51775118Sfenner break; 51875118Sfenner case CPCODES_PROT_REJ: 51975118Sfenner if (length < 6) 52075118Sfenner break; 521276788Sdelphij ND_TCHECK2(*tptr, 2); 522276788Sdelphij ND_PRINT((ndo, "\n\t Rejected %s Protocol (0x%04x)", 523127675Sbms tok2str(ppptype2str,"unknown", EXTRACT_16BITS(tptr)), 524276788Sdelphij EXTRACT_16BITS(tptr))); 525147904Ssam /* XXX: need to decode Rejected-Information? - hexdump for now */ 526276788Sdelphij if (len > 6) { 527276788Sdelphij ND_PRINT((ndo, "\n\t Rejected Packet")); 528276788Sdelphij print_unknown_data(ndo, tptr + 2, "\n\t ", len - 2); 529276788Sdelphij } 53075118Sfenner break; 53175118Sfenner case CPCODES_ECHO_REQ: 53275118Sfenner case CPCODES_ECHO_RPL: 53375118Sfenner case CPCODES_DISC_REQ: 534147904Ssam if (length < 8) 535147904Ssam break; 536276788Sdelphij ND_TCHECK2(*tptr, 4); 537276788Sdelphij ND_PRINT((ndo, "\n\t Magic-Num 0x%08x", EXTRACT_32BITS(tptr))); 538147904Ssam /* XXX: need to decode Data? - hexdump for now */ 539276788Sdelphij if (len > 8) { 540276788Sdelphij ND_PRINT((ndo, "\n\t -----trailing data-----")); 541276788Sdelphij ND_TCHECK2(tptr[4], len - 8); 542276788Sdelphij print_unknown_data(ndo, tptr + 4, "\n\t ", len - 8); 543276788Sdelphij } 544147904Ssam break; 54575118Sfenner case CPCODES_ID: 54675118Sfenner if (length < 8) 54775118Sfenner break; 548276788Sdelphij ND_TCHECK2(*tptr, 4); 549276788Sdelphij ND_PRINT((ndo, "\n\t Magic-Num 0x%08x", EXTRACT_32BITS(tptr))); 550147904Ssam /* RFC 1661 says this is intended to be human readable */ 551276788Sdelphij if (len > 8) { 552276788Sdelphij ND_PRINT((ndo, "\n\t Message\n\t ")); 553276788Sdelphij if (fn_printn(ndo, tptr + 4, len - 4, ndo->ndo_snapend)) 554276788Sdelphij goto trunc; 555276788Sdelphij } 55675118Sfenner break; 55775118Sfenner case CPCODES_TIME_REM: 55875118Sfenner if (length < 12) 55975118Sfenner break; 560276788Sdelphij ND_TCHECK2(*tptr, 4); 561276788Sdelphij ND_PRINT((ndo, "\n\t Magic-Num 0x%08x", EXTRACT_32BITS(tptr))); 562276788Sdelphij ND_TCHECK2(*(tptr + 4), 4); 563276788Sdelphij ND_PRINT((ndo, ", Seconds-Remaining %us", EXTRACT_32BITS(tptr + 4))); 56475118Sfenner /* XXX: need to decode Message? */ 56575118Sfenner break; 56656896Sfenner default: 567276788Sdelphij /* XXX this is dirty but we do not get the 568276788Sdelphij * original pointer passed to the begin 569276788Sdelphij * the PPP packet */ 570276788Sdelphij if (ndo->ndo_vflag <= 1) 571276788Sdelphij print_unknown_data(ndo, pptr - 2, "\n\t ", length + 2); 57256896Sfenner break; 57338638Sthepish } 574127675Sbms return; 575127675Sbms 576127675Sbmstrunc: 577276788Sdelphij ND_PRINT((ndo, "[|%s]", typestr)); 57838638Sthepish} 57932149Spst 58038638Sthepish/* LCP config options */ 58138638Sthepishstatic int 582276788Sdelphijprint_lcp_config_options(netdissect_options *ndo, 583276788Sdelphij const u_char *p, int length) 58438638Sthepish{ 58575118Sfenner int len, opt; 58675118Sfenner 58775118Sfenner if (length < 2) 58875118Sfenner return 0; 589276788Sdelphij ND_TCHECK2(*p, 2); 59075118Sfenner len = p[1]; 59175118Sfenner opt = p[0]; 59275118Sfenner if (length < len) 59375118Sfenner return 0; 594147904Ssam if (len < 2) { 595147904Ssam if ((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX)) 596276788Sdelphij ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u (length bogus, should be >= 2)", 597276788Sdelphij lcpconfopts[opt], opt, len)); 598147904Ssam else 599276788Sdelphij ND_PRINT((ndo, "\n\tunknown LCP option 0x%02x", opt)); 600147904Ssam return 0; 601147904Ssam } 60256896Sfenner if ((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX)) 603276788Sdelphij ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u", lcpconfopts[opt], opt, len)); 60475118Sfenner else { 605276788Sdelphij ND_PRINT((ndo, "\n\tunknown LCP option 0x%02x", opt)); 60675118Sfenner return len; 60775118Sfenner } 60838638Sthepish 60956896Sfenner switch (opt) { 61075118Sfenner case LCPOPT_VEXT: 611276788Sdelphij if (len < 6) { 612276788Sdelphij ND_PRINT((ndo, " (length bogus, should be >= 6)")); 613276788Sdelphij return len; 614276788Sdelphij } 615276788Sdelphij ND_TCHECK2(*(p + 2), 3); 616276788Sdelphij ND_PRINT((ndo, ": Vendor: %s (%u)", 617276788Sdelphij tok2str(oui_values,"Unknown",EXTRACT_24BITS(p+2)), 618276788Sdelphij EXTRACT_24BITS(p + 2))); 61975118Sfenner#if 0 620276788Sdelphij ND_TCHECK(p[5]); 621276788Sdelphij ND_PRINT((ndo, ", kind: 0x%02x", p[5])); 622276788Sdelphij ND_PRINT((ndo, ", Value: 0x")); 623276788Sdelphij for (i = 0; i < len - 6; i++) { 624276788Sdelphij ND_TCHECK(p[6 + i]); 625276788Sdelphij ND_PRINT((ndo, "%02x", p[6 + i])); 626276788Sdelphij } 62775118Sfenner#endif 62875118Sfenner break; 62956896Sfenner case LCPOPT_MRU: 630276788Sdelphij if (len != 4) { 631276788Sdelphij ND_PRINT((ndo, " (length bogus, should be = 4)")); 632276788Sdelphij return len; 633127675Sbms } 634276788Sdelphij ND_TCHECK2(*(p + 2), 2); 635276788Sdelphij ND_PRINT((ndo, ": %u", EXTRACT_16BITS(p + 2))); 63656896Sfenner break; 63775118Sfenner case LCPOPT_ACCM: 638276788Sdelphij if (len != 6) { 639276788Sdelphij ND_PRINT((ndo, " (length bogus, should be = 6)")); 640276788Sdelphij return len; 641127675Sbms } 642276788Sdelphij ND_TCHECK2(*(p + 2), 4); 643276788Sdelphij ND_PRINT((ndo, ": 0x%08x", EXTRACT_32BITS(p + 2))); 64475118Sfenner break; 64556896Sfenner case LCPOPT_AP: 646276788Sdelphij if (len < 4) { 647276788Sdelphij ND_PRINT((ndo, " (length bogus, should be >= 4)")); 648276788Sdelphij return len; 649276788Sdelphij } 650276788Sdelphij ND_TCHECK2(*(p + 2), 2); 651276788Sdelphij ND_PRINT((ndo, ": %s", tok2str(ppptype2str, "Unknown Auth Proto (0x04x)", EXTRACT_16BITS(p + 2)))); 652146778Ssam 653276788Sdelphij switch (EXTRACT_16BITS(p+2)) { 654276788Sdelphij case PPP_CHAP: 655276788Sdelphij ND_TCHECK(p[4]); 656276788Sdelphij ND_PRINT((ndo, ", %s", tok2str(authalg_values, "Unknown Auth Alg %u", p[4]))); 657127675Sbms break; 658276788Sdelphij case PPP_PAP: /* fall through */ 659276788Sdelphij case PPP_EAP: 660276788Sdelphij case PPP_SPAP: 661276788Sdelphij case PPP_SPAP_OLD: 662146778Ssam break; 663276788Sdelphij default: 664276788Sdelphij print_unknown_data(ndo, p, "\n\t", len); 66556896Sfenner } 66656896Sfenner break; 66756896Sfenner case LCPOPT_QP: 668276788Sdelphij if (len < 4) { 669276788Sdelphij ND_PRINT((ndo, " (length bogus, should be >= 4)")); 670276788Sdelphij return 0; 67156896Sfenner } 672276788Sdelphij ND_TCHECK2(*(p + 2), 2); 673276788Sdelphij if (EXTRACT_16BITS(p+2) == PPP_LQM) 674276788Sdelphij ND_PRINT((ndo, ": LQR")); 675276788Sdelphij else 676276788Sdelphij ND_PRINT((ndo, ": unknown")); 67756896Sfenner break; 67856896Sfenner case LCPOPT_MN: 679276788Sdelphij if (len != 6) { 680276788Sdelphij ND_PRINT((ndo, " (length bogus, should be = 6)")); 681276788Sdelphij return 0; 682127675Sbms } 683276788Sdelphij ND_TCHECK2(*(p + 2), 4); 684276788Sdelphij ND_PRINT((ndo, ": 0x%08x", EXTRACT_32BITS(p + 2))); 68556896Sfenner break; 68656896Sfenner case LCPOPT_PFC: 68756896Sfenner break; 68856896Sfenner case LCPOPT_ACFC: 68956896Sfenner break; 69075118Sfenner case LCPOPT_LD: 691276788Sdelphij if (len != 4) { 692276788Sdelphij ND_PRINT((ndo, " (length bogus, should be = 4)")); 693276788Sdelphij return 0; 694127675Sbms } 695276788Sdelphij ND_TCHECK2(*(p + 2), 2); 696276788Sdelphij ND_PRINT((ndo, ": 0x%04x", EXTRACT_16BITS(p + 2))); 69775118Sfenner break; 69875118Sfenner case LCPOPT_CBACK: 699276788Sdelphij if (len < 3) { 700276788Sdelphij ND_PRINT((ndo, " (length bogus, should be >= 3)")); 701276788Sdelphij return 0; 702276788Sdelphij } 703276788Sdelphij ND_PRINT((ndo, ": ")); 704276788Sdelphij ND_TCHECK(p[2]); 705276788Sdelphij ND_PRINT((ndo, ": Callback Operation %s (%u)", 706276788Sdelphij tok2str(ppp_callback_values, "Unknown", p[2]), 707276788Sdelphij p[2])); 70875118Sfenner break; 70975118Sfenner case LCPOPT_MLMRRU: 710276788Sdelphij if (len != 4) { 711276788Sdelphij ND_PRINT((ndo, " (length bogus, should be = 4)")); 712276788Sdelphij return 0; 713127675Sbms } 714276788Sdelphij ND_TCHECK2(*(p + 2), 2); 715276788Sdelphij ND_PRINT((ndo, ": %u", EXTRACT_16BITS(p + 2))); 71675118Sfenner break; 71775118Sfenner case LCPOPT_MLED: 718276788Sdelphij if (len < 3) { 719276788Sdelphij ND_PRINT((ndo, " (length bogus, should be >= 3)")); 720276788Sdelphij return 0; 721276788Sdelphij } 722276788Sdelphij ND_TCHECK(p[2]); 72375118Sfenner switch (p[2]) { /* class */ 72475118Sfenner case MEDCLASS_NULL: 725276788Sdelphij ND_PRINT((ndo, ": Null")); 72675118Sfenner break; 72775118Sfenner case MEDCLASS_LOCAL: 728276788Sdelphij ND_PRINT((ndo, ": Local")); /* XXX */ 72975118Sfenner break; 73075118Sfenner case MEDCLASS_IPV4: 731276788Sdelphij if (len != 7) { 732276788Sdelphij ND_PRINT((ndo, " (length bogus, should be = 7)")); 733276788Sdelphij return 0; 734276788Sdelphij } 735276788Sdelphij ND_TCHECK2(*(p + 3), 4); 736276788Sdelphij ND_PRINT((ndo, ": IPv4 %s", ipaddr_string(ndo, p + 3))); 73775118Sfenner break; 73875118Sfenner case MEDCLASS_MAC: 739276788Sdelphij if (len != 9) { 740276788Sdelphij ND_PRINT((ndo, " (length bogus, should be = 9)")); 741276788Sdelphij return 0; 742276788Sdelphij } 743276788Sdelphij ND_TCHECK2(*(p + 3), 6); 744276788Sdelphij ND_PRINT((ndo, ": MAC %s", etheraddr_string(ndo, p + 3))); 74575118Sfenner break; 74675118Sfenner case MEDCLASS_MNB: 747276788Sdelphij ND_PRINT((ndo, ": Magic-Num-Block")); /* XXX */ 74875118Sfenner break; 74975118Sfenner case MEDCLASS_PSNDN: 750276788Sdelphij ND_PRINT((ndo, ": PSNDN")); /* XXX */ 75175118Sfenner break; 752276788Sdelphij default: 753276788Sdelphij ND_PRINT((ndo, ": Unknown class %u", p[2])); 754276788Sdelphij break; 75575118Sfenner } 75675118Sfenner break; 75775118Sfenner 75875118Sfenner/* XXX: to be supported */ 75975118Sfenner#if 0 76075118Sfenner case LCPOPT_DEP6: 76175118Sfenner case LCPOPT_FCSALT: 76275118Sfenner case LCPOPT_SDP: 76375118Sfenner case LCPOPT_NUMMODE: 76475118Sfenner case LCPOPT_DEP12: 76575118Sfenner case LCPOPT_DEP14: 76675118Sfenner case LCPOPT_DEP15: 76775118Sfenner case LCPOPT_DEP16: 768146778Ssam case LCPOPT_MLSSNHF: 76975118Sfenner case LCPOPT_PROP: 77075118Sfenner case LCPOPT_DCEID: 77175118Sfenner case LCPOPT_MPP: 77275118Sfenner case LCPOPT_LCPAOPT: 77375118Sfenner case LCPOPT_COBS: 77475118Sfenner case LCPOPT_PE: 77575118Sfenner case LCPOPT_MLHF: 77675118Sfenner case LCPOPT_I18N: 77775118Sfenner case LCPOPT_SDLOS: 77875118Sfenner case LCPOPT_PPPMUX: 77975118Sfenner break; 78075118Sfenner#endif 781276788Sdelphij default: 782276788Sdelphij /* 783276788Sdelphij * Unknown option; dump it as raw bytes now if we're 784276788Sdelphij * not going to do so below. 785276788Sdelphij */ 786276788Sdelphij if (ndo->ndo_vflag < 2) 787276788Sdelphij print_unknown_data(ndo, &p[2], "\n\t ", len - 2); 788276788Sdelphij break; 78938638Sthepish } 790147904Ssam 791276788Sdelphij if (ndo->ndo_vflag > 1) 792276788Sdelphij print_unknown_data(ndo, &p[2], "\n\t ", len - 2); /* exclude TLV header */ 793276788Sdelphij 79456896Sfenner return len; 795127675Sbms 796127675Sbmstrunc: 797276788Sdelphij ND_PRINT((ndo, "[|lcp]")); 798127675Sbms return 0; 79938638Sthepish} 80038638Sthepish 801146778Ssam/* ML-PPP*/ 802276788Sdelphijstatic const struct tok ppp_ml_flag_values[] = { 803146778Ssam { 0x80, "begin" }, 804146778Ssam { 0x40, "end" }, 805146778Ssam { 0, NULL } 806146778Ssam}; 807146778Ssam 808146778Ssamstatic void 809276788Sdelphijhandle_mlppp(netdissect_options *ndo, 810285275Spkelsey const u_char *p, int length) 811285275Spkelsey{ 812276788Sdelphij if (!ndo->ndo_eflag) 813276788Sdelphij ND_PRINT((ndo, "MLPPP, ")); 814146778Ssam 815276788Sdelphij ND_PRINT((ndo, "seq 0x%03x, Flags [%s], length %u", 816146778Ssam (EXTRACT_16BITS(p))&0x0fff, /* only support 12-Bit sequence space for now */ 817146778Ssam bittok2str(ppp_ml_flag_values, "none", *p & 0xc0), 818276788Sdelphij length)); 819146778Ssam} 820146778Ssam 82138638Sthepish/* CHAP */ 82256896Sfennerstatic void 823276788Sdelphijhandle_chap(netdissect_options *ndo, 824276788Sdelphij const u_char *p, int length) 82538638Sthepish{ 82675118Sfenner u_int code, len; 82775118Sfenner int val_size, name_size, msg_size; 82875118Sfenner const u_char *p0; 82975118Sfenner int i; 83038638Sthepish 83175118Sfenner p0 = p; 83275118Sfenner if (length < 1) { 833276788Sdelphij ND_PRINT((ndo, "[|chap]")); 83475118Sfenner return; 83575118Sfenner } else if (length < 4) { 836276788Sdelphij ND_TCHECK(*p); 837276788Sdelphij ND_PRINT((ndo, "[|chap 0x%02x]", *p)); 83875118Sfenner return; 83975118Sfenner } 84038638Sthepish 841276788Sdelphij ND_TCHECK(*p); 84275118Sfenner code = *p; 843276788Sdelphij ND_PRINT((ndo, "CHAP, %s (0x%02x)", 844146778Ssam tok2str(chapcode_values,"unknown",code), 845276788Sdelphij code)); 84675118Sfenner p++; 84732149Spst 848276788Sdelphij ND_TCHECK(*p); 849276788Sdelphij ND_PRINT((ndo, ", id %u", *p)); /* ID */ 85075118Sfenner p++; 85175118Sfenner 852276788Sdelphij ND_TCHECK2(*p, 2); 85375118Sfenner len = EXTRACT_16BITS(p); 85475118Sfenner p += 2; 85575118Sfenner 85675118Sfenner /* 85775118Sfenner * Note that this is a generic CHAP decoding routine. Since we 85875118Sfenner * don't know which flavor of CHAP (i.e. CHAP-MD5, MS-CHAPv1, 85975118Sfenner * MS-CHAPv2) is used at this point, we can't decode packet 86075118Sfenner * specifically to each algorithms. Instead, we simply decode 86175118Sfenner * the GCD (Gratest Common Denominator) for all algorithms. 86275118Sfenner */ 86375118Sfenner switch (code) { 86456896Sfenner case CHAP_CHAL: 86556896Sfenner case CHAP_RESP: 86675118Sfenner if (length - (p - p0) < 1) 86775118Sfenner return; 868276788Sdelphij ND_TCHECK(*p); 86975118Sfenner val_size = *p; /* value size */ 87075118Sfenner p++; 87175118Sfenner if (length - (p - p0) < val_size) 87275118Sfenner return; 873276788Sdelphij ND_PRINT((ndo, ", Value ")); 874127675Sbms for (i = 0; i < val_size; i++) { 875276788Sdelphij ND_TCHECK(*p); 876276788Sdelphij ND_PRINT((ndo, "%02x", *p++)); 877127675Sbms } 87875118Sfenner name_size = len - (p - p0); 879276788Sdelphij ND_PRINT((ndo, ", Name ")); 880127675Sbms for (i = 0; i < name_size; i++) { 881276788Sdelphij ND_TCHECK(*p); 882276788Sdelphij safeputchar(ndo, *p++); 883127675Sbms } 88456896Sfenner break; 88575118Sfenner case CHAP_SUCC: 88675118Sfenner case CHAP_FAIL: 88775118Sfenner msg_size = len - (p - p0); 888276788Sdelphij ND_PRINT((ndo, ", Msg ")); 889127675Sbms for (i = 0; i< msg_size; i++) { 890276788Sdelphij ND_TCHECK(*p); 891276788Sdelphij safeputchar(ndo, *p++); 892127675Sbms } 89375118Sfenner break; 89438638Sthepish } 895127675Sbms return; 896127675Sbms 897127675Sbmstrunc: 898276788Sdelphij ND_PRINT((ndo, "[|chap]")); 89938638Sthepish} 90038638Sthepish 90175118Sfenner/* PAP (see RFC 1334) */ 90256896Sfennerstatic void 903276788Sdelphijhandle_pap(netdissect_options *ndo, 904276788Sdelphij const u_char *p, int length) 90538638Sthepish{ 90675118Sfenner u_int code, len; 90775118Sfenner int peerid_len, passwd_len, msg_len; 90875118Sfenner const u_char *p0; 90975118Sfenner int i; 91038638Sthepish 91175118Sfenner p0 = p; 91275118Sfenner if (length < 1) { 913276788Sdelphij ND_PRINT((ndo, "[|pap]")); 91475118Sfenner return; 91575118Sfenner } else if (length < 4) { 916276788Sdelphij ND_TCHECK(*p); 917276788Sdelphij ND_PRINT((ndo, "[|pap 0x%02x]", *p)); 91875118Sfenner return; 91975118Sfenner } 92038638Sthepish 921276788Sdelphij ND_TCHECK(*p); 92275118Sfenner code = *p; 923276788Sdelphij ND_PRINT((ndo, "PAP, %s (0x%02x)", 924276788Sdelphij tok2str(papcode_values, "unknown", code), 925276788Sdelphij code)); 92675118Sfenner p++; 92738638Sthepish 928276788Sdelphij ND_TCHECK(*p); 929276788Sdelphij ND_PRINT((ndo, ", id %u", *p)); /* ID */ 93075118Sfenner p++; 93175118Sfenner 932276788Sdelphij ND_TCHECK2(*p, 2); 93375118Sfenner len = EXTRACT_16BITS(p); 93475118Sfenner p += 2; 93575118Sfenner 936147904Ssam if ((int)len > length) { 937276788Sdelphij ND_PRINT((ndo, ", length %u > packet size", len)); 938147904Ssam return; 939147904Ssam } 940147904Ssam length = len; 941147904Ssam if (length < (p - p0)) { 942276788Sdelphij ND_PRINT((ndo, ", length %u < PAP header length", length)); 943147904Ssam return; 944147904Ssam } 945147904Ssam 94675118Sfenner switch (code) { 94756896Sfenner case PAP_AREQ: 94875118Sfenner if (length - (p - p0) < 1) 94975118Sfenner return; 950276788Sdelphij ND_TCHECK(*p); 95175118Sfenner peerid_len = *p; /* Peer-ID Length */ 95275118Sfenner p++; 95375118Sfenner if (length - (p - p0) < peerid_len) 95475118Sfenner return; 955276788Sdelphij ND_PRINT((ndo, ", Peer ")); 956127675Sbms for (i = 0; i < peerid_len; i++) { 957276788Sdelphij ND_TCHECK(*p); 958276788Sdelphij safeputchar(ndo, *p++); 959127675Sbms } 96075118Sfenner 96175118Sfenner if (length - (p - p0) < 1) 96275118Sfenner return; 963276788Sdelphij ND_TCHECK(*p); 96475118Sfenner passwd_len = *p; /* Password Length */ 96575118Sfenner p++; 96675118Sfenner if (length - (p - p0) < passwd_len) 96775118Sfenner return; 968276788Sdelphij ND_PRINT((ndo, ", Name ")); 969127675Sbms for (i = 0; i < passwd_len; i++) { 970276788Sdelphij ND_TCHECK(*p); 971276788Sdelphij safeputchar(ndo, *p++); 972127675Sbms } 97356896Sfenner break; 97456896Sfenner case PAP_AACK: 97556896Sfenner case PAP_ANAK: 97675118Sfenner if (length - (p - p0) < 1) 97775118Sfenner return; 978276788Sdelphij ND_TCHECK(*p); 97975118Sfenner msg_len = *p; /* Msg-Length */ 98075118Sfenner p++; 98175118Sfenner if (length - (p - p0) < msg_len) 98275118Sfenner return; 983276788Sdelphij ND_PRINT((ndo, ", Msg ")); 984127675Sbms for (i = 0; i< msg_len; i++) { 985276788Sdelphij ND_TCHECK(*p); 986276788Sdelphij safeputchar(ndo, *p++); 987127675Sbms } 98856896Sfenner break; 98938638Sthepish } 99075118Sfenner return; 991127675Sbms 992127675Sbmstrunc: 993276788Sdelphij ND_PRINT((ndo, "[|pap]")); 99438638Sthepish} 99538638Sthepish 99675118Sfenner/* BAP */ 99756896Sfennerstatic void 998276788Sdelphijhandle_bap(netdissect_options *ndo _U_, 999276788Sdelphij const u_char *p _U_, int length _U_) 100038638Sthepish{ 100175118Sfenner /* XXX: to be supported!! */ 100275118Sfenner} 100375118Sfenner 100475118Sfenner 100575118Sfenner/* IPCP config options */ 100675118Sfennerstatic int 1007276788Sdelphijprint_ipcp_config_options(netdissect_options *ndo, 1008276788Sdelphij const u_char *p, int length) 100975118Sfenner{ 101075118Sfenner int len, opt; 1011172686Smlaier u_int compproto, ipcomp_subopttotallen, ipcomp_subopt, ipcomp_suboptlen; 101275118Sfenner 101375118Sfenner if (length < 2) 101475118Sfenner return 0; 1015276788Sdelphij ND_TCHECK2(*p, 2); 101675118Sfenner len = p[1]; 101775118Sfenner opt = p[0]; 101875118Sfenner if (length < len) 101975118Sfenner return 0; 1020147904Ssam if (len < 2) { 1021276788Sdelphij ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u (length bogus, should be >= 2)", 1022147904Ssam tok2str(ipcpopt_values,"unknown",opt), 1023147904Ssam opt, 1024276788Sdelphij len)); 1025147904Ssam return 0; 1026147904Ssam } 1027146778Ssam 1028276788Sdelphij ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u", 1029146778Ssam tok2str(ipcpopt_values,"unknown",opt), 1030147904Ssam opt, 1031276788Sdelphij len)); 1032146778Ssam 103375118Sfenner switch (opt) { 103475118Sfenner case IPCPOPT_2ADDR: /* deprecated */ 1035276788Sdelphij if (len != 10) { 1036276788Sdelphij ND_PRINT((ndo, " (length bogus, should be = 10)")); 1037276788Sdelphij return len; 1038276788Sdelphij } 1039276788Sdelphij ND_TCHECK2(*(p + 6), 4); 1040276788Sdelphij ND_PRINT((ndo, ": src %s, dst %s", 1041276788Sdelphij ipaddr_string(ndo, p + 2), 1042276788Sdelphij ipaddr_string(ndo, p + 6))); 104356896Sfenner break; 104475118Sfenner case IPCPOPT_IPCOMP: 1045276788Sdelphij if (len < 4) { 1046276788Sdelphij ND_PRINT((ndo, " (length bogus, should be >= 4)")); 1047276788Sdelphij return 0; 1048276788Sdelphij } 1049276788Sdelphij ND_TCHECK2(*(p + 2), 2); 1050276788Sdelphij compproto = EXTRACT_16BITS(p+2); 1051172686Smlaier 1052276788Sdelphij ND_PRINT((ndo, ": %s (0x%02x):", 1053276788Sdelphij tok2str(ipcpopt_compproto_values, "Unknown", compproto), 1054276788Sdelphij compproto)); 1055172686Smlaier 1056172686Smlaier switch (compproto) { 1057172686Smlaier case PPP_VJC: 105875118Sfenner /* XXX: VJ-Comp parameters should be decoded */ 1059172686Smlaier break; 1060172686Smlaier case IPCPOPT_IPCOMP_HDRCOMP: 1061276788Sdelphij if (len < IPCPOPT_IPCOMP_MINLEN) { 1062276788Sdelphij ND_PRINT((ndo, " (length bogus, should be >= %u)", 1063276788Sdelphij IPCPOPT_IPCOMP_MINLEN)); 1064276788Sdelphij return 0; 1065276788Sdelphij } 1066172686Smlaier 1067276788Sdelphij ND_TCHECK2(*(p + 2), IPCPOPT_IPCOMP_MINLEN); 1068276788Sdelphij ND_PRINT((ndo, "\n\t TCP Space %u, non-TCP Space %u" \ 1069172686Smlaier ", maxPeriod %u, maxTime %u, maxHdr %u", 1070172686Smlaier EXTRACT_16BITS(p+4), 1071172686Smlaier EXTRACT_16BITS(p+6), 1072172686Smlaier EXTRACT_16BITS(p+8), 1073172686Smlaier EXTRACT_16BITS(p+10), 1074276788Sdelphij EXTRACT_16BITS(p+12))); 1075172686Smlaier 1076172686Smlaier /* suboptions present ? */ 1077172686Smlaier if (len > IPCPOPT_IPCOMP_MINLEN) { 1078172686Smlaier ipcomp_subopttotallen = len - IPCPOPT_IPCOMP_MINLEN; 1079172686Smlaier p += IPCPOPT_IPCOMP_MINLEN; 1080172686Smlaier 1081276788Sdelphij ND_PRINT((ndo, "\n\t Suboptions, length %u", ipcomp_subopttotallen)); 1082276788Sdelphij 1083172686Smlaier while (ipcomp_subopttotallen >= 2) { 1084276788Sdelphij ND_TCHECK2(*p, 2); 1085172686Smlaier ipcomp_subopt = *p; 1086172686Smlaier ipcomp_suboptlen = *(p+1); 1087276788Sdelphij 1088172686Smlaier /* sanity check */ 1089172686Smlaier if (ipcomp_subopt == 0 || 1090172686Smlaier ipcomp_suboptlen == 0 ) 1091172686Smlaier break; 1092172686Smlaier 1093172686Smlaier /* XXX: just display the suboptions for now */ 1094276788Sdelphij ND_PRINT((ndo, "\n\t\t%s Suboption #%u, length %u", 1095172686Smlaier tok2str(ipcpopt_compproto_subopt_values, 1096172686Smlaier "Unknown", 1097172686Smlaier ipcomp_subopt), 1098172686Smlaier ipcomp_subopt, 1099276788Sdelphij ipcomp_suboptlen)); 1100172686Smlaier 1101172686Smlaier ipcomp_subopttotallen -= ipcomp_suboptlen; 1102172686Smlaier p += ipcomp_suboptlen; 1103172686Smlaier } 1104172686Smlaier } 1105172686Smlaier break; 1106172686Smlaier default: 1107172686Smlaier break; 1108172686Smlaier } 110956896Sfenner break; 1110146778Ssam 1111146778Ssam case IPCPOPT_ADDR: /* those options share the same format - fall through */ 111275118Sfenner case IPCPOPT_MOBILE4: 111375118Sfenner case IPCPOPT_PRIDNS: 111475118Sfenner case IPCPOPT_PRINBNS: 111575118Sfenner case IPCPOPT_SECDNS: 111675118Sfenner case IPCPOPT_SECNBNS: 1117276788Sdelphij if (len != 6) { 1118276788Sdelphij ND_PRINT((ndo, " (length bogus, should be = 6)")); 1119276788Sdelphij return 0; 1120276788Sdelphij } 1121276788Sdelphij ND_TCHECK2(*(p + 2), 4); 1122276788Sdelphij ND_PRINT((ndo, ": %s", ipaddr_string(ndo, p + 2))); 112375118Sfenner break; 112475118Sfenner default: 1125276788Sdelphij /* 1126276788Sdelphij * Unknown option; dump it as raw bytes now if we're 1127276788Sdelphij * not going to do so below. 1128276788Sdelphij */ 1129276788Sdelphij if (ndo->ndo_vflag < 2) 1130276788Sdelphij print_unknown_data(ndo, &p[2], "\n\t ", len - 2); 113175118Sfenner break; 113275118Sfenner } 1133276788Sdelphij if (ndo->ndo_vflag > 1) 1134276788Sdelphij print_unknown_data(ndo, &p[2], "\n\t ", len - 2); /* exclude TLV header */ 113575118Sfenner return len; 113638638Sthepish 1137127675Sbmstrunc: 1138276788Sdelphij ND_PRINT((ndo, "[|ipcp]")); 1139127675Sbms return 0; 114075118Sfenner} 114175118Sfenner 1142146778Ssam/* IP6CP config options */ 1143146778Ssamstatic int 1144276788Sdelphijprint_ip6cp_config_options(netdissect_options *ndo, 1145276788Sdelphij const u_char *p, int length) 1146146778Ssam{ 1147146778Ssam int len, opt; 1148146778Ssam 1149146778Ssam if (length < 2) 1150146778Ssam return 0; 1151276788Sdelphij ND_TCHECK2(*p, 2); 1152146778Ssam len = p[1]; 1153146778Ssam opt = p[0]; 1154146778Ssam if (length < len) 1155146778Ssam return 0; 1156147904Ssam if (len < 2) { 1157276788Sdelphij ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u (length bogus, should be >= 2)", 1158147904Ssam tok2str(ip6cpopt_values,"unknown",opt), 1159147904Ssam opt, 1160276788Sdelphij len)); 1161276788Sdelphij return 0; 1162147904Ssam } 1163146778Ssam 1164276788Sdelphij ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u", 1165146778Ssam tok2str(ip6cpopt_values,"unknown",opt), 1166147904Ssam opt, 1167276788Sdelphij len)); 1168146778Ssam 1169146778Ssam switch (opt) { 1170146778Ssam case IP6CP_IFID: 1171276788Sdelphij if (len != 10) { 1172276788Sdelphij ND_PRINT((ndo, " (length bogus, should be = 10)")); 1173276788Sdelphij return len; 1174276788Sdelphij } 1175276788Sdelphij ND_TCHECK2(*(p + 2), 8); 1176276788Sdelphij ND_PRINT((ndo, ": %04x:%04x:%04x:%04x", 1177146778Ssam EXTRACT_16BITS(p + 2), 1178146778Ssam EXTRACT_16BITS(p + 4), 1179146778Ssam EXTRACT_16BITS(p + 6), 1180276788Sdelphij EXTRACT_16BITS(p + 8))); 1181146778Ssam break; 1182146778Ssam default: 1183276788Sdelphij /* 1184276788Sdelphij * Unknown option; dump it as raw bytes now if we're 1185276788Sdelphij * not going to do so below. 1186276788Sdelphij */ 1187276788Sdelphij if (ndo->ndo_vflag < 2) 1188276788Sdelphij print_unknown_data(ndo, &p[2], "\n\t ", len - 2); 1189146778Ssam break; 1190146778Ssam } 1191276788Sdelphij if (ndo->ndo_vflag > 1) 1192276788Sdelphij print_unknown_data(ndo, &p[2], "\n\t ", len - 2); /* exclude TLV header */ 1193147904Ssam 1194146778Ssam return len; 1195146778Ssam 1196146778Ssamtrunc: 1197276788Sdelphij ND_PRINT((ndo, "[|ip6cp]")); 1198146778Ssam return 0; 1199146778Ssam} 1200146778Ssam 1201146778Ssam 120275118Sfenner/* CCP config options */ 120375118Sfennerstatic int 1204276788Sdelphijprint_ccp_config_options(netdissect_options *ndo, 1205276788Sdelphij const u_char *p, int length) 120675118Sfenner{ 120775118Sfenner int len, opt; 120875118Sfenner 120975118Sfenner if (length < 2) 121075118Sfenner return 0; 1211276788Sdelphij ND_TCHECK2(*p, 2); 121275118Sfenner len = p[1]; 121375118Sfenner opt = p[0]; 121475118Sfenner if (length < len) 121575118Sfenner return 0; 1216147904Ssam if (len < 2) { 1217276788Sdelphij ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u (length bogus, should be >= 2)", 1218276788Sdelphij tok2str(ccpconfopts_values, "Unknown", opt), 1219276788Sdelphij opt, 1220276788Sdelphij len)); 1221276788Sdelphij return 0; 1222276788Sdelphij } 1223147904Ssam 1224276788Sdelphij ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u", 1225276788Sdelphij tok2str(ccpconfopts_values, "Unknown", opt), 1226276788Sdelphij opt, 1227276788Sdelphij len)); 1228147904Ssam 122975118Sfenner switch (opt) { 1230276788Sdelphij case CCPOPT_BSDCOMP: 1231276788Sdelphij if (len < 3) { 1232276788Sdelphij ND_PRINT((ndo, " (length bogus, should be >= 3)")); 1233276788Sdelphij return len; 1234276788Sdelphij } 1235276788Sdelphij ND_TCHECK2(*(p + 2), 1); 1236276788Sdelphij ND_PRINT((ndo, ": Version: %u, Dictionary Bits: %u", 1237276788Sdelphij p[2] >> 5, p[2] & 0x1f)); 1238276788Sdelphij break; 1239276788Sdelphij case CCPOPT_MVRCA: 1240276788Sdelphij if (len < 4) { 1241276788Sdelphij ND_PRINT((ndo, " (length bogus, should be >= 4)")); 1242276788Sdelphij return len; 1243276788Sdelphij } 1244276788Sdelphij ND_TCHECK2(*(p + 2), 1); 1245276788Sdelphij ND_PRINT((ndo, ": Features: %u, PxP: %s, History: %u, #CTX-ID: %u", 1246276788Sdelphij (p[2] & 0xc0) >> 6, 1247276788Sdelphij (p[2] & 0x20) ? "Enabled" : "Disabled", 1248276788Sdelphij p[2] & 0x1f, p[3])); 1249276788Sdelphij break; 1250276788Sdelphij case CCPOPT_DEFLATE: 1251276788Sdelphij if (len < 4) { 1252276788Sdelphij ND_PRINT((ndo, " (length bogus, should be >= 4)")); 1253276788Sdelphij return len; 1254276788Sdelphij } 1255276788Sdelphij ND_TCHECK2(*(p + 2), 1); 1256276788Sdelphij ND_PRINT((ndo, ": Window: %uK, Method: %s (0x%x), MBZ: %u, CHK: %u", 1257276788Sdelphij (p[2] & 0xf0) >> 4, 1258276788Sdelphij ((p[2] & 0x0f) == 8) ? "zlib" : "unkown", 1259276788Sdelphij p[2] & 0x0f, (p[3] & 0xfc) >> 2, p[3] & 0x03)); 1260276788Sdelphij break; 1261276788Sdelphij 1262276788Sdelphij/* XXX: to be supported */ 1263276788Sdelphij#if 0 126475118Sfenner case CCPOPT_OUI: 126575118Sfenner case CCPOPT_PRED1: 126675118Sfenner case CCPOPT_PRED2: 126775118Sfenner case CCPOPT_PJUMP: 126875118Sfenner case CCPOPT_HPPPC: 126975118Sfenner case CCPOPT_STACLZS: 127075118Sfenner case CCPOPT_MPPC: 127175118Sfenner case CCPOPT_GFZA: 127275118Sfenner case CCPOPT_V42BIS: 127375118Sfenner case CCPOPT_LZSDCP: 127475118Sfenner case CCPOPT_DEC: 127575118Sfenner case CCPOPT_RESV: 1276276788Sdelphij break; 1277276788Sdelphij#endif 127875118Sfenner default: 1279276788Sdelphij /* 1280276788Sdelphij * Unknown option; dump it as raw bytes now if we're 1281276788Sdelphij * not going to do so below. 1282276788Sdelphij */ 1283276788Sdelphij if (ndo->ndo_vflag < 2) 1284276788Sdelphij print_unknown_data(ndo, &p[2], "\n\t ", len - 2); 128575118Sfenner break; 128638638Sthepish } 1287276788Sdelphij if (ndo->ndo_vflag > 1) 1288276788Sdelphij print_unknown_data(ndo, &p[2], "\n\t ", len - 2); /* exclude TLV header */ 1289147904Ssam 129075118Sfenner return len; 1291127675Sbms 1292127675Sbmstrunc: 1293276788Sdelphij ND_PRINT((ndo, "[|ccp]")); 1294127675Sbms return 0; 129538638Sthepish} 129675118Sfenner 129775118Sfenner/* BACP config options */ 129875118Sfennerstatic int 1299276788Sdelphijprint_bacp_config_options(netdissect_options *ndo, 1300276788Sdelphij const u_char *p, int length) 130175118Sfenner{ 130275118Sfenner int len, opt; 130375118Sfenner 130475118Sfenner if (length < 2) 130575118Sfenner return 0; 1306276788Sdelphij ND_TCHECK2(*p, 2); 130775118Sfenner len = p[1]; 130875118Sfenner opt = p[0]; 130975118Sfenner if (length < len) 131075118Sfenner return 0; 1311147904Ssam if (len < 2) { 1312276788Sdelphij ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u (length bogus, should be >= 2)", 1313276788Sdelphij tok2str(bacconfopts_values, "Unknown", opt), 1314276788Sdelphij opt, 1315276788Sdelphij len)); 1316276788Sdelphij return 0; 1317276788Sdelphij } 1318147904Ssam 1319276788Sdelphij ND_PRINT((ndo, "\n\t %s Option (0x%02x), length %u", 1320276788Sdelphij tok2str(bacconfopts_values, "Unknown", opt), 1321276788Sdelphij opt, 1322276788Sdelphij len)); 1323147904Ssam 1324147904Ssam switch (opt) { 1325147904Ssam case BACPOPT_FPEER: 1326276788Sdelphij if (len != 6) { 1327276788Sdelphij ND_PRINT((ndo, " (length bogus, should be = 6)")); 1328276788Sdelphij return len; 1329276788Sdelphij } 1330276788Sdelphij ND_TCHECK2(*(p + 2), 4); 1331276788Sdelphij ND_PRINT((ndo, ": Magic-Num 0x%08x", EXTRACT_32BITS(p + 2))); 1332276788Sdelphij break; 1333147904Ssam default: 1334276788Sdelphij /* 1335276788Sdelphij * Unknown option; dump it as raw bytes now if we're 1336276788Sdelphij * not going to do so below. 1337276788Sdelphij */ 1338276788Sdelphij if (ndo->ndo_vflag < 2) 1339276788Sdelphij print_unknown_data(ndo, &p[2], "\n\t ", len - 2); 1340147904Ssam break; 134175118Sfenner } 1342276788Sdelphij if (ndo->ndo_vflag > 1) 1343276788Sdelphij print_unknown_data(ndo, &p[2], "\n\t ", len - 2); /* exclude TLV header */ 1344147904Ssam 134575118Sfenner return len; 1346127675Sbms 1347127675Sbmstrunc: 1348276788Sdelphij ND_PRINT((ndo, "[|bacp]")); 1349127675Sbms return 0; 135075118Sfenner} 135175118Sfenner 1352146778Ssamstatic void 1353276788Sdelphijppp_hdlc(netdissect_options *ndo, 1354276788Sdelphij const u_char *p, int length) 1355146778Ssam{ 1356285275Spkelsey u_char *b, *t, c; 1357285275Spkelsey const u_char *s; 1358146778Ssam int i, proto; 1359146778Ssam const void *se; 1360146778Ssam 1361276788Sdelphij if (length <= 0) 1362276788Sdelphij return; 1363276788Sdelphij 1364285275Spkelsey b = (u_char *)malloc(length); 1365146778Ssam if (b == NULL) 1366146778Ssam return; 1367146778Ssam 1368146778Ssam /* 1369146778Ssam * Unescape all the data into a temporary, private, buffer. 1370146778Ssam * Do this so that we dont overwrite the original packet 1371146778Ssam * contents. 1372146778Ssam */ 1373285275Spkelsey for (s = p, t = b, i = length; i > 0 && ND_TTEST(*s); i--) { 1374146778Ssam c = *s++; 1375146778Ssam if (c == 0x7d) { 1376285275Spkelsey if (i <= 1 || !ND_TTEST(*s)) 1377285275Spkelsey break; 1378285275Spkelsey i--; 1379285275Spkelsey c = *s++ ^ 0x20; 1380146778Ssam } 1381146778Ssam *t++ = c; 1382146778Ssam } 1383146778Ssam 1384276788Sdelphij se = ndo->ndo_snapend; 1385276788Sdelphij ndo->ndo_snapend = t; 1386276788Sdelphij length = t - b; 1387146778Ssam 1388146778Ssam /* now lets guess about the payload codepoint format */ 1389276788Sdelphij if (length < 1) 1390276788Sdelphij goto trunc; 1391146778Ssam proto = *b; /* start with a one-octet codepoint guess */ 1392276788Sdelphij 1393146778Ssam switch (proto) { 1394146778Ssam case PPP_IP: 1395276788Sdelphij ip_print(ndo, b + 1, length - 1); 1396146778Ssam goto cleanup; 1397146778Ssam case PPP_IPV6: 1398276788Sdelphij ip6_print(ndo, b + 1, length - 1); 1399235530Sdelphij goto cleanup; 1400146778Ssam default: /* no luck - try next guess */ 1401235530Sdelphij break; 1402146778Ssam } 1403146778Ssam 1404276788Sdelphij if (length < 2) 1405276788Sdelphij goto trunc; 1406146778Ssam proto = EXTRACT_16BITS(b); /* next guess - load two octets */ 1407146778Ssam 1408146778Ssam switch (proto) { 1409146778Ssam case (PPP_ADDRESS << 8 | PPP_CONTROL): /* looks like a PPP frame */ 1410276788Sdelphij if (length < 4) 1411276788Sdelphij goto trunc; 1412146778Ssam proto = EXTRACT_16BITS(b+2); /* load the PPP proto-id */ 1413276788Sdelphij handle_ppp(ndo, proto, b + 4, length - 4); 1414146778Ssam break; 1415146778Ssam default: /* last guess - proto must be a PPP proto-id */ 1416276788Sdelphij handle_ppp(ndo, proto, b + 2, length - 2); 1417146778Ssam break; 1418146778Ssam } 1419146778Ssam 1420146778Ssamcleanup: 1421276788Sdelphij ndo->ndo_snapend = se; 1422146778Ssam free(b); 1423146778Ssam return; 1424276788Sdelphij 1425276788Sdelphijtrunc: 1426276788Sdelphij ndo->ndo_snapend = se; 1427276788Sdelphij free(b); 1428276788Sdelphij ND_PRINT((ndo, "[|ppp]")); 1429146778Ssam} 1430146778Ssam 1431146778Ssam 143275118Sfenner/* PPP */ 143375118Sfennerstatic void 1434276788Sdelphijhandle_ppp(netdissect_options *ndo, 1435276788Sdelphij u_int proto, const u_char *p, int length) 143675118Sfenner{ 1437276788Sdelphij if ((proto & 0xff00) == 0x7e00) { /* is this an escape code ? */ 1438276788Sdelphij ppp_hdlc(ndo, p - 1, length); 1439276788Sdelphij return; 1440276788Sdelphij } 1441146778Ssam 144275118Sfenner switch (proto) { 1443146778Ssam case PPP_LCP: /* fall through */ 144475118Sfenner case PPP_IPCP: 1445127675Sbms case PPP_OSICP: 1446127675Sbms case PPP_MPLSCP: 1447127675Sbms case PPP_IPV6CP: 144875118Sfenner case PPP_CCP: 144975118Sfenner case PPP_BACP: 1450276788Sdelphij handle_ctrl_proto(ndo, proto, p, length); 145175118Sfenner break; 1452276788Sdelphij case PPP_ML: 1453276788Sdelphij handle_mlppp(ndo, p, length); 1454276788Sdelphij break; 145575118Sfenner case PPP_CHAP: 1456276788Sdelphij handle_chap(ndo, p, length); 145775118Sfenner break; 145875118Sfenner case PPP_PAP: 1459276788Sdelphij handle_pap(ndo, p, length); 146075118Sfenner break; 146175118Sfenner case PPP_BAP: /* XXX: not yet completed */ 1462276788Sdelphij handle_bap(ndo, p, length); 146375118Sfenner break; 146475118Sfenner case ETHERTYPE_IP: /*XXX*/ 1465146778Ssam case PPP_VJNC: 146675118Sfenner case PPP_IP: 1467276788Sdelphij ip_print(ndo, p, length); 146875118Sfenner break; 146975118Sfenner case ETHERTYPE_IPV6: /*XXX*/ 147075118Sfenner case PPP_IPV6: 1471276788Sdelphij ip6_print(ndo, p, length); 147275118Sfenner break; 147375118Sfenner case ETHERTYPE_IPX: /*XXX*/ 147475118Sfenner case PPP_IPX: 1475276788Sdelphij ipx_print(ndo, p, length); 147675118Sfenner break; 147798527Sfenner case PPP_OSI: 1478276788Sdelphij isoclns_print(ndo, p, length, length); 1479276788Sdelphij break; 1480127675Sbms case PPP_MPLS_UCAST: 1481127675Sbms case PPP_MPLS_MCAST: 1482276788Sdelphij mpls_print(ndo, p, length); 1483127675Sbms break; 1484146778Ssam case PPP_COMP: 1485276788Sdelphij ND_PRINT((ndo, "compressed PPP data")); 1486146778Ssam break; 148798527Sfenner default: 1488276788Sdelphij ND_PRINT((ndo, "%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto))); 1489276788Sdelphij print_unknown_data(ndo, p, "\n\t", length); 1490146778Ssam break; 149175118Sfenner } 149275118Sfenner} 149375118Sfenner 149456896Sfenner/* Standard PPP printer */ 1495127675Sbmsu_int 1496276788Sdelphijppp_print(netdissect_options *ndo, 1497276788Sdelphij register const u_char *p, u_int length) 149875118Sfenner{ 1499146778Ssam u_int proto,ppp_header; 1500127675Sbms u_int olen = length; /* _o_riginal length */ 1501127675Sbms u_int hdr_len = 0; 150275118Sfenner 150375118Sfenner /* 150475118Sfenner * Here, we assume that p points to the Address and Control 150575118Sfenner * field (if they present). 150675118Sfenner */ 150775118Sfenner if (length < 2) 150875118Sfenner goto trunc; 1509276788Sdelphij ND_TCHECK2(*p, 2); 1510146778Ssam ppp_header = EXTRACT_16BITS(p); 151175118Sfenner 1512146778Ssam switch(ppp_header) { 1513146778Ssam case (PPP_WITHDIRECTION_IN << 8 | PPP_CONTROL): 1514276788Sdelphij if (ndo->ndo_eflag) ND_PRINT((ndo, "In ")); 1515146778Ssam p += 2; 1516146778Ssam length -= 2; 1517146778Ssam hdr_len += 2; 1518146778Ssam break; 1519146778Ssam case (PPP_WITHDIRECTION_OUT << 8 | PPP_CONTROL): 1520276788Sdelphij if (ndo->ndo_eflag) ND_PRINT((ndo, "Out ")); 1521146778Ssam p += 2; 1522146778Ssam length -= 2; 1523146778Ssam hdr_len += 2; 1524146778Ssam break; 1525146778Ssam case (PPP_ADDRESS << 8 | PPP_CONTROL): 1526146778Ssam p += 2; /* ACFC not used */ 1527146778Ssam length -= 2; 1528146778Ssam hdr_len += 2; 1529146778Ssam break; 1530146778Ssam 1531146778Ssam default: 1532146778Ssam break; 1533146778Ssam } 1534146778Ssam 153575118Sfenner if (length < 2) 153675118Sfenner goto trunc; 1537276788Sdelphij ND_TCHECK(*p); 153875118Sfenner if (*p % 2) { 153975118Sfenner proto = *p; /* PFC is used */ 154075118Sfenner p++; 154175118Sfenner length--; 1542127675Sbms hdr_len++; 154375118Sfenner } else { 1544276788Sdelphij ND_TCHECK2(*p, 2); 154575118Sfenner proto = EXTRACT_16BITS(p); 154675118Sfenner p += 2; 154775118Sfenner length -= 2; 1548127675Sbms hdr_len += 2; 154975118Sfenner } 155075118Sfenner 1551276788Sdelphij if (ndo->ndo_eflag) 1552276788Sdelphij ND_PRINT((ndo, "%s (0x%04x), length %u: ", 1553276788Sdelphij tok2str(ppptype2str, "unknown", proto), 1554276788Sdelphij proto, 1555276788Sdelphij olen)); 155675118Sfenner 1557276788Sdelphij handle_ppp(ndo, proto, p, length); 1558127675Sbms return (hdr_len); 155975118Sfennertrunc: 1560276788Sdelphij ND_PRINT((ndo, "[|ppp]")); 1561127675Sbms return (0); 156275118Sfenner} 156375118Sfenner 156475118Sfenner 156575118Sfenner/* PPP I/F printer */ 1566127675Sbmsu_int 1567276788Sdelphijppp_if_print(netdissect_options *ndo, 1568276788Sdelphij const struct pcap_pkthdr *h, register const u_char *p) 156938638Sthepish{ 157038638Sthepish register u_int length = h->len; 157138638Sthepish register u_int caplen = h->caplen; 157238638Sthepish 157317680Spst if (caplen < PPP_HDRLEN) { 1574276788Sdelphij ND_PRINT((ndo, "[|ppp]")); 1575127675Sbms return (caplen); 157617680Spst } 157717680Spst 157875118Sfenner#if 0 157975118Sfenner /* 158075118Sfenner * XXX: seems to assume that there are 2 octets prepended to an 158175118Sfenner * actual PPP frame. The 1st octet looks like Input/Output flag 158275118Sfenner * while 2nd octet is unknown, at least to me 158375118Sfenner * (mshindo@mshindo.net). 158475118Sfenner * 158575118Sfenner * That was what the original tcpdump code did. 158675118Sfenner * 158775118Sfenner * FreeBSD's "if_ppp.c" *does* set the first octet to 1 for outbound 158875118Sfenner * packets and 0 for inbound packets - but only if the 158975118Sfenner * protocol field has the 0x8000 bit set (i.e., it's a network 159075118Sfenner * control protocol); it does so before running the packet through 159175118Sfenner * "bpf_filter" to see if it should be discarded, and to see 159275118Sfenner * if we should update the time we sent the most recent packet... 159375118Sfenner * 159475118Sfenner * ...but it puts the original address field back after doing 159575118Sfenner * so. 159675118Sfenner * 159775118Sfenner * NetBSD's "if_ppp.c" doesn't set the first octet in that fashion. 159875118Sfenner * 159975118Sfenner * I don't know if any PPP implementation handed up to a BPF 160075118Sfenner * device packets with the first octet being 1 for outbound and 160175118Sfenner * 0 for inbound packets, so I (guy@alum.mit.edu) don't know 160275118Sfenner * whether that ever needs to be checked or not. 160375118Sfenner * 160475118Sfenner * Note that NetBSD has a DLT_PPP_SERIAL, which it uses for PPP, 160575118Sfenner * and its tcpdump appears to assume that the frame always 160675118Sfenner * begins with an address field and a control field, and that 160775118Sfenner * the address field might be 0x0f or 0x8f, for Cisco 160875118Sfenner * point-to-point with HDLC framing as per section 4.3.1 of RFC 160975118Sfenner * 1547, as well as 0xff, for PPP in HDLC-like framing as per 161075118Sfenner * RFC 1662. 161175118Sfenner * 161275118Sfenner * (Is the Cisco framing in question what DLT_C_HDLC, in 161375118Sfenner * BSD/OS, is?) 161475118Sfenner */ 1615276788Sdelphij if (ndo->ndo_eflag) 1616276788Sdelphij ND_PRINT((ndo, "%c %4d %02x ", p[0] ? 'O' : 'I', length, p[1])); 161775118Sfenner#endif 161875118Sfenner 1619276788Sdelphij ppp_print(ndo, p, length); 162075118Sfenner 1621127675Sbms return (0); 162253146Sbrian} 162353146Sbrian 162453146Sbrian/* 162575118Sfenner * PPP I/F printer to use if we know that RFC 1662-style PPP in HDLC-like 162675118Sfenner * framing, or Cisco PPP with HDLC framing as per section 4.3.1 of RFC 1547, 162775118Sfenner * is being used (i.e., we don't check for PPP_ADDRESS and PPP_CONTROL, 162875118Sfenner * discard them *if* those are the first two octets, and parse the remaining 162975118Sfenner * packet as a PPP packet, as "ppp_print()" does). 163075118Sfenner * 163175118Sfenner * This handles, for example, DLT_PPP_SERIAL in NetBSD. 163253146Sbrian */ 1633127675Sbmsu_int 1634276788Sdelphijppp_hdlc_if_print(netdissect_options *ndo, 1635276788Sdelphij const struct pcap_pkthdr *h, register const u_char *p) 163653146Sbrian{ 163775118Sfenner register u_int length = h->len; 163875118Sfenner register u_int caplen = h->caplen; 163975118Sfenner u_int proto; 1640127675Sbms u_int hdrlen = 0; 164117680Spst 164275118Sfenner if (caplen < 2) { 1643276788Sdelphij ND_PRINT((ndo, "[|ppp]")); 1644127675Sbms return (caplen); 164575118Sfenner } 164617680Spst 164775118Sfenner switch (p[0]) { 164875118Sfenner 164975118Sfenner case PPP_ADDRESS: 165075118Sfenner if (caplen < 4) { 1651276788Sdelphij ND_PRINT((ndo, "[|ppp]")); 1652127675Sbms return (caplen); 165375118Sfenner } 165475118Sfenner 1655276788Sdelphij if (ndo->ndo_eflag) 1656276788Sdelphij ND_PRINT((ndo, "%02x %02x %d ", p[0], p[1], length)); 165775118Sfenner p += 2; 165875118Sfenner length -= 2; 1659127675Sbms hdrlen += 2; 166075118Sfenner 166175118Sfenner proto = EXTRACT_16BITS(p); 166275118Sfenner p += 2; 166375118Sfenner length -= 2; 1664127675Sbms hdrlen += 2; 1665276788Sdelphij ND_PRINT((ndo, "%s: ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto))); 166675118Sfenner 1667276788Sdelphij handle_ppp(ndo, proto, p, length); 166817692Spst break; 166938638Sthepish 167075118Sfenner case CHDLC_UNICAST: 167175118Sfenner case CHDLC_BCAST: 1672276788Sdelphij return (chdlc_if_print(ndo, h, p)); 167375118Sfenner 167417692Spst default: 1675276788Sdelphij if (ndo->ndo_eflag) 1676276788Sdelphij ND_PRINT((ndo, "%02x %02x %d ", p[0], p[1], length)); 167775118Sfenner p += 2; 1678127675Sbms hdrlen += 2; 167975118Sfenner 168075118Sfenner /* 168175118Sfenner * XXX - NetBSD's "ppp_netbsd_serial_if_print()" treats 168275118Sfenner * the next two octets as an Ethernet type; does that 168375118Sfenner * ever happen? 168475118Sfenner */ 1685276788Sdelphij ND_PRINT((ndo, "unknown addr %02x; ctrl %02x", p[0], p[1])); 168675118Sfenner break; 168717692Spst } 168817692Spst 1689127675Sbms return (hdrlen); 169017680Spst} 169117680Spst 169239300Sfenner#define PPP_BSDI_HDRLEN 24 169339300Sfenner 169439300Sfenner/* BSD/OS specific PPP printer */ 1695127675Sbmsu_int 1696276788Sdelphijppp_bsdos_if_print(netdissect_options *ndo _U_, 1697276788Sdelphij const struct pcap_pkthdr *h _U_, register const u_char *p _U_) 169817680Spst{ 1699127675Sbms register int hdrlength; 170056896Sfenner#ifdef __bsdi__ 170139300Sfenner register u_int length = h->len; 170239300Sfenner register u_int caplen = h->caplen; 1703276788Sdelphij uint16_t ptype; 170456896Sfenner const u_char *q; 170556896Sfenner int i; 170639300Sfenner 170739300Sfenner if (caplen < PPP_BSDI_HDRLEN) { 1708276788Sdelphij ND_PRINT((ndo, "[|ppp]")); 1709127675Sbms return (caplen) 171039300Sfenner } 171139300Sfenner 171239300Sfenner hdrlength = 0; 171339300Sfenner 171456896Sfenner#if 0 171539300Sfenner if (p[0] == PPP_ADDRESS && p[1] == PPP_CONTROL) { 1716276788Sdelphij if (ndo->ndo_eflag) 1717276788Sdelphij ND_PRINT((ndo, "%02x %02x ", p[0], p[1])); 171839300Sfenner p += 2; 171939300Sfenner hdrlength = 2; 172039300Sfenner } 172139300Sfenner 1722276788Sdelphij if (ndo->ndo_eflag) 1723276788Sdelphij ND_PRINT((ndo, "%d ", length)); 172439300Sfenner /* Retrieve the protocol type */ 172539300Sfenner if (*p & 01) { 172639300Sfenner /* Compressed protocol field */ 172739300Sfenner ptype = *p; 1728276788Sdelphij if (ndo->ndo_eflag) 1729276788Sdelphij ND_PRINT((ndo, "%02x ", ptype)); 173039300Sfenner p++; 173139300Sfenner hdrlength += 1; 173239300Sfenner } else { 173339300Sfenner /* Un-compressed protocol field */ 1734214478Srpaulo ptype = EXTRACT_16BITS(p); 1735276788Sdelphij if (ndo->ndo_eflag) 1736276788Sdelphij ND_PRINT((ndo, "%04x ", ptype)); 173739300Sfenner p += 2; 173839300Sfenner hdrlength += 2; 173939300Sfenner } 174056896Sfenner#else 174156896Sfenner ptype = 0; /*XXX*/ 1742276788Sdelphij if (ndo->ndo_eflag) 1743276788Sdelphij ND_PRINT((ndo, "%c ", p[SLC_DIR] ? 'O' : 'I')); 174456896Sfenner if (p[SLC_LLHL]) { 174556896Sfenner /* link level header */ 174656896Sfenner struct ppp_header *ph; 174756896Sfenner 174856896Sfenner q = p + SLC_BPFHDRLEN; 174956896Sfenner ph = (struct ppp_header *)q; 175056896Sfenner if (ph->phdr_addr == PPP_ADDRESS 175156896Sfenner && ph->phdr_ctl == PPP_CONTROL) { 1752276788Sdelphij if (ndo->ndo_eflag) 1753276788Sdelphij ND_PRINT((ndo, "%02x %02x ", q[0], q[1])); 1754214478Srpaulo ptype = EXTRACT_16BITS(&ph->phdr_type); 1755276788Sdelphij if (ndo->ndo_eflag && (ptype == PPP_VJC || ptype == PPP_VJNC)) { 1756276788Sdelphij ND_PRINT((ndo, "%s ", tok2str(ppptype2str, 1757276788Sdelphij "proto-#%d", ptype))); 175856896Sfenner } 175956896Sfenner } else { 1760276788Sdelphij if (ndo->ndo_eflag) { 1761276788Sdelphij ND_PRINT((ndo, "LLH=[")); 176256896Sfenner for (i = 0; i < p[SLC_LLHL]; i++) 1763276788Sdelphij ND_PRINT((ndo, "%02x", q[i])); 1764276788Sdelphij ND_PRINT((ndo, "] ")); 176556896Sfenner } 176656896Sfenner } 176756896Sfenner } 1768276788Sdelphij if (ndo->ndo_eflag) 1769276788Sdelphij ND_PRINT((ndo, "%d ", length)); 177056896Sfenner if (p[SLC_CHL]) { 177156896Sfenner q = p + SLC_BPFHDRLEN + p[SLC_LLHL]; 177256896Sfenner 177356896Sfenner switch (ptype) { 177456896Sfenner case PPP_VJC: 1775276788Sdelphij ptype = vjc_print(ndo, q, ptype); 177656896Sfenner hdrlength = PPP_BSDI_HDRLEN; 177756896Sfenner p += hdrlength; 177875118Sfenner switch (ptype) { 177975118Sfenner case PPP_IP: 1780276788Sdelphij ip_print(ndo, p, length); 178175118Sfenner break; 178275118Sfenner case PPP_IPV6: 1783276788Sdelphij ip6_print(ndo, p, length); 178475118Sfenner break; 1785127675Sbms case PPP_MPLS_UCAST: 1786127675Sbms case PPP_MPLS_MCAST: 1787276788Sdelphij mpls_print(ndo, p, length); 1788127675Sbms break; 178975118Sfenner } 179056896Sfenner goto printx; 179156896Sfenner case PPP_VJNC: 1792276788Sdelphij ptype = vjc_print(ndo, q, ptype); 179356896Sfenner hdrlength = PPP_BSDI_HDRLEN; 179456896Sfenner p += hdrlength; 179575118Sfenner switch (ptype) { 179675118Sfenner case PPP_IP: 1797276788Sdelphij ip_print(ndo, p, length); 179875118Sfenner break; 179975118Sfenner case PPP_IPV6: 1800276788Sdelphij ip6_print(ndo, p, length); 180175118Sfenner break; 1802127675Sbms case PPP_MPLS_UCAST: 1803127675Sbms case PPP_MPLS_MCAST: 1804276788Sdelphij mpls_print(ndo, p, length); 1805127675Sbms break; 180675118Sfenner } 180756896Sfenner goto printx; 180856896Sfenner default: 1809276788Sdelphij if (ndo->ndo_eflag) { 1810276788Sdelphij ND_PRINT((ndo, "CH=[")); 181156896Sfenner for (i = 0; i < p[SLC_LLHL]; i++) 1812276788Sdelphij ND_PRINT((ndo, "%02x", q[i])); 1813276788Sdelphij ND_PRINT((ndo, "] ")); 181456896Sfenner } 181556896Sfenner break; 181656896Sfenner } 181756896Sfenner } 181856896Sfenner 181956896Sfenner hdrlength = PPP_BSDI_HDRLEN; 182056896Sfenner#endif 182156896Sfenner 182239300Sfenner length -= hdrlength; 182356896Sfenner p += hdrlength; 182439300Sfenner 182575118Sfenner switch (ptype) { 182675118Sfenner case PPP_IP: 182739300Sfenner ip_print(p, length); 182875118Sfenner break; 182975118Sfenner case PPP_IPV6: 1830276788Sdelphij ip6_print(ndo, p, length); 183175118Sfenner break; 1832276788Sdelphij case PPP_MPLS_UCAST: 1833276788Sdelphij case PPP_MPLS_MCAST: 1834276788Sdelphij mpls_print(ndo, p, length); 1835276788Sdelphij break; 183675118Sfenner default: 1837276788Sdelphij ND_PRINT((ndo, "%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", ptype))); 183875118Sfenner } 183939300Sfenner 184056896Sfennerprintx: 1841127675Sbms#else /* __bsdi */ 1842127675Sbms hdrlength = 0; 184356896Sfenner#endif /* __bsdi__ */ 1844127675Sbms return (hdrlength); 184517680Spst} 1846146778Ssam 1847146778Ssam 1848146778Ssam/* 1849146778Ssam * Local Variables: 1850146778Ssam * c-style: whitesmith 1851146778Ssam * c-basic-offset: 8 1852146778Ssam * End: 1853146778Ssam */ 1854