Logo Search packages:      
Sourcecode: tcpdump version File versions

print-ppp.c

/*
 * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
 *    The Regents of the University of California.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that: (1) source code distributions
 * retain the above copyright notice and this paragraph in its entirety, (2)
 * distributions including binary code include the above copyright notice and
 * this paragraph in its entirety in the documentation or other materials
 * provided with the distribution, and (3) all advertising materials mentioning
 * features or use of this software display the following acknowledgement:
 * ``This product includes software developed by the University of California,
 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
 * the University nor the names of its contributors may be used to endorse
 * or promote products derived from this software without specific prior
 * written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * Extensively modified by Motonori Shindo (mshindo@mshindo.net) for more
 * complete PPP support.
 */

/*
 * TODO:
 * o resolve XXX as much as possible
 * o MP support
 * o BAP support
 */

#ifndef lint
static const char rcsid[] _U_ =
    "@(#) $Header: /tcpdump/master/tcpdump/print-ppp.c,v 1.89.2.3 2004/03/24 03:32:43 guy Exp $ (LBL)";
#endif

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <tcpdump-stdinc.h>

#ifdef __bsdi__
#include <net/slcompress.h>
#include <net/if_ppp.h>
#endif

#include <pcap.h>
#include <stdio.h>

#include "interface.h"
#include "extract.h"
#include "addrtoname.h"
#include "ppp.h"
#include "chdlc.h"
#include "ethertype.h"

/*
 * The following constatns are defined by IANA. Please refer to
 *    http://www.isi.edu/in-notes/iana/assignments/ppp-numbers
 * for the up-to-date information.
 */

/* Protocol Codes defined in ppp.h */

struct tok ppptype2str[] = {
        { PPP_IP,   "IP" },
        { PPP_OSI,        "OSI" },
        { PPP_NS,   "NS" },
        { PPP_DECNET,     "DECNET" },
        { PPP_APPLE,      "APPLE" },
      { PPP_IPX,    "IPX" },
      { PPP_VJC,    "VJC" },
      { PPP_VJNC,   "VJNC" },
      { PPP_BRPDU,        "BRPDU" },
      { PPP_STII,   "STII" },
      { PPP_VINES,        "VINES" },
      { PPP_MPLS_UCAST, "MPLS" },
      { PPP_MPLS_MCAST, "MPLS" },

      { PPP_HELLO,        "HELLO" },
      { PPP_LUXCOM,       "LUXCOM" },
      { PPP_SNS,    "SNS" },
      { PPP_IPCP,   "IPCP" },
      { PPP_OSICP,        "OSICP" },
      { PPP_NSCP,   "NSCP" },
      { PPP_DECNETCP,   "DECNETCP" },
      { PPP_APPLECP,      "APPLECP" },
      { PPP_IPXCP,        "IPXCP" },
      { PPP_STIICP,       "STIICP" },
      { PPP_VINESCP,      "VINESCP" },
      { PPP_MPLSCP,       "MPLSCP" },

      { PPP_LCP,    "LCP" },
      { PPP_PAP,    "PAP" },
      { PPP_LQM,    "LQM" },
      { PPP_CHAP,   "CHAP" },
      { PPP_BACP,   "BACP" },
      { PPP_BAP,    "BAP" },
      { PPP_MP,     "ML" },
      { 0,          NULL }
};

/* Control Protocols (LCP/IPCP/CCP etc.) Codes defined in RFC 1661 */

#define CPCODES_VEXT          0     /* Vendor-Specific (RFC2153) */
#define CPCODES_CONF_REQ      1     /* Configure-Request */
#define CPCODES_CONF_ACK      2     /* Configure-Ack */
#define CPCODES_CONF_NAK      3     /* Configure-Nak */
#define CPCODES_CONF_REJ      4     /* Configure-Reject */
#define CPCODES_TERM_REQ      5     /* Terminate-Request */
#define CPCODES_TERM_ACK      6     /* Terminate-Ack */
#define CPCODES_CODE_REJ      7     /* Code-Reject */
#define CPCODES_PROT_REJ      8     /* Protocol-Reject (LCP only) */
#define CPCODES_ECHO_REQ      9     /* Echo-Request (LCP only) */
#define CPCODES_ECHO_RPL      10    /* Echo-Reply (LCP only) */
#define CPCODES_DISC_REQ      11    /* Discard-Request (LCP only) */
#define CPCODES_ID            12    /* Identification (LCP only) RFC1570 */
#define CPCODES_TIME_REM      13    /* Time-Remaining (LCP only) RFC1570 */
#define CPCODES_RESET_REQ     14    /* Reset-Request (CCP only) RFC1962 */
#define CPCODES_RESET_REP     15    /* Reset-Reply (CCP only) */

struct tok cpcodes[] = {
      {CPCODES_VEXT,      "Vendor-Extension"}, /* RFC2153 */
      {CPCODES_CONF_REQ,  "Conf-Request"},
        {CPCODES_CONF_ACK,  "Conf-Ack"},
      {CPCODES_CONF_NAK,  "Conf-Nack"},
      {CPCODES_CONF_REJ,  "Conf-Reject"},
      {CPCODES_TERM_REQ,  "Term-Request"},
      {CPCODES_TERM_ACK,  "Term-Ack"},
      {CPCODES_CODE_REJ,  "Code-Reject"},
      {CPCODES_PROT_REJ,  "Prot-Reject"},
      {CPCODES_ECHO_REQ,  "Echo-Request"},
      {CPCODES_ECHO_RPL,  "Echo-Reply"},
      {CPCODES_DISC_REQ,  "Disc-Req"},
      {CPCODES_ID,        "Ident"},            /* RFC1570 */
      {CPCODES_TIME_REM,  "Time-Rem"},         /* RFC1570 */
      {CPCODES_RESET_REQ, "Reset-Req"},        /* RFC1962 */
      {CPCODES_RESET_REP, "Reset-Ack"},        /* RFC1962 */
        {0,                 NULL}
};

