X-Git-Url: https://git.tcpdump.org/tcpdump/blobdiff_plain/a7092012a34c4976a341df7c1eb89928d39fe55c..fb8b947488c7f22b518de1df1a91e663dc7ab33c:/print-ppp.c diff --git a/print-ppp.c b/print-ppp.c index fb8424ad..cfa92e5e 100644 --- a/print-ppp.c +++ b/print-ppp.c @@ -30,8 +30,8 @@ */ #ifndef lint -static const char rcsid[] = - "@(#) $Header: /tcpdump/master/tcpdump/print-ppp.c,v 1.82 2003-05-11 08:59:22 hannes Exp $ (LBL)"; +static const char rcsid[] _U_ = + "@(#) $Header: /tcpdump/master/tcpdump/print-ppp.c,v 1.98 2004-07-06 22:11:17 guy Exp $ (LBL)"; #endif #ifdef HAVE_CONFIG_H @@ -47,6 +47,7 @@ static const char rcsid[] = #include #include +#include #include "interface.h" #include "extract.h" @@ -54,6 +55,7 @@ static const char rcsid[] = #include "ppp.h" #include "chdlc.h" #include "ethertype.h" +#include "oui.h" /* * The following constatns are defined by IANA. Please refer to @@ -70,13 +72,14 @@ struct tok ppptype2str[] = { { PPP_DECNET, "DECNET" }, { PPP_APPLE, "APPLE" }, { PPP_IPX, "IPX" }, - { PPP_VJC, "VJC" }, - { PPP_VJNC, "VJNC" }, + { PPP_VJC, "VJC IP" }, + { PPP_VJNC, "VJNC IP" }, { PPP_BRPDU, "BRPDU" }, { PPP_STII, "STII" }, { PPP_VINES, "VINES" }, { PPP_MPLS_UCAST, "MPLS" }, { PPP_MPLS_MCAST, "MPLS" }, + { PPP_COMP, "Compressed"}, { PPP_HELLO, "HELLO" }, { PPP_LUXCOM, "LUXCOM" }, @@ -369,11 +372,13 @@ 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); +static void ppp_hdlc(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; @@ -381,17 +386,21 @@ handle_ctrl_proto(u_int proto, const u_char *pptr, int length) tptr=pptr; - printf("%s, ",tok2str(ppptype2str, "unknown", proto)); + typestr = tok2str(ppptype2str, "unknown", proto); + printf("%s, ",typestr); if (length < 4) /* FIXME weak boundary checking */ - return; + goto trunc; + TCHECK2(*tptr, 2); code = *tptr++; - printf("%s (%u)", - tok2str(cpcodes, "Unknown Opcode 0x%02x",code), + printf("%s (0x%02x), id %u", + tok2str(cpcodes, "Unknown Opcode",code), + code, *tptr++); /* ID */ + TCHECK2(*tptr, 2); len = EXTRACT_16BITS(tptr); tptr += 2; @@ -402,9 +411,13 @@ handle_ctrl_proto(u_int proto, const u_char *pptr, int length) case CPCODES_VEXT: if (length < 11) break; - printf(", Magic-Num=%08x", EXTRACT_32BITS(tptr)); + TCHECK2(*tptr, 4); + printf(", Magic-Num 0x%08x", EXTRACT_32BITS(tptr)); tptr += 4; - printf(" OUI=%02x%02x%02x", tptr[0], tptr[1], tptr[2]); + TCHECK2(*tptr, 3); + printf(" Vendor: %s (%u)", + tok2str(oui_values,"Unknown",EXTRACT_24BITS(tptr)), + EXTRACT_24BITS(tptr)); /* XXX: need to decode Kind and Value(s)? */ break; case CPCODES_CONF_REQ: @@ -452,7 +465,10 @@ handle_ctrl_proto(u_int proto, const u_char *pptr, int length) case CPCODES_PROT_REJ: if (length < 6) break; - printf(", Rejected-Protocol=%04x", EXTRACT_16BITS(tptr)); + 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: @@ -461,14 +477,17 @@ handle_ctrl_proto(u_int proto, const u_char *pptr, int length) case CPCODES_ID: if (length < 8) break; - printf(", Magic-Num=%08x", EXTRACT_32BITS(tptr)); + 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; - printf(", Magic-Num=%08x", EXTRACT_32BITS(tptr)); - printf(" Seconds-Remaining=%u", EXTRACT_32BITS(tptr + 4)); + 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: @@ -479,9 +498,14 @@ handle_ctrl_proto(u_int proto, const u_char *pptr, int length) 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 */ @@ -492,12 +516,13 @@ print_lcp_config_options(const u_char *p, int length) 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]); + printf(", %s (%u)", lcpconfopts[opt],opt); else { printf(", unknown LCP option 0x%02x", opt); return len; @@ -506,78 +531,101 @@ print_lcp_config_options(const u_char *p, int length) switch (opt) { case LCPOPT_VEXT: if (len >= 6) { - printf(" OUI=%02x%02x%02x", p[2], p[3], p[4]); + TCHECK2(*(p + 2), 3); + printf(" Vendor: %s (%u)", + tok2str(oui_values,"Unknown",EXTRACT_24BITS(p+2)), + EXTRACT_24BITS(p+2)); #if 0 - printf(" kind=%02x", p[5]); - printf(" val=") + TCHECK(p[5]); + printf(", kind: 0x%02x", p[5]); + printf(", Value: 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) - printf("=%u", EXTRACT_16BITS(p + 2)); + if (len == 4) { + TCHECK2(*(p + 2), 2); + printf(" %u", EXTRACT_16BITS(p + 2)); + } break; case LCPOPT_ACCM: - if (len == 6) - printf("=%08x", EXTRACT_32BITS(p + 2)); + if (len == 6) { + TCHECK2(*(p + 2), 4); + printf(" 0x%08x", EXTRACT_32BITS(p + 2)); + } break; case LCPOPT_AP: if (len >= 4) { - if (p[2] == 0xc0 && p[3] == 0x23) - printf(" PAP"); - else if (p[2] == 0xc2 && p[3] == 0x23) { - printf(" CHAP/"); - 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; - } + 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; } - else if (p[2] == 0xc2 && p[3] == 0x27) - printf(" EAP"); - else if (p[2] == 0xc0 && p[3] == 0x27) - printf(" SPAP"); - else if (p[2] == 0xc1 && p[3] == 0x23) - printf(" Old-SPAP"); - else - printf("unknown"); + 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) { - if (p[2] == 0xc0 && p[3] == 0x25) + TCHECK2(*(p + 2), 2); + if (EXTRACT_16BITS(p+2) == PPP_LQM) printf(" LQR"); else printf(" unknown"); } break; case LCPOPT_MN: - if (len == 6) - printf("=%08x", EXTRACT_32BITS(p + 2)); + 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) - printf("=%04x", EXTRACT_16BITS(p + 2)); + 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"); @@ -603,12 +651,15 @@ print_lcp_config_options(const u_char *p, int length) } break; case LCPOPT_MLMRRU: - if (len == 4) - printf("=%u", EXTRACT_16BITS(p + 2)); + 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"); @@ -619,12 +670,14 @@ print_lcp_config_options(const u_char *p, int length) case MEDCLASS_IPV4: if (len != 7) break; - printf(" IPv4=%s", ipaddr_string(p + 3)); + TCHECK2(*(p + 3), 4); + printf(" IPv4 %s", ipaddr_string(p + 3)); break; case MEDCLASS_MAC: if (len != 9) break; - printf(" MAC=%02x:%02x:%02x:%02x:%02x:%02x", + 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: @@ -661,6 +714,10 @@ print_lcp_config_options(const u_char *p, int length) #endif } return len; + +trunc: + printf("[|lcp]"); + return 0; } /* CHAP */ @@ -677,10 +734,12 @@ handle_chap(const u_char *p, int length) 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]); @@ -690,9 +749,11 @@ handle_chap(const u_char *p, int length) } p++; + TCHECK(*p); printf("(%u)", *p); /* ID */ p++; + TCHECK2(*p, 2); len = EXTRACT_16BITS(p); p += 2; @@ -708,26 +769,37 @@ handle_chap(const u_char *p, int length) 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++) + 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++) + 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++) + printf(", Msg "); + for (i = 0; i< msg_size; i++) { + TCHECK(*p); safeputchar(*p++); + } break; } + return; + +trunc: + printf("[|chap]"); } /* PAP (see RFC 1334) */ @@ -744,10 +816,12 @@ handle_pap(const u_char *p, int length) 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]); @@ -757,9 +831,11 @@ handle_pap(const u_char *p, int length) } p++; + TCHECK(*p); printf("(%u)", *p); /* ID */ p++; + TCHECK2(*p, 2); len = EXTRACT_16BITS(p); p += 2; @@ -767,38 +843,50 @@ handle_pap(const u_char *p, int length) 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++) + 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++) + 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++) + printf(", Msg "); + for (i = 0; i< msg_len; i++) { + TCHECK(*p); safeputchar(*p++); + } break; } return; + +trunc: + printf("[|pap]"); } /* BAP */ @@ -817,6 +905,7 @@ print_ipcp_config_options(const u_char *p, int length) if (length < 2) return 0; + TCHECK2(*p, 2); len = p[1]; opt = p[0]; if (length < len) @@ -825,7 +914,8 @@ print_ipcp_config_options(const u_char *p, int length) case IPCPOPT_2ADDR: /* deprecated */ if (len != 10) goto invlen; - printf(", IP-Addrs src=%s dst=%s", + TCHECK2(*(p + 6), 4); + printf(", IP-Addrs src %s, dst %s", ipaddr_string(p + 2), ipaddr_string(p + 6)); break; @@ -833,6 +923,7 @@ print_ipcp_config_options(const u_char *p, int length) 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 */ @@ -842,32 +933,38 @@ print_ipcp_config_options(const u_char *p, int length) case IPCPOPT_ADDR: if (len != 6) goto invlen; - printf(", IP-Addr=%s", ipaddr_string(p + 2)); + TCHECK2(*(p + 2), 4); + printf(", IP-Addr %s", ipaddr_string(p + 2)); break; case IPCPOPT_MOBILE4: if (len != 6) goto invlen; - printf(", Home-Addr=%s", ipaddr_string(p + 2)); + TCHECK2(*(p + 2), 4); + printf(", Home-Addr %s", ipaddr_string(p + 2)); break; case IPCPOPT_PRIDNS: if (len != 6) goto invlen; - printf(", Pri-DNS=%s", ipaddr_string(p + 2)); + TCHECK2(*(p + 2), 4); + printf(", Pri-DNS %s", ipaddr_string(p + 2)); break; case IPCPOPT_PRINBNS: if (len != 6) goto invlen; - printf(", Pri-NBNS=%s", ipaddr_string(p + 2)); + TCHECK2(*(p + 2), 4); + printf(", Pri-NBNS %s", ipaddr_string(p + 2)); break; case IPCPOPT_SECDNS: if (len != 6) goto invlen; - printf(", Sec-DNS=%s", ipaddr_string(p + 2)); + TCHECK2(*(p + 2), 4); + printf(", Sec-DNS %s", ipaddr_string(p + 2)); break; case IPCPOPT_SECNBNS: if (len != 6) goto invlen; - printf(", Sec-NBNS=%s", ipaddr_string(p + 2)); + TCHECK2(*(p + 2), 4); + printf(", Sec-NBNS %s", ipaddr_string(p + 2)); break; default: printf(", unknown-%d", opt); @@ -878,6 +975,10 @@ print_ipcp_config_options(const u_char *p, int length) invlen: printf(", invalid-length-%d", opt); return 0; + +trunc: + printf("[|ipcp]"); + return 0; } /* CCP config options */ @@ -888,6 +989,7 @@ print_ccp_config_options(const u_char *p, int length) if (length < 2) return 0; + TCHECK2(*p, 2); len = p[1]; opt = p[0]; if (length < len) @@ -919,6 +1021,10 @@ print_ccp_config_options(const u_char *p, int length) } #endif return len; + +trunc: + printf("[|ccp]"); + return 0; } /* BACP config options */ @@ -929,17 +1035,89 @@ print_bacp_config_options(const u_char *p, int length) 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=%08x", EXTRACT_32BITS(p + 2)); + printf(", Magic-Num 0x%08x", EXTRACT_32BITS(p + 2)); } else { printf(", unknown-option-%d", opt); } return len; + +trunc: + printf("[|bacp]"); + return 0; +} + + +static void +ppp_hdlc(const u_char *p, int length) +{ + u_char *b, *s, *t, c; + int i, proto; + const void *se; + + b = (u_int8_t *)malloc(length); + if (b == NULL) + return; + + /* + * Unescape all the data into a temporary, private, buffer. + * Do this so that we dont overwrite the original packet + * contents. + */ + for (s = (u_char *)p, t = b, i = length; i > 0; i--) { + c = *s++; + if (c == 0x7d) { + if (i > 1) { + i--; + c = *s++ ^ 0x20; + } else + continue; + } + *t++ = c; + } + + se = snapend; + snapend = t; + + /* now lets guess about the payload codepoint format */ + proto = *b; /* start with a one-octet codepoint guess */ + + switch (proto) { + case PPP_IP: + ip_print(b+1, t - b - 1); + goto cleanup; +#ifdef INET6 + case PPP_IPV6: + ip6_print(b+1, t - b - 1); + goto cleanup; +#endif + default: /* no luck - try next guess */ + break; + } + + proto = EXTRACT_16BITS(b); /* next guess - load two octets */ + + switch (proto) { + case 0xff03: /* looks like a PPP frame */ + proto = EXTRACT_16BITS(b+2); /* load the PPP proto-id */ + handle_ppp(proto, b+4, t - b - 4); + break; + default: /* last guess - proto must be a PPP proto-id */ + handle_ppp(proto, b+2, t - b - 2); + break; + } + +cleanup: + snapend = se; + free(b); + return; } @@ -947,9 +1125,17 @@ print_bacp_config_options(const u_char *p, int length) static void handle_ppp(u_int proto, const u_char *p, int length) { + if ((proto & 0xff00) == 0x7e00) {/* is this an escape code ? */ + ppp_hdlc(p-1, length); + return; + } + 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); @@ -964,6 +1150,7 @@ handle_ppp(u_int proto, const u_char *p, int length) handle_bap(p, length); break; case ETHERTYPE_IP: /*XXX*/ + case PPP_VJNC: case PPP_IP: ip_print(p, length); break; @@ -978,16 +1165,19 @@ handle_ppp(u_int proto, const u_char *p, int length) ipx_print(p, length); break; case PPP_OSI: - isoclns_print(p, length, length, NULL, NULL); + isoclns_print(p, length, length); break; case PPP_MPLS_UCAST: case PPP_MPLS_MCAST: mpls_print(p, length); break; + case PPP_COMP: + printf("compressed PPP data"); + break; default: - printf("unknown PPP protocol (0x%04x)", proto); - print_unknown_data(p,"\n\t",length); - break; + printf("%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto)); + print_unknown_data(p,"\n\t",length); + break; } } @@ -1005,6 +1195,7 @@ ppp_print(register const u_char *p, u_int length) */ if (length < 2) goto trunc; + TCHECK2(*p, 2); if (*p == PPP_ADDRESS && *(p + 1) == PPP_CONTROL) { p += 2; /* ACFC not used */ length -= 2; @@ -1013,12 +1204,14 @@ ppp_print(register const u_char *p, u_int length) 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; @@ -1026,7 +1219,7 @@ ppp_print(register const u_char *p, u_int length) } if (eflag) - printf("PPP-%s (0x%04x) length: %u, ", + printf("%s (0x%04x), length %u: ", tok2str(ppptype2str, "unknown", proto), proto, olen);