/* LCP Config Options */

#define LCPOPT_VEXT     0
#define LCPOPT_MRU      1
#define LCPOPT_ACCM     2
#define LCPOPT_AP 3
#define LCPOPT_QP 4
#define LCPOPT_MN 5
#define LCPOPT_DEP6     6
#define LCPOPT_PFC      7
#define LCPOPT_ACFC     8
#define LCPOPT_FCSALT   9
#define LCPOPT_SDP      10
#define LCPOPT_NUMMODE  11
#define LCPOPT_DEP12    12
#define LCPOPT_CBACK    13
#define LCPOPT_DEP14    14
#define LCPOPT_DEP15    15
#define LCPOPT_DEP16    16
#define LCPOPT_MLMRRU   17
#define LCPOPT_MLSSNHF  18
#define LCPOPT_MLED     19
#define LCPOPT_PROP     20
#define LCPOPT_DCEID    21
#define LCPOPT_MPP      22
#define LCPOPT_LD 23
#define LCPOPT_LCPAOPT  24
#define LCPOPT_COBS     25
#define LCPOPT_PE 26
#define LCPOPT_MLHF     27
#define LCPOPT_I18N     28
#define LCPOPT_SDLOS    29
#define LCPOPT_PPPMUX   30

#define LCPOPT_MIN LCPOPT_VEXT
#define LCPOPT_MAX LCPOPT_PPPMUX

static const char *lcpconfopts[] = {
      "Vend-Ext",       /* (0) */
      "MRU",                  /* (1) */
      "ACCM",                 /* (2) */
      "Auth-Prot",            /* (3) */
      "Qual-Prot",            /* (4) */
      "Magic-Num",            /* (5) */
      "deprecated(6)",  /* used to be a Quality Protocol */
      "PFC",                  /* (7) */
      "ACFC",                 /* (8) */
      "FCS-Alt",        /* (9) */
      "SDP",                  /* (10) */
      "Num-Mode",       /* (11) */
      "deprecated(12)", /* used to be a Multi-Link-Procedure*/
      "Call-Back",            /* (13) */
      "deprecated(14)", /* used to be a Connect-Time */
      "deprecated(15)", /* used to be a Compund-Frames */
      "deprecated(16)", /* used to be a Nominal-Data-Encap */
      "MRRU",                 /* (17) */
      "SSNHF",          /* (18) */
      "End-Disc",       /* (19) */
      "Proprietary",          /* (20) */
      "DCE-Id",         /* (21) */
      "MP+",                  /* (22) */
      "Link-Disc",            /* (23) */
      "LCP-Auth-Opt",         /* (24) */
      "COBS",                 /* (25) */
      "Prefix-elision", /* (26) */
      "Multilink-header-Form",/* (27) */
      "I18N",                 /* (28) */
      "SDL-over-SONET/SDH",   /* (29) */
      "PPP-Muxing",           /* (30) */
};

/* IPV6CP - to be supported */
/* ECP - to be supported */

/* CCP Config Options */

#define CCPOPT_OUI      0     /* RFC1962 */
#define CCPOPT_PRED1    1     /* RFC1962 */
#define CCPOPT_PRED2    2     /* RFC1962 */
#define CCPOPT_PJUMP    3     /* RFC1962 */
/* 4-15 unassigned */
#define CCPOPT_HPPPC    16    /* RFC1962 */
#define CCPOPT_STACLZS  17    /* RFC1974 */
#define CCPOPT_MPPC     18    /* RFC2118 */
#define CCPOPT_GFZA     19    /* RFC1962 */
#define CCPOPT_V42BIS   20    /* RFC1962 */
#define CCPOPT_BSDCOMP  21    /* RFC1977 */
/* 22 unassigned */
#define CCPOPT_LZSDCP   23    /* RFC1967 */
#define CCPOPT_MVRCA    24    /* RFC1975 */
#define CCPOPT_DEC      25    /* RFC1976 */
#define CCPOPT_DEFLATE  26    /* RFC1979 */
/* 27-254 unassigned */
#define CCPOPT_RESV     255   /* RFC1962 */

#define CCPOPT_MIN CCPOPT_OUI
#define CCPOPT_MAX CCPOPT_DEFLATE    /* XXX: should be CCPOPT_RESV but... */

static const char *ccpconfopts[] = {
      "OUI",                  /* (0) */
      "Pred-1",         /* (1) */
      "Pred-2",         /* (2) */
      "Puddle",         /* (3) */
      "unassigned(4)",  /* (4) */
      "unassigned(5)",  /* (5) */
      "unassigned(6)",  /* (6) */
      "unassigned(7)",  /* (7) */
      "unassigned(8)",  /* (8) */
      "unassigned(9)",  /* (9) */
      "unassigned(10)", /* (10) */
      "unassigned(11)", /* (11) */
      "unassigned(12)", /* (12) */
      "unassigned(13)", /* (13) */
      "unassigned(14)", /* (14) */
      "unassigned(15)", /* (15) */
      "HP-PPC",         /* (16) */
      "Stac-LZS",       /* (17) */
      "MPPC",                 /* (18) */
      "Gand-FZA",       /* (19) */
      "V.42bis",        /* (20) */
      "BSD-Comp",       /* (21) */
      "unassigned(22)", /* (22) */
      "LZS-DCP",        /* (23) */
      "MVRCA",          /* (24) */
      "DEC",                  /* (25) */
      "Deflate",        /* (26) */
};

/* BACP Config Options */

#define BACPOPT_FPEER   1     /* RFC2125 */

/* SDCP - to be supported */

/* IPCP Config Options */

#define IPCPOPT_2ADDR   1     /* RFC1172, RFC1332 (deprecated) */
#define IPCPOPT_IPCOMP  2     /* RFC1332 */
#define IPCPOPT_ADDR    3     /* RFC1332 */
#define IPCPOPT_MOBILE4 4     /* RFC2290 */

#define IPCPOPT_PRIDNS  129   /* RFC1877 */
#define IPCPOPT_PRINBNS 130   /* RFC1877 */
#define IPCPOPT_SECDNS  131   /* RFC1877 */
#define IPCPOPT_SECNBNS 132   /* RFC1877 */

/* ATCP - to be supported */
/* OSINLCP - to be supported */
/* BVCP - to be supported */
/* BCP - to be supported */
/* IPXCP - to be supported */
/* MPLSCP - to be supported */

/* Auth Algorithms */

/* 0-4 Reserved (RFC1994) */
#define AUTHALG_CHAPMD5 5     /* RFC1994 */
#define AUTHALG_MSCHAP1 128   /* RFC2433 */
#define AUTHALG_MSCHAP2 129   /* RFC2795 */

/* FCS Alternatives - to be supported */

/* Multilink Endpoint Discriminator (RFC1717) */
#define MEDCLASS_NULL   0     /* Null Class */
#define MEDCLASS_LOCAL  1     /* Locally Assigned */
#define MEDCLASS_IPV4   2     /* Internet Protocol (IPv4) */
#define MEDCLASS_MAC    3     /* IEEE 802.1 global MAC address */
#define MEDCLASS_MNB    4     /* PPP Magic Number Block */
#define MEDCLASS_PSNDN  5     /* Public Switched Network Director Number */

/* PPP LCP Callback */
#define CALLBACK_AUTH   0     /* Location determined by user auth */
#define CALLBACK_DSTR   1     /* Dialing string */
#define CALLBACK_LID    2     /* Location identifier */
#define CALLBACK_E164   3     /* E.164 number */
#define CALLBACK_X500   4     /* X.500 distinguished name */
#define CALLBACK_CBCP   6     /* Location is determined during CBCP nego */

/* CHAP */

#define CHAP_CHAL 1
#define CHAP_RESP 2
#define CHAP_SUCC 3
#define CHAP_FAIL 4

#define CHAP_CODEMIN CHAP_CHAL
#define CHAP_CODEMAX CHAP_FAIL

static const char *chapcode[] = {
      "Chal",           /* (1) */
      "Resp",           /* (2) */
      "Succ",           /* (3) */
      "Fail",           /* (4) */
};

/* PAP */

#define PAP_AREQ  1
#define PAP_AACK  2
#define PAP_ANAK  3

#define PAP_CODEMIN     PAP_AREQ
#define PAP_CODEMAX     PAP_ANAK

static const char *papcode[] = {
      "Auth-Req", /* (1) */
      "Auth-Ack", /* (2) */
      "Auth-Nak", /* (3) */
};

/* BAP */
#define BAP_CALLREQ     1
#define BAP_CALLRES     2
#define BAP_CBREQ 3
#define BAP_CBRES 4
#define BAP_LDQREQ      5
#define BAP_LDQRES      6
#define BAP_CSIND 7
#define BAP_CSRES 8

static void handle_ctrl_proto (u_int proto,const u_char *p, int length);
static void handle_chap (const u_char *p, int length);
static void handle_pap (const u_char *p, int length);
static void handle_bap (const u_char *p, int length);
static int print_lcp_config_options (const u_char *p, int);
static int print_ipcp_config_options (const u_char *p, int);
static int print_ccp_config_options (const u_char *p, int);
static int print_bacp_config_options (const u_char *p, int);
static void handle_ppp (u_int proto, const u_char *p, int length);

/* generic Control Protocol (e.g. LCP, IPCP, CCP, etc.) handler */
static void
handle_ctrl_proto(u_int proto, const u_char *pptr, int length)
{
      const char *typestr;
      u_int code, len;
      int (*pfunc)(const u_char *, int);
      int x, j;
        const u_char *tptr;

        tptr=pptr;

        typestr = tok2str(ppptype2str, "unknown", proto);
        printf("%s, ",typestr);

      if (length < 4) /* FIXME weak boundary checking */
            goto trunc;
      TCHECK2(*tptr, 2);

      code = *tptr++;
      
        printf("%s (0x%02x), id %u",
               tok2str(cpcodes, "Unknown Opcode",code),
             code,
               *tptr++); /* ID */

      TCHECK2(*tptr, 2);
      len = EXTRACT_16BITS(tptr);
      tptr += 2;

      if (length <= 4)
            return;           /* there may be a NULL confreq etc. */

      switch (code) {
      case CPCODES_VEXT:
            if (length < 11)
                  break;
            TCHECK2(*tptr, 4);
            printf(", Magic-Num 0x%08x", EXTRACT_32BITS(tptr));
            tptr += 4;
            TCHECK2(*tptr, 3);
            printf(" OUI 0x%06x", EXTRACT_24BITS(tptr));
            /* XXX: need to decode Kind and Value(s)? */
            break;
      case CPCODES_CONF_REQ:
      case CPCODES_CONF_ACK:
      case CPCODES_CONF_NAK:
      case CPCODES_CONF_REJ:
            x = len - 4;      /* Code(1), Identifier(1) and Length(2) */
            do {
                  switch (proto) {
                  case PPP_LCP:
                        pfunc = print_lcp_config_options;
                        break;
                  case PPP_IPCP:
                        pfunc = print_ipcp_config_options;
                        break;
                  case PPP_CCP:
                        pfunc = print_ccp_config_options;
                        break;
                  case PPP_BACP:
                        pfunc = print_bacp_config_options;
                        break;
                  default:
                        /*
                         * This should never happen, but we set
                         * "pfunc" to squelch uninitialized
                         * variable warnings from compilers.
                         */
                        pfunc = NULL;
                        break;
                  }
                  if ((j = (*pfunc)(tptr, len)) == 0)
                        break;
                  x -= j;
                  tptr += j;
            } while (x > 0);
            break;

      case CPCODES_TERM_REQ:
      case CPCODES_TERM_ACK:
            /* XXX: need to decode Data? */
            break;
      case CPCODES_CODE_REJ:
            /* XXX: need to decode Rejected-Packet? */
            break;
      case CPCODES_PROT_REJ:
            if (length < 6)
                  break;
            TCHECK2(*tptr, 2);
            printf(", Rejected %s Protocol (0x%04x)",
                   tok2str(ppptype2str,"unknown", EXTRACT_16BITS(tptr)),
                   EXTRACT_16BITS(tptr));
            /* XXX: need to decode Rejected-Information? */
            break;
      case CPCODES_ECHO_REQ:
      case CPCODES_ECHO_RPL:
      case CPCODES_DISC_REQ:
      case CPCODES_ID:
            if (length < 8)
                  break;
            TCHECK2(*tptr, 4);
            printf(", Magic-Num 0x%08x", EXTRACT_32BITS(tptr));
            /* XXX: need to decode Data? */
            break;
      case CPCODES_TIME_REM:
            if (length < 12)
                  break;
            TCHECK2(*tptr, 4);
            printf(", Magic-Num 0x%08x", EXTRACT_32BITS(tptr));
            TCHECK2(*(tptr + 4), 4);
            printf(", Seconds-Remaining %us", EXTRACT_32BITS(tptr + 4));
            /* XXX: need to decode Message? */
            break;
      default:
            /* XXX this is dirty but we do not get the
             * original pointer passed to the begin
             * the PPP packet */
                if (vflag <= 1)
                    print_unknown_data(pptr-2,"\n\t",length+2);
            break;
      }
      printf(", length %u", length);

        if (vflag >1)
            print_unknown_data(pptr-2,"\n\t",length+2);
      return;

trunc:
      printf("[|%s]", typestr);
}

/* LCP config options */
static int
print_lcp_config_options(const u_char *p, int length)
{
      int len, opt;

      if (length < 2)
            return 0;
      TCHECK2(*p, 2);
      len = p[1];
      opt = p[0];
      if (length < len)
            return 0;
      if ((opt >= LCPOPT_MIN) && (opt <= LCPOPT_MAX))
            printf(", %s ", lcpconfopts[opt]);
      else {
            printf(", unknown LCP option 0x%02x", opt);
            return len;
      }

      switch (opt) {
      case LCPOPT_VEXT:
            if (len >= 6) {
                  TCHECK2(*(p + 2), 3);
                  printf(" OUI 0x%06x", EXTRACT_24BITS(p+2));
#if 0
                  TCHECK(p[5]);
                  printf(" kind 0x%02x", p[5]);
                  printf(" val 0x")
                  for (i = 0; i < len - 6; i++) {
                        TCHECK(p[6 + i]);
                        printf("%02x", p[6 + i]);
                  }
#endif
            }
            break;
      case LCPOPT_MRU:
            if (len == 4) {
                  TCHECK2(*(p + 2), 2);
                  printf(" %u", EXTRACT_16BITS(p + 2));
            }
            break;
      case LCPOPT_ACCM:
            if (len == 6) {
                  TCHECK2(*(p + 2), 4);
                  printf(" %08x", EXTRACT_32BITS(p + 2));
            }
            break;
      case LCPOPT_AP:
            if (len >= 4) {
                TCHECK2(*(p + 2), 2);
                switch (EXTRACT_16BITS(p+2)) {
                case PPP_PAP:
                    printf(" PAP");
                  break;
                case PPP_CHAP:
                    printf(" CHAP");
                    TCHECK(p[4]);
                  switch (p[4]) {
                  default:
                      printf(", unknown-algorithm-%u", p[4]);
                      break;
                  case AUTHALG_CHAPMD5:
                      printf(", MD5");
                      break;
                  case AUTHALG_MSCHAP1:
                      printf(", MSCHAPv1");
                      break;
                  case AUTHALG_MSCHAP2:
                      printf(", MSCHAPv2");
                      break;
                  }
                  break;
                case PPP_EAP:
                    printf(" EAP");
                  break;
                case PPP_SPAP:
                  printf(" SPAP");
                  break;
                case PPP_SPAP_OLD:
                  printf(" Old-SPAP");
                  break;
                default:
                  printf("unknown");
                }
            }
            break;
      case LCPOPT_QP:
            if (len >= 4) {
                  TCHECK2(*(p + 2), 2);
                    if (EXTRACT_16BITS(p+2) == PPP_LQM)
                        printf(" LQR");
                  else
                        printf(" unknown");
            }
            break;
      case LCPOPT_MN:
            if (len == 6) {
                  TCHECK2(*(p + 2), 4);
                  printf(" 0x%08x", EXTRACT_32BITS(p + 2));
            }
            break;
      case LCPOPT_PFC:
            break;
      case LCPOPT_ACFC:
            break;
      case LCPOPT_LD:
            if (len == 4) {
                  TCHECK2(*(p + 2), 2);
                  printf(" 0x%04x", EXTRACT_16BITS(p + 2));
            }
            break;
      case LCPOPT_CBACK:
            if (len < 3)
                  break;
            TCHECK(p[2]);
            switch (p[2]) {         /* Operation */
            case CALLBACK_AUTH:
                  printf(" UserAuth");
                  break;
            case CALLBACK_DSTR:
                  printf(" DialString");
                  break;
            case CALLBACK_LID:
                  printf(" LocalID");
                  break;
            case CALLBACK_E164:
                  printf(" E.164");
                  break;
            case CALLBACK_X500:
                  printf(" X.500");
                  break;
            case CALLBACK_CBCP:
                  printf(" CBCP");
                  break;
            default:
                  printf(" unknown-operation=%u", p[2]);
                  break;
            }
            break;
      case LCPOPT_MLMRRU:
            if (len == 4) {
                  TCHECK2(*(p + 2), 2);
                  printf(" %u", EXTRACT_16BITS(p + 2));
            }
            break;
      case LCPOPT_MLED:
            if (len < 3)
                  break;
            TCHECK(p[2]);
            switch (p[2]) {         /* class */
            case MEDCLASS_NULL:
                  printf(" Null");
                  break;
            case MEDCLASS_LOCAL:
                  printf(" Local"); /* XXX */
                  break;
            case MEDCLASS_IPV4:
                  if (len != 7)
                        break;
                  TCHECK2(*(p + 3), 4);
                  printf(" IPv4 %s", ipaddr_string(p + 3));
                  break;
            case MEDCLASS_MAC:
                  if (len != 9)
                        break;
                  TCHECK(p[8]);
                  printf(" MAC %02x:%02x:%02x:%02x:%02x:%02x",
                         p[3], p[4], p[5], p[6], p[7], p[8]);
                  break;
            case MEDCLASS_MNB:
                  printf(" Magic-Num-Block"); /* XXX */
                  break;
            case MEDCLASS_PSNDN:
                  printf(" PSNDN"); /* XXX */
                  break;
            }
            break;

/* XXX: to be supported */
#if 0
      case LCPOPT_DEP6:
      case LCPOPT_FCSALT:
      case LCPOPT_SDP:
      case LCPOPT_NUMMODE:
      case LCPOPT_DEP12:
      case LCPOPT_DEP14:
      case LCPOPT_DEP15:
      case LCPOPT_DEP16:
      case LCPOPT_MLSSNHF:
      case LCPOPT_PROP:
      case LCPOPT_DCEID:
      case LCPOPT_MPP:
      case LCPOPT_LCPAOPT:
      case LCPOPT_COBS:
      case LCPOPT_PE:
      case LCPOPT_MLHF:
      case LCPOPT_I18N:
      case LCPOPT_SDLOS:
      case LCPOPT_PPPMUX:
            break;
#endif
      }
      return len;

trunc:
      printf("[|lcp]");
      return 0;
}

/* CHAP */
static void
handle_chap(const u_char *p, int length)
{
      u_int code, len;
      int val_size, name_size, msg_size;
      const u_char *p0;
      int i;

      p0 = p;
      if (length < 1) {
            printf("[|chap]");
            return;
      } else if (length < 4) {
            TCHECK(*p);
            printf("[|chap 0x%02x]", *p);
            return;
      }

      TCHECK(*p);
      code = *p;
      if ((code >= CHAP_CODEMIN) && (code <= CHAP_CODEMAX))
            printf("%s", chapcode[code - 1]);
      else {
            printf("0x%02x", code);
            return;
      }
      p++;

      TCHECK(*p);
      printf("(%u)", *p);           /* ID */
      p++;

      TCHECK2(*p, 2);
      len = EXTRACT_16BITS(p);
      p += 2;

      /*
       * Note that this is a generic CHAP decoding routine. Since we
       * don't know which flavor of CHAP (i.e. CHAP-MD5, MS-CHAPv1,
       * MS-CHAPv2) is used at this point, we can't decode packet
       * specifically to each algorithms. Instead, we simply decode
       * the GCD (Gratest Common Denominator) for all algorithms.
       */
      switch (code) {
      case CHAP_CHAL:
      case CHAP_RESP:
            if (length - (p - p0) < 1)
                  return;
            TCHECK(*p);
            val_size = *p;          /* value size */
            p++;
            if (length - (p - p0) < val_size)
                  return;
            printf(", Value ");
            for (i = 0; i < val_size; i++) {
                  TCHECK(*p);
                  printf("%02x", *p++);
            }
            name_size = len - (p - p0);
            printf(", Name ");
            for (i = 0; i < name_size; i++) {
                  TCHECK(*p);
                  safeputchar(*p++);
            }
            break;
      case CHAP_SUCC:
      case CHAP_FAIL:
            msg_size = len - (p - p0);
            printf(", Msg ");
            for (i = 0; i< msg_size; i++) {
                  TCHECK(*p);
                  safeputchar(*p++);
            }
            break;
      }
      return;

trunc:
      printf("[|chap]");
}

/* PAP (see RFC 1334) */
static void
handle_pap(const u_char *p, int length)
{
      u_int code, len;
      int peerid_len, passwd_len, msg_len;
      const u_char *p0;
      int i;

      p0 = p;
      if (length < 1) {
            printf("[|pap]");
            return;
      } else if (length < 4) {
            TCHECK(*p);
            printf("[|pap 0x%02x]", *p);
            return;
      }

      TCHECK(*p);
      code = *p;
      if ((code >= PAP_CODEMIN) && (code <= PAP_CODEMAX))
            printf("%s", papcode[code - 1]);
      else {
            printf("0x%02x", code);
            return;
      }
      p++;

      TCHECK(*p);
      printf("(%u)", *p);           /* ID */
      p++;

      TCHECK2(*p, 2);
      len = EXTRACT_16BITS(p);
      p += 2;

      switch (code) {
      case PAP_AREQ:
            if (length - (p - p0) < 1)
                  return;
            TCHECK(*p);
            peerid_len = *p;  /* Peer-ID Length */
            p++;
            if (length - (p - p0) < peerid_len)
                  return;
            printf(", Peer ");
            for (i = 0; i < peerid_len; i++) {
                  TCHECK(*p);
                  safeputchar(*p++);
            }

            if (length - (p - p0) < 1)
                  return;
            TCHECK(*p);
            passwd_len = *p;  /* Password Length */
            p++;
            if (length - (p - p0) < passwd_len)
                  return;
            printf(", Name ");
            for (i = 0; i < passwd_len; i++) {
                  TCHECK(*p);
                  safeputchar(*p++);
            }
            break;
      case PAP_AACK:
      case PAP_ANAK:
            if (length - (p - p0) < 1)
                  return;
            TCHECK(*p);
            msg_len = *p;           /* Msg-Length */
            p++;
            if (length - (p - p0) < msg_len)
                  return;
            printf(", Msg ");
            for (i = 0; i< msg_len; i++) {
                  TCHECK(*p);
                  safeputchar(*p++);
            }
            break;
      }
      return;

trunc:
      printf("[|pap]");
}

/* BAP */
static void
handle_bap(const u_char *p _U_, int length _U_)
{
      /* XXX: to be supported!! */
}


/* IPCP config options */
static int
print_ipcp_config_options(const u_char *p, int length)
{
      int len, opt;

      if (length < 2)
            return 0;
      TCHECK2(*p, 2);
      len = p[1];
      opt = p[0];
      if (length < len)
            return 0;
      switch (opt) {
      case IPCPOPT_2ADDR:           /* deprecated */
            if (len != 10)
                  goto invlen;
            TCHECK2(*(p + 6), 4);
            printf(", IP-Addrs src %s, dst %s",
                   ipaddr_string(p + 2),
                   ipaddr_string(p + 6));
            break;
      case IPCPOPT_IPCOMP:
            if (len < 4)
                  goto invlen;
            printf(", IP-Comp");
            TCHECK2(*(p + 2), 2);
            if (EXTRACT_16BITS(p + 2) == PPP_VJC) {
                  printf(" VJ-Comp");
                  /* XXX: VJ-Comp parameters should be decoded */
            } else
                  printf(" unknown-comp-proto=%04x", EXTRACT_16BITS(p + 2));
            break;
      case IPCPOPT_ADDR:
            if (len != 6)
                  goto invlen;
            TCHECK2(*(p + 2), 4);
            printf(", IP-Addr %s", ipaddr_string(p + 2));
            break;
      case IPCPOPT_MOBILE4:
            if (len != 6)
                  goto invlen;
            TCHECK2(*(p + 2), 4);
            printf(", Home-Addr %s", ipaddr_string(p + 2));
            break;
      case IPCPOPT_PRIDNS:
            if (len != 6)
                  goto invlen;
            TCHECK2(*(p + 2), 4);
            printf(", Pri-DNS %s", ipaddr_string(p + 2));
            break;
      case IPCPOPT_PRINBNS:
            if (len != 6)
                  goto invlen;
            TCHECK2(*(p + 2), 4);
            printf(", Pri-NBNS %s", ipaddr_string(p + 2));
            break;
      case IPCPOPT_SECDNS:
            if (len != 6)
                  goto invlen;
            TCHECK2(*(p + 2), 4);
            printf(", Sec-DNS %s", ipaddr_string(p + 2));
            break;
      case IPCPOPT_SECNBNS:
            if (len != 6)
                  goto invlen;
            TCHECK2(*(p + 2), 4);
            printf(", Sec-NBNS %s", ipaddr_string(p + 2));
            break;
      default:
            printf(", unknown-%d", opt);
            break;
      }
      return len;

invlen:
      printf(", invalid-length-%d", opt);
      return 0;

trunc:
      printf("[|ipcp]");
      return 0;
}

/* CCP config options */
static int
print_ccp_config_options(const u_char *p, int length)
{
      int len, opt;

      if (length < 2)
            return 0;
      TCHECK2(*p, 2);
      len = p[1];
      opt = p[0];
      if (length < len)
            return 0;
      if ((opt >= CCPOPT_MIN) && (opt <= CCPOPT_MAX))
            printf(", %s", ccpconfopts[opt]);
#if 0 /* XXX */
      switch (opt) {
      case CCPOPT_OUI:
      case CCPOPT_PRED1:
      case CCPOPT_PRED2:
      case CCPOPT_PJUMP:
      case CCPOPT_HPPPC:
      case CCPOPT_STACLZS:
      case CCPOPT_MPPC:
      case CCPOPT_GFZA:
      case CCPOPT_V42BIS:
      case CCPOPT_BSDCOMP:
      case CCPOPT_LZSDCP:
      case CCPOPT_MVRCA:
      case CCPOPT_DEC:
      case CCPOPT_DEFLATE:
      case CCPOPT_RESV:
            break;

      default:
            printf(", unknown-%d", opt);
            break;
      }
#endif
      return len;

trunc:
      printf("[|ccp]");
      return 0;
}

/* BACP config options */
static int
print_bacp_config_options(const u_char *p, int length)
{
      int len, opt;

      if (length < 2)
            return 0;
      TCHECK2(*p, 2);
      len = p[1];
      opt = p[0];
      if (length < len)
            return 0;
      if (opt == BACPOPT_FPEER) {
            TCHECK2(*(p + 2), 4);
            printf(", Favored-Peer");
            printf(", Magic-Num 0x%08x", EXTRACT_32BITS(p + 2));
      } else {
            printf(", unknown-option-%d", opt);
      }
      return len;

trunc:
      printf("[|bacp]");
      return 0;
}


/* PPP */
static void
handle_ppp(u_int proto, const u_char *p, int length)
{
      switch (proto) {
      case PPP_LCP:
      case PPP_IPCP:
      case PPP_OSICP:
      case PPP_MPLSCP:
      case PPP_IPV6CP:
      case PPP_CCP:
      case PPP_BACP:
            handle_ctrl_proto(proto, p, length);
            break;
      case PPP_CHAP:
            handle_chap(p, length);
            break;
      case PPP_PAP:
            handle_pap(p, length);
            break;
      case PPP_BAP:           /* XXX: not yet completed */
            handle_bap(p, length);
            break;
      case ETHERTYPE_IP:      /*XXX*/
      case PPP_IP:
            ip_print(p, length);
            break;
#ifdef INET6
      case ETHERTYPE_IPV6:    /*XXX*/
      case PPP_IPV6:
            ip6_print(p, length);
            break;
#endif
      case ETHERTYPE_IPX:     /*XXX*/
      case PPP_IPX:
            ipx_print(p, length);
            break;
      case PPP_OSI:
              isoclns_print(p, length, length);
              break;
      case PPP_MPLS_UCAST:
      case PPP_MPLS_MCAST:
            mpls_print(p, length);
            break;
      default:
                printf("unknown PPP protocol (0x%04x)", proto);
                print_unknown_data(p,"\n\t",length);
                break;
      }
}

/* Standard PPP printer */
u_int
ppp_print(register const u_char *p, u_int length)
{
      u_int proto;
        u_int olen = length; /* _o_riginal length */
      u_int hdr_len = 0;

      /*
       * Here, we assume that p points to the Address and Control
       * field (if they present).
       */
      if (length < 2)
            goto trunc;
      TCHECK2(*p, 2);
      if (*p == PPP_ADDRESS && *(p + 1) == PPP_CONTROL) {
            p += 2;                 /* ACFC not used */
            length -= 2;
            hdr_len += 2;
      }

      if (length < 2)
            goto trunc;
      TCHECK(*p);
      if (*p % 2) {
            proto = *p;       /* PFC is used */
            p++;
            length--;
            hdr_len++;
      } else {
            TCHECK2(*p, 2);
            proto = EXTRACT_16BITS(p);
            p += 2;
            length -= 2;
            hdr_len += 2;
      }

        if (eflag)
            printf("PPP-%s (0x%04x), length %u: ",
                   tok2str(ppptype2str, "unknown", proto),
                   proto,
                   olen);

      handle_ppp(proto, p, length);
      return (hdr_len);
trunc:
      printf("[|ppp]");
      return (0);
}


/* PPP I/F printer */
u_int
ppp_if_print(const struct pcap_pkthdr *h, register const u_char *p)
{
      register u_int length = h->len;
      register u_int caplen = h->caplen;

      if (caplen < PPP_HDRLEN) {
            printf("[|ppp]");
            return (caplen);
      }

#if 0
      /*
       * XXX: seems to assume that there are 2 octets prepended to an
       * actual PPP frame. The 1st octet looks like Input/Output flag
       * while 2nd octet is unknown, at least to me
       * (mshindo@mshindo.net).
       *
       * That was what the original tcpdump code did.
       *
       * FreeBSD's "if_ppp.c" *does* set the first octet to 1 for outbound
       * packets and 0 for inbound packets - but only if the
       * protocol field has the 0x8000 bit set (i.e., it's a network
       * control protocol); it does so before running the packet through
       * "bpf_filter" to see if it should be discarded, and to see
       * if we should update the time we sent the most recent packet...
       *
       * ...but it puts the original address field back after doing
       * so.
       *
       * NetBSD's "if_ppp.c" doesn't set the first octet in that fashion.
       *
       * I don't know if any PPP implementation handed up to a BPF
       * device packets with the first octet being 1 for outbound and
       * 0 for inbound packets, so I (guy@alum.mit.edu) don't know
       * whether that ever needs to be checked or not.
       *
       * Note that NetBSD has a DLT_PPP_SERIAL, which it uses for PPP,
       * and its tcpdump appears to assume that the frame always
       * begins with an address field and a control field, and that
       * the address field might be 0x0f or 0x8f, for Cisco
       * point-to-point with HDLC framing as per section 4.3.1 of RFC
       * 1547, as well as 0xff, for PPP in HDLC-like framing as per
       * RFC 1662.
       *
       * (Is the Cisco framing in question what DLT_C_HDLC, in
       * BSD/OS, is?)
       */
      if (eflag)
            printf("%c %4d %02x ", p[0] ? 'O' : 'I', length, p[1]);
#endif

      ppp_print(p, length);

      return (0);
}

/*
 * PPP I/F printer to use if we know that RFC 1662-style PPP in HDLC-like
 * framing, or Cisco PPP with HDLC framing as per section 4.3.1 of RFC 1547,
 * is being used (i.e., we don't check for PPP_ADDRESS and PPP_CONTROL,
 * discard them *if* those are the first two octets, and parse the remaining
 * packet as a PPP packet, as "ppp_print()" does).
 *
 * This handles, for example, DLT_PPP_SERIAL in NetBSD.
 */
u_int
ppp_hdlc_if_print(const struct pcap_pkthdr *h, register const u_char *p)
{
      register u_int length = h->len;
      register u_int caplen = h->caplen;
      u_int proto;
      u_int hdrlen = 0;

      if (caplen < 2) {
            printf("[|ppp]");
            return (caplen);
      }

      switch (p[0]) {

      case PPP_ADDRESS:
            if (caplen < 4) {
                  printf("[|ppp]");
                  return (caplen);
            }

            if (eflag)
                  printf("%02x %02x %d ", p[0], p[1], length);
            p += 2;
            length -= 2;
            hdrlen += 2;

            proto = EXTRACT_16BITS(p);
            p += 2;
            length -= 2;
            hdrlen += 2;
            printf("%s: ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto));

            handle_ppp(proto, p, length);
            break;

      case CHDLC_UNICAST:
      case CHDLC_BCAST:
            return (chdlc_if_print(h, p));

      default:
            if (eflag)
                  printf("%02x %02x %d ", p[0], p[1], length);
            p += 2;
            length -= 2;
            hdrlen += 2;

            /*
             * XXX - NetBSD's "ppp_netbsd_serial_if_print()" treats
             * the next two octets as an Ethernet type; does that
             * ever happen?
             */
            printf("unknown addr %02x; ctrl %02x", p[0], p[1]);
            break;
      }

      return (hdrlen);
}

#define PPP_BSDI_HDRLEN 24

/* BSD/OS specific PPP printer */
u_int
ppp_bsdos_if_print(const struct pcap_pkthdr *h _U_, register const u_char *p _U_)
{
      register int hdrlength;
#ifdef __bsdi__
      register u_int length = h->len;
      register u_int caplen = h->caplen;
      u_int16_t ptype;
      const u_char *q;
      int i;

      if (caplen < PPP_BSDI_HDRLEN) {
            printf("[|ppp]");
            return (caplen)
      }

      hdrlength = 0;

#if 0
      if (p[0] == PPP_ADDRESS && p[1] == PPP_CONTROL) {
            if (eflag)
                  printf("%02x %02x ", p[0], p[1]);
            p += 2;
            hdrlength = 2;
      }

      if (eflag)
            printf("%d ", length);
      /* Retrieve the protocol type */
      if (*p & 01) {
            /* Compressed protocol field */
            ptype = *p;
            if (eflag)
                  printf("%02x ", ptype);
            p++;
            hdrlength += 1;
      } else {
            /* Un-compressed protocol field */
            ptype = ntohs(*(u_int16_t *)p);
            if (eflag)
                  printf("%04x ", ptype);
            p += 2;
            hdrlength += 2;
      }
#else
      ptype = 0;  /*XXX*/
      if (eflag)
            printf("%c ", p[SLC_DIR] ? 'O' : 'I');
      if (p[SLC_LLHL]) {
            /* link level header */
            struct ppp_header *ph;

            q = p + SLC_BPFHDRLEN;
            ph = (struct ppp_header *)q;
            if (ph->phdr_addr == PPP_ADDRESS
             && ph->phdr_ctl == PPP_CONTROL) {
                  if (eflag)
                        printf("%02x %02x ", q[0], q[1]);
                  ptype = ntohs(ph->phdr_type);
                  if (eflag && (ptype == PPP_VJC || ptype == PPP_VJNC)) {
                        printf("%s ", tok2str(ppptype2str,
                                    "proto-#%d", ptype));
                  }
            } else {
                  if (eflag) {
                        printf("LLH=[");
                        for (i = 0; i < p[SLC_LLHL]; i++)
                              printf("%02x", q[i]);
                        printf("] ");
                  }
            }
      }
      if (eflag)
            printf("%d ", length);
      if (p[SLC_CHL]) {
            q = p + SLC_BPFHDRLEN + p[SLC_LLHL];

            switch (ptype) {
            case PPP_VJC:
                  ptype = vjc_print(q, ptype);
                  hdrlength = PPP_BSDI_HDRLEN;
                  p += hdrlength;
                  switch (ptype) {
                  case PPP_IP:
                        ip_print(p, length);
                        break;
#ifdef INET6
                  case PPP_IPV6:
                        ip6_print(p, length);
                        break;
#endif
                  case PPP_MPLS_UCAST:
                  case PPP_MPLS_MCAST:
                        mpls_print(p, length);
                        break;
                  }
                  goto printx;
            case PPP_VJNC:
                  ptype = vjc_print(q, ptype);
                  hdrlength = PPP_BSDI_HDRLEN;
                  p += hdrlength;
                  switch (ptype) {
                  case PPP_IP:
                        ip_print(p, length);
                        break;
#ifdef INET6
                  case PPP_IPV6:
                        ip6_print(p, length);
                        break;
#endif
                  case PPP_MPLS_UCAST:
                  case PPP_MPLS_MCAST:
                        mpls_print(p, length);
                        break;
                  }
                  goto printx;
            default:
                  if (eflag) {
                        printf("CH=[");
                        for (i = 0; i < p[SLC_LLHL]; i++)
                              printf("%02x", q[i]);
                        printf("] ");
                  }
                  break;
            }
      }

      hdrlength = PPP_BSDI_HDRLEN;
#endif

      length -= hdrlength;
      p += hdrlength;

      switch (ptype) {
      case PPP_IP:
            ip_print(p, length);
            break;
#ifdef INET6
      case PPP_IPV6:
            ip6_print(p, length);
            break;
#endif
        case PPP_MPLS_UCAST:
        case PPP_MPLS_MCAST:
                mpls_print(p, length);
                break;
      default:
            printf("%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", ptype));
      }

printx:
#else /* __bsdi */
      hdrlength = 0;
#endif /* __bsdi__ */
      return (hdrlength);
}

Generated by  Doxygen 1.6.0   Back to index