tcpdump-4.99.1/0000755000026300017510000000000014060212545011414 5ustar mcrmcrtcpdump-4.99.1/mib.h0000644000026300017510000006452314057477727012373 0ustar mcrmcr/* * This file was generated by tcpdump/makemib on Wed Sep 26 12:12:31 EDT 1990 * You probably don't want to edit this by hand! * * struct mib somename = { desc, oid-octet, type, child-pointer, next-pointer }; */ /* parse problem: new name "mib" for mgmt.mib(1) ignored */ /* parse problem: no parent for 0.nullSpecific(0) */ static struct obj _proteon_obj = { "proteon", 1, 0, NULL, NULL }, _ibm_obj = { "ibm", 2, 0, NULL, &_proteon_obj }, _cmu_obj = { "cmu", 3, 0, NULL, &_ibm_obj }, _unix_obj = { "unix", 4, 0, NULL, &_cmu_obj }, _acc_obj = { "acc", 5, 0, NULL, &_unix_obj }, _twg_obj = { "twg", 6, 0, NULL, &_acc_obj }, _cayman_obj = { "cayman", 7, 0, NULL, &_twg_obj }, _nysernet_obj = { "nysernet", 8, 0, NULL, &_cayman_obj }, _cisco_obj = { "cisco", 9, 0, NULL, &_nysernet_obj }, _nsc_obj = { "nsc", 10, 0, NULL, &_cisco_obj }, _hp_obj = { "hp", 11, 0, NULL, &_nsc_obj }, _epilogue_obj = { "epilogue", 12, 0, NULL, &_hp_obj }, _utennessee_obj = { "utennessee", 13, 0, NULL, &_epilogue_obj }, _bbn_obj = { "bbn", 14, 0, NULL, &_utennessee_obj }, _xylogics_obj = { "xylogics", 15, 0, NULL, &_bbn_obj }, _unisys_obj = { "unisys", 16, 0, NULL, &_xylogics_obj }, _canstar_obj = { "canstar", 17, 0, NULL, &_unisys_obj }, _wellfleet_obj = { "wellfleet", 18, 0, NULL, &_canstar_obj }, _trw_obj = { "trw", 19, 0, NULL, &_wellfleet_obj }, _mit_obj = { "mit", 20, 0, NULL, &_trw_obj }, _eon_obj = { "eon", 21, 0, NULL, &_mit_obj }, _spartacus_obj = { "spartacus", 22, 0, NULL, &_eon_obj }, _excelan_obj = { "excelan", 23, 0, NULL, &_spartacus_obj }, _spider_obj = { "spider", 24, 0, NULL, &_excelan_obj }, _nsfnet_obj = { "nsfnet", 25, 0, NULL, &_spider_obj }, _sytek_obj = { "sytek", 26, 0, NULL, &_nsfnet_obj }, _intergraph_obj = { "intergraph", 27, 0, NULL, &_sytek_obj }, _interlan_obj = { "interlan", 28, 0, NULL, &_intergraph_obj }, _vitalink_obj = { "vitalink", 29, 0, NULL, &_interlan_obj }, _ulana_obj = { "ulana", 30, 0, NULL, &_vitalink_obj }, _nswc_obj = { "nswc", 31, 0, NULL, &_ulana_obj }, _santacruzoperation_obj = { "santacruzoperation", 32, 0, NULL, &_nswc_obj }, _xyplex_obj = { "xyplex", 33, 0, NULL, &_santacruzoperation_obj }, _cray_obj = { "cray", 34, 0, NULL, &_xyplex_obj }, _bellnorthernresearch_obj = { "bellnorthernresearch", 35, 0, NULL, &_cray_obj }, _dec_obj = { "dec", 36, 0, NULL, &_bellnorthernresearch_obj }, _touch_obj = { "touch", 37, 0, NULL, &_dec_obj }, _networkresearchcorp_obj = { "networkresearchcorp", 38, 0, NULL, &_touch_obj }, _baylor_obj = { "baylor", 39, 0, NULL, &_networkresearchcorp_obj }, _nmfeccllnl_obj = { "nmfeccllnl", 40, 0, NULL, &_baylor_obj }, _sri_obj = { "sri", 41, 0, NULL, &_nmfeccllnl_obj }, _sun_obj = { "sun", 42, 0, NULL, &_sri_obj }, _3com_obj = { "3com", 43, 0, NULL, &_sun_obj }, _cmc_obj = { "cmc", 44, 0, NULL, &_3com_obj }, _synoptics_obj = { "synoptics", 45, 0, NULL, &_cmc_obj }, _cheyenne_obj = { "cheyenne", 46, 0, NULL, &_synoptics_obj }, _prime_obj = { "prime", 47, 0, NULL, &_cheyenne_obj }, _mcnc_obj = { "mcnc", 48, 0, NULL, &_prime_obj }, _chipcom_obj = { "chipcom", 49, 0, NULL, &_mcnc_obj }, _opticaldatasystems_obj = { "opticaldatasystems", 50, 0, NULL, &_chipcom_obj }, _gated_obj = { "gated", 51, 0, NULL, &_opticaldatasystems_obj }, _cabletron_obj = { "cabletron", 52, 0, NULL, &_gated_obj }, _apollo_obj = { "apollo", 53, 0, NULL, &_cabletron_obj }, _desktalksystems_obj = { "desktalksystems", 54, 0, NULL, &_apollo_obj }, _ssds_obj = { "ssds", 55, 0, NULL, &_desktalksystems_obj }, _castlerock_obj = { "castlerock", 56, 0, NULL, &_ssds_obj }, _mips_obj = { "mips", 57, 0, NULL, &_castlerock_obj }, _tgv_obj = { "tgv", 58, 0, NULL, &_mips_obj }, _silicongraphics_obj = { "silicongraphics", 59, 0, NULL, &_tgv_obj }, _ubc_obj = { "ubc", 60, 0, NULL, &_silicongraphics_obj }, _merit_obj = { "merit", 61, 0, NULL, &_ubc_obj }, _fibercom_obj = { "fibercom", 62, 0, NULL, &_merit_obj }, _apple_obj = { "apple", 63, 0, NULL, &_fibercom_obj }, _gandalf_obj = { "gandalf", 64, 0, NULL, &_apple_obj }, _dartmouth_obj = { "dartmouth", 65, 0, NULL, &_gandalf_obj }, _davidsystems_obj = { "davidsystems", 66, 0, NULL, &_dartmouth_obj }, _reuter_obj = { "reuter", 67, 0, NULL, &_davidsystems_obj }, _cornell_obj = { "cornell", 68, 0, NULL, &_reuter_obj }, _tmac_obj = { "tmac", 69, 0, NULL, &_cornell_obj }, _locus_obj = { "locus", 70, 0, NULL, &_tmac_obj }, _nasa_obj = { "nasa", 71, 0, NULL, &_locus_obj }, _retix_obj = { "retix", 72, 0, NULL, &_nasa_obj }, _boeing_obj = { "boeing", 73, 0, NULL, &_retix_obj }, _att_obj = { "att", 74, 0, NULL, &_boeing_obj }, _ungermannbass_obj = { "ungermannbass", 75, 0, NULL, &_att_obj }, _digitalanalysis_obj = { "digitalanalysis", 76, 0, NULL, &_ungermannbass_obj }, _hplanman_obj = { "hplanman", 77, 0, NULL, &_digitalanalysis_obj }, _netlabs_obj = { "netlabs", 78, 0, NULL, &_hplanman_obj }, _icl_obj = { "icl", 79, 0, NULL, &_netlabs_obj }, _auspex_obj = { "auspex", 80, 0, NULL, &_icl_obj }, _lannet_obj = { "lannet", 81, 0, NULL, &_auspex_obj }, _ncd_obj = { "ncd", 82, 0, NULL, &_lannet_obj }, _raycom_obj = { "raycom", 83, 0, NULL, &_ncd_obj }, _pirellifocom_obj = { "pirellifocom", 84, 0, NULL, &_raycom_obj }, _datability_obj = { "datability", 85, 0, NULL, &_pirellifocom_obj }, _networkappltech_obj = { "networkappltech", 86, 0, NULL, &_datability_obj }, _link_obj = { "link", 87, 0, NULL, &_networkappltech_obj }, _nyu_obj = { "nyu", 88, 0, NULL, &_link_obj }, _rnd_obj = { "rnd", 89, 0, NULL, &_nyu_obj }, _intercon_obj = { "intercon", 90, 0, NULL, &_rnd_obj }, _learningtree_obj = { "learningtree", 91, 0, NULL, &_intercon_obj }, _webstercomputer_obj = { "webstercomputer", 92, 0, NULL, &_learningtree_obj }, _frontier_obj = { "frontier", 93, 0, NULL, &_webstercomputer_obj }, _nokia_obj = { "nokia", 94, 0, NULL, &_frontier_obj }, _allenbradley_obj = { "allenbradley", 95, 0, NULL, &_nokia_obj }, _cern_obj = { "cern", 96, 0, NULL, &_allenbradley_obj }, _sigma_obj = { "sigma", 97, 0, NULL, &_cern_obj }, _emergingtech_obj = { "emergingtech", 98, 0, NULL, &_sigma_obj }, _snmpresearch_obj = { "snmpresearch", 99, 0, NULL, &_emergingtech_obj }, _ohiostate_obj = { "ohiostate", 100, 0, NULL, &_snmpresearch_obj }, _ultra_obj = { "ultra", 101, 0, NULL, &_ohiostate_obj }, _ccur_obj = { "ccur", 136, 0, NULL, &_ultra_obj }, _enterprises_obj = { "enterprises", 1, 0, &_ccur_obj, NULL }, _snmpInPkts_obj = { "snmpInPkts", 1, 0, NULL, NULL }, _snmpOutPkts_obj = { "snmpOutPkts", 2, 0, NULL, &_snmpInPkts_obj }, _snmpInBadVersions_obj = { "snmpInBadVersions", 3, 0, NULL, &_snmpOutPkts_obj }, _snmpInBadCommunityNames_obj = { "snmpInBadCommunityNames", 4, 0, NULL, &_snmpInBadVersions_obj }, _snmpInBadCommunityUses_obj = { "snmpInBadCommunityUses", 5, 0, NULL, &_snmpInBadCommunityNames_obj }, _snmpInASNParseErrs_obj = { "snmpInASNParseErrs", 6, 0, NULL, &_snmpInBadCommunityUses_obj }, _snmpInBadTypes_obj = { "snmpInBadTypes", 7, 0, NULL, &_snmpInASNParseErrs_obj }, _snmpInTooBigs_obj = { "snmpInTooBigs", 8, 0, NULL, &_snmpInBadTypes_obj }, _snmpInNoSuchNames_obj = { "snmpInNoSuchNames", 9, 0, NULL, &_snmpInTooBigs_obj }, _snmpInBadValues_obj = { "snmpInBadValues", 10, 0, NULL, &_snmpInNoSuchNames_obj }, _snmpInReadOnlys_obj = { "snmpInReadOnlys", 11, 0, NULL, &_snmpInBadValues_obj }, _snmpInGenErrs_obj = { "snmpInGenErrs", 12, 0, NULL, &_snmpInReadOnlys_obj }, _snmpInTotalReqVars_obj = { "snmpInTotalReqVars", 13, 0, NULL, &_snmpInGenErrs_obj }, _snmpInTotalSetVars_obj = { "snmpInTotalSetVars", 14, 0, NULL, &_snmpInTotalReqVars_obj }, _snmpInGetRequests_obj = { "snmpInGetRequests", 15, 0, NULL, &_snmpInTotalSetVars_obj }, _snmpInGetNexts_obj = { "snmpInGetNexts", 16, 0, NULL, &_snmpInGetRequests_obj }, _snmpInSetRequests_obj = { "snmpInSetRequests", 17, 0, NULL, &_snmpInGetNexts_obj }, _snmpInGetResponses_obj = { "snmpInGetResponses", 18, 0, NULL, &_snmpInSetRequests_obj }, _snmpInTraps_obj = { "snmpInTraps", 19, 0, NULL, &_snmpInGetResponses_obj }, _snmpOutTooBigs_obj = { "snmpOutTooBigs", 20, 0, NULL, &_snmpInTraps_obj }, _snmpOutNoSuchNames_obj = { "snmpOutNoSuchNames", 21, 0, NULL, &_snmpOutTooBigs_obj }, _snmpOutBadValues_obj = { "snmpOutBadValues", 22, 0, NULL, &_snmpOutNoSuchNames_obj }, _snmpOutReadOnlys_obj = { "snmpOutReadOnlys", 23, 0, NULL, &_snmpOutBadValues_obj }, _snmpOutGenErrs_obj = { "snmpOutGenErrs", 24, 0, NULL, &_snmpOutReadOnlys_obj }, _snmpOutGetRequests_obj = { "snmpOutGetRequests", 25, 0, NULL, &_snmpOutGenErrs_obj }, _snmpOutGetNexts_obj = { "snmpOutGetNexts", 26, 0, NULL, &_snmpOutGetRequests_obj }, _snmpOutSetRequests_obj = { "snmpOutSetRequests", 27, 0, NULL, &_snmpOutGetNexts_obj }, _snmpOutGetResponses_obj = { "snmpOutGetResponses", 28, 0, NULL, &_snmpOutSetRequests_obj }, _snmpOutTraps_obj = { "snmpOutTraps", 29, 0, NULL, &_snmpOutGetResponses_obj }, _snmpEnableAuthTraps_obj = { "snmpEnableAuthTraps", 30, 0, NULL, &_snmpOutTraps_obj }, _egpNeighState_obj = { "egpNeighState", 1, 0, NULL, NULL }, _egpNeighAddr_obj = { "egpNeighAddr", 2, 0, NULL, &_egpNeighState_obj }, _egpNeighAs_obj = { "egpNeighAs", 3, 0, NULL, &_egpNeighAddr_obj }, _egpNeighInMsgs_obj = { "egpNeighInMsgs", 4, 0, NULL, &_egpNeighAs_obj }, _egpNeighInErrs_obj = { "egpNeighInErrs", 5, 0, NULL, &_egpNeighInMsgs_obj }, _egpNeighOutMsgs_obj = { "egpNeighOutMsgs", 6, 0, NULL, &_egpNeighInErrs_obj }, _egpNeighOutErrs_obj = { "egpNeighOutErrs", 7, 0, NULL, &_egpNeighOutMsgs_obj }, _egpNeighInErrMsgs_obj = { "egpNeighInErrMsgs", 8, 0, NULL, &_egpNeighOutErrs_obj }, _egpNeighOutErrMsgs_obj = { "egpNeighOutErrMsgs", 9, 0, NULL, &_egpNeighInErrMsgs_obj }, _egpNeighStateUps_obj = { "egpNeighStateUps", 10, 0, NULL, &_egpNeighOutErrMsgs_obj }, _egpNeighStateDowns_obj = { "egpNeighStateDowns", 11, 0, NULL, &_egpNeighStateUps_obj }, _egpNeighIntervalHello_obj = { "egpNeighIntervalHello", 12, 0, NULL, &_egpNeighStateDowns_obj }, _egpNeighIntervalPoll_obj = { "egpNeighIntervalPoll", 13, 0, NULL, &_egpNeighIntervalHello_obj }, _egpNeighMode_obj = { "egpNeighMode", 14, 0, NULL, &_egpNeighIntervalPoll_obj }, _egpNeighEventTrigger_obj = { "egpNeighEventTrigger", 15, 0, NULL, &_egpNeighMode_obj }, _egpNeighEntry_obj = { "egpNeighEntry", 1, 0, &_egpNeighEventTrigger_obj, NULL }, _egpInMsgs_obj = { "egpInMsgs", 1, 0, NULL, NULL }, _egpInErrors_obj = { "egpInErrors", 2, 0, NULL, &_egpInMsgs_obj }, _egpOutMsgs_obj = { "egpOutMsgs", 3, 0, NULL, &_egpInErrors_obj }, _egpOutErrors_obj = { "egpOutErrors", 4, 0, NULL, &_egpOutMsgs_obj }, _egpNeighTable_obj = { "egpNeighTable", 5, 0, &_egpNeighEntry_obj, &_egpOutErrors_obj }, _egpAs_obj = { "egpAs", 6, 0, NULL, &_egpNeighTable_obj }, _udpLocalAddress_obj = { "udpLocalAddress", 1, 0, NULL, NULL }, _udpLocalPort_obj = { "udpLocalPort", 2, 0, NULL, &_udpLocalAddress_obj }, _udpEntry_obj = { "udpEntry", 1, 0, &_udpLocalPort_obj, NULL }, _udpInDatagrams_obj = { "udpInDatagrams", 1, 0, NULL, NULL }, _udpNoPorts_obj = { "udpNoPorts", 2, 0, NULL, &_udpInDatagrams_obj }, _udpInErrors_obj = { "udpInErrors", 3, 0, NULL, &_udpNoPorts_obj }, _udpOutDatagrams_obj = { "udpOutDatagrams", 4, 0, NULL, &_udpInErrors_obj }, _udpTable_obj = { "udpTable", 5, 0, &_udpEntry_obj, &_udpOutDatagrams_obj }, _tcpConnState_obj = { "tcpConnState", 1, 0, NULL, NULL }, _tcpConnLocalAddress_obj = { "tcpConnLocalAddress", 2, 0, NULL, &_tcpConnState_obj }, _tcpConnLocalPort_obj = { "tcpConnLocalPort", 3, 0, NULL, &_tcpConnLocalAddress_obj }, _tcpConnRemAddress_obj = { "tcpConnRemAddress", 4, 0, NULL, &_tcpConnLocalPort_obj }, _tcpConnRemPort_obj = { "tcpConnRemPort", 5, 0, NULL, &_tcpConnRemAddress_obj }, _tcpConnEntry_obj = { "tcpConnEntry", 1, 0, &_tcpConnRemPort_obj, NULL }, _tcpRtoAlgorithm_obj = { "tcpRtoAlgorithm", 1, 0, NULL, NULL }, _tcpRtoMin_obj = { "tcpRtoMin", 2, 0, NULL, &_tcpRtoAlgorithm_obj }, _tcpRtoMax_obj = { "tcpRtoMax", 3, 0, NULL, &_tcpRtoMin_obj }, _tcpMaxConn_obj = { "tcpMaxConn", 4, 0, NULL, &_tcpRtoMax_obj }, _tcpActiveOpens_obj = { "tcpActiveOpens", 5, 0, NULL, &_tcpMaxConn_obj }, _tcpPassiveOpens_obj = { "tcpPassiveOpens", 6, 0, NULL, &_tcpActiveOpens_obj }, _tcpAttemptFails_obj = { "tcpAttemptFails", 7, 0, NULL, &_tcpPassiveOpens_obj }, _tcpEstabResets_obj = { "tcpEstabResets", 8, 0, NULL, &_tcpAttemptFails_obj }, _tcpCurrEstab_obj = { "tcpCurrEstab", 9, 0, NULL, &_tcpEstabResets_obj }, _tcpInSegs_obj = { "tcpInSegs", 10, 0, NULL, &_tcpCurrEstab_obj }, _tcpOutSegs_obj = { "tcpOutSegs", 11, 0, NULL, &_tcpInSegs_obj }, _tcpRetransSegs_obj = { "tcpRetransSegs", 12, 0, NULL, &_tcpOutSegs_obj }, _tcpConnTable_obj = { "tcpConnTable", 13, 0, &_tcpConnEntry_obj, &_tcpRetransSegs_obj }, _tcpInErrs_obj = { "tcpInErrs", 14, 0, NULL, &_tcpConnTable_obj }, _tcpOutRsts_obj = { "tcpOutRsts", 15, 0, NULL, &_tcpInErrs_obj }, _icmpInMsgs_obj = { "icmpInMsgs", 1, 0, NULL, NULL }, _icmpInErrors_obj = { "icmpInErrors", 2, 0, NULL, &_icmpInMsgs_obj }, _icmpInDestUnreachs_obj = { "icmpInDestUnreachs", 3, 0, NULL, &_icmpInErrors_obj }, _icmpInTimeExcds_obj = { "icmpInTimeExcds", 4, 0, NULL, &_icmpInDestUnreachs_obj }, _icmpInParmProbs_obj = { "icmpInParmProbs", 5, 0, NULL, &_icmpInTimeExcds_obj }, _icmpInSrcQuenchs_obj = { "icmpInSrcQuenchs", 6, 0, NULL, &_icmpInParmProbs_obj }, _icmpInRedirects_obj = { "icmpInRedirects", 7, 0, NULL, &_icmpInSrcQuenchs_obj }, _icmpInEchos_obj = { "icmpInEchos", 8, 0, NULL, &_icmpInRedirects_obj }, _icmpInEchoReps_obj = { "icmpInEchoReps", 9, 0, NULL, &_icmpInEchos_obj }, _icmpInTimestamps_obj = { "icmpInTimestamps", 10, 0, NULL, &_icmpInEchoReps_obj }, _icmpInTimestampReps_obj = { "icmpInTimestampReps", 11, 0, NULL, &_icmpInTimestamps_obj }, _icmpInAddrMasks_obj = { "icmpInAddrMasks", 12, 0, NULL, &_icmpInTimestampReps_obj }, _icmpInAddrMaskReps_obj = { "icmpInAddrMaskReps", 13, 0, NULL, &_icmpInAddrMasks_obj }, _icmpOutMsgs_obj = { "icmpOutMsgs", 14, 0, NULL, &_icmpInAddrMaskReps_obj }, _icmpOutErrors_obj = { "icmpOutErrors", 15, 0, NULL, &_icmpOutMsgs_obj }, _icmpOutDestUnreachs_obj = { "icmpOutDestUnreachs", 16, 0, NULL, &_icmpOutErrors_obj }, _icmpOutTimeExcds_obj = { "icmpOutTimeExcds", 17, 0, NULL, &_icmpOutDestUnreachs_obj }, _icmpOutParmProbs_obj = { "icmpOutParmProbs", 18, 0, NULL, &_icmpOutTimeExcds_obj }, _icmpOutSrcQuenchs_obj = { "icmpOutSrcQuenchs", 19, 0, NULL, &_icmpOutParmProbs_obj }, _icmpOutRedirects_obj = { "icmpOutRedirects", 20, 0, NULL, &_icmpOutSrcQuenchs_obj }, _icmpOutEchos_obj = { "icmpOutEchos", 21, 0, NULL, &_icmpOutRedirects_obj }, _icmpOutEchoReps_obj = { "icmpOutEchoReps", 22, 0, NULL, &_icmpOutEchos_obj }, _icmpOutTimestamps_obj = { "icmpOutTimestamps", 23, 0, NULL, &_icmpOutEchoReps_obj }, _icmpOutTimestampReps_obj = { "icmpOutTimestampReps", 24, 0, NULL, &_icmpOutTimestamps_obj }, _icmpOutAddrMasks_obj = { "icmpOutAddrMasks", 25, 0, NULL, &_icmpOutTimestampReps_obj }, _icmpOutAddrMaskReps_obj = { "icmpOutAddrMaskReps", 26, 0, NULL, &_icmpOutAddrMasks_obj }, _ipNetToMediaIfIndex_obj = { "ipNetToMediaIfIndex", 1, 0, NULL, NULL }, _ipNetToMediaPhysAddress_obj = { "ipNetToMediaPhysAddress", 2, 0, NULL, &_ipNetToMediaIfIndex_obj }, _ipNetToMediaNetAddress_obj = { "ipNetToMediaNetAddress", 3, 0, NULL, &_ipNetToMediaPhysAddress_obj }, _ipNetToMediaType_obj = { "ipNetToMediaType", 4, 0, NULL, &_ipNetToMediaNetAddress_obj }, _ipNetToMediaEntry_obj = { "ipNetToMediaEntry", 1, 0, &_ipNetToMediaType_obj, NULL }, _ipRouteDest_obj = { "ipRouteDest", 1, 0, NULL, NULL }, _ipRouteIfIndex_obj = { "ipRouteIfIndex", 2, 0, NULL, &_ipRouteDest_obj }, _ipRouteMetric1_obj = { "ipRouteMetric1", 3, 0, NULL, &_ipRouteIfIndex_obj }, _ipRouteMetric2_obj = { "ipRouteMetric2", 4, 0, NULL, &_ipRouteMetric1_obj }, _ipRouteMetric3_obj = { "ipRouteMetric3", 5, 0, NULL, &_ipRouteMetric2_obj }, _ipRouteMetric4_obj = { "ipRouteMetric4", 6, 0, NULL, &_ipRouteMetric3_obj }, _ipRouteNextHop_obj = { "ipRouteNextHop", 7, 0, NULL, &_ipRouteMetric4_obj }, _ipRouteType_obj = { "ipRouteType", 8, 0, NULL, &_ipRouteNextHop_obj }, _ipRouteProto_obj = { "ipRouteProto", 9, 0, NULL, &_ipRouteType_obj }, _ipRouteAge_obj = { "ipRouteAge", 10, 0, NULL, &_ipRouteProto_obj }, _ipRouteMask_obj = { "ipRouteMask", 11, 0, NULL, &_ipRouteAge_obj }, _ipRouteEntry_obj = { "ipRouteEntry", 1, 0, &_ipRouteMask_obj, NULL }, _ipAdEntAddr_obj = { "ipAdEntAddr", 1, 0, NULL, NULL }, _ipAdEntIfIndex_obj = { "ipAdEntIfIndex", 2, 0, NULL, &_ipAdEntAddr_obj }, _ipAdEntNetMask_obj = { "ipAdEntNetMask", 3, 0, NULL, &_ipAdEntIfIndex_obj }, _ipAdEntBcastAddr_obj = { "ipAdEntBcastAddr", 4, 0, NULL, &_ipAdEntNetMask_obj }, _ipAdEntReasmMaxSize_obj = { "ipAdEntReasmMaxSize", 5, 0, NULL, &_ipAdEntBcastAddr_obj }, _ipAddrEntry_obj = { "ipAddrEntry", 1, 0, &_ipAdEntReasmMaxSize_obj, NULL }, _ipForwarding_obj = { "ipForwarding", 1, 0, NULL, NULL }, _ipDefaultTTL_obj = { "ipDefaultTTL", 2, 0, NULL, &_ipForwarding_obj }, _ipInReceives_obj = { "ipInReceives", 3, 0, NULL, &_ipDefaultTTL_obj }, _ipInHdrErrors_obj = { "ipInHdrErrors", 4, 0, NULL, &_ipInReceives_obj }, _ipInAddrErrors_obj = { "ipInAddrErrors", 5, 0, NULL, &_ipInHdrErrors_obj }, _ipForwDatagrams_obj = { "ipForwDatagrams", 6, 0, NULL, &_ipInAddrErrors_obj }, _ipInUnknownProtos_obj = { "ipInUnknownProtos", 7, 0, NULL, &_ipForwDatagrams_obj }, _ipInDiscards_obj = { "ipInDiscards", 8, 0, NULL, &_ipInUnknownProtos_obj }, _ipInDelivers_obj = { "ipInDelivers", 9, 0, NULL, &_ipInDiscards_obj }, _ipOutRequests_obj = { "ipOutRequests", 10, 0, NULL, &_ipInDelivers_obj }, _ipOutDiscards_obj = { "ipOutDiscards", 11, 0, NULL, &_ipOutRequests_obj }, _ipOutNoRoutes_obj = { "ipOutNoRoutes", 12, 0, NULL, &_ipOutDiscards_obj }, _ipReasmTimeout_obj = { "ipReasmTimeout", 13, 0, NULL, &_ipOutNoRoutes_obj }, _ipReasmReqds_obj = { "ipReasmReqds", 14, 0, NULL, &_ipReasmTimeout_obj }, _ipReasmOKs_obj = { "ipReasmOKs", 15, 0, NULL, &_ipReasmReqds_obj }, _ipReasmFails_obj = { "ipReasmFails", 16, 0, NULL, &_ipReasmOKs_obj }, _ipFragOKs_obj = { "ipFragOKs", 17, 0, NULL, &_ipReasmFails_obj }, _ipFragFails_obj = { "ipFragFails", 18, 0, NULL, &_ipFragOKs_obj }, _ipFragCreates_obj = { "ipFragCreates", 19, 0, NULL, &_ipFragFails_obj }, _ipAddrTable_obj = { "ipAddrTable", 20, 0, &_ipAddrEntry_obj, &_ipFragCreates_obj }, _ipRoutingTable_obj = { "ipRoutingTable", 21, 0, &_ipRouteEntry_obj, &_ipAddrTable_obj }, _ipNetToMediaTable_obj = { "ipNetToMediaTable", 22, 0, &_ipNetToMediaEntry_obj, &_ipRoutingTable_obj }, _atIfIndex_obj = { "atIfIndex", 1, 0, NULL, NULL }, _atPhysAddress_obj = { "atPhysAddress", 2, 0, NULL, &_atIfIndex_obj }, _atNetAddress_obj = { "atNetAddress", 3, 0, NULL, &_atPhysAddress_obj }, _atEntry_obj = { "atEntry", 1, 0, &_atNetAddress_obj, NULL }, _atTable_obj = { "atTable", 1, 0, &_atEntry_obj, NULL }, _ifIndex_obj = { "ifIndex", 1, 0, NULL, NULL }, _ifDescr_obj = { "ifDescr", 2, 0, NULL, &_ifIndex_obj }, _ifType_obj = { "ifType", 3, 0, NULL, &_ifDescr_obj }, _ifMtu_obj = { "ifMtu", 4, 0, NULL, &_ifType_obj }, _ifSpeed_obj = { "ifSpeed", 5, 0, NULL, &_ifMtu_obj }, _ifPhysAddress_obj = { "ifPhysAddress", 6, 0, NULL, &_ifSpeed_obj }, _ifAdminStatus_obj = { "ifAdminStatus", 7, 0, NULL, &_ifPhysAddress_obj }, _ifOperStatus_obj = { "ifOperStatus", 8, 0, NULL, &_ifAdminStatus_obj }, _ifLastChange_obj = { "ifLastChange", 9, 0, NULL, &_ifOperStatus_obj }, _ifInOctets_obj = { "ifInOctets", 10, 0, NULL, &_ifLastChange_obj }, _ifInUcastPkts_obj = { "ifInUcastPkts", 11, 0, NULL, &_ifInOctets_obj }, _ifInNUcastPkts_obj = { "ifInNUcastPkts", 12, 0, NULL, &_ifInUcastPkts_obj }, _ifInDiscards_obj = { "ifInDiscards", 13, 0, NULL, &_ifInNUcastPkts_obj }, _ifInErrors_obj = { "ifInErrors", 14, 0, NULL, &_ifInDiscards_obj }, _ifInUnknownProtos_obj = { "ifInUnknownProtos", 15, 0, NULL, &_ifInErrors_obj }, _ifOutOctets_obj = { "ifOutOctets", 16, 0, NULL, &_ifInUnknownProtos_obj }, _ifOutUcastPkts_obj = { "ifOutUcastPkts", 17, 0, NULL, &_ifOutOctets_obj }, _ifOutNUcastPkts_obj = { "ifOutNUcastPkts", 18, 0, NULL, &_ifOutUcastPkts_obj }, _ifOutDiscards_obj = { "ifOutDiscards", 19, 0, NULL, &_ifOutNUcastPkts_obj }, _ifOutErrors_obj = { "ifOutErrors", 20, 0, NULL, &_ifOutDiscards_obj }, _ifOutQLen_obj = { "ifOutQLen", 21, 0, NULL, &_ifOutErrors_obj }, _ifSpecific_obj = { "ifSpecific", 22, 0, NULL, &_ifOutQLen_obj }, _ifEntry_obj = { "ifEntry", 1, 0, &_ifSpecific_obj, NULL }, _ifNumber_obj = { "ifNumber", 1, 0, NULL, NULL }, _ifTable_obj = { "ifTable", 2, 0, &_ifEntry_obj, &_ifNumber_obj }, _sysDescr_obj = { "sysDescr", 1, 0, NULL, NULL }, _sysObjectID_obj = { "sysObjectID", 2, 0, NULL, &_sysDescr_obj }, _sysUpTime_obj = { "sysUpTime", 3, 0, NULL, &_sysObjectID_obj }, _sysContact_obj = { "sysContact", 4, 0, NULL, &_sysUpTime_obj }, _sysName_obj = { "sysName", 5, 0, NULL, &_sysContact_obj }, _sysLocation_obj = { "sysLocation", 6, 0, NULL, &_sysName_obj }, _sysServices_obj = { "sysServices", 7, 0, NULL, &_sysLocation_obj }, _system_obj = { "system", 1, 0, &_sysServices_obj, NULL }, _interfaces_obj = { "interfaces", 2, 0, &_ifTable_obj, &_system_obj }, _at_obj = { "at", 3, 0, &_atTable_obj, &_interfaces_obj }, _ip_obj = { "ip", 4, 0, &_ipNetToMediaTable_obj, &_at_obj }, _icmp_obj = { "icmp", 5, 0, &_icmpOutAddrMaskReps_obj, &_ip_obj }, _tcp_obj = { "tcp", 6, 0, &_tcpOutRsts_obj, &_icmp_obj }, _udp_obj = { "udp", 7, 0, &_udpTable_obj, &_tcp_obj }, _egp_obj = { "egp", 8, 0, &_egpAs_obj, &_udp_obj }, _transmission_obj = { "transmission", 10, 0, NULL, &_egp_obj }, _snmp_obj = { "snmp", 11, 0, &_snmpEnableAuthTraps_obj, &_transmission_obj }, _usmMIBCompliances_obj = { "usmMIBCompliances", 1, 0, NULL, NULL }, _usmMIBGroups_obj = { "usmMIBGroups", 2, 0, NULL, &_usmMIBCompliances_obj }, _usmUserEngineID_obj = { "usmUserEngineID", 1, 0, NULL, NULL }, _usmUserName_obj = { "usmUserName", 2, 0, NULL, &_usmUserEngineID_obj }, _usmUserSecurityName_obj = { "usmUserSecurityName", 3, 0, NULL, &_usmUserName_obj }, _usmUserCloneFrom_obj = { "usmUserCloneFrom", 4, 0, NULL, &_usmUserSecurityName_obj }, _usmUserAuthProtocol_obj = { "usmUserAuthProtocol", 5, 0, NULL, &_usmUserCloneFrom_obj }, _usmUserAuthKeyChange_obj = { "usmUserAuthKeyChange", 6, 0, NULL, &_usmUserAuthProtocol_obj }, _usmUserOwnAuthKeyChange_obj = { "usmUserOwnAuthKeyChange", 7, 0, NULL, &_usmUserAuthKeyChange_obj }, _usmUserPrivProtocol_obj = { "usmUserPrivProtocol", 8, 0, NULL, &_usmUserOwnAuthKeyChange_obj }, _usmUserPrivKeyChange_obj = { "usmUserPrivKeyChange", 9, 0, NULL, &_usmUserPrivProtocol_obj }, _usmUserOwnPrivKeyChange_obj = { "usmUserOwnPrivKeyChange", 10, 0, NULL, &_usmUserPrivKeyChange_obj }, _usmUserPublic_obj = { "usmUserPublic", 11, 0, NULL, &_usmUserOwnPrivKeyChange_obj }, _usmUserStorageType_obj = { "usmUserStorageType", 12, 0, NULL, &_usmUserPublic_obj }, _usmUserStatus_obj = { "usmUserStatus", 13, 0, NULL, &_usmUserStorageType_obj }, _usmUserEntry_obj = { "usmUserEntry", 1, 0, &_usmUserStatus_obj, NULL }, _usmUserSpinLock_obj = { "usmUserSpinLock", 1, 0, NULL, NULL }, _usmUserTable_obj = { "usmUserTable", 2, 0, &_usmUserEntry_obj, &_usmUserSpinLock_obj }, _usmStatsUnsupportedSecLevels_obj = { "usmStatsUnsupportedSecLevels", 1, 0, NULL, NULL }, _usmStatsNotInTimeWindows_obj = { "usmStatsNotInTimeWindows", 2, 0, NULL, &_usmStatsUnsupportedSecLevels_obj }, _usmStatsUnknownUserNames_obj = { "usmStatsUnknownUserNames", 3, 0, NULL, &_usmStatsNotInTimeWindows_obj }, _usmStatsUnknownEngineIDs_obj = { "usmStatsUnknownEngineIDs", 4, 0, NULL, &_usmStatsUnknownUserNames_obj }, _usmStatsWrongDigests_obj = { "usmStatsWrongDigests", 5, 0, NULL, &_usmStatsUnknownEngineIDs_obj }, _usmStatsDecryptionErrors_obj = { "usmStatsDecryptionErrors", 6, 0, NULL, &_usmStatsWrongDigests_obj }, _usmStats_obj = { "usmStats", 1, 0, &_usmStatsDecryptionErrors_obj, NULL }, _usmUser_obj = { "usmUser", 2, 0, &_usmUserTable_obj, &_usmStats_obj }, _usmMIBObjects_obj = { "usmMIBObjects", 1, 0, &_usmUser_obj, NULL }, _usmMIBConformance_obj = { "usmMIBConformance", 2, 0, &_usmMIBGroups_obj, &_usmMIBObjects_obj }, _snmpMPDMIBCompliances_obj = { "snmpMPDMIBCompliances", 1, 0, NULL, NULL }, _snmpMPDMIBGroups_obj = { "snmpMPDMIBGroups", 2, 0, NULL, &_snmpMPDMIBCompliances_obj }, _snmpUnknownSecurityModels_obj = { "snmpUnknownSecurityModels", 1, 0, NULL, NULL }, _snmpInvalidMsgs_obj = { "snmpInvalidMsgs", 2, 0, NULL, &_snmpUnknownSecurityModels_obj }, _snmpUnknownPDUHandlers_obj = { "snmpUnknownPDUHandlers", 3, 0, NULL, &_snmpInvalidMsgs_obj }, _snmpMPDStats_obj = { "snmpMPDStats", 1, 0, &_snmpUnknownPDUHandlers_obj, NULL }, _snmpMPDAdmin_obj = { "snmpMPDAdmin", 1, 0, NULL, NULL }, _snmpMPDMIBObjects_obj = { "snmpMPDMIBObjects", 2, 0, &_snmpMPDStats_obj, &_snmpMPDAdmin_obj }, _snmpMPDMIBConformance_obj = { "snmpMPDMIBConformance", 3, 0, &_snmpMPDMIBGroups_obj, &_snmpMPDMIBObjects_obj }, _snmpEngineID_obj = { "snmpEngineID", 1, 0, NULL, NULL }, _snmpEngineBoots_obj = { "snmpEngineBoots", 2, 0, NULL, &_snmpEngineID_obj }, _snmpEngineTime_obj = { "snmpEngineTime", 3, 0, NULL, &_snmpEngineBoots_obj }, _snmpEngineMaxMessageSize_obj = { "snmpEngineMaxMessageSize", 4, 0, NULL, &_snmpEngineTime_obj }, _snmpEngine_obj = { "snmpEngine", 1, 0, &_snmpEngineMaxMessageSize_obj, NULL }, _snmpFrameworkAdmin_obj = { "snmpFrameworkAdmin", 1, 0, NULL, NULL }, _snmpFrameworkMIBObjects_obj = { "snmpFrameworkMIBObjects", 2, 0, &_snmpEngine_obj, &_snmpFrameworkAdmin_obj }, _snmpFrameworkMIBConformance_obj = { "snmpFrameworkMIBConformance", 3, 0, NULL, &_snmpFrameworkMIBObjects_obj }, _snmpFrameworkMIB_obj = { "snmpFrameworkMIB", 10, 0, &_snmpFrameworkMIBConformance_obj, NULL }, _snmpMPDMIB_obj = { "snmpMPDMIB", 11, 0, &_snmpMPDMIBConformance_obj, &_snmpFrameworkMIB_obj }, _snmpUsmMIB_obj = { "snmpUsmMIB", 15, 0, &_usmMIBConformance_obj, &_snmpMPDMIB_obj }, _snmpModules_obj = { "snmpModules", 3, 0, &_snmpUsmMIB_obj, NULL }, _mib_obj = { "mib", 1, 0, &_snmp_obj, NULL }, _directory_obj = { "directory", 1, 0, NULL, NULL }, _mgmt_obj = { "mgmt", 2, 0, &_mib_obj, &_directory_obj }, _experimental_obj = { "experimental", 3, 0, NULL, &_mgmt_obj }, _private_obj = { "private", 4, 0, &_enterprises_obj, &_experimental_obj }, _security_obj = { "security", 5, 0, NULL, &_private_obj }, _snmpV2_obj = { "snmpV2", 6, 0, &_snmpModules_obj, &_security_obj }, _internet_obj = { "internet", 1, 0, &_snmpV2_obj, NULL }, _dod_obj = { "dod", 6, 0, &_internet_obj, NULL }, _org_obj = { "org", 3, 0, &_dod_obj, NULL }, _iso_obj = { "iso", 1, 0, &_org_obj, NULL }, *mibroot = &_iso_obj; tcpdump-4.99.1/print-802_11.c0000644000026300017510000030217214057477734013554 0ustar mcrmcr/* * Copyright (c) 2001 * Fortress Technologies, Inc. All rights reserved. * Charlie Lenahan (clenahan@fortresstech.com) * * 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. */ /* \summary: IEEE 802.11 printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include #include "netdissect.h" #include "addrtoname.h" #include "extract.h" #include "cpack.h" /* Lengths of 802.11 header components. */ #define IEEE802_11_FC_LEN 2 #define IEEE802_11_DUR_LEN 2 #define IEEE802_11_DA_LEN 6 #define IEEE802_11_SA_LEN 6 #define IEEE802_11_BSSID_LEN 6 #define IEEE802_11_RA_LEN 6 #define IEEE802_11_TA_LEN 6 #define IEEE802_11_ADDR1_LEN 6 #define IEEE802_11_SEQ_LEN 2 #define IEEE802_11_CTL_LEN 2 #define IEEE802_11_CARRIED_FC_LEN 2 #define IEEE802_11_HT_CONTROL_LEN 4 #define IEEE802_11_IV_LEN 3 #define IEEE802_11_KID_LEN 1 /* Frame check sequence length. */ #define IEEE802_11_FCS_LEN 4 /* Lengths of beacon components. */ #define IEEE802_11_TSTAMP_LEN 8 #define IEEE802_11_BCNINT_LEN 2 #define IEEE802_11_CAPINFO_LEN 2 #define IEEE802_11_LISTENINT_LEN 2 #define IEEE802_11_AID_LEN 2 #define IEEE802_11_STATUS_LEN 2 #define IEEE802_11_REASON_LEN 2 /* Length of previous AP in reassocation frame */ #define IEEE802_11_AP_LEN 6 #define T_MGMT 0x0 /* management */ #define T_CTRL 0x1 /* control */ #define T_DATA 0x2 /* data */ #define T_RESV 0x3 /* reserved */ #define ST_ASSOC_REQUEST 0x0 #define ST_ASSOC_RESPONSE 0x1 #define ST_REASSOC_REQUEST 0x2 #define ST_REASSOC_RESPONSE 0x3 #define ST_PROBE_REQUEST 0x4 #define ST_PROBE_RESPONSE 0x5 /* RESERVED 0x6 */ /* RESERVED 0x7 */ #define ST_BEACON 0x8 #define ST_ATIM 0x9 #define ST_DISASSOC 0xA #define ST_AUTH 0xB #define ST_DEAUTH 0xC #define ST_ACTION 0xD /* RESERVED 0xE */ /* RESERVED 0xF */ static const struct tok st_str[] = { { ST_ASSOC_REQUEST, "Assoc Request" }, { ST_ASSOC_RESPONSE, "Assoc Response" }, { ST_REASSOC_REQUEST, "ReAssoc Request" }, { ST_REASSOC_RESPONSE, "ReAssoc Response" }, { ST_PROBE_REQUEST, "Probe Request" }, { ST_PROBE_RESPONSE, "Probe Response" }, { ST_BEACON, "Beacon" }, { ST_ATIM, "ATIM" }, { ST_DISASSOC, "Disassociation" }, { ST_AUTH, "Authentication" }, { ST_DEAUTH, "DeAuthentication" }, { ST_ACTION, "Action" }, { 0, NULL } }; #define CTRL_CONTROL_WRAPPER 0x7 #define CTRL_BAR 0x8 #define CTRL_BA 0x9 #define CTRL_PS_POLL 0xA #define CTRL_RTS 0xB #define CTRL_CTS 0xC #define CTRL_ACK 0xD #define CTRL_CF_END 0xE #define CTRL_END_ACK 0xF static const struct tok ctrl_str[] = { { CTRL_CONTROL_WRAPPER, "Control Wrapper" }, { CTRL_BAR, "BAR" }, { CTRL_BA, "BA" }, { CTRL_PS_POLL, "Power Save-Poll" }, { CTRL_RTS, "Request-To-Send" }, { CTRL_CTS, "Clear-To-Send" }, { CTRL_ACK, "Acknowledgment" }, { CTRL_CF_END, "CF-End" }, { CTRL_END_ACK, "CF-End+CF-Ack" }, { 0, NULL } }; #define DATA_DATA 0x0 #define DATA_DATA_CF_ACK 0x1 #define DATA_DATA_CF_POLL 0x2 #define DATA_DATA_CF_ACK_POLL 0x3 #define DATA_NODATA 0x4 #define DATA_NODATA_CF_ACK 0x5 #define DATA_NODATA_CF_POLL 0x6 #define DATA_NODATA_CF_ACK_POLL 0x7 #define DATA_QOS_DATA 0x8 #define DATA_QOS_DATA_CF_ACK 0x9 #define DATA_QOS_DATA_CF_POLL 0xA #define DATA_QOS_DATA_CF_ACK_POLL 0xB #define DATA_QOS_NODATA 0xC #define DATA_QOS_CF_POLL_NODATA 0xE #define DATA_QOS_CF_ACK_POLL_NODATA 0xF /* * The subtype field of a data frame is, in effect, composed of 4 flag * bits - CF-Ack, CF-Poll, Null (means the frame doesn't actually have * any data), and QoS. */ #define DATA_FRAME_IS_CF_ACK(x) ((x) & 0x01) #define DATA_FRAME_IS_CF_POLL(x) ((x) & 0x02) #define DATA_FRAME_IS_NULL(x) ((x) & 0x04) #define DATA_FRAME_IS_QOS(x) ((x) & 0x08) /* * Bits in the frame control field. */ #define FC_VERSION(fc) ((fc) & 0x3) #define FC_TYPE(fc) (((fc) >> 2) & 0x3) #define FC_SUBTYPE(fc) (((fc) >> 4) & 0xF) #define FC_TO_DS(fc) ((fc) & 0x0100) #define FC_FROM_DS(fc) ((fc) & 0x0200) #define FC_MORE_FLAG(fc) ((fc) & 0x0400) #define FC_RETRY(fc) ((fc) & 0x0800) #define FC_POWER_MGMT(fc) ((fc) & 0x1000) #define FC_MORE_DATA(fc) ((fc) & 0x2000) #define FC_PROTECTED(fc) ((fc) & 0x4000) #define FC_ORDER(fc) ((fc) & 0x8000) struct mgmt_header_t { nd_uint16_t fc; nd_uint16_t duration; nd_mac_addr da; nd_mac_addr sa; nd_mac_addr bssid; nd_uint16_t seq_ctrl; }; #define MGMT_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ IEEE802_11_DA_LEN+IEEE802_11_SA_LEN+\ IEEE802_11_BSSID_LEN+IEEE802_11_SEQ_LEN) #define CAPABILITY_ESS(cap) ((cap) & 0x0001) #define CAPABILITY_IBSS(cap) ((cap) & 0x0002) #define CAPABILITY_CFP(cap) ((cap) & 0x0004) #define CAPABILITY_CFP_REQ(cap) ((cap) & 0x0008) #define CAPABILITY_PRIVACY(cap) ((cap) & 0x0010) struct ssid_t { uint8_t element_id; uint8_t length; u_char ssid[33]; /* 32 + 1 for null */ }; struct rates_t { uint8_t element_id; uint8_t length; uint8_t rate[16]; }; struct challenge_t { uint8_t element_id; uint8_t length; uint8_t text[254]; /* 1-253 + 1 for null */ }; struct fh_t { uint8_t element_id; uint8_t length; uint16_t dwell_time; uint8_t hop_set; uint8_t hop_pattern; uint8_t hop_index; }; struct ds_t { uint8_t element_id; uint8_t length; uint8_t channel; }; struct cf_t { uint8_t element_id; uint8_t length; uint8_t count; uint8_t period; uint16_t max_duration; uint16_t dur_remaining; }; struct tim_t { uint8_t element_id; uint8_t length; uint8_t count; uint8_t period; uint8_t bitmap_control; uint8_t bitmap[251]; }; #define E_SSID 0 #define E_RATES 1 #define E_FH 2 #define E_DS 3 #define E_CF 4 #define E_TIM 5 #define E_IBSS 6 /* reserved 7 */ /* reserved 8 */ /* reserved 9 */ /* reserved 10 */ /* reserved 11 */ /* reserved 12 */ /* reserved 13 */ /* reserved 14 */ /* reserved 15 */ /* reserved 16 */ #define E_CHALLENGE 16 /* reserved 17 */ /* reserved 18 */ /* reserved 19 */ /* reserved 16 */ /* reserved 16 */ struct mgmt_body_t { uint8_t timestamp[IEEE802_11_TSTAMP_LEN]; uint16_t beacon_interval; uint16_t listen_interval; uint16_t status_code; uint16_t aid; u_char ap[IEEE802_11_AP_LEN]; uint16_t reason_code; uint16_t auth_alg; uint16_t auth_trans_seq_num; int challenge_present; struct challenge_t challenge; uint16_t capability_info; int ssid_present; struct ssid_t ssid; int rates_present; struct rates_t rates; int ds_present; struct ds_t ds; int cf_present; struct cf_t cf; int fh_present; struct fh_t fh; int tim_present; struct tim_t tim; }; struct ctrl_control_wrapper_hdr_t { nd_uint16_t fc; nd_uint16_t duration; nd_mac_addr addr1; nd_uint16_t carried_fc[IEEE802_11_CARRIED_FC_LEN]; nd_uint16_t ht_control[IEEE802_11_HT_CONTROL_LEN]; }; #define CTRL_CONTROL_WRAPPER_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ IEEE802_11_ADDR1_LEN+\ IEEE802_11_CARRIED_FC_LEN+\ IEEE802_11_HT_CONTROL_LEN) struct ctrl_rts_hdr_t { nd_uint16_t fc; nd_uint16_t duration; nd_mac_addr ra; nd_mac_addr ta; }; #define CTRL_RTS_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ IEEE802_11_RA_LEN+IEEE802_11_TA_LEN) struct ctrl_cts_hdr_t { nd_uint16_t fc; nd_uint16_t duration; nd_mac_addr ra; }; #define CTRL_CTS_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN) struct ctrl_ack_hdr_t { nd_uint16_t fc; nd_uint16_t duration; nd_mac_addr ra; }; #define CTRL_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN) struct ctrl_ps_poll_hdr_t { nd_uint16_t fc; nd_uint16_t aid; nd_mac_addr bssid; nd_mac_addr ta; }; #define CTRL_PS_POLL_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_AID_LEN+\ IEEE802_11_BSSID_LEN+IEEE802_11_TA_LEN) struct ctrl_end_hdr_t { nd_uint16_t fc; nd_uint16_t duration; nd_mac_addr ra; nd_mac_addr bssid; }; #define CTRL_END_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN) struct ctrl_end_ack_hdr_t { nd_uint16_t fc; nd_uint16_t duration; nd_mac_addr ra; nd_mac_addr bssid; }; #define CTRL_END_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ IEEE802_11_RA_LEN+IEEE802_11_BSSID_LEN) struct ctrl_ba_hdr_t { nd_uint16_t fc; nd_uint16_t duration; nd_mac_addr ra; }; #define CTRL_BA_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN) struct ctrl_bar_hdr_t { nd_uint16_t fc; nd_uint16_t dur; nd_mac_addr ra; nd_mac_addr ta; nd_uint16_t ctl; nd_uint16_t seq; }; #define CTRL_BAR_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\ IEEE802_11_RA_LEN+IEEE802_11_TA_LEN+\ IEEE802_11_CTL_LEN+IEEE802_11_SEQ_LEN) struct meshcntl_t { nd_uint8_t flags; nd_uint8_t ttl; nd_uint32_t seq; nd_mac_addr addr4; nd_mac_addr addr5; nd_mac_addr addr6; }; #define IV_IV(iv) ((iv) & 0xFFFFFF) #define IV_PAD(iv) (((iv) >> 24) & 0x3F) #define IV_KEYID(iv) (((iv) >> 30) & 0x03) #define PRINT_SSID(p) \ if (p.ssid_present) { \ ND_PRINT(" ("); \ fn_print_str(ndo, p.ssid.ssid); \ ND_PRINT(")"); \ } #define PRINT_RATE(_sep, _r, _suf) \ ND_PRINT("%s%2.1f%s", _sep, (.5 * ((_r) & 0x7f)), _suf) #define PRINT_RATES(p) \ if (p.rates_present) { \ int z; \ const char *sep = " ["; \ for (z = 0; z < p.rates.length ; z++) { \ PRINT_RATE(sep, p.rates.rate[z], \ (p.rates.rate[z] & 0x80 ? "*" : "")); \ sep = " "; \ } \ if (p.rates.length != 0) \ ND_PRINT(" Mbit]"); \ } #define PRINT_DS_CHANNEL(p) \ if (p.ds_present) \ ND_PRINT(" CH: %u", p.ds.channel); \ ND_PRINT("%s", \ CAPABILITY_PRIVACY(p.capability_info) ? ", PRIVACY" : ""); #define MAX_MCS_INDEX 76 /* * Indices are: * * the MCS index (0-76); * * 0 for 20 MHz, 1 for 40 MHz; * * 0 for a long guard interval, 1 for a short guard interval. */ static const float ieee80211_float_htrates[MAX_MCS_INDEX+1][2][2] = { /* MCS 0 */ { /* 20 Mhz */ { 6.5f, /* SGI */ 7.2f, }, /* 40 Mhz */ { 13.5f, /* SGI */ 15.0f, }, }, /* MCS 1 */ { /* 20 Mhz */ { 13.0f, /* SGI */ 14.4f, }, /* 40 Mhz */ { 27.0f, /* SGI */ 30.0f, }, }, /* MCS 2 */ { /* 20 Mhz */ { 19.5f, /* SGI */ 21.7f, }, /* 40 Mhz */ { 40.5f, /* SGI */ 45.0f, }, }, /* MCS 3 */ { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, }, /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, }, }, /* MCS 4 */ { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, }, /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, }, }, /* MCS 5 */ { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, }, /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, }, }, /* MCS 6 */ { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, }, /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, }, }, /* MCS 7 */ { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, }, /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, }, }, /* MCS 8 */ { /* 20 Mhz */ { 13.0f, /* SGI */ 14.4f, }, /* 40 Mhz */ { 27.0f, /* SGI */ 30.0f, }, }, /* MCS 9 */ { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, }, /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, }, }, /* MCS 10 */ { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, }, /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, }, }, /* MCS 11 */ { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, }, /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, }, }, /* MCS 12 */ { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, }, /* MCS 13 */ { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, }, /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, }, }, /* MCS 14 */ { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, }, /* MCS 15 */ { /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, }, /* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, }, }, /* MCS 16 */ { /* 20 Mhz */ { 19.5f, /* SGI */ 21.7f, }, /* 40 Mhz */ { 40.5f, /* SGI */ 45.0f, }, }, /* MCS 17 */ { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, }, /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, }, }, /* MCS 18 */ { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, }, /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, }, }, /* MCS 19 */ { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, }, /* MCS 20 */ { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, }, /* MCS 21 */ { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, }, /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, }, }, /* MCS 22 */ { /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, }, /* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, }, }, /* MCS 23 */ { /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, }, /* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, }, }, /* MCS 24 */ { /* 20 Mhz */ { 26.0f, /* SGI */ 28.9f, }, /* 40 Mhz */ { 54.0f, /* SGI */ 60.0f, }, }, /* MCS 25 */ { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, }, /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, }, }, /* MCS 26 */ { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, }, /* MCS 27 */ { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, }, /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, }, }, /* MCS 28 */ { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, }, /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, }, }, /* MCS 29 */ { /* 20 Mhz */ { 208.0f, /* SGI */ 231.1f, }, /* 40 Mhz */ { 432.0f, /* SGI */ 480.0f, }, }, /* MCS 30 */ { /* 20 Mhz */ { 234.0f, /* SGI */ 260.0f, }, /* 40 Mhz */ { 486.0f, /* SGI */ 540.0f, }, }, /* MCS 31 */ { /* 20 Mhz */ { 260.0f, /* SGI */ 288.9f, }, /* 40 Mhz */ { 540.0f, /* SGI */ 600.0f, }, }, /* MCS 32 */ { /* 20 Mhz */ { 0.0f, /* SGI */ 0.0f, }, /* not valid */ /* 40 Mhz */ { 6.0f, /* SGI */ 6.7f, }, }, /* MCS 33 */ { /* 20 Mhz */ { 39.0f, /* SGI */ 43.3f, }, /* 40 Mhz */ { 81.0f, /* SGI */ 90.0f, }, }, /* MCS 34 */ { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, }, /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, }, }, /* MCS 35 */ { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, }, /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, }, }, /* MCS 36 */ { /* 20 Mhz */ { 58.5f, /* SGI */ 65.0f, }, /* 40 Mhz */ { 121.5f, /* SGI */ 135.0f, }, }, /* MCS 37 */ { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, }, /* MCS 38 */ { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, }, /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, }, }, /* MCS 39 */ { /* 20 Mhz */ { 52.0f, /* SGI */ 57.8f, }, /* 40 Mhz */ { 108.0f, /* SGI */ 120.0f, }, }, /* MCS 40 */ { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, }, /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, }, }, /* MCS 41 */ { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, }, /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, }, }, /* MCS 42 */ { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, }, /* MCS 43 */ { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, }, /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, }, }, /* MCS 44 */ { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, }, /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, }, }, /* MCS 45 */ { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, }, /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, }, }, /* MCS 46 */ { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, }, /* MCS 47 */ { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, }, /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, }, }, /* MCS 48 */ { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, }, /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, }, }, /* MCS 49 */ { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, }, /* MCS 50 */ { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, }, /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, }, }, /* MCS 51 */ { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, }, /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, }, }, /* MCS 52 */ { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, }, /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, }, }, /* MCS 53 */ { /* 20 Mhz */ { 65.0f, /* SGI */ 72.2f, }, /* 40 Mhz */ { 135.0f, /* SGI */ 150.0f, }, }, /* MCS 54 */ { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, }, /* MCS 55 */ { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, }, /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, }, }, /* MCS 56 */ { /* 20 Mhz */ { 78.0f, /* SGI */ 86.7f, }, /* 40 Mhz */ { 162.0f, /* SGI */ 180.0f, }, }, /* MCS 57 */ { /* 20 Mhz */ { 91.0f, /* SGI */ 101.1f, }, /* 40 Mhz */ { 189.0f, /* SGI */ 210.0f, }, }, /* MCS 58 */ { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, }, /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, }, }, /* MCS 59 */ { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, }, /* MCS 60 */ { /* 20 Mhz */ { 104.0f, /* SGI */ 115.6f, }, /* 40 Mhz */ { 216.0f, /* SGI */ 240.0f, }, }, /* MCS 61 */ { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, }, /* MCS 62 */ { /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, }, /* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, }, }, /* MCS 63 */ { /* 20 Mhz */ { 130.0f, /* SGI */ 144.4f, }, /* 40 Mhz */ { 270.0f, /* SGI */ 300.0f, }, }, /* MCS 64 */ { /* 20 Mhz */ { 143.0f, /* SGI */ 158.9f, }, /* 40 Mhz */ { 297.0f, /* SGI */ 330.0f, }, }, /* MCS 65 */ { /* 20 Mhz */ { 97.5f, /* SGI */ 108.3f, }, /* 40 Mhz */ { 202.5f, /* SGI */ 225.0f, }, }, /* MCS 66 */ { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, }, /* MCS 67 */ { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, }, /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, }, }, /* MCS 68 */ { /* 20 Mhz */ { 117.0f, /* SGI */ 130.0f, }, /* 40 Mhz */ { 243.0f, /* SGI */ 270.0f, }, }, /* MCS 69 */ { /* 20 Mhz */ { 136.5f, /* SGI */ 151.7f, }, /* 40 Mhz */ { 283.5f, /* SGI */ 315.0f, }, }, /* MCS 70 */ { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, }, /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, }, }, /* MCS 71 */ { /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, }, /* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, }, }, /* MCS 72 */ { /* 20 Mhz */ { 156.0f, /* SGI */ 173.3f, }, /* 40 Mhz */ { 324.0f, /* SGI */ 360.0f, }, }, /* MCS 73 */ { /* 20 Mhz */ { 175.5f, /* SGI */ 195.0f, }, /* 40 Mhz */ { 364.5f, /* SGI */ 405.0f, }, }, /* MCS 74 */ { /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, }, /* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, }, }, /* MCS 75 */ { /* 20 Mhz */ { 195.0f, /* SGI */ 216.7f, }, /* 40 Mhz */ { 405.0f, /* SGI */ 450.0f, }, }, /* MCS 76 */ { /* 20 Mhz */ { 214.5f, /* SGI */ 238.3f, }, /* 40 Mhz */ { 445.5f, /* SGI */ 495.0f, }, }, }; static const char *auth_alg_text[]={"Open System","Shared Key","EAP"}; #define NUM_AUTH_ALGS (sizeof(auth_alg_text) / sizeof(auth_alg_text[0])) static const char *status_text[] = { "Successful", /* 0 */ "Unspecified failure", /* 1 */ "TDLS wakeup schedule rejected but alternative schedule " "provided", /* 2 */ "TDLS wakeup schedule rejected",/* 3 */ "Reserved", /* 4 */ "Security disabled", /* 5 */ "Unacceptable lifetime", /* 6 */ "Not in same BSS", /* 7 */ "Reserved", /* 8 */ "Reserved", /* 9 */ "Cannot Support all requested capabilities in the Capability " "Information field", /* 10 */ "Reassociation denied due to inability to confirm that association " "exists", /* 11 */ "Association denied due to reason outside the scope of this " "standard", /* 12 */ "Responding STA does not support the specified authentication " "algorithm", /* 13 */ "Received an Authentication frame with authentication transaction " "sequence number out of expected sequence", /* 14 */ "Authentication rejected because of challenge failure", /* 15 */ "Authentication rejected due to timeout waiting for next frame in " "sequence", /* 16 */ "Association denied because AP is unable to handle " "additional associated STAs", /* 17 */ "Association denied due to requesting STA not supporting " "all of the data rates in the BSSBasicRateSet parameter, " "the Basic HT-MCS Set field of the HT Operation " "parameter, or the Basic VHT-MCS and NSS Set field in " "the VHT Operation parameter", /* 18 */ "Association denied due to requesting STA not supporting " "the short preamble option", /* 19 */ "Reserved", /* 20 */ "Reserved", /* 21 */ "Association request rejected because Spectrum Management " "capability is required", /* 22 */ "Association request rejected because the information in the " "Power Capability element is unacceptable", /* 23 */ "Association request rejected because the information in the " "Supported Channels element is unacceptable", /* 24 */ "Association denied due to requesting STA not supporting " "the Short Slot Time option", /* 25 */ "Reserved", /* 26 */ "Association denied because the requested STA does not support HT " "features", /* 27 */ "R0KH unreachable", /* 28 */ "Association denied because the requesting STA does not " "support the phased coexistence operation (PCO) " "transition time required by the AP", /* 29 */ "Association request rejected temporarily; try again " "later", /* 30 */ "Robust management frame policy violation", /* 31 */ "Unspecified, QoS-related failure", /* 32 */ "Association denied because QoS AP or PCP has " "insufficient bandwidth to handle another QoS " "STA", /* 33 */ "Association denied due to excessive frame loss rates and/or " "poor conditions on current operating channel", /* 34 */ "Association (with QoS BSS) denied because the requesting STA " "does not support the QoS facility", /* 35 */ "Reserved", /* 36 */ "The request has been declined", /* 37 */ "The request has not been successful as one or more parameters " "have invalid values", /* 38 */ "The allocation or TS has not been created because the request " "cannot be honored; however, a suggested TSPEC/DMG TSPEC is " "provided so that the initiating STA can attempt to set " "another allocation or TS with the suggested changes to the " "TSPEC/DMG TSPEC", /* 39 */ "Invalid element, i.e., an element defined in this standard " "for which the content does not meet the specifications in " "Clause 9", /* 40 */ "Invalid group cipher", /* 41 */ "Invalid pairwise cipher", /* 42 */ "Invalid AKMP", /* 43 */ "Unsupported RSNE version", /* 44 */ "Invalid RSNE capabilities", /* 45 */ "Cipher suite rejected because of security policy", /* 46 */ "The TS or allocation has not been created; however, the " "HC or PCP might be capable of creating a TS or " "allocation, in response to a request, after the time " "indicated in the TS Delay element", /* 47 */ "Direct Link is not allowed in the BSS by policy", /* 48 */ "The Destination STA is not present within this BSS", /* 49 */ "The Destination STA is not a QoS STA", /* 50 */ "Association denied because the listen interval is " "too large", /* 51 */ "Invalid FT Action frame count", /* 52 */ "Invalid pairwise master key identifier (PMKID)", /* 53 */ "Invalid MDE", /* 54 */ "Invalid FTE", /* 55 */ "Requested TCLAS processing is not supported by the AP " "or PCP", /* 56 */ "The AP or PCP has insufficient TCLAS processing " "resources to satisfy the request", /* 57 */ "The TS has not been created because the request " "cannot be honored; however, the HC or PCP suggests " "that the STA transition to a different BSS to set up " "the TS", /* 58 */ "GAS Advertisement Protocol not supported", /* 59 */ "No outstanding GAS request", /* 60 */ "GAS Response not received from the Advertisement " "Server", /* 61 */ "STA timed out waiting for GAS Query Response", /* 62 */ "LARGE GAS Response is larger than query response " "length limit", /* 63 */ "Request refused because home network does not support " "request", /* 64 */ "Advertisement Server in the network is not currently " "reachable", /* 65 */ "Reserved", /* 66 */ "Request refused due to permissions received via SSPN " "interface", /* 67 */ "Request refused because the AP or PCP does not " "support unauthenticated access", /* 68 */ "Reserved", /* 69 */ "Reserved", /* 70 */ "Reserved", /* 71 */ "Invalid contents of RSNE", /* 72 */ "U-APSD coexistence is not supported", /* 73 */ "Requested U-APSD coexistence mode is not supported", /* 74 */ "Requested Interval/Duration value cannot be " "supported with U-APSD coexistence", /* 75 */ "Authentication is rejected because an Anti-Clogging " "Token is required", /* 76 */ "Authentication is rejected because the offered " "finite cyclic group is not supported", /* 77 */ "The TBTT adjustment request has not been successful " "because the STA could not find an alternative TBTT", /* 78 */ "Transmission failure", /* 79 */ "Requested TCLAS Not Supported", /* 80 */ "TCLAS Resources Exhausted", /* 81 */ "Rejected with Suggested BSS transition", /* 82 */ "Reject with recommended schedule", /* 83 */ "Reject because no wakeup schedule specified", /* 84 */ "Success, the destination STA is in power save mode", /* 85 */ "FST pending, in process of admitting FST session", /* 86 */ "Performing FST now", /* 87 */ "FST pending, gap(s) in block ack window", /* 88 */ "Reject because of U-PID setting", /* 89 */ "Reserved", /* 90 */ "Reserved", /* 91 */ "(Re)Association refused for some external reason", /* 92 */ "(Re)Association refused because of memory limits " "at the AP", /* 93 */ "(Re)Association refused because emergency services " "are not supported at the AP", /* 94 */ "GAS query response not yet received", /* 95 */ "Reject since the request is for transition to a " "frequency band subject to DSE procedures and " "FST Initiator is a dependent STA", /* 96 */ "Requested TCLAS processing has been terminated by " "the AP", /* 97 */ "The TS schedule conflicts with an existing " "schedule; an alternative schedule is provided", /* 98 */ "The association has been denied; however, one or " "more Multi-band elements are included that can " "be used by the receiving STA to join the BSS", /* 99 */ "The request failed due to a reservation conflict", /* 100 */ "The request failed due to exceeded MAF limit", /* 101 */ "The request failed due to exceeded MCCA track " "limit", /* 102 */ "Association denied because the information in the" "Spectrum Management field is unacceptable", /* 103 */ "Association denied because the requesting STA " "does not support VHT features", /* 104 */ "Enablement denied", /* 105 */ "Enablement denied due to restriction from an " "authorized GDB", /* 106 */ "Authorization deenabled", /* 107 */ }; #define NUM_STATUSES (sizeof(status_text) / sizeof(status_text[0])) static const char *reason_text[] = { "Reserved", /* 0 */ "Unspecified reason", /* 1 */ "Previous authentication no longer valid", /* 2 */ "Deauthenticated because sending STA is leaving (or has left) " "IBSS or ESS", /* 3 */ "Disassociated due to inactivity", /* 4 */ "Disassociated because AP is unable to handle all currently " " associated STAs", /* 5 */ "Class 2 frame received from nonauthenticated STA", /* 6 */ "Class 3 frame received from nonassociated STA", /* 7 */ "Disassociated because sending STA is leaving " "(or has left) BSS", /* 8 */ "STA requesting (re)association is not authenticated with " "responding STA", /* 9 */ "Disassociated because the information in the Power Capability " "element is unacceptable", /* 10 */ "Disassociated because the information in the Supported Channels " "element is unacceptable", /* 11 */ "Disassociated due to BSS transition management", /* 12 */ "Invalid element, i.e., an element defined in this standard for " "which the content does not meet the specifications " "in Clause 9", /* 13 */ "Message integrity code (MIC) failure", /* 14 */ "4-Way Handshake timeout", /* 15 */ "Group key handshake timeout", /* 16 */ "Information element in 4-Way Handshake different from (Re)Association" "Request/Probe Response/Beacon frame", /* 17 */ "Invalid group cipher", /* 18 */ "Invalid pairwise cipher", /* 19 */ "Invalid AKMP", /* 20 */ "Unsupported RSNE version", /* 21 */ "Invalid RSNE capabilities", /* 22 */ "IEEE 802.1X authentication failed", /* 23 */ "Cipher suite rejected because of the security policy", /* 24 */ "TDLS direct-link teardown due to TDLS peer STA " "unreachable via the TDLS direct link", /* 25 */ "TDLS direct-link teardown for unspecified reason", /* 26 */ "Disassociated because session terminated by SSP request",/* 27 */ "Disassociated because of lack of SSP roaming agreement",/* 28 */ "Requested service rejected because of SSP cipher suite or " "AKM requirement", /* 29 */ "Requested service not authorized in this location", /* 30 */ "TS deleted because QoS AP lacks sufficient bandwidth for this " "QoS STA due to a change in BSS service characteristics or " "operational mode (e.g. an HT BSS change from 40 MHz channel " "to 20 MHz channel)", /* 31 */ "Disassociated for unspecified, QoS-related reason", /* 32 */ "Disassociated because QoS AP lacks sufficient bandwidth for this " "QoS STA", /* 33 */ "Disassociated because of excessive number of frames that need to be " "acknowledged, but are not acknowledged due to AP transmissions " "and/or poor channel conditions", /* 34 */ "Disassociated because STA is transmitting outside the limits " "of its TXOPs", /* 35 */ "Requested from peer STA as the STA is leaving the BSS " "(or resetting)", /* 36 */ "Requested from peer STA as it does not want to use the " "mechanism", /* 37 */ "Requested from peer STA as the STA received frames using the " "mechanism for which a set up is required", /* 38 */ "Requested from peer STA due to time out", /* 39 */ "Reserved", /* 40 */ "Reserved", /* 41 */ "Reserved", /* 42 */ "Reserved", /* 43 */ "Reserved", /* 44 */ "Peer STA does not support the requested cipher suite", /* 45 */ "In a DLS Teardown frame: The teardown was initiated by the " "DLS peer. In a Disassociation frame: Disassociated because " "authorized access limit reached", /* 46 */ "In a DLS Teardown frame: The teardown was initiated by the " "AP. In a Disassociation frame: Disassociated due to external " "service requirements", /* 47 */ "Invalid FT Action frame count", /* 48 */ "Invalid pairwise master key identifier (PMKID)", /* 49 */ "Invalid MDE", /* 50 */ "Invalid FTE", /* 51 */ "Mesh peering canceled for unknown reasons", /* 52 */ "The mesh STA has reached the supported maximum number of " "peer mesh STAs", /* 53 */ "The received information violates the Mesh Configuration " "policy configured in the mesh STA profile", /* 54 */ "The mesh STA has received a Mesh Peering Close frame " "requesting to close the mesh peering", /* 55 */ "The mesh STA has resent dot11MeshMaxRetries Mesh " "Peering Open frames, without receiving a Mesh Peering " "Confirm frame", /* 56 */ "The confirmTimer for the mesh peering instance times out", /* 57 */ "The mesh STA fails to unwrap the GTK or the values in the " "wrapped contents do not match", /* 58 */ "The mesh STA receives inconsistent information about the " "mesh parameters between mesh peering Management frames", /* 59 */ "The mesh STA fails the authenticated mesh peering exchange " "because due to failure in selecting either the pairwise " "ciphersuite or group ciphersuite", /* 60 */ "The mesh STA does not have proxy information for this " "external destination", /* 61 */ "The mesh STA does not have forwarding information for this " "destination", /* 62 */ "The mesh STA determines that the link to the next hop of an " "active path in its forwarding information is no longer " "usable", /* 63 */ "The Deauthentication frame was sent because the MAC " "address of the STA already exists in the mesh BSS", /* 64 */ "The mesh STA performs channel switch to meet regulatory " "requirements", /* 65 */ "The mesh STA performs channel switching with unspecified " "reason", /* 66 */ }; #define NUM_REASONS (sizeof(reason_text) / sizeof(reason_text[0])) static int wep_print(netdissect_options *ndo, const u_char *p) { uint32_t iv; ND_TCHECK_LEN(p, IEEE802_11_IV_LEN + IEEE802_11_KID_LEN); iv = GET_LE_U_4(p); ND_PRINT(" IV:%3x Pad %x KeyID %x", IV_IV(iv), IV_PAD(iv), IV_KEYID(iv)); return 1; trunc: return 0; } static int parse_elements(netdissect_options *ndo, struct mgmt_body_t *pbody, const u_char *p, int offset, u_int length) { u_int elementlen; struct ssid_t ssid; struct challenge_t challenge; struct rates_t rates; struct ds_t ds; struct cf_t cf; struct tim_t tim; /* * We haven't seen any elements yet. */ pbody->challenge_present = 0; pbody->ssid_present = 0; pbody->rates_present = 0; pbody->ds_present = 0; pbody->cf_present = 0; pbody->tim_present = 0; while (length != 0) { /* Make sure we at least have the element ID and length. */ ND_TCHECK_2(p + offset); if (length < 2) goto trunc; elementlen = GET_U_1(p + offset + 1); /* Make sure we have the entire element. */ ND_TCHECK_LEN(p + offset + 2, elementlen); if (length < elementlen + 2) goto trunc; switch (GET_U_1(p + offset)) { case E_SSID: memcpy(&ssid, p + offset, 2); offset += 2; length -= 2; if (ssid.length != 0) { if (ssid.length > sizeof(ssid.ssid) - 1) return 0; memcpy(&ssid.ssid, p + offset, ssid.length); offset += ssid.length; length -= ssid.length; } ssid.ssid[ssid.length] = '\0'; /* * Present and not truncated. * * If we haven't already seen an SSID IE, * copy this one, otherwise ignore this one, * so we later report the first one we saw. */ if (!pbody->ssid_present) { pbody->ssid = ssid; pbody->ssid_present = 1; } break; case E_CHALLENGE: memcpy(&challenge, p + offset, 2); offset += 2; length -= 2; if (challenge.length != 0) { if (challenge.length > sizeof(challenge.text) - 1) return 0; memcpy(&challenge.text, p + offset, challenge.length); offset += challenge.length; length -= challenge.length; } challenge.text[challenge.length] = '\0'; /* * Present and not truncated. * * If we haven't already seen a challenge IE, * copy this one, otherwise ignore this one, * so we later report the first one we saw. */ if (!pbody->challenge_present) { pbody->challenge = challenge; pbody->challenge_present = 1; } break; case E_RATES: memcpy(&rates, p + offset, 2); offset += 2; length -= 2; if (rates.length != 0) { if (rates.length > sizeof(rates.rate)) return 0; memcpy(&rates.rate, p + offset, rates.length); offset += rates.length; length -= rates.length; } /* * Present and not truncated. * * If we haven't already seen a rates IE, * copy this one if it's not zero-length, * otherwise ignore this one, so we later * report the first one we saw. * * We ignore zero-length rates IEs as some * devices seem to put a zero-length rates * IE, followed by an SSID IE, followed by * a non-zero-length rates IE into frames, * even though IEEE Std 802.11-2007 doesn't * seem to indicate that a zero-length rates * IE is valid. */ if (!pbody->rates_present && rates.length != 0) { pbody->rates = rates; pbody->rates_present = 1; } break; case E_DS: memcpy(&ds, p + offset, 2); offset += 2; length -= 2; if (ds.length != 1) { offset += ds.length; length -= ds.length; break; } ds.channel = GET_U_1(p + offset); offset += 1; length -= 1; /* * Present and not truncated. * * If we haven't already seen a DS IE, * copy this one, otherwise ignore this one, * so we later report the first one we saw. */ if (!pbody->ds_present) { pbody->ds = ds; pbody->ds_present = 1; } break; case E_CF: memcpy(&cf, p + offset, 2); offset += 2; length -= 2; if (cf.length != 6) { offset += cf.length; length -= cf.length; break; } memcpy(&cf.count, p + offset, 6); offset += 6; length -= 6; /* * Present and not truncated. * * If we haven't already seen a CF IE, * copy this one, otherwise ignore this one, * so we later report the first one we saw. */ if (!pbody->cf_present) { pbody->cf = cf; pbody->cf_present = 1; } break; case E_TIM: memcpy(&tim, p + offset, 2); offset += 2; length -= 2; if (tim.length <= 3U) { offset += tim.length; length -= tim.length; break; } if (tim.length - 3U > sizeof(tim.bitmap)) return 0; memcpy(&tim.count, p + offset, 3); offset += 3; length -= 3; memcpy(tim.bitmap, p + offset, tim.length - 3); offset += tim.length - 3; length -= tim.length - 3; /* * Present and not truncated. * * If we haven't already seen a TIM IE, * copy this one, otherwise ignore this one, * so we later report the first one we saw. */ if (!pbody->tim_present) { pbody->tim = tim; pbody->tim_present = 1; } break; default: #if 0 ND_PRINT("(1) unhandled element_id (%u) ", GET_U_1(p + offset)); #endif offset += 2 + elementlen; length -= 2 + elementlen; break; } } /* No problems found. */ return 1; trunc: return 0; } /********************************************************************************* * Print Handle functions for the management frame types *********************************************************************************/ static int handle_beacon(netdissect_options *ndo, const u_char *p, u_int length) { struct mgmt_body_t pbody; int offset = 0; int ret; memset(&pbody, 0, sizeof(pbody)); ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + IEEE802_11_CAPINFO_LEN); if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + IEEE802_11_CAPINFO_LEN) goto trunc; memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN); offset += IEEE802_11_TSTAMP_LEN; length -= IEEE802_11_TSTAMP_LEN; pbody.beacon_interval = GET_LE_U_2(p + offset); offset += IEEE802_11_BCNINT_LEN; length -= IEEE802_11_BCNINT_LEN; pbody.capability_info = GET_LE_U_2(p + offset); offset += IEEE802_11_CAPINFO_LEN; length -= IEEE802_11_CAPINFO_LEN; ret = parse_elements(ndo, &pbody, p, offset, length); PRINT_SSID(pbody); PRINT_RATES(pbody); ND_PRINT(" %s", CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS"); PRINT_DS_CHANNEL(pbody); return ret; trunc: return 0; } static int handle_assoc_request(netdissect_options *ndo, const u_char *p, u_int length) { struct mgmt_body_t pbody; int offset = 0; int ret; memset(&pbody, 0, sizeof(pbody)); ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN); if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN) goto trunc; pbody.capability_info = GET_LE_U_2(p); offset += IEEE802_11_CAPINFO_LEN; length -= IEEE802_11_CAPINFO_LEN; pbody.listen_interval = GET_LE_U_2(p + offset); offset += IEEE802_11_LISTENINT_LEN; length -= IEEE802_11_LISTENINT_LEN; ret = parse_elements(ndo, &pbody, p, offset, length); PRINT_SSID(pbody); PRINT_RATES(pbody); return ret; trunc: return 0; } static int handle_assoc_response(netdissect_options *ndo, const u_char *p, u_int length) { struct mgmt_body_t pbody; int offset = 0; int ret; memset(&pbody, 0, sizeof(pbody)); ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN + IEEE802_11_AID_LEN); if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_STATUS_LEN + IEEE802_11_AID_LEN) goto trunc; pbody.capability_info = GET_LE_U_2(p); offset += IEEE802_11_CAPINFO_LEN; length -= IEEE802_11_CAPINFO_LEN; pbody.status_code = GET_LE_U_2(p + offset); offset += IEEE802_11_STATUS_LEN; length -= IEEE802_11_STATUS_LEN; pbody.aid = GET_LE_U_2(p + offset); offset += IEEE802_11_AID_LEN; length -= IEEE802_11_AID_LEN; ret = parse_elements(ndo, &pbody, p, offset, length); ND_PRINT(" AID(%x) :%s: %s", ((uint16_t)(pbody.aid << 2 )) >> 2 , CAPABILITY_PRIVACY(pbody.capability_info) ? " PRIVACY " : "", (pbody.status_code < NUM_STATUSES ? status_text[pbody.status_code] : "n/a")); return ret; trunc: return 0; } static int handle_reassoc_request(netdissect_options *ndo, const u_char *p, u_int length) { struct mgmt_body_t pbody; int offset = 0; int ret; memset(&pbody, 0, sizeof(pbody)); ND_TCHECK_LEN(p, IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN + IEEE802_11_AP_LEN); if (length < IEEE802_11_CAPINFO_LEN + IEEE802_11_LISTENINT_LEN + IEEE802_11_AP_LEN) goto trunc; pbody.capability_info = GET_LE_U_2(p); offset += IEEE802_11_CAPINFO_LEN; length -= IEEE802_11_CAPINFO_LEN; pbody.listen_interval = GET_LE_U_2(p + offset); offset += IEEE802_11_LISTENINT_LEN; length -= IEEE802_11_LISTENINT_LEN; memcpy(&pbody.ap, p+offset, IEEE802_11_AP_LEN); offset += IEEE802_11_AP_LEN; length -= IEEE802_11_AP_LEN; ret = parse_elements(ndo, &pbody, p, offset, length); PRINT_SSID(pbody); ND_PRINT(" AP : %s", etheraddr_string(ndo, pbody.ap )); return ret; trunc: return 0; } static int handle_reassoc_response(netdissect_options *ndo, const u_char *p, u_int length) { /* Same as a Association Response */ return handle_assoc_response(ndo, p, length); } static int handle_probe_request(netdissect_options *ndo, const u_char *p, u_int length) { struct mgmt_body_t pbody; int offset = 0; int ret; memset(&pbody, 0, sizeof(pbody)); ret = parse_elements(ndo, &pbody, p, offset, length); PRINT_SSID(pbody); PRINT_RATES(pbody); return ret; } static int handle_probe_response(netdissect_options *ndo, const u_char *p, u_int length) { struct mgmt_body_t pbody; int offset = 0; int ret; memset(&pbody, 0, sizeof(pbody)); ND_TCHECK_LEN(p, IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + IEEE802_11_CAPINFO_LEN); if (length < IEEE802_11_TSTAMP_LEN + IEEE802_11_BCNINT_LEN + IEEE802_11_CAPINFO_LEN) goto trunc; memcpy(&pbody.timestamp, p, IEEE802_11_TSTAMP_LEN); offset += IEEE802_11_TSTAMP_LEN; length -= IEEE802_11_TSTAMP_LEN; pbody.beacon_interval = GET_LE_U_2(p + offset); offset += IEEE802_11_BCNINT_LEN; length -= IEEE802_11_BCNINT_LEN; pbody.capability_info = GET_LE_U_2(p + offset); offset += IEEE802_11_CAPINFO_LEN; length -= IEEE802_11_CAPINFO_LEN; ret = parse_elements(ndo, &pbody, p, offset, length); PRINT_SSID(pbody); PRINT_RATES(pbody); PRINT_DS_CHANNEL(pbody); return ret; trunc: return 0; } static int handle_atim(void) { /* the frame body for ATIM is null. */ return 1; } static int handle_disassoc(netdissect_options *ndo, const u_char *p, u_int length) { struct mgmt_body_t pbody; memset(&pbody, 0, sizeof(pbody)); ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN); if (length < IEEE802_11_REASON_LEN) goto trunc; pbody.reason_code = GET_LE_U_2(p); ND_PRINT(": %s", (pbody.reason_code < NUM_REASONS) ? reason_text[pbody.reason_code] : "Reserved"); return 1; trunc: return 0; } static int handle_auth(netdissect_options *ndo, const u_char *p, u_int length) { struct mgmt_body_t pbody; int offset = 0; int ret; memset(&pbody, 0, sizeof(pbody)); ND_TCHECK_6(p); if (length < 6) goto trunc; pbody.auth_alg = GET_LE_U_2(p); offset += 2; length -= 2; pbody.auth_trans_seq_num = GET_LE_U_2(p + offset); offset += 2; length -= 2; pbody.status_code = GET_LE_U_2(p + offset); offset += 2; length -= 2; ret = parse_elements(ndo, &pbody, p, offset, length); if ((pbody.auth_alg == 1) && ((pbody.auth_trans_seq_num == 2) || (pbody.auth_trans_seq_num == 3))) { ND_PRINT(" (%s)-%x [Challenge Text] %s", (pbody.auth_alg < NUM_AUTH_ALGS) ? auth_alg_text[pbody.auth_alg] : "Reserved", pbody.auth_trans_seq_num, ((pbody.auth_trans_seq_num % 2) ? ((pbody.status_code < NUM_STATUSES) ? status_text[pbody.status_code] : "n/a") : "")); return ret; } ND_PRINT(" (%s)-%x: %s", (pbody.auth_alg < NUM_AUTH_ALGS) ? auth_alg_text[pbody.auth_alg] : "Reserved", pbody.auth_trans_seq_num, (pbody.auth_trans_seq_num % 2) ? ((pbody.status_code < NUM_STATUSES) ? status_text[pbody.status_code] : "n/a") : ""); return ret; trunc: return 0; } static int handle_deauth(netdissect_options *ndo, const uint8_t *src, const u_char *p, u_int length) { struct mgmt_body_t pbody; const char *reason = NULL; memset(&pbody, 0, sizeof(pbody)); ND_TCHECK_LEN(p, IEEE802_11_REASON_LEN); if (length < IEEE802_11_REASON_LEN) goto trunc; pbody.reason_code = GET_LE_U_2(p); reason = (pbody.reason_code < NUM_REASONS) ? reason_text[pbody.reason_code] : "Reserved"; if (ndo->ndo_eflag) { ND_PRINT(": %s", reason); } else { ND_PRINT(" (%s): %s", GET_ETHERADDR_STRING(src), reason); } return 1; trunc: return 0; } #define PRINT_HT_ACTION(v) (\ (v) == 0 ? ND_PRINT("TxChWidth"): \ (v) == 1 ? ND_PRINT("MIMOPwrSave"): \ ND_PRINT("Act#%u", (v))) #define PRINT_BA_ACTION(v) (\ (v) == 0 ? ND_PRINT("ADDBA Request"): \ (v) == 1 ? ND_PRINT("ADDBA Response"): \ (v) == 2 ? ND_PRINT("DELBA"): \ ND_PRINT("Act#%u", (v))) #define PRINT_MESHLINK_ACTION(v) (\ (v) == 0 ? ND_PRINT("Request"): \ (v) == 1 ? ND_PRINT("Report"): \ ND_PRINT("Act#%u", (v))) #define PRINT_MESHPEERING_ACTION(v) (\ (v) == 0 ? ND_PRINT("Open"): \ (v) == 1 ? ND_PRINT("Confirm"): \ (v) == 2 ? ND_PRINT("Close"): \ ND_PRINT("Act#%u", (v))) #define PRINT_MESHPATH_ACTION(v) (\ (v) == 0 ? ND_PRINT("Request"): \ (v) == 1 ? ND_PRINT("Report"): \ (v) == 2 ? ND_PRINT("Error"): \ (v) == 3 ? ND_PRINT("RootAnnouncement"): \ ND_PRINT("Act#%u", (v))) #define PRINT_MESH_ACTION(v) (\ (v) == 0 ? ND_PRINT("MeshLink"): \ (v) == 1 ? ND_PRINT("HWMP"): \ (v) == 2 ? ND_PRINT("Gate Announcement"): \ (v) == 3 ? ND_PRINT("Congestion Control"): \ (v) == 4 ? ND_PRINT("MCCA Setup Request"): \ (v) == 5 ? ND_PRINT("MCCA Setup Reply"): \ (v) == 6 ? ND_PRINT("MCCA Advertisement Request"): \ (v) == 7 ? ND_PRINT("MCCA Advertisement"): \ (v) == 8 ? ND_PRINT("MCCA Teardown"): \ (v) == 9 ? ND_PRINT("TBTT Adjustment Request"): \ (v) == 10 ? ND_PRINT("TBTT Adjustment Response"): \ ND_PRINT("Act#%u", (v))) #define PRINT_MULTIHOP_ACTION(v) (\ (v) == 0 ? ND_PRINT("Proxy Update"): \ (v) == 1 ? ND_PRINT("Proxy Update Confirmation"): \ ND_PRINT("Act#%u", (v))) #define PRINT_SELFPROT_ACTION(v) (\ (v) == 1 ? ND_PRINT("Peering Open"): \ (v) == 2 ? ND_PRINT("Peering Confirm"): \ (v) == 3 ? ND_PRINT("Peering Close"): \ (v) == 4 ? ND_PRINT("Group Key Inform"): \ (v) == 5 ? ND_PRINT("Group Key Acknowledge"): \ ND_PRINT("Act#%u", (v))) static int handle_action(netdissect_options *ndo, const uint8_t *src, const u_char *p, u_int length) { ND_TCHECK_2(p); if (length < 2) goto trunc; if (ndo->ndo_eflag) { ND_PRINT(": "); } else { ND_PRINT(" (%s): ", GET_ETHERADDR_STRING(src)); } switch (GET_U_1(p)) { case 0: ND_PRINT("Spectrum Management Act#%u", GET_U_1(p + 1)); break; case 1: ND_PRINT("QoS Act#%u", GET_U_1(p + 1)); break; case 2: ND_PRINT("DLS Act#%u", GET_U_1(p + 1)); break; case 3: ND_PRINT("BA "); PRINT_BA_ACTION(GET_U_1(p + 1)); break; case 7: ND_PRINT("HT "); PRINT_HT_ACTION(GET_U_1(p + 1)); break; case 13: ND_PRINT("MeshAction "); PRINT_MESH_ACTION(GET_U_1(p + 1)); break; case 14: ND_PRINT("MultiohopAction "); PRINT_MULTIHOP_ACTION(GET_U_1(p + 1)); break; case 15: ND_PRINT("SelfprotectAction "); PRINT_SELFPROT_ACTION(GET_U_1(p + 1)); break; case 127: ND_PRINT("Vendor Act#%u", GET_U_1(p + 1)); break; default: ND_PRINT("Reserved(%u) Act#%u", GET_U_1(p), GET_U_1(p + 1)); break; } return 1; trunc: return 0; } /********************************************************************************* * Print Body funcs *********************************************************************************/ static int mgmt_body_print(netdissect_options *ndo, uint16_t fc, const uint8_t *src, const u_char *p, u_int length) { ND_PRINT("%s", tok2str(st_str, "Unhandled Management subtype(%x)", FC_SUBTYPE(fc))); /* There may be a problem w/ AP not having this bit set */ if (FC_PROTECTED(fc)) return wep_print(ndo, p); switch (FC_SUBTYPE(fc)) { case ST_ASSOC_REQUEST: return handle_assoc_request(ndo, p, length); case ST_ASSOC_RESPONSE: return handle_assoc_response(ndo, p, length); case ST_REASSOC_REQUEST: return handle_reassoc_request(ndo, p, length); case ST_REASSOC_RESPONSE: return handle_reassoc_response(ndo, p, length); case ST_PROBE_REQUEST: return handle_probe_request(ndo, p, length); case ST_PROBE_RESPONSE: return handle_probe_response(ndo, p, length); case ST_BEACON: return handle_beacon(ndo, p, length); case ST_ATIM: return handle_atim(); case ST_DISASSOC: return handle_disassoc(ndo, p, length); case ST_AUTH: return handle_auth(ndo, p, length); case ST_DEAUTH: return handle_deauth(ndo, src, p, length); case ST_ACTION: return handle_action(ndo, src, p, length); default: return 1; } } /********************************************************************************* * Handles printing all the control frame types *********************************************************************************/ static int ctrl_body_print(netdissect_options *ndo, uint16_t fc, const u_char *p) { ND_PRINT("%s", tok2str(ctrl_str, "Unknown Ctrl Subtype", FC_SUBTYPE(fc))); switch (FC_SUBTYPE(fc)) { case CTRL_CONTROL_WRAPPER: /* XXX - requires special handling */ break; case CTRL_BAR: ND_TCHECK_LEN(p, CTRL_BAR_HDRLEN); if (!ndo->ndo_eflag) ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ", GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra), GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta), GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl), GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq)); break; case CTRL_BA: ND_TCHECK_LEN(p, CTRL_BA_HDRLEN); if (!ndo->ndo_eflag) ND_PRINT(" RA:%s ", GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra)); break; case CTRL_PS_POLL: ND_TCHECK_LEN(p, CTRL_PS_POLL_HDRLEN); ND_PRINT(" AID(%x)", GET_LE_U_2(((const struct ctrl_ps_poll_hdr_t *)p)->aid)); break; case CTRL_RTS: ND_TCHECK_LEN(p, CTRL_RTS_HDRLEN); if (!ndo->ndo_eflag) ND_PRINT(" TA:%s ", GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta)); break; case CTRL_CTS: ND_TCHECK_LEN(p, CTRL_CTS_HDRLEN); if (!ndo->ndo_eflag) ND_PRINT(" RA:%s ", GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra)); break; case CTRL_ACK: ND_TCHECK_LEN(p, CTRL_ACK_HDRLEN); if (!ndo->ndo_eflag) ND_PRINT(" RA:%s ", GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra)); break; case CTRL_CF_END: ND_TCHECK_LEN(p, CTRL_END_HDRLEN); if (!ndo->ndo_eflag) ND_PRINT(" RA:%s ", GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra)); break; case CTRL_END_ACK: ND_TCHECK_LEN(p, CTRL_END_ACK_HDRLEN); if (!ndo->ndo_eflag) ND_PRINT(" RA:%s ", GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra)); break; } return 1; trunc: return 0; } /* * Data Frame - Address field contents * * To Ds | From DS | Addr 1 | Addr 2 | Addr 3 | Addr 4 * 0 | 0 | DA | SA | BSSID | n/a * 0 | 1 | DA | BSSID | SA | n/a * 1 | 0 | BSSID | SA | DA | n/a * 1 | 1 | RA | TA | DA | SA */ /* * Function to get source and destination MAC addresses for a data frame. */ static void get_data_src_dst_mac(uint16_t fc, const u_char *p, const uint8_t **srcp, const uint8_t **dstp) { #define ADDR1 (p + 4) #define ADDR2 (p + 10) #define ADDR3 (p + 16) #define ADDR4 (p + 24) if (!FC_TO_DS(fc)) { if (!FC_FROM_DS(fc)) { /* not To DS and not From DS */ *srcp = ADDR2; *dstp = ADDR1; } else { /* not To DS and From DS */ *srcp = ADDR3; *dstp = ADDR1; } } else { if (!FC_FROM_DS(fc)) { /* From DS and not To DS */ *srcp = ADDR2; *dstp = ADDR3; } else { /* To DS and From DS */ *srcp = ADDR4; *dstp = ADDR3; } } #undef ADDR1 #undef ADDR2 #undef ADDR3 #undef ADDR4 } static void get_mgmt_src_dst_mac(const u_char *p, const uint8_t **srcp, const uint8_t **dstp) { const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p; if (srcp != NULL) *srcp = hp->sa; if (dstp != NULL) *dstp = hp->da; } /* * Print Header funcs */ static void data_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p) { u_int subtype = FC_SUBTYPE(fc); if (DATA_FRAME_IS_CF_ACK(subtype) || DATA_FRAME_IS_CF_POLL(subtype) || DATA_FRAME_IS_QOS(subtype)) { ND_PRINT("CF "); if (DATA_FRAME_IS_CF_ACK(subtype)) { if (DATA_FRAME_IS_CF_POLL(subtype)) ND_PRINT("Ack/Poll"); else ND_PRINT("Ack"); } else { if (DATA_FRAME_IS_CF_POLL(subtype)) ND_PRINT("Poll"); } if (DATA_FRAME_IS_QOS(subtype)) ND_PRINT("+QoS"); ND_PRINT(" "); } #define ADDR1 (p + 4) #define ADDR2 (p + 10) #define ADDR3 (p + 16) #define ADDR4 (p + 24) if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) { ND_PRINT("DA:%s SA:%s BSSID:%s ", GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2), GET_ETHERADDR_STRING(ADDR3)); } else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) { ND_PRINT("DA:%s BSSID:%s SA:%s ", GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2), GET_ETHERADDR_STRING(ADDR3)); } else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) { ND_PRINT("BSSID:%s SA:%s DA:%s ", GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2), GET_ETHERADDR_STRING(ADDR3)); } else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) { ND_PRINT("RA:%s TA:%s DA:%s SA:%s ", GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2), GET_ETHERADDR_STRING(ADDR3), GET_ETHERADDR_STRING(ADDR4)); } #undef ADDR1 #undef ADDR2 #undef ADDR3 #undef ADDR4 } static void mgmt_header_print(netdissect_options *ndo, const u_char *p) { const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p; ND_PRINT("BSSID:%s DA:%s SA:%s ", GET_ETHERADDR_STRING((hp)->bssid), GET_ETHERADDR_STRING((hp)->da), GET_ETHERADDR_STRING((hp)->sa)); } static void ctrl_header_print(netdissect_options *ndo, uint16_t fc, const u_char *p) { switch (FC_SUBTYPE(fc)) { case CTRL_BAR: ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ", GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra), GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta), GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl), GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq)); break; case CTRL_BA: ND_PRINT("RA:%s ", GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra)); break; case CTRL_PS_POLL: ND_PRINT("BSSID:%s TA:%s ", GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->bssid), GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->ta)); break; case CTRL_RTS: ND_PRINT("RA:%s TA:%s ", GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ra), GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta)); break; case CTRL_CTS: ND_PRINT("RA:%s ", GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra)); break; case CTRL_ACK: ND_PRINT("RA:%s ", GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra)); break; case CTRL_CF_END: ND_PRINT("RA:%s BSSID:%s ", GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra), GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->bssid)); break; case CTRL_END_ACK: ND_PRINT("RA:%s BSSID:%s ", GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra), GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->bssid)); break; default: /* We shouldn't get here - we should already have quit */ break; } } static int extract_header_length(netdissect_options *ndo, uint16_t fc) { int len; switch (FC_TYPE(fc)) { case T_MGMT: return MGMT_HDRLEN; case T_CTRL: switch (FC_SUBTYPE(fc)) { case CTRL_CONTROL_WRAPPER: return CTRL_CONTROL_WRAPPER_HDRLEN; case CTRL_BAR: return CTRL_BAR_HDRLEN; case CTRL_BA: return CTRL_BA_HDRLEN; case CTRL_PS_POLL: return CTRL_PS_POLL_HDRLEN; case CTRL_RTS: return CTRL_RTS_HDRLEN; case CTRL_CTS: return CTRL_CTS_HDRLEN; case CTRL_ACK: return CTRL_ACK_HDRLEN; case CTRL_CF_END: return CTRL_END_HDRLEN; case CTRL_END_ACK: return CTRL_END_ACK_HDRLEN; default: ND_PRINT("unknown 802.11 ctrl frame subtype (%u)", FC_SUBTYPE(fc)); return 0; } case T_DATA: len = (FC_TO_DS(fc) && FC_FROM_DS(fc)) ? 30 : 24; if (DATA_FRAME_IS_QOS(FC_SUBTYPE(fc))) len += 2; return len; default: ND_PRINT("unknown 802.11 frame type (%u)", FC_TYPE(fc)); return 0; } } static int extract_mesh_header_length(netdissect_options *ndo, const u_char *p) { return (GET_U_1(p) &~ 3) ? 0 : 6*(1 + (GET_U_1(p) & 3)); } /* * Print the 802.11 MAC header. */ static void ieee_802_11_hdr_print(netdissect_options *ndo, uint16_t fc, const u_char *p, u_int hdrlen, u_int meshdrlen) { if (ndo->ndo_vflag) { if (FC_MORE_DATA(fc)) ND_PRINT("More Data "); if (FC_MORE_FLAG(fc)) ND_PRINT("More Fragments "); if (FC_POWER_MGMT(fc)) ND_PRINT("Pwr Mgmt "); if (FC_RETRY(fc)) ND_PRINT("Retry "); if (FC_ORDER(fc)) ND_PRINT("Strictly Ordered "); if (FC_PROTECTED(fc)) ND_PRINT("Protected "); if (FC_TYPE(fc) != T_CTRL || FC_SUBTYPE(fc) != CTRL_PS_POLL) ND_PRINT("%uus ", GET_LE_U_2(((const struct mgmt_header_t *)p)->duration)); } if (meshdrlen != 0) { const struct meshcntl_t *mc = (const struct meshcntl_t *)(p + hdrlen - meshdrlen); u_int ae = GET_U_1(mc->flags) & 3; ND_PRINT("MeshData (AE %u TTL %u seq %u", ae, GET_U_1(mc->ttl), GET_LE_U_4(mc->seq)); if (ae > 0) ND_PRINT(" A4:%s", GET_ETHERADDR_STRING(mc->addr4)); if (ae > 1) ND_PRINT(" A5:%s", GET_ETHERADDR_STRING(mc->addr5)); if (ae > 2) ND_PRINT(" A6:%s", GET_ETHERADDR_STRING(mc->addr6)); ND_PRINT(") "); } switch (FC_TYPE(fc)) { case T_MGMT: mgmt_header_print(ndo, p); break; case T_CTRL: ctrl_header_print(ndo, fc, p); break; case T_DATA: data_header_print(ndo, fc, p); break; default: break; } } static u_int ieee802_11_print(netdissect_options *ndo, const u_char *p, u_int length, u_int orig_caplen, int pad, u_int fcslen) { uint16_t fc; u_int caplen, hdrlen, meshdrlen; struct lladdr_info src, dst; int llc_hdrlen; ndo->ndo_protocol = "802.11"; caplen = orig_caplen; /* Remove FCS, if present */ if (length < fcslen) { nd_print_trunc(ndo); return caplen; } length -= fcslen; if (caplen > length) { /* Amount of FCS in actual packet data, if any */ fcslen = caplen - length; caplen -= fcslen; ndo->ndo_snapend -= fcslen; } if (caplen < IEEE802_11_FC_LEN) { nd_print_trunc(ndo); return orig_caplen; } fc = GET_LE_U_2(p); hdrlen = extract_header_length(ndo, fc); if (hdrlen == 0) { /* Unknown frame type or control frame subtype; quit. */ return (0); } if (pad) hdrlen = roundup2(hdrlen, 4); if (ndo->ndo_Hflag && FC_TYPE(fc) == T_DATA && DATA_FRAME_IS_QOS(FC_SUBTYPE(fc))) { if(!ND_TTEST_1(p + hdrlen)) { nd_print_trunc(ndo); return hdrlen; } meshdrlen = extract_mesh_header_length(ndo, p + hdrlen); hdrlen += meshdrlen; } else meshdrlen = 0; if (caplen < hdrlen) { nd_print_trunc(ndo); return hdrlen; } if (ndo->ndo_eflag) ieee_802_11_hdr_print(ndo, fc, p, hdrlen, meshdrlen); /* * Go past the 802.11 header. */ length -= hdrlen; caplen -= hdrlen; p += hdrlen; src.addr_string = etheraddr_string; dst.addr_string = etheraddr_string; switch (FC_TYPE(fc)) { case T_MGMT: get_mgmt_src_dst_mac(p - hdrlen, &src.addr, &dst.addr); if (!mgmt_body_print(ndo, fc, src.addr, p, length)) { nd_print_trunc(ndo); return hdrlen; } break; case T_CTRL: if (!ctrl_body_print(ndo, fc, p - hdrlen)) { nd_print_trunc(ndo); return hdrlen; } break; case T_DATA: if (DATA_FRAME_IS_NULL(FC_SUBTYPE(fc))) return hdrlen; /* no-data frame */ /* There may be a problem w/ AP not having this bit set */ if (FC_PROTECTED(fc)) { ND_PRINT("Data"); if (!wep_print(ndo, p)) { nd_print_trunc(ndo); return hdrlen; } } else { get_data_src_dst_mac(fc, p - hdrlen, &src.addr, &dst.addr); llc_hdrlen = llc_print(ndo, p, length, caplen, &src, &dst); if (llc_hdrlen < 0) { /* * Some kinds of LLC packet we cannot * handle intelligently */ if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); llc_hdrlen = -llc_hdrlen; } hdrlen += llc_hdrlen; } break; default: /* We shouldn't get here - we should already have quit */ break; } return hdrlen; } /* * This is the top level routine of the printer. 'p' points * to the 802.11 header of the packet, 'h->ts' is the timestamp, * 'h->len' is the length of the packet off the wire, and 'h->caplen' * is the number of bytes actually captured. */ void ieee802_11_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { ndo->ndo_protocol = "802.11"; ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, h->len, h->caplen, 0, 0); } /* $FreeBSD: src/sys/net80211/ieee80211_radiotap.h,v 1.5 2005/01/22 20:12:05 sam Exp $ */ /* NetBSD: ieee802_11_radio.h,v 1.2 2006/02/26 03:04:03 dyoung Exp */ /*- * Copyright (c) 2003, 2004 David Young. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of David Young may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. */ /* A generic radio capture format is desirable. It must be * rigidly defined (e.g., units for fields should be given), * and easily extensible. * * The following is an extensible radio capture format. It is * based on a bitmap indicating which fields are present. * * I am trying to describe precisely what the application programmer * should expect in the following, and for that reason I tell the * units and origin of each measurement (where it applies), or else I * use sufficiently weaselly language ("is a monotonically nondecreasing * function of...") that I cannot set false expectations for lawyerly * readers. */ /* * The radio capture header precedes the 802.11 header. * * Note well: all radiotap fields are little-endian. */ struct ieee80211_radiotap_header { nd_uint8_t it_version; /* Version 0. Only increases * for drastic changes, * introduction of compatible * new fields does not count. */ nd_uint8_t it_pad; nd_uint16_t it_len; /* length of the whole * header in bytes, including * it_version, it_pad, * it_len, and data fields. */ nd_uint32_t it_present; /* A bitmap telling which * fields are present. Set bit 31 * (0x80000000) to extend the * bitmap by another 32 bits. * Additional extensions are made * by setting bit 31. */ }; /* Name Data type Units * ---- --------- ----- * * IEEE80211_RADIOTAP_TSFT uint64_t microseconds * * Value in microseconds of the MAC's 64-bit 802.11 Time * Synchronization Function timer when the first bit of the * MPDU arrived at the MAC. For received frames, only. * * IEEE80211_RADIOTAP_CHANNEL 2 x uint16_t MHz, bitmap * * Tx/Rx frequency in MHz, followed by flags (see below). * Note that IEEE80211_RADIOTAP_XCHANNEL must be used to * represent an HT channel as there is not enough room in * the flags word. * * IEEE80211_RADIOTAP_FHSS uint16_t see below * * For frequency-hopping radios, the hop set (first byte) * and pattern (second byte). * * IEEE80211_RADIOTAP_RATE uint8_t 500kb/s or index * * Tx/Rx data rate. If bit 0x80 is set then it represents an * an MCS index and not an IEEE rate. * * IEEE80211_RADIOTAP_DBM_ANTSIGNAL int8_t decibels from * one milliwatt (dBm) * * RF signal power at the antenna, decibel difference from * one milliwatt. * * IEEE80211_RADIOTAP_DBM_ANTNOISE int8_t decibels from * one milliwatt (dBm) * * RF noise power at the antenna, decibel difference from one * milliwatt. * * IEEE80211_RADIOTAP_DB_ANTSIGNAL uint8_t decibel (dB) * * RF signal power at the antenna, decibel difference from an * arbitrary, fixed reference. * * IEEE80211_RADIOTAP_DB_ANTNOISE uint8_t decibel (dB) * * RF noise power at the antenna, decibel difference from an * arbitrary, fixed reference point. * * IEEE80211_RADIOTAP_LOCK_QUALITY uint16_t unitless * * Quality of Barker code lock. Unitless. Monotonically * nondecreasing with "better" lock strength. Called "Signal * Quality" in datasheets. (Is there a standard way to measure * this?) * * IEEE80211_RADIOTAP_TX_ATTENUATION uint16_t unitless * * Transmit power expressed as unitless distance from max * power set at factory calibration. 0 is max power. * Monotonically nondecreasing with lower power levels. * * IEEE80211_RADIOTAP_DB_TX_ATTENUATION uint16_t decibels (dB) * * Transmit power expressed as decibel distance from max power * set at factory calibration. 0 is max power. Monotonically * nondecreasing with lower power levels. * * IEEE80211_RADIOTAP_DBM_TX_POWER int8_t decibels from * one milliwatt (dBm) * * Transmit power expressed as dBm (decibels from a 1 milliwatt * reference). This is the absolute power level measured at * the antenna port. * * IEEE80211_RADIOTAP_FLAGS uint8_t bitmap * * Properties of transmitted and received frames. See flags * defined below. * * IEEE80211_RADIOTAP_ANTENNA uint8_t antenna index * * Unitless indication of the Rx/Tx antenna for this packet. * The first antenna is antenna 0. * * IEEE80211_RADIOTAP_RX_FLAGS uint16_t bitmap * * Properties of received frames. See flags defined below. * * IEEE80211_RADIOTAP_XCHANNEL uint32_t bitmap * uint16_t MHz * uint8_t channel number * uint8_t .5 dBm * * Extended channel specification: flags (see below) followed by * frequency in MHz, the corresponding IEEE channel number, and * finally the maximum regulatory transmit power cap in .5 dBm * units. This property supersedes IEEE80211_RADIOTAP_CHANNEL * and only one of the two should be present. * * IEEE80211_RADIOTAP_MCS uint8_t known * uint8_t flags * uint8_t mcs * * Bitset indicating which fields have known values, followed * by bitset of flag values, followed by the MCS rate index as * in IEEE 802.11n. * * * IEEE80211_RADIOTAP_AMPDU_STATUS u32, u16, u8, u8 unitless * * Contains the AMPDU information for the subframe. * * IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16 * * Contains VHT information about this frame. * * IEEE80211_RADIOTAP_VENDOR_NAMESPACE * uint8_t OUI[3] * uint8_t subspace * uint16_t length * * The Vendor Namespace Field contains three sub-fields. The first * sub-field is 3 bytes long. It contains the vendor's IEEE 802 * Organizationally Unique Identifier (OUI). The fourth byte is a * vendor-specific "namespace selector." * */ enum ieee80211_radiotap_type { IEEE80211_RADIOTAP_TSFT = 0, IEEE80211_RADIOTAP_FLAGS = 1, IEEE80211_RADIOTAP_RATE = 2, IEEE80211_RADIOTAP_CHANNEL = 3, IEEE80211_RADIOTAP_FHSS = 4, IEEE80211_RADIOTAP_DBM_ANTSIGNAL = 5, IEEE80211_RADIOTAP_DBM_ANTNOISE = 6, IEEE80211_RADIOTAP_LOCK_QUALITY = 7, IEEE80211_RADIOTAP_TX_ATTENUATION = 8, IEEE80211_RADIOTAP_DB_TX_ATTENUATION = 9, IEEE80211_RADIOTAP_DBM_TX_POWER = 10, IEEE80211_RADIOTAP_ANTENNA = 11, IEEE80211_RADIOTAP_DB_ANTSIGNAL = 12, IEEE80211_RADIOTAP_DB_ANTNOISE = 13, IEEE80211_RADIOTAP_RX_FLAGS = 14, /* NB: gap for netbsd definitions */ IEEE80211_RADIOTAP_XCHANNEL = 18, IEEE80211_RADIOTAP_MCS = 19, IEEE80211_RADIOTAP_AMPDU_STATUS = 20, IEEE80211_RADIOTAP_VHT = 21, IEEE80211_RADIOTAP_NAMESPACE = 29, IEEE80211_RADIOTAP_VENDOR_NAMESPACE = 30, IEEE80211_RADIOTAP_EXT = 31 }; /* channel attributes */ #define IEEE80211_CHAN_TURBO 0x00010 /* Turbo channel */ #define IEEE80211_CHAN_CCK 0x00020 /* CCK channel */ #define IEEE80211_CHAN_OFDM 0x00040 /* OFDM channel */ #define IEEE80211_CHAN_2GHZ 0x00080 /* 2 GHz spectrum channel. */ #define IEEE80211_CHAN_5GHZ 0x00100 /* 5 GHz spectrum channel */ #define IEEE80211_CHAN_PASSIVE 0x00200 /* Only passive scan allowed */ #define IEEE80211_CHAN_DYN 0x00400 /* Dynamic CCK-OFDM channel */ #define IEEE80211_CHAN_GFSK 0x00800 /* GFSK channel (FHSS PHY) */ #define IEEE80211_CHAN_GSM 0x01000 /* 900 MHz spectrum channel */ #define IEEE80211_CHAN_STURBO 0x02000 /* 11a static turbo channel only */ #define IEEE80211_CHAN_HALF 0x04000 /* Half rate channel */ #define IEEE80211_CHAN_QUARTER 0x08000 /* Quarter rate channel */ #define IEEE80211_CHAN_HT20 0x10000 /* HT 20 channel */ #define IEEE80211_CHAN_HT40U 0x20000 /* HT 40 channel w/ ext above */ #define IEEE80211_CHAN_HT40D 0x40000 /* HT 40 channel w/ ext below */ /* Useful combinations of channel characteristics, borrowed from Ethereal */ #define IEEE80211_CHAN_A \ (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM) #define IEEE80211_CHAN_B \ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK) #define IEEE80211_CHAN_G \ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN) #define IEEE80211_CHAN_TA \ (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM | IEEE80211_CHAN_TURBO) #define IEEE80211_CHAN_TG \ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN | IEEE80211_CHAN_TURBO) /* For IEEE80211_RADIOTAP_FLAGS */ #define IEEE80211_RADIOTAP_F_CFP 0x01 /* sent/received * during CFP */ #define IEEE80211_RADIOTAP_F_SHORTPRE 0x02 /* sent/received * with short * preamble */ #define IEEE80211_RADIOTAP_F_WEP 0x04 /* sent/received * with WEP encryption */ #define IEEE80211_RADIOTAP_F_FRAG 0x08 /* sent/received * with fragmentation */ #define IEEE80211_RADIOTAP_F_FCS 0x10 /* frame includes FCS */ #define IEEE80211_RADIOTAP_F_DATAPAD 0x20 /* frame has padding between * 802.11 header and payload * (to 32-bit boundary) */ #define IEEE80211_RADIOTAP_F_BADFCS 0x40 /* does not pass FCS check */ /* For IEEE80211_RADIOTAP_RX_FLAGS */ #define IEEE80211_RADIOTAP_F_RX_BADFCS 0x0001 /* frame failed crc check */ #define IEEE80211_RADIOTAP_F_RX_PLCP_CRC 0x0002 /* frame failed PLCP CRC check */ /* For IEEE80211_RADIOTAP_MCS known */ #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN 0x01 #define IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN 0x02 /* MCS index field */ #define IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN 0x04 #define IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN 0x08 #define IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN 0x10 #define IEEE80211_RADIOTAP_MCS_STBC_KNOWN 0x20 #define IEEE80211_RADIOTAP_MCS_NESS_KNOWN 0x40 #define IEEE80211_RADIOTAP_MCS_NESS_BIT_1 0x80 /* For IEEE80211_RADIOTAP_MCS flags */ #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK 0x03 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20 0 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 1 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20L 2 #define IEEE80211_RADIOTAP_MCS_BANDWIDTH_20U 3 #define IEEE80211_RADIOTAP_MCS_SHORT_GI 0x04 /* short guard interval */ #define IEEE80211_RADIOTAP_MCS_HT_GREENFIELD 0x08 #define IEEE80211_RADIOTAP_MCS_FEC_LDPC 0x10 #define IEEE80211_RADIOTAP_MCS_STBC_MASK 0x60 #define IEEE80211_RADIOTAP_MCS_STBC_1 1 #define IEEE80211_RADIOTAP_MCS_STBC_2 2 #define IEEE80211_RADIOTAP_MCS_STBC_3 3 #define IEEE80211_RADIOTAP_MCS_STBC_SHIFT 5 #define IEEE80211_RADIOTAP_MCS_NESS_BIT_0 0x80 /* For IEEE80211_RADIOTAP_AMPDU_STATUS */ #define IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN 0x0001 #define IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN 0x0002 #define IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN 0x0004 #define IEEE80211_RADIOTAP_AMPDU_IS_LAST 0x0008 #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR 0x0010 #define IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN 0x0020 /* For IEEE80211_RADIOTAP_VHT known */ #define IEEE80211_RADIOTAP_VHT_STBC_KNOWN 0x0001 #define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA_KNOWN 0x0002 #define IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN 0x0004 #define IEEE80211_RADIOTAP_VHT_SGI_NSYM_DIS_KNOWN 0x0008 #define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM_KNOWN 0x0010 #define IEEE80211_RADIOTAP_VHT_BEAMFORMED_KNOWN 0x0020 #define IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN 0x0040 #define IEEE80211_RADIOTAP_VHT_GROUP_ID_KNOWN 0x0080 #define IEEE80211_RADIOTAP_VHT_PARTIAL_AID_KNOWN 0x0100 /* For IEEE80211_RADIOTAP_VHT flags */ #define IEEE80211_RADIOTAP_VHT_STBC 0x01 #define IEEE80211_RADIOTAP_VHT_TXOP_PS_NA 0x02 #define IEEE80211_RADIOTAP_VHT_SHORT_GI 0x04 #define IEEE80211_RADIOTAP_VHT_SGI_NSYM_M10_9 0x08 #define IEEE80211_RADIOTAP_VHT_LDPC_EXTRA_OFDM_SYM 0x10 #define IEEE80211_RADIOTAP_VHT_BEAMFORMED 0x20 #define IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK 0x1f #define IEEE80211_RADIOTAP_VHT_NSS_MASK 0x0f #define IEEE80211_RADIOTAP_VHT_MCS_MASK 0xf0 #define IEEE80211_RADIOTAP_VHT_MCS_SHIFT 4 #define IEEE80211_RADIOTAP_CODING_LDPC_USERn 0x01 #define IEEE80211_CHAN_FHSS \ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_GFSK) #define IEEE80211_CHAN_A \ (IEEE80211_CHAN_5GHZ | IEEE80211_CHAN_OFDM) #define IEEE80211_CHAN_B \ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_CCK) #define IEEE80211_CHAN_PUREG \ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_OFDM) #define IEEE80211_CHAN_G \ (IEEE80211_CHAN_2GHZ | IEEE80211_CHAN_DYN) #define IS_CHAN_FHSS(flags) \ ((flags & IEEE80211_CHAN_FHSS) == IEEE80211_CHAN_FHSS) #define IS_CHAN_A(flags) \ ((flags & IEEE80211_CHAN_A) == IEEE80211_CHAN_A) #define IS_CHAN_B(flags) \ ((flags & IEEE80211_CHAN_B) == IEEE80211_CHAN_B) #define IS_CHAN_PUREG(flags) \ ((flags & IEEE80211_CHAN_PUREG) == IEEE80211_CHAN_PUREG) #define IS_CHAN_G(flags) \ ((flags & IEEE80211_CHAN_G) == IEEE80211_CHAN_G) #define IS_CHAN_ANYG(flags) \ (IS_CHAN_PUREG(flags) || IS_CHAN_G(flags)) static void print_chaninfo(netdissect_options *ndo, uint16_t freq, uint32_t flags, uint32_t presentflags) { ND_PRINT("%u MHz", freq); if (presentflags & (1 << IEEE80211_RADIOTAP_MCS)) { /* * We have the MCS field, so this is 11n, regardless * of what the channel flags say. */ ND_PRINT(" 11n"); } else { if (IS_CHAN_FHSS(flags)) ND_PRINT(" FHSS"); if (IS_CHAN_A(flags)) { if (flags & IEEE80211_CHAN_HALF) ND_PRINT(" 11a/10Mhz"); else if (flags & IEEE80211_CHAN_QUARTER) ND_PRINT(" 11a/5Mhz"); else ND_PRINT(" 11a"); } if (IS_CHAN_ANYG(flags)) { if (flags & IEEE80211_CHAN_HALF) ND_PRINT(" 11g/10Mhz"); else if (flags & IEEE80211_CHAN_QUARTER) ND_PRINT(" 11g/5Mhz"); else ND_PRINT(" 11g"); } else if (IS_CHAN_B(flags)) ND_PRINT(" 11b"); if (flags & IEEE80211_CHAN_TURBO) ND_PRINT(" Turbo"); } /* * These apply to 11n. */ if (flags & IEEE80211_CHAN_HT20) ND_PRINT(" ht/20"); else if (flags & IEEE80211_CHAN_HT40D) ND_PRINT(" ht/40-"); else if (flags & IEEE80211_CHAN_HT40U) ND_PRINT(" ht/40+"); ND_PRINT(" "); } static int print_radiotap_field(netdissect_options *ndo, struct cpack_state *s, uint32_t bit, uint8_t *flagsp, uint32_t presentflags) { u_int i; int rc; switch (bit) { case IEEE80211_RADIOTAP_TSFT: { uint64_t tsft; rc = nd_cpack_uint64(ndo, s, &tsft); if (rc != 0) goto trunc; ND_PRINT("%" PRIu64 "us tsft ", tsft); break; } case IEEE80211_RADIOTAP_FLAGS: { uint8_t flagsval; rc = nd_cpack_uint8(ndo, s, &flagsval); if (rc != 0) goto trunc; *flagsp = flagsval; if (flagsval & IEEE80211_RADIOTAP_F_CFP) ND_PRINT("cfp "); if (flagsval & IEEE80211_RADIOTAP_F_SHORTPRE) ND_PRINT("short preamble "); if (flagsval & IEEE80211_RADIOTAP_F_WEP) ND_PRINT("wep "); if (flagsval & IEEE80211_RADIOTAP_F_FRAG) ND_PRINT("fragmented "); if (flagsval & IEEE80211_RADIOTAP_F_BADFCS) ND_PRINT("bad-fcs "); break; } case IEEE80211_RADIOTAP_RATE: { uint8_t rate; rc = nd_cpack_uint8(ndo, s, &rate); if (rc != 0) goto trunc; /* * XXX On FreeBSD rate & 0x80 means we have an MCS. On * Linux and AirPcap it does not. (What about * macOS, NetBSD, OpenBSD, and DragonFly BSD?) * * This is an issue either for proprietary extensions * to 11a or 11g, which do exist, or for 11n * implementations that stuff a rate value into * this field, which also appear to exist. * * We currently handle that by assuming that * if the 0x80 bit is set *and* the remaining * bits have a value between 0 and 15 it's * an MCS value, otherwise it's a rate. If * there are cases where systems that use * "0x80 + MCS index" for MCS indices > 15, * or stuff a rate value here between 64 and * 71.5 Mb/s in here, we'll need a preference * setting. Such rates do exist, e.g. 11n * MCS 7 at 20 MHz with a long guard interval. */ if (rate >= 0x80 && rate <= 0x8f) { /* * XXX - we don't know the channel width * or guard interval length, so we can't * convert this to a data rate. * * If you want us to show a data rate, * use the MCS field, not the Rate field; * the MCS field includes not only the * MCS index, it also includes bandwidth * and guard interval information. * * XXX - can we get the channel width * from XChannel and the guard interval * information from Flags, at least on * FreeBSD? */ ND_PRINT("MCS %u ", rate & 0x7f); } else ND_PRINT("%2.1f Mb/s ", .5 * rate); break; } case IEEE80211_RADIOTAP_CHANNEL: { uint16_t frequency; uint16_t flags; rc = nd_cpack_uint16(ndo, s, &frequency); if (rc != 0) goto trunc; rc = nd_cpack_uint16(ndo, s, &flags); if (rc != 0) goto trunc; /* * If CHANNEL and XCHANNEL are both present, skip * CHANNEL. */ if (presentflags & (1 << IEEE80211_RADIOTAP_XCHANNEL)) break; print_chaninfo(ndo, frequency, flags, presentflags); break; } case IEEE80211_RADIOTAP_FHSS: { uint8_t hopset; uint8_t hoppat; rc = nd_cpack_uint8(ndo, s, &hopset); if (rc != 0) goto trunc; rc = nd_cpack_uint8(ndo, s, &hoppat); if (rc != 0) goto trunc; ND_PRINT("fhset %u fhpat %u ", hopset, hoppat); break; } case IEEE80211_RADIOTAP_DBM_ANTSIGNAL: { int8_t dbm_antsignal; rc = nd_cpack_int8(ndo, s, &dbm_antsignal); if (rc != 0) goto trunc; ND_PRINT("%ddBm signal ", dbm_antsignal); break; } case IEEE80211_RADIOTAP_DBM_ANTNOISE: { int8_t dbm_antnoise; rc = nd_cpack_int8(ndo, s, &dbm_antnoise); if (rc != 0) goto trunc; ND_PRINT("%ddBm noise ", dbm_antnoise); break; } case IEEE80211_RADIOTAP_LOCK_QUALITY: { uint16_t lock_quality; rc = nd_cpack_uint16(ndo, s, &lock_quality); if (rc != 0) goto trunc; ND_PRINT("%u sq ", lock_quality); break; } case IEEE80211_RADIOTAP_TX_ATTENUATION: { int16_t tx_attenuation; rc = nd_cpack_int16(ndo, s, &tx_attenuation); if (rc != 0) goto trunc; ND_PRINT("%d tx power ", -tx_attenuation); break; } case IEEE80211_RADIOTAP_DB_TX_ATTENUATION: { int8_t db_tx_attenuation; rc = nd_cpack_int8(ndo, s, &db_tx_attenuation); if (rc != 0) goto trunc; ND_PRINT("%ddB tx attenuation ", -db_tx_attenuation); break; } case IEEE80211_RADIOTAP_DBM_TX_POWER: { int8_t dbm_tx_power; rc = nd_cpack_int8(ndo, s, &dbm_tx_power); if (rc != 0) goto trunc; ND_PRINT("%ddBm tx power ", dbm_tx_power); break; } case IEEE80211_RADIOTAP_ANTENNA: { uint8_t antenna; rc = nd_cpack_uint8(ndo, s, &antenna); if (rc != 0) goto trunc; ND_PRINT("antenna %u ", antenna); break; } case IEEE80211_RADIOTAP_DB_ANTSIGNAL: { uint8_t db_antsignal; rc = nd_cpack_uint8(ndo, s, &db_antsignal); if (rc != 0) goto trunc; ND_PRINT("%udB signal ", db_antsignal); break; } case IEEE80211_RADIOTAP_DB_ANTNOISE: { uint8_t db_antnoise; rc = nd_cpack_uint8(ndo, s, &db_antnoise); if (rc != 0) goto trunc; ND_PRINT("%udB noise ", db_antnoise); break; } case IEEE80211_RADIOTAP_RX_FLAGS: { uint16_t rx_flags; rc = nd_cpack_uint16(ndo, s, &rx_flags); if (rc != 0) goto trunc; /* Do nothing for now */ break; } case IEEE80211_RADIOTAP_XCHANNEL: { uint32_t flags; uint16_t frequency; uint8_t channel; uint8_t maxpower; rc = nd_cpack_uint32(ndo, s, &flags); if (rc != 0) goto trunc; rc = nd_cpack_uint16(ndo, s, &frequency); if (rc != 0) goto trunc; rc = nd_cpack_uint8(ndo, s, &channel); if (rc != 0) goto trunc; rc = nd_cpack_uint8(ndo, s, &maxpower); if (rc != 0) goto trunc; print_chaninfo(ndo, frequency, flags, presentflags); break; } case IEEE80211_RADIOTAP_MCS: { uint8_t known; uint8_t flags; uint8_t mcs_index; static const char *ht_bandwidth[4] = { "20 MHz", "40 MHz", "20 MHz (L)", "20 MHz (U)" }; float htrate; rc = nd_cpack_uint8(ndo, s, &known); if (rc != 0) goto trunc; rc = nd_cpack_uint8(ndo, s, &flags); if (rc != 0) goto trunc; rc = nd_cpack_uint8(ndo, s, &mcs_index); if (rc != 0) goto trunc; if (known & IEEE80211_RADIOTAP_MCS_MCS_INDEX_KNOWN) { /* * We know the MCS index. */ if (mcs_index <= MAX_MCS_INDEX) { /* * And it's in-range. */ if (known & (IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN|IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN)) { /* * And we know both the bandwidth and * the guard interval, so we can look * up the rate. */ htrate = ieee80211_float_htrates [mcs_index] [((flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK) == IEEE80211_RADIOTAP_MCS_BANDWIDTH_40 ? 1 : 0)] [((flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ? 1 : 0)]; } else { /* * We don't know both the bandwidth * and the guard interval, so we can * only report the MCS index. */ htrate = 0.0; } } else { /* * The MCS value is out of range. */ htrate = 0.0; } if (htrate != 0.0) { /* * We have the rate. * Print it. */ ND_PRINT("%.1f Mb/s MCS %u ", htrate, mcs_index); } else { /* * We at least have the MCS index. * Print it. */ ND_PRINT("MCS %u ", mcs_index); } } if (known & IEEE80211_RADIOTAP_MCS_BANDWIDTH_KNOWN) { ND_PRINT("%s ", ht_bandwidth[flags & IEEE80211_RADIOTAP_MCS_BANDWIDTH_MASK]); } if (known & IEEE80211_RADIOTAP_MCS_GUARD_INTERVAL_KNOWN) { ND_PRINT("%s GI ", (flags & IEEE80211_RADIOTAP_MCS_SHORT_GI) ? "short" : "long"); } if (known & IEEE80211_RADIOTAP_MCS_HT_FORMAT_KNOWN) { ND_PRINT("%s ", (flags & IEEE80211_RADIOTAP_MCS_HT_GREENFIELD) ? "greenfield" : "mixed"); } if (known & IEEE80211_RADIOTAP_MCS_FEC_TYPE_KNOWN) { ND_PRINT("%s FEC ", (flags & IEEE80211_RADIOTAP_MCS_FEC_LDPC) ? "LDPC" : "BCC"); } if (known & IEEE80211_RADIOTAP_MCS_STBC_KNOWN) { ND_PRINT("RX-STBC%u ", (flags & IEEE80211_RADIOTAP_MCS_STBC_MASK) >> IEEE80211_RADIOTAP_MCS_STBC_SHIFT); } break; } case IEEE80211_RADIOTAP_AMPDU_STATUS: { uint32_t reference_num; uint16_t flags; uint8_t delim_crc; uint8_t reserved; rc = nd_cpack_uint32(ndo, s, &reference_num); if (rc != 0) goto trunc; rc = nd_cpack_uint16(ndo, s, &flags); if (rc != 0) goto trunc; rc = nd_cpack_uint8(ndo, s, &delim_crc); if (rc != 0) goto trunc; rc = nd_cpack_uint8(ndo, s, &reserved); if (rc != 0) goto trunc; /* Do nothing for now */ break; } case IEEE80211_RADIOTAP_VHT: { uint16_t known; uint8_t flags; uint8_t bandwidth; uint8_t mcs_nss[4]; uint8_t coding; uint8_t group_id; uint16_t partial_aid; static const char *vht_bandwidth[32] = { "20 MHz", "40 MHz", "20 MHz (L)", "20 MHz (U)", "80 MHz", "80 MHz (L)", "80 MHz (U)", "80 MHz (LL)", "80 MHz (LU)", "80 MHz (UL)", "80 MHz (UU)", "160 MHz", "160 MHz (L)", "160 MHz (U)", "160 MHz (LL)", "160 MHz (LU)", "160 MHz (UL)", "160 MHz (UU)", "160 MHz (LLL)", "160 MHz (LLU)", "160 MHz (LUL)", "160 MHz (UUU)", "160 MHz (ULL)", "160 MHz (ULU)", "160 MHz (UUL)", "160 MHz (UUU)", "unknown (26)", "unknown (27)", "unknown (28)", "unknown (29)", "unknown (30)", "unknown (31)" }; rc = nd_cpack_uint16(ndo, s, &known); if (rc != 0) goto trunc; rc = nd_cpack_uint8(ndo, s, &flags); if (rc != 0) goto trunc; rc = nd_cpack_uint8(ndo, s, &bandwidth); if (rc != 0) goto trunc; for (i = 0; i < 4; i++) { rc = nd_cpack_uint8(ndo, s, &mcs_nss[i]); if (rc != 0) goto trunc; } rc = nd_cpack_uint8(ndo, s, &coding); if (rc != 0) goto trunc; rc = nd_cpack_uint8(ndo, s, &group_id); if (rc != 0) goto trunc; rc = nd_cpack_uint16(ndo, s, &partial_aid); if (rc != 0) goto trunc; for (i = 0; i < 4; i++) { u_int nss, mcs; nss = mcs_nss[i] & IEEE80211_RADIOTAP_VHT_NSS_MASK; mcs = (mcs_nss[i] & IEEE80211_RADIOTAP_VHT_MCS_MASK) >> IEEE80211_RADIOTAP_VHT_MCS_SHIFT; if (nss == 0) continue; ND_PRINT("User %u MCS %u ", i, mcs); ND_PRINT("%s FEC ", (coding & (IEEE80211_RADIOTAP_CODING_LDPC_USERn << i)) ? "LDPC" : "BCC"); } if (known & IEEE80211_RADIOTAP_VHT_BANDWIDTH_KNOWN) { ND_PRINT("%s ", vht_bandwidth[bandwidth & IEEE80211_RADIOTAP_VHT_BANDWIDTH_MASK]); } if (known & IEEE80211_RADIOTAP_VHT_GUARD_INTERVAL_KNOWN) { ND_PRINT("%s GI ", (flags & IEEE80211_RADIOTAP_VHT_SHORT_GI) ? "short" : "long"); } break; } default: /* this bit indicates a field whose * size we do not know, so we cannot * proceed. Just print the bit number. */ ND_PRINT("[bit %u] ", bit); return -1; } return 0; trunc: nd_print_trunc(ndo); return rc; } static int print_in_radiotap_namespace(netdissect_options *ndo, struct cpack_state *s, uint8_t *flags, uint32_t presentflags, int bit0) { #define BITNO_32(x) (((x) >> 16) ? 16 + BITNO_16((x) >> 16) : BITNO_16((x))) #define BITNO_16(x) (((x) >> 8) ? 8 + BITNO_8((x) >> 8) : BITNO_8((x))) #define BITNO_8(x) (((x) >> 4) ? 4 + BITNO_4((x) >> 4) : BITNO_4((x))) #define BITNO_4(x) (((x) >> 2) ? 2 + BITNO_2((x) >> 2) : BITNO_2((x))) #define BITNO_2(x) (((x) & 2) ? 1 : 0) uint32_t present, next_present; int bitno; enum ieee80211_radiotap_type bit; int rc; for (present = presentflags; present; present = next_present) { /* * Clear the least significant bit that is set. */ next_present = present & (present - 1); /* * Get the bit number, within this presence word, * of the remaining least significant bit that * is set. */ bitno = BITNO_32(present ^ next_present); /* * Stop if this is one of the "same meaning * in all presence flags" bits. */ if (bitno >= IEEE80211_RADIOTAP_NAMESPACE) break; /* * Get the radiotap bit number of that bit. */ bit = (enum ieee80211_radiotap_type)(bit0 + bitno); rc = print_radiotap_field(ndo, s, bit, flags, presentflags); if (rc != 0) return rc; } return 0; } u_int ieee802_11_radio_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen) { #define BIT(n) (1U << n) #define IS_EXTENDED(__p) \ (GET_LE_U_4(__p) & BIT(IEEE80211_RADIOTAP_EXT)) != 0 struct cpack_state cpacker; const struct ieee80211_radiotap_header *hdr; uint32_t presentflags; const nd_uint32_t *presentp, *last_presentp; int vendor_namespace; uint8_t vendor_oui[3]; uint8_t vendor_subnamespace; uint16_t skip_length; int bit0; u_int len; uint8_t flags; int pad; u_int fcslen; ndo->ndo_protocol = "802.11_radio"; if (caplen < sizeof(*hdr)) { nd_print_trunc(ndo); return caplen; } hdr = (const struct ieee80211_radiotap_header *)p; len = GET_LE_U_2(hdr->it_len); if (len < sizeof(*hdr)) { /* * The length is the length of the entire header, so * it must be as large as the fixed-length part of * the header. */ nd_print_trunc(ndo); return caplen; } /* * If we don't have the entire radiotap header, just give up. */ if (caplen < len) { nd_print_trunc(ndo); return caplen; } nd_cpack_init(&cpacker, (const uint8_t *)hdr, len); /* align against header start */ nd_cpack_advance(&cpacker, sizeof(*hdr)); /* includes the 1st bitmap */ for (last_presentp = &hdr->it_present; (const u_char*)(last_presentp + 1) <= p + len && IS_EXTENDED(last_presentp); last_presentp++) nd_cpack_advance(&cpacker, sizeof(hdr->it_present)); /* more bitmaps */ /* are there more bitmap extensions than bytes in header? */ if ((const u_char*)(last_presentp + 1) > p + len) { nd_print_trunc(ndo); return caplen; } /* * Start out at the beginning of the default radiotap namespace. */ bit0 = 0; vendor_namespace = 0; memset(vendor_oui, 0, 3); vendor_subnamespace = 0; skip_length = 0; /* Assume no flags */ flags = 0; /* Assume no Atheros padding between 802.11 header and body */ pad = 0; /* Assume no FCS at end of frame */ fcslen = 0; for (presentp = &hdr->it_present; presentp <= last_presentp; presentp++) { presentflags = GET_LE_U_4(presentp); /* * If this is a vendor namespace, we don't handle it. */ if (vendor_namespace) { /* * Skip past the stuff we don't understand. * If we add support for any vendor namespaces, * it'd be added here; use vendor_oui and * vendor_subnamespace to interpret the fields. */ if (nd_cpack_advance(&cpacker, skip_length) != 0) { /* * Ran out of space in the packet. */ break; } /* * We've skipped it all; nothing more to * skip. */ skip_length = 0; } else { if (print_in_radiotap_namespace(ndo, &cpacker, &flags, presentflags, bit0) != 0) { /* * Fatal error - can't process anything * more in the radiotap header. */ break; } } /* * Handle the namespace switch bits; we've already handled * the extension bit in all but the last word above. */ switch (presentflags & (BIT(IEEE80211_RADIOTAP_NAMESPACE)|BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE))) { case 0: /* * We're not changing namespaces. * advance to the next 32 bits in the current * namespace. */ bit0 += 32; break; case BIT(IEEE80211_RADIOTAP_NAMESPACE): /* * We're switching to the radiotap namespace. * Reset the presence-bitmap index to 0, and * reset the namespace to the default radiotap * namespace. */ bit0 = 0; vendor_namespace = 0; memset(vendor_oui, 0, 3); vendor_subnamespace = 0; skip_length = 0; break; case BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE): /* * We're switching to a vendor namespace. * Reset the presence-bitmap index to 0, * note that we're in a vendor namespace, * and fetch the fields of the Vendor Namespace * item. */ bit0 = 0; vendor_namespace = 1; if ((nd_cpack_align_and_reserve(&cpacker, 2)) == NULL) { nd_print_trunc(ndo); break; } if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[0]) != 0) { nd_print_trunc(ndo); break; } if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[1]) != 0) { nd_print_trunc(ndo); break; } if (nd_cpack_uint8(ndo, &cpacker, &vendor_oui[2]) != 0) { nd_print_trunc(ndo); break; } if (nd_cpack_uint8(ndo, &cpacker, &vendor_subnamespace) != 0) { nd_print_trunc(ndo); break; } if (nd_cpack_uint16(ndo, &cpacker, &skip_length) != 0) { nd_print_trunc(ndo); break; } break; default: /* * Illegal combination. The behavior in this * case is undefined by the radiotap spec; we * just ignore both bits. */ break; } } if (flags & IEEE80211_RADIOTAP_F_DATAPAD) pad = 1; /* Atheros padding */ if (flags & IEEE80211_RADIOTAP_F_FCS) fcslen = 4; /* FCS at end of packet */ return len + ieee802_11_print(ndo, p + len, length - len, caplen - len, pad, fcslen); #undef BITNO_32 #undef BITNO_16 #undef BITNO_8 #undef BITNO_4 #undef BITNO_2 #undef BIT } static u_int ieee802_11_radio_avs_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen) { uint32_t caphdr_len; ndo->ndo_protocol = "802.11_radio_avs"; if (caplen < 8) { nd_print_trunc(ndo); return caplen; } caphdr_len = GET_BE_U_4(p + 4); if (caphdr_len < 8) { /* * Yow! The capture header length is claimed not * to be large enough to include even the version * cookie or capture header length! */ nd_print_trunc(ndo); return caplen; } if (caplen < caphdr_len) { nd_print_trunc(ndo); return caplen; } return caphdr_len + ieee802_11_print(ndo, p + caphdr_len, length - caphdr_len, caplen - caphdr_len, 0, 0); } #define PRISM_HDR_LEN 144 #define WLANCAP_MAGIC_COOKIE_BASE 0x80211000 #define WLANCAP_MAGIC_COOKIE_V1 0x80211001 #define WLANCAP_MAGIC_COOKIE_V2 0x80211002 /* * For DLT_PRISM_HEADER; like DLT_IEEE802_11, but with an extra header, * containing information such as radio information, which we * currently ignore. * * If, however, the packet begins with WLANCAP_MAGIC_COOKIE_V1 or * WLANCAP_MAGIC_COOKIE_V2, it's really DLT_IEEE802_11_RADIO_AVS * (currently, on Linux, there's no ARPHRD_ type for * DLT_IEEE802_11_RADIO_AVS, as there is a ARPHRD_IEEE80211_PRISM * for DLT_PRISM_HEADER, so ARPHRD_IEEE80211_PRISM is used for * the AVS header, and the first 4 bytes of the header are used to * indicate whether it's a Prism header or an AVS header). */ void prism_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { u_int caplen = h->caplen; u_int length = h->len; uint32_t msgcode; ndo->ndo_protocol = "prism"; if (caplen < 4) { nd_print_trunc(ndo); ndo->ndo_ll_hdr_len += caplen; return; } msgcode = GET_BE_U_4(p); if (msgcode == WLANCAP_MAGIC_COOKIE_V1 || msgcode == WLANCAP_MAGIC_COOKIE_V2) { ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, length, caplen); return; } if (caplen < PRISM_HDR_LEN) { nd_print_trunc(ndo); ndo->ndo_ll_hdr_len += caplen; return; } p += PRISM_HDR_LEN; length -= PRISM_HDR_LEN; caplen -= PRISM_HDR_LEN; ndo->ndo_ll_hdr_len += PRISM_HDR_LEN; ndo->ndo_ll_hdr_len += ieee802_11_print(ndo, p, length, caplen, 0, 0); } /* * For DLT_IEEE802_11_RADIO; like DLT_IEEE802_11, but with an extra * header, containing information such as radio information. */ void ieee802_11_radio_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { ndo->ndo_protocol = "802.11_radio"; ndo->ndo_ll_hdr_len += ieee802_11_radio_print(ndo, p, h->len, h->caplen); } /* * For DLT_IEEE802_11_RADIO_AVS; like DLT_IEEE802_11, but with an * extra header, containing information such as radio information, * which we currently ignore. */ void ieee802_11_radio_avs_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { ndo->ndo_protocol = "802.11_radio_avs"; ndo->ndo_ll_hdr_len += ieee802_11_radio_avs_print(ndo, p, h->len, h->caplen); } tcpdump-4.99.1/print-dvmrp.c0000644000026300017510000001772314057477727014101 0ustar mcrmcr/* * Copyright (c) 1995, 1996 * 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. */ /* \summary: Distance Vector Multicast Routing Protocol printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" #include "extract.h" #include "addrtoname.h" /* * See: RFC 1075 and draft-ietf-idmr-dvmrp-v3 * * DVMRP message types and flag values shamelessly stolen from * mrouted/dvmrp.h. */ #define DVMRP_PROBE 1 /* for finding neighbors */ #define DVMRP_REPORT 2 /* for reporting some or all routes */ #define DVMRP_ASK_NEIGHBORS 3 /* sent by mapper, asking for a list */ /* of this router's neighbors */ #define DVMRP_NEIGHBORS 4 /* response to such a request */ #define DVMRP_ASK_NEIGHBORS2 5 /* as above, want new format reply */ #define DVMRP_NEIGHBORS2 6 #define DVMRP_PRUNE 7 /* prune message */ #define DVMRP_GRAFT 8 /* graft message */ #define DVMRP_GRAFT_ACK 9 /* graft acknowledgement */ static const struct tok dvmrp_msgtype_str[] = { { DVMRP_PROBE, "Probe" }, { DVMRP_REPORT, "Report" }, { DVMRP_ASK_NEIGHBORS, "Ask-neighbors(old)" }, { DVMRP_NEIGHBORS, "Neighbors(old)" }, { DVMRP_ASK_NEIGHBORS2, "Ask-neighbors2" }, { DVMRP_NEIGHBORS2, "Neighbors2" }, { DVMRP_PRUNE, "Prune" }, { DVMRP_GRAFT, "Graft" }, { DVMRP_GRAFT_ACK, "Graft-ACK" }, { 0, NULL } }; /* * 'flags' byte values in DVMRP_NEIGHBORS2 reply. */ #define DVMRP_NF_TUNNEL 0x01 /* neighbors reached via tunnel */ #define DVMRP_NF_SRCRT 0x02 /* tunnel uses IP source routing */ #define DVMRP_NF_DOWN 0x10 /* kernel state of interface */ #define DVMRP_NF_DISABLED 0x20 /* administratively disabled */ #define DVMRP_NF_QUERIER 0x40 /* I am the subnet's querier */ static void print_probe(netdissect_options *, const u_char *, u_int); static void print_report(netdissect_options *, const u_char *, u_int); static void print_neighbors(netdissect_options *, const u_char *, u_int); static void print_neighbors2(netdissect_options *, const u_char *, u_int, uint8_t, uint8_t); void dvmrp_print(netdissect_options *ndo, const u_char *bp, u_int len) { u_char type; uint8_t major_version, minor_version; ndo->ndo_protocol = "dvmrp"; if (len < 8) { ND_PRINT(" [length %u < 8]", len); goto invalid; } type = GET_U_1(bp + 1); /* Skip IGMP header */ bp += 8; len -= 8; ND_PRINT(" %s", tok2str(dvmrp_msgtype_str, "[type %u]", type)); switch (type) { case DVMRP_PROBE: if (ndo->ndo_vflag) { print_probe(ndo, bp, len); } break; case DVMRP_REPORT: if (ndo->ndo_vflag > 1) { print_report(ndo, bp, len); } break; case DVMRP_NEIGHBORS: print_neighbors(ndo, bp, len); break; case DVMRP_NEIGHBORS2: /* * extract version from IGMP group address field */ bp -= 4; major_version = GET_U_1(bp + 3); minor_version = GET_U_1(bp + 2); bp += 4; print_neighbors2(ndo, bp, len, major_version, minor_version); break; case DVMRP_PRUNE: ND_PRINT(" src %s grp %s", GET_IPADDR_STRING(bp), GET_IPADDR_STRING(bp + 4)); ND_PRINT(" timer "); unsigned_relts_print(ndo, GET_BE_U_4(bp + 8)); break; case DVMRP_GRAFT: ND_PRINT(" src %s grp %s", GET_IPADDR_STRING(bp), GET_IPADDR_STRING(bp + 4)); break; case DVMRP_GRAFT_ACK: ND_PRINT(" src %s grp %s", GET_IPADDR_STRING(bp), GET_IPADDR_STRING(bp + 4)); break; } return; invalid: nd_print_invalid(ndo); } static void print_report(netdissect_options *ndo, const u_char *bp, u_int len) { uint32_t mask, origin; u_int metric, done; u_int i, width; while (len > 0) { if (len < 3) { ND_PRINT(" [length %u < 3]", len); goto invalid; } mask = (uint32_t)0xff << 24 | GET_U_1(bp) << 16 | GET_U_1(bp + 1) << 8 | GET_U_1(bp + 2); width = 1; if (GET_U_1(bp)) width = 2; if (GET_U_1(bp + 1)) width = 3; if (GET_U_1(bp + 2)) width = 4; ND_PRINT("\n\tMask %s", intoa(htonl(mask))); bp += 3; len -= 3; do { if (len < width + 1) { ND_PRINT("\n\t [Truncated Report]"); goto invalid; } origin = 0; for (i = 0; i < width; ++i) { origin = origin << 8 | GET_U_1(bp); bp++; } for ( ; i < 4; ++i) origin <<= 8; metric = GET_U_1(bp); bp++; done = metric & 0x80; metric &= 0x7f; ND_PRINT("\n\t %s metric %u", intoa(htonl(origin)), metric); len -= width + 1; } while (!done); } return; invalid: nd_print_invalid(ndo); } static void print_probe(netdissect_options *ndo, const u_char *bp, u_int len) { if (len < 4) { ND_PRINT(" [full length %u < 4]", len); goto invalid; } ND_PRINT(ndo->ndo_vflag > 1 ? "\n\t" : " "); ND_PRINT("genid %u", GET_BE_U_4(bp)); if (ndo->ndo_vflag < 2) return; bp += 4; len -= 4; while (len > 0) { if (len < 4) { ND_PRINT("[remaining length %u < 4]", len); goto invalid; } ND_PRINT("\n\tneighbor %s", GET_IPADDR_STRING(bp)); bp += 4; len -= 4; } return; invalid: nd_print_invalid(ndo); } static void print_neighbors(netdissect_options *ndo, const u_char *bp, u_int len) { const u_char *laddr; u_char metric; u_char thresh; int ncount; while (len > 0) { if (len < 7) { ND_PRINT(" [length %u < 7]", len); goto invalid; } laddr = bp; bp += 4; metric = GET_U_1(bp); bp++; thresh = GET_U_1(bp); bp++; ncount = GET_U_1(bp); bp++; len -= 7; while (--ncount >= 0) { if (len < 4) { ND_PRINT(" [length %u < 4]", len); goto invalid; } ND_PRINT(" [%s ->", GET_IPADDR_STRING(laddr)); ND_PRINT(" %s, (%u/%u)]", GET_IPADDR_STRING(bp), metric, thresh); bp += 4; len -= 4; } } return; invalid: nd_print_invalid(ndo); } static void print_neighbors2(netdissect_options *ndo, const u_char *bp, u_int len, uint8_t major_version, uint8_t minor_version) { const u_char *laddr; u_char metric, thresh, flags; int ncount; ND_PRINT(" (v %u.%u):", major_version, minor_version); while (len > 0) { if (len < 8) { ND_PRINT(" [length %u < 8]", len); goto invalid; } laddr = bp; bp += 4; metric = GET_U_1(bp); bp++; thresh = GET_U_1(bp); bp++; flags = GET_U_1(bp); bp++; ncount = GET_U_1(bp); bp++; len -= 8; while (--ncount >= 0 && len > 0) { if (len < 4) { ND_PRINT(" [length %u < 4]", len); goto invalid; } ND_PRINT(" [%s -> ", GET_IPADDR_STRING(laddr)); ND_PRINT("%s (%u/%u", GET_IPADDR_STRING(bp), metric, thresh); if (flags & DVMRP_NF_TUNNEL) ND_PRINT("/tunnel"); if (flags & DVMRP_NF_SRCRT) ND_PRINT("/srcrt"); if (flags & DVMRP_NF_QUERIER) ND_PRINT("/querier"); if (flags & DVMRP_NF_DISABLED) ND_PRINT("/disabled"); if (flags & DVMRP_NF_DOWN) ND_PRINT("/down"); ND_PRINT(")]"); bp += 4; len -= 4; } if (ncount != -1) { ND_PRINT(" [invalid ncount]"); goto invalid; } } return; invalid: nd_print_invalid(ndo); } tcpdump-4.99.1/addrtostr.c0000644000026300017510000001320414057477727013613 0ustar mcrmcr/* * Copyright (c) 1999 Kungliga Tekniska Högskolan * (Royal Institute of Technology, Stockholm, Sweden). * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Kungliga Tekniska * Högskolan and its contributors. * * 4. Neither the name of the Institute 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 BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "addrtostr.h" #include #include /* * */ #ifndef IN6ADDRSZ #define IN6ADDRSZ 16 /* IPv6 T_AAAA */ #endif #ifndef INT16SZ #define INT16SZ 2 /* word size */ #endif const char * addrtostr (const void *src, char *dst, size_t size) { const u_char *srcaddr = (const u_char *)src; const char digits[] = "0123456789"; int i; const char *orig_dst = dst; if (size < INET_ADDRSTRLEN) { errno = ENOSPC; return NULL; } for (i = 0; i < 4; ++i) { int n = *srcaddr++; int non_zerop = 0; if (non_zerop || n / 100 > 0) { *dst++ = digits[n / 100]; n %= 100; non_zerop = 1; } if (non_zerop || n / 10 > 0) { *dst++ = digits[n / 10]; n %= 10; non_zerop = 1; } *dst++ = digits[n]; if (i != 3) *dst++ = '.'; } *dst++ = '\0'; return orig_dst; } /* * Convert IPv6 binary address into presentation (printable) format. */ const char * addrtostr6 (const void *src, char *dst, size_t size) { /* * Note that int32_t and int16_t need only be "at least" large enough * to contain a value of the specified size. On some systems, like * Crays, there is no such thing as an integer variable with 16 bits. * Keep this in mind if you think this function should have been coded * to use pointer overlays. All the world's not a VAX. */ const u_char *srcaddr = (const u_char *)src; char *dp; size_t space_left, added_space; int snprintfed; struct { int base; int len; } best, cur; uint16_t words [IN6ADDRSZ / INT16SZ]; int i; /* Preprocess: * Copy the input (bytewise) array into a wordwise array. * Find the longest run of 0x00's in src[] for :: shorthanding. */ for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) words[i] = (srcaddr[2*i] << 8) | srcaddr[2*i + 1]; best.len = 0; best.base = -1; cur.len = 0; cur.base = -1; for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { if (words[i] == 0) { if (cur.base == -1) cur.base = i, cur.len = 1; else cur.len++; } else if (cur.base != -1) { if (best.base == -1 || cur.len > best.len) best = cur; cur.base = -1; } } if ((cur.base != -1) && (best.base == -1 || cur.len > best.len)) best = cur; if (best.base != -1 && best.len < 2) best.base = -1; /* Format the result. */ dp = dst; space_left = size; #define APPEND_CHAR(c) \ { \ if (space_left == 0) { \ errno = ENOSPC; \ return (NULL); \ } \ *dp++ = c; \ space_left--; \ } for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { /* Are we inside the best run of 0x00's? */ if (best.base != -1 && i >= best.base && i < (best.base + best.len)) { if (i == best.base) APPEND_CHAR(':'); continue; } /* Are we following an initial run of 0x00s or any real hex? */ if (i != 0) APPEND_CHAR(':'); /* Is this address an encapsulated IPv4? */ if (i == 6 && best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { if (!addrtostr(srcaddr+12, dp, space_left)) { errno = ENOSPC; return (NULL); } added_space = strlen(dp); dp += added_space; space_left -= added_space; break; } snprintfed = snprintf (dp, space_left, "%x", words[i]); if (snprintfed < 0) return (NULL); if ((size_t) snprintfed >= space_left) { errno = ENOSPC; return (NULL); } dp += snprintfed; space_left -= snprintfed; } /* Was it a trailing run of 0x00's? */ if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) APPEND_CHAR(':'); APPEND_CHAR('\0'); return (dst); } tcpdump-4.99.1/print-ospf6.c0000644000026300017510000007125714057477727014010 0ustar mcrmcr/* * Copyright (c) 1992, 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. * * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu) */ /* \summary: IPv6 Open Shortest Path First (OSPFv3) printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include #include "netdissect.h" #include "addrtoname.h" #include "extract.h" #include "ospf.h" #define OSPF_TYPE_HELLO 1 /* Hello */ #define OSPF_TYPE_DD 2 /* Database Description */ #define OSPF_TYPE_LS_REQ 3 /* Link State Request */ #define OSPF_TYPE_LS_UPDATE 4 /* Link State Update */ #define OSPF_TYPE_LS_ACK 5 /* Link State Ack */ /* Options *_options */ #define OSPF6_OPTION_V6 0x01 /* V6 bit: A bit for peeping tom */ #define OSPF6_OPTION_E 0x02 /* E bit: External routes advertised */ #define OSPF6_OPTION_MC 0x04 /* MC bit: Multicast capable */ #define OSPF6_OPTION_N 0x08 /* N bit: For type-7 LSA */ #define OSPF6_OPTION_R 0x10 /* R bit: Router bit */ #define OSPF6_OPTION_DC 0x20 /* DC bit: Demand circuits */ /* The field is actually 24-bit (RFC5340 Section A.2). */ #define OSPF6_OPTION_AF 0x0100 /* AF bit: Multiple address families */ #define OSPF6_OPTION_L 0x0200 /* L bit: Link-local signaling (LLS) */ #define OSPF6_OPTION_AT 0x0400 /* AT bit: Authentication trailer */ /* db_flags */ #define OSPF6_DB_INIT 0x04 /* */ #define OSPF6_DB_MORE 0x02 #define OSPF6_DB_MASTER 0x01 #define OSPF6_DB_M6 0x10 /* IPv6 MTU */ /* ls_type */ #define LS_TYPE_ROUTER 1 /* router link */ #define LS_TYPE_NETWORK 2 /* network link */ #define LS_TYPE_INTER_AP 3 /* Inter-Area-Prefix */ #define LS_TYPE_INTER_AR 4 /* Inter-Area-Router */ #define LS_TYPE_ASE 5 /* ASE */ #define LS_TYPE_GROUP 6 /* Group membership */ #define LS_TYPE_NSSA 7 /* NSSA */ #define LS_TYPE_LINK 8 /* Link LSA */ #define LS_TYPE_INTRA_AP 9 /* Intra-Area-Prefix */ #define LS_TYPE_INTRA_ATE 10 /* Intra-Area-TE */ #define LS_TYPE_GRACE 11 /* Grace LSA */ #define LS_TYPE_RI 12 /* Router information */ #define LS_TYPE_INTER_ASTE 13 /* Inter-AS-TE */ #define LS_TYPE_L1VPN 14 /* L1VPN */ #define LS_TYPE_MASK 0x1fff #define LS_SCOPE_LINKLOCAL 0x0000 #define LS_SCOPE_AREA 0x2000 #define LS_SCOPE_AS 0x4000 #define LS_SCOPE_MASK 0x6000 #define LS_SCOPE_U 0x8000 /* rla_link.link_type */ #define RLA_TYPE_ROUTER 1 /* point-to-point to another router */ #define RLA_TYPE_TRANSIT 2 /* connection to transit network */ #define RLA_TYPE_VIRTUAL 4 /* virtual link */ /* rla_flags */ #define RLA_FLAG_B 0x01 #define RLA_FLAG_E 0x02 #define RLA_FLAG_V 0x04 #define RLA_FLAG_W 0x08 #define RLA_FLAG_Nt 0x10 /* lsa_prefix options */ #define LSA_PREFIX_OPT_NU 0x01 #define LSA_PREFIX_OPT_LA 0x02 #define LSA_PREFIX_OPT_MC 0x04 #define LSA_PREFIX_OPT_P 0x08 #define LSA_PREFIX_OPT_DN 0x10 #define LSA_PREFIX_OPT_N 0x20 /* sla_tosmetric breakdown */ #define SLA_MASK_TOS 0x7f000000 #define SLA_MASK_METRIC 0x00ffffff #define SLA_SHIFT_TOS 24 /* asla_metric */ #define ASLA_FLAG_FWDADDR 0x02000000 #define ASLA_FLAG_ROUTETAG 0x01000000 #define ASLA_MASK_METRIC 0x00ffffff /* RFC6506 Section 4.1 */ #define OSPF6_AT_HDRLEN 16U #define OSPF6_AUTH_TYPE_HMAC 0x0001 typedef nd_uint32_t rtrid_t; /* link state advertisement header */ struct lsa6_hdr { nd_uint16_t ls_age; nd_uint16_t ls_type; rtrid_t ls_stateid; rtrid_t ls_router; nd_uint32_t ls_seq; nd_uint16_t ls_chksum; nd_uint16_t ls_length; }; /* Length of an IPv6 address, in bytes. */ #define IPV6_ADDR_LEN_BYTES (128/8) struct lsa6_prefix { nd_uint8_t lsa_p_len; nd_uint8_t lsa_p_opt; nd_uint16_t lsa_p_metric; nd_byte lsa_p_prefix[IPV6_ADDR_LEN_BYTES]; /* maximum length */ }; /* link state advertisement */ struct lsa6 { struct lsa6_hdr ls_hdr; /* Link state types */ union { /* Router links advertisements */ struct { union { nd_uint8_t flg; nd_uint32_t opt; } rla_flgandopt; #define rla_flags rla_flgandopt.flg #define rla_options rla_flgandopt.opt struct rlalink6 { nd_uint8_t link_type; nd_byte link_zero; nd_uint16_t link_metric; nd_uint32_t link_ifid; nd_uint32_t link_nifid; rtrid_t link_nrtid; } rla_link[1]; /* may repeat */ } un_rla; /* Network links advertisements */ struct { nd_uint32_t nla_options; rtrid_t nla_router[1]; /* may repeat */ } un_nla; /* Inter Area Prefix LSA */ struct { nd_uint32_t inter_ap_metric; struct lsa6_prefix inter_ap_prefix[1]; } un_inter_ap; /* AS external links advertisements */ struct { nd_uint32_t asla_metric; struct lsa6_prefix asla_prefix[1]; /* some optional fields follow */ } un_asla; #if 0 /* Summary links advertisements */ struct { nd_ipv4 sla_mask; nd_uint32_t sla_tosmetric[1]; /* may repeat */ } un_sla; /* Multicast group membership */ struct mcla { nd_uint32_t mcla_vtype; nd_ipv4 mcla_vid; } un_mcla[1]; #endif /* Type 7 LSA */ /* Link LSA */ struct llsa { union { nd_uint8_t pri; nd_uint32_t opt; } llsa_priandopt; #define llsa_priority llsa_priandopt.pri #define llsa_options llsa_priandopt.opt nd_ipv6 llsa_lladdr; nd_uint32_t llsa_nprefix; struct lsa6_prefix llsa_prefix[1]; } un_llsa; /* Intra-Area-Prefix */ struct { nd_uint16_t intra_ap_nprefix; nd_uint16_t intra_ap_lstype; rtrid_t intra_ap_lsid; rtrid_t intra_ap_rtid; struct lsa6_prefix intra_ap_prefix[1]; } un_intra_ap; } lsa_un; }; /* * the main header */ struct ospf6hdr { nd_uint8_t ospf6_version; nd_uint8_t ospf6_type; nd_uint16_t ospf6_len; rtrid_t ospf6_routerid; rtrid_t ospf6_areaid; nd_uint16_t ospf6_chksum; nd_uint8_t ospf6_instanceid; nd_uint8_t ospf6_rsvd; }; /* * The OSPF6 header length is 16 bytes, regardless of how your compiler * might choose to pad the above structure. */ #define OSPF6HDR_LEN 16 /* Hello packet */ struct hello6 { nd_uint32_t hello_ifid; union { nd_uint8_t pri; nd_uint32_t opt; } hello_priandopt; #define hello_priority hello_priandopt.pri #define hello_options hello_priandopt.opt nd_uint16_t hello_helloint; nd_uint16_t hello_deadint; rtrid_t hello_dr; rtrid_t hello_bdr; rtrid_t hello_neighbor[1]; /* may repeat */ }; /* Database Description packet */ struct dd6 { nd_uint32_t db_options; nd_uint16_t db_mtu; nd_uint8_t db_mbz; nd_uint8_t db_flags; nd_uint32_t db_seq; struct lsa6_hdr db_lshdr[1]; /* may repeat */ }; /* Link State Request */ struct lsr6 { nd_uint16_t ls_mbz; nd_uint16_t ls_type; rtrid_t ls_stateid; rtrid_t ls_router; }; /* Link State Update */ struct lsu6 { nd_uint32_t lsu_count; struct lsa6 lsu_lsa[1]; /* may repeat */ }; static const struct tok ospf6_option_values[] = { { OSPF6_OPTION_V6, "V6" }, { OSPF6_OPTION_E, "External" }, { OSPF6_OPTION_MC, "Deprecated" }, { OSPF6_OPTION_N, "NSSA" }, { OSPF6_OPTION_R, "Router" }, { OSPF6_OPTION_DC, "Demand Circuit" }, { OSPF6_OPTION_AF, "AFs Support" }, { OSPF6_OPTION_L, "LLS" }, { OSPF6_OPTION_AT, "Authentication Trailer" }, { 0, NULL } }; static const struct tok ospf6_rla_flag_values[] = { { RLA_FLAG_B, "ABR" }, { RLA_FLAG_E, "External" }, { RLA_FLAG_V, "Virtual-Link Endpoint" }, { RLA_FLAG_W, "Deprecated" }, { RLA_FLAG_Nt, "NSSA Translator" }, { 0, NULL } }; static const struct tok ospf6_asla_flag_values[] = { { ASLA_FLAG_EXTERNAL, "External Type 2" }, { ASLA_FLAG_FWDADDR, "Forwarding" }, { ASLA_FLAG_ROUTETAG, "Tag" }, { 0, NULL } }; static const struct tok ospf6_type_values[] = { { OSPF_TYPE_HELLO, "Hello" }, { OSPF_TYPE_DD, "Database Description" }, { OSPF_TYPE_LS_REQ, "LS-Request" }, { OSPF_TYPE_LS_UPDATE, "LS-Update" }, { OSPF_TYPE_LS_ACK, "LS-Ack" }, { 0, NULL } }; static const struct tok ospf6_lsa_values[] = { { LS_TYPE_ROUTER, "Router" }, { LS_TYPE_NETWORK, "Network" }, { LS_TYPE_INTER_AP, "Inter-Area Prefix" }, { LS_TYPE_INTER_AR, "Inter-Area Router" }, { LS_TYPE_ASE, "External" }, { LS_TYPE_GROUP, "Deprecated" }, { LS_TYPE_NSSA, "NSSA" }, { LS_TYPE_LINK, "Link" }, { LS_TYPE_INTRA_AP, "Intra-Area Prefix" }, { LS_TYPE_INTRA_ATE, "Intra-Area TE" }, { LS_TYPE_GRACE, "Grace" }, { LS_TYPE_RI, "Router Information" }, { LS_TYPE_INTER_ASTE, "Inter-AS-TE" }, { LS_TYPE_L1VPN, "Layer 1 VPN" }, { 0, NULL } }; static const struct tok ospf6_ls_scope_values[] = { { LS_SCOPE_LINKLOCAL, "Link Local" }, { LS_SCOPE_AREA, "Area Local" }, { LS_SCOPE_AS, "Domain Wide" }, { 0, NULL } }; static const struct tok ospf6_dd_flag_values[] = { { OSPF6_DB_INIT, "Init" }, { OSPF6_DB_MORE, "More" }, { OSPF6_DB_MASTER, "Master" }, { OSPF6_DB_M6, "IPv6 MTU" }, { 0, NULL } }; static const struct tok ospf6_lsa_prefix_option_values[] = { { LSA_PREFIX_OPT_NU, "No Unicast" }, { LSA_PREFIX_OPT_LA, "Local address" }, { LSA_PREFIX_OPT_MC, "Deprecated" }, { LSA_PREFIX_OPT_P, "Propagate" }, { LSA_PREFIX_OPT_DN, "Down" }, { LSA_PREFIX_OPT_N, "N-bit" }, { 0, NULL } }; static const struct tok ospf6_auth_type_str[] = { { OSPF6_AUTH_TYPE_HMAC, "HMAC" }, { 0, NULL } }; static void ospf6_print_ls_type(netdissect_options *ndo, u_int ls_type, const rtrid_t *ls_stateid) { ND_PRINT("\n\t %s LSA (%u), %s Scope%s, LSA-ID %s", tok2str(ospf6_lsa_values, "Unknown", ls_type & LS_TYPE_MASK), ls_type & LS_TYPE_MASK, tok2str(ospf6_ls_scope_values, "Unknown", ls_type & LS_SCOPE_MASK), ls_type &0x8000 ? ", transitive" : "", /* U-bit */ GET_IPADDR_STRING((const u_char *)ls_stateid)); } static int ospf6_print_lshdr(netdissect_options *ndo, const struct lsa6_hdr *lshp, const u_char *dataend) { if ((const u_char *)(lshp + 1) > dataend) goto trunc; ND_PRINT("\n\t Advertising Router %s, seq 0x%08x, age %us, length %zu", GET_IPADDR_STRING(lshp->ls_router), GET_BE_U_4(lshp->ls_seq), GET_BE_U_2(lshp->ls_age), GET_BE_U_2(lshp->ls_length)-sizeof(struct lsa6_hdr)); ospf6_print_ls_type(ndo, GET_BE_U_2(lshp->ls_type), &lshp->ls_stateid); return (0); trunc: return (1); } static int ospf6_print_lsaprefix(netdissect_options *ndo, const uint8_t *tptr, u_int lsa_length) { const struct lsa6_prefix *lsapp = (const struct lsa6_prefix *)tptr; u_int wordlen; nd_ipv6 prefix; if (lsa_length < sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES) goto trunc; lsa_length -= sizeof (*lsapp) - IPV6_ADDR_LEN_BYTES; ND_TCHECK_LEN(lsapp, sizeof(*lsapp) - IPV6_ADDR_LEN_BYTES); wordlen = (GET_U_1(lsapp->lsa_p_len) + 31) / 32; if (wordlen * 4 > sizeof(nd_ipv6)) { ND_PRINT(" bogus prefixlen /%u", GET_U_1(lsapp->lsa_p_len)); goto trunc; } if (lsa_length < wordlen * 4) goto trunc; lsa_length -= wordlen * 4; memset(prefix, 0, sizeof(prefix)); GET_CPY_BYTES(prefix, lsapp->lsa_p_prefix, wordlen * 4); ND_PRINT("\n\t\t%s/%u", ip6addr_string(ndo, prefix), /* local buffer, not packet data; don't use GET_IP6ADDR_STRING() */ GET_U_1(lsapp->lsa_p_len)); if (GET_U_1(lsapp->lsa_p_opt)) { ND_PRINT(", Options [%s]", bittok2str(ospf6_lsa_prefix_option_values, "none", GET_U_1(lsapp->lsa_p_opt))); } ND_PRINT(", metric %u", GET_BE_U_2(lsapp->lsa_p_metric)); return sizeof(*lsapp) - IPV6_ADDR_LEN_BYTES + wordlen * 4; trunc: return -1; } /* * Print a single link state advertisement. If truncated return 1, else 0. */ static int ospf6_print_lsa(netdissect_options *ndo, const struct lsa6 *lsap, const u_char *dataend) { const struct rlalink6 *rlp; #if 0 const struct tos_metric *tosp; #endif const rtrid_t *ap; #if 0 const struct aslametric *almp; const struct mcla *mcp; #endif const struct llsa *llsap; const struct lsa6_prefix *lsapp; #if 0 const uint32_t *lp; #endif u_int prefixes; int bytelen; u_int length, lsa_length; uint32_t flags32; const uint8_t *tptr; if (ospf6_print_lshdr(ndo, &lsap->ls_hdr, dataend)) return (1); length = GET_BE_U_2(lsap->ls_hdr.ls_length); /* * The LSA length includes the length of the header; * it must have a value that's at least that length. * If it does, find the length of what follows the * header. */ if (length < sizeof(struct lsa6_hdr) || (const u_char *)lsap + length > dataend) return (1); lsa_length = length - sizeof(struct lsa6_hdr); tptr = (const uint8_t *)lsap+sizeof(struct lsa6_hdr); switch (GET_BE_U_2(lsap->ls_hdr.ls_type)) { case LS_TYPE_ROUTER | LS_SCOPE_AREA: if (lsa_length < sizeof (lsap->lsa_un.un_rla.rla_options)) return (1); lsa_length -= sizeof (lsap->lsa_un.un_rla.rla_options); ND_PRINT("\n\t Options [%s]", bittok2str(ospf6_option_values, "none", GET_BE_U_4(lsap->lsa_un.un_rla.rla_options))); ND_PRINT(", RLA-Flags [%s]", bittok2str(ospf6_rla_flag_values, "none", GET_U_1(lsap->lsa_un.un_rla.rla_flags))); rlp = lsap->lsa_un.un_rla.rla_link; while (lsa_length != 0) { if (lsa_length < sizeof (*rlp)) return (1); lsa_length -= sizeof (*rlp); ND_TCHECK_SIZE(rlp); switch (GET_U_1(rlp->link_type)) { case RLA_TYPE_VIRTUAL: ND_PRINT("\n\t Virtual Link: Neighbor Router-ID %s" "\n\t Neighbor Interface-ID %s, Interface %s", GET_IPADDR_STRING(rlp->link_nrtid), GET_IPADDR_STRING(rlp->link_nifid), GET_IPADDR_STRING(rlp->link_ifid)); break; case RLA_TYPE_ROUTER: ND_PRINT("\n\t Neighbor Router-ID %s" "\n\t Neighbor Interface-ID %s, Interface %s", GET_IPADDR_STRING(rlp->link_nrtid), GET_IPADDR_STRING(rlp->link_nifid), GET_IPADDR_STRING(rlp->link_ifid)); break; case RLA_TYPE_TRANSIT: ND_PRINT("\n\t Neighbor Network-ID %s" "\n\t Neighbor Interface-ID %s, Interface %s", GET_IPADDR_STRING(rlp->link_nrtid), GET_IPADDR_STRING(rlp->link_nifid), GET_IPADDR_STRING(rlp->link_ifid)); break; default: ND_PRINT("\n\t Unknown Router Links Type 0x%02x", GET_U_1(rlp->link_type)); return (0); } ND_PRINT(", metric %u", GET_BE_U_2(rlp->link_metric)); rlp++; } break; case LS_TYPE_NETWORK | LS_SCOPE_AREA: if (lsa_length < sizeof (lsap->lsa_un.un_nla.nla_options)) return (1); lsa_length -= sizeof (lsap->lsa_un.un_nla.nla_options); ND_PRINT("\n\t Options [%s]", bittok2str(ospf6_option_values, "none", GET_BE_U_4(lsap->lsa_un.un_nla.nla_options))); ND_PRINT("\n\t Connected Routers:"); ap = lsap->lsa_un.un_nla.nla_router; while (lsa_length != 0) { if (lsa_length < sizeof (*ap)) return (1); lsa_length -= sizeof (*ap); ND_TCHECK_SIZE(ap); ND_PRINT("\n\t\t%s", GET_IPADDR_STRING(*ap)); ++ap; } break; case LS_TYPE_INTER_AP | LS_SCOPE_AREA: if (lsa_length < sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric)) return (1); lsa_length -= sizeof (lsap->lsa_un.un_inter_ap.inter_ap_metric); ND_PRINT(", metric %u", GET_BE_U_4(lsap->lsa_un.un_inter_ap.inter_ap_metric) & SLA_MASK_METRIC); tptr = (const uint8_t *)lsap->lsa_un.un_inter_ap.inter_ap_prefix; while (lsa_length != 0) { bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length); if (bytelen < 0) goto trunc; /* * ospf6_print_lsaprefix() will return -1 if * the length is too high, so this will not * underflow. */ lsa_length -= bytelen; tptr += bytelen; } break; case LS_TYPE_ASE | LS_SCOPE_AS: if (lsa_length < sizeof (lsap->lsa_un.un_asla.asla_metric)) return (1); lsa_length -= sizeof (lsap->lsa_un.un_asla.asla_metric); flags32 = GET_BE_U_4(lsap->lsa_un.un_asla.asla_metric); ND_PRINT("\n\t Flags [%s]", bittok2str(ospf6_asla_flag_values, "none", flags32)); ND_PRINT(" metric %u", GET_BE_U_4(lsap->lsa_un.un_asla.asla_metric) & ASLA_MASK_METRIC); tptr = (const uint8_t *)lsap->lsa_un.un_asla.asla_prefix; lsapp = (const struct lsa6_prefix *)tptr; bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length); if (bytelen < 0) goto trunc; /* * ospf6_print_lsaprefix() will return -1 if * the length is too high, so this will not * underflow. */ lsa_length -= bytelen; tptr += bytelen; if ((flags32 & ASLA_FLAG_FWDADDR) != 0) { if (lsa_length < sizeof (nd_ipv6)) return (1); lsa_length -= sizeof (nd_ipv6); ND_PRINT(" forward %s", GET_IP6ADDR_STRING(tptr)); tptr += sizeof(nd_ipv6); } if ((flags32 & ASLA_FLAG_ROUTETAG) != 0) { if (lsa_length < sizeof (uint32_t)) return (1); lsa_length -= sizeof (uint32_t); ND_PRINT(" tag %s", GET_IPADDR_STRING(tptr)); tptr += sizeof(uint32_t); } if (GET_U_1(lsapp->lsa_p_metric)) { if (lsa_length < sizeof (uint32_t)) return (1); lsa_length -= sizeof (uint32_t); ND_PRINT(" RefLSID: %s", GET_IPADDR_STRING(tptr)); tptr += sizeof(uint32_t); } break; case LS_TYPE_LINK: /* Link LSA */ llsap = &lsap->lsa_un.un_llsa; if (lsa_length < sizeof (llsap->llsa_priandopt)) return (1); lsa_length -= sizeof (llsap->llsa_priandopt); ND_TCHECK_SIZE(&llsap->llsa_priandopt); ND_PRINT("\n\t Options [%s]", bittok2str(ospf6_option_values, "none", GET_BE_U_4(llsap->llsa_options))); if (lsa_length < sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix)) return (1); lsa_length -= sizeof (llsap->llsa_lladdr) + sizeof (llsap->llsa_nprefix); prefixes = GET_BE_U_4(llsap->llsa_nprefix); ND_PRINT("\n\t Priority %u, Link-local address %s, Prefixes %u:", GET_U_1(llsap->llsa_priority), GET_IP6ADDR_STRING(llsap->llsa_lladdr), prefixes); tptr = (const uint8_t *)llsap->llsa_prefix; while (prefixes > 0) { bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length); if (bytelen < 0) goto trunc; prefixes--; /* * ospf6_print_lsaprefix() will return -1 if * the length is too high, so this will not * underflow. */ lsa_length -= bytelen; tptr += bytelen; } break; case LS_TYPE_INTRA_AP | LS_SCOPE_AREA: /* Intra-Area-Prefix LSA */ if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid)) return (1); lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_rtid); ND_TCHECK_4(lsap->lsa_un.un_intra_ap.intra_ap_rtid); ospf6_print_ls_type(ndo, GET_BE_U_2(lsap->lsa_un.un_intra_ap.intra_ap_lstype), &lsap->lsa_un.un_intra_ap.intra_ap_lsid); if (lsa_length < sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix)) return (1); lsa_length -= sizeof (lsap->lsa_un.un_intra_ap.intra_ap_nprefix); prefixes = GET_BE_U_2(lsap->lsa_un.un_intra_ap.intra_ap_nprefix); ND_PRINT("\n\t Prefixes %u:", prefixes); tptr = (const uint8_t *)lsap->lsa_un.un_intra_ap.intra_ap_prefix; while (prefixes > 0) { bytelen = ospf6_print_lsaprefix(ndo, tptr, lsa_length); if (bytelen < 0) goto trunc; prefixes--; /* * ospf6_print_lsaprefix() will return -1 if * the length is too high, so this will not * underflow. */ lsa_length -= bytelen; tptr += bytelen; } break; case LS_TYPE_GRACE | LS_SCOPE_LINKLOCAL: if (ospf_grace_lsa_print(ndo, tptr, lsa_length) == -1) { return 1; } break; case LS_TYPE_INTRA_ATE | LS_SCOPE_LINKLOCAL: if (ospf_te_lsa_print(ndo, tptr, lsa_length) == -1) { return 1; } break; default: if(!print_unknown_data(ndo,tptr, "\n\t ", lsa_length)) { return (1); } break; } return (0); trunc: return (1); } static int ospf6_decode_v3(netdissect_options *ndo, const struct ospf6hdr *op, const u_char *dataend) { const rtrid_t *ap; const struct lsr6 *lsrp; const struct lsa6_hdr *lshp; const struct lsa6 *lsap; int i; switch (GET_U_1(op->ospf6_type)) { case OSPF_TYPE_HELLO: { const struct hello6 *hellop = (const struct hello6 *)((const uint8_t *)op + OSPF6HDR_LEN); ND_PRINT("\n\tOptions [%s]", bittok2str(ospf6_option_values, "none", GET_BE_U_4(hellop->hello_options))); ND_PRINT("\n\t Hello Timer %us, Dead Timer %us, Interface-ID %s, Priority %u", GET_BE_U_2(hellop->hello_helloint), GET_BE_U_2(hellop->hello_deadint), GET_IPADDR_STRING(hellop->hello_ifid), GET_U_1(hellop->hello_priority)); if (GET_BE_U_4(hellop->hello_dr) != 0) ND_PRINT("\n\t Designated Router %s", GET_IPADDR_STRING(hellop->hello_dr)); if (GET_BE_U_4(hellop->hello_bdr) != 0) ND_PRINT(", Backup Designated Router %s", GET_IPADDR_STRING(hellop->hello_bdr)); if (ndo->ndo_vflag > 1) { ND_PRINT("\n\t Neighbor List:"); ap = hellop->hello_neighbor; while ((const u_char *)ap < dataend) { ND_TCHECK_SIZE(ap); ND_PRINT("\n\t %s", GET_IPADDR_STRING(*ap)); ++ap; } } break; /* HELLO */ } case OSPF_TYPE_DD: { const struct dd6 *ddp = (const struct dd6 *)((const uint8_t *)op + OSPF6HDR_LEN); ND_PRINT("\n\tOptions [%s]", bittok2str(ospf6_option_values, "none", GET_BE_U_4(ddp->db_options))); ND_PRINT(", DD Flags [%s]", bittok2str(ospf6_dd_flag_values,"none",GET_U_1(ddp->db_flags))); ND_PRINT(", MTU %u, DD-Sequence 0x%08x", GET_BE_U_2(ddp->db_mtu), GET_BE_U_4(ddp->db_seq)); if (ndo->ndo_vflag > 1) { /* Print all the LS adv's */ lshp = ddp->db_lshdr; while ((const u_char *)lshp < dataend) { if (ospf6_print_lshdr(ndo, lshp++, dataend)) goto trunc; } } break; } case OSPF_TYPE_LS_REQ: if (ndo->ndo_vflag > 1) { lsrp = (const struct lsr6 *)((const uint8_t *)op + OSPF6HDR_LEN); while ((const u_char *)lsrp < dataend) { ND_TCHECK_SIZE(lsrp); ND_PRINT("\n\t Advertising Router %s", GET_IPADDR_STRING(lsrp->ls_router)); ospf6_print_ls_type(ndo, GET_BE_U_2(lsrp->ls_type), &lsrp->ls_stateid); ++lsrp; } } break; case OSPF_TYPE_LS_UPDATE: if (ndo->ndo_vflag > 1) { const struct lsu6 *lsup = (const struct lsu6 *)((const uint8_t *)op + OSPF6HDR_LEN); i = GET_BE_U_4(lsup->lsu_count); lsap = lsup->lsu_lsa; while ((const u_char *)lsap < dataend && i--) { if (ospf6_print_lsa(ndo, lsap, dataend)) goto trunc; lsap = (const struct lsa6 *)((const u_char *)lsap + GET_BE_U_2(lsap->ls_hdr.ls_length)); } } break; case OSPF_TYPE_LS_ACK: if (ndo->ndo_vflag > 1) { lshp = (const struct lsa6_hdr *)((const uint8_t *)op + OSPF6HDR_LEN); while ((const u_char *)lshp < dataend) { if (ospf6_print_lshdr(ndo, lshp++, dataend)) goto trunc; } } break; default: break; } return (0); trunc: return (1); } /* RFC5613 Section 2.2 (w/o the TLVs) */ static int ospf6_print_lls(netdissect_options *ndo, const u_char *cp, const u_int len) { uint16_t llsdatalen; if (len == 0) return 0; if (len < OSPF_LLS_HDRLEN) goto trunc; /* Checksum */ ND_PRINT("\n\tLLS Checksum 0x%04x", GET_BE_U_2(cp)); cp += 2; /* LLS Data Length */ llsdatalen = GET_BE_U_2(cp); ND_PRINT(", Data Length %u", llsdatalen); if (llsdatalen < OSPF_LLS_HDRLEN || llsdatalen > len) goto trunc; cp += 2; /* LLS TLVs */ ND_TCHECK_LEN(cp, llsdatalen - OSPF_LLS_HDRLEN); /* FIXME: code in print-ospf.c can be reused to decode the TLVs */ return llsdatalen; trunc: return -1; } /* RFC6506 Section 4.1 */ static int ospf6_decode_at(netdissect_options *ndo, const u_char *cp, const u_int len) { uint16_t authdatalen; if (len == 0) return 0; if (len < OSPF6_AT_HDRLEN) goto trunc; /* Authentication Type */ ND_PRINT("\n\tAuthentication Type %s", tok2str(ospf6_auth_type_str, "unknown (0x%04x)", GET_BE_U_2(cp))); cp += 2; /* Auth Data Len */ authdatalen = GET_BE_U_2(cp); ND_PRINT(", Length %u", authdatalen); if (authdatalen < OSPF6_AT_HDRLEN || authdatalen > len) goto trunc; cp += 2; /* Reserved */ cp += 2; /* Security Association ID */ ND_PRINT(", SAID %u", GET_BE_U_2(cp)); cp += 2; /* Cryptographic Sequence Number (High-Order 32 Bits) */ ND_PRINT(", CSN 0x%08x", GET_BE_U_4(cp)); cp += 4; /* Cryptographic Sequence Number (Low-Order 32 Bits) */ ND_PRINT(":%08x", GET_BE_U_4(cp)); cp += 4; /* Authentication Data */ ND_TCHECK_LEN(cp, authdatalen - OSPF6_AT_HDRLEN); if (ndo->ndo_vflag > 1) print_unknown_data(ndo,cp, "\n\tAuthentication Data ", authdatalen - OSPF6_AT_HDRLEN); return 0; trunc: return 1; } /* The trailing data may include LLS and/or AT data (in this specific order). * LLS data may be present only in Hello and DBDesc packets with the L-bit set. * AT data may be present in Hello and DBDesc packets with the AT-bit set or in * any other packet type, thus decode the AT data regardless of the AT-bit. */ static int ospf6_decode_v3_trailer(netdissect_options *ndo, const struct ospf6hdr *op, const u_char *cp, const unsigned len) { uint8_t type; int llslen = 0; int lls_hello = 0; int lls_dd = 0; type = GET_U_1(op->ospf6_type); if (type == OSPF_TYPE_HELLO) { const struct hello6 *hellop = (const struct hello6 *)((const uint8_t *)op + OSPF6HDR_LEN); if (GET_BE_U_4(hellop->hello_options) & OSPF6_OPTION_L) lls_hello = 1; } else if (type == OSPF_TYPE_DD) { const struct dd6 *ddp = (const struct dd6 *)((const uint8_t *)op + OSPF6HDR_LEN); if (GET_BE_U_4(ddp->db_options) & OSPF6_OPTION_L) lls_dd = 1; } if ((lls_hello || lls_dd) && (llslen = ospf6_print_lls(ndo, cp, len)) < 0) goto trunc; return ospf6_decode_at(ndo, cp + llslen, len - llslen); trunc: return 1; } void ospf6_print(netdissect_options *ndo, const u_char *bp, u_int length) { const struct ospf6hdr *op; const u_char *dataend; const char *cp; uint16_t datalen; ndo->ndo_protocol = "ospf3"; op = (const struct ospf6hdr *)bp; /* If the type is valid translate it, or just print the type */ /* value. If it's not valid, say so and return */ cp = tok2str(ospf6_type_values, "unknown packet type (%u)", GET_U_1(op->ospf6_type)); ND_PRINT("OSPFv%u, %s, length %u", GET_U_1(op->ospf6_version), cp, length); if (*cp == 'u') { return; } if(!ndo->ndo_vflag) { /* non verbose - so lets bail out here */ return; } /* OSPFv3 data always comes first and optional trailing data may follow. */ datalen = GET_BE_U_2(op->ospf6_len); if (datalen > length) { ND_PRINT(" [len %u]", datalen); return; } dataend = bp + datalen; ND_PRINT("\n\tRouter-ID %s", GET_IPADDR_STRING(op->ospf6_routerid)); if (GET_BE_U_4(op->ospf6_areaid) != 0) ND_PRINT(", Area %s", GET_IPADDR_STRING(op->ospf6_areaid)); else ND_PRINT(", Backbone Area"); if (GET_U_1(op->ospf6_instanceid)) ND_PRINT(", Instance %u", GET_U_1(op->ospf6_instanceid)); /* Do rest according to version. */ switch (GET_U_1(op->ospf6_version)) { case 3: /* ospf version 3 */ if (ospf6_decode_v3(ndo, op, dataend) || ospf6_decode_v3_trailer(ndo, op, dataend, length - datalen)) goto trunc; break; } /* end switch on version */ return; trunc: nd_print_trunc(ndo); } tcpdump-4.99.1/cpack.h0000644000026300017510000000504514057477727012677 0ustar mcrmcr/*- * Copyright (c) 2003, 2004 David Young. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of David Young may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY DAVID YOUNG ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID * YOUNG BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY * OF SUCH DAMAGE. */ #ifndef ND_CPACK_H #define ND_CPACK_H #include "netdissect.h" struct cpack_state { const uint8_t *c_buf; const uint8_t *c_next; size_t c_len; }; int nd_cpack_init(struct cpack_state *, const uint8_t *, size_t); int nd_cpack_uint8(netdissect_options *, struct cpack_state *, uint8_t *); int nd_cpack_int8(netdissect_options *, struct cpack_state *, int8_t *); int nd_cpack_uint16(netdissect_options *, struct cpack_state *, uint16_t *); int nd_cpack_int16(netdissect_options *, struct cpack_state *, int16_t *); int nd_cpack_uint32(netdissect_options *, struct cpack_state *, uint32_t *); int nd_cpack_int32(netdissect_options *, struct cpack_state *, int32_t *); int nd_cpack_uint64(netdissect_options *, struct cpack_state *, uint64_t *); int nd_cpack_int64(netdissect_options *, struct cpack_state *, int64_t *); const uint8_t *nd_cpack_next_boundary(const uint8_t *buf, const uint8_t *p, size_t alignment); const uint8_t *nd_cpack_align_and_reserve(struct cpack_state *cs, size_t wordsize); extern int nd_cpack_advance(struct cpack_state *, const size_t); #endif /* ND_CPACK_H */ tcpdump-4.99.1/getservent.h0000644000026300017510000000521014057477727013776 0ustar mcrmcr/* * Copyright (c) 1983, 1993 The Regents of the University of California. * Copyright (c) 1993 Digital Equipment Corporation. * Copyright (c) 2012 G. Vanem . * Copyright (c) 2017 Ali Abdulkadir . * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef ND_GETSERVENT_H #define ND_GETSERVENT_H #ifdef _NETDB_H_ /* Just in case... */ #error netdb.h and getservent.h are incompatible #else #define _NETDB_H_ #endif #ifdef _WIN32 #define __PATH_SYSROOT "SYSTEMROOT" #define __PATH_ETC_INET "\\System32\\drivers\\etc\\" #define __PATH_SERVICES "services" #else /* * The idea here is to be able to replace "PREFIX" in __PATH_SYSROOT with a variable * that could, for example, point to an alternative install location. */ #define __PATH_SYSROOT "PREFIX" #define __PATH_ETC_INET "/etc/" #define __PATH_SERVICES __PATH_ETC_INET"services" #endif #define MAXALIASES 35 void endservent (void); struct servent *getservent(void); void setservent (int f); #endif /* ! ND_GETSERVENT_H */ tcpdump-4.99.1/print-nsh.c0000644000026300017510000002131014057477727013524 0ustar mcrmcr/* Copyright (c) 2015, bugyo * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* \summary: Network Service Header (NSH) printer */ /* specification: RFC 8300 */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "extract.h" static const struct tok nsh_flags [] = { { 0x2, "O" }, { 0, NULL } }; /* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |Ver|O|U| TTL | Length |U|U|U|U|MD Type| Next Protocol | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ #define NSH_BASE_HDR_LEN 4 #define NSH_VER(x) (((x) & 0xc0000000) >> 30) #define NSH_FLAGS(x) (((x) & 0x30000000) >> 28) #define NSH_TTL(x) (((x) & 0x0fc00000) >> 22) #define NSH_LENGTH(x) (((x) & 0x003f0000) >> 16) #define NSH_MD_TYPE(x) (((x) & 0x00000f00) >> 8) #define NSH_NEXT_PROT(x) (((x) & 0x000000ff) >> 0) #define NSH_SERVICE_PATH_HDR_LEN 4 #define NSH_HDR_WORD_SIZE 4U #define MD_RSV 0x00 #define MD_TYPE1 0x01 #define MD_TYPE2 0x02 #define MD_EXP 0x0F static const struct tok md_str[] = { { MD_RSV, "reserved" }, { MD_TYPE1, "1" }, { MD_TYPE2, "2" }, { MD_EXP, "experimental" }, { 0, NULL } }; #define NP_IPV4 0x01 #define NP_IPV6 0x02 #define NP_ETH 0x03 #define NP_NSH 0x04 #define NP_MPLS 0x05 #define NP_EXP1 0xFE #define NP_EXP2 0xFF static const struct tok np_str[] = { { NP_IPV4, "IPv4" }, { NP_IPV6, "IPv6" }, { NP_ETH, "Ethernet" }, { NP_NSH, "NSH" }, { NP_MPLS, "MPLS" }, { NP_EXP1, "Experiment 1" }, { NP_EXP2, "Experiment 2" }, { 0, NULL } }; void nsh_print(netdissect_options *ndo, const u_char *bp, u_int len) { uint32_t basehdr; u_int ver, length, md_type; uint8_t next_protocol; u_char past_headers = 0; u_int next_len; ndo->ndo_protocol = "nsh"; /* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Base Header | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Service Path Header | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | * ~ Context Header(s) ~ * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* print Base Header and Service Path Header */ if (len < NSH_BASE_HDR_LEN + NSH_SERVICE_PATH_HDR_LEN) { ND_PRINT(" (packet length %u < %u)", len, NSH_BASE_HDR_LEN + NSH_SERVICE_PATH_HDR_LEN); goto invalid; } basehdr = GET_BE_U_4(bp); bp += 4; ver = NSH_VER(basehdr); length = NSH_LENGTH(basehdr); md_type = NSH_MD_TYPE(basehdr); next_protocol = NSH_NEXT_PROT(basehdr); ND_PRINT("NSH, "); if (ndo->ndo_vflag > 1) { ND_PRINT("ver %u, ", ver); } if (ver != 0) return; ND_PRINT("flags [%s], ", bittok2str_nosep(nsh_flags, "none", NSH_FLAGS(basehdr))); if (ndo->ndo_vflag > 2) { ND_PRINT("TTL %u, ", NSH_TTL(basehdr)); ND_PRINT("length %u, ", length); ND_PRINT("md type %s, ", tok2str(md_str, "unknown (0x%02x)", md_type)); } if (ndo->ndo_vflag > 1) { ND_PRINT("next-protocol %s, ", tok2str(np_str, "unknown (0x%02x)", next_protocol)); } /* Make sure we have all the headers */ if (len < length * NSH_HDR_WORD_SIZE) { ND_PRINT(" (too many headers for packet length %u)", len); goto invalid; } /* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Service Path Identifier (SPI) | Service Index | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ ND_PRINT("service-path-id 0x%06x, ", GET_BE_U_3(bp)); bp += 3; ND_PRINT("service-index 0x%x", GET_U_1(bp)); bp += 1; /* * length includes the lengths of the Base and Service Path headers. * That means it must be at least 2. */ if (length < 2) { ND_PRINT(" (less than two headers)"); goto invalid; } /* * Print, or skip, the Context Headers. * (length - 2) is the length of those headers. */ if (ndo->ndo_vflag > 2) { u_int n; if (md_type == MD_TYPE1) { if (length != 6) { ND_PRINT(" (invalid length for the MD type)"); goto invalid; } for (n = 0; n < length - 2; n++) { ND_PRINT("\n Context[%02u]: 0x%08x", n, GET_BE_U_4(bp)); bp += NSH_HDR_WORD_SIZE; } past_headers = 1; } else if (md_type == MD_TYPE2) { n = 0; while (n < length - 2) { uint16_t tlv_class; uint8_t tlv_type, tlv_len, tlv_len_padded; tlv_class = GET_BE_U_2(bp); bp += 2; tlv_type = GET_U_1(bp); bp += 1; tlv_len = GET_U_1(bp) & 0x7f; bp += 1; tlv_len_padded = roundup2(tlv_len, NSH_HDR_WORD_SIZE); ND_PRINT("\n TLV Class %u, Type %u, Len %u", tlv_class, tlv_type, tlv_len); n += 1; if (length - 2 < n + tlv_len_padded / NSH_HDR_WORD_SIZE) { ND_PRINT(" (length too big)"); goto invalid; } if (tlv_len) { const char *sep = "0x"; u_int vn; ND_PRINT("\n Value: "); for (vn = 0; vn < tlv_len; vn++) { ND_PRINT("%s%02x", sep, GET_U_1(bp)); bp += 1; sep = ":"; } /* Cover any TLV padding. */ ND_TCHECK_LEN(bp, tlv_len_padded - tlv_len); bp += tlv_len_padded - tlv_len; n += tlv_len_padded / NSH_HDR_WORD_SIZE; } } past_headers = 1; } } if (! past_headers) { ND_TCHECK_LEN(bp, (length - 2) * NSH_HDR_WORD_SIZE); bp += (length - 2) * NSH_HDR_WORD_SIZE; } ND_PRINT(ndo->ndo_vflag ? "\n " : ": "); /* print Next Protocol */ next_len = len - length * NSH_HDR_WORD_SIZE; switch (next_protocol) { case NP_IPV4: ip_print(ndo, bp, next_len); break; case NP_IPV6: ip6_print(ndo, bp, next_len); break; case NP_ETH: ether_print(ndo, bp, next_len, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL); break; default: ND_PRINT("ERROR: unknown-next-protocol"); return; } return; invalid: nd_print_invalid(ndo); } tcpdump-4.99.1/ftmacros.h0000644000026300017510000001123214057477727013427 0ustar mcrmcr/* * Copyright (c) 1994, 1995, 1996 * 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 the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef ftmacros_h #define ftmacros_h /* * Define some feature test macros to make sure that everything we want * to be declared gets declared. * * On some UN*Xes we need to force strtok_r() to be declared. * We do *NOT* want to define _POSIX_C_SOURCE, as that tends * to make non-POSIX APIs that we use unavailable. * XXX - is there no portable way to say "please pollute the * namespace to the maximum extent possible"? */ #if defined(sun) || defined(__sun) #define __EXTENSIONS__ /* * We also need to define _XPG4_2 in order to get * the Single UNIX Specification version of * recvmsg(). */ #define _XPG4_2 #elif defined(_hpux) || defined(hpux) || defined(__hpux) #define _REENTRANT /* * We need this to get the versions of socket functions that * use socklen_t. Define it only if it's not already defined, * so we don't get redefiniton warnings. */ #ifndef _XOPEN_SOURCE_EXTENDED #define _XOPEN_SOURCE_EXTENDED #endif /* * XXX - the list of PA-RISC options for GCC makes it sound as if * building code that uses a particular vintage of UNIX API/ABI * is complicated: * * https://gcc.gnu.org/onlinedocs/gcc/HPPA-Options.html * * See the description of the -munix flag. * * We probably want libpcap to work with programs built for any * UN*X standard. I'm not sure whether that's possible and, if * it is, what sort of stuff it'd have to do. * * It might also be a requirement that we build with a special * flag to allow the library to be used with threaded code, at * least with HP's C compiler; hopefully doing so won't make it * *not* work with *un*-threaded code. */ #else /* * Turn on _GNU_SOURCE to get everything GNU libc has to offer, * including asprintf(), if we're using GNU libc. * * Unfortunately, one thing it has to offer is a strerror_r() * that's not POSIX-compliant, but we deal with that in * pcap_fmt_errmsg_for_errno(). * * We don't limit this to, for example, Linux and Cygwin, because * this might, for example, be GNU/HURD or one of Debian's kFreeBSD * OSes ("GNU/FreeBSD"). */ #define _GNU_SOURCE /* * We turn on both _DEFAULT_SOURCE and _BSD_SOURCE to try to get * the BSD u_XXX types, such as u_int and u_short, defined. We * define _DEFAULT_SOURCE first, so that newer versions of GNU libc * don't whine about _BSD_SOURCE being deprecated; we still have * to define _BSD_SOURCE to handle older versions of GNU libc that * don't support _DEFAULT_SOURCE. * * But, if it's already defined, don't define it, so that we don't * get a warning of it being redefined if it's defined as, for * example, 1. */ #ifndef _DEFAULT_SOURCE #define _DEFAULT_SOURCE #endif /* Avoid redefining _BSD_SOURCE if it's already defined as for ex. 1 */ #ifndef _BSD_SOURCE #define _BSD_SOURCE #endif #endif #endif tcpdump-4.99.1/print-beep.c0000644000026300017510000000327514057477727013661 0ustar mcrmcr/* * Copyright (C) 2000, Richard Sharpe * * This software may be distributed either under the terms of the * BSD-style license that accompanies tcpdump or under the GNU GPL * version 2 or later. * * print-beep.c * */ /* \summary: Blocks Extensible Exchange Protocol (BEEP) printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include #include "netdissect.h" /* Check for a string but not go beyond length * Return TRUE on match, FALSE otherwise * * Looks at the first few chars up to tl1 ... */ static int l_strnstart(netdissect_options *ndo, const char *tstr1, u_int tl1, const char *str2, u_int l2) { if (!ND_TTEST_LEN(str2, tl1)) { /* * We don't have tl1 bytes worth of captured data * for the string, so we can't check for this * string. */ return 0; } if (tl1 > l2) return 0; return (strncmp(tstr1, str2, tl1) == 0 ? 1 : 0); } void beep_print(netdissect_options *ndo, const u_char *bp, u_int length) { ndo->ndo_protocol = "beep"; if (l_strnstart(ndo, "MSG", 4, (const char *)bp, length)) /* A REQuest */ ND_PRINT(" BEEP MSG"); else if (l_strnstart(ndo, "RPY ", 4, (const char *)bp, length)) ND_PRINT(" BEEP RPY"); else if (l_strnstart(ndo, "ERR ", 4, (const char *)bp, length)) ND_PRINT(" BEEP ERR"); else if (l_strnstart(ndo, "ANS ", 4, (const char *)bp, length)) ND_PRINT(" BEEP ANS"); else if (l_strnstart(ndo, "NUL ", 4, (const char *)bp, length)) ND_PRINT(" BEEP NUL"); else if (l_strnstart(ndo, "SEQ ", 4, (const char *)bp, length)) ND_PRINT(" BEEP SEQ"); else if (l_strnstart(ndo, "END", 4, (const char *)bp, length)) ND_PRINT(" BEEP END"); else ND_PRINT(" BEEP (payload or undecoded)"); } tcpdump-4.99.1/print-lldp.c0000644000026300017510000016276014057477734013704 0ustar mcrmcr/* * Copyright (c) 1998-2007 The TCPDUMP project * * 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, and (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. * 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. * * Original code by Hannes Gredler (hannes@gredler.at) * IEEE and TIA extensions by Carles Kishimoto * DCBX extensions by Kaladhar Musunuru */ /* \summary: IEEE 802.1ab Link Layer Discovery Protocol (LLDP) printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include #include "netdissect.h" #include "extract.h" #include "addrtoname.h" #include "af.h" #include "oui.h" #define LLDP_EXTRACT_TYPE(x) (((x)&0xfe00)>>9) #define LLDP_EXTRACT_LEN(x) ((x)&0x01ff) /* * TLV type codes */ #define LLDP_END_TLV 0 #define LLDP_CHASSIS_ID_TLV 1 #define LLDP_PORT_ID_TLV 2 #define LLDP_TTL_TLV 3 #define LLDP_PORT_DESCR_TLV 4 #define LLDP_SYSTEM_NAME_TLV 5 #define LLDP_SYSTEM_DESCR_TLV 6 #define LLDP_SYSTEM_CAP_TLV 7 #define LLDP_MGMT_ADDR_TLV 8 #define LLDP_PRIVATE_TLV 127 static const struct tok lldp_tlv_values[] = { { LLDP_END_TLV, "End" }, { LLDP_CHASSIS_ID_TLV, "Chassis ID" }, { LLDP_PORT_ID_TLV, "Port ID" }, { LLDP_TTL_TLV, "Time to Live" }, { LLDP_PORT_DESCR_TLV, "Port Description" }, { LLDP_SYSTEM_NAME_TLV, "System Name" }, { LLDP_SYSTEM_DESCR_TLV, "System Description" }, { LLDP_SYSTEM_CAP_TLV, "System Capabilities" }, { LLDP_MGMT_ADDR_TLV, "Management Address" }, { LLDP_PRIVATE_TLV, "Organization specific" }, { 0, NULL} }; /* * Chassis ID subtypes */ #define LLDP_CHASSIS_CHASSIS_COMP_SUBTYPE 1 #define LLDP_CHASSIS_INTF_ALIAS_SUBTYPE 2 #define LLDP_CHASSIS_PORT_COMP_SUBTYPE 3 #define LLDP_CHASSIS_MAC_ADDR_SUBTYPE 4 #define LLDP_CHASSIS_NETWORK_ADDR_SUBTYPE 5 #define LLDP_CHASSIS_INTF_NAME_SUBTYPE 6 #define LLDP_CHASSIS_LOCAL_SUBTYPE 7 static const struct tok lldp_chassis_subtype_values[] = { { LLDP_CHASSIS_CHASSIS_COMP_SUBTYPE, "Chassis component"}, { LLDP_CHASSIS_INTF_ALIAS_SUBTYPE, "Interface alias"}, { LLDP_CHASSIS_PORT_COMP_SUBTYPE, "Port component"}, { LLDP_CHASSIS_MAC_ADDR_SUBTYPE, "MAC address"}, { LLDP_CHASSIS_NETWORK_ADDR_SUBTYPE, "Network address"}, { LLDP_CHASSIS_INTF_NAME_SUBTYPE, "Interface name"}, { LLDP_CHASSIS_LOCAL_SUBTYPE, "Local"}, { 0, NULL} }; /* * Port ID subtypes */ #define LLDP_PORT_INTF_ALIAS_SUBTYPE 1 #define LLDP_PORT_PORT_COMP_SUBTYPE 2 #define LLDP_PORT_MAC_ADDR_SUBTYPE 3 #define LLDP_PORT_NETWORK_ADDR_SUBTYPE 4 #define LLDP_PORT_INTF_NAME_SUBTYPE 5 #define LLDP_PORT_AGENT_CIRC_ID_SUBTYPE 6 #define LLDP_PORT_LOCAL_SUBTYPE 7 static const struct tok lldp_port_subtype_values[] = { { LLDP_PORT_INTF_ALIAS_SUBTYPE, "Interface alias"}, { LLDP_PORT_PORT_COMP_SUBTYPE, "Port component"}, { LLDP_PORT_MAC_ADDR_SUBTYPE, "MAC address"}, { LLDP_PORT_NETWORK_ADDR_SUBTYPE, "Network Address"}, { LLDP_PORT_INTF_NAME_SUBTYPE, "Interface Name"}, { LLDP_PORT_AGENT_CIRC_ID_SUBTYPE, "Agent circuit ID"}, { LLDP_PORT_LOCAL_SUBTYPE, "Local"}, { 0, NULL} }; /* * System Capabilities */ #define LLDP_CAP_OTHER (1 << 0) #define LLDP_CAP_REPEATER (1 << 1) #define LLDP_CAP_BRIDGE (1 << 2) #define LLDP_CAP_WLAN_AP (1 << 3) #define LLDP_CAP_ROUTER (1 << 4) #define LLDP_CAP_PHONE (1 << 5) #define LLDP_CAP_DOCSIS (1 << 6) #define LLDP_CAP_STATION_ONLY (1 << 7) static const struct tok lldp_cap_values[] = { { LLDP_CAP_OTHER, "Other"}, { LLDP_CAP_REPEATER, "Repeater"}, { LLDP_CAP_BRIDGE, "Bridge"}, { LLDP_CAP_WLAN_AP, "WLAN AP"}, { LLDP_CAP_ROUTER, "Router"}, { LLDP_CAP_PHONE, "Telephone"}, { LLDP_CAP_DOCSIS, "Docsis"}, { LLDP_CAP_STATION_ONLY, "Station Only"}, { 0, NULL} }; #define LLDP_PRIVATE_8021_SUBTYPE_PORT_VLAN_ID 1 #define LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID 2 #define LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME 3 #define LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY 4 #define LLDP_PRIVATE_8021_SUBTYPE_LINKAGGR 7 #define LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION 8 #define LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION 9 #define LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION 10 #define LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION 11 #define LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY 12 #define LLDP_PRIVATE_8021_SUBTYPE_EVB 13 #define LLDP_PRIVATE_8021_SUBTYPE_CDCP 14 static const struct tok lldp_8021_subtype_values[] = { { LLDP_PRIVATE_8021_SUBTYPE_PORT_VLAN_ID, "Port VLAN Id"}, { LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID, "Port and Protocol VLAN ID"}, { LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME, "VLAN name"}, { LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY, "Protocol Identity"}, { LLDP_PRIVATE_8021_SUBTYPE_LINKAGGR, "Link aggregation"}, { LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION, "Congestion Notification"}, { LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION, "ETS Configuration"}, { LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION, "ETS Recommendation"}, { LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION, "Priority Flow Control Configuration"}, { LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY, "Application Priority"}, { LLDP_PRIVATE_8021_SUBTYPE_EVB, "EVB"}, { LLDP_PRIVATE_8021_SUBTYPE_CDCP,"CDCP"}, { 0, NULL} }; #define LLDP_8021_PORT_PROTOCOL_VLAN_SUPPORT (1 << 1) #define LLDP_8021_PORT_PROTOCOL_VLAN_STATUS (1 << 2) static const struct tok lldp_8021_port_protocol_id_values[] = { { LLDP_8021_PORT_PROTOCOL_VLAN_SUPPORT, "supported"}, { LLDP_8021_PORT_PROTOCOL_VLAN_STATUS, "enabled"}, { 0, NULL} }; #define LLDP_PRIVATE_8023_SUBTYPE_MACPHY 1 #define LLDP_PRIVATE_8023_SUBTYPE_MDIPOWER 2 #define LLDP_PRIVATE_8023_SUBTYPE_LINKAGGR 3 #define LLDP_PRIVATE_8023_SUBTYPE_MTU 4 static const struct tok lldp_8023_subtype_values[] = { { LLDP_PRIVATE_8023_SUBTYPE_MACPHY, "MAC/PHY configuration/status"}, { LLDP_PRIVATE_8023_SUBTYPE_MDIPOWER, "Power via MDI"}, { LLDP_PRIVATE_8023_SUBTYPE_LINKAGGR, "Link aggregation"}, { LLDP_PRIVATE_8023_SUBTYPE_MTU, "Max frame size"}, { 0, NULL} }; #define LLDP_PRIVATE_TIA_SUBTYPE_CAPABILITIES 1 #define LLDP_PRIVATE_TIA_SUBTYPE_NETWORK_POLICY 2 #define LLDP_PRIVATE_TIA_SUBTYPE_LOCAL_ID 3 #define LLDP_PRIVATE_TIA_SUBTYPE_EXTENDED_POWER_MDI 4 #define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV 5 #define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV 6 #define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV 7 #define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER 8 #define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME 9 #define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME 10 #define LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID 11 static const struct tok lldp_tia_subtype_values[] = { { LLDP_PRIVATE_TIA_SUBTYPE_CAPABILITIES, "LLDP-MED Capabilities" }, { LLDP_PRIVATE_TIA_SUBTYPE_NETWORK_POLICY, "Network policy" }, { LLDP_PRIVATE_TIA_SUBTYPE_LOCAL_ID, "Location identification" }, { LLDP_PRIVATE_TIA_SUBTYPE_EXTENDED_POWER_MDI, "Extended power-via-MDI" }, { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV, "Inventory - hardware revision" }, { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV, "Inventory - firmware revision" }, { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV, "Inventory - software revision" }, { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER, "Inventory - serial number" }, { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME, "Inventory - manufacturer name" }, { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME, "Inventory - model name" }, { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID, "Inventory - asset ID" }, { 0, NULL} }; #define LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_METERS 1 #define LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_FLOORS 2 static const struct tok lldp_tia_location_altitude_type_values[] = { { LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_METERS, "meters"}, { LLDP_PRIVATE_TIA_LOCATION_ALTITUDE_FLOORS, "floors"}, { 0, NULL} }; /* ANSI/TIA-1057 - Annex B */ #define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A1 1 #define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A2 2 #define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A3 3 #define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A4 4 #define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A5 5 #define LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A6 6 static const struct tok lldp_tia_location_lci_catype_values[] = { { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A1, "national subdivisions (state,canton,region,province,prefecture)"}, { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A2, "county, parish, gun, district"}, { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A3, "city, township, shi"}, { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A4, "city division, borough, city district, ward chou"}, { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A5, "neighborhood, block"}, { LLDP_PRIVATE_TIA_LOCATION_LCI_CATYPE_A6, "street"}, { 0, NULL} }; static const struct tok lldp_tia_location_lci_what_values[] = { { 0, "location of DHCP server"}, { 1, "location of the network element believed to be closest to the client"}, { 2, "location of the client"}, { 0, NULL} }; /* * From RFC 3636 - dot3MauType */ #define LLDP_MAU_TYPE_UNKNOWN 0 #define LLDP_MAU_TYPE_AUI 1 #define LLDP_MAU_TYPE_10BASE_5 2 #define LLDP_MAU_TYPE_FOIRL 3 #define LLDP_MAU_TYPE_10BASE_2 4 #define LLDP_MAU_TYPE_10BASE_T 5 #define LLDP_MAU_TYPE_10BASE_FP 6 #define LLDP_MAU_TYPE_10BASE_FB 7 #define LLDP_MAU_TYPE_10BASE_FL 8 #define LLDP_MAU_TYPE_10BROAD36 9 #define LLDP_MAU_TYPE_10BASE_T_HD 10 #define LLDP_MAU_TYPE_10BASE_T_FD 11 #define LLDP_MAU_TYPE_10BASE_FL_HD 12 #define LLDP_MAU_TYPE_10BASE_FL_FD 13 #define LLDP_MAU_TYPE_100BASE_T4 14 #define LLDP_MAU_TYPE_100BASE_TX_HD 15 #define LLDP_MAU_TYPE_100BASE_TX_FD 16 #define LLDP_MAU_TYPE_100BASE_FX_HD 17 #define LLDP_MAU_TYPE_100BASE_FX_FD 18 #define LLDP_MAU_TYPE_100BASE_T2_HD 19 #define LLDP_MAU_TYPE_100BASE_T2_FD 20 #define LLDP_MAU_TYPE_1000BASE_X_HD 21 #define LLDP_MAU_TYPE_1000BASE_X_FD 22 #define LLDP_MAU_TYPE_1000BASE_LX_HD 23 #define LLDP_MAU_TYPE_1000BASE_LX_FD 24 #define LLDP_MAU_TYPE_1000BASE_SX_HD 25 #define LLDP_MAU_TYPE_1000BASE_SX_FD 26 #define LLDP_MAU_TYPE_1000BASE_CX_HD 27 #define LLDP_MAU_TYPE_1000BASE_CX_FD 28 #define LLDP_MAU_TYPE_1000BASE_T_HD 29 #define LLDP_MAU_TYPE_1000BASE_T_FD 30 #define LLDP_MAU_TYPE_10GBASE_X 31 #define LLDP_MAU_TYPE_10GBASE_LX4 32 #define LLDP_MAU_TYPE_10GBASE_R 33 #define LLDP_MAU_TYPE_10GBASE_ER 34 #define LLDP_MAU_TYPE_10GBASE_LR 35 #define LLDP_MAU_TYPE_10GBASE_SR 36 #define LLDP_MAU_TYPE_10GBASE_W 37 #define LLDP_MAU_TYPE_10GBASE_EW 38 #define LLDP_MAU_TYPE_10GBASE_LW 39 #define LLDP_MAU_TYPE_10GBASE_SW 40 static const struct tok lldp_mau_types_values[] = { { LLDP_MAU_TYPE_UNKNOWN, "Unknown"}, { LLDP_MAU_TYPE_AUI, "AUI"}, { LLDP_MAU_TYPE_10BASE_5, "10BASE_5"}, { LLDP_MAU_TYPE_FOIRL, "FOIRL"}, { LLDP_MAU_TYPE_10BASE_2, "10BASE2"}, { LLDP_MAU_TYPE_10BASE_T, "10BASET duplex mode unknown"}, { LLDP_MAU_TYPE_10BASE_FP, "10BASEFP"}, { LLDP_MAU_TYPE_10BASE_FB, "10BASEFB"}, { LLDP_MAU_TYPE_10BASE_FL, "10BASEFL duplex mode unknown"}, { LLDP_MAU_TYPE_10BROAD36, "10BROAD36"}, { LLDP_MAU_TYPE_10BASE_T_HD, "10BASET hdx"}, { LLDP_MAU_TYPE_10BASE_T_FD, "10BASET fdx"}, { LLDP_MAU_TYPE_10BASE_FL_HD, "10BASEFL hdx"}, { LLDP_MAU_TYPE_10BASE_FL_FD, "10BASEFL fdx"}, { LLDP_MAU_TYPE_100BASE_T4, "100BASET4"}, { LLDP_MAU_TYPE_100BASE_TX_HD, "100BASETX hdx"}, { LLDP_MAU_TYPE_100BASE_TX_FD, "100BASETX fdx"}, { LLDP_MAU_TYPE_100BASE_FX_HD, "100BASEFX hdx"}, { LLDP_MAU_TYPE_100BASE_FX_FD, "100BASEFX fdx"}, { LLDP_MAU_TYPE_100BASE_T2_HD, "100BASET2 hdx"}, { LLDP_MAU_TYPE_100BASE_T2_FD, "100BASET2 fdx"}, { LLDP_MAU_TYPE_1000BASE_X_HD, "1000BASEX hdx"}, { LLDP_MAU_TYPE_1000BASE_X_FD, "1000BASEX fdx"}, { LLDP_MAU_TYPE_1000BASE_LX_HD, "1000BASELX hdx"}, { LLDP_MAU_TYPE_1000BASE_LX_FD, "1000BASELX fdx"}, { LLDP_MAU_TYPE_1000BASE_SX_HD, "1000BASESX hdx"}, { LLDP_MAU_TYPE_1000BASE_SX_FD, "1000BASESX fdx"}, { LLDP_MAU_TYPE_1000BASE_CX_HD, "1000BASECX hdx"}, { LLDP_MAU_TYPE_1000BASE_CX_FD, "1000BASECX fdx"}, { LLDP_MAU_TYPE_1000BASE_T_HD, "1000BASET hdx"}, { LLDP_MAU_TYPE_1000BASE_T_FD, "1000BASET fdx"}, { LLDP_MAU_TYPE_10GBASE_X, "10GBASEX"}, { LLDP_MAU_TYPE_10GBASE_LX4, "10GBASELX4"}, { LLDP_MAU_TYPE_10GBASE_R, "10GBASER"}, { LLDP_MAU_TYPE_10GBASE_ER, "10GBASEER"}, { LLDP_MAU_TYPE_10GBASE_LR, "10GBASELR"}, { LLDP_MAU_TYPE_10GBASE_SR, "10GBASESR"}, { LLDP_MAU_TYPE_10GBASE_W, "10GBASEW"}, { LLDP_MAU_TYPE_10GBASE_EW, "10GBASEEW"}, { LLDP_MAU_TYPE_10GBASE_LW, "10GBASELW"}, { LLDP_MAU_TYPE_10GBASE_SW, "10GBASESW"}, { 0, NULL} }; #define LLDP_8023_AUTONEGOTIATION_SUPPORT (1 << 0) #define LLDP_8023_AUTONEGOTIATION_STATUS (1 << 1) static const struct tok lldp_8023_autonegotiation_values[] = { { LLDP_8023_AUTONEGOTIATION_SUPPORT, "supported"}, { LLDP_8023_AUTONEGOTIATION_STATUS, "enabled"}, { 0, NULL} }; #define LLDP_TIA_CAPABILITY_MED (1 << 0) #define LLDP_TIA_CAPABILITY_NETWORK_POLICY (1 << 1) #define LLDP_TIA_CAPABILITY_LOCATION_IDENTIFICATION (1 << 2) #define LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PSE (1 << 3) #define LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PD (1 << 4) #define LLDP_TIA_CAPABILITY_INVENTORY (1 << 5) static const struct tok lldp_tia_capabilities_values[] = { { LLDP_TIA_CAPABILITY_MED, "LLDP-MED capabilities"}, { LLDP_TIA_CAPABILITY_NETWORK_POLICY, "network policy"}, { LLDP_TIA_CAPABILITY_LOCATION_IDENTIFICATION, "location identification"}, { LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PSE, "extended power via MDI-PSE"}, { LLDP_TIA_CAPABILITY_EXTENDED_POWER_MDI_PD, "extended power via MDI-PD"}, { LLDP_TIA_CAPABILITY_INVENTORY, "Inventory"}, { 0, NULL} }; #define LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_1 1 #define LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_2 2 #define LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_3 3 #define LLDP_TIA_DEVICE_TYPE_NETWORK_CONNECTIVITY 4 static const struct tok lldp_tia_device_type_values[] = { { LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_1, "endpoint class 1"}, { LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_2, "endpoint class 2"}, { LLDP_TIA_DEVICE_TYPE_ENDPOINT_CLASS_3, "endpoint class 3"}, { LLDP_TIA_DEVICE_TYPE_NETWORK_CONNECTIVITY, "network connectivity"}, { 0, NULL} }; #define LLDP_TIA_APPLICATION_TYPE_VOICE 1 #define LLDP_TIA_APPLICATION_TYPE_VOICE_SIGNALING 2 #define LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE 3 #define LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE_SIGNALING 4 #define LLDP_TIA_APPLICATION_TYPE_SOFTPHONE_VOICE 5 #define LLDP_TIA_APPLICATION_TYPE_VIDEO_CONFERENCING 6 #define LLDP_TIA_APPLICATION_TYPE_STREAMING_VIDEO 7 #define LLDP_TIA_APPLICATION_TYPE_VIDEO_SIGNALING 8 static const struct tok lldp_tia_application_type_values[] = { { LLDP_TIA_APPLICATION_TYPE_VOICE, "voice"}, { LLDP_TIA_APPLICATION_TYPE_VOICE_SIGNALING, "voice signaling"}, { LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE, "guest voice"}, { LLDP_TIA_APPLICATION_TYPE_GUEST_VOICE_SIGNALING, "guest voice signaling"}, { LLDP_TIA_APPLICATION_TYPE_SOFTPHONE_VOICE, "softphone voice"}, { LLDP_TIA_APPLICATION_TYPE_VIDEO_CONFERENCING, "video conferencing"}, { LLDP_TIA_APPLICATION_TYPE_STREAMING_VIDEO, "streaming video"}, { LLDP_TIA_APPLICATION_TYPE_VIDEO_SIGNALING, "video signaling"}, { 0, NULL} }; #define LLDP_TIA_NETWORK_POLICY_X_BIT (1 << 5) #define LLDP_TIA_NETWORK_POLICY_T_BIT (1 << 6) #define LLDP_TIA_NETWORK_POLICY_U_BIT (1 << 7) static const struct tok lldp_tia_network_policy_bits_values[] = { { LLDP_TIA_NETWORK_POLICY_U_BIT, "Unknown"}, { LLDP_TIA_NETWORK_POLICY_T_BIT, "Tagged"}, { LLDP_TIA_NETWORK_POLICY_X_BIT, "reserved"}, { 0, NULL} }; #define LLDP_EXTRACT_NETWORK_POLICY_VLAN(x) (((x)&0x1ffe)>>1) #define LLDP_EXTRACT_NETWORK_POLICY_L2_PRIORITY(x) (((x)&0x01ff)>>6) #define LLDP_EXTRACT_NETWORK_POLICY_DSCP(x) ((x)&0x003f) #define LLDP_TIA_LOCATION_DATA_FORMAT_COORDINATE_BASED 1 #define LLDP_TIA_LOCATION_DATA_FORMAT_CIVIC_ADDRESS 2 #define LLDP_TIA_LOCATION_DATA_FORMAT_ECS_ELIN 3 static const struct tok lldp_tia_location_data_format_values[] = { { LLDP_TIA_LOCATION_DATA_FORMAT_COORDINATE_BASED, "coordinate-based LCI"}, { LLDP_TIA_LOCATION_DATA_FORMAT_CIVIC_ADDRESS, "civic address LCI"}, { LLDP_TIA_LOCATION_DATA_FORMAT_ECS_ELIN, "ECS ELIN"}, { 0, NULL} }; #define LLDP_TIA_LOCATION_DATUM_WGS_84 1 #define LLDP_TIA_LOCATION_DATUM_NAD_83_NAVD_88 2 #define LLDP_TIA_LOCATION_DATUM_NAD_83_MLLW 3 static const struct tok lldp_tia_location_datum_type_values[] = { { LLDP_TIA_LOCATION_DATUM_WGS_84, "World Geodesic System 1984"}, { LLDP_TIA_LOCATION_DATUM_NAD_83_NAVD_88, "North American Datum 1983 (NAVD88)"}, { LLDP_TIA_LOCATION_DATUM_NAD_83_MLLW, "North American Datum 1983 (MLLW)"}, { 0, NULL} }; #define LLDP_TIA_POWER_SOURCE_PSE 1 #define LLDP_TIA_POWER_SOURCE_LOCAL 2 #define LLDP_TIA_POWER_SOURCE_PSE_AND_LOCAL 3 static const struct tok lldp_tia_power_source_values[] = { { LLDP_TIA_POWER_SOURCE_PSE, "PSE - primary power source"}, { LLDP_TIA_POWER_SOURCE_LOCAL, "local - backup power source"}, { LLDP_TIA_POWER_SOURCE_PSE_AND_LOCAL, "PSE+local - reserved"}, { 0, NULL} }; #define LLDP_TIA_POWER_PRIORITY_CRITICAL 1 #define LLDP_TIA_POWER_PRIORITY_HIGH 2 #define LLDP_TIA_POWER_PRIORITY_LOW 3 static const struct tok lldp_tia_power_priority_values[] = { { LLDP_TIA_POWER_PRIORITY_CRITICAL, "critical"}, { LLDP_TIA_POWER_PRIORITY_HIGH, "high"}, { LLDP_TIA_POWER_PRIORITY_LOW, "low"}, { 0, NULL} }; #define LLDP_TIA_POWER_VAL_MAX 1024 static const struct tok lldp_tia_inventory_values[] = { { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV, "Hardware revision" }, { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV, "Firmware revision" }, { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV, "Software revision" }, { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER, "Serial number" }, { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME, "Manufacturer name" }, { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME, "Model name" }, { LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID, "Asset ID" }, { 0, NULL} }; /* * From RFC 3636 - ifMauAutoNegCapAdvertisedBits */ #define LLDP_MAU_PMD_OTHER (1 << 15) #define LLDP_MAU_PMD_10BASE_T (1 << 14) #define LLDP_MAU_PMD_10BASE_T_FD (1 << 13) #define LLDP_MAU_PMD_100BASE_T4 (1 << 12) #define LLDP_MAU_PMD_100BASE_TX (1 << 11) #define LLDP_MAU_PMD_100BASE_TX_FD (1 << 10) #define LLDP_MAU_PMD_100BASE_T2 (1 << 9) #define LLDP_MAU_PMD_100BASE_T2_FD (1 << 8) #define LLDP_MAU_PMD_FDXPAUSE (1 << 7) #define LLDP_MAU_PMD_FDXAPAUSE (1 << 6) #define LLDP_MAU_PMD_FDXSPAUSE (1 << 5) #define LLDP_MAU_PMD_FDXBPAUSE (1 << 4) #define LLDP_MAU_PMD_1000BASE_X (1 << 3) #define LLDP_MAU_PMD_1000BASE_X_FD (1 << 2) #define LLDP_MAU_PMD_1000BASE_T (1 << 1) #define LLDP_MAU_PMD_1000BASE_T_FD (1 << 0) static const struct tok lldp_pmd_capability_values[] = { { LLDP_MAU_PMD_10BASE_T, "10BASE-T hdx"}, { LLDP_MAU_PMD_10BASE_T_FD, "10BASE-T fdx"}, { LLDP_MAU_PMD_100BASE_T4, "100BASE-T4"}, { LLDP_MAU_PMD_100BASE_TX, "100BASE-TX hdx"}, { LLDP_MAU_PMD_100BASE_TX_FD, "100BASE-TX fdx"}, { LLDP_MAU_PMD_100BASE_T2, "100BASE-T2 hdx"}, { LLDP_MAU_PMD_100BASE_T2_FD, "100BASE-T2 fdx"}, { LLDP_MAU_PMD_FDXPAUSE, "Pause for fdx links"}, { LLDP_MAU_PMD_FDXAPAUSE, "Asym PAUSE for fdx"}, { LLDP_MAU_PMD_FDXSPAUSE, "Sym PAUSE for fdx"}, { LLDP_MAU_PMD_FDXBPAUSE, "Asym and Sym PAUSE for fdx"}, { LLDP_MAU_PMD_1000BASE_X, "1000BASE-{X LX SX CX} hdx"}, { LLDP_MAU_PMD_1000BASE_X_FD, "1000BASE-{X LX SX CX} fdx"}, { LLDP_MAU_PMD_1000BASE_T, "1000BASE-T hdx"}, { LLDP_MAU_PMD_1000BASE_T_FD, "1000BASE-T fdx"}, { 0, NULL} }; #define LLDP_MDI_PORT_CLASS (1 << 0) #define LLDP_MDI_POWER_SUPPORT (1 << 1) #define LLDP_MDI_POWER_STATE (1 << 2) #define LLDP_MDI_PAIR_CONTROL_ABILITY (1 << 3) static const struct tok lldp_mdi_values[] = { { LLDP_MDI_PORT_CLASS, "PSE"}, { LLDP_MDI_POWER_SUPPORT, "supported"}, { LLDP_MDI_POWER_STATE, "enabled"}, { LLDP_MDI_PAIR_CONTROL_ABILITY, "can be controlled"}, { 0, NULL} }; #define LLDP_MDI_PSE_PORT_POWER_PAIRS_SIGNAL 1 #define LLDP_MDI_PSE_PORT_POWER_PAIRS_SPARE 2 static const struct tok lldp_mdi_power_pairs_values[] = { { LLDP_MDI_PSE_PORT_POWER_PAIRS_SIGNAL, "signal"}, { LLDP_MDI_PSE_PORT_POWER_PAIRS_SPARE, "spare"}, { 0, NULL} }; #define LLDP_MDI_POWER_CLASS0 1 #define LLDP_MDI_POWER_CLASS1 2 #define LLDP_MDI_POWER_CLASS2 3 #define LLDP_MDI_POWER_CLASS3 4 #define LLDP_MDI_POWER_CLASS4 5 static const struct tok lldp_mdi_power_class_values[] = { { LLDP_MDI_POWER_CLASS0, "class0"}, { LLDP_MDI_POWER_CLASS1, "class1"}, { LLDP_MDI_POWER_CLASS2, "class2"}, { LLDP_MDI_POWER_CLASS3, "class3"}, { LLDP_MDI_POWER_CLASS4, "class4"}, { 0, NULL} }; #define LLDP_AGGREGATION_CAPABILITY (1 << 0) #define LLDP_AGGREGATION_STATUS (1 << 1) static const struct tok lldp_aggregation_values[] = { { LLDP_AGGREGATION_CAPABILITY, "supported"}, { LLDP_AGGREGATION_STATUS, "enabled"}, { 0, NULL} }; /* * DCBX protocol subtypes. */ #define LLDP_DCBX_SUBTYPE_1 1 #define LLDP_DCBX_SUBTYPE_2 2 static const struct tok lldp_dcbx_subtype_values[] = { { LLDP_DCBX_SUBTYPE_1, "DCB Capability Exchange Protocol Rev 1" }, { LLDP_DCBX_SUBTYPE_2, "DCB Capability Exchange Protocol Rev 1.01" }, { 0, NULL} }; #define LLDP_DCBX_CONTROL_TLV 1 #define LLDP_DCBX_PRIORITY_GROUPS_TLV 2 #define LLDP_DCBX_PRIORITY_FLOW_CONTROL_TLV 3 #define LLDP_DCBX_APPLICATION_TLV 4 /* * Interface numbering subtypes. */ #define LLDP_INTF_NUMB_IFX_SUBTYPE 2 #define LLDP_INTF_NUMB_SYSPORT_SUBTYPE 3 static const struct tok lldp_intf_numb_subtype_values[] = { { LLDP_INTF_NUMB_IFX_SUBTYPE, "Interface Index" }, { LLDP_INTF_NUMB_SYSPORT_SUBTYPE, "System Port Number" }, { 0, NULL} }; #define LLDP_INTF_NUM_LEN 5 #define LLDP_EVB_MODE_NOT_SUPPORTED 0 #define LLDP_EVB_MODE_EVB_BRIDGE 1 #define LLDP_EVB_MODE_EVB_STATION 2 #define LLDP_EVB_MODE_RESERVED 3 static const struct tok lldp_evb_mode_values[]={ { LLDP_EVB_MODE_NOT_SUPPORTED, "Not Supported"}, { LLDP_EVB_MODE_EVB_BRIDGE, "EVB Bridge"}, { LLDP_EVB_MODE_EVB_STATION, "EVB Station"}, { LLDP_EVB_MODE_RESERVED, "Reserved for future Standardization"}, { 0, NULL}, }; #define NO_OF_BITS 8 #define LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION_LENGTH 6 #define LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION_LENGTH 25 #define LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION_LENGTH 25 #define LLDP_PRIVATE_8021_SUBTYPE_PFC_CONFIGURATION_LENGTH 6 #define LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY_MIN_LENGTH 5 #define LLDP_PRIVATE_8021_SUBTYPE_EVB_LENGTH 9 #define LLDP_PRIVATE_8021_SUBTYPE_CDCP_MIN_LENGTH 8 #define LLDP_IANA_SUBTYPE_MUDURL 1 static const struct tok lldp_iana_subtype_values[] = { { LLDP_IANA_SUBTYPE_MUDURL, "MUD-URL" }, { 0, NULL } }; static void print_ets_priority_assignment_table(netdissect_options *ndo, const u_char *ptr) { ND_PRINT("\n\t Priority Assignment Table"); ND_PRINT("\n\t Priority : 0 1 2 3 4 5 6 7"); ND_PRINT("\n\t Value : %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d", GET_U_1(ptr) >> 4, GET_U_1(ptr) & 0x0f, GET_U_1(ptr + 1) >> 4, GET_U_1(ptr + 1) & 0x0f, GET_U_1(ptr + 2) >> 4, GET_U_1(ptr + 2) & 0x0f, GET_U_1(ptr + 3) >> 4, GET_U_1(ptr + 3) & 0x0f); } static void print_tc_bandwidth_table(netdissect_options *ndo, const u_char *ptr) { ND_PRINT("\n\t TC Bandwidth Table"); ND_PRINT("\n\t TC%% : 0 1 2 3 4 5 6 7"); ND_PRINT("\n\t Value : %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d", GET_U_1(ptr), GET_U_1(ptr + 1), GET_U_1(ptr + 2), GET_U_1(ptr + 3), GET_U_1(ptr + 4), GET_U_1(ptr + 5), GET_U_1(ptr + 6), GET_U_1(ptr + 7)); } static void print_tsa_assignment_table(netdissect_options *ndo, const u_char *ptr) { ND_PRINT("\n\t TSA Assignment Table"); ND_PRINT("\n\t Traffic Class: 0 1 2 3 4 5 6 7"); ND_PRINT("\n\t Value : %-3d %-3d %-3d %-3d %-3d %-3d %-3d %-3d", GET_U_1(ptr), GET_U_1(ptr + 1), GET_U_1(ptr + 2), GET_U_1(ptr + 3), GET_U_1(ptr + 4), GET_U_1(ptr + 5), GET_U_1(ptr + 6), GET_U_1(ptr + 7)); } /* * Print IEEE 802.1 private extensions. (802.1AB annex E) */ static int lldp_private_8021_print(netdissect_options *ndo, const u_char *tptr, u_int tlv_len) { int hexdump = FALSE; u_int subtype; u_int sublen; u_int tval; u_int i; if (tlv_len < 4) { return hexdump; } subtype = GET_U_1(tptr + 3); ND_PRINT("\n\t %s Subtype (%u)", tok2str(lldp_8021_subtype_values, "unknown", subtype), subtype); switch (subtype) { case LLDP_PRIVATE_8021_SUBTYPE_PORT_VLAN_ID: if (tlv_len < 6) { return hexdump; } ND_PRINT("\n\t port vlan id (PVID): %u", GET_BE_U_2(tptr + 4)); break; case LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_VLAN_ID: if (tlv_len < 7) { return hexdump; } ND_PRINT("\n\t port and protocol vlan id (PPVID): %u, flags [%s] (0x%02x)", GET_BE_U_2(tptr + 5), bittok2str(lldp_8021_port_protocol_id_values, "none", GET_U_1(tptr + 4)), GET_U_1(tptr + 4)); break; case LLDP_PRIVATE_8021_SUBTYPE_VLAN_NAME: if (tlv_len < 6) { return hexdump; } ND_PRINT("\n\t vlan id (VID): %u", GET_BE_U_2(tptr + 4)); if (tlv_len < 7) { return hexdump; } sublen = GET_U_1(tptr + 6); if (tlv_len < 7+sublen) { return hexdump; } ND_PRINT("\n\t vlan name: "); nd_printjnp(ndo, tptr + 7, sublen); break; case LLDP_PRIVATE_8021_SUBTYPE_PROTOCOL_IDENTITY: if (tlv_len < 5) { return hexdump; } sublen = GET_U_1(tptr + 4); if (tlv_len < 5+sublen) { return hexdump; } ND_PRINT("\n\t protocol identity: "); nd_printjnp(ndo, tptr + 5, sublen); break; case LLDP_PRIVATE_8021_SUBTYPE_LINKAGGR: if (tlv_len < 9) { return hexdump; } ND_PRINT("\n\t aggregation status [%s], aggregation port ID %u", bittok2str(lldp_aggregation_values, "none", GET_U_1((tptr + 4))), GET_BE_U_4(tptr + 5)); break; case LLDP_PRIVATE_8021_SUBTYPE_CONGESTION_NOTIFICATION: if(tlv_len> i) & 0x01); tval=GET_U_1(tptr + 5); ND_PRINT("\n\t Pre-Priority Ready Indicator"); ND_PRINT("\n\t Priority : 0 1 2 3 4 5 6 7"); ND_PRINT("\n\t Value : "); for(i=0;i> i) & 0x01); break; case LLDP_PRIVATE_8021_SUBTYPE_ETS_CONFIGURATION: if(tlv_len> 7, (tval >> 6) & 0x02, (tval >> 3) & 0x07, tval & 0x07); /*Print Priority Assignment Table*/ print_ets_priority_assignment_table(ndo, tptr + 5); /*Print TC Bandwidth Table*/ print_tc_bandwidth_table(ndo, tptr + 9); /* Print TSA Assignment Table */ print_tsa_assignment_table(ndo, tptr + 17); break; case LLDP_PRIVATE_8021_SUBTYPE_ETS_RECOMMENDATION: if(tlv_len> 7, (tval >> 6) & 0x01, (tval >> 4) & 0x03, (tval & 0x0f)); ND_PRINT("\n\t PFC Enable"); tval=GET_U_1(tptr + 5); ND_PRINT("\n\t Priority : 0 1 2 3 4 5 6 7"); ND_PRINT("\n\t Value : "); for(i=0;i> i) & 0x01); break; case LLDP_PRIVATE_8021_SUBTYPE_APPLICATION_PRIORITY: if(tlv_len> 5, (tval >> 3) & 0x03, (tval & 0x07), GET_BE_U_2(tptr + i + 6)); i=i+3; } break; case LLDP_PRIVATE_8021_SUBTYPE_EVB: if(tlv_len> 3, (tval >> 2) & 0x01, (tval >> 1) & 0x01, tval & 0x01); ND_PRINT("\n\t EVB Station Status"); tval=GET_U_1(tptr + 5); ND_PRINT("\n\t RES: %u, SGID: %u, RRREQ: %u,RRSTAT: %u", tval >> 4, (tval >> 3) & 0x01, (tval >> 2) & 0x01, tval & 0x03); tval=GET_U_1(tptr + 6); ND_PRINT("\n\t R: %u, RTE: %u, ",tval >> 5, tval & 0x1f); tval=GET_U_1(tptr + 7); ND_PRINT("EVB Mode: %s [%u]", tok2str(lldp_evb_mode_values, "unknown", tval >> 6), tval >> 6); ND_PRINT("\n\t ROL: %u, RWD: %u, ", (tval >> 5) & 0x01, tval & 0x1f); tval=GET_U_1(tptr + 8); ND_PRINT("RES: %u, ROL: %u, RKA: %u", tval >> 6, (tval >> 5) & 0x01, tval & 0x1f); break; case LLDP_PRIVATE_8021_SUBTYPE_CDCP: if(tlv_len> 7, (tval >> 4) & 0x07, (tval >> 3) & 0x01); ND_PRINT("ChnCap: %u", GET_BE_U_2(tptr + 6) & 0x0fff); sublen=tlv_len-8; if(sublen%3!=0) { return hexdump; } i=0; while(i> 12, tval & 0x000fff); i=i+3; } break; default: hexdump = TRUE; break; } return hexdump; } /* * Print IEEE 802.3 private extensions. (802.3bc) */ static int lldp_private_8023_print(netdissect_options *ndo, const u_char *tptr, u_int tlv_len) { int hexdump = FALSE; u_int subtype; if (tlv_len < 4) { return hexdump; } subtype = GET_U_1(tptr + 3); ND_PRINT("\n\t %s Subtype (%u)", tok2str(lldp_8023_subtype_values, "unknown", subtype), subtype); switch (subtype) { case LLDP_PRIVATE_8023_SUBTYPE_MACPHY: if (tlv_len < 9) { return hexdump; } ND_PRINT("\n\t autonegotiation [%s] (0x%02x)", bittok2str(lldp_8023_autonegotiation_values, "none", GET_U_1(tptr + 4)), GET_U_1(tptr + 4)); ND_PRINT("\n\t PMD autoneg capability [%s] (0x%04x)", bittok2str(lldp_pmd_capability_values,"unknown", GET_BE_U_2(tptr + 5)), GET_BE_U_2(tptr + 5)); ND_PRINT("\n\t MAU type %s (0x%04x)", tok2str(lldp_mau_types_values, "unknown", GET_BE_U_2(tptr + 7)), GET_BE_U_2(tptr + 7)); break; case LLDP_PRIVATE_8023_SUBTYPE_MDIPOWER: if (tlv_len < 7) { return hexdump; } ND_PRINT("\n\t MDI power support [%s], power pair %s, power class %s", bittok2str(lldp_mdi_values, "none", GET_U_1((tptr + 4))), tok2str(lldp_mdi_power_pairs_values, "unknown", GET_U_1((tptr + 5))), tok2str(lldp_mdi_power_class_values, "unknown", GET_U_1((tptr + 6)))); break; case LLDP_PRIVATE_8023_SUBTYPE_LINKAGGR: if (tlv_len < 9) { return hexdump; } ND_PRINT("\n\t aggregation status [%s], aggregation port ID %u", bittok2str(lldp_aggregation_values, "none", GET_U_1((tptr + 4))), GET_BE_U_4(tptr + 5)); break; case LLDP_PRIVATE_8023_SUBTYPE_MTU: if (tlv_len < 6) { return hexdump; } ND_PRINT("\n\t MTU size %u", GET_BE_U_2(tptr + 4)); break; default: hexdump = TRUE; break; } return hexdump; } /* * Extract 34bits of latitude/longitude coordinates. */ static uint64_t lldp_extract_latlon(netdissect_options *ndo, const u_char *tptr) { uint64_t latlon; latlon = GET_U_1(tptr) & 0x3; latlon = (latlon << 32) | GET_BE_U_4(tptr + 1); return latlon; } /* objects defined in IANA subtype 00 00 5e * (right now there is only one) */ static int lldp_private_iana_print(netdissect_options *ndo, const u_char *tptr, u_int tlv_len) { int hexdump = FALSE; u_int subtype; if (tlv_len < 8) { return hexdump; } subtype = GET_U_1(tptr + 3); ND_PRINT("\n\t %s Subtype (%u)", tok2str(lldp_iana_subtype_values, "unknown", subtype), subtype); switch (subtype) { case LLDP_IANA_SUBTYPE_MUDURL: ND_PRINT("\n\t MUD-URL="); (void)nd_printn(ndo, tptr+4, tlv_len-4, NULL); break; default: hexdump=TRUE; } return hexdump; } /* * Print private TIA extensions. */ static int lldp_private_tia_print(netdissect_options *ndo, const u_char *tptr, u_int tlv_len) { int hexdump = FALSE; u_int subtype; uint8_t location_format; uint16_t power_val; u_int lci_len; uint8_t ca_type, ca_len; if (tlv_len < 4) { return hexdump; } subtype = GET_U_1(tptr + 3); ND_PRINT("\n\t %s Subtype (%u)", tok2str(lldp_tia_subtype_values, "unknown", subtype), subtype); switch (subtype) { case LLDP_PRIVATE_TIA_SUBTYPE_CAPABILITIES: if (tlv_len < 7) { return hexdump; } ND_PRINT("\n\t Media capabilities [%s] (0x%04x)", bittok2str(lldp_tia_capabilities_values, "none", GET_BE_U_2(tptr + 4)), GET_BE_U_2(tptr + 4)); ND_PRINT("\n\t Device type [%s] (0x%02x)", tok2str(lldp_tia_device_type_values, "unknown", GET_U_1(tptr + 6)), GET_U_1(tptr + 6)); break; case LLDP_PRIVATE_TIA_SUBTYPE_NETWORK_POLICY: if (tlv_len < 8) { return hexdump; } ND_PRINT("\n\t Application type [%s] (0x%02x)", tok2str(lldp_tia_application_type_values, "none", GET_U_1(tptr + 4)), GET_U_1(tptr + 4)); ND_PRINT(", Flags [%s]", bittok2str( lldp_tia_network_policy_bits_values, "none", GET_U_1((tptr + 5)))); ND_PRINT("\n\t Vlan id %u", LLDP_EXTRACT_NETWORK_POLICY_VLAN(GET_BE_U_2(tptr + 5))); ND_PRINT(", L2 priority %u", LLDP_EXTRACT_NETWORK_POLICY_L2_PRIORITY(GET_BE_U_2(tptr + 6))); ND_PRINT(", DSCP value %u", LLDP_EXTRACT_NETWORK_POLICY_DSCP(GET_BE_U_2(tptr + 6))); break; case LLDP_PRIVATE_TIA_SUBTYPE_LOCAL_ID: if (tlv_len < 5) { return hexdump; } location_format = GET_U_1(tptr + 4); ND_PRINT("\n\t Location data format %s (0x%02x)", tok2str(lldp_tia_location_data_format_values, "unknown", location_format), location_format); switch (location_format) { case LLDP_TIA_LOCATION_DATA_FORMAT_COORDINATE_BASED: if (tlv_len < 21) { return hexdump; } ND_PRINT("\n\t Latitude resolution %u, latitude value %" PRIu64, (GET_U_1(tptr + 5) >> 2), lldp_extract_latlon(ndo, tptr + 5)); ND_PRINT("\n\t Longitude resolution %u, longitude value %" PRIu64, (GET_U_1(tptr + 10) >> 2), lldp_extract_latlon(ndo, tptr + 10)); ND_PRINT("\n\t Altitude type %s (%u)", tok2str(lldp_tia_location_altitude_type_values, "unknown",GET_U_1(tptr + 15) >> 4), (GET_U_1(tptr + 15) >> 4)); ND_PRINT("\n\t Altitude resolution %u, altitude value 0x%x", (GET_BE_U_2(tptr + 15)>>6)&0x3f, (GET_BE_U_4(tptr + 16) & 0x3fffffff)); ND_PRINT("\n\t Datum %s (0x%02x)", tok2str(lldp_tia_location_datum_type_values, "unknown", GET_U_1(tptr + 20)), GET_U_1(tptr + 20)); break; case LLDP_TIA_LOCATION_DATA_FORMAT_CIVIC_ADDRESS: if (tlv_len < 6) { return hexdump; } lci_len = GET_U_1(tptr + 5); if (lci_len < 3) { return hexdump; } if (tlv_len < 7+lci_len) { return hexdump; } ND_PRINT("\n\t LCI length %u, LCI what %s (0x%02x), Country-code ", lci_len, tok2str(lldp_tia_location_lci_what_values, "unknown", GET_U_1(tptr + 6)), GET_U_1(tptr + 6)); /* Country code */ nd_printjnp(ndo, tptr + 7, 2); lci_len = lci_len-3; tptr = tptr + 9; /* Decode each civic address element */ while (lci_len > 0) { if (lci_len < 2) { return hexdump; } ca_type = GET_U_1(tptr); ca_len = GET_U_1(tptr + 1); tptr += 2; lci_len -= 2; ND_PRINT("\n\t CA type \'%s\' (%u), length %u: ", tok2str(lldp_tia_location_lci_catype_values, "unknown", ca_type), ca_type, ca_len); /* basic sanity check */ if ( ca_type == 0 || ca_len == 0) { return hexdump; } if (lci_len < ca_len) { return hexdump; } nd_printjnp(ndo, tptr, ca_len); tptr += ca_len; lci_len -= ca_len; } break; case LLDP_TIA_LOCATION_DATA_FORMAT_ECS_ELIN: ND_PRINT("\n\t ECS ELIN id "); nd_printjnp(ndo, tptr + 5, tlv_len - 5); break; default: ND_PRINT("\n\t Location ID "); print_unknown_data(ndo, tptr + 5, "\n\t ", tlv_len - 5); } break; case LLDP_PRIVATE_TIA_SUBTYPE_EXTENDED_POWER_MDI: if (tlv_len < 7) { return hexdump; } ND_PRINT("\n\t Power type [%s]", (GET_U_1(tptr + 4) & 0xC0 >> 6) ? "PD device" : "PSE device"); ND_PRINT(", Power source [%s]", tok2str(lldp_tia_power_source_values, "none", (GET_U_1((tptr + 4)) & 0x30) >> 4)); ND_PRINT("\n\t Power priority [%s] (0x%02x)", tok2str(lldp_tia_power_priority_values, "none", GET_U_1(tptr + 4) & 0x0f), GET_U_1(tptr + 4) & 0x0f); power_val = GET_BE_U_2(tptr + 5); if (power_val < LLDP_TIA_POWER_VAL_MAX) { ND_PRINT(", Power %.1f Watts", ((float)power_val) / 10); } else { ND_PRINT(", Power %u (Reserved)", power_val); } break; case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_HARDWARE_REV: case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_FIRMWARE_REV: case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SOFTWARE_REV: case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_SERIAL_NUMBER: case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MANUFACTURER_NAME: case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_MODEL_NAME: case LLDP_PRIVATE_TIA_SUBTYPE_INVENTORY_ASSET_ID: ND_PRINT("\n\t %s ", tok2str(lldp_tia_inventory_values, "unknown", subtype)); nd_printjnp(ndo, tptr + 4, tlv_len - 4); break; default: hexdump = TRUE; break; } return hexdump; } /* * Print DCBX Protocol fields (V 1.01). */ static int lldp_private_dcbx_print(netdissect_options *ndo, const u_char *pptr, u_int len) { int hexdump = FALSE; u_int subtype; uint16_t tval; uint16_t tlv; uint32_t i, pgval, uval; u_int tlen, tlv_type; uint16_t tlv_len; const u_char *tptr, *mptr; if (len < 4) { return hexdump; } subtype = GET_U_1(pptr + 3); ND_PRINT("\n\t %s Subtype (%u)", tok2str(lldp_dcbx_subtype_values, "unknown", subtype), subtype); /* by passing old version */ if (subtype == LLDP_DCBX_SUBTYPE_1) return TRUE; tptr = pptr + 4; tlen = len - 4; while (tlen >= sizeof(tlv)) { ND_TCHECK_LEN(tptr, sizeof(tlv)); tlv = GET_BE_U_2(tptr); tlv_type = LLDP_EXTRACT_TYPE(tlv); tlv_len = LLDP_EXTRACT_LEN(tlv); hexdump = FALSE; tlen -= sizeof(tlv); tptr += sizeof(tlv); /* loop check */ if (!tlv_type || !tlv_len) { break; } ND_TCHECK_LEN(tptr, tlv_len); if (tlen < tlv_len) { goto trunc; } /* decode every tlv */ switch (tlv_type) { case LLDP_DCBX_CONTROL_TLV: if (tlv_len < 10) { goto trunc; } ND_PRINT("\n\t Control - Protocol Control (type 0x%x, length %u)", LLDP_DCBX_CONTROL_TLV, tlv_len); ND_PRINT("\n\t Oper_Version: %u", GET_U_1(tptr)); ND_PRINT("\n\t Max_Version: %u", GET_U_1(tptr + 1)); ND_PRINT("\n\t Sequence Number: %u", GET_BE_U_4(tptr + 2)); ND_PRINT("\n\t Acknowledgement Number: %u", GET_BE_U_4(tptr + 6)); break; case LLDP_DCBX_PRIORITY_GROUPS_TLV: if (tlv_len < 17) { goto trunc; } ND_PRINT("\n\t Feature - Priority Group (type 0x%x, length %u)", LLDP_DCBX_PRIORITY_GROUPS_TLV, tlv_len); ND_PRINT("\n\t Oper_Version: %u", GET_U_1(tptr)); ND_PRINT("\n\t Max_Version: %u", GET_U_1(tptr + 1)); ND_PRINT("\n\t Info block(0x%02X): ", GET_U_1(tptr + 2)); tval = GET_U_1(tptr + 2); ND_PRINT("Enable bit: %u, Willing bit: %u, Error Bit: %u", (tval & 0x80) ? 1 : 0, (tval & 0x40) ? 1 : 0, (tval & 0x20) ? 1 : 0); ND_PRINT("\n\t SubType: %u", GET_U_1(tptr + 3)); ND_PRINT("\n\t Priority Allocation"); /* * Array of 8 4-bit priority group ID values; we fetch all * 32 bits and extract each nibble. */ pgval = GET_BE_U_4(tptr + 4); for (i = 0; i <= 7; i++) { ND_PRINT("\n\t PgId_%u: %u", i, (pgval >> (28 - 4 * i)) & 0xF); } ND_PRINT("\n\t Priority Group Allocation"); for (i = 0; i <= 7; i++) ND_PRINT("\n\t Pg percentage[%u]: %u", i, GET_U_1(tptr + 8 + i)); ND_PRINT("\n\t NumTCsSupported: %u", GET_U_1(tptr + 8 + 8)); break; case LLDP_DCBX_PRIORITY_FLOW_CONTROL_TLV: if (tlv_len < 6) { goto trunc; } ND_PRINT("\n\t Feature - Priority Flow Control"); ND_PRINT(" (type 0x%x, length %u)", LLDP_DCBX_PRIORITY_FLOW_CONTROL_TLV, tlv_len); ND_PRINT("\n\t Oper_Version: %u", GET_U_1(tptr)); ND_PRINT("\n\t Max_Version: %u", GET_U_1(tptr + 1)); ND_PRINT("\n\t Info block(0x%02X): ", GET_U_1(tptr + 2)); tval = GET_U_1(tptr + 2); ND_PRINT("Enable bit: %u, Willing bit: %u, Error Bit: %u", (tval & 0x80) ? 1 : 0, (tval & 0x40) ? 1 : 0, (tval & 0x20) ? 1 : 0); ND_PRINT("\n\t SubType: %u", GET_U_1(tptr + 3)); tval = GET_U_1(tptr + 4); ND_PRINT("\n\t PFC Config (0x%02X)", GET_U_1(tptr + 4)); for (i = 0; i <= 7; i++) ND_PRINT("\n\t Priority Bit %u: %s", i, (tval & (1 << i)) ? "Enabled" : "Disabled"); ND_PRINT("\n\t NumTCPFCSupported: %u", GET_U_1(tptr + 5)); break; case LLDP_DCBX_APPLICATION_TLV: if (tlv_len < 4) { goto trunc; } ND_PRINT("\n\t Feature - Application (type 0x%x, length %u)", LLDP_DCBX_APPLICATION_TLV, tlv_len); ND_PRINT("\n\t Oper_Version: %u", GET_U_1(tptr)); ND_PRINT("\n\t Max_Version: %u", GET_U_1(tptr + 1)); ND_PRINT("\n\t Info block(0x%02X): ", GET_U_1(tptr + 2)); tval = GET_U_1(tptr + 2); ND_PRINT("Enable bit: %u, Willing bit: %u, Error Bit: %u", (tval & 0x80) ? 1 : 0, (tval & 0x40) ? 1 : 0, (tval & 0x20) ? 1 : 0); ND_PRINT("\n\t SubType: %u", GET_U_1(tptr + 3)); tval = tlv_len - 4; mptr = tptr + 4; while (tval >= 6) { ND_PRINT("\n\t Application Value"); ND_PRINT("\n\t Application Protocol ID: 0x%04x", GET_BE_U_2(mptr)); uval = GET_BE_U_3(mptr + 2); ND_PRINT("\n\t SF (0x%x) Application Protocol ID is %s", (uval >> 22), (uval >> 22) ? "Socket Number" : "L2 EtherType"); ND_PRINT("\n\t OUI: 0x%06x", uval & 0x3fffff); ND_PRINT("\n\t User Priority Map: 0x%02x", GET_U_1(mptr + 5)); tval = tval - 6; mptr = mptr + 6; } break; default: hexdump = TRUE; break; } /* do we also want to see a hex dump ? */ if (ndo->ndo_vflag > 1 || (ndo->ndo_vflag && hexdump)) { print_unknown_data(ndo, tptr, "\n\t ", tlv_len); } tlen -= tlv_len; tptr += tlv_len; } trunc: return hexdump; } static char * lldp_network_addr_print(netdissect_options *ndo, const u_char *tptr, u_int len) { uint8_t af; static char buf[BUFSIZE]; const char * (*pfunc)(netdissect_options *, const u_char *); if (len < 1) return NULL; len--; af = GET_U_1(tptr); switch (af) { case AFNUM_INET: if (len < sizeof(nd_ipv4)) return NULL; pfunc = ipaddr_string; break; case AFNUM_INET6: if (len < sizeof(nd_ipv6)) return NULL; pfunc = ip6addr_string; break; case AFNUM_802: if (len < MAC_ADDR_LEN) return NULL; pfunc = etheraddr_string; break; default: pfunc = NULL; break; } if (!pfunc) { snprintf(buf, sizeof(buf), "AFI %s (%u), no AF printer !", tok2str(af_values, "Unknown", af), af); } else { snprintf(buf, sizeof(buf), "AFI %s (%u): %s", tok2str(af_values, "Unknown", af), af, (*pfunc)(ndo, tptr+1)); } return buf; } static int lldp_mgmt_addr_tlv_print(netdissect_options *ndo, const u_char *pptr, u_int len) { uint8_t mgmt_addr_len, intf_num_subtype, oid_len; const u_char *tptr; u_int tlen; char *mgmt_addr; tlen = len; tptr = pptr; if (tlen < 1) { return 0; } mgmt_addr_len = GET_U_1(tptr); tptr++; tlen--; if (tlen < mgmt_addr_len) { return 0; } mgmt_addr = lldp_network_addr_print(ndo, tptr, mgmt_addr_len); if (mgmt_addr == NULL) { return 0; } ND_PRINT("\n\t Management Address length %u, %s", mgmt_addr_len, mgmt_addr); tptr += mgmt_addr_len; tlen -= mgmt_addr_len; if (tlen < LLDP_INTF_NUM_LEN) { return 0; } intf_num_subtype = GET_U_1(tptr); ND_PRINT("\n\t %s Interface Numbering (%u): %u", tok2str(lldp_intf_numb_subtype_values, "Unknown", intf_num_subtype), intf_num_subtype, GET_BE_U_4(tptr + 1)); tptr += LLDP_INTF_NUM_LEN; tlen -= LLDP_INTF_NUM_LEN; /* * The OID is optional. */ if (tlen) { oid_len = GET_U_1(tptr); if (tlen < 1U + oid_len) { return 0; } if (oid_len) { ND_PRINT("\n\t OID length %u", oid_len); nd_printjnp(ndo, tptr + 1, oid_len); } } return 1; } void lldp_print(netdissect_options *ndo, const u_char *pptr, u_int len) { uint8_t subtype; uint16_t tlv, cap, ena_cap; u_int oui, tlen, hexdump, tlv_type, tlv_len; const u_char *tptr; char *network_addr; ndo->ndo_protocol = "lldp"; tptr = pptr; tlen = len; ND_PRINT("LLDP, length %u", len); while (tlen >= sizeof(tlv)) { ND_TCHECK_LEN(tptr, sizeof(tlv)); tlv = GET_BE_U_2(tptr); tlv_type = LLDP_EXTRACT_TYPE(tlv); tlv_len = LLDP_EXTRACT_LEN(tlv); hexdump = FALSE; tlen -= sizeof(tlv); tptr += sizeof(tlv); if (ndo->ndo_vflag) { ND_PRINT("\n\t%s TLV (%u), length %u", tok2str(lldp_tlv_values, "Unknown", tlv_type), tlv_type, tlv_len); } /* infinite loop check */ if (!tlv_type || !tlv_len) { break; } ND_TCHECK_LEN(tptr, tlv_len); if (tlen < tlv_len) { goto trunc; } switch (tlv_type) { case LLDP_CHASSIS_ID_TLV: if (ndo->ndo_vflag) { if (tlv_len < 2) { goto trunc; } subtype = GET_U_1(tptr); ND_PRINT("\n\t Subtype %s (%u): ", tok2str(lldp_chassis_subtype_values, "Unknown", subtype), subtype); switch (subtype) { case LLDP_CHASSIS_MAC_ADDR_SUBTYPE: if (tlv_len < 1+6) { goto trunc; } ND_PRINT("%s", GET_ETHERADDR_STRING(tptr + 1)); break; case LLDP_CHASSIS_INTF_NAME_SUBTYPE: /* fall through */ case LLDP_CHASSIS_LOCAL_SUBTYPE: case LLDP_CHASSIS_CHASSIS_COMP_SUBTYPE: case LLDP_CHASSIS_INTF_ALIAS_SUBTYPE: case LLDP_CHASSIS_PORT_COMP_SUBTYPE: nd_printjnp(ndo, tptr + 1, tlv_len - 1); break; case LLDP_CHASSIS_NETWORK_ADDR_SUBTYPE: network_addr = lldp_network_addr_print(ndo, tptr+1, tlv_len-1); if (network_addr == NULL) { goto trunc; } ND_PRINT("%s", network_addr); break; default: hexdump = TRUE; break; } } break; case LLDP_PORT_ID_TLV: if (ndo->ndo_vflag) { if (tlv_len < 2) { goto trunc; } subtype = GET_U_1(tptr); ND_PRINT("\n\t Subtype %s (%u): ", tok2str(lldp_port_subtype_values, "Unknown", subtype), subtype); switch (subtype) { case LLDP_PORT_MAC_ADDR_SUBTYPE: if (tlv_len < 1+6) { goto trunc; } ND_PRINT("%s", GET_ETHERADDR_STRING(tptr + 1)); break; case LLDP_PORT_INTF_NAME_SUBTYPE: /* fall through */ case LLDP_PORT_LOCAL_SUBTYPE: case LLDP_PORT_AGENT_CIRC_ID_SUBTYPE: case LLDP_PORT_INTF_ALIAS_SUBTYPE: case LLDP_PORT_PORT_COMP_SUBTYPE: nd_printjnp(ndo, tptr + 1, tlv_len - 1); break; case LLDP_PORT_NETWORK_ADDR_SUBTYPE: network_addr = lldp_network_addr_print(ndo, tptr+1, tlv_len-1); if (network_addr == NULL) { goto trunc; } ND_PRINT("%s", network_addr); break; default: hexdump = TRUE; break; } } break; case LLDP_TTL_TLV: if (ndo->ndo_vflag) { if (tlv_len < 2) { goto trunc; } ND_PRINT(": TTL %us", GET_BE_U_2(tptr)); } break; case LLDP_PORT_DESCR_TLV: if (ndo->ndo_vflag) { ND_PRINT(": "); nd_printjnp(ndo, tptr, tlv_len); } break; case LLDP_SYSTEM_NAME_TLV: /* * The system name is also print in non-verbose mode * similar to the CDP printer. */ ND_PRINT(": "); nd_printjnp(ndo, tptr, tlv_len); break; case LLDP_SYSTEM_DESCR_TLV: if (ndo->ndo_vflag) { ND_PRINT("\n\t "); nd_printjnp(ndo, tptr, tlv_len); } break; case LLDP_SYSTEM_CAP_TLV: if (ndo->ndo_vflag) { /* * XXX - IEEE Std 802.1AB-2009 says the first octet * if a chassis ID subtype, with the system * capabilities and enabled capabilities following * it. */ if (tlv_len < 4) { goto trunc; } cap = GET_BE_U_2(tptr); ena_cap = GET_BE_U_2(tptr + 2); ND_PRINT("\n\t System Capabilities [%s] (0x%04x)", bittok2str(lldp_cap_values, "none", cap), cap); ND_PRINT("\n\t Enabled Capabilities [%s] (0x%04x)", bittok2str(lldp_cap_values, "none", ena_cap), ena_cap); } break; case LLDP_MGMT_ADDR_TLV: if (ndo->ndo_vflag) { if (!lldp_mgmt_addr_tlv_print(ndo, tptr, tlv_len)) { goto trunc; } } break; case LLDP_PRIVATE_TLV: if (ndo->ndo_vflag) { if (tlv_len < 3) { goto trunc; } oui = GET_BE_U_3(tptr); ND_PRINT(": OUI %s (0x%06x)", tok2str(oui_values, "Unknown", oui), oui); switch (oui) { case OUI_IEEE_8021_PRIVATE: hexdump = lldp_private_8021_print(ndo, tptr, tlv_len); break; case OUI_IEEE_8023_PRIVATE: hexdump = lldp_private_8023_print(ndo, tptr, tlv_len); break; case OUI_IANA: hexdump = lldp_private_iana_print(ndo, tptr, tlv_len); break; case OUI_TIA: hexdump = lldp_private_tia_print(ndo, tptr, tlv_len); break; case OUI_DCBX: hexdump = lldp_private_dcbx_print(ndo, tptr, tlv_len); break; default: hexdump = TRUE; break; } } break; default: hexdump = TRUE; break; } /* do we also want to see a hex dump ? */ if (ndo->ndo_vflag > 1 || (ndo->ndo_vflag && hexdump)) { print_unknown_data(ndo, tptr, "\n\t ", tlv_len); } tlen -= tlv_len; tptr += tlv_len; } return; trunc: nd_print_trunc(ndo); } tcpdump-4.99.1/print-telnet.c0000644000026300017510000003531614057477727014242 0ustar mcrmcr/* $NetBSD: print-telnet.c,v 1.2 1999/10/11 12:40:12 sjg Exp $ */ /*- * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by Simon J. Gerraty. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the NetBSD * Foundation, Inc. and its contributors. * 4. Neither the name of The NetBSD Foundation 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 BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * @(#)Copyright (c) 1994, Simon J. Gerraty. * * This is free software. It comes with NO WARRANTY. * Permission to use, modify and distribute this source code * is granted subject to the following conditions. * 1/ that the above copyright notice and this notice * are preserved in all copies. */ /* \summary: Telnet option printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include #include "netdissect.h" #include "extract.h" /* NetBSD: telnet.h,v 1.9 2001/06/11 01:50:50 wiz Exp */ /* * Definitions for the TELNET protocol. */ #define IAC 255 /* interpret as command: */ #define DONT 254 /* you are not to use option */ #define DO 253 /* please, you use option */ #define WONT 252 /* I won't use option */ #define WILL 251 /* I will use option */ #define SB 250 /* interpret as subnegotiation */ #define GA 249 /* you may reverse the line */ #define EL 248 /* erase the current line */ #define EC 247 /* erase the current character */ #define AYT 246 /* are you there */ #define AO 245 /* abort output--but let prog finish */ #define IP 244 /* interrupt process--permanently */ #define BREAK 243 /* break */ #define DM 242 /* data mark--for connect. cleaning */ #define NOP 241 /* nop */ #define SE 240 /* end sub negotiation */ #define EOR 239 /* end of record (transparent mode) */ #define ABORT 238 /* Abort process */ #define SUSP 237 /* Suspend process */ #define xEOF 236 /* End of file: EOF is already used... */ #define SYNCH 242 /* for telfunc calls */ static const char *telcmds[] = { "EOF", "SUSP", "ABORT", "EOR", "SE", "NOP", "DMARK", "BRK", "IP", "AO", "AYT", "EC", "EL", "GA", "SB", "WILL", "WONT", "DO", "DONT", "IAC", 0, }; #define TELCMD_FIRST xEOF #define TELCMD_LAST IAC #define TELCMD_OK(x) ((unsigned int)(x) <= TELCMD_LAST && \ (unsigned int)(x) >= TELCMD_FIRST) #define TELCMD(x) telcmds[(x)-TELCMD_FIRST] /* telnet options */ #define TELOPT_BINARY 0 /* 8-bit data path */ #define TELOPT_ECHO 1 /* echo */ #define TELOPT_RCP 2 /* prepare to reconnect */ #define TELOPT_SGA 3 /* suppress go ahead */ #define TELOPT_NAMS 4 /* approximate message size */ #define TELOPT_STATUS 5 /* give status */ #define TELOPT_TM 6 /* timing mark */ #define TELOPT_RCTE 7 /* remote controlled transmission and echo */ #define TELOPT_NAOL 8 /* negotiate about output line width */ #define TELOPT_NAOP 9 /* negotiate about output page size */ #define TELOPT_NAOCRD 10 /* negotiate about CR disposition */ #define TELOPT_NAOHTS 11 /* negotiate about horizontal tabstops */ #define TELOPT_NAOHTD 12 /* negotiate about horizontal tab disposition */ #define TELOPT_NAOFFD 13 /* negotiate about formfeed disposition */ #define TELOPT_NAOVTS 14 /* negotiate about vertical tab stops */ #define TELOPT_NAOVTD 15 /* negotiate about vertical tab disposition */ #define TELOPT_NAOLFD 16 /* negotiate about output LF disposition */ #define TELOPT_XASCII 17 /* extended ascic character set */ #define TELOPT_LOGOUT 18 /* force logout */ #define TELOPT_BM 19 /* byte macro */ #define TELOPT_DET 20 /* data entry terminal */ #define TELOPT_SUPDUP 21 /* supdup protocol */ #define TELOPT_SUPDUPOUTPUT 22 /* supdup output */ #define TELOPT_SNDLOC 23 /* send location */ #define TELOPT_TTYPE 24 /* terminal type */ #define TELOPT_EOR 25 /* end or record */ #define TELOPT_TUID 26 /* TACACS user identification */ #define TELOPT_OUTMRK 27 /* output marking */ #define TELOPT_TTYLOC 28 /* terminal location number */ #define TELOPT_3270REGIME 29 /* 3270 regime */ #define TELOPT_X3PAD 30 /* X.3 PAD */ #define TELOPT_NAWS 31 /* window size */ #define TELOPT_TSPEED 32 /* terminal speed */ #define TELOPT_LFLOW 33 /* remote flow control */ #define TELOPT_LINEMODE 34 /* Linemode option */ #define TELOPT_XDISPLOC 35 /* X Display Location */ #define TELOPT_OLD_ENVIRON 36 /* Old - Environment variables */ #define TELOPT_AUTHENTICATION 37/* Authenticate */ #define TELOPT_ENCRYPT 38 /* Encryption option */ #define TELOPT_NEW_ENVIRON 39 /* New - Environment variables */ #define TELOPT_EXOPL 255 /* extended-options-list */ #define NTELOPTS (1+TELOPT_NEW_ENVIRON) static const char *telopts[NTELOPTS+1] = { "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME", "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP", "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS", "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO", "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT", "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD", "TACACS UID", "OUTPUT MARKING", "TTYLOC", "3270 REGIME", "X.3 PAD", "NAWS", "TSPEED", "LFLOW", "LINEMODE", "XDISPLOC", "OLD-ENVIRON", "AUTHENTICATION", "ENCRYPT", "NEW-ENVIRON", 0, }; #define TELOPT_FIRST TELOPT_BINARY #define TELOPT_LAST TELOPT_NEW_ENVIRON #define TELOPT_OK(x) ((unsigned int)(x) <= TELOPT_LAST) #define TELOPT(x) telopts[(x)-TELOPT_FIRST] /* sub-option qualifiers */ #define TELQUAL_IS 0 /* option is... */ #define TELQUAL_SEND 1 /* send option */ #define TELQUAL_INFO 2 /* ENVIRON: informational version of IS */ #define TELQUAL_REPLY 2 /* AUTHENTICATION: client version of IS */ #define TELQUAL_NAME 3 /* AUTHENTICATION: client version of IS */ #define LFLOW_OFF 0 /* Disable remote flow control */ #define LFLOW_ON 1 /* Enable remote flow control */ #define LFLOW_RESTART_ANY 2 /* Restart output on any char */ #define LFLOW_RESTART_XON 3 /* Restart output only on XON */ /* * LINEMODE suboptions */ #define LM_MODE 1 #define LM_FORWARDMASK 2 #define LM_SLC 3 #define MODE_EDIT 0x01 #define MODE_TRAPSIG 0x02 #define MODE_ACK 0x04 #define MODE_SOFT_TAB 0x08 #define MODE_LIT_ECHO 0x10 #define MODE_MASK 0x1f #define SLC_SYNCH 1 #define SLC_BRK 2 #define SLC_IP 3 #define SLC_AO 4 #define SLC_AYT 5 #define SLC_EOR 6 #define SLC_ABORT 7 #define SLC_EOF 8 #define SLC_SUSP 9 #define SLC_EC 10 #define SLC_EL 11 #define SLC_EW 12 #define SLC_RP 13 #define SLC_LNEXT 14 #define SLC_XON 15 #define SLC_XOFF 16 #define SLC_FORW1 17 #define SLC_FORW2 18 #define SLC_MCL 19 #define SLC_MCR 20 #define SLC_MCWL 21 #define SLC_MCWR 22 #define SLC_MCBOL 23 #define SLC_MCEOL 24 #define SLC_INSRT 25 #define SLC_OVER 26 #define SLC_ECR 27 #define SLC_EWR 28 #define SLC_EBOL 29 #define SLC_EEOL 30 #define NSLC 30 /* * For backwards compatibility, we define SLC_NAMES to be the * list of names if SLC_NAMES is not defined. */ #define SLC_NAMELIST "0", "SYNCH", "BRK", "IP", "AO", "AYT", "EOR", \ "ABORT", "EOF", "SUSP", "EC", "EL", "EW", "RP", \ "LNEXT", "XON", "XOFF", "FORW1", "FORW2", \ "MCL", "MCR", "MCWL", "MCWR", "MCBOL", \ "MCEOL", "INSRT", "OVER", "ECR", "EWR", \ "EBOL", "EEOL", \ 0, #ifdef SLC_NAMES const char *slc_names[] = { SLC_NAMELIST }; #else extern char *slc_names[]; #define SLC_NAMES SLC_NAMELIST #endif #define SLC_NAME_OK(x) ((unsigned int)(x) <= NSLC) #define SLC_NAME(x) slc_names[x] #define SLC_NOSUPPORT 0 #define SLC_CANTCHANGE 1 #define SLC_VARIABLE 2 #define SLC_DEFAULT 3 #define SLC_LEVELBITS 0x03 #define SLC_FUNC 0 #define SLC_FLAGS 1 #define SLC_VALUE 2 #define SLC_ACK 0x80 #define SLC_FLUSHIN 0x40 #define SLC_FLUSHOUT 0x20 #define OLD_ENV_VAR 1 #define OLD_ENV_VALUE 0 #define NEW_ENV_VAR 0 #define NEW_ENV_VALUE 1 #define ENV_ESC 2 #define ENV_USERVAR 3 /* * AUTHENTICATION suboptions */ /* * Who is authenticating who ... */ #define AUTH_WHO_CLIENT 0 /* Client authenticating server */ #define AUTH_WHO_SERVER 1 /* Server authenticating client */ #define AUTH_WHO_MASK 1 #define AUTHTYPE_NULL 0 #define AUTHTYPE_KERBEROS_V4 1 #define AUTHTYPE_KERBEROS_V5 2 #define AUTHTYPE_SPX 3 #define AUTHTYPE_MINK 4 #define AUTHTYPE_CNT 5 #define AUTHTYPE_TEST 99 #ifdef AUTH_NAMES const char *authtype_names[] = { "NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", 0, }; #else extern char *authtype_names[]; #endif #define AUTHTYPE_NAME_OK(x) ((unsigned int)(x) < AUTHTYPE_CNT) #define AUTHTYPE_NAME(x) authtype_names[x] /* * ENCRYPTion suboptions */ #define ENCRYPT_IS 0 /* I pick encryption type ... */ #define ENCRYPT_SUPPORT 1 /* I support encryption types ... */ #define ENCRYPT_REPLY 2 /* Initial setup response */ #define ENCRYPT_START 3 /* Am starting to send encrypted */ #define ENCRYPT_END 4 /* Am ending encrypted */ #define ENCRYPT_REQSTART 5 /* Request you start encrypting */ #define ENCRYPT_REQEND 6 /* Request you send encrypting */ #define ENCRYPT_ENC_KEYID 7 #define ENCRYPT_DEC_KEYID 8 #define ENCRYPT_CNT 9 #define ENCTYPE_ANY 0 #define ENCTYPE_DES_CFB64 1 #define ENCTYPE_DES_OFB64 2 #define ENCTYPE_CNT 3 #ifdef ENCRYPT_NAMES const char *encrypt_names[] = { "IS", "SUPPORT", "REPLY", "START", "END", "REQUEST-START", "REQUEST-END", "ENC-KEYID", "DEC-KEYID", 0, }; const char *enctype_names[] = { "ANY", "DES_CFB64", "DES_OFB64", 0, }; #else extern char *encrypt_names[]; extern char *enctype_names[]; #endif #define ENCRYPT_NAME_OK(x) ((unsigned int)(x) < ENCRYPT_CNT) #define ENCRYPT_NAME(x) encrypt_names[x] #define ENCTYPE_NAME_OK(x) ((unsigned int)(x) < ENCTYPE_CNT) #define ENCTYPE_NAME(x) enctype_names[x] /* normal */ static const char *cmds[] = { "IS", "SEND", "INFO", }; /* 37: Authentication */ static const char *authcmd[] = { "IS", "SEND", "REPLY", "NAME", }; static const char *authtype[] = { "NULL", "KERBEROS_V4", "KERBEROS_V5", "SPX", "MINK", "SRP", "RSA", "SSL", NULL, NULL, "LOKI", "SSA", "KEA_SJ", "KEA_SJ_INTEG", "DSS", "NTLM", }; /* 38: Encryption */ static const char *enccmd[] = { "IS", "SUPPORT", "REPLY", "START", "END", "REQUEST-START", "REQUEST-END", "END_KEYID", "DEC_KEYID", }; static const char *enctype[] = { "NULL", "DES_CFB64", "DES_OFB64", "DES3_CFB64", "DES3_OFB64", NULL, "CAST5_40_CFB64", "CAST5_40_OFB64", "CAST128_CFB64", "CAST128_OFB64", }; #define STR_OR_ID(x, tab) \ (((x) < sizeof(tab)/sizeof(tab[0]) && tab[(x)]) ? tab[(x)] : numstr(x)) static char * numstr(int x) { static char buf[20]; snprintf(buf, sizeof(buf), "%#x", x); return buf; } /* sp points to IAC byte */ static int telnet_parse(netdissect_options *ndo, const u_char *sp, u_int length, int print) { int i, x; u_int c; const u_char *osp, *p; #define FETCH(c, sp, length) \ do { \ if (length < 1) \ goto pktend; \ c = GET_U_1(sp); \ sp++; \ length--; \ } while (0) osp = sp; FETCH(c, sp, length); if (c != IAC) goto pktend; FETCH(c, sp, length); if (c == IAC) { /* ! */ if (print) ND_PRINT("IAC IAC"); goto done; } i = c - TELCMD_FIRST; if (i < 0 || i > IAC - TELCMD_FIRST) goto pktend; switch (c) { case DONT: case DO: case WONT: case WILL: case SB: /* DONT/DO/WONT/WILL x */ FETCH(x, sp, length); if (x >= 0 && x < NTELOPTS) { if (print) ND_PRINT("%s %s", telcmds[i], telopts[x]); } else { if (print) ND_PRINT("%s %#x", telcmds[i], x); } if (c != SB) break; /* IAC SB .... IAC SE */ p = sp; while (length > (u_int)(p + 1 - sp)) { if (GET_U_1(p) == IAC && GET_U_1(p + 1) == SE) break; p++; } if (GET_U_1(p) != IAC) goto pktend; switch (x) { case TELOPT_AUTHENTICATION: if (p <= sp) break; FETCH(c, sp, length); if (print) ND_PRINT(" %s", STR_OR_ID(c, authcmd)); if (p <= sp) break; FETCH(c, sp, length); if (print) ND_PRINT(" %s", STR_OR_ID(c, authtype)); break; case TELOPT_ENCRYPT: if (p <= sp) break; FETCH(c, sp, length); if (print) ND_PRINT(" %s", STR_OR_ID(c, enccmd)); if (p <= sp) break; FETCH(c, sp, length); if (print) ND_PRINT(" %s", STR_OR_ID(c, enctype)); break; default: if (p <= sp) break; FETCH(c, sp, length); if (print) ND_PRINT(" %s", STR_OR_ID(c, cmds)); break; } while (p > sp) { FETCH(x, sp, length); if (print) ND_PRINT(" %#x", x); } /* terminating IAC SE */ if (print) ND_PRINT(" SE"); sp += 2; break; default: if (print) ND_PRINT("%s", telcmds[i]); goto done; } done: return (int)(sp - osp); pktend: return -1; #undef FETCH } void telnet_print(netdissect_options *ndo, const u_char *sp, u_int length) { int first = 1; const u_char *osp; int l; ndo->ndo_protocol = "telnet"; osp = sp; while (length > 0 && GET_U_1(sp) == IAC) { /* * Parse the Telnet command without printing it, * to determine its length. */ l = telnet_parse(ndo, sp, length, 0); if (l < 0) break; /* * now print it */ if (ndo->ndo_Xflag && 2 < ndo->ndo_vflag) { if (first) ND_PRINT("\nTelnet:"); hex_print_with_offset(ndo, "\n", sp, l, (u_int)(sp - osp)); if (l > 8) ND_PRINT("\n\t\t\t\t"); else ND_PRINT("%*s\t", (8 - l) * 3, ""); } else ND_PRINT("%s", (first) ? " [telnet " : ", "); (void)telnet_parse(ndo, sp, length, 1); first = 0; sp += l; length -= l; } if (!first) { if (ndo->ndo_Xflag && 2 < ndo->ndo_vflag) ND_PRINT("\n"); else ND_PRINT("]"); } } tcpdump-4.99.1/VERSION0000644000026300017510000000000714060212433012455 0ustar mcrmcr4.99.1 tcpdump-4.99.1/parsenfsfh.c0000644000026300017510000003044114057477727013746 0ustar mcrmcr/* * Copyright (c) 1993, 1994 Jeffrey C. Mogul, Digital Equipment Corporation, * Western Research Laboratory. All rights reserved. * Copyright (c) 2001 Compaq Computer Corporation. All rights reserved. * * Permission to use, copy, and modify this software and its * documentation is hereby granted only under the following terms and * conditions. Both the above copyright notice and this permission * notice must appear in all copies of the software, derivative works * or modified versions, and any portions thereof, and both notices * must appear in supporting documentation. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * THE SOFTWARE IS PROVIDED "AS IS" AND COMPAQ COMPUTER CORPORATION * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO * EVENT SHALL COMPAQ COMPUTER CORPORATION BE LIABLE FOR ANY * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS * SOFTWARE. */ /* * parsenfsfh.c - portable parser for NFS file handles * uses all sorts of heuristics * * Jeffrey C. Mogul * Digital Equipment Corporation * Western Research Laboratory */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include #include #include "netdissect-ctype.h" #include "netdissect.h" #include "extract.h" #include "nfsfh.h" /* * This routine attempts to parse a file handle (in network byte order), * using heuristics to guess what kind of format it is in. See the * file "fhandle_layouts" for a detailed description of the various * patterns we know about. * * The file handle is parsed into our internal representation of a * file-system id, and an internal representation of an inode-number. */ #define FHT_UNKNOWN 0 #define FHT_AUSPEX 1 #define FHT_DECOSF 2 #define FHT_IRIX4 3 #define FHT_IRIX5 4 #define FHT_SUNOS3 5 #define FHT_SUNOS4 6 #define FHT_ULTRIX 7 #define FHT_VMSUCX 8 #define FHT_SUNOS5 9 #define FHT_AIX32 10 #define FHT_HPUX9 11 #define FHT_BSD44 12 static int is_UCX(netdissect_options *, const unsigned char *, u_int); void Parse_fh(netdissect_options *ndo, const unsigned char *fh, u_int len, my_fsid *fsidp, uint32_t *inop, const char **osnamep, /* if non-NULL, return OS name here */ const char **fsnamep, /* if non-NULL, return server fs name here (for VMS) */ int ourself) /* true if file handle was generated on this host */ { const unsigned char *fhp = fh; uint32_t temp; int fhtype = FHT_UNKNOWN; u_int i; /* * Require at least 16 bytes of file handle; it's variable-length * in NFSv3. "len" is in units of 32-bit words, not bytes. */ if (len < 16/4) fhtype = FHT_UNKNOWN; else { if (ourself) { /* File handle generated on this host, no need for guessing */ #if defined(IRIX40) fhtype = FHT_IRIX4; #endif #if defined(IRIX50) fhtype = FHT_IRIX5; #endif #if defined(IRIX51) fhtype = FHT_IRIX5; #endif #if defined(SUNOS4) fhtype = FHT_SUNOS4; #endif #if defined(SUNOS5) fhtype = FHT_SUNOS5; #endif #if defined(ultrix) fhtype = FHT_ULTRIX; #endif #if defined(__osf__) fhtype = FHT_DECOSF; #endif #if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) \ || defined(__OpenBSD__) fhtype = FHT_BSD44; #endif } /* * This is basically a big decision tree */ else if ((GET_U_1(fhp) == 0) && (GET_U_1(fhp + 1) == 0)) { /* bytes[0,1] == (0,0); rules out Ultrix, IRIX5, SUNOS5 */ /* probably rules out HP-UX, AIX unless they allow major=0 */ if ((GET_U_1(fhp + 2) == 0) && (GET_U_1(fhp + 3) == 0)) { /* bytes[2,3] == (0,0); must be Auspex */ /* XXX or could be Ultrix+MASSBUS "hp" disk? */ fhtype = FHT_AUSPEX; } else { /* * bytes[2,3] != (0,0); rules out Auspex, could be * DECOSF, SUNOS4, or IRIX4 */ if ((GET_U_1(fhp + 4) != 0) && (GET_U_1(fhp + 5) == 0) && (GET_U_1(fhp + 8) == 12) && (GET_U_1(fhp + 9) == 0)) { /* seems to be DECOSF, with minor == 0 */ fhtype = FHT_DECOSF; } else { /* could be SUNOS4 or IRIX4 */ /* XXX the test of fhp[5] == 8 could be wrong */ if ((GET_U_1(fhp + 4) == 0) && (GET_U_1(fhp + 5) == 8) && (GET_U_1(fhp + 6) == 0) && (GET_U_1(fhp + 7) == 0)) { /* looks like a length, not a file system typecode */ fhtype = FHT_IRIX4; } else { /* by elimination */ fhtype = FHT_SUNOS4; } } } } else { /* * bytes[0,1] != (0,0); rules out Auspex, IRIX4, SUNOS4 * could be IRIX5, DECOSF, UCX, Ultrix, SUNOS5 * could be AIX, HP-UX */ if ((GET_U_1(fhp + 2) == 0) && (GET_U_1(fhp + 3) == 0)) { /* * bytes[2,3] == (0,0); rules out OSF, probably not UCX * (unless the exported device name is just one letter!), * could be Ultrix, IRIX5, AIX, or SUNOS5 * might be HP-UX (depends on their values for minor devs) */ if ((GET_U_1(fhp + 6) == 0) && (GET_U_1(fhp + 7) == 0)) { fhtype = FHT_BSD44; } /*XXX we probably only need to test of these two bytes */ else if ((len >= 24/4) && (GET_U_1(fhp + 21) == 0) && (GET_U_1(fhp + 23) == 0)) { fhtype = FHT_ULTRIX; } else { /* Could be SUNOS5/IRIX5, maybe AIX */ /* XXX no obvious difference between SUNOS5 and IRIX5 */ if (GET_U_1(fhp + 9) == 10) fhtype = FHT_SUNOS5; /* XXX what about AIX? */ } } else { /* * bytes[2,3] != (0,0); rules out Ultrix, could be * DECOSF, SUNOS5, IRIX5, AIX, HP-UX, or UCX */ if ((GET_U_1(fhp + 8) == 12) && (GET_U_1(fhp + 9) == 0)) { fhtype = FHT_DECOSF; } else if ((GET_U_1(fhp + 8) == 0) && (GET_U_1(fhp + 9) == 10)) { /* could be SUNOS5/IRIX5, AIX, HP-UX */ if ((GET_U_1(fhp + 7) == 0) && (GET_U_1(fhp + 6) == 0) && (GET_U_1(fhp + 5) == 0) && (GET_U_1(fhp + 4) == 0)) { /* XXX is this always true of HP-UX? */ fhtype = FHT_HPUX9; } else if (GET_U_1(fhp + 7) == 2) { /* This would be MNT_NFS on AIX, which is impossible */ fhtype = FHT_SUNOS5; /* or maybe IRIX5 */ } else { /* * XXX Could be SUNOS5/IRIX5 or AIX. I don't * XXX see any way to disambiguate these, so * XXX I'm going with the more likely guess. * XXX Sorry, Big Blue. */ fhtype = FHT_SUNOS5; /* or maybe IRIX5 */ } } else { if (is_UCX(ndo, fhp, len)) { fhtype = FHT_VMSUCX; } else { fhtype = FHT_UNKNOWN; } } } } } /* XXX still needs to handle SUNOS3 */ switch (fhtype) { case FHT_AUSPEX: fsidp->Fsid_dev.Minor = GET_U_1(fhp + 7); fsidp->Fsid_dev.Major = GET_U_1(fhp + 6); fsidp->fsid_code = 0; *inop = GET_BE_U_4(fhp + 12); if (osnamep) *osnamep = "Auspex"; break; case FHT_BSD44: fsidp->Fsid_dev.Minor = GET_U_1(fhp); fsidp->Fsid_dev.Major = GET_U_1(fhp + 1); fsidp->fsid_code = 0; *inop = GET_LE_U_4(fhp + 12); if (osnamep) *osnamep = "BSD 4.4"; break; case FHT_DECOSF: fsidp->fsid_code = GET_LE_U_4(fhp + 4); /* XXX could ignore 3 high-order bytes */ temp = GET_LE_U_4(fhp); fsidp->Fsid_dev.Minor = temp & 0xFFFFF; fsidp->Fsid_dev.Major = (temp>>20) & 0xFFF; *inop = GET_LE_U_4(fhp + 12); if (osnamep) *osnamep = "OSF"; break; case FHT_IRIX4: fsidp->Fsid_dev.Minor = GET_U_1(fhp + 3); fsidp->Fsid_dev.Major = GET_U_1(fhp + 2); fsidp->fsid_code = 0; *inop = GET_BE_U_4(fhp + 8); if (osnamep) *osnamep = "IRIX4"; break; case FHT_IRIX5: fsidp->Fsid_dev.Minor = GET_BE_U_2(fhp + 2); fsidp->Fsid_dev.Major = GET_BE_U_2(fhp); fsidp->fsid_code = GET_BE_U_4(fhp + 4); *inop = GET_BE_U_4(fhp + 12); if (osnamep) *osnamep = "IRIX5"; break; #ifdef notdef case FHT_SUNOS3: /* * XXX - none of the heuristics above return this. * Are there any SunOS 3.x systems around to care about? */ if (osnamep) *osnamep = "SUNOS3"; break; #endif case FHT_SUNOS4: fsidp->Fsid_dev.Minor = GET_U_1(fhp + 3); fsidp->Fsid_dev.Major = GET_U_1(fhp + 2); fsidp->fsid_code = GET_BE_U_4(fhp + 4); *inop = GET_BE_U_4(fhp + 12); if (osnamep) *osnamep = "SUNOS4"; break; case FHT_SUNOS5: temp = GET_BE_U_2(fhp); fsidp->Fsid_dev.Major = (temp>>2) & 0x3FFF; temp = GET_BE_U_3(fhp + 1); fsidp->Fsid_dev.Minor = temp & 0x3FFFF; fsidp->fsid_code = GET_BE_U_4(fhp + 4); *inop = GET_BE_U_4(fhp + 12); if (osnamep) *osnamep = "SUNOS5"; break; case FHT_ULTRIX: fsidp->fsid_code = 0; fsidp->Fsid_dev.Minor = GET_U_1(fhp); fsidp->Fsid_dev.Major = GET_U_1(fhp + 1); temp = GET_LE_U_4(fhp + 4); *inop = temp; if (osnamep) *osnamep = "Ultrix"; break; case FHT_VMSUCX: /* No numeric file system ID, so hash on the device-name */ if (sizeof(*fsidp) >= 14) { if (sizeof(*fsidp) > 14) memset((char *)fsidp, 0, sizeof(*fsidp)); /* just use the whole thing */ memcpy((char *)fsidp, (const char *)fh, 14); } else { uint32_t tempa[4]; /* at least 16 bytes, maybe more */ memset((char *)tempa, 0, sizeof(tempa)); memcpy((char *)tempa, (const char *)fh, 14); /* ensure alignment */ fsidp->Fsid_dev.Minor = tempa[0] + (tempa[1]<<1); fsidp->Fsid_dev.Major = tempa[2] + (tempa[3]<<1); fsidp->fsid_code = 0; } /* VMS file ID is: (RVN, FidHi, FidLo) */ *inop = (((uint32_t) GET_U_1(fhp + 26)) << 24) | (((uint32_t) GET_U_1(fhp + 27)) << 16) | (GET_LE_U_2(fhp + 22) << 0); /* Caller must save (and null-terminate?) this value */ if (fsnamep) *fsnamep = (const char *)(fhp + 1); if (osnamep) *osnamep = "VMS"; break; case FHT_AIX32: fsidp->Fsid_dev.Minor = GET_BE_U_2(fhp + 2); fsidp->Fsid_dev.Major = GET_BE_U_2(fhp); fsidp->fsid_code = GET_BE_U_4(fhp + 4); *inop = GET_BE_U_4(fhp + 12); if (osnamep) *osnamep = "AIX32"; break; case FHT_HPUX9: fsidp->Fsid_dev.Major = GET_U_1(fhp); temp = GET_BE_U_3(fhp + 1); fsidp->Fsid_dev.Minor = temp; fsidp->fsid_code = GET_BE_U_4(fhp + 4); *inop = GET_BE_U_4(fhp + 12); if (osnamep) *osnamep = "HPUX9"; break; case FHT_UNKNOWN: #ifdef DEBUG /* XXX debugging */ for (i = 0; i < len*4; i++) (void)fprintf(stderr, "%x.", GET_U_1(fhp + i)); (void)fprintf(stderr, "\n"); #endif /* Save the actual handle, so it can be display with -u */ for (i = 0; i < len*4 && i*2 < sizeof(fsidp->Opaque_Handle) - 1; i++) (void)snprintf(&(fsidp->Opaque_Handle[i*2]), 3, "%.2X", GET_U_1(fhp + i)); fsidp->Opaque_Handle[i*2] = '\0'; /* XXX for now, give "bogus" values to aid debugging */ fsidp->fsid_code = 0; fsidp->Fsid_dev.Minor = 257; fsidp->Fsid_dev.Major = 257; *inop = 1; /* display will show this string instead of (257,257) */ if (fsnamep) *fsnamep = "Unknown"; if (osnamep) *osnamep = "Unknown"; break; } } /* * Is this a VMS UCX file handle? * Check for: * (1) leading code byte [XXX not yet] * (2) followed by string of printing chars & spaces * (3) followed by string of nulls */ static int is_UCX(netdissect_options *ndo, const unsigned char *fhp, u_int len) { u_int i; int seen_null = 0; /* * Require at least 28 bytes of file handle; it's variable-length * in NFSv3. "len" is in units of 32-bit words, not bytes. */ if (len < 28/4) return(0); for (i = 1; i < 14; i++) { if (ND_ASCII_ISPRINT(GET_U_1(fhp + i))) { if (seen_null) return(0); else continue; } else if (GET_U_1(fhp + i) == 0) { seen_null = 1; continue; } else return(0); } return(1); } tcpdump-4.99.1/print-domain.c0000644000026300017510000006631714057477734014221 0ustar mcrmcr/* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 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. */ /* \summary: Domain Name System (DNS) printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include #include "netdissect.h" #include "addrtoname.h" #include "addrtostr.h" #include "extract.h" #include "nameser.h" static const char *ns_ops[] = { "", " inv_q", " stat", " op3", " notify", " update", " op6", " op7", " op8", " updateA", " updateD", " updateDA", " updateM", " updateMA", " zoneInit", " zoneRef", }; static const char *ns_resp[] = { "", " FormErr", " ServFail", " NXDomain", " NotImp", " Refused", " YXDomain", " YXRRSet", " NXRRSet", " NotAuth", " NotZone", " Resp11", " Resp12", " Resp13", " Resp14", " NoChange", " BadVers", "Resp17", " Resp18", " Resp19", " Resp20", "Resp21", " Resp22", " BadCookie", }; static const char * ns_rcode(u_int rcode) { static char buf[sizeof(" Resp4095")]; if (rcode < sizeof(ns_resp)/sizeof(ns_resp[0])) { return (ns_resp[rcode]); } snprintf(buf, sizeof(buf), " Resp%u", rcode & 0xfff); return (buf); } /* skip over a domain name */ static const u_char * ns_nskip(netdissect_options *ndo, const u_char *cp) { u_char i; if (!ND_TTEST_1(cp)) return (NULL); i = GET_U_1(cp); cp++; while (i) { switch (i & TYPE_MASK) { case TYPE_INDIR: return (cp + 1); case TYPE_EDNS0: { int bitlen, bytelen; if ((i & ~TYPE_MASK) != EDNS0_ELT_BITLABEL) return(NULL); /* unknown ELT */ if (!ND_TTEST_1(cp)) return (NULL); if ((bitlen = GET_U_1(cp)) == 0) bitlen = 256; cp++; bytelen = (bitlen + 7) / 8; cp += bytelen; } break; case TYPE_RESERVED: return (NULL); case TYPE_LABEL: cp += i; break; } if (!ND_TTEST_1(cp)) return (NULL); i = GET_U_1(cp); cp++; } return (cp); } static const u_char * blabel_print(netdissect_options *ndo, const u_char *cp) { u_int bitlen, slen, b; const u_char *bitp, *lim; uint8_t tc; if (!ND_TTEST_1(cp)) return(NULL); if ((bitlen = GET_U_1(cp)) == 0) bitlen = 256; slen = (bitlen + 3) / 4; lim = cp + 1 + slen; /* print the bit string as a hex string */ ND_PRINT("\\[x"); for (bitp = cp + 1, b = bitlen; bitp < lim && b > 7; b -= 8, bitp++) { ND_PRINT("%02x", GET_U_1(bitp)); } if (b > 4) { tc = GET_U_1(bitp); bitp++; ND_PRINT("%02x", tc & (0xff << (8 - b))); } else if (b > 0) { tc = GET_U_1(bitp); bitp++; ND_PRINT("%1x", ((tc >> 4) & 0x0f) & (0x0f << (4 - b))); } ND_PRINT("/%u]", bitlen); return lim; } static int labellen(netdissect_options *ndo, const u_char *cp) { u_int i; if (!ND_TTEST_1(cp)) return(-1); i = GET_U_1(cp); switch (i & TYPE_MASK) { case TYPE_EDNS0: { u_int bitlen, elt; if ((elt = (i & ~TYPE_MASK)) != EDNS0_ELT_BITLABEL) { ND_PRINT("", elt); return(-1); } if (!ND_TTEST_1(cp + 1)) return(-1); if ((bitlen = GET_U_1(cp + 1)) == 0) bitlen = 256; return(((bitlen + 7) / 8) + 1); } case TYPE_INDIR: case TYPE_LABEL: return(i); default: /* * TYPE_RESERVED, but we use default to suppress compiler * warnings about falling out of the switch statement. */ ND_PRINT(""); return(-1); } } /* print a */ const u_char * fqdn_print(netdissect_options *ndo, const u_char *cp, const u_char *bp) { u_int i, l; const u_char *rp = NULL; int compress = 0; u_int elt; u_int offset, max_offset; u_int name_chars = 0; if ((l = labellen(ndo, cp)) == (u_int)-1) return(NULL); if (!ND_TTEST_1(cp)) return(NULL); max_offset = (u_int)(cp - bp); i = GET_U_1(cp); cp++; if ((i & TYPE_MASK) != TYPE_INDIR) { compress = 0; rp = cp + l; } if (i != 0) { while (i && cp < ndo->ndo_snapend) { switch (i & TYPE_MASK) { case TYPE_INDIR: if (!compress) { rp = cp + 1; compress = 1; } if (!ND_TTEST_1(cp)) return(NULL); offset = (((i << 8) | GET_U_1(cp)) & 0x3fff); /* * This must move backwards in the packet. * No RFC explicitly says that, but BIND's * name decompression code requires it, * as a way of preventing infinite loops * and other bad behavior, and it's probably * what was intended (compress by pointing * to domain name suffixes already seen in * the packet). */ if (offset >= max_offset) { ND_PRINT(""); return(NULL); } max_offset = offset; cp = bp + offset; if (!ND_TTEST_1(cp)) return(NULL); i = GET_U_1(cp); if ((l = labellen(ndo, cp)) == (u_int)-1) return(NULL); cp++; continue; case TYPE_EDNS0: elt = (i & ~TYPE_MASK); switch(elt) { case EDNS0_ELT_BITLABEL: if (blabel_print(ndo, cp) == NULL) return (NULL); break; default: /* unknown ELT */ ND_PRINT("", elt); return(NULL); } break; case TYPE_RESERVED: ND_PRINT(""); return(NULL); case TYPE_LABEL: if (name_chars + l <= MAXCDNAME) { if (nd_printn(ndo, cp, l, ndo->ndo_snapend)) return(NULL); } else if (name_chars < MAXCDNAME) { if (nd_printn(ndo, cp, MAXCDNAME - name_chars, ndo->ndo_snapend)) return(NULL); } name_chars += l; break; } cp += l; if (name_chars <= MAXCDNAME) ND_PRINT("."); name_chars++; if (!ND_TTEST_1(cp)) return(NULL); i = GET_U_1(cp); if ((l = labellen(ndo, cp)) == (u_int)-1) return(NULL); cp++; if (!compress) rp += l + 1; } if (name_chars > MAXCDNAME) ND_PRINT(""); } else ND_PRINT("."); return (rp); } /* print a */ static const u_char * ns_cprint(netdissect_options *ndo, const u_char *cp) { u_int i; if (!ND_TTEST_1(cp)) return (NULL); i = GET_U_1(cp); cp++; if (nd_printn(ndo, cp, i, ndo->ndo_snapend)) return (NULL); return (cp + i); } static void print_eopt_ecs(netdissect_options *ndo, const u_char *cp, u_int data_len) { u_int family, addr_bits, src_len, scope_len; u_char padded[32]; char addr[INET6_ADDRSTRLEN]; /* ecs option must at least contain family, src len, and scope len */ if (data_len < 4) { nd_print_invalid(ndo); return; } family = GET_BE_U_2(cp); cp += 2; src_len = GET_U_1(cp); cp += 1; scope_len = GET_U_1(cp); cp += 1; if (family == 1) addr_bits = 32; else if (family == 2) addr_bits = 128; else { nd_print_invalid(ndo); return; } if (data_len - 4 > (addr_bits / 8)) { nd_print_invalid(ndo); return; } /* checks for invalid ecs scope or source length */ if (src_len > addr_bits || scope_len > addr_bits || ((src_len + 7) / 8) != (data_len - 4)) { nd_print_invalid(ndo); return; } /* pad the truncated address from ecs with zeros */ memset(padded, 0, sizeof(padded)); memcpy(padded, cp, data_len - 4); if (family == 1) ND_PRINT("%s/%d/%d", addrtostr(padded, addr, INET_ADDRSTRLEN), src_len, scope_len); else ND_PRINT("%s/%d/%d", addrtostr6(padded, addr, INET6_ADDRSTRLEN), src_len, scope_len); } extern const struct tok edns_opt2str[]; extern const struct tok dau_alg2str[]; extern const struct tok dhu_alg2str[]; extern const struct tok n3u_alg2str[]; /* print an */ static const u_char * eopt_print(netdissect_options *ndo, const u_char *cp) { u_int opt, data_len, i; if (!ND_TTEST_2(cp)) return (NULL); opt = GET_BE_U_2(cp); cp += 2; ND_PRINT("%s", tok2str(edns_opt2str, "Opt%u", opt)); if (!ND_TTEST_2(cp)) return (NULL); data_len = GET_BE_U_2(cp); cp += 2; ND_TCHECK_LEN(cp, data_len); if (data_len > 0) { ND_PRINT(" "); switch (opt) { case E_ECS: print_eopt_ecs(ndo, cp, data_len); break; case E_COOKIE: if (data_len < 8 || (data_len > 8 && data_len < 16) || data_len > 40) nd_print_invalid(ndo); else { for (i = 0; i < data_len; ++i) { /* split client and server cookie */ if (i == 8) ND_PRINT(" "); ND_PRINT("%02x", GET_U_1(cp + i)); } } break; case E_KEEPALIVE: if (data_len != 2) nd_print_invalid(ndo); else /* keepalive is in increments of 100ms. Convert to seconds */ ND_PRINT("%0.1f sec", (GET_BE_U_2(cp) / 10.0)); break; case E_EXPIRE: if (data_len != 4) nd_print_invalid(ndo); else ND_PRINT("%u sec", GET_BE_U_4(cp)); break; case E_PADDING: /* ignore contents and just print length */ ND_PRINT("(%u)", data_len); break; case E_KEYTAG: if (data_len % 2 != 0) nd_print_invalid(ndo); else for (i = 0; i < data_len; i += 2) { if (i > 0) ND_PRINT(" "); ND_PRINT("%u", GET_BE_U_2(cp + i)); } break; case E_DAU: for (i = 0; i < data_len; ++i) { if (i > 0) ND_PRINT(" "); ND_PRINT("%s", tok2str(dau_alg2str, "Alg_%u", GET_U_1(cp + i))); } break; case E_DHU: for (i = 0; i < data_len; ++i) { if (i > 0) ND_PRINT(" "); ND_PRINT("%s", tok2str(dhu_alg2str, "Alg_%u", GET_U_1(cp + i))); } break; case E_N3U: for (i = 0; i < data_len; ++i) { if (i > 0) ND_PRINT(" "); ND_PRINT("%s", tok2str(n3u_alg2str, "Alg_%u", GET_U_1(cp + i))); } break; case E_CHAIN: fqdn_print(ndo, cp, cp + data_len); break; case E_NSID: /* intentional fall-through. NSID is an undefined byte string */ default: for (i = 0; i < data_len; ++i) ND_PRINT("%02x", GET_U_1(cp + i)); break; } } return (cp + data_len); trunc: return (NULL); } extern const struct tok ns_type2str[]; /* https://www.iana.org/assignments/dns-parameters */ const struct tok ns_type2str[] = { { T_A, "A" }, /* RFC 1035 */ { T_NS, "NS" }, /* RFC 1035 */ { T_MD, "MD" }, /* RFC 1035 */ { T_MF, "MF" }, /* RFC 1035 */ { T_CNAME, "CNAME" }, /* RFC 1035 */ { T_SOA, "SOA" }, /* RFC 1035 */ { T_MB, "MB" }, /* RFC 1035 */ { T_MG, "MG" }, /* RFC 1035 */ { T_MR, "MR" }, /* RFC 1035 */ { T_NULL, "NULL" }, /* RFC 1035 */ { T_WKS, "WKS" }, /* RFC 1035 */ { T_PTR, "PTR" }, /* RFC 1035 */ { T_HINFO, "HINFO" }, /* RFC 1035 */ { T_MINFO, "MINFO" }, /* RFC 1035 */ { T_MX, "MX" }, /* RFC 1035 */ { T_TXT, "TXT" }, /* RFC 1035 */ { T_RP, "RP" }, /* RFC 1183 */ { T_AFSDB, "AFSDB" }, /* RFC 1183 */ { T_X25, "X25" }, /* RFC 1183 */ { T_ISDN, "ISDN" }, /* RFC 1183 */ { T_RT, "RT" }, /* RFC 1183 */ { T_NSAP, "NSAP" }, /* RFC 1706 */ { T_NSAP_PTR, "NSAP_PTR" }, { T_SIG, "SIG" }, /* RFC 2535 */ { T_KEY, "KEY" }, /* RFC 2535 */ { T_PX, "PX" }, /* RFC 2163 */ { T_GPOS, "GPOS" }, /* RFC 1712 */ { T_AAAA, "AAAA" }, /* RFC 1886 */ { T_LOC, "LOC" }, /* RFC 1876 */ { T_NXT, "NXT" }, /* RFC 2535 */ { T_EID, "EID" }, /* Nimrod */ { T_NIMLOC, "NIMLOC" }, /* Nimrod */ { T_SRV, "SRV" }, /* RFC 2782 */ { T_ATMA, "ATMA" }, /* ATM Forum */ { T_NAPTR, "NAPTR" }, /* RFC 2168, RFC 2915 */ { T_KX, "KX" }, /* RFC 2230 */ { T_CERT, "CERT" }, /* RFC 2538 */ { T_A6, "A6" }, /* RFC 2874 */ { T_DNAME, "DNAME" }, /* RFC 2672 */ { T_SINK, "SINK" }, { T_OPT, "OPT" }, /* RFC 2671 */ { T_APL, "APL" }, /* RFC 3123 */ { T_DS, "DS" }, /* RFC 4034 */ { T_SSHFP, "SSHFP" }, /* RFC 4255 */ { T_IPSECKEY, "IPSECKEY" }, /* RFC 4025 */ { T_RRSIG, "RRSIG" }, /* RFC 4034 */ { T_NSEC, "NSEC" }, /* RFC 4034 */ { T_DNSKEY, "DNSKEY" }, /* RFC 4034 */ { T_SPF, "SPF" }, /* RFC-schlitt-spf-classic-02.txt */ { T_UINFO, "UINFO" }, { T_UID, "UID" }, { T_GID, "GID" }, { T_UNSPEC, "UNSPEC" }, { T_UNSPECA, "UNSPECA" }, { T_TKEY, "TKEY" }, /* RFC 2930 */ { T_TSIG, "TSIG" }, /* RFC 2845 */ { T_IXFR, "IXFR" }, /* RFC 1995 */ { T_AXFR, "AXFR" }, /* RFC 1035 */ { T_MAILB, "MAILB" }, /* RFC 1035 */ { T_MAILA, "MAILA" }, /* RFC 1035 */ { T_ANY, "ANY" }, { T_URI, "URI" }, /* RFC 7553 */ { 0, NULL } }; extern const struct tok ns_class2str[]; const struct tok ns_class2str[] = { { C_IN, "IN" }, /* Not used */ { C_CHAOS, "CHAOS" }, { C_HS, "HS" }, { C_ANY, "ANY" }, { 0, NULL } }; const struct tok edns_opt2str[] = { { E_LLQ, "LLQ" }, { E_UL, "UL" }, { E_NSID, "NSID" }, { E_DAU, "DAU" }, { E_DHU, "DHU" }, { E_N3U, "N3U" }, { E_ECS, "ECS" }, { E_EXPIRE, "EXPIRE" }, { E_COOKIE, "COOKIE" }, { E_KEEPALIVE, "KEEPALIVE" }, { E_PADDING, "PADDING" }, { E_CHAIN, "CHAIN" }, { E_KEYTAG, "KEY-TAG" }, { E_CLIENTTAG, "CLIENT-TAG" }, { E_SERVERTAG, "SERVER-TAG" }, { 0, NULL } }; const struct tok dau_alg2str[] = { { A_DELETE, "DELETE" }, { A_RSAMD5, "RSAMD5" }, { A_DH, "DH" }, { A_DSA, "DS" }, { A_RSASHA1, "RSASHA1" }, { A_DSA_NSEC3_SHA1, "DSA-NSEC3-SHA1" }, { A_RSASHA1_NSEC3_SHA1, "RSASHA1-NSEC3-SHA1" }, { A_RSASHA256, "RSASHA256" }, { A_RSASHA512, "RSASHA512" }, { A_ECC_GOST, "ECC-GOST" }, { A_ECDSAP256SHA256, "ECDSAP256SHA256" }, { A_ECDSAP384SHA384, "ECDSAP384SHA384" }, { A_ED25519, "ED25519" }, { A_ED448, "ED448" }, { A_INDIRECT, "INDIRECT" }, { A_PRIVATEDNS, "PRIVATEDNS" }, { A_PRIVATEOID, "PRIVATEOID" }, { 0, NULL } }; const struct tok dhu_alg2str[] = { { DS_SHA1, "SHA-1" }, { DS_SHA256,"SHA-256" }, { DS_GOST, "GOST_R_34.11-94" }, { DS_SHA384,"SHA-384" }, { 0, NULL } }; const struct tok n3u_alg2str[] = { { NSEC_SHA1,"SHA-1" }, { 0, NULL } }; /* print a query */ static const u_char * ns_qprint(netdissect_options *ndo, const u_char *cp, const u_char *bp, int is_mdns) { const u_char *np = cp; u_int i, class; cp = ns_nskip(ndo, cp); if (cp == NULL || !ND_TTEST_4(cp)) return(NULL); /* print the qtype */ i = GET_BE_U_2(cp); cp += 2; ND_PRINT(" %s", tok2str(ns_type2str, "Type%u", i)); /* print the qclass (if it's not IN) */ i = GET_BE_U_2(cp); cp += 2; if (is_mdns) class = (i & ~C_QU); else class = i; if (class != C_IN) ND_PRINT(" %s", tok2str(ns_class2str, "(Class %u)", class)); if (is_mdns) { ND_PRINT(i & C_QU ? " (QU)" : " (QM)"); } ND_PRINT("? "); cp = fqdn_print(ndo, np, bp); return(cp ? cp + 4 : NULL); } /* print a reply */ static const u_char * ns_rprint(netdissect_options *ndo, const u_char *cp, const u_char *bp, int is_mdns) { u_int i, class, opt_flags = 0; u_short typ, len; const u_char *rp; if (ndo->ndo_vflag) { ND_PRINT(" "); if ((cp = fqdn_print(ndo, cp, bp)) == NULL) return NULL; } else cp = ns_nskip(ndo, cp); if (cp == NULL || !ND_TTEST_LEN(cp, 10)) return (ndo->ndo_snapend); /* print the type/qtype */ typ = GET_BE_U_2(cp); cp += 2; /* print the class (if it's not IN and the type isn't OPT) */ i = GET_BE_U_2(cp); cp += 2; if (is_mdns) class = (i & ~C_CACHE_FLUSH); else class = i; if (class != C_IN && typ != T_OPT) ND_PRINT(" %s", tok2str(ns_class2str, "(Class %u)", class)); if (is_mdns) { if (i & C_CACHE_FLUSH) ND_PRINT(" (Cache flush)"); } if (typ == T_OPT) { /* get opt flags */ cp += 2; opt_flags = GET_BE_U_2(cp); /* ignore rest of ttl field */ cp += 2; } else if (ndo->ndo_vflag > 2) { /* print ttl */ ND_PRINT(" ["); unsigned_relts_print(ndo, GET_BE_U_4(cp)); ND_PRINT("]"); cp += 4; } else { /* ignore ttl */ cp += 4; } len = GET_BE_U_2(cp); cp += 2; rp = cp + len; ND_PRINT(" %s", tok2str(ns_type2str, "Type%u", typ)); if (rp > ndo->ndo_snapend) return(NULL); switch (typ) { case T_A: if (!ND_TTEST_LEN(cp, sizeof(nd_ipv4))) return(NULL); ND_PRINT(" %s", intoa(GET_IPV4_TO_NETWORK_ORDER(cp))); break; case T_NS: case T_CNAME: case T_PTR: case T_DNAME: ND_PRINT(" "); if (fqdn_print(ndo, cp, bp) == NULL) return(NULL); break; case T_SOA: if (!ndo->ndo_vflag) break; ND_PRINT(" "); if ((cp = fqdn_print(ndo, cp, bp)) == NULL) return(NULL); ND_PRINT(" "); if ((cp = fqdn_print(ndo, cp, bp)) == NULL) return(NULL); if (!ND_TTEST_LEN(cp, 5 * 4)) return(NULL); ND_PRINT(" %u", GET_BE_U_4(cp)); cp += 4; ND_PRINT(" %u", GET_BE_U_4(cp)); cp += 4; ND_PRINT(" %u", GET_BE_U_4(cp)); cp += 4; ND_PRINT(" %u", GET_BE_U_4(cp)); cp += 4; ND_PRINT(" %u", GET_BE_U_4(cp)); cp += 4; break; case T_MX: ND_PRINT(" "); if (!ND_TTEST_2(cp)) return(NULL); if (fqdn_print(ndo, cp + 2, bp) == NULL) return(NULL); ND_PRINT(" %u", GET_BE_U_2(cp)); break; case T_TXT: while (cp < rp) { ND_PRINT(" \""); cp = ns_cprint(ndo, cp); if (cp == NULL) return(NULL); ND_PRINT("\""); } break; case T_SRV: ND_PRINT(" "); if (!ND_TTEST_6(cp)) return(NULL); if (fqdn_print(ndo, cp + 6, bp) == NULL) return(NULL); ND_PRINT(":%u %u %u", GET_BE_U_2(cp + 4), GET_BE_U_2(cp), GET_BE_U_2(cp + 2)); break; case T_AAAA: { char ntop_buf[INET6_ADDRSTRLEN]; if (!ND_TTEST_LEN(cp, sizeof(nd_ipv6))) return(NULL); ND_PRINT(" %s", addrtostr6(cp, ntop_buf, sizeof(ntop_buf))); break; } case T_A6: { nd_ipv6 a; int pbit, pbyte; char ntop_buf[INET6_ADDRSTRLEN]; if (!ND_TTEST_1(cp)) return(NULL); pbit = GET_U_1(cp); pbyte = (pbit & ~7) / 8; if (pbit > 128) { ND_PRINT(" %u(bad plen)", pbit); break; } else if (pbit < 128) { memset(a, 0, sizeof(a)); GET_CPY_BYTES(a + pbyte, cp + 1, sizeof(a) - pbyte); ND_PRINT(" %u %s", pbit, addrtostr6(&a, ntop_buf, sizeof(ntop_buf))); } if (pbit > 0) { ND_PRINT(" "); if (fqdn_print(ndo, cp + 1 + sizeof(a) - pbyte, bp) == NULL) return(NULL); } break; } case T_URI: if (!ND_TTEST_LEN(cp, len)) return(NULL); ND_PRINT(" %u %u ", GET_BE_U_2(cp), GET_BE_U_2(cp + 2)); if (nd_printn(ndo, cp + 4, len - 4, ndo->ndo_snapend)) return(NULL); break; case T_OPT: ND_PRINT(" UDPsize=%u", class); if (opt_flags & 0x8000) ND_PRINT(" DO"); if (cp < rp) { ND_PRINT(" ["); while (cp < rp) { cp = eopt_print(ndo, cp); if (cp == NULL) return(NULL); if (cp < rp) ND_PRINT(","); } ND_PRINT("]"); } break; case T_UNSPECA: /* One long string */ if (!ND_TTEST_LEN(cp, len)) return(NULL); if (nd_printn(ndo, cp, len, ndo->ndo_snapend)) return(NULL); break; case T_TSIG: { if (cp + len > ndo->ndo_snapend) return(NULL); if (!ndo->ndo_vflag) break; ND_PRINT(" "); if ((cp = fqdn_print(ndo, cp, bp)) == NULL) return(NULL); cp += 6; if (!ND_TTEST_2(cp)) return(NULL); ND_PRINT(" fudge=%u", GET_BE_U_2(cp)); cp += 2; if (!ND_TTEST_2(cp)) return(NULL); ND_PRINT(" maclen=%u", GET_BE_U_2(cp)); cp += 2 + GET_BE_U_2(cp); if (!ND_TTEST_2(cp)) return(NULL); ND_PRINT(" origid=%u", GET_BE_U_2(cp)); cp += 2; if (!ND_TTEST_2(cp)) return(NULL); ND_PRINT(" error=%u", GET_BE_U_2(cp)); cp += 2; if (!ND_TTEST_2(cp)) return(NULL); ND_PRINT(" otherlen=%u", GET_BE_U_2(cp)); cp += 2; } } return (rp); /* XXX This isn't always right */ } void domain_print(netdissect_options *ndo, const u_char *bp, u_int length, int over_tcp, int is_mdns) { const dns_header_t *np; uint16_t flags, rcode, rdlen, type; u_int qdcount, ancount, nscount, arcount; u_int i; const u_char *cp; uint16_t b2; ndo->ndo_protocol = "domain"; if (over_tcp) { /* * The message is prefixed with a two byte length field * which gives the message length, excluding the two byte * length field. (RFC 1035 - 4.2.2. TCP usage) */ if (length < 2) { ND_PRINT(" [DNS over TCP: length %u < 2]", length); nd_print_invalid(ndo); return; } else { length -= 2; /* excluding the two byte length field */ if (GET_BE_U_2(bp) != length) { ND_PRINT(" [prefix length(%u) != length(%u)]", GET_BE_U_2(bp), length); nd_print_invalid(ndo); return; } else { bp += 2; /* in over TCP case, we need to prepend a space * (not needed in over UDP case) */ ND_PRINT(" "); } } } np = (const dns_header_t *)bp; if(length < sizeof(*np)) { nd_print_protocol(ndo); ND_PRINT(" [length %u < %zu]", length, sizeof(*np)); nd_print_invalid(ndo); return; } ND_TCHECK_SIZE(np); flags = GET_BE_U_2(np->flags); /* get the byte-order right */ qdcount = GET_BE_U_2(np->qdcount); ancount = GET_BE_U_2(np->ancount); nscount = GET_BE_U_2(np->nscount); arcount = GET_BE_U_2(np->arcount); /* find the opt record to extract extended rcode */ cp = (const u_char *)(np + 1); rcode = DNS_RCODE(flags); for (i = 0; i < qdcount; i++) { if ((cp = ns_nskip(ndo, cp)) == NULL) goto print; cp += 4; /* skip QTYPE and QCLASS */ if (cp >= ndo->ndo_snapend) goto print; } for (i = 0; i < ancount + nscount; i++) { if ((cp = ns_nskip(ndo, cp)) == NULL) goto print; cp += 8; /* skip TYPE, CLASS and TTL */ if (cp + 2 > ndo->ndo_snapend) goto print; rdlen = GET_BE_U_2(cp); cp += 2 + rdlen; if (cp >= ndo->ndo_snapend) goto print; } for (i = 0; i < arcount; i++) { if ((cp = ns_nskip(ndo, cp)) == NULL) goto print; if (cp + 2 > ndo->ndo_snapend) goto print; type = GET_BE_U_2(cp); cp += 4; /* skip TYPE and CLASS */ if (cp + 1 > ndo->ndo_snapend) goto print; if (type == T_OPT) { rcode |= (GET_U_1(cp) << 4); goto print; } cp += 4; if (cp + 2 > ndo->ndo_snapend) goto print; rdlen = GET_BE_U_2(cp); cp += 2 + rdlen; if (cp >= ndo->ndo_snapend) goto print; } print: if (DNS_QR(flags)) { /* this is a response */ ND_PRINT("%u%s%s%s%s%s%s", GET_BE_U_2(np->id), ns_ops[DNS_OPCODE(flags)], ns_rcode(rcode), DNS_AA(flags)? "*" : "", DNS_RA(flags)? "" : "-", DNS_TC(flags)? "|" : "", DNS_AD(flags)? "$" : ""); if (qdcount != 1) ND_PRINT(" [%uq]", qdcount); /* Print QUESTION section on -vv */ cp = (const u_char *)(np + 1); for (i = 0; i < qdcount; i++) { if (i != 0) ND_PRINT(","); if (ndo->ndo_vflag > 1) { ND_PRINT(" q:"); if ((cp = ns_qprint(ndo, cp, bp, is_mdns)) == NULL) goto trunc; } else { if ((cp = ns_nskip(ndo, cp)) == NULL) goto trunc; cp += 4; /* skip QTYPE and QCLASS */ } } ND_PRINT(" %u/%u/%u", ancount, nscount, arcount); if (ancount) { if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) goto trunc; ancount--; while (cp < ndo->ndo_snapend && ancount) { ND_PRINT(","); if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) goto trunc; ancount--; } } if (ancount) goto trunc; /* Print NS and AR sections on -vv */ if (ndo->ndo_vflag > 1) { if (cp < ndo->ndo_snapend && nscount) { ND_PRINT(" ns:"); if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) goto trunc; nscount--; while (cp < ndo->ndo_snapend && nscount) { ND_PRINT(","); if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) goto trunc; nscount--; } } if (nscount) goto trunc; if (cp < ndo->ndo_snapend && arcount) { ND_PRINT(" ar:"); if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) goto trunc; arcount--; while (cp < ndo->ndo_snapend && arcount) { ND_PRINT(","); if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) goto trunc; arcount--; } } if (arcount) goto trunc; } } else { /* this is a request */ ND_PRINT("%u%s%s%s", GET_BE_U_2(np->id), ns_ops[DNS_OPCODE(flags)], DNS_RD(flags) ? "+" : "", DNS_CD(flags) ? "%" : ""); /* any weirdness? */ b2 = GET_BE_U_2(((const u_short *)np) + 1); if (b2 & 0x6cf) ND_PRINT(" [b2&3=0x%x]", b2); if (DNS_OPCODE(flags) == IQUERY) { if (qdcount) ND_PRINT(" [%uq]", qdcount); if (ancount != 1) ND_PRINT(" [%ua]", ancount); } else { if (ancount) ND_PRINT(" [%ua]", ancount); if (qdcount != 1) ND_PRINT(" [%uq]", qdcount); } if (nscount) ND_PRINT(" [%un]", nscount); if (arcount) ND_PRINT(" [%uau]", arcount); cp = (const u_char *)(np + 1); if (qdcount) { cp = ns_qprint(ndo, cp, (const u_char *)np, is_mdns); if (!cp) goto trunc; qdcount--; while (cp < ndo->ndo_snapend && qdcount) { cp = ns_qprint(ndo, (const u_char *)cp, (const u_char *)np, is_mdns); if (!cp) goto trunc; qdcount--; } } if (qdcount) goto trunc; /* Print remaining sections on -vv */ if (ndo->ndo_vflag > 1) { if (ancount) { if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) goto trunc; ancount--; while (cp < ndo->ndo_snapend && ancount) { ND_PRINT(","); if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) goto trunc; ancount--; } } if (ancount) goto trunc; if (cp < ndo->ndo_snapend && nscount) { ND_PRINT(" ns:"); if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) goto trunc; nscount--; while (cp < ndo->ndo_snapend && nscount) { ND_PRINT(","); if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) goto trunc; nscount--; } } if (nscount > 0) goto trunc; if (cp < ndo->ndo_snapend && arcount) { ND_PRINT(" ar:"); if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) goto trunc; arcount--; while (cp < ndo->ndo_snapend && arcount) { ND_PRINT(","); if ((cp = ns_rprint(ndo, cp, bp, is_mdns)) == NULL) goto trunc; arcount--; } } if (arcount) goto trunc; } } ND_PRINT(" (%u)", length); return; trunc: nd_print_trunc(ndo); } tcpdump-4.99.1/l2vpn.h0000644000026300017510000000141514057477727012654 0ustar mcrmcr/* * 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, and (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. * 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. * * Original code by Hannes Gredler (hannes@gredler.at) */ extern const struct tok l2vpn_encaps_values[]; extern const struct tok mpls_pw_types_values[]; tcpdump-4.99.1/print-vxlan.c0000644000026300017510000000463014057477727014072 0ustar mcrmcr/* * 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, and (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. * 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. * * Original code by Francesco Fondelli (francesco dot fondelli, gmail dot com) */ /* \summary: Virtual eXtensible Local Area Network (VXLAN) printer */ /* specification: RFC 7348 */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "extract.h" static const struct tok vxlan_flags [] = { { 0x08, "I" }, { 0, NULL } }; #define VXLAN_HDR_LEN 8 /* * VXLAN header, RFC7348 * Virtual eXtensible Local Area Network (VXLAN): A Framework * for Overlaying Virtualized Layer 2 Networks over Layer 3 Networks * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |R|R|R|R|I|R|R|R| Reserved | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | VXLAN Network Identifier (VNI) | Reserved | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ void vxlan_print(netdissect_options *ndo, const u_char *bp, u_int len) { uint8_t flags; uint32_t vni; ndo->ndo_protocol = "vxlan"; nd_print_protocol_caps(ndo); if (len < VXLAN_HDR_LEN) goto invalid; flags = GET_U_1(bp); bp += 1; ND_PRINT(", flags [%s] (0x%02x), ", bittok2str_nosep(vxlan_flags, "invalid", flags), flags); /* 1st Reserved */ bp += 3; vni = GET_BE_U_3(bp); bp += 3; ND_PRINT("vni %u\n", vni); /* 2nd Reserved */ ND_TCHECK_1(bp); bp += 1; ether_print(ndo, bp, len - VXLAN_HDR_LEN, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL); return; invalid: nd_print_invalid(ndo); } tcpdump-4.99.1/compiler-tests.h0000644000026300017510000001327514057477727014574 0ustar mcrmcr/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ /* * Copyright (c) 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 the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef nd_compiler_tests_h #define nd_compiler_tests_h /* * This was introduced by Clang: * * https://clang.llvm.org/docs/LanguageExtensions.html#has-attribute * * in some version (which version?); it has been picked up by GCC 5.0. */ #ifndef __has_attribute /* * It's a macro, so you can check whether it's defined to check * whether it's supported. * * If it's not, define it to always return 0, so that we move on to * the fallback checks. */ #define __has_attribute(x) 0 #endif /* * Note that the C90 spec's "6.8.1 Conditional inclusion" and the * C99 spec's and C11 spec's "6.10.1 Conditional inclusion" say: * * Prior to evaluation, macro invocations in the list of preprocessing * tokens that will become the controlling constant expression are * replaced (except for those macro names modified by the defined unary * operator), just as in normal text. If the token "defined" is * generated as a result of this replacement process or use of the * "defined" unary operator does not match one of the two specified * forms prior to macro replacement, the behavior is undefined. * * so you shouldn't use defined() in a #define that's used in #if or * #elif. Some versions of Clang, for example, will warn about this. * * Instead, we check whether the pre-defined macros for particular * compilers are defined and, if not, define the "is this version XXX * or a later version of this compiler" macros as 0. */ /* * Check whether this is GCC major.minor or a later release, or some * compiler that claims to be "just like GCC" of that version or a * later release. */ #if ! defined(__GNUC__) #define ND_IS_AT_LEAST_GNUC_VERSION(major, minor) 0 #else #define ND_IS_AT_LEAST_GNUC_VERSION(major, minor) \ (__GNUC__ > (major) || \ (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))) #endif /* * Check whether this is Sun C/SunPro C/Oracle Studio major.minor * or a later release. * * The version number in __SUNPRO_C is encoded in hex BCD, with the * uppermost hex digit being the major version number, the next * one or two hex digits being the minor version number, and * the last digit being the patch version. * * It represents the *compiler* version, not the product version; * see * * https://sourceforge.net/p/predef/wiki/Compilers/ * * for a partial mapping, which we assume continues for later * 12.x product releases. */ #if ! defined(__SUNPRO_C) #define ND_IS_AT_LEAST_SUNC_VERSION(major,minor) 0 #else #define ND_SUNPRO_VERSION_TO_BCD(major, minor) \ (((minor) >= 10) ? \ (((major) << 12) | (((minor)/10) << 8) | (((minor)%10) << 4)) : \ (((major) << 8) | ((minor) << 4))) #define ND_IS_AT_LEAST_SUNC_VERSION(major,minor) \ (__SUNPRO_C >= ND_SUNPRO_VERSION_TO_BCD((major), (minor))) #endif /* * Check whether this is IBM XL C major.minor or a later release. * * The version number in __xlC__ has the major version in the * upper 8 bits and the minor version in the lower 8 bits. */ #if ! defined(__xlC__) #define ND_IS_AT_LEAST_XL_C_VERSION(major,minor) 0 #else #define ND_IS_AT_LEAST_XL_C_VERSION(major, minor) \ (__xlC__ >= (((major) << 8) | (minor))) #endif /* * Check whether this is HP aC++/HP C major.minor or a later release. * * The version number in __HP_aCC is encoded in zero-padded decimal BCD, * with the "A." stripped off, the uppermost two decimal digits being * the major version number, the next two decimal digits being the minor * version number, and the last two decimal digits being the patch version. * (Strip off the A., remove the . between the major and minor version * number, and add two digits of patch.) */ #if ! defined(__HP_aCC) #define ND_IS_AT_LEAST_HP_C_VERSION(major,minor) 0 #else #define ND_IS_AT_LEAST_HP_C_VERSION(major,minor) \ (__HP_aCC >= ((major)*10000 + (minor)*100)) #endif #endif /* nd_funcattrs_h */ tcpdump-4.99.1/machdep.h0000644000026300017510000000236614057477727013222 0ustar mcrmcr/* * Copyright (c) 1996 * 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. */ #ifndef netdissect_machdep_h #define netdissect_machdep_h int abort_on_misalignment(char *, size_t); #endif tcpdump-4.99.1/rpc_msg.h0000644000026300017510000000632114057477727013246 0ustar mcrmcr/* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 * * from: @(#)rpc_msg.h 1.7 86/07/16 SMI * from: @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC * $FreeBSD: src/include/rpc/rpc_msg.h,v 1.11.2.1 1999/08/29 14:39:07 peter Exp $ */ /* * rpc_msg.h * rpc message definition * * Copyright (C) 1984, Sun Microsystems, Inc. */ #define SUNRPC_MSG_VERSION ((uint32_t) 2) /* * Bottom up definition of an rpc message. * NOTE: call and reply use the same overall struct but * different parts of unions within it. */ enum sunrpc_msg_type { SUNRPC_CALL=0, SUNRPC_REPLY=1 }; enum sunrpc_reply_stat { SUNRPC_MSG_ACCEPTED=0, SUNRPC_MSG_DENIED=1 }; enum sunrpc_accept_stat { SUNRPC_SUCCESS=0, SUNRPC_PROG_UNAVAIL=1, SUNRPC_PROG_MISMATCH=2, SUNRPC_PROC_UNAVAIL=3, SUNRPC_GARBAGE_ARGS=4, SUNRPC_SYSTEM_ERR=5 }; enum sunrpc_reject_stat { SUNRPC_RPC_MISMATCH=0, SUNRPC_AUTH_ERROR=1 }; /* * Reply part of an rpc exchange */ /* * Reply to an rpc request that was rejected by the server. */ struct sunrpc_rejected_reply { nd_uint32_t rj_stat; /* enum reject_stat */ union { struct { nd_uint32_t low; nd_uint32_t high; } RJ_versions; nd_uint32_t RJ_why; /* enum auth_stat - why authentication did not work */ } ru; #define rj_vers ru.RJ_versions #define rj_why ru.RJ_why }; /* * Body of a reply to an rpc request. */ struct sunrpc_reply_body { nd_uint32_t rp_stat; /* enum reply_stat */ struct sunrpc_rejected_reply rp_reject; /* if rejected */ }; /* * Body of an rpc request call. */ struct sunrpc_call_body { nd_uint32_t cb_rpcvers; /* must be equal to two */ nd_uint32_t cb_prog; nd_uint32_t cb_vers; nd_uint32_t cb_proc; struct sunrpc_opaque_auth cb_cred; /* followed by opaque verifier */ }; /* * The rpc message */ struct sunrpc_msg { nd_uint32_t rm_xid; nd_uint32_t rm_direction; /* enum msg_type */ union { struct sunrpc_call_body RM_cmb; struct sunrpc_reply_body RM_rmb; } ru; #define rm_call ru.RM_cmb #define rm_reply ru.RM_rmb }; #define acpted_rply ru.RM_rmb.ru.RP_ar #define rjcted_rply ru.RM_rmb.ru.RP_dr tcpdump-4.99.1/nlpid.h0000644000026300017510000000246614057477727012730 0ustar mcrmcr/* * 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, and (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. * 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. * * Original code by Hannes Gredler (hannes@gredler.at) */ extern const struct tok nlpid_values[]; #define NLPID_NULLNS 0x00 #define NLPID_Q933 0x08 /* ANSI T1.617 Annex D or ITU-T Q.933 Annex A */ #define NLPID_LMI 0x09 /* The original, aka Cisco, aka Gang of Four */ #define NLPID_SNAP 0x80 #define NLPID_CLNP 0x81 /* iso9577 */ #define NLPID_ESIS 0x82 /* iso9577 */ #define NLPID_ISIS 0x83 /* iso9577 */ #define NLPID_CONS 0x84 #define NLPID_IDRP 0x85 #define NLPID_MFR 0xb1 /* FRF.15 */ #define NLPID_SPB 0xc1 /* IEEE 802.1aq/D4.5 */ #define NLPID_IP 0xcc #define NLPID_PPP 0xcf #define NLPID_X25_ESIS 0x8a #define NLPID_IP6 0x8e tcpdump-4.99.1/print-ldp.c0000644000026300017510000005672114057477727013531 0ustar mcrmcr/* * 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, and (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. * 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. * * Original code by Hannes Gredler (hannes@gredler.at) * and Steinar Haug (sthaug@nethelp.no) */ /* \summary: Label Distribution Protocol (LDP) printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" #include "extract.h" #include "addrtoname.h" #include "l2vpn.h" #include "af.h" /* * ldp common header * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Version | PDU Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | LDP Identifier | * + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * */ struct ldp_common_header { nd_uint16_t version; nd_uint16_t pdu_length; nd_ipv4 lsr_id; nd_uint16_t label_space; }; #define LDP_VERSION 1 /* * ldp message header * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |U| Message Type | Message Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Message ID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | * + + * | Mandatory Parameters | * + + * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | * + + * | Optional Parameters | * + + * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ struct ldp_msg_header { nd_uint16_t type; nd_uint16_t length; nd_uint32_t id; }; #define LDP_MASK_MSG_TYPE(x) ((x)&0x7fff) #define LDP_MASK_U_BIT(x) ((x)&0x8000) #define LDP_MSG_NOTIF 0x0001 #define LDP_MSG_HELLO 0x0100 #define LDP_MSG_INIT 0x0200 #define LDP_MSG_KEEPALIVE 0x0201 #define LDP_MSG_ADDRESS 0x0300 #define LDP_MSG_ADDRESS_WITHDRAW 0x0301 #define LDP_MSG_LABEL_MAPPING 0x0400 #define LDP_MSG_LABEL_REQUEST 0x0401 #define LDP_MSG_LABEL_WITHDRAW 0x0402 #define LDP_MSG_LABEL_RELEASE 0x0403 #define LDP_MSG_LABEL_ABORT_REQUEST 0x0404 #define LDP_VENDOR_PRIVATE_MIN 0x3e00 #define LDP_VENDOR_PRIVATE_MAX 0x3eff #define LDP_EXPERIMENTAL_MIN 0x3f00 #define LDP_EXPERIMENTAL_MAX 0x3fff static const struct tok ldp_msg_values[] = { { LDP_MSG_NOTIF, "Notification" }, { LDP_MSG_HELLO, "Hello" }, { LDP_MSG_INIT, "Initialization" }, { LDP_MSG_KEEPALIVE, "Keepalive" }, { LDP_MSG_ADDRESS, "Address" }, { LDP_MSG_ADDRESS_WITHDRAW, "Address Withdraw" }, { LDP_MSG_LABEL_MAPPING, "Label Mapping" }, { LDP_MSG_LABEL_REQUEST, "Label Request" }, { LDP_MSG_LABEL_WITHDRAW, "Label Withdraw" }, { LDP_MSG_LABEL_RELEASE, "Label Release" }, { LDP_MSG_LABEL_ABORT_REQUEST, "Label Abort Request" }, { 0, NULL} }; #define LDP_MASK_TLV_TYPE(x) ((x)&0x3fff) #define LDP_MASK_F_BIT(x) ((x)&0x4000) #define LDP_TLV_FEC 0x0100 #define LDP_TLV_ADDRESS_LIST 0x0101 #define LDP_TLV_ADDRESS_LIST_AFNUM_LEN 2 #define LDP_TLV_HOP_COUNT 0x0103 #define LDP_TLV_PATH_VECTOR 0x0104 #define LDP_TLV_GENERIC_LABEL 0x0200 #define LDP_TLV_ATM_LABEL 0x0201 #define LDP_TLV_FR_LABEL 0x0202 #define LDP_TLV_STATUS 0x0300 #define LDP_TLV_EXTD_STATUS 0x0301 #define LDP_TLV_RETURNED_PDU 0x0302 #define LDP_TLV_RETURNED_MSG 0x0303 #define LDP_TLV_COMMON_HELLO 0x0400 #define LDP_TLV_IPV4_TRANSPORT_ADDR 0x0401 #define LDP_TLV_CONFIG_SEQ_NUMBER 0x0402 #define LDP_TLV_IPV6_TRANSPORT_ADDR 0x0403 #define LDP_TLV_COMMON_SESSION 0x0500 #define LDP_TLV_ATM_SESSION_PARM 0x0501 #define LDP_TLV_FR_SESSION_PARM 0x0502 #define LDP_TLV_FT_SESSION 0x0503 #define LDP_TLV_LABEL_REQUEST_MSG_ID 0x0600 #define LDP_TLV_MTU 0x0601 /* rfc 3988 */ static const struct tok ldp_tlv_values[] = { { LDP_TLV_FEC, "FEC" }, { LDP_TLV_ADDRESS_LIST, "Address List" }, { LDP_TLV_HOP_COUNT, "Hop Count" }, { LDP_TLV_PATH_VECTOR, "Path Vector" }, { LDP_TLV_GENERIC_LABEL, "Generic Label" }, { LDP_TLV_ATM_LABEL, "ATM Label" }, { LDP_TLV_FR_LABEL, "Frame-Relay Label" }, { LDP_TLV_STATUS, "Status" }, { LDP_TLV_EXTD_STATUS, "Extended Status" }, { LDP_TLV_RETURNED_PDU, "Returned PDU" }, { LDP_TLV_RETURNED_MSG, "Returned Message" }, { LDP_TLV_COMMON_HELLO, "Common Hello Parameters" }, { LDP_TLV_IPV4_TRANSPORT_ADDR, "IPv4 Transport Address" }, { LDP_TLV_CONFIG_SEQ_NUMBER, "Configuration Sequence Number" }, { LDP_TLV_IPV6_TRANSPORT_ADDR, "IPv6 Transport Address" }, { LDP_TLV_COMMON_SESSION, "Common Session Parameters" }, { LDP_TLV_ATM_SESSION_PARM, "ATM Session Parameters" }, { LDP_TLV_FR_SESSION_PARM, "Frame-Relay Session Parameters" }, { LDP_TLV_FT_SESSION, "Fault-Tolerant Session Parameters" }, { LDP_TLV_LABEL_REQUEST_MSG_ID, "Label Request Message ID" }, { LDP_TLV_MTU, "MTU" }, { 0, NULL} }; #define LDP_FEC_WILDCARD 0x01 #define LDP_FEC_PREFIX 0x02 #define LDP_FEC_HOSTADDRESS 0x03 /* From RFC 4906; should probably be updated to RFC 4447 (e.g., VC -> PW) */ #define LDP_FEC_MARTINI_VC 0x80 static const struct tok ldp_fec_values[] = { { LDP_FEC_WILDCARD, "Wildcard" }, { LDP_FEC_PREFIX, "Prefix" }, { LDP_FEC_HOSTADDRESS, "Host address" }, { LDP_FEC_MARTINI_VC, "Martini VC" }, { 0, NULL} }; #define LDP_FEC_MARTINI_IFPARM_MTU 0x01 #define LDP_FEC_MARTINI_IFPARM_DESC 0x03 #define LDP_FEC_MARTINI_IFPARM_VCCV 0x0c static const struct tok ldp_fec_martini_ifparm_values[] = { { LDP_FEC_MARTINI_IFPARM_MTU, "MTU" }, { LDP_FEC_MARTINI_IFPARM_DESC, "Description" }, { LDP_FEC_MARTINI_IFPARM_VCCV, "VCCV" }, { 0, NULL} }; /* draft-ietf-pwe3-vccv-04.txt */ static const struct tok ldp_fec_martini_ifparm_vccv_cc_values[] = { { 0x01, "PWE3 control word" }, { 0x02, "MPLS Router Alert Label" }, { 0x04, "MPLS inner label TTL = 1" }, { 0, NULL} }; /* draft-ietf-pwe3-vccv-04.txt */ static const struct tok ldp_fec_martini_ifparm_vccv_cv_values[] = { { 0x01, "ICMP Ping" }, { 0x02, "LSP Ping" }, { 0x04, "BFD" }, { 0, NULL} }; static u_int ldp_pdu_print(netdissect_options *, const u_char *); /* * ldp tlv header * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |U|F| Type | Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | * | Value | * ~ ~ * | | * | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ #define TLV_TCHECK(minlen) \ if (tlv_tlen < minlen) { \ ND_PRINT(" [tlv length %u < %u]", tlv_tlen, minlen); \ nd_print_invalid(ndo); \ goto invalid; \ } static u_int ldp_tlv_print(netdissect_options *ndo, const u_char *tptr, u_int msg_tlen) { struct ldp_tlv_header { nd_uint16_t type; nd_uint16_t length; }; const struct ldp_tlv_header *ldp_tlv_header; u_short tlv_type,tlv_len,tlv_tlen,af,ft_flags; u_char fec_type; u_int ui,vc_info_len, vc_info_tlv_type, vc_info_tlv_len,idx; char buf[100]; int i; ldp_tlv_header = (const struct ldp_tlv_header *)tptr; ND_TCHECK_SIZE(ldp_tlv_header); tlv_len=GET_BE_U_2(ldp_tlv_header->length); if (tlv_len + 4U > msg_tlen) { ND_PRINT("\n\t\t TLV contents go past end of message"); return 0; } tlv_tlen=tlv_len; tlv_type=LDP_MASK_TLV_TYPE(GET_BE_U_2(ldp_tlv_header->type)); /* FIXME vendor private / experimental check */ ND_PRINT("\n\t %s TLV (0x%04x), length: %u, Flags: [%s and %s forward if unknown]", tok2str(ldp_tlv_values, "Unknown", tlv_type), tlv_type, tlv_len, LDP_MASK_U_BIT(GET_BE_U_2(ldp_tlv_header->type)) ? "continue processing" : "ignore", LDP_MASK_F_BIT(GET_BE_U_2(ldp_tlv_header->type)) ? "do" : "don't"); tptr+=sizeof(struct ldp_tlv_header); switch(tlv_type) { case LDP_TLV_COMMON_HELLO: TLV_TCHECK(4); ND_PRINT("\n\t Hold Time: %us, Flags: [%s Hello%s]", GET_BE_U_2(tptr), (GET_BE_U_2(tptr + 2)&0x8000) ? "Targeted" : "Link", (GET_BE_U_2(tptr + 2)&0x4000) ? ", Request for targeted Hellos" : ""); break; case LDP_TLV_IPV4_TRANSPORT_ADDR: TLV_TCHECK(4); ND_PRINT("\n\t IPv4 Transport Address: %s", GET_IPADDR_STRING(tptr)); break; case LDP_TLV_IPV6_TRANSPORT_ADDR: TLV_TCHECK(16); ND_PRINT("\n\t IPv6 Transport Address: %s", GET_IP6ADDR_STRING(tptr)); break; case LDP_TLV_CONFIG_SEQ_NUMBER: TLV_TCHECK(4); ND_PRINT("\n\t Sequence Number: %u", GET_BE_U_4(tptr)); break; case LDP_TLV_ADDRESS_LIST: TLV_TCHECK(LDP_TLV_ADDRESS_LIST_AFNUM_LEN); af = GET_BE_U_2(tptr); tptr+=LDP_TLV_ADDRESS_LIST_AFNUM_LEN; tlv_tlen -= LDP_TLV_ADDRESS_LIST_AFNUM_LEN; ND_PRINT("\n\t Address Family: %s, addresses", tok2str(af_values, "Unknown (%u)", af)); switch (af) { case AFNUM_INET: while(tlv_tlen >= sizeof(nd_ipv4)) { ND_PRINT(" %s", GET_IPADDR_STRING(tptr)); tlv_tlen-=sizeof(nd_ipv4); tptr+=sizeof(nd_ipv4); } break; case AFNUM_INET6: while(tlv_tlen >= sizeof(nd_ipv6)) { ND_PRINT(" %s", GET_IP6ADDR_STRING(tptr)); tlv_tlen-=sizeof(nd_ipv6); tptr+=sizeof(nd_ipv6); } break; default: /* unknown AF */ break; } break; case LDP_TLV_COMMON_SESSION: TLV_TCHECK(8); ND_PRINT("\n\t Version: %u, Keepalive: %us, Flags: [Downstream %s, Loop Detection %s]", GET_BE_U_2(tptr), GET_BE_U_2(tptr + 2), (GET_BE_U_2(tptr + 6)&0x8000) ? "On Demand" : "Unsolicited", (GET_BE_U_2(tptr + 6)&0x4000) ? "Enabled" : "Disabled" ); break; case LDP_TLV_FEC: TLV_TCHECK(1); fec_type = GET_U_1(tptr); ND_PRINT("\n\t %s FEC (0x%02x)", tok2str(ldp_fec_values, "Unknown", fec_type), fec_type); tptr+=1; tlv_tlen-=1; switch(fec_type) { case LDP_FEC_WILDCARD: break; case LDP_FEC_PREFIX: TLV_TCHECK(2); af = GET_BE_U_2(tptr); tptr+=2; tlv_tlen-=2; if (af == AFNUM_INET) { i=decode_prefix4(ndo, tptr, tlv_tlen, buf, sizeof(buf)); if (i == -2) goto trunc; if (i == -3) ND_PRINT(": IPv4 prefix (goes past end of TLV)"); else if (i == -1) ND_PRINT(": IPv4 prefix (invalid length)"); else ND_PRINT(": IPv4 prefix %s", buf); } else if (af == AFNUM_INET6) { i=decode_prefix6(ndo, tptr, tlv_tlen, buf, sizeof(buf)); if (i == -2) goto trunc; if (i == -3) ND_PRINT(": IPv4 prefix (goes past end of TLV)"); else if (i == -1) ND_PRINT(": IPv6 prefix (invalid length)"); else ND_PRINT(": IPv6 prefix %s", buf); } else ND_PRINT(": Address family %u prefix", af); break; case LDP_FEC_HOSTADDRESS: break; case LDP_FEC_MARTINI_VC: /* * We assume the type was supposed to be one of the MPLS * Pseudowire Types. */ TLV_TCHECK(7); vc_info_len = GET_U_1(tptr + 2); /* * According to RFC 4908, the VC info Length field can be zero, * in which case not only are there no interface parameters, * there's no VC ID. */ if (vc_info_len == 0) { ND_PRINT(": %s, %scontrol word, group-ID %u, VC-info-length: %u", tok2str(mpls_pw_types_values, "Unknown", GET_BE_U_2(tptr)&0x7fff), GET_BE_U_2(tptr)&0x8000 ? "" : "no ", GET_BE_U_4(tptr + 3), vc_info_len); break; } /* Make sure we have the VC ID as well */ TLV_TCHECK(11); ND_PRINT(": %s, %scontrol word, group-ID %u, VC-ID %u, VC-info-length: %u", tok2str(mpls_pw_types_values, "Unknown", GET_BE_U_2(tptr)&0x7fff), GET_BE_U_2(tptr)&0x8000 ? "" : "no ", GET_BE_U_4(tptr + 3), GET_BE_U_4(tptr + 7), vc_info_len); if (vc_info_len < 4) { /* minimum 4, for the VC ID */ ND_PRINT(" (invalid, < 4"); return(tlv_len+4); /* Type & Length fields not included */ } vc_info_len -= 4; /* subtract out the VC ID, giving the length of the interface parameters */ /* Skip past the fixed information and the VC ID */ tptr+=11; tlv_tlen-=11; TLV_TCHECK(vc_info_len); while (vc_info_len > 2) { vc_info_tlv_type = GET_U_1(tptr); vc_info_tlv_len = GET_U_1(tptr + 1); if (vc_info_tlv_len < 2) break; if (vc_info_len < vc_info_tlv_len) break; ND_PRINT("\n\t\tInterface Parameter: %s (0x%02x), len %u", tok2str(ldp_fec_martini_ifparm_values,"Unknown",vc_info_tlv_type), vc_info_tlv_type, vc_info_tlv_len); switch(vc_info_tlv_type) { case LDP_FEC_MARTINI_IFPARM_MTU: ND_PRINT(": %u", GET_BE_U_2(tptr + 2)); break; case LDP_FEC_MARTINI_IFPARM_DESC: ND_PRINT(": "); for (idx = 2; idx < vc_info_tlv_len; idx++) fn_print_char(ndo, GET_U_1(tptr + idx)); break; case LDP_FEC_MARTINI_IFPARM_VCCV: ND_PRINT("\n\t\t Control Channels (0x%02x) = [%s]", GET_U_1((tptr + 2)), bittok2str(ldp_fec_martini_ifparm_vccv_cc_values, "none", GET_U_1((tptr + 2)))); ND_PRINT("\n\t\t CV Types (0x%02x) = [%s]", GET_U_1((tptr + 3)), bittok2str(ldp_fec_martini_ifparm_vccv_cv_values, "none", GET_U_1((tptr + 3)))); break; default: print_unknown_data(ndo, tptr+2, "\n\t\t ", vc_info_tlv_len-2); break; } vc_info_len -= vc_info_tlv_len; tptr += vc_info_tlv_len; } break; } break; case LDP_TLV_GENERIC_LABEL: TLV_TCHECK(4); ND_PRINT("\n\t Label: %u", GET_BE_U_4(tptr) & 0xfffff); break; case LDP_TLV_STATUS: TLV_TCHECK(8); ui = GET_BE_U_4(tptr); tptr+=4; ND_PRINT("\n\t Status: 0x%02x, Flags: [%s and %s forward]", ui&0x3fffffff, ui&0x80000000 ? "Fatal error" : "Advisory Notification", ui&0x40000000 ? "do" : "don't"); ui = GET_BE_U_4(tptr); tptr+=4; if (ui) ND_PRINT(", causing Message ID: 0x%08x", ui); break; case LDP_TLV_FT_SESSION: TLV_TCHECK(12); ft_flags = GET_BE_U_2(tptr); ND_PRINT("\n\t Flags: [%sReconnect, %sSave State, %sAll-Label Protection, %s Checkpoint, %sRe-Learn State]", ft_flags&0x8000 ? "" : "No ", ft_flags&0x8 ? "" : "Don't ", ft_flags&0x4 ? "" : "No ", ft_flags&0x2 ? "Sequence Numbered Label" : "All Labels", ft_flags&0x1 ? "" : "Don't "); /* 16 bits (FT Flags) + 16 bits (Reserved) */ tptr+=4; ui = GET_BE_U_4(tptr); if (ui) ND_PRINT(", Reconnect Timeout: %ums", ui); tptr+=4; ui = GET_BE_U_4(tptr); if (ui) ND_PRINT(", Recovery Time: %ums", ui); break; case LDP_TLV_MTU: TLV_TCHECK(2); ND_PRINT("\n\t MTU: %u", GET_BE_U_2(tptr)); break; /* * FIXME those are the defined TLVs that lack a decoder * you are welcome to contribute code ;-) */ case LDP_TLV_HOP_COUNT: case LDP_TLV_PATH_VECTOR: case LDP_TLV_ATM_LABEL: case LDP_TLV_FR_LABEL: case LDP_TLV_EXTD_STATUS: case LDP_TLV_RETURNED_PDU: case LDP_TLV_RETURNED_MSG: case LDP_TLV_ATM_SESSION_PARM: case LDP_TLV_FR_SESSION_PARM: case LDP_TLV_LABEL_REQUEST_MSG_ID: default: if (ndo->ndo_vflag <= 1) print_unknown_data(ndo, tptr, "\n\t ", tlv_tlen); break; } return(tlv_len+4); /* Type & Length fields not included */ trunc: nd_trunc_longjmp(ndo); invalid: return(tlv_len+4); /* Type & Length fields not included */ } void ldp_print(netdissect_options *ndo, const u_char *pptr, u_int len) { u_int processed; ndo->ndo_protocol = "ldp"; while (len > (sizeof(struct ldp_common_header) + sizeof(struct ldp_msg_header))) { processed = ldp_pdu_print(ndo, pptr); if (processed == 0) return; if (len < processed) { ND_PRINT(" [remaining length %u < %u]", len, processed); nd_print_invalid(ndo); break; } len -= processed; pptr += processed; } } static u_int ldp_pdu_print(netdissect_options *ndo, const u_char *pptr) { const struct ldp_common_header *ldp_com_header; const struct ldp_msg_header *ldp_msg_header; const u_char *tptr,*msg_tptr; u_short tlen; u_short pdu_len,msg_len,msg_type; u_int msg_tlen; int hexdump,processed; ldp_com_header = (const struct ldp_common_header *)pptr; ND_TCHECK_SIZE(ldp_com_header); /* * Sanity checking of the header. */ if (GET_BE_U_2(ldp_com_header->version) != LDP_VERSION) { ND_PRINT("%sLDP version %u packet not supported", (ndo->ndo_vflag < 1) ? "" : "\n\t", GET_BE_U_2(ldp_com_header->version)); return 0; } pdu_len = GET_BE_U_2(ldp_com_header->pdu_length); if (pdu_len < sizeof(struct ldp_common_header)-4) { /* length too short */ ND_PRINT("%sLDP, pdu-length: %u (too short, < %zu)", (ndo->ndo_vflag < 1) ? "" : "\n\t", pdu_len, sizeof(struct ldp_common_header)-4); return 0; } /* print the LSR-ID, label-space & length */ ND_PRINT("%sLDP, Label-Space-ID: %s:%u, pdu-length: %u", (ndo->ndo_vflag < 1) ? "" : "\n\t", GET_IPADDR_STRING(ldp_com_header->lsr_id), GET_BE_U_2(ldp_com_header->label_space), pdu_len); /* bail out if non-verbose */ if (ndo->ndo_vflag < 1) return 0; /* ok they seem to want to know everything - lets fully decode it */ tptr = pptr + sizeof(struct ldp_common_header); tlen = pdu_len - (sizeof(struct ldp_common_header)-4); /* Type & Length fields not included */ while(tlen>0) { /* did we capture enough for fully decoding the msg header ? */ ND_TCHECK_LEN(tptr, sizeof(struct ldp_msg_header)); ldp_msg_header = (const struct ldp_msg_header *)tptr; msg_len=GET_BE_U_2(ldp_msg_header->length); msg_type=LDP_MASK_MSG_TYPE(GET_BE_U_2(ldp_msg_header->type)); if (msg_len < sizeof(struct ldp_msg_header)-4) { /* length too short */ /* FIXME vendor private / experimental check */ ND_PRINT("\n\t %s Message (0x%04x), length: %u (too short, < %zu)", tok2str(ldp_msg_values, "Unknown", msg_type), msg_type, msg_len, sizeof(struct ldp_msg_header)-4); return 0; } /* FIXME vendor private / experimental check */ ND_PRINT("\n\t %s Message (0x%04x), length: %u, Message ID: 0x%08x, Flags: [%s if unknown]", tok2str(ldp_msg_values, "Unknown", msg_type), msg_type, msg_len, GET_BE_U_4(ldp_msg_header->id), LDP_MASK_U_BIT(GET_BE_U_2(ldp_msg_header->type)) ? "continue processing" : "ignore"); msg_tptr=tptr+sizeof(struct ldp_msg_header); msg_tlen=msg_len-(sizeof(struct ldp_msg_header)-4); /* Type & Length fields not included */ /* did we capture enough for fully decoding the message ? */ ND_TCHECK_LEN(tptr, msg_len); hexdump=FALSE; switch(msg_type) { case LDP_MSG_NOTIF: case LDP_MSG_HELLO: case LDP_MSG_INIT: case LDP_MSG_KEEPALIVE: case LDP_MSG_ADDRESS: case LDP_MSG_LABEL_MAPPING: case LDP_MSG_ADDRESS_WITHDRAW: case LDP_MSG_LABEL_WITHDRAW: while(msg_tlen >= 4) { processed = ldp_tlv_print(ndo, msg_tptr, msg_tlen); if (processed == 0) break; msg_tlen-=processed; msg_tptr+=processed; } break; /* * FIXME those are the defined messages that lack a decoder * you are welcome to contribute code ;-) */ case LDP_MSG_LABEL_REQUEST: case LDP_MSG_LABEL_RELEASE: case LDP_MSG_LABEL_ABORT_REQUEST: default: if (ndo->ndo_vflag <= 1) print_unknown_data(ndo, msg_tptr, "\n\t ", msg_tlen); break; } /* do we want to see an additionally hexdump ? */ if (ndo->ndo_vflag > 1 || hexdump==TRUE) print_unknown_data(ndo, tptr+sizeof(struct ldp_msg_header), "\n\t ", msg_len); tptr += msg_len+4; tlen -= msg_len+4; } return pdu_len+4; trunc: nd_trunc_longjmp(ndo); } tcpdump-4.99.1/print-cnfp.c0000644000026300017510000003314414057477734013670 0ustar mcrmcr/* $OpenBSD: print-cnfp.c,v 1.2 1998/06/25 20:26:59 mickey Exp $ */ /* * Copyright (c) 1998 Michael Shalayeff * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Michael Shalayeff. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* \summary: Cisco NetFlow protocol printer */ /* * Cisco NetFlow protocol * * See * * https://www.cisco.com/c/en/us/td/docs/net_mgmt/netflow_collection_engine/3-6/user/guide/format.html#wp1005892 */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include #include "netdissect.h" #include "addrtoname.h" #include "extract.h" #include "tcp.h" #include "ipproto.h" struct nfhdr_v1 { nd_uint16_t version; /* version number */ nd_uint16_t count; /* # of records */ nd_uint32_t msys_uptime; nd_uint32_t utc_sec; nd_uint32_t utc_nsec; }; struct nfrec_v1 { nd_ipv4 src_ina; nd_ipv4 dst_ina; nd_ipv4 nhop_ina; nd_uint16_t input; /* SNMP index of input interface */ nd_uint16_t output; /* SNMP index of output interface */ nd_uint32_t packets; /* packets in the flow */ nd_uint32_t octets; /* layer 3 octets in the packets of the flow */ nd_uint32_t start_time; /* sys_uptime value at start of flow */ nd_uint32_t last_time; /* sys_uptime value when last packet of flow was received */ nd_uint16_t srcport; /* TCP/UDP source port or equivalent */ nd_uint16_t dstport; /* TCP/UDP source port or equivalent */ nd_byte pad1[2]; /* pad */ nd_uint8_t proto; /* IP protocol type */ nd_uint8_t tos; /* IP type of service */ nd_uint8_t tcp_flags; /* cumulative OR of TCP flags */ nd_byte pad[3]; /* padding */ nd_uint32_t reserved; /* unused */ }; struct nfhdr_v5 { nd_uint16_t version; /* version number */ nd_uint16_t count; /* # of records */ nd_uint32_t msys_uptime; nd_uint32_t utc_sec; nd_uint32_t utc_nsec; nd_uint32_t sequence; /* flow sequence number */ nd_uint8_t engine_type; /* type of flow-switching engine */ nd_uint8_t engine_id; /* slot number of the flow-switching engine */ nd_uint16_t sampling_interval; /* sampling mode and interval */ }; struct nfrec_v5 { nd_ipv4 src_ina; nd_ipv4 dst_ina; nd_ipv4 nhop_ina; nd_uint16_t input; /* SNMP index of input interface */ nd_uint16_t output; /* SNMP index of output interface */ nd_uint32_t packets; /* packets in the flow */ nd_uint32_t octets; /* layer 3 octets in the packets of the flow */ nd_uint32_t start_time; /* sys_uptime value at start of flow */ nd_uint32_t last_time; /* sys_uptime value when last packet of flow was received */ nd_uint16_t srcport; /* TCP/UDP source port or equivalent */ nd_uint16_t dstport; /* TCP/UDP source port or equivalent */ nd_byte pad1; /* pad */ nd_uint8_t tcp_flags; /* cumulative OR of TCP flags */ nd_uint8_t proto; /* IP protocol type */ nd_uint8_t tos; /* IP type of service */ nd_uint16_t src_as; /* AS number of the source */ nd_uint16_t dst_as; /* AS number of the destination */ nd_uint8_t src_mask; /* source address mask bits */ nd_uint8_t dst_mask; /* destination address prefix mask bits */ nd_byte pad2[2]; nd_ipv4 peer_nexthop; /* v6: IP address of the nexthop within the peer (FIB)*/ }; struct nfhdr_v6 { nd_uint16_t version; /* version number */ nd_uint16_t count; /* # of records */ nd_uint32_t msys_uptime; nd_uint32_t utc_sec; nd_uint32_t utc_nsec; nd_uint32_t sequence; /* v5 flow sequence number */ nd_uint32_t reserved; /* v5 only */ }; struct nfrec_v6 { nd_ipv4 src_ina; nd_ipv4 dst_ina; nd_ipv4 nhop_ina; nd_uint16_t input; /* SNMP index of input interface */ nd_uint16_t output; /* SNMP index of output interface */ nd_uint32_t packets; /* packets in the flow */ nd_uint32_t octets; /* layer 3 octets in the packets of the flow */ nd_uint32_t start_time; /* sys_uptime value at start of flow */ nd_uint32_t last_time; /* sys_uptime value when last packet of flow was received */ nd_uint16_t srcport; /* TCP/UDP source port or equivalent */ nd_uint16_t dstport; /* TCP/UDP source port or equivalent */ nd_byte pad1; /* pad */ nd_uint8_t tcp_flags; /* cumulative OR of TCP flags */ nd_uint8_t proto; /* IP protocol type */ nd_uint8_t tos; /* IP type of service */ nd_uint16_t src_as; /* AS number of the source */ nd_uint16_t dst_as; /* AS number of the destination */ nd_uint8_t src_mask; /* source address mask bits */ nd_uint8_t dst_mask; /* destination address prefix mask bits */ nd_uint16_t flags; nd_ipv4 peer_nexthop; /* v6: IP address of the nexthop within the peer (FIB)*/ }; static void cnfp_v1_print(netdissect_options *ndo, const u_char *cp) { const struct nfhdr_v1 *nh; const struct nfrec_v1 *nr; const char *p_name; uint8_t proto; u_int nrecs, ver; #if 0 time_t t; #endif nh = (const struct nfhdr_v1 *)cp; ND_TCHECK_SIZE(nh); ver = GET_BE_U_2(nh->version); nrecs = GET_BE_U_4(nh->count); #if 0 /* * This is seconds since the UN*X epoch, and is followed by * nanoseconds. XXX - format it, rather than just dumping the * raw seconds-since-the-Epoch. */ t = GET_BE_U_4(nh->utc_sec); #endif ND_PRINT("NetFlow v%x, %u.%03u uptime, %u.%09u, ", ver, GET_BE_U_4(nh->msys_uptime)/1000, GET_BE_U_4(nh->msys_uptime)%1000, GET_BE_U_4(nh->utc_sec), GET_BE_U_4(nh->utc_nsec)); nr = (const struct nfrec_v1 *)&nh[1]; ND_PRINT("%2u recs", nrecs); for (; nrecs != 0; nr++, nrecs--) { char buf[20]; char asbuf[20]; /* * Make sure we have the entire record. */ ND_TCHECK_SIZE(nr); ND_PRINT("\n started %u.%03u, last %u.%03u", GET_BE_U_4(nr->start_time)/1000, GET_BE_U_4(nr->start_time)%1000, GET_BE_U_4(nr->last_time)/1000, GET_BE_U_4(nr->last_time)%1000); asbuf[0] = buf[0] = '\0'; ND_PRINT("\n %s%s%s:%u ", intoa(GET_IPV4_TO_NETWORK_ORDER(nr->src_ina)), buf, asbuf, GET_BE_U_2(nr->srcport)); ND_PRINT("> %s%s%s:%u ", intoa(GET_IPV4_TO_NETWORK_ORDER(nr->dst_ina)), buf, asbuf, GET_BE_U_2(nr->dstport)); ND_PRINT(">> %s\n ", intoa(GET_IPV4_TO_NETWORK_ORDER(nr->nhop_ina))); proto = GET_U_1(nr->proto); if (!ndo->ndo_nflag && (p_name = netdb_protoname(proto)) != NULL) ND_PRINT("%s ", p_name); else ND_PRINT("%u ", proto); /* tcp flags for tcp only */ if (proto == IPPROTO_TCP) { u_int flags; flags = GET_U_1(nr->tcp_flags); ND_PRINT("%s%s%s%s%s%s%s", flags & TH_FIN ? "F" : "", flags & TH_SYN ? "S" : "", flags & TH_RST ? "R" : "", flags & TH_PUSH ? "P" : "", flags & TH_ACK ? "A" : "", flags & TH_URG ? "U" : "", flags ? " " : ""); } buf[0]='\0'; ND_PRINT("tos %u, %u (%u octets) %s", GET_U_1(nr->tos), GET_BE_U_4(nr->packets), GET_BE_U_4(nr->octets), buf); } return; trunc: nd_print_trunc(ndo); } static void cnfp_v5_print(netdissect_options *ndo, const u_char *cp) { const struct nfhdr_v5 *nh; const struct nfrec_v5 *nr; const char *p_name; uint8_t proto; u_int nrecs, ver; #if 0 time_t t; #endif nh = (const struct nfhdr_v5 *)cp; ND_TCHECK_SIZE(nh); ver = GET_BE_U_2(nh->version); nrecs = GET_BE_U_4(nh->count); #if 0 /* * This is seconds since the UN*X epoch, and is followed by * nanoseconds. XXX - format it, rather than just dumping the * raw seconds-since-the-Epoch. */ t = GET_BE_U_4(nh->utc_sec); #endif ND_PRINT("NetFlow v%x, %u.%03u uptime, %u.%09u, ", ver, GET_BE_U_4(nh->msys_uptime)/1000, GET_BE_U_4(nh->msys_uptime)%1000, GET_BE_U_4(nh->utc_sec), GET_BE_U_4(nh->utc_nsec)); ND_PRINT("#%u, ", GET_BE_U_4(nh->sequence)); nr = (const struct nfrec_v5 *)&nh[1]; ND_PRINT("%2u recs", nrecs); for (; nrecs != 0; nr++, nrecs--) { char buf[20]; char asbuf[20]; /* * Make sure we have the entire record. */ ND_TCHECK_SIZE(nr); ND_PRINT("\n started %u.%03u, last %u.%03u", GET_BE_U_4(nr->start_time)/1000, GET_BE_U_4(nr->start_time)%1000, GET_BE_U_4(nr->last_time)/1000, GET_BE_U_4(nr->last_time)%1000); asbuf[0] = buf[0] = '\0'; snprintf(buf, sizeof(buf), "/%u", GET_U_1(nr->src_mask)); snprintf(asbuf, sizeof(asbuf), ":%u", GET_BE_U_2(nr->src_as)); ND_PRINT("\n %s%s%s:%u ", intoa(GET_IPV4_TO_NETWORK_ORDER(nr->src_ina)), buf, asbuf, GET_BE_U_2(nr->srcport)); snprintf(buf, sizeof(buf), "/%u", GET_U_1(nr->dst_mask)); snprintf(asbuf, sizeof(asbuf), ":%u", GET_BE_U_2(nr->dst_as)); ND_PRINT("> %s%s%s:%u ", intoa(GET_IPV4_TO_NETWORK_ORDER(nr->dst_ina)), buf, asbuf, GET_BE_U_2(nr->dstport)); ND_PRINT(">> %s\n ", intoa(GET_IPV4_TO_NETWORK_ORDER(nr->nhop_ina))); proto = GET_U_1(nr->proto); if (!ndo->ndo_nflag && (p_name = netdb_protoname(proto)) != NULL) ND_PRINT("%s ", p_name); else ND_PRINT("%u ", proto); /* tcp flags for tcp only */ if (proto == IPPROTO_TCP) { u_int flags; flags = GET_U_1(nr->tcp_flags); ND_PRINT("%s%s%s%s%s%s%s", flags & TH_FIN ? "F" : "", flags & TH_SYN ? "S" : "", flags & TH_RST ? "R" : "", flags & TH_PUSH ? "P" : "", flags & TH_ACK ? "A" : "", flags & TH_URG ? "U" : "", flags ? " " : ""); } buf[0]='\0'; ND_PRINT("tos %u, %u (%u octets) %s", GET_U_1(nr->tos), GET_BE_U_4(nr->packets), GET_BE_U_4(nr->octets), buf); } return; trunc: nd_print_trunc(ndo); } static void cnfp_v6_print(netdissect_options *ndo, const u_char *cp) { const struct nfhdr_v6 *nh; const struct nfrec_v6 *nr; const char *p_name; uint8_t proto; u_int nrecs, ver; #if 0 time_t t; #endif nh = (const struct nfhdr_v6 *)cp; ND_TCHECK_SIZE(nh); ver = GET_BE_U_2(nh->version); nrecs = GET_BE_U_4(nh->count); #if 0 /* * This is seconds since the UN*X epoch, and is followed by * nanoseconds. XXX - format it, rather than just dumping the * raw seconds-since-the-Epoch. */ t = GET_BE_U_4(nh->utc_sec); #endif ND_PRINT("NetFlow v%x, %u.%03u uptime, %u.%09u, ", ver, GET_BE_U_4(nh->msys_uptime)/1000, GET_BE_U_4(nh->msys_uptime)%1000, GET_BE_U_4(nh->utc_sec), GET_BE_U_4(nh->utc_nsec)); ND_PRINT("#%u, ", GET_BE_U_4(nh->sequence)); nr = (const struct nfrec_v6 *)&nh[1]; ND_PRINT("%2u recs", nrecs); for (; nrecs != 0; nr++, nrecs--) { char buf[20]; char asbuf[20]; /* * Make sure we have the entire record. */ ND_TCHECK_SIZE(nr); ND_PRINT("\n started %u.%03u, last %u.%03u", GET_BE_U_4(nr->start_time)/1000, GET_BE_U_4(nr->start_time)%1000, GET_BE_U_4(nr->last_time)/1000, GET_BE_U_4(nr->last_time)%1000); asbuf[0] = buf[0] = '\0'; snprintf(buf, sizeof(buf), "/%u", GET_U_1(nr->src_mask)); snprintf(asbuf, sizeof(asbuf), ":%u", GET_BE_U_2(nr->src_as)); ND_PRINT("\n %s%s%s:%u ", intoa(GET_IPV4_TO_NETWORK_ORDER(nr->src_ina)), buf, asbuf, GET_BE_U_2(nr->srcport)); snprintf(buf, sizeof(buf), "/%u", GET_U_1(nr->dst_mask)); snprintf(asbuf, sizeof(asbuf), ":%u", GET_BE_U_2(nr->dst_as)); ND_PRINT("> %s%s%s:%u ", intoa(GET_IPV4_TO_NETWORK_ORDER(nr->dst_ina)), buf, asbuf, GET_BE_U_2(nr->dstport)); ND_PRINT(">> %s\n ", intoa(GET_IPV4_TO_NETWORK_ORDER(nr->nhop_ina))); proto = GET_U_1(nr->proto); if (!ndo->ndo_nflag && (p_name = netdb_protoname(proto)) != NULL) ND_PRINT("%s ", p_name); else ND_PRINT("%u ", proto); /* tcp flags for tcp only */ if (proto == IPPROTO_TCP) { u_int flags; flags = GET_U_1(nr->tcp_flags); ND_PRINT("%s%s%s%s%s%s%s", flags & TH_FIN ? "F" : "", flags & TH_SYN ? "S" : "", flags & TH_RST ? "R" : "", flags & TH_PUSH ? "P" : "", flags & TH_ACK ? "A" : "", flags & TH_URG ? "U" : "", flags ? " " : ""); } buf[0]='\0'; snprintf(buf, sizeof(buf), "(%u<>%u encaps)", (GET_BE_U_2(nr->flags) >> 8) & 0xff, (GET_BE_U_2(nr->flags)) & 0xff); ND_PRINT("tos %u, %u (%u octets) %s", GET_U_1(nr->tos), GET_BE_U_4(nr->packets), GET_BE_U_4(nr->octets), buf); } return; trunc: nd_print_trunc(ndo); } void cnfp_print(netdissect_options *ndo, const u_char *cp) { int ver; /* * First 2 bytes are the version number. */ ndo->ndo_protocol = "cnfp"; ver = GET_BE_U_2(cp); switch (ver) { case 1: cnfp_v1_print(ndo, cp); break; case 5: cnfp_v5_print(ndo, cp); break; case 6: cnfp_v6_print(ndo, cp); break; default: ND_PRINT("NetFlow v%x", ver); break; } } tcpdump-4.99.1/print-tcp.c0000644000026300017510000011375314057477734013535 0ustar mcrmcr/* $NetBSD: print-tcp.c,v 1.9 2007/07/26 18:15:12 plunky Exp $ */ /* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * Copyright (c) 1999-2004 The tcpdump.org project * * 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. */ /* \summary: TCP printer */ #ifndef lint #else __RCSID("$NetBSD: print-tcp.c,v 1.8 2007/07/24 11:53:48 drochner Exp $"); #endif #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include #include #include "netdissect.h" #include "addrtoname.h" #include "extract.h" #include "tcp.h" #include "ip.h" #include "ip6.h" #include "ipproto.h" #include "rpc_auth.h" #include "rpc_msg.h" #ifdef HAVE_LIBCRYPTO #include #include "signature.h" static int tcp_verify_signature(netdissect_options *ndo, const struct ip *ip, const struct tcphdr *tp, const u_char *data, u_int length, const u_char *rcvsig); #endif static void print_tcp_rst_data(netdissect_options *, const u_char *sp, u_int length); static void print_tcp_fastopen_option(netdissect_options *ndo, const u_char *cp, u_int datalen, int exp); #define MAX_RST_DATA_LEN 30 struct tha { nd_ipv4 src; nd_ipv4 dst; u_int port; }; struct tcp_seq_hash { struct tcp_seq_hash *nxt; struct tha addr; uint32_t seq; uint32_t ack; }; struct tha6 { nd_ipv6 src; nd_ipv6 dst; u_int port; }; struct tcp_seq_hash6 { struct tcp_seq_hash6 *nxt; struct tha6 addr; uint32_t seq; uint32_t ack; }; #define TSEQ_HASHSIZE 919 /* These tcp options do not have the size octet */ #define ZEROLENOPT(o) ((o) == TCPOPT_EOL || (o) == TCPOPT_NOP) static struct tcp_seq_hash tcp_seq_hash4[TSEQ_HASHSIZE]; static struct tcp_seq_hash6 tcp_seq_hash6[TSEQ_HASHSIZE]; static const struct tok tcp_flag_values[] = { { TH_FIN, "F" }, { TH_SYN, "S" }, { TH_RST, "R" }, { TH_PUSH, "P" }, { TH_ACK, "." }, { TH_URG, "U" }, { TH_ECNECHO, "E" }, { TH_CWR, "W" }, { 0, NULL } }; static const struct tok tcp_option_values[] = { { TCPOPT_EOL, "eol" }, { TCPOPT_NOP, "nop" }, { TCPOPT_MAXSEG, "mss" }, { TCPOPT_WSCALE, "wscale" }, { TCPOPT_SACKOK, "sackOK" }, { TCPOPT_SACK, "sack" }, { TCPOPT_ECHO, "echo" }, { TCPOPT_ECHOREPLY, "echoreply" }, { TCPOPT_TIMESTAMP, "TS" }, { TCPOPT_CC, "cc" }, { TCPOPT_CCNEW, "ccnew" }, { TCPOPT_CCECHO, "" }, { TCPOPT_SIGNATURE, "md5" }, { TCPOPT_SCPS, "scps" }, { TCPOPT_UTO, "uto" }, { TCPOPT_TCPAO, "tcp-ao" }, { TCPOPT_MPTCP, "mptcp" }, { TCPOPT_FASTOPEN, "tfo" }, { TCPOPT_EXPERIMENT2, "exp" }, { 0, NULL } }; static uint16_t tcp_cksum(netdissect_options *ndo, const struct ip *ip, const struct tcphdr *tp, u_int len) { return nextproto4_cksum(ndo, ip, (const uint8_t *)tp, len, len, IPPROTO_TCP); } static uint16_t tcp6_cksum(netdissect_options *ndo, const struct ip6_hdr *ip6, const struct tcphdr *tp, u_int len) { return nextproto6_cksum(ndo, ip6, (const uint8_t *)tp, len, len, IPPROTO_TCP); } void tcp_print(netdissect_options *ndo, const u_char *bp, u_int length, const u_char *bp2, int fragmented) { const struct tcphdr *tp; const struct ip *ip; u_char flags; u_int hlen; char ch; uint16_t sport, dport, win, urp; uint32_t seq, ack, thseq, thack; u_int utoval; uint16_t magic; int rev; const struct ip6_hdr *ip6; u_int header_len; /* Header length in bytes */ ndo->ndo_protocol = "tcp"; tp = (const struct tcphdr *)bp; ip = (const struct ip *)bp2; if (IP_V(ip) == 6) ip6 = (const struct ip6_hdr *)bp2; else ip6 = NULL; ch = '\0'; if (!ND_TTEST_2(tp->th_dport)) { if (ip6) { ND_PRINT("%s > %s:", GET_IP6ADDR_STRING(ip6->ip6_src), GET_IP6ADDR_STRING(ip6->ip6_dst)); } else { ND_PRINT("%s > %s:", GET_IPADDR_STRING(ip->ip_src), GET_IPADDR_STRING(ip->ip_dst)); } nd_print_trunc(ndo); return; } sport = GET_BE_U_2(tp->th_sport); dport = GET_BE_U_2(tp->th_dport); if (ip6) { if (GET_U_1(ip6->ip6_nxt) == IPPROTO_TCP) { ND_PRINT("%s.%s > %s.%s: ", GET_IP6ADDR_STRING(ip6->ip6_src), tcpport_string(ndo, sport), GET_IP6ADDR_STRING(ip6->ip6_dst), tcpport_string(ndo, dport)); } else { ND_PRINT("%s > %s: ", tcpport_string(ndo, sport), tcpport_string(ndo, dport)); } } else { if (GET_U_1(ip->ip_p) == IPPROTO_TCP) { ND_PRINT("%s.%s > %s.%s: ", GET_IPADDR_STRING(ip->ip_src), tcpport_string(ndo, sport), GET_IPADDR_STRING(ip->ip_dst), tcpport_string(ndo, dport)); } else { ND_PRINT("%s > %s: ", tcpport_string(ndo, sport), tcpport_string(ndo, dport)); } } ND_TCHECK_SIZE(tp); hlen = TH_OFF(tp) * 4; if (hlen < sizeof(*tp)) { ND_PRINT(" tcp %u [bad hdr length %u - too short, < %zu]", length - hlen, hlen, sizeof(*tp)); return; } seq = GET_BE_U_4(tp->th_seq); ack = GET_BE_U_4(tp->th_ack); win = GET_BE_U_2(tp->th_win); urp = GET_BE_U_2(tp->th_urp); if (ndo->ndo_qflag) { ND_PRINT("tcp %u", length - hlen); if (hlen > length) { ND_PRINT(" [bad hdr length %u - too long, > %u]", hlen, length); } return; } flags = GET_U_1(tp->th_flags); ND_PRINT("Flags [%s]", bittok2str_nosep(tcp_flag_values, "none", flags)); if (!ndo->ndo_Sflag && (flags & TH_ACK)) { /* * Find (or record) the initial sequence numbers for * this conversation. (we pick an arbitrary * collating order so there's only one entry for * both directions). */ rev = 0; if (ip6) { struct tcp_seq_hash6 *th; struct tcp_seq_hash6 *tcp_seq_hash; const void *src, *dst; struct tha6 tha; tcp_seq_hash = tcp_seq_hash6; src = (const void *)ip6->ip6_src; dst = (const void *)ip6->ip6_dst; if (sport > dport) rev = 1; else if (sport == dport) { if (UNALIGNED_MEMCMP(src, dst, sizeof(ip6->ip6_dst)) > 0) rev = 1; } if (rev) { UNALIGNED_MEMCPY(&tha.src, dst, sizeof(ip6->ip6_dst)); UNALIGNED_MEMCPY(&tha.dst, src, sizeof(ip6->ip6_src)); tha.port = ((u_int)dport) << 16 | sport; } else { UNALIGNED_MEMCPY(&tha.dst, dst, sizeof(ip6->ip6_dst)); UNALIGNED_MEMCPY(&tha.src, src, sizeof(ip6->ip6_src)); tha.port = ((u_int)sport) << 16 | dport; } for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; th->nxt; th = th->nxt) if (memcmp((char *)&tha, (char *)&th->addr, sizeof(th->addr)) == 0) break; if (!th->nxt || (flags & TH_SYN)) { /* didn't find it or new conversation */ /* calloc() return used by the 'tcp_seq_hash6' hash table: do not free() */ if (th->nxt == NULL) { th->nxt = (struct tcp_seq_hash6 *) calloc(1, sizeof(*th)); if (th->nxt == NULL) (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, "%s: calloc", __func__); } th->addr = tha; if (rev) th->ack = seq, th->seq = ack - 1; else th->seq = seq, th->ack = ack - 1; } else { if (rev) seq -= th->ack, ack -= th->seq; else seq -= th->seq, ack -= th->ack; } thseq = th->seq; thack = th->ack; } else { struct tcp_seq_hash *th; struct tcp_seq_hash *tcp_seq_hash; struct tha tha; tcp_seq_hash = tcp_seq_hash4; if (sport > dport) rev = 1; else if (sport == dport) { if (UNALIGNED_MEMCMP(ip->ip_src, ip->ip_dst, sizeof(ip->ip_dst)) > 0) rev = 1; } if (rev) { UNALIGNED_MEMCPY(&tha.src, ip->ip_dst, sizeof(ip->ip_dst)); UNALIGNED_MEMCPY(&tha.dst, ip->ip_src, sizeof(ip->ip_src)); tha.port = ((u_int)dport) << 16 | sport; } else { UNALIGNED_MEMCPY(&tha.dst, ip->ip_dst, sizeof(ip->ip_dst)); UNALIGNED_MEMCPY(&tha.src, ip->ip_src, sizeof(ip->ip_src)); tha.port = ((u_int)sport) << 16 | dport; } for (th = &tcp_seq_hash[tha.port % TSEQ_HASHSIZE]; th->nxt; th = th->nxt) if (memcmp((char *)&tha, (char *)&th->addr, sizeof(th->addr)) == 0) break; if (!th->nxt || (flags & TH_SYN)) { /* didn't find it or new conversation */ /* calloc() return used by the 'tcp_seq_hash4' hash table: do not free() */ if (th->nxt == NULL) { th->nxt = (struct tcp_seq_hash *) calloc(1, sizeof(*th)); if (th->nxt == NULL) (*ndo->ndo_error)(ndo, S_ERR_ND_MEM_ALLOC, "%s: calloc", __func__); } th->addr = tha; if (rev) th->ack = seq, th->seq = ack - 1; else th->seq = seq, th->ack = ack - 1; } else { if (rev) seq -= th->ack, ack -= th->seq; else seq -= th->seq, ack -= th->ack; } thseq = th->seq; thack = th->ack; } } else { /*fool gcc*/ thseq = thack = rev = 0; } if (hlen > length) { ND_PRINT(" [bad hdr length %u - too long, > %u]", hlen, length); return; } if (ndo->ndo_vflag && !ndo->ndo_Kflag && !fragmented) { /* Check the checksum, if possible. */ uint16_t sum, tcp_sum; if (IP_V(ip) == 4) { if (ND_TTEST_LEN(tp->th_sport, length)) { sum = tcp_cksum(ndo, ip, tp, length); tcp_sum = GET_BE_U_2(tp->th_sum); ND_PRINT(", cksum 0x%04x", tcp_sum); if (sum != 0) ND_PRINT(" (incorrect -> 0x%04x)", in_cksum_shouldbe(tcp_sum, sum)); else ND_PRINT(" (correct)"); } } else if (IP_V(ip) == 6) { if (ND_TTEST_LEN(tp->th_sport, length)) { sum = tcp6_cksum(ndo, ip6, tp, length); tcp_sum = GET_BE_U_2(tp->th_sum); ND_PRINT(", cksum 0x%04x", tcp_sum); if (sum != 0) ND_PRINT(" (incorrect -> 0x%04x)", in_cksum_shouldbe(tcp_sum, sum)); else ND_PRINT(" (correct)"); } } } length -= hlen; if (ndo->ndo_vflag > 1 || length > 0 || flags & (TH_SYN | TH_FIN | TH_RST)) { ND_PRINT(", seq %u", seq); if (length > 0) { ND_PRINT(":%u", seq + length); } } if (flags & TH_ACK) { ND_PRINT(", ack %u", ack); } ND_PRINT(", win %u", win); if (flags & TH_URG) ND_PRINT(", urg %u", urp); /* * Handle any options. */ if (hlen > sizeof(*tp)) { const u_char *cp; u_int i, opt, datalen; u_int len; hlen -= sizeof(*tp); cp = (const u_char *)tp + sizeof(*tp); ND_PRINT(", options ["); while (hlen > 0) { if (ch != '\0') ND_PRINT("%c", ch); opt = GET_U_1(cp); cp++; if (ZEROLENOPT(opt)) len = 1; else { len = GET_U_1(cp); cp++; /* total including type, len */ if (len < 2 || len > hlen) goto bad; --hlen; /* account for length byte */ } --hlen; /* account for type byte */ datalen = 0; /* Bail if "l" bytes of data are not left or were not captured */ #define LENCHECK(l) { if ((l) > hlen) goto bad; ND_TCHECK_LEN(cp, l); } ND_PRINT("%s", tok2str(tcp_option_values, "unknown-%u", opt)); switch (opt) { case TCPOPT_MAXSEG: datalen = 2; LENCHECK(datalen); ND_PRINT(" %u", GET_BE_U_2(cp)); break; case TCPOPT_WSCALE: datalen = 1; LENCHECK(datalen); ND_PRINT(" %u", GET_U_1(cp)); break; case TCPOPT_SACK: datalen = len - 2; if (datalen % 8 != 0) { ND_PRINT(" invalid sack"); } else { uint32_t s, e; ND_PRINT(" %u ", datalen / 8); for (i = 0; i < datalen; i += 8) { LENCHECK(i + 4); s = GET_BE_U_4(cp + i); LENCHECK(i + 8); e = GET_BE_U_4(cp + i + 4); if (rev) { s -= thseq; e -= thseq; } else { s -= thack; e -= thack; } ND_PRINT("{%u:%u}", s, e); } } break; case TCPOPT_CC: case TCPOPT_CCNEW: case TCPOPT_CCECHO: case TCPOPT_ECHO: case TCPOPT_ECHOREPLY: /* * those options share their semantics. * fall through */ datalen = 4; LENCHECK(datalen); ND_PRINT(" %u", GET_BE_U_4(cp)); break; case TCPOPT_TIMESTAMP: datalen = 8; LENCHECK(datalen); ND_PRINT(" val %u ecr %u", GET_BE_U_4(cp), GET_BE_U_4(cp + 4)); break; case TCPOPT_SIGNATURE: datalen = TCP_SIGLEN; LENCHECK(datalen); ND_PRINT(" "); #ifdef HAVE_LIBCRYPTO switch (tcp_verify_signature(ndo, ip, tp, bp + TH_OFF(tp) * 4, length, cp)) { case SIGNATURE_VALID: ND_PRINT("valid"); break; case SIGNATURE_INVALID: nd_print_invalid(ndo); break; case CANT_CHECK_SIGNATURE: ND_PRINT("can't check - "); for (i = 0; i < TCP_SIGLEN; ++i) ND_PRINT("%02x", GET_U_1(cp + i)); break; } #else for (i = 0; i < TCP_SIGLEN; ++i) ND_PRINT("%02x", GET_U_1(cp + i)); #endif break; case TCPOPT_SCPS: datalen = 2; LENCHECK(datalen); ND_PRINT(" cap %02x id %u", GET_U_1(cp), GET_U_1(cp + 1)); break; case TCPOPT_TCPAO: datalen = len - 2; /* RFC 5925 Section 2.2: * "The Length value MUST be greater than or equal to 4." * (This includes the Kind and Length fields already processed * at this point.) */ if (datalen < 2) { nd_print_invalid(ndo); } else { LENCHECK(1); ND_PRINT(" keyid %u", GET_U_1(cp)); LENCHECK(2); ND_PRINT(" rnextkeyid %u", GET_U_1(cp + 1)); if (datalen > 2) { ND_PRINT(" mac 0x"); for (i = 2; i < datalen; i++) { LENCHECK(i + 1); ND_PRINT("%02x", GET_U_1(cp + i)); } } } break; case TCPOPT_EOL: case TCPOPT_NOP: case TCPOPT_SACKOK: /* * Nothing interesting. * fall through */ break; case TCPOPT_UTO: datalen = 2; LENCHECK(datalen); utoval = GET_BE_U_2(cp); ND_PRINT(" 0x%x", utoval); if (utoval & 0x0001) utoval = (utoval >> 1) * 60; else utoval >>= 1; ND_PRINT(" %u", utoval); break; case TCPOPT_MPTCP: { const u_char *snapend_save; int ret; datalen = len - 2; LENCHECK(datalen); /* Update the snapend to the end of the option * before calling mptcp_print(). Some options * (MPTCP or others) may be present after a * MPTCP option. This prevents that, in * mptcp_print(), the remaining length < the * remaining caplen. */ snapend_save = ndo->ndo_snapend; ndo->ndo_snapend = ND_MIN(cp - 2 + len, ndo->ndo_snapend); ret = mptcp_print(ndo, cp - 2, len, flags); ndo->ndo_snapend = snapend_save; if (!ret) goto bad; break; } case TCPOPT_FASTOPEN: datalen = len - 2; LENCHECK(datalen); ND_PRINT(" "); print_tcp_fastopen_option(ndo, cp, datalen, FALSE); break; case TCPOPT_EXPERIMENT2: datalen = len - 2; LENCHECK(datalen); if (datalen < 2) goto bad; /* RFC6994 */ magic = GET_BE_U_2(cp); ND_PRINT("-"); switch(magic) { case 0xf989: /* TCP Fast Open RFC 7413 */ print_tcp_fastopen_option(ndo, cp + 2, datalen - 2, TRUE); break; default: /* Unknown magic number */ ND_PRINT("%04x", magic); break; } break; default: datalen = len - 2; if (datalen) ND_PRINT(" 0x"); for (i = 0; i < datalen; ++i) { LENCHECK(i + 1); ND_PRINT("%02x", GET_U_1(cp + i)); } break; } /* Account for data printed */ cp += datalen; hlen -= datalen; /* Check specification against observed length */ ++datalen; /* option octet */ if (!ZEROLENOPT(opt)) ++datalen; /* size octet */ if (datalen != len) ND_PRINT("[len %u]", len); ch = ','; if (opt == TCPOPT_EOL) break; } ND_PRINT("]"); } /* * Print length field before crawling down the stack. */ ND_PRINT(", length %u", length); if (length <= 0) return; /* * Decode payload if necessary. */ header_len = TH_OFF(tp) * 4; /* * Do a bounds check before decoding the payload. * At least the header data is required. */ if (!ND_TTEST_LEN(bp, header_len)) { ND_PRINT(" [remaining caplen(%u) < header length(%u)]", ND_BYTES_AVAILABLE_AFTER(bp), header_len); nd_trunc_longjmp(ndo); } bp += header_len; if ((flags & TH_RST) && ndo->ndo_vflag) { print_tcp_rst_data(ndo, bp, length); return; } if (ndo->ndo_packettype) { switch (ndo->ndo_packettype) { case PT_ZMTP1: zmtp1_print(ndo, bp, length); break; case PT_RESP: resp_print(ndo, bp, length); break; case PT_DOMAIN: /* over_tcp: TRUE, is_mdns: FALSE */ domain_print(ndo, bp, length, TRUE, FALSE); break; } return; } if (IS_SRC_OR_DST_PORT(TELNET_PORT)) { telnet_print(ndo, bp, length); } else if (IS_SRC_OR_DST_PORT(SMTP_PORT)) { ND_PRINT(": "); smtp_print(ndo, bp, length); } else if (IS_SRC_OR_DST_PORT(WHOIS_PORT)) { ND_PRINT(": "); ndo->ndo_protocol = "whois"; /* needed by txtproto_print() */ txtproto_print(ndo, bp, length, NULL, 0); /* RFC 3912 */ } else if (IS_SRC_OR_DST_PORT(BGP_PORT)) bgp_print(ndo, bp, length); else if (IS_SRC_OR_DST_PORT(PPTP_PORT)) pptp_print(ndo, bp); else if (IS_SRC_OR_DST_PORT(REDIS_PORT)) resp_print(ndo, bp, length); else if (IS_SRC_OR_DST_PORT(SSH_PORT)) ssh_print(ndo, bp, length); #ifdef ENABLE_SMB else if (IS_SRC_OR_DST_PORT(NETBIOS_SSN_PORT)) nbt_tcp_print(ndo, bp, length); else if (IS_SRC_OR_DST_PORT(SMB_PORT)) smb_tcp_print(ndo, bp, length); #endif else if (IS_SRC_OR_DST_PORT(BEEP_PORT)) beep_print(ndo, bp, length); else if (IS_SRC_OR_DST_PORT(OPENFLOW_PORT_OLD) || IS_SRC_OR_DST_PORT(OPENFLOW_PORT_IANA)) openflow_print(ndo, bp, length); else if (IS_SRC_OR_DST_PORT(FTP_PORT)) { ND_PRINT(": "); ftp_print(ndo, bp, length); } else if (IS_SRC_OR_DST_PORT(HTTP_PORT) || IS_SRC_OR_DST_PORT(HTTP_PORT_ALT)) { ND_PRINT(": "); http_print(ndo, bp, length); } else if (IS_SRC_OR_DST_PORT(RTSP_PORT) || IS_SRC_OR_DST_PORT(RTSP_PORT_ALT)) { ND_PRINT(": "); rtsp_print(ndo, bp, length); } else if (IS_SRC_OR_DST_PORT(NAMESERVER_PORT)) { /* over_tcp: TRUE, is_mdns: FALSE */ domain_print(ndo, bp, length, TRUE, FALSE); } else if (IS_SRC_OR_DST_PORT(MSDP_PORT)) { msdp_print(ndo, bp, length); } else if (IS_SRC_OR_DST_PORT(RPKI_RTR_PORT)) { rpki_rtr_print(ndo, bp, length); } else if (IS_SRC_OR_DST_PORT(LDP_PORT)) { ldp_print(ndo, bp, length); } else if ((IS_SRC_OR_DST_PORT(NFS_PORT)) && length >= 4 && ND_TTEST_4(bp)) { /* * If data present, header length valid, and NFS port used, * assume NFS. * Pass offset of data plus 4 bytes for RPC TCP msg length * to NFS print routines. */ uint32_t fraglen; const struct sunrpc_msg *rp; enum sunrpc_msg_type direction; fraglen = GET_BE_U_4(bp) & 0x7FFFFFFF; if (fraglen > (length) - 4) fraglen = (length) - 4; rp = (const struct sunrpc_msg *)(bp + 4); if (ND_TTEST_4(rp->rm_direction)) { direction = (enum sunrpc_msg_type) GET_BE_U_4(rp->rm_direction); if (dport == NFS_PORT && direction == SUNRPC_CALL) { ND_PRINT(": NFS request xid %u ", GET_BE_U_4(rp->rm_xid)); nfsreq_noaddr_print(ndo, (const u_char *)rp, fraglen, (const u_char *)ip); return; } if (sport == NFS_PORT && direction == SUNRPC_REPLY) { ND_PRINT(": NFS reply xid %u ", GET_BE_U_4(rp->rm_xid)); nfsreply_noaddr_print(ndo, (const u_char *)rp, fraglen, (const u_char *)ip); return; } } } return; bad: ND_PRINT("[bad opt]"); if (ch != '\0') ND_PRINT("]"); return; trunc: nd_print_trunc(ndo); if (ch != '\0') ND_PRINT(">"); } /* * RFC1122 says the following on data in RST segments: * * 4.2.2.12 RST Segment: RFC-793 Section 3.4 * * A TCP SHOULD allow a received RST segment to include data. * * DISCUSSION * It has been suggested that a RST segment could contain * ASCII text that encoded and explained the cause of the * RST. No standard has yet been established for such * data. * */ static void print_tcp_rst_data(netdissect_options *ndo, const u_char *sp, u_int length) { u_char c; ND_PRINT(ND_TTEST_LEN(sp, length) ? " [RST" : " [!RST"); if (length > MAX_RST_DATA_LEN) { length = MAX_RST_DATA_LEN; /* can use -X for longer */ ND_PRINT("+"); /* indicate we truncate */ } ND_PRINT(" "); while (length && sp < ndo->ndo_snapend) { c = GET_U_1(sp); sp++; fn_print_char(ndo, c); length--; } ND_PRINT("]"); } static void print_tcp_fastopen_option(netdissect_options *ndo, const u_char *cp, u_int datalen, int exp) { u_int i; if (exp) ND_PRINT("tfo"); if (datalen == 0) { /* Fast Open Cookie Request */ ND_PRINT(" cookiereq"); } else { /* Fast Open Cookie */ if (datalen % 2 != 0 || datalen < 4 || datalen > 16) { nd_print_invalid(ndo); } else { ND_PRINT(" cookie "); for (i = 0; i < datalen; ++i) ND_PRINT("%02x", GET_U_1(cp + i)); } } } #ifdef HAVE_LIBCRYPTO USES_APPLE_DEPRECATED_API static int tcp_verify_signature(netdissect_options *ndo, const struct ip *ip, const struct tcphdr *tp, const u_char *data, u_int length, const u_char *rcvsig) { struct tcphdr tp1; u_char sig[TCP_SIGLEN]; char zero_proto = 0; MD5_CTX ctx; uint16_t savecsum, tlen; const struct ip6_hdr *ip6; uint32_t len32; uint8_t nxt; if (data + length > ndo->ndo_snapend) { ND_PRINT("snaplen too short, "); return (CANT_CHECK_SIGNATURE); } tp1 = *tp; if (ndo->ndo_sigsecret == NULL) { ND_PRINT("shared secret not supplied with -M, "); return (CANT_CHECK_SIGNATURE); } MD5_Init(&ctx); /* * Step 1: Update MD5 hash with IP pseudo-header. */ if (IP_V(ip) == 4) { MD5_Update(&ctx, (const char *)&ip->ip_src, sizeof(ip->ip_src)); MD5_Update(&ctx, (const char *)&ip->ip_dst, sizeof(ip->ip_dst)); MD5_Update(&ctx, (const char *)&zero_proto, sizeof(zero_proto)); MD5_Update(&ctx, (const char *)&ip->ip_p, sizeof(ip->ip_p)); tlen = GET_BE_U_2(ip->ip_len) - IP_HL(ip) * 4; tlen = htons(tlen); MD5_Update(&ctx, (const char *)&tlen, sizeof(tlen)); } else if (IP_V(ip) == 6) { ip6 = (const struct ip6_hdr *)ip; MD5_Update(&ctx, (const char *)&ip6->ip6_src, sizeof(ip6->ip6_src)); MD5_Update(&ctx, (const char *)&ip6->ip6_dst, sizeof(ip6->ip6_dst)); len32 = htonl(GET_BE_U_2(ip6->ip6_plen)); MD5_Update(&ctx, (const char *)&len32, sizeof(len32)); nxt = 0; MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt)); MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt)); MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt)); nxt = IPPROTO_TCP; MD5_Update(&ctx, (const char *)&nxt, sizeof(nxt)); } else { ND_PRINT("IP version not 4 or 6, "); return (CANT_CHECK_SIGNATURE); } /* * Step 2: Update MD5 hash with TCP header, excluding options. * The TCP checksum must be set to zero. */ memcpy(&savecsum, tp1.th_sum, sizeof(savecsum)); memset(tp1.th_sum, 0, sizeof(tp1.th_sum)); MD5_Update(&ctx, (const char *)&tp1, sizeof(struct tcphdr)); memcpy(tp1.th_sum, &savecsum, sizeof(tp1.th_sum)); /* * Step 3: Update MD5 hash with TCP segment data, if present. */ if (length > 0) MD5_Update(&ctx, data, length); /* * Step 4: Update MD5 hash with shared secret. */ MD5_Update(&ctx, ndo->ndo_sigsecret, strlen(ndo->ndo_sigsecret)); MD5_Final(sig, &ctx); if (memcmp(rcvsig, sig, TCP_SIGLEN) == 0) return (SIGNATURE_VALID); else return (SIGNATURE_INVALID); } USES_APPLE_RST #endif /* HAVE_LIBCRYPTO */ tcpdump-4.99.1/print-pptp.c0000644000026300017510000005661614057477727013740 0ustar mcrmcr/* * Copyright (c) 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. * * PPTP support contributed by Motonori Shindo (mshindo@mshindo.net) */ /* \summary: Point-to-Point Tunnelling Protocol (PPTP) printer */ /* specification: RFC 2637 */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" #include "extract.h" #define PPTP_MSG_TYPE_CTRL 1 /* Control Message */ #define PPTP_MSG_TYPE_MGMT 2 /* Management Message (currently not used */ #define PPTP_MAGIC_COOKIE 0x1a2b3c4d /* for sanity check */ #define PPTP_CTRL_MSG_TYPE_SCCRQ 1 #define PPTP_CTRL_MSG_TYPE_SCCRP 2 #define PPTP_CTRL_MSG_TYPE_StopCCRQ 3 #define PPTP_CTRL_MSG_TYPE_StopCCRP 4 #define PPTP_CTRL_MSG_TYPE_ECHORQ 5 #define PPTP_CTRL_MSG_TYPE_ECHORP 6 #define PPTP_CTRL_MSG_TYPE_OCRQ 7 #define PPTP_CTRL_MSG_TYPE_OCRP 8 #define PPTP_CTRL_MSG_TYPE_ICRQ 9 #define PPTP_CTRL_MSG_TYPE_ICRP 10 #define PPTP_CTRL_MSG_TYPE_ICCN 11 #define PPTP_CTRL_MSG_TYPE_CCRQ 12 #define PPTP_CTRL_MSG_TYPE_CDN 13 #define PPTP_CTRL_MSG_TYPE_WEN 14 #define PPTP_CTRL_MSG_TYPE_SLI 15 #define PPTP_FRAMING_CAP_ASYNC_MASK 0x00000001 /* Aynchronous */ #define PPTP_FRAMING_CAP_SYNC_MASK 0x00000002 /* Synchronous */ #define PPTP_BEARER_CAP_ANALOG_MASK 0x00000001 /* Analog */ #define PPTP_BEARER_CAP_DIGITAL_MASK 0x00000002 /* Digital */ static const char *pptp_message_type_string[] = { "NOT_DEFINED", /* 0 Not defined in the RFC2637 */ "SCCRQ", /* 1 Start-Control-Connection-Request */ "SCCRP", /* 2 Start-Control-Connection-Reply */ "StopCCRQ", /* 3 Stop-Control-Connection-Request */ "StopCCRP", /* 4 Stop-Control-Connection-Reply */ "ECHORQ", /* 5 Echo Request */ "ECHORP", /* 6 Echo Reply */ "OCRQ", /* 7 Outgoing-Call-Request */ "OCRP", /* 8 Outgoing-Call-Reply */ "ICRQ", /* 9 Incoming-Call-Request */ "ICRP", /* 10 Incoming-Call-Reply */ "ICCN", /* 11 Incoming-Call-Connected */ "CCRQ", /* 12 Call-Clear-Request */ "CDN", /* 13 Call-Disconnect-Notify */ "WEN", /* 14 WAN-Error-Notify */ "SLI" /* 15 Set-Link-Info */ #define PPTP_MAX_MSGTYPE_INDEX 16 }; /* common for all PPTP control messages */ struct pptp_hdr { nd_uint16_t length; nd_uint16_t msg_type; nd_uint32_t magic_cookie; nd_uint16_t ctrl_msg_type; nd_uint16_t reserved0; }; struct pptp_msg_sccrq { nd_uint16_t proto_ver; nd_uint16_t reserved1; nd_uint32_t framing_cap; nd_uint32_t bearer_cap; nd_uint16_t max_channel; nd_uint16_t firm_rev; nd_byte hostname[64]; nd_byte vendor[64]; }; struct pptp_msg_sccrp { nd_uint16_t proto_ver; nd_uint8_t result_code; nd_uint8_t err_code; nd_uint32_t framing_cap; nd_uint32_t bearer_cap; nd_uint16_t max_channel; nd_uint16_t firm_rev; nd_byte hostname[64]; nd_byte vendor[64]; }; struct pptp_msg_stopccrq { nd_uint8_t reason; nd_uint8_t reserved1; nd_uint16_t reserved2; }; struct pptp_msg_stopccrp { nd_uint8_t result_code; nd_uint8_t err_code; nd_uint16_t reserved1; }; struct pptp_msg_echorq { nd_uint32_t id; }; struct pptp_msg_echorp { nd_uint32_t id; nd_uint8_t result_code; nd_uint8_t err_code; nd_uint16_t reserved1; }; struct pptp_msg_ocrq { nd_uint16_t call_id; nd_uint16_t call_ser; nd_uint32_t min_bps; nd_uint32_t max_bps; nd_uint32_t bearer_type; nd_uint32_t framing_type; nd_uint16_t recv_winsiz; nd_uint16_t pkt_proc_delay; nd_uint16_t phone_no_len; nd_uint16_t reserved1; nd_byte phone_no[64]; nd_byte subaddr[64]; }; struct pptp_msg_ocrp { nd_uint16_t call_id; nd_uint16_t peer_call_id; nd_uint8_t result_code; nd_uint8_t err_code; nd_uint16_t cause_code; nd_uint32_t conn_speed; nd_uint16_t recv_winsiz; nd_uint16_t pkt_proc_delay; nd_uint32_t phy_chan_id; }; struct pptp_msg_icrq { nd_uint16_t call_id; nd_uint16_t call_ser; nd_uint32_t bearer_type; nd_uint32_t phy_chan_id; nd_uint16_t dialed_no_len; nd_uint16_t dialing_no_len; nd_byte dialed_no[64]; /* DNIS */ nd_byte dialing_no[64]; /* CLID */ nd_byte subaddr[64]; }; struct pptp_msg_icrp { nd_uint16_t call_id; nd_uint16_t peer_call_id; nd_uint8_t result_code; nd_uint8_t err_code; nd_uint16_t recv_winsiz; nd_uint16_t pkt_proc_delay; nd_uint16_t reserved1; }; struct pptp_msg_iccn { nd_uint16_t peer_call_id; nd_uint16_t reserved1; nd_uint32_t conn_speed; nd_uint16_t recv_winsiz; nd_uint16_t pkt_proc_delay; nd_uint32_t framing_type; }; struct pptp_msg_ccrq { nd_uint16_t call_id; nd_uint16_t reserved1; }; struct pptp_msg_cdn { nd_uint16_t call_id; nd_uint8_t result_code; nd_uint8_t err_code; nd_uint16_t cause_code; nd_uint16_t reserved1; nd_byte call_stats[128]; }; struct pptp_msg_wen { nd_uint16_t peer_call_id; nd_uint16_t reserved1; nd_uint32_t crc_err; nd_uint32_t framing_err; nd_uint32_t hardware_overrun; nd_uint32_t buffer_overrun; nd_uint32_t timeout_err; nd_uint32_t align_err; }; struct pptp_msg_sli { nd_uint16_t peer_call_id; nd_uint16_t reserved1; nd_uint32_t send_accm; nd_uint32_t recv_accm; }; /* attributes that appear more than once in above messages: Number of occurrence attributes -------------------------------------- 2 uint32_t bearer_cap; 2 uint32_t bearer_type; 6 uint16_t call_id; 2 uint16_t call_ser; 2 uint16_t cause_code; 2 uint32_t conn_speed; 6 uint8_t err_code; 2 uint16_t firm_rev; 2 uint32_t framing_cap; 2 uint32_t framing_type; 2 u_char hostname[64]; 2 uint32_t id; 2 uint16_t max_channel; 5 uint16_t peer_call_id; 2 uint32_t phy_chan_id; 4 uint16_t pkt_proc_delay; 2 uint16_t proto_ver; 4 uint16_t recv_winsiz; 2 uint8_t reserved1; 9 uint16_t reserved1; 6 uint8_t result_code; 2 u_char subaddr[64]; 2 u_char vendor[64]; so I will prepare print out functions for these attributes (except for reserved*). */ #define PRINT_RESERVED_IF_NOT_ZERO_1(reserved) \ if (GET_U_1(reserved)) \ ND_PRINT(" [ERROR: reserved=%u must be zero]", \ GET_U_1(reserved)); #define PRINT_RESERVED_IF_NOT_ZERO_2(reserved) \ if (GET_BE_U_2(reserved)) \ ND_PRINT(" [ERROR: reserved=%u must be zero]", \ GET_BE_U_2(reserved)); /******************************************/ /* Attribute-specific print out functions */ /******************************************/ static void pptp_bearer_cap_print(netdissect_options *ndo, const nd_uint32_t bearer_cap) { ND_PRINT(" BEARER_CAP(%s%s)", GET_BE_U_4(bearer_cap) & PPTP_BEARER_CAP_DIGITAL_MASK ? "D" : "", GET_BE_U_4(bearer_cap) & PPTP_BEARER_CAP_ANALOG_MASK ? "A" : ""); } static const struct tok pptp_btype_str[] = { { 1, "A" }, /* Analog */ { 2, "D" }, /* Digital */ { 3, "Any" }, { 0, NULL } }; static void pptp_bearer_type_print(netdissect_options *ndo, const nd_uint32_t bearer_type) { ND_PRINT(" BEARER_TYPE(%s)", tok2str(pptp_btype_str, "?", GET_BE_U_4(bearer_type))); } static void pptp_call_id_print(netdissect_options *ndo, const nd_uint16_t call_id) { ND_PRINT(" CALL_ID(%u)", GET_BE_U_2(call_id)); } static void pptp_call_ser_print(netdissect_options *ndo, const nd_uint16_t call_ser) { ND_PRINT(" CALL_SER_NUM(%u)", GET_BE_U_2(call_ser)); } static void pptp_cause_code_print(netdissect_options *ndo, const nd_uint16_t cause_code) { ND_PRINT(" CAUSE_CODE(%u)", GET_BE_U_2(cause_code)); } static void pptp_conn_speed_print(netdissect_options *ndo, const nd_uint32_t conn_speed) { ND_PRINT(" CONN_SPEED(%u)", GET_BE_U_4(conn_speed)); } static const struct tok pptp_errcode_str[] = { { 0, "None" }, { 1, "Not-Connected" }, { 2, "Bad-Format" }, { 3, "Bad-Value" }, { 4, "No-Resource" }, { 5, "Bad-Call-ID" }, { 6, "PAC-Error" }, { 0, NULL } }; static void pptp_err_code_print(netdissect_options *ndo, const nd_uint8_t err_code) { ND_PRINT(" ERR_CODE(%u", GET_U_1(err_code)); if (ndo->ndo_vflag) { ND_PRINT(":%s", tok2str(pptp_errcode_str, "?", GET_U_1(err_code))); } ND_PRINT(")"); } static void pptp_firm_rev_print(netdissect_options *ndo, const nd_uint16_t firm_rev) { ND_PRINT(" FIRM_REV(%u)", GET_BE_U_2(firm_rev)); } static void pptp_framing_cap_print(netdissect_options *ndo, const nd_uint32_t framing_cap) { ND_PRINT(" FRAME_CAP("); if (GET_BE_U_4(framing_cap) & PPTP_FRAMING_CAP_ASYNC_MASK) { ND_PRINT("A"); /* Async */ } if (GET_BE_U_4(framing_cap) & PPTP_FRAMING_CAP_SYNC_MASK) { ND_PRINT("S"); /* Sync */ } ND_PRINT(")"); } static const struct tok pptp_ftype_str[] = { { 1, "A" }, /* Async */ { 2, "S" }, /* Sync */ { 3, "E" }, /* Either */ { 0, NULL } }; static void pptp_framing_type_print(netdissect_options *ndo, const nd_uint32_t framing_type) { ND_PRINT(" FRAME_TYPE(%s)", tok2str(pptp_ftype_str, "?", GET_BE_U_4(framing_type))); } static void pptp_hostname_print(netdissect_options *ndo, const u_char *hostname) { ND_PRINT(" HOSTNAME("); nd_printjnp(ndo, hostname, 64); ND_PRINT(")"); } static void pptp_id_print(netdissect_options *ndo, const nd_uint32_t id) { ND_PRINT(" ID(%u)", GET_BE_U_4(id)); } static void pptp_max_channel_print(netdissect_options *ndo, const nd_uint16_t max_channel) { ND_PRINT(" MAX_CHAN(%u)", GET_BE_U_2(max_channel)); } static void pptp_peer_call_id_print(netdissect_options *ndo, const nd_uint16_t peer_call_id) { ND_PRINT(" PEER_CALL_ID(%u)", GET_BE_U_2(peer_call_id)); } static void pptp_phy_chan_id_print(netdissect_options *ndo, const nd_uint32_t phy_chan_id) { ND_PRINT(" PHY_CHAN_ID(%u)", GET_BE_U_4(phy_chan_id)); } static void pptp_pkt_proc_delay_print(netdissect_options *ndo, const nd_uint16_t pkt_proc_delay) { ND_PRINT(" PROC_DELAY(%u)", GET_BE_U_2(pkt_proc_delay)); } static void pptp_proto_ver_print(netdissect_options *ndo, const nd_uint16_t proto_ver) { ND_PRINT(" PROTO_VER(%u.%u)", /* Version.Revision */ GET_BE_U_2(proto_ver) >> 8, GET_BE_U_2(proto_ver) & 0xff); } static void pptp_recv_winsiz_print(netdissect_options *ndo, const nd_uint16_t recv_winsiz) { ND_PRINT(" RECV_WIN(%u)", GET_BE_U_2(recv_winsiz)); } static const struct tok pptp_scrrp_str[] = { { 1, "Successful channel establishment" }, { 2, "General error" }, { 3, "Command channel already exists" }, { 4, "Requester is not authorized to establish a command channel" }, { 5, "The protocol version of the requester is not supported" }, { 0, NULL } }; static const struct tok pptp_echorp_str[] = { { 1, "OK" }, { 2, "General Error" }, { 0, NULL } }; static const struct tok pptp_ocrp_str[] = { { 1, "Connected" }, { 2, "General Error" }, { 3, "No Carrier" }, { 4, "Busy" }, { 5, "No Dial Tone" }, { 6, "Time-out" }, { 7, "Do Not Accept" }, { 0, NULL } }; static const struct tok pptp_icrp_str[] = { { 1, "Connect" }, { 2, "General Error" }, { 3, "Do Not Accept" }, { 0, NULL } }; static const struct tok pptp_cdn_str[] = { { 1, "Lost Carrier" }, { 2, "General Error" }, { 3, "Admin Shutdown" }, { 4, "Request" }, { 0, NULL } }; static void pptp_result_code_print(netdissect_options *ndo, const nd_uint8_t result_code, int ctrl_msg_type) { ND_PRINT(" RESULT_CODE(%u", GET_U_1(result_code)); if (ndo->ndo_vflag) { const struct tok *dict = ctrl_msg_type == PPTP_CTRL_MSG_TYPE_SCCRP ? pptp_scrrp_str : ctrl_msg_type == PPTP_CTRL_MSG_TYPE_StopCCRP ? pptp_echorp_str : ctrl_msg_type == PPTP_CTRL_MSG_TYPE_ECHORP ? pptp_echorp_str : ctrl_msg_type == PPTP_CTRL_MSG_TYPE_OCRP ? pptp_ocrp_str : ctrl_msg_type == PPTP_CTRL_MSG_TYPE_ICRP ? pptp_icrp_str : ctrl_msg_type == PPTP_CTRL_MSG_TYPE_CDN ? pptp_cdn_str : NULL; /* assertion error */ if (dict != NULL) ND_PRINT(":%s", tok2str(dict, "?", GET_U_1(result_code))); } ND_PRINT(")"); } static void pptp_subaddr_print(netdissect_options *ndo, const u_char *subaddr) { ND_PRINT(" SUB_ADDR("); nd_printjnp(ndo, subaddr, 64); ND_PRINT(")"); } static void pptp_vendor_print(netdissect_options *ndo, const u_char *vendor) { ND_PRINT(" VENDOR("); nd_printjnp(ndo, vendor, 64); ND_PRINT(")"); } /************************************/ /* PPTP message print out functions */ /************************************/ static void pptp_sccrq_print(netdissect_options *ndo, const u_char *dat) { const struct pptp_msg_sccrq *ptr = (const struct pptp_msg_sccrq *)dat; pptp_proto_ver_print(ndo, ptr->proto_ver); PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1); pptp_framing_cap_print(ndo, ptr->framing_cap); pptp_bearer_cap_print(ndo, ptr->bearer_cap); pptp_max_channel_print(ndo, ptr->max_channel); pptp_firm_rev_print(ndo, ptr->firm_rev); pptp_hostname_print(ndo, ptr->hostname); pptp_vendor_print(ndo, ptr->vendor); } static void pptp_sccrp_print(netdissect_options *ndo, const u_char *dat) { const struct pptp_msg_sccrp *ptr = (const struct pptp_msg_sccrp *)dat; pptp_proto_ver_print(ndo, ptr->proto_ver); pptp_result_code_print(ndo, ptr->result_code, PPTP_CTRL_MSG_TYPE_SCCRP); pptp_err_code_print(ndo, ptr->err_code); pptp_framing_cap_print(ndo, ptr->framing_cap); pptp_bearer_cap_print(ndo, ptr->bearer_cap); pptp_max_channel_print(ndo, ptr->max_channel); pptp_firm_rev_print(ndo, ptr->firm_rev); pptp_hostname_print(ndo, ptr->hostname); pptp_vendor_print(ndo, ptr->vendor); } static void pptp_stopccrq_print(netdissect_options *ndo, const u_char *dat) { const struct pptp_msg_stopccrq *ptr = (const struct pptp_msg_stopccrq *)dat; ND_PRINT(" REASON(%u", GET_U_1(ptr->reason)); if (ndo->ndo_vflag) { switch (GET_U_1(ptr->reason)) { case 1: ND_PRINT(":None"); break; case 2: ND_PRINT(":Stop-Protocol"); break; case 3: ND_PRINT(":Stop-Local-Shutdown"); break; default: ND_PRINT(":?"); break; } } ND_PRINT(")"); PRINT_RESERVED_IF_NOT_ZERO_1(ptr->reserved1); PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved2); } static void pptp_stopccrp_print(netdissect_options *ndo, const u_char *dat) { const struct pptp_msg_stopccrp *ptr = (const struct pptp_msg_stopccrp *)dat; pptp_result_code_print(ndo, ptr->result_code, PPTP_CTRL_MSG_TYPE_StopCCRP); pptp_err_code_print(ndo, ptr->err_code); PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1); } static void pptp_echorq_print(netdissect_options *ndo, const u_char *dat) { const struct pptp_msg_echorq *ptr = (const struct pptp_msg_echorq *)dat; pptp_id_print(ndo, ptr->id); } static void pptp_echorp_print(netdissect_options *ndo, const u_char *dat) { const struct pptp_msg_echorp *ptr = (const struct pptp_msg_echorp *)dat; pptp_id_print(ndo, ptr->id); pptp_result_code_print(ndo, ptr->result_code, PPTP_CTRL_MSG_TYPE_ECHORP); pptp_err_code_print(ndo, ptr->err_code); PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1); } static void pptp_ocrq_print(netdissect_options *ndo, const u_char *dat) { const struct pptp_msg_ocrq *ptr = (const struct pptp_msg_ocrq *)dat; pptp_call_id_print(ndo, ptr->call_id); pptp_call_ser_print(ndo, ptr->call_ser); ND_PRINT(" MIN_BPS(%u)", GET_BE_U_4(ptr->min_bps)); ND_PRINT(" MAX_BPS(%u)", GET_BE_U_4(ptr->max_bps)); pptp_bearer_type_print(ndo, ptr->bearer_type); pptp_framing_type_print(ndo, ptr->framing_type); pptp_recv_winsiz_print(ndo, ptr->recv_winsiz); pptp_pkt_proc_delay_print(ndo, ptr->pkt_proc_delay); ND_PRINT(" PHONE_NO_LEN(%u)", GET_BE_U_2(ptr->phone_no_len)); PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1); ND_PRINT(" PHONE_NO("); nd_printjnp(ndo, ptr->phone_no, ND_MIN(64, GET_BE_U_2(ptr->phone_no_len))); ND_PRINT(")"); pptp_subaddr_print(ndo, ptr->subaddr); } static void pptp_ocrp_print(netdissect_options *ndo, const u_char *dat) { const struct pptp_msg_ocrp *ptr = (const struct pptp_msg_ocrp *)dat; pptp_call_id_print(ndo, ptr->call_id); pptp_peer_call_id_print(ndo, ptr->peer_call_id); pptp_result_code_print(ndo, ptr->result_code, PPTP_CTRL_MSG_TYPE_OCRP); pptp_err_code_print(ndo, ptr->err_code); pptp_cause_code_print(ndo, ptr->cause_code); pptp_conn_speed_print(ndo, ptr->conn_speed); pptp_recv_winsiz_print(ndo, ptr->recv_winsiz); pptp_pkt_proc_delay_print(ndo, ptr->pkt_proc_delay); pptp_phy_chan_id_print(ndo, ptr->phy_chan_id); } static void pptp_icrq_print(netdissect_options *ndo, const u_char *dat) { const struct pptp_msg_icrq *ptr = (const struct pptp_msg_icrq *)dat; pptp_call_id_print(ndo, ptr->call_id); pptp_call_ser_print(ndo, ptr->call_ser); pptp_bearer_type_print(ndo, ptr->bearer_type); pptp_phy_chan_id_print(ndo, ptr->phy_chan_id); ND_PRINT(" DIALED_NO_LEN(%u)", GET_BE_U_2(ptr->dialed_no_len)); ND_PRINT(" DIALING_NO_LEN(%u)", GET_BE_U_2(ptr->dialing_no_len)); ND_PRINT(" DIALED_NO("); nd_printjnp(ndo, ptr->dialed_no, ND_MIN(64, GET_BE_U_2(ptr->dialed_no_len))); ND_PRINT(")"); ND_PRINT(" DIALING_NO("); nd_printjnp(ndo, ptr->dialing_no, ND_MIN(64, GET_BE_U_2(ptr->dialing_no_len))); ND_PRINT(")"); pptp_subaddr_print(ndo, ptr->subaddr); } static void pptp_icrp_print(netdissect_options *ndo, const u_char *dat) { const struct pptp_msg_icrp *ptr = (const struct pptp_msg_icrp *)dat; pptp_call_id_print(ndo, ptr->call_id); pptp_peer_call_id_print(ndo, ptr->peer_call_id); pptp_result_code_print(ndo, ptr->result_code, PPTP_CTRL_MSG_TYPE_ICRP); pptp_err_code_print(ndo, ptr->err_code); pptp_recv_winsiz_print(ndo, ptr->recv_winsiz); pptp_pkt_proc_delay_print(ndo, ptr->pkt_proc_delay); PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1); } static void pptp_iccn_print(netdissect_options *ndo, const u_char *dat) { const struct pptp_msg_iccn *ptr = (const struct pptp_msg_iccn *)dat; pptp_peer_call_id_print(ndo, ptr->peer_call_id); PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1); pptp_conn_speed_print(ndo, ptr->conn_speed); pptp_recv_winsiz_print(ndo, ptr->recv_winsiz); pptp_pkt_proc_delay_print(ndo, ptr->pkt_proc_delay); pptp_framing_type_print(ndo, ptr->framing_type); } static void pptp_ccrq_print(netdissect_options *ndo, const u_char *dat) { const struct pptp_msg_ccrq *ptr = (const struct pptp_msg_ccrq *)dat; pptp_call_id_print(ndo, ptr->call_id); PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1); } static void pptp_cdn_print(netdissect_options *ndo, const u_char *dat) { const struct pptp_msg_cdn *ptr = (const struct pptp_msg_cdn *)dat; pptp_call_id_print(ndo, ptr->call_id); pptp_result_code_print(ndo, ptr->result_code, PPTP_CTRL_MSG_TYPE_CDN); pptp_err_code_print(ndo, ptr->err_code); pptp_cause_code_print(ndo, ptr->cause_code); PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1); ND_PRINT(" CALL_STATS("); nd_printjnp(ndo, ptr->call_stats, 128); ND_PRINT(")"); } static void pptp_wen_print(netdissect_options *ndo, const u_char *dat) { const struct pptp_msg_wen *ptr = (const struct pptp_msg_wen *)dat; pptp_peer_call_id_print(ndo, ptr->peer_call_id); PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1); ND_PRINT(" CRC_ERR(%u)", GET_BE_U_4(ptr->crc_err)); ND_PRINT(" FRAMING_ERR(%u)", GET_BE_U_4(ptr->framing_err)); ND_PRINT(" HARDWARE_OVERRUN(%u)", GET_BE_U_4(ptr->hardware_overrun)); ND_PRINT(" BUFFER_OVERRUN(%u)", GET_BE_U_4(ptr->buffer_overrun)); ND_PRINT(" TIMEOUT_ERR(%u)", GET_BE_U_4(ptr->timeout_err)); ND_PRINT(" ALIGN_ERR(%u)", GET_BE_U_4(ptr->align_err)); } static void pptp_sli_print(netdissect_options *ndo, const u_char *dat) { const struct pptp_msg_sli *ptr = (const struct pptp_msg_sli *)dat; pptp_peer_call_id_print(ndo, ptr->peer_call_id); PRINT_RESERVED_IF_NOT_ZERO_2(ptr->reserved1); ND_PRINT(" SEND_ACCM(0x%08x)", GET_BE_U_4(ptr->send_accm)); ND_PRINT(" RECV_ACCM(0x%08x)", GET_BE_U_4(ptr->recv_accm)); } void pptp_print(netdissect_options *ndo, const u_char *dat) { const struct pptp_hdr *hdr; uint32_t mc; uint16_t ctrl_msg_type; ndo->ndo_protocol = "pptp"; ND_PRINT(": "); nd_print_protocol(ndo); hdr = (const struct pptp_hdr *)dat; if (ndo->ndo_vflag) { ND_PRINT(" Length=%u", GET_BE_U_2(hdr->length)); } if (ndo->ndo_vflag) { switch(GET_BE_U_2(hdr->msg_type)) { case PPTP_MSG_TYPE_CTRL: ND_PRINT(" CTRL-MSG"); break; case PPTP_MSG_TYPE_MGMT: ND_PRINT(" MGMT-MSG"); break; default: ND_PRINT(" UNKNOWN-MSG-TYPE"); break; } } mc = GET_BE_U_4(hdr->magic_cookie); if (mc != PPTP_MAGIC_COOKIE) { ND_PRINT(" UNEXPECTED Magic-Cookie!!(%08x)", mc); } if (ndo->ndo_vflag || mc != PPTP_MAGIC_COOKIE) { ND_PRINT(" Magic-Cookie=%08x", mc); } ctrl_msg_type = GET_BE_U_2(hdr->ctrl_msg_type); if (ctrl_msg_type < PPTP_MAX_MSGTYPE_INDEX) { ND_PRINT(" CTRL_MSGTYPE=%s", pptp_message_type_string[ctrl_msg_type]); } else { ND_PRINT(" UNKNOWN_CTRL_MSGTYPE(%u)", ctrl_msg_type); } PRINT_RESERVED_IF_NOT_ZERO_2(hdr->reserved0); dat += 12; switch(ctrl_msg_type) { case PPTP_CTRL_MSG_TYPE_SCCRQ: pptp_sccrq_print(ndo, dat); break; case PPTP_CTRL_MSG_TYPE_SCCRP: pptp_sccrp_print(ndo, dat); break; case PPTP_CTRL_MSG_TYPE_StopCCRQ: pptp_stopccrq_print(ndo, dat); break; case PPTP_CTRL_MSG_TYPE_StopCCRP: pptp_stopccrp_print(ndo, dat); break; case PPTP_CTRL_MSG_TYPE_ECHORQ: pptp_echorq_print(ndo, dat); break; case PPTP_CTRL_MSG_TYPE_ECHORP: pptp_echorp_print(ndo, dat); break; case PPTP_CTRL_MSG_TYPE_OCRQ: pptp_ocrq_print(ndo, dat); break; case PPTP_CTRL_MSG_TYPE_OCRP: pptp_ocrp_print(ndo, dat); break; case PPTP_CTRL_MSG_TYPE_ICRQ: pptp_icrq_print(ndo, dat); break; case PPTP_CTRL_MSG_TYPE_ICRP: pptp_icrp_print(ndo, dat); break; case PPTP_CTRL_MSG_TYPE_ICCN: pptp_iccn_print(ndo, dat); break; case PPTP_CTRL_MSG_TYPE_CCRQ: pptp_ccrq_print(ndo, dat); break; case PPTP_CTRL_MSG_TYPE_CDN: pptp_cdn_print(ndo, dat); break; case PPTP_CTRL_MSG_TYPE_WEN: pptp_wen_print(ndo, dat); break; case PPTP_CTRL_MSG_TYPE_SLI: pptp_sli_print(ndo, dat); break; default: /* do nothing */ break; } } tcpdump-4.99.1/print-unsupported.c0000644000026300017510000000207414057477727015332 0ustar mcrmcr/* * Copyright (c) 2020 The TCPDUMP project * 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, and (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. * 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. */ /* \summary: unsupported link-layer protocols printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" void unsupported_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { ndo->ndo_protocol = "unsupported"; nd_print_protocol_caps(ndo); hex_and_ascii_print(ndo, "\n\t", p, h->caplen); } tcpdump-4.99.1/send-ack.awk0000644000026300017510000000307614057477727013640 0ustar mcrmcrBEGIN { # we need the number of bytes in a packet to do the output # in packet numbers rather than byte numbers. if (packetsize <= 0) packetsize = 512 expectNext = 1 lastwin = -1 } { # convert tcp trace to send/ack form. n = split ($1,t,":") tim = t[1]*3600 + t[2]*60 + t[3] if (NR <= 1) { tzero = tim ltim = tim OFS = "\t" } if ($6 != "ack") { # we have a data packet record: # ignore guys with syn, fin or reset 'cause we # can't handle their sequence numbers. Try to # detect and add a flag character for 'anomalies': # * -> re-sent packet # - -> packet after hole (missing packet(s)) # # -> odd size packet if ($5 !~ /[SFR]/) { i = index($6,":") j = index($6,"(") strtSeq = substr($6,1,i-1) endSeq = substr($6,i+1,j-i-1) len = endSeq - strtSeq id = endSeq if (! timeOf[id]) timeOf[id] = tim if (endSeq - expectNext < 0) flag = "*" else { if (strtSeq - expectNext > 0) flag = "-" else if (len != packetsize) flag = "#" else flag = " " expectNext = endSeq } printf "%7.2f\t%7.2f\t%s send %s %d", tim-tzero, tim-ltim,\ flag, $5, strtSeq if (++timesSent[id] > 1) printf " (%.2f) [%d]", tim - timeOf[id], timesSent[id] if (len != packetsize) printf " <%d>", len } } else { id = $7 printf "%7.2f\t%7.2f\t%s ack %s %d", tim-tzero, tim-ltim,\ flag, $5, id if ($9 != lastwin) { printf " win %d", $9 lastwin = $9 } printf " (%.2f)", tim - timeOf[id] if (++timesAcked[id] > 1) printf " [%d]", timesAcked[id] } printf "\n" ltim = tim } tcpdump-4.99.1/print-olsr.c0000644000026300017510000005646514057477734013734 0ustar mcrmcr/* * Copyright (c) 1998-2007 The TCPDUMP project * Copyright (c) 2009 Florian Forster * * 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, and (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. * 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. * * Original code by Hannes Gredler * IPv6 additions by Florian Forster */ /* \summary: Optimized Link State Routing Protocol (OLSR) printer */ /* specification: RFC 3626 */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" #include "addrtoname.h" #include "extract.h" /* * RFC 3626 common header * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Packet Length | Packet Sequence Number | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Message Type | Vtime | Message Size | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Originator Address | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Time To Live | Hop Count | Message Sequence Number | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | * : MESSAGE : * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Message Type | Vtime | Message Size | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Originator Address | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Time To Live | Hop Count | Message Sequence Number | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | * : MESSAGE : * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * : : */ struct olsr_common { nd_uint16_t packet_len; nd_uint16_t packet_seq; }; #define OLSR_HELLO_MSG 1 /* rfc3626 */ #define OLSR_TC_MSG 2 /* rfc3626 */ #define OLSR_MID_MSG 3 /* rfc3626 */ #define OLSR_HNA_MSG 4 /* rfc3626 */ #define OLSR_POWERINFO_MSG 128 #define OLSR_NAMESERVICE_MSG 130 #define OLSR_HELLO_LQ_MSG 201 /* LQ extensions olsr.org */ #define OLSR_TC_LQ_MSG 202 /* LQ extensions olsr.org */ static const struct tok olsr_msg_values[] = { { OLSR_HELLO_MSG, "Hello" }, { OLSR_TC_MSG, "TC" }, { OLSR_MID_MSG, "MID" }, { OLSR_HNA_MSG, "HNA" }, { OLSR_POWERINFO_MSG, "Powerinfo" }, { OLSR_NAMESERVICE_MSG, "Nameservice" }, { OLSR_HELLO_LQ_MSG, "Hello-LQ" }, { OLSR_TC_LQ_MSG, "TC-LQ" }, { 0, NULL} }; struct olsr_msg4 { nd_uint8_t msg_type; nd_uint8_t vtime; nd_uint16_t msg_len; nd_ipv4 originator; nd_uint8_t ttl; nd_uint8_t hopcount; nd_uint16_t msg_seq; }; struct olsr_msg6 { nd_uint8_t msg_type; nd_uint8_t vtime; nd_uint16_t msg_len; nd_ipv6 originator; nd_uint8_t ttl; nd_uint8_t hopcount; nd_uint16_t msg_seq; }; struct olsr_hello { nd_byte res[2]; nd_uint8_t htime; nd_uint8_t will; }; struct olsr_hello_link { nd_uint8_t link_code; nd_byte res; nd_uint16_t len; }; struct olsr_tc { nd_uint16_t ans_seq; nd_byte res[2]; }; struct olsr_hna4 { nd_ipv4 network; nd_ipv4 mask; }; struct olsr_hna6 { nd_ipv6 network; nd_ipv6 mask; }; /** gateway HNA flags */ enum gateway_hna_flags { GW_HNA_FLAG_LINKSPEED = 1 << 0, GW_HNA_FLAG_IPV4 = 1 << 1, GW_HNA_FLAG_IPV4_NAT = 1 << 2, GW_HNA_FLAG_IPV6 = 1 << 3, GW_HNA_FLAG_IPV6PREFIX = 1 << 4 }; /** gateway HNA field byte offsets in the netmask field of the HNA */ enum gateway_hna_fields { GW_HNA_PAD = 0, GW_HNA_FLAGS = 1, GW_HNA_UPLINK = 2, GW_HNA_DOWNLINK = 3, GW_HNA_V6PREFIXLEN = 4, GW_HNA_V6PREFIX = 5 }; #define OLSR_EXTRACT_LINK_TYPE(link_code) (link_code & 0x3) #define OLSR_EXTRACT_NEIGHBOR_TYPE(link_code) (link_code >> 2) static const struct tok olsr_link_type_values[] = { { 0, "Unspecified" }, { 1, "Asymmetric" }, { 2, "Symmetric" }, { 3, "Lost" }, { 0, NULL} }; static const struct tok olsr_neighbor_type_values[] = { { 0, "Not-Neighbor" }, { 1, "Symmetric" }, { 2, "Symmetric-MPR" }, { 0, NULL} }; struct olsr_lq_neighbor4 { nd_ipv4 neighbor; nd_uint8_t link_quality; nd_uint8_t neighbor_link_quality; nd_byte res[2]; }; struct olsr_lq_neighbor6 { nd_ipv6 neighbor; nd_uint8_t link_quality; nd_uint8_t neighbor_link_quality; nd_byte res[2]; }; #define MAX_SMARTGW_SPEED 320000000 /** * Convert an encoded 1 byte transport value (5 bits mantissa, 3 bits exponent) * to an uplink/downlink speed value * * @param value the encoded 1 byte transport value * @return the uplink/downlink speed value (in kbit/s) */ static uint32_t deserialize_gw_speed(uint8_t value) { uint32_t speed; uint32_t exp; if (!value) { return 0; } if (value == UINT8_MAX) { /* maximum value: also return maximum value */ return MAX_SMARTGW_SPEED; } speed = (value >> 3) + 1; exp = value & 7; while (exp != 0) { speed *= 10; exp--; } return speed; } /* * macro to convert the 8-bit mantissa/exponent to a double float * taken from olsr.org. */ #define VTIME_SCALE_FACTOR 0.0625 #define ME_TO_DOUBLE(me) \ (double)(VTIME_SCALE_FACTOR*(1+(double)(me>>4)/16)*(double)(1<<(me&0x0F))) /* * print a neighbor list with LQ extensions. */ static int olsr_print_lq_neighbor4(netdissect_options *ndo, const u_char *msg_data, u_int hello_len) { const struct olsr_lq_neighbor4 *lq_neighbor; while (hello_len >= sizeof(struct olsr_lq_neighbor4)) { lq_neighbor = (const struct olsr_lq_neighbor4 *)msg_data; ND_TCHECK_SIZE(lq_neighbor); ND_PRINT("\n\t neighbor %s, link-quality %.2f%%" ", neighbor-link-quality %.2f%%", GET_IPADDR_STRING(lq_neighbor->neighbor), ((double) GET_U_1(lq_neighbor->link_quality)/2.55), ((double) GET_U_1(lq_neighbor->neighbor_link_quality)/2.55)); msg_data += sizeof(struct olsr_lq_neighbor4); hello_len -= sizeof(struct olsr_lq_neighbor4); } return (0); trunc: return -1; } static int olsr_print_lq_neighbor6(netdissect_options *ndo, const u_char *msg_data, u_int hello_len) { const struct olsr_lq_neighbor6 *lq_neighbor; while (hello_len >= sizeof(struct olsr_lq_neighbor6)) { lq_neighbor = (const struct olsr_lq_neighbor6 *)msg_data; ND_TCHECK_SIZE(lq_neighbor); ND_PRINT("\n\t neighbor %s, link-quality %.2f%%" ", neighbor-link-quality %.2f%%", GET_IP6ADDR_STRING(lq_neighbor->neighbor), ((double) GET_U_1(lq_neighbor->link_quality)/2.55), ((double) GET_U_1(lq_neighbor->neighbor_link_quality)/2.55)); msg_data += sizeof(struct olsr_lq_neighbor6); hello_len -= sizeof(struct olsr_lq_neighbor6); } return (0); trunc: return -1; } /* * print a neighbor list. */ static int olsr_print_neighbor(netdissect_options *ndo, const u_char *msg_data, u_int hello_len) { int neighbor; ND_PRINT("\n\t neighbor\n\t\t"); neighbor = 1; while (hello_len >= sizeof(nd_ipv4)) { /* print 4 neighbors per line */ ND_PRINT("%s%s", GET_IPADDR_STRING(msg_data), neighbor % 4 == 0 ? "\n\t\t" : " "); msg_data += sizeof(nd_ipv4); hello_len -= sizeof(nd_ipv4); } return (0); } void olsr_print(netdissect_options *ndo, const u_char *pptr, u_int length, int is_ipv6) { union { const struct olsr_common *common; const struct olsr_msg4 *msg4; const struct olsr_msg6 *msg6; const struct olsr_hello *hello; const struct olsr_hello_link *hello_link; const struct olsr_tc *tc; const struct olsr_hna4 *hna; } ptr; u_int msg_type, msg_len, msg_tlen, hello_len; uint16_t name_entry_type, name_entry_len; u_int name_entry_padding; uint8_t link_type, neighbor_type; const u_char *tptr, *msg_data; ndo->ndo_protocol = "olsr"; tptr = pptr; nd_print_protocol_caps(ndo); ND_PRINT("v%u", (is_ipv6) ? 6 : 4); if (length < sizeof(struct olsr_common)) { goto trunc; } ND_TCHECK_LEN(tptr, sizeof(struct olsr_common)); ptr.common = (const struct olsr_common *)tptr; length = ND_MIN(length, GET_BE_U_2(ptr.common->packet_len)); ND_PRINT(", seq 0x%04x, length %u", GET_BE_U_2(ptr.common->packet_seq), length); tptr += sizeof(struct olsr_common); /* * In non-verbose mode, just print version. */ if (ndo->ndo_vflag < 1) { return; } while (tptr < (pptr+length)) { union { const struct olsr_msg4 *v4; const struct olsr_msg6 *v6; } msgptr; int msg_len_valid = 0; if (is_ipv6) { ND_TCHECK_LEN(tptr, sizeof(struct olsr_msg6)); msgptr.v6 = (const struct olsr_msg6 *) tptr; msg_type = GET_U_1(msgptr.v6->msg_type); msg_len = GET_BE_U_2(msgptr.v6->msg_len); if ((msg_len >= sizeof (struct olsr_msg6)) && (msg_len <= length)) msg_len_valid = 1; /* infinite loop check */ if (msg_type == 0 || msg_len == 0) { return; } ND_PRINT("\n\t%s Message (%#04x), originator %s, ttl %u, hop %u" "\n\t vtime %.3fs, msg-seq 0x%04x, length %u%s", tok2str(olsr_msg_values, "Unknown", msg_type), msg_type, GET_IP6ADDR_STRING(msgptr.v6->originator), GET_U_1(msgptr.v6->ttl), GET_U_1(msgptr.v6->hopcount), ME_TO_DOUBLE(GET_U_1(msgptr.v6->vtime)), GET_BE_U_2(msgptr.v6->msg_seq), msg_len, (msg_len_valid == 0) ? " (invalid)" : ""); if (!msg_len_valid) { return; } msg_tlen = msg_len - sizeof(struct olsr_msg6); msg_data = tptr + sizeof(struct olsr_msg6); } else /* (!is_ipv6) */ { ND_TCHECK_LEN(tptr, sizeof(struct olsr_msg4)); msgptr.v4 = (const struct olsr_msg4 *) tptr; msg_type = GET_U_1(msgptr.v4->msg_type); msg_len = GET_BE_U_2(msgptr.v4->msg_len); if ((msg_len >= sizeof (struct olsr_msg4)) && (msg_len <= length)) msg_len_valid = 1; /* infinite loop check */ if (msg_type == 0 || msg_len == 0) { return; } ND_PRINT("\n\t%s Message (%#04x), originator %s, ttl %u, hop %u" "\n\t vtime %.3fs, msg-seq 0x%04x, length %u%s", tok2str(olsr_msg_values, "Unknown", msg_type), msg_type, GET_IPADDR_STRING(msgptr.v4->originator), GET_U_1(msgptr.v4->ttl), GET_U_1(msgptr.v4->hopcount), ME_TO_DOUBLE(GET_U_1(msgptr.v4->vtime)), GET_BE_U_2(msgptr.v4->msg_seq), msg_len, (msg_len_valid == 0) ? " (invalid)" : ""); if (!msg_len_valid) { return; } msg_tlen = msg_len - sizeof(struct olsr_msg4); msg_data = tptr + sizeof(struct olsr_msg4); } switch (msg_type) { case OLSR_HELLO_MSG: case OLSR_HELLO_LQ_MSG: if (msg_tlen < sizeof(struct olsr_hello)) goto trunc; ND_TCHECK_LEN(msg_data, sizeof(struct olsr_hello)); ptr.hello = (const struct olsr_hello *)msg_data; ND_PRINT("\n\t hello-time %.3fs, MPR willingness %u", ME_TO_DOUBLE(GET_U_1(ptr.hello->htime)), GET_U_1(ptr.hello->will)); msg_data += sizeof(struct olsr_hello); msg_tlen -= sizeof(struct olsr_hello); while (msg_tlen >= sizeof(struct olsr_hello_link)) { int hello_len_valid = 0; /* * link-type. */ ND_TCHECK_LEN(msg_data, sizeof(struct olsr_hello_link)); ptr.hello_link = (const struct olsr_hello_link *)msg_data; hello_len = GET_BE_U_2(ptr.hello_link->len); link_type = OLSR_EXTRACT_LINK_TYPE(GET_U_1(ptr.hello_link->link_code)); neighbor_type = OLSR_EXTRACT_NEIGHBOR_TYPE(GET_U_1(ptr.hello_link->link_code)); if ((hello_len <= msg_tlen) && (hello_len >= sizeof(struct olsr_hello_link))) hello_len_valid = 1; ND_PRINT("\n\t link-type %s, neighbor-type %s, len %u%s", tok2str(olsr_link_type_values, "Unknown", link_type), tok2str(olsr_neighbor_type_values, "Unknown", neighbor_type), hello_len, (hello_len_valid == 0) ? " (invalid)" : ""); if (hello_len_valid == 0) break; msg_data += sizeof(struct olsr_hello_link); msg_tlen -= sizeof(struct olsr_hello_link); hello_len -= sizeof(struct olsr_hello_link); ND_TCHECK_LEN(msg_data, hello_len); if (msg_type == OLSR_HELLO_MSG) { if (olsr_print_neighbor(ndo, msg_data, hello_len) == -1) goto trunc; } else { if (is_ipv6) { if (olsr_print_lq_neighbor6(ndo, msg_data, hello_len) == -1) goto trunc; } else { if (olsr_print_lq_neighbor4(ndo, msg_data, hello_len) == -1) goto trunc; } } msg_data += hello_len; msg_tlen -= hello_len; } break; case OLSR_TC_MSG: case OLSR_TC_LQ_MSG: if (msg_tlen < sizeof(struct olsr_tc)) goto trunc; ND_TCHECK_LEN(msg_data, sizeof(struct olsr_tc)); ptr.tc = (const struct olsr_tc *)msg_data; ND_PRINT("\n\t advertised neighbor seq 0x%04x", GET_BE_U_2(ptr.tc->ans_seq)); msg_data += sizeof(struct olsr_tc); msg_tlen -= sizeof(struct olsr_tc); if (msg_type == OLSR_TC_MSG) { if (olsr_print_neighbor(ndo, msg_data, msg_tlen) == -1) goto trunc; } else { if (is_ipv6) { if (olsr_print_lq_neighbor6(ndo, msg_data, msg_tlen) == -1) goto trunc; } else { if (olsr_print_lq_neighbor4(ndo, msg_data, msg_tlen) == -1) goto trunc; } } break; case OLSR_MID_MSG: { u_int addr_size = (u_int)sizeof(nd_ipv4); if (is_ipv6) addr_size = (u_int)sizeof(nd_ipv6); while (msg_tlen >= addr_size) { ND_TCHECK_LEN(msg_data, addr_size); ND_PRINT("\n\t interface address %s", is_ipv6 ? GET_IP6ADDR_STRING(msg_data) : GET_IPADDR_STRING(msg_data)); msg_data += addr_size; msg_tlen -= addr_size; } break; } case OLSR_HNA_MSG: if (is_ipv6) { int i = 0; ND_PRINT("\n\t Advertised networks (total %u)", (unsigned int) (msg_tlen / sizeof(struct olsr_hna6))); while (msg_tlen >= sizeof(struct olsr_hna6)) { const struct olsr_hna6 *hna6; ND_TCHECK_LEN(msg_data, sizeof(struct olsr_hna6)); hna6 = (const struct olsr_hna6 *)msg_data; ND_PRINT("\n\t #%i: %s/%u", i, GET_IP6ADDR_STRING(hna6->network), mask62plen (hna6->mask)); msg_data += sizeof(struct olsr_hna6); msg_tlen -= sizeof(struct olsr_hna6); } } else { int col = 0; ND_PRINT("\n\t Advertised networks (total %u)", (unsigned int) (msg_tlen / sizeof(struct olsr_hna4))); while (msg_tlen >= sizeof(struct olsr_hna4)) { ND_TCHECK_LEN(msg_data, sizeof(struct olsr_hna4)); ptr.hna = (const struct olsr_hna4 *)msg_data; /* print 4 prefixes per line */ if (!ptr.hna->network[0] && !ptr.hna->network[1] && !ptr.hna->network[2] && !ptr.hna->network[3] && !ptr.hna->mask[GW_HNA_PAD] && ptr.hna->mask[GW_HNA_FLAGS]) { /* smart gateway */ ND_PRINT("%sSmart-Gateway:%s%s%s%s%s %u/%u", col == 0 ? "\n\t " : ", ", /* indent */ /* sgw */ /* LINKSPEED */ (ptr.hna->mask[GW_HNA_FLAGS] & GW_HNA_FLAG_LINKSPEED) ? " LINKSPEED" : "", /* IPV4 */ (ptr.hna->mask[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV4) ? " IPV4" : "", /* IPV4-NAT */ (ptr.hna->mask[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV4_NAT) ? " IPV4-NAT" : "", /* IPV6 */ (ptr.hna->mask[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV6) ? " IPV6" : "", /* IPv6PREFIX */ (ptr.hna->mask[GW_HNA_FLAGS] & GW_HNA_FLAG_IPV6PREFIX) ? " IPv6-PREFIX" : "", /* uplink */ (ptr.hna->mask[GW_HNA_FLAGS] & GW_HNA_FLAG_LINKSPEED) ? deserialize_gw_speed(ptr.hna->mask[GW_HNA_UPLINK]) : 0, /* downlink */ (ptr.hna->mask[GW_HNA_FLAGS] & GW_HNA_FLAG_LINKSPEED) ? deserialize_gw_speed(ptr.hna->mask[GW_HNA_DOWNLINK]) : 0 ); } else { /* normal route */ ND_PRINT("%s%s/%u", col == 0 ? "\n\t " : ", ", GET_IPADDR_STRING(ptr.hna->network), mask2plen(GET_BE_U_4(ptr.hna->mask))); } msg_data += sizeof(struct olsr_hna4); msg_tlen -= sizeof(struct olsr_hna4); col = (col + 1) % 4; } } break; case OLSR_NAMESERVICE_MSG: { u_int name_entries; u_int addr_size; int name_entries_valid; u_int i; if (msg_tlen < 4) goto trunc; name_entries = GET_BE_U_2(msg_data + 2); addr_size = 4; if (is_ipv6) addr_size = 16; name_entries_valid = 0; if ((name_entries > 0) && ((name_entries * (4 + addr_size)) <= msg_tlen)) name_entries_valid = 1; ND_PRINT("\n\t Version %u, Entries %u%s", GET_BE_U_2(msg_data), name_entries, (name_entries_valid == 0) ? " (invalid)" : ""); if (name_entries_valid == 0) break; msg_data += 4; msg_tlen -= 4; for (i = 0; i < name_entries; i++) { int name_entry_len_valid = 0; if (msg_tlen < 4) break; name_entry_type = GET_BE_U_2(msg_data); name_entry_len = GET_BE_U_2(msg_data + 2); msg_data += 4; msg_tlen -= 4; if ((name_entry_len > 0) && ((addr_size + name_entry_len) <= msg_tlen)) name_entry_len_valid = 1; ND_PRINT("\n\t #%u: type %#06x, length %u%s", (unsigned int) i, name_entry_type, name_entry_len, (name_entry_len_valid == 0) ? " (invalid)" : ""); if (name_entry_len_valid == 0) break; /* 32-bit alignment */ name_entry_padding = 0; if (name_entry_len%4 != 0) name_entry_padding = 4-(name_entry_len%4); if (msg_tlen < addr_size + name_entry_len + name_entry_padding) goto trunc; ND_TCHECK_LEN(msg_data, addr_size + name_entry_len + name_entry_padding); if (is_ipv6) ND_PRINT(", address %s, name \"", GET_IP6ADDR_STRING(msg_data)); else ND_PRINT(", address %s, name \"", GET_IPADDR_STRING(msg_data)); (void)nd_printn(ndo, msg_data + addr_size, name_entry_len, NULL); ND_PRINT("\""); msg_data += addr_size + name_entry_len + name_entry_padding; msg_tlen -= addr_size + name_entry_len + name_entry_padding; } /* for (i = 0; i < name_entries; i++) */ break; } /* case OLSR_NAMESERVICE_MSG */ /* * FIXME those are the defined messages that lack a decoder * you are welcome to contribute code ;-) */ case OLSR_POWERINFO_MSG: default: print_unknown_data(ndo, msg_data, "\n\t ", msg_tlen); break; } /* switch (msg_type) */ tptr += msg_len; } /* while (tptr < (pptr+length)) */ return; trunc: nd_print_trunc(ndo); } tcpdump-4.99.1/print-bt.c0000644000026300017510000000453314057477727013351 0ustar mcrmcr/* * Copyright (c) 2007 * paolo.abeni@email.it 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 Paolo Abeni.'' * The name of author may not 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. */ /* \summary: Bluetooth printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "extract.h" #ifdef DLT_BLUETOOTH_HCI_H4_WITH_PHDR /* * Header prepended by libpcap to each bluetooth h4 frame; * the direction field is in network byte order. */ typedef struct _bluetooth_h4_header { nd_uint32_t direction; /* if first bit is set direction is incoming */ } bluetooth_h4_header; #define BT_HDRLEN sizeof(bluetooth_h4_header) /* * This is the top level routine of the printer. 'p' points * to the bluetooth header of the packet, 'h->ts' is the timestamp, * 'h->len' is the length of the packet off the wire, and 'h->caplen' * is the number of bytes actually captured. */ void bt_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { u_int length = h->len; u_int caplen = h->caplen; const bluetooth_h4_header* hdr = (const bluetooth_h4_header*)p; ndo->ndo_protocol = "bluetooth"; nd_print_protocol(ndo); ND_TCHECK_LEN(p, BT_HDRLEN); ndo->ndo_ll_hdr_len += BT_HDRLEN; caplen -= BT_HDRLEN; length -= BT_HDRLEN; p += BT_HDRLEN; if (ndo->ndo_eflag) ND_PRINT(", hci length %u, direction %s", length, (GET_BE_U_4(hdr->direction)&0x1) ? "in" : "out"); if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); } #endif tcpdump-4.99.1/print-openflow.c0000644000026300017510000001650114057477727014573 0ustar mcrmcr/* * This module implements printing of the very basic (version-independent) * OpenFlow header and iteration over OpenFlow messages. It is intended for * dispatching of version-specific OpenFlow message decoding. * * * Copyright (c) 2013 The TCPDUMP project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* \summary: version-independent OpenFlow printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "extract.h" #include "openflow.h" #include "oui.h" static const struct tok ofver_str[] = { { OF_VER_1_0, "1.0" }, { OF_VER_1_1, "1.1" }, { OF_VER_1_2, "1.2" }, { OF_VER_1_3, "1.3" }, { OF_VER_1_4, "1.4" }, { OF_VER_1_5, "1.5" }, { 0, NULL } }; const struct tok onf_exp_str[] = { { ONF_EXP_ONF, "ONF Extensions" }, { ONF_EXP_BUTE, "Budapest University of Technology and Economics" }, { ONF_EXP_NOVIFLOW, "NoviFlow" }, { ONF_EXP_L3, "L3+ Extensions, Vendor Neutral" }, { ONF_EXP_L4L7, "L4-L7 Extensions" }, { ONF_EXP_WMOB, "Wireless and Mobility Extensions" }, { ONF_EXP_FABS, "Forwarding Abstractions Extensions" }, { ONF_EXP_OTRANS, "Optical Transport Extensions" }, { ONF_EXP_NBLNCTU, "Network Benchmarking Lab, NCTU" }, { ONF_EXP_MPCE, "Mobile Packet Core Extensions" }, { ONF_EXP_MPLSTPSPTN, "MPLS-TP OpenFlow Extensions for SPTN" }, { 0, NULL } }; const char * of_vendor_name(const uint32_t vendor) { const struct tok *table = (vendor & 0xff000000) == 0 ? oui_values : onf_exp_str; return tok2str(table, "unknown", vendor); } void of_bitmap_print(netdissect_options *ndo, const struct tok *t, const uint32_t v, const uint32_t u) { /* Assigned bits? */ if (v & ~u) ND_PRINT(" (%s)", bittok2str(t, "", v)); /* Unassigned bits? */ if (v & u) ND_PRINT(" (bogus)"); } void of_data_print(netdissect_options *ndo, const u_char *cp, const u_int len) { if (len == 0) return; /* data */ ND_PRINT("\n\t data (%u octets)", len); if (ndo->ndo_vflag >= 2) hex_and_ascii_print(ndo, "\n\t ", cp, len); else ND_TCHECK_LEN(cp, len); } static void of_message_print(netdissect_options *ndo, const u_char *cp, uint16_t len, const struct of_msgtypeinfo *mti) { /* * Here "cp" and "len" stand for the message part beyond the common * OpenFlow 1.0 header, if any. * * Most message types are longer than just the header, and the length * constraints may be complex. When possible, validate the constraint * completely here (REQ_FIXLEN), otherwise check that the message is * long enough to begin the decoding (REQ_MINLEN) and have the * type-specific function do any remaining validation. */ if (!mti) goto tcheck_remainder; if ((mti->req_what == REQ_FIXLEN && len != mti->req_value) || (mti->req_what == REQ_MINLEN && len < mti->req_value)) goto invalid; if (!ndo->ndo_vflag || !mti->decoder) goto tcheck_remainder; mti->decoder(ndo, cp, len); return; invalid: nd_print_invalid(ndo); tcheck_remainder: ND_TCHECK_LEN(cp, len); } /* Print a TCP segment worth of OpenFlow messages presuming the segment begins * on a message boundary. */ void openflow_print(netdissect_options *ndo, const u_char *cp, u_int len) { ndo->ndo_protocol = "openflow"; ND_PRINT(": OpenFlow"); while (len) { /* Print a single OpenFlow message. */ uint8_t version, type; uint16_t length; const struct of_msgtypeinfo *mti; /* version */ version = GET_U_1(cp); OF_FWD(1); ND_PRINT("\n\tversion %s", tok2str(ofver_str, "unknown (0x%02x)", version)); /* type */ if (len < 1) goto partial_header; type = GET_U_1(cp); OF_FWD(1); mti = version == OF_VER_1_0 ? of10_identify_msgtype(type) : version == OF_VER_1_3 ? of13_identify_msgtype(type) : NULL; if (mti && mti->name) ND_PRINT(", type %s", mti->name); else ND_PRINT(", type unknown (0x%02x)", type); /* length */ if (len < 2) goto partial_header; length = GET_BE_U_2(cp); OF_FWD(2); ND_PRINT(", length %u%s", length, length < OF_HEADER_FIXLEN ? " (too short!)" : ""); /* xid */ if (len < 4) goto partial_header; ND_PRINT(", xid 0x%08x", GET_BE_U_4(cp)); OF_FWD(4); /* * When a TCP packet can contain several protocol messages, * and at the same time a protocol message can span several * TCP packets, decoding an incomplete message at the end of * a TCP packet requires attention to detail in this loop. * * Message length includes the header length and a message * always includes the basic header. A message length underrun * fails decoding of the rest of the current packet. At the * same time, try decoding as much of the current message as * possible even when it does not end within the current TCP * segment. * * Specifically, to try to process the message body in this * iteration do NOT require the header "length" to be small * enough for the full declared OpenFlow message to fit into * the remainder of the declared TCP segment, same as the full * declared TCP segment is not required to fit into the * captured packet buffer. * * But DO require the same at the end of this iteration to * decrement "len" and to proceed to the next iteration. * (Ideally the declared TCP payload end will be at or after * the captured packet buffer end, but stay safe even when * that's somehow not the case.) */ if (length < OF_HEADER_FIXLEN) goto invalid; of_message_print(ndo, cp, length - OF_HEADER_FIXLEN, mti); if (length - OF_HEADER_FIXLEN > len) break; OF_FWD(length - OF_HEADER_FIXLEN); } /* while (len) */ return; partial_header: ND_PRINT(" (end of TCP payload)"); ND_TCHECK_LEN(cp, len); return; invalid: /* fail the current packet */ nd_print_invalid(ndo); ND_TCHECK_LEN(cp, len); } tcpdump-4.99.1/appletalk.h0000644000026300017510000001024514057477734013567 0ustar mcrmcr/* * Copyright (c) 1988, 1989, 1990, 1993, 1994, 1995, 1996 * 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. * * AppleTalk protocol formats (courtesy Bill Croft of Stanford/SUMEX). */ struct LAP { nd_uint8_t dst; nd_uint8_t src; nd_uint8_t type; }; #define lapShortDDP 1 /* short DDP type */ #define lapDDP 2 /* DDP type */ #define lapKLAP 'K' /* Kinetics KLAP type */ /* Datagram Delivery Protocol */ struct atDDP { nd_uint16_t length; nd_uint16_t checksum; nd_uint16_t dstNet; nd_uint16_t srcNet; nd_uint8_t dstNode; nd_uint8_t srcNode; nd_uint8_t dstSkt; nd_uint8_t srcSkt; nd_uint8_t type; }; struct atShortDDP { nd_uint16_t length; nd_uint8_t dstSkt; nd_uint8_t srcSkt; nd_uint8_t type; }; #define ddpMaxWKS 0x7F #define ddpMaxData 586 #define ddpLengthMask 0x3FF #define ddpHopShift 10 #define ddpSize 13 /* size of DDP header (avoid struct padding) */ #define ddpSSize 5 #define ddpWKS 128 /* boundary of DDP well known sockets */ #define ddpRTMP 1 /* RTMP type */ #define ddpRTMPrequest 5 /* RTMP request type */ #define ddpNBP 2 /* NBP type */ #define ddpATP 3 /* ATP type */ #define ddpECHO 4 /* ECHO type */ #define ddpIP 22 /* IP type */ #define ddpARP 23 /* ARP type */ #define ddpEIGRP 88 /* EIGRP over Appletalk */ #define ddpKLAP 0x4b /* Kinetics KLAP type */ /* AppleTalk Transaction Protocol */ struct atATP { nd_uint8_t control; nd_uint8_t bitmap; nd_uint16_t transID; nd_uint32_t userData; }; #define atpReqCode 0x40 #define atpRspCode 0x80 #define atpRelCode 0xC0 #define atpXO 0x20 #define atpEOM 0x10 #define atpSTS 0x08 #define atpFlagMask 0x3F #define atpControlMask 0xF8 #define atpMaxNum 8 #define atpMaxData 578 /* AppleTalk Echo Protocol */ struct atEcho { nd_uint8_t echoFunction; nd_uint8_t echoData[1]; /* Should be [], C99-style */ }; #define echoSkt 4 /* the echoer socket */ #define echoSize 1 /* size of echo header */ #define echoRequest 1 /* echo request */ #define echoReply 2 /* echo request */ /* Name Binding Protocol */ struct atNBP { nd_uint8_t control; nd_uint8_t id; }; struct atNBPtuple { nd_uint16_t net; nd_uint8_t node; nd_uint8_t skt; nd_uint8_t enumerator; }; #define nbpBrRq 0x10 #define nbpLkUp 0x20 #define nbpLkUpReply 0x30 #define nbpNIS 2 #define nbpTupleMax 15 #define nbpHeaderSize 2 #define nbpTupleSize 5 #define nbpSkt 2 /* NIS */ /* Routing Table Maint. Protocol */ #define rtmpSkt 1 /* number of RTMP socket */ #define rtmpSize 4 /* minimum size */ #define rtmpTupleSize 3 /* Zone Information Protocol */ struct zipHeader { nd_uint8_t command; nd_uint8_t netcount; }; #define zipHeaderSize 2 #define zipQuery 1 #define zipReply 2 #define zipTakedown 3 #define zipBringup 4 #define ddpZIP 6 #define zipSkt 6 #define GetMyZone 7 #define GetZoneList 8 /* * UDP port range used for ddp-in-udp encapsulation is 16512-16639 * for client sockets (128-255) and 200-327 for server sockets * (0-127). We also try to recognize the pre-April 88 server * socket range of 768-895. */ #define atalk_port(p) \ (((unsigned)((p) - 16512) < 128) || \ ((unsigned)((p) - 200) < 128) || \ ((unsigned)((p) - 768) < 128)) tcpdump-4.99.1/print-hsrp.c0000644000026300017510000001100314057477727013706 0ustar mcrmcr/* * Copyright (C) 2001 Julian Cowley * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project 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 BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* \summary: Cisco Hot Standby Router Protocol (HSRP) printer */ /* specification: RFC 2281 for version 1 */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" #include "addrtoname.h" #include "extract.h" /* HSRP op code types. */ static const char *op_code_str[] = { "hello", "coup", "resign" }; /* HSRP states and associated names. */ static const struct tok states[] = { { 0, "initial" }, { 1, "learn" }, { 2, "listen" }, { 4, "speak" }, { 8, "standby" }, { 16, "active" }, { 0, NULL } }; /* * RFC 2281: * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Version | Op Code | State | Hellotime | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Holdtime | Priority | Group | Reserved | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Authentication Data | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Authentication Data | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Virtual IP Address | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ #define HSRP_AUTH_SIZE 8 /* HSRP protocol header. */ struct hsrp { nd_uint8_t hsrp_version; nd_uint8_t hsrp_op_code; nd_uint8_t hsrp_state; nd_uint8_t hsrp_hellotime; nd_uint8_t hsrp_holdtime; nd_uint8_t hsrp_priority; nd_uint8_t hsrp_group; nd_uint8_t hsrp_reserved; nd_byte hsrp_authdata[HSRP_AUTH_SIZE]; nd_ipv4 hsrp_virtaddr; }; void hsrp_print(netdissect_options *ndo, const u_char *bp, u_int len) { const struct hsrp *hp = (const struct hsrp *) bp; uint8_t version; ndo->ndo_protocol = "hsrp"; version = GET_U_1(hp->hsrp_version); ND_PRINT("HSRPv%u", version); if (version != 0) return; ND_PRINT("-"); ND_PRINT("%s ", tok2strary(op_code_str, "unknown (%u)", GET_U_1(hp->hsrp_op_code))); ND_PRINT("%u: ", len); ND_PRINT("state=%s ", tok2str(states, "Unknown (%u)", GET_U_1(hp->hsrp_state))); ND_PRINT("group=%u ", GET_U_1(hp->hsrp_group)); if (GET_U_1(hp->hsrp_reserved) != 0) { ND_PRINT("[reserved=%u!] ", GET_U_1(hp->hsrp_reserved)); } ND_PRINT("addr=%s", GET_IPADDR_STRING(hp->hsrp_virtaddr)); if (ndo->ndo_vflag) { ND_PRINT(" hellotime="); unsigned_relts_print(ndo, GET_U_1(hp->hsrp_hellotime)); ND_PRINT(" holdtime="); unsigned_relts_print(ndo, GET_U_1(hp->hsrp_holdtime)); ND_PRINT(" priority=%u", GET_U_1(hp->hsrp_priority)); ND_PRINT(" auth=\""); /* * RFC 2281 Section 5.1 does not specify the encoding of * Authentication Data explicitly, but zero padding can be * inferred from the "recommended default value". */ nd_printjnp(ndo, hp->hsrp_authdata, HSRP_AUTH_SIZE); ND_PRINT("\""); } } tcpdump-4.99.1/print-krb.c0000644000026300017510000001414614057477727013523 0ustar mcrmcr/* * Copyright (c) 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. * * Initial contribution from John Hawkinson (jhawk@mit.edu). */ /* \summary: Kerberos printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" #include "extract.h" /* * Kerberos 4: * * Athena Technical Plan * Section E.2.1 * Kerberos Authentication and Authorization System * by S. P. Miller, B. C. Neuman, J. I. Schiller, and J. H. Saltzer * * https://web.mit.edu/Saltzer/www/publications/athenaplan/e.2.1.pdf * * 7. Appendix I Design Specifications * * Kerberos 5: * * RFC 1510, RFC 2630, etc. */ static const u_char *c_print(netdissect_options *, const u_char *, const u_char *); static const u_char *krb4_print_hdr(netdissect_options *, const u_char *); static void krb4_print(netdissect_options *, const u_char *); #define AUTH_MSG_KDC_REQUEST 1<<1 #define AUTH_MSG_KDC_REPLY 2<<1 #define AUTH_MSG_APPL_REQUEST 3<<1 #define AUTH_MSG_APPL_REQUEST_MUTUAL 4<<1 #define AUTH_MSG_ERR_REPLY 5<<1 #define AUTH_MSG_PRIVATE 6<<1 #define AUTH_MSG_SAFE 7<<1 #define AUTH_MSG_APPL_ERR 8<<1 #define AUTH_MSG_DIE 63<<1 #define KERB_ERR_OK 0 #define KERB_ERR_NAME_EXP 1 #define KERB_ERR_SERVICE_EXP 2 #define KERB_ERR_AUTH_EXP 3 #define KERB_ERR_PKT_VER 4 #define KERB_ERR_NAME_MAST_KEY_VER 5 #define KERB_ERR_SERV_MAST_KEY_VER 6 #define KERB_ERR_BYTE_ORDER 7 #define KERB_ERR_PRINCIPAL_UNKNOWN 8 #define KERB_ERR_PRINCIPAL_NOT_UNIQUE 9 #define KERB_ERR_NULL_KEY 10 struct krb { nd_uint8_t pvno; /* Protocol Version */ nd_uint8_t type; /* Type+B */ }; static const struct tok type2str[] = { { AUTH_MSG_KDC_REQUEST, "KDC_REQUEST" }, { AUTH_MSG_KDC_REPLY, "KDC_REPLY" }, { AUTH_MSG_APPL_REQUEST, "APPL_REQUEST" }, { AUTH_MSG_APPL_REQUEST_MUTUAL, "APPL_REQUEST_MUTUAL" }, { AUTH_MSG_ERR_REPLY, "ERR_REPLY" }, { AUTH_MSG_PRIVATE, "PRIVATE" }, { AUTH_MSG_SAFE, "SAFE" }, { AUTH_MSG_APPL_ERR, "APPL_ERR" }, { AUTH_MSG_DIE, "DIE" }, { 0, NULL } }; static const struct tok kerr2str[] = { { KERB_ERR_OK, "OK" }, { KERB_ERR_NAME_EXP, "NAME_EXP" }, { KERB_ERR_SERVICE_EXP, "SERVICE_EXP" }, { KERB_ERR_AUTH_EXP, "AUTH_EXP" }, { KERB_ERR_PKT_VER, "PKT_VER" }, { KERB_ERR_NAME_MAST_KEY_VER, "NAME_MAST_KEY_VER" }, { KERB_ERR_SERV_MAST_KEY_VER, "SERV_MAST_KEY_VER" }, { KERB_ERR_BYTE_ORDER, "BYTE_ORDER" }, { KERB_ERR_PRINCIPAL_UNKNOWN, "PRINCIPAL_UNKNOWN" }, { KERB_ERR_PRINCIPAL_NOT_UNIQUE,"PRINCIPAL_NOT_UNIQUE" }, { KERB_ERR_NULL_KEY, "NULL_KEY"}, { 0, NULL} }; static const u_char * c_print(netdissect_options *ndo, const u_char *s, const u_char *ep) { u_char c; int flag; flag = 1; while (s < ep) { c = GET_U_1(s); s++; if (c == '\0') { flag = 0; break; } fn_print_char(ndo, c); } if (flag) return NULL; return (s); } static const u_char * krb4_print_hdr(netdissect_options *ndo, const u_char *cp) { cp += 2; #define PRINT if ((cp = c_print(ndo, cp, ndo->ndo_snapend)) == NULL) goto trunc PRINT; ND_PRINT("."); PRINT; ND_PRINT("@"); PRINT; return (cp); trunc: nd_print_trunc(ndo); return (NULL); #undef PRINT } static void krb4_print(netdissect_options *ndo, const u_char *cp) { const struct krb *kp; u_char type; u_short len; #define PRINT if ((cp = c_print(ndo, cp, ndo->ndo_snapend)) == NULL) goto trunc /* True if struct krb is little endian */ #define IS_LENDIAN(kp) ((GET_U_1((kp)->type) & 0x01) != 0) #define KTOHSP(kp, cp) (IS_LENDIAN(kp) ? GET_LE_U_2(cp) : GET_BE_U_2(cp)) kp = (const struct krb *)cp; type = GET_U_1(kp->type) & (0xFF << 1); ND_PRINT(" %s %s: ", IS_LENDIAN(kp) ? "le" : "be", tok2str(type2str, NULL, type)); switch (type) { case AUTH_MSG_KDC_REQUEST: if ((cp = krb4_print_hdr(ndo, cp)) == NULL) return; cp += 4; /* ctime */ ND_PRINT(" %umin ", GET_U_1(cp) * 5); cp++; PRINT; ND_PRINT("."); PRINT; break; case AUTH_MSG_APPL_REQUEST: cp += 2; ND_PRINT("v%u ", GET_U_1(cp)); cp++; PRINT; ND_PRINT(" (%u)", GET_U_1(cp)); cp++; ND_PRINT(" (%u)", GET_U_1(cp)); break; case AUTH_MSG_KDC_REPLY: if ((cp = krb4_print_hdr(ndo, cp)) == NULL) return; cp += 10; /* timestamp + n + exp + kvno */ len = KTOHSP(kp, cp); ND_PRINT(" (%u)", len); break; case AUTH_MSG_ERR_REPLY: if ((cp = krb4_print_hdr(ndo, cp)) == NULL) return; cp += 4; /* timestamp */ ND_PRINT(" %s ", tok2str(kerr2str, NULL, KTOHSP(kp, cp))); cp += 4; PRINT; break; default: ND_PRINT("(unknown)"); break; } return; trunc: nd_print_trunc(ndo); } void krb_print(netdissect_options *ndo, const u_char *dat) { const struct krb *kp; ndo->ndo_protocol = "krb"; kp = (const struct krb *)dat; if (dat >= ndo->ndo_snapend) { nd_print_trunc(ndo); return; } switch (GET_U_1(kp->pvno)) { case 1: case 2: case 3: ND_PRINT(" v%u", GET_U_1(kp->pvno)); break; case 4: ND_PRINT(" v%u", GET_U_1(kp->pvno)); krb4_print(ndo, (const u_char *)kp); break; case 106: case 107: ND_PRINT(" v5"); /* Decode ASN.1 here "someday" */ break; } } tcpdump-4.99.1/INSTALL.txt0000644000026300017510000001221014057477727013304 0ustar mcrmcrIf you have not built libpcap, and your system does not have libpcap installed, install libpcap first. Your system might provide a version of libpcap that can be installed; if so, to compile tcpdump you might need to install a "developer" version of libpcap as well as the "run-time" version. You can also install tcpdump.org's version of libpcap; see the README.md file in this directory for the location. You will need an ANSI C compiler to build tcpdump. The configure script will abort if your compiler is not ANSI compliant. If this happens, use the generally available GNU C compiler (GCC). After libpcap has been built (either install it with "make install" or make sure both the libpcap and tcpdump source trees are in the same directory), run ./configure (a shell script). "configure" will determine your system attributes and generate an appropriate Makefile from Makefile.in. Now build tcpdump by running "make". If everything builds ok, su and type "make install". This will install tcpdump and the manual entry. Any user will be able to use tcpdump to read saved captures. Whether a user will be able to capture traffic depends on the OS and the configuration of the system; see the tcpdump man page for details. DO NOT give untrusted users the ability to capture traffic. If a user can capture traffic, he or she could use utilities such as tcpdump to capture any traffic on your net, including passwords. Note that most systems ship tcpdump, but usually an older version. Remember to remove or rename the installed binary when upgrading. If your system is not one which we have tested tcpdump on, you may have to modify the configure script and Makefile.in. Please send us patches for any modifications you need to make. Please see "README.md" for notes about tested platforms. FILES ----- CHANGES - description of differences between releases CONTRIBUTING - guidelines for contributing CREDITS - people that have helped tcpdump along INSTALL.txt - this file LICENSE - the license under which tcpdump is distributed Makefile.in - compilation rules (input to the configure script) README.md - description of distribution Readme.Win32 - notes on building tcpdump on Win32 systems (with WinPcap) VERSION - version of this release aclocal.m4 - autoconf macros addrtoname.c - address to hostname routines addrtoname.h - address to hostname definitions addrtostr.c - address to printable string routines addrtostr.h - address to printable string definitions ah.h - IPSEC Authentication Header definitions appletalk.h - AppleTalk definitions ascii_strcasecmp.c - locale-independent case-independent string comparison routines atime.awk - TCP ack awk script atm.h - ATM traffic type definitions bpf_dump.c - BPF program printing routines, in case libpcap doesn't have them chdlc.h - Cisco HDLC definitions cpack.c - functions to extract packed data cpack.h - declarations of functions to extract packed data config.guess - autoconf support config.h.in - autoconf input config.sub - autoconf support configure - configure script (run this first) configure.ac - configure script source ethertype.h - Ethernet type value definitions extract.h - alignment definitions gmpls.c - GMPLS definitions gmpls.h - GMPLS declarations install-sh - BSD style install script interface.h - globals, prototypes and definitions ip.h - IP definitions ip6.h - IPv6 definitions ipproto.c - IP protocol type value-to-name table ipproto.h - IP protocol type value definitions l2vpn.c - L2VPN encapsulation value-to-name table l2vpn.h - L2VPN encapsulation definitions lbl/os-*.h - OS-dependent defines and prototypes llc.h - LLC definitions machdep.c - machine dependent routines machdep.h - machine dependent definitions makemib - mib to header script mib.h - mib definitions missing/* - replacements for missing library functions ntp.c - functions to handle ntp structs ntp.h - declarations of functions to handle ntp structs mkdep - construct Makefile dependency list mpls.h - MPLS definitions nameser.h - DNS definitions netdissect.h - definitions and declarations for tcpdump-as-library (under development) nfs.h - Network File System V2 definitions nfsfh.h - Network File System file handle definitions nlpid.c - OSI NLPID value-to-name table nlpid.h - OSI NLPID definitions ospf.h - Open Shortest Path First definitions packetdat.awk - TCP chunk summary awk script parsenfsfh.c - Network File System file parser routines pcap-missing.h - declarations of functions possibly missing from libpcap ppp.h - Point to Point Protocol definitions print.c - Top-level routines for protocol printing print-*.c - The netdissect printers rpc_auth.h - definitions for ONC RPC authentication rpc_msg.h - definitions for ONC RPC messages send-ack.awk - unidirectional tcp send/ack awk script slcompress.h - SLIP/PPP Van Jacobson compression (RFC1144) definitions smb.h - SMB/CIFS definitions smbutil.c - SMB/CIFS utility routines stime.awk - TCP send awk script tcp.h - TCP definitions tcpdump.1 - manual entry tcpdump.c - main program timeval-operations.h - timeval operations macros udp.h - UDP definitions util-print.c - utility routines for protocol printers win32 - headers and routines for building on Win32 systems tcpdump-4.99.1/print-bgp.c0000644000026300017510000032514314057477734013515 0ustar mcrmcr/* * Copyright (C) 1999 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project 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 BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Extensively modified by Hannes Gredler (hannes@gredler.at) for more * complete BGP support. */ /* \summary: Border Gateway Protocol (BGP) printer */ /* specification: RFC 4271 */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include #include #include "netdissect.h" #include "addrtoname.h" #include "extract.h" #include "af.h" #include "l2vpn.h" struct bgp { nd_byte bgp_marker[16]; nd_uint16_t bgp_len; nd_uint8_t bgp_type; }; #define BGP_SIZE 19 /* unaligned */ #define BGP_OPEN 1 #define BGP_UPDATE 2 #define BGP_NOTIFICATION 3 #define BGP_KEEPALIVE 4 #define BGP_ROUTE_REFRESH 5 static const struct tok bgp_msg_values[] = { { BGP_OPEN, "Open"}, { BGP_UPDATE, "Update"}, { BGP_NOTIFICATION, "Notification"}, { BGP_KEEPALIVE, "Keepalive"}, { BGP_ROUTE_REFRESH, "Route Refresh"}, { 0, NULL} }; struct bgp_open { nd_byte bgpo_marker[16]; nd_uint16_t bgpo_len; nd_uint8_t bgpo_type; nd_uint8_t bgpo_version; nd_uint16_t bgpo_myas; nd_uint16_t bgpo_holdtime; nd_uint32_t bgpo_id; nd_uint8_t bgpo_optlen; /* options should follow */ }; #define BGP_OPEN_SIZE 29 /* unaligned */ struct bgp_opt { nd_uint8_t bgpopt_type; nd_uint8_t bgpopt_len; /* variable length */ }; #define BGP_OPT_SIZE 2 /* some compilers may pad to 4 bytes */ #define BGP_CAP_HEADER_SIZE 2 /* some compilers may pad to 4 bytes */ struct bgp_notification { nd_byte bgpn_marker[16]; nd_uint16_t bgpn_len; nd_uint8_t bgpn_type; nd_uint8_t bgpn_major; nd_uint8_t bgpn_minor; }; #define BGP_NOTIFICATION_SIZE 21 /* unaligned */ struct bgp_route_refresh { nd_byte bgp_marker[16]; nd_uint16_t len; nd_uint8_t type; /* No padding after this; afi is, in fact, not aligned */ nd_uint16_t afi; nd_uint8_t res; nd_uint8_t safi; }; #define BGP_ROUTE_REFRESH_SIZE 23 #define bgp_attr_lenlen(flags, p) \ (((flags) & 0x10) ? 2U : 1U) #define bgp_attr_len(flags, p) \ (((flags) & 0x10) ? GET_BE_U_2(p) : GET_U_1(p)) #define BGPTYPE_ORIGIN 1 #define BGPTYPE_AS_PATH 2 #define BGPTYPE_NEXT_HOP 3 #define BGPTYPE_MULTI_EXIT_DISC 4 #define BGPTYPE_LOCAL_PREF 5 #define BGPTYPE_ATOMIC_AGGREGATE 6 #define BGPTYPE_AGGREGATOR 7 #define BGPTYPE_COMMUNITIES 8 /* RFC1997 */ #define BGPTYPE_ORIGINATOR_ID 9 /* RFC4456 */ #define BGPTYPE_CLUSTER_LIST 10 /* RFC4456 */ #define BGPTYPE_DPA 11 /* deprecated, draft-ietf-idr-bgp-dpa */ #define BGPTYPE_ADVERTISERS 12 /* deprecated RFC1863 */ #define BGPTYPE_RCID_PATH 13 /* deprecated RFC1863 */ #define BGPTYPE_MP_REACH_NLRI 14 /* RFC4760 */ #define BGPTYPE_MP_UNREACH_NLRI 15 /* RFC4760 */ #define BGPTYPE_EXTD_COMMUNITIES 16 /* RFC4360 */ #define BGPTYPE_AS4_PATH 17 /* RFC6793 */ #define BGPTYPE_AGGREGATOR4 18 /* RFC6793 */ #define BGPTYPE_PMSI_TUNNEL 22 /* RFC6514 */ #define BGPTYPE_TUNNEL_ENCAP 23 /* RFC5512 */ #define BGPTYPE_TRAFFIC_ENG 24 /* RFC5543 */ #define BGPTYPE_IPV6_EXTD_COMMUNITIES 25 /* RFC5701 */ #define BGPTYPE_AIGP 26 /* RFC7311 */ #define BGPTYPE_PE_DISTINGUISHER_LABEL 27 /* RFC6514 */ #define BGPTYPE_ENTROPY_LABEL 28 /* RFC6790 */ #define BGPTYPE_LARGE_COMMUNITY 32 /* draft-ietf-idr-large-community-05 */ #define BGPTYPE_ATTR_SET 128 /* RFC6368 */ #define BGP_MP_NLRI_MINSIZE 3 /* End of RIB Marker detection */ static const struct tok bgp_attr_values[] = { { BGPTYPE_ORIGIN, "Origin"}, { BGPTYPE_AS_PATH, "AS Path"}, { BGPTYPE_AS4_PATH, "AS4 Path"}, { BGPTYPE_NEXT_HOP, "Next Hop"}, { BGPTYPE_MULTI_EXIT_DISC, "Multi Exit Discriminator"}, { BGPTYPE_LOCAL_PREF, "Local Preference"}, { BGPTYPE_ATOMIC_AGGREGATE, "Atomic Aggregate"}, { BGPTYPE_AGGREGATOR, "Aggregator"}, { BGPTYPE_AGGREGATOR4, "Aggregator4"}, { BGPTYPE_COMMUNITIES, "Community"}, { BGPTYPE_ORIGINATOR_ID, "Originator ID"}, { BGPTYPE_CLUSTER_LIST, "Cluster List"}, { BGPTYPE_DPA, "DPA"}, { BGPTYPE_ADVERTISERS, "Advertisers"}, { BGPTYPE_RCID_PATH, "RCID Path / Cluster ID"}, { BGPTYPE_MP_REACH_NLRI, "Multi-Protocol Reach NLRI"}, { BGPTYPE_MP_UNREACH_NLRI, "Multi-Protocol Unreach NLRI"}, { BGPTYPE_EXTD_COMMUNITIES, "Extended Community"}, { BGPTYPE_PMSI_TUNNEL, "PMSI Tunnel"}, { BGPTYPE_TUNNEL_ENCAP, "Tunnel Encapsulation"}, { BGPTYPE_TRAFFIC_ENG, "Traffic Engineering"}, { BGPTYPE_IPV6_EXTD_COMMUNITIES, "IPv6 Extended Community"}, { BGPTYPE_AIGP, "Accumulated IGP Metric"}, { BGPTYPE_PE_DISTINGUISHER_LABEL, "PE Distinguisher Label"}, { BGPTYPE_ENTROPY_LABEL, "Entropy Label"}, { BGPTYPE_LARGE_COMMUNITY, "Large Community"}, { BGPTYPE_ATTR_SET, "Attribute Set"}, { 255, "Reserved for development"}, { 0, NULL} }; #define BGP_AS_SET 1 #define BGP_AS_SEQUENCE 2 #define BGP_CONFED_AS_SEQUENCE 3 /* draft-ietf-idr-rfc3065bis-01 */ #define BGP_CONFED_AS_SET 4 /* draft-ietf-idr-rfc3065bis-01 */ #define BGP_AS_SEG_TYPE_MIN BGP_AS_SET #define BGP_AS_SEG_TYPE_MAX BGP_CONFED_AS_SET static const struct tok bgp_as_path_segment_open_values[] = { { BGP_AS_SEQUENCE, ""}, { BGP_AS_SET, "{ "}, { BGP_CONFED_AS_SEQUENCE, "( "}, { BGP_CONFED_AS_SET, "({ "}, { 0, NULL} }; static const struct tok bgp_as_path_segment_close_values[] = { { BGP_AS_SEQUENCE, ""}, { BGP_AS_SET, "}"}, { BGP_CONFED_AS_SEQUENCE, ")"}, { BGP_CONFED_AS_SET, "})"}, { 0, NULL} }; #define BGP_OPT_AUTH 1 #define BGP_OPT_CAP 2 static const struct tok bgp_opt_values[] = { { BGP_OPT_AUTH, "Authentication Information"}, { BGP_OPT_CAP, "Capabilities Advertisement"}, { 0, NULL} }; #define BGP_CAPCODE_MP 1 /* RFC2858 */ #define BGP_CAPCODE_RR 2 /* RFC2918 */ #define BGP_CAPCODE_ORF 3 /* RFC5291 */ #define BGP_CAPCODE_MR 4 /* RFC3107 */ #define BGP_CAPCODE_EXT_NH 5 /* RFC5549 */ #define BGP_CAPCODE_ML 8 /* RFC8277 */ #define BGP_CAPCODE_RESTART 64 /* RFC4724 */ #define BGP_CAPCODE_AS_NEW 65 /* RFC6793 */ #define BGP_CAPCODE_DYN_CAP 67 /* draft-ietf-idr-dynamic-cap */ #define BGP_CAPCODE_MULTISESS 68 /* draft-ietf-idr-bgp-multisession */ #define BGP_CAPCODE_ADD_PATH 69 /* RFC7911 */ #define BGP_CAPCODE_ENH_RR 70 /* draft-keyur-bgp-enhanced-route-refresh */ #define BGP_CAPCODE_LLGR 71 /* draft-uttaro-idr-bgp-persistence-05 */ #define BGP_CAPCODE_RR_CISCO 128 static const struct tok bgp_capcode_values[] = { { BGP_CAPCODE_MP, "Multiprotocol Extensions"}, { BGP_CAPCODE_RR, "Route Refresh"}, { BGP_CAPCODE_ORF, "Cooperative Route Filtering"}, { BGP_CAPCODE_MR, "Multiple Routes to a Destination"}, { BGP_CAPCODE_EXT_NH, "Extended Next Hop Encoding"}, { BGP_CAPCODE_ML, "Multiple Labels"}, { BGP_CAPCODE_RESTART, "Graceful Restart"}, { BGP_CAPCODE_AS_NEW, "32-Bit AS Number"}, { BGP_CAPCODE_DYN_CAP, "Dynamic Capability"}, { BGP_CAPCODE_MULTISESS, "Multisession BGP"}, { BGP_CAPCODE_ADD_PATH, "Multiple Paths"}, { BGP_CAPCODE_ENH_RR, "Enhanced Route Refresh"}, { BGP_CAPCODE_LLGR, "Long-lived Graceful Restart"}, { BGP_CAPCODE_RR_CISCO, "Route Refresh (Cisco)"}, { 0, NULL} }; #define BGP_NOTIFY_MAJOR_MSG 1 #define BGP_NOTIFY_MAJOR_OPEN 2 #define BGP_NOTIFY_MAJOR_UPDATE 3 #define BGP_NOTIFY_MAJOR_HOLDTIME 4 #define BGP_NOTIFY_MAJOR_FSM 5 #define BGP_NOTIFY_MAJOR_CEASE 6 #define BGP_NOTIFY_MAJOR_CAP 7 static const struct tok bgp_notify_major_values[] = { { BGP_NOTIFY_MAJOR_MSG, "Message Header Error"}, { BGP_NOTIFY_MAJOR_OPEN, "OPEN Message Error"}, { BGP_NOTIFY_MAJOR_UPDATE, "UPDATE Message Error"}, { BGP_NOTIFY_MAJOR_HOLDTIME,"Hold Timer Expired"}, { BGP_NOTIFY_MAJOR_FSM, "Finite State Machine Error"}, { BGP_NOTIFY_MAJOR_CEASE, "Cease"}, { BGP_NOTIFY_MAJOR_CAP, "Capability Message Error"}, { 0, NULL} }; /* draft-ietf-idr-cease-subcode-02 */ #define BGP_NOTIFY_MINOR_CEASE_MAXPRFX 1 /* draft-ietf-idr-shutdown-07 */ #define BGP_NOTIFY_MINOR_CEASE_SHUT 2 #define BGP_NOTIFY_MINOR_CEASE_RESET 4 #define BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN 128 static const struct tok bgp_notify_minor_cease_values[] = { { BGP_NOTIFY_MINOR_CEASE_MAXPRFX, "Maximum Number of Prefixes Reached"}, { BGP_NOTIFY_MINOR_CEASE_SHUT, "Administrative Shutdown"}, { 3, "Peer Unconfigured"}, { BGP_NOTIFY_MINOR_CEASE_RESET, "Administrative Reset"}, { 5, "Connection Rejected"}, { 6, "Other Configuration Change"}, { 7, "Connection Collision Resolution"}, { 0, NULL} }; static const struct tok bgp_notify_minor_msg_values[] = { { 1, "Connection Not Synchronized"}, { 2, "Bad Message Length"}, { 3, "Bad Message Type"}, { 0, NULL} }; static const struct tok bgp_notify_minor_open_values[] = { { 1, "Unsupported Version Number"}, { 2, "Bad Peer AS"}, { 3, "Bad BGP Identifier"}, { 4, "Unsupported Optional Parameter"}, { 5, "Authentication Failure"}, { 6, "Unacceptable Hold Time"}, { 7, "Capability Message Error"}, { 0, NULL} }; static const struct tok bgp_notify_minor_update_values[] = { { 1, "Malformed Attribute List"}, { 2, "Unrecognized Well-known Attribute"}, { 3, "Missing Well-known Attribute"}, { 4, "Attribute Flags Error"}, { 5, "Attribute Length Error"}, { 6, "Invalid ORIGIN Attribute"}, { 7, "AS Routing Loop"}, { 8, "Invalid NEXT_HOP Attribute"}, { 9, "Optional Attribute Error"}, { 10, "Invalid Network Field"}, { 11, "Malformed AS_PATH"}, { 0, NULL} }; static const struct tok bgp_notify_minor_fsm_values[] = { { 0, "Unspecified Error"}, { 1, "In OpenSent State"}, { 2, "In OpenConfirm State"}, { 3, "In Established State"}, { 0, NULL } }; static const struct tok bgp_notify_minor_cap_values[] = { { 1, "Invalid Action Value" }, { 2, "Invalid Capability Length" }, { 3, "Malformed Capability Value" }, { 4, "Unsupported Capability Code" }, { 0, NULL } }; static const struct tok bgp_origin_values[] = { { 0, "IGP"}, { 1, "EGP"}, { 2, "Incomplete"}, { 0, NULL} }; #define BGP_PMSI_TUNNEL_RSVP_P2MP 1 #define BGP_PMSI_TUNNEL_LDP_P2MP 2 #define BGP_PMSI_TUNNEL_PIM_SSM 3 #define BGP_PMSI_TUNNEL_PIM_SM 4 #define BGP_PMSI_TUNNEL_PIM_BIDIR 5 #define BGP_PMSI_TUNNEL_INGRESS 6 #define BGP_PMSI_TUNNEL_LDP_MP2MP 7 static const struct tok bgp_pmsi_tunnel_values[] = { { BGP_PMSI_TUNNEL_RSVP_P2MP, "RSVP-TE P2MP LSP"}, { BGP_PMSI_TUNNEL_LDP_P2MP, "LDP P2MP LSP"}, { BGP_PMSI_TUNNEL_PIM_SSM, "PIM-SSM Tree"}, { BGP_PMSI_TUNNEL_PIM_SM, "PIM-SM Tree"}, { BGP_PMSI_TUNNEL_PIM_BIDIR, "PIM-Bidir Tree"}, { BGP_PMSI_TUNNEL_INGRESS, "Ingress Replication"}, { BGP_PMSI_TUNNEL_LDP_MP2MP, "LDP MP2MP LSP"}, { 0, NULL} }; static const struct tok bgp_pmsi_flag_values[] = { { 0x01, "Leaf Information required"}, { 0, NULL} }; #define BGP_AIGP_TLV 1 static const struct tok bgp_aigp_values[] = { { BGP_AIGP_TLV, "AIGP"}, { 0, NULL} }; /* Subsequent address family identifier, RFC2283 section 7 */ #define SAFNUM_RES 0 #define SAFNUM_UNICAST 1 #define SAFNUM_MULTICAST 2 #define SAFNUM_UNIMULTICAST 3 /* deprecated now */ /* labeled BGP RFC3107 */ #define SAFNUM_LABUNICAST 4 /* RFC6514 */ #define SAFNUM_MULTICAST_VPN 5 /* draft-nalawade-kapoor-tunnel-safi */ #define SAFNUM_TUNNEL 64 /* RFC4761 */ #define SAFNUM_VPLS 65 /* RFC6037 */ #define SAFNUM_MDT 66 /* RFC7432 */ #define SAFNUM_EVPN 70 /* RFC4364 */ #define SAFNUM_VPNUNICAST 128 /* RFC6513 */ #define SAFNUM_VPNMULTICAST 129 #define SAFNUM_VPNUNIMULTICAST 130 /* deprecated now */ /* RFC4684 */ #define SAFNUM_RT_ROUTING_INFO 132 #define BGP_VPN_RD_LEN 8 static const struct tok bgp_safi_values[] = { { SAFNUM_RES, "Reserved"}, { SAFNUM_UNICAST, "Unicast"}, { SAFNUM_MULTICAST, "Multicast"}, { SAFNUM_UNIMULTICAST, "Unicast+Multicast"}, { SAFNUM_LABUNICAST, "labeled Unicast"}, { SAFNUM_TUNNEL, "Tunnel"}, { SAFNUM_VPLS, "VPLS"}, { SAFNUM_MDT, "MDT"}, { SAFNUM_EVPN, "EVPN"}, { SAFNUM_VPNUNICAST, "labeled VPN Unicast"}, { SAFNUM_VPNMULTICAST, "labeled VPN Multicast"}, { SAFNUM_VPNUNIMULTICAST, "labeled VPN Unicast+Multicast"}, { SAFNUM_RT_ROUTING_INFO, "Route Target Routing Information"}, { SAFNUM_MULTICAST_VPN, "Multicast VPN"}, { 0, NULL } }; /* well-known community */ #define BGP_COMMUNITY_NO_EXPORT 0xffffff01 #define BGP_COMMUNITY_NO_ADVERT 0xffffff02 #define BGP_COMMUNITY_NO_EXPORT_SUBCONFED 0xffffff03 /* Extended community type - RFC 4360 */ #define BGP_EXT_COM_RT_0 0x0002 /* Route Target,Format AS(2bytes):AN(4bytes) */ #define BGP_EXT_COM_RT_1 0x0102 /* Route Target,Format IP address:AN(2bytes) */ #define BGP_EXT_COM_RT_2 0x0202 /* Route Target,Format AN(4bytes):local(2bytes) */ #define BGP_EXT_COM_RO_0 0x0003 /* Route Origin,Format AS(2bytes):AN(4bytes) */ #define BGP_EXT_COM_RO_1 0x0103 /* Route Origin,Format IP address:AN(2bytes) */ #define BGP_EXT_COM_RO_2 0x0203 /* Route Origin,Format AN(4bytes):local(2bytes) */ #define BGP_EXT_COM_LINKBAND 0x4004 /* Link Bandwidth,Format AS(2B):Bandwidth(4B) */ /* rfc2547 bgp-mpls-vpns */ #define BGP_EXT_COM_VPN_ORIGIN 0x0005 /* OSPF Domain ID / VPN of Origin - draft-rosen-vpns-ospf-bgp-mpls */ #define BGP_EXT_COM_VPN_ORIGIN2 0x0105 /* duplicate - keep for backwards compatibility */ #define BGP_EXT_COM_VPN_ORIGIN3 0x0205 /* duplicate - keep for backwards compatibility */ #define BGP_EXT_COM_VPN_ORIGIN4 0x8005 /* duplicate - keep for backwards compatibility */ #define BGP_EXT_COM_OSPF_RTYPE 0x0306 /* OSPF Route Type,Format Area(4B):RouteType(1B):Options(1B) */ #define BGP_EXT_COM_OSPF_RTYPE2 0x8000 /* duplicate - keep for backwards compatibility */ #define BGP_EXT_COM_ENCAP 0x030c /* rfc5512 */ #define BGP_EXT_COM_OSPF_RID 0x0107 /* OSPF Router ID,Format RouterID(4B):Unused(2B) */ #define BGP_EXT_COM_OSPF_RID2 0x8001 /* duplicate - keep for backwards compatibility */ #define BGP_EXT_COM_L2INFO 0x800a /* draft-kompella-ppvpn-l2vpn */ #define BGP_EXT_COM_SOURCE_AS 0x0009 /* RFC-ietf-l3vpn-2547bis-mcast-bgp-08.txt */ #define BGP_EXT_COM_VRF_RT_IMP 0x010b /* RFC-ietf-l3vpn-2547bis-mcast-bgp-08.txt */ #define BGP_EXT_COM_L2VPN_RT_0 0x000a /* L2VPN Identifier,Format AS(2bytes):AN(4bytes) */ #define BGP_EXT_COM_L2VPN_RT_1 0xF10a /* L2VPN Identifier,Format IP address:AN(2bytes) */ /* https://www.cisco.com/en/US/tech/tk436/tk428/technologies_tech_note09186a00801eb09a.shtml */ #define BGP_EXT_COM_EIGRP_GEN 0x8800 #define BGP_EXT_COM_EIGRP_METRIC_AS_DELAY 0x8801 #define BGP_EXT_COM_EIGRP_METRIC_REL_NH_BW 0x8802 #define BGP_EXT_COM_EIGRP_METRIC_LOAD_MTU 0x8803 #define BGP_EXT_COM_EIGRP_EXT_REMAS_REMID 0x8804 #define BGP_EXT_COM_EIGRP_EXT_REMPROTO_REMMETRIC 0x8805 static const struct tok bgp_extd_comm_flag_values[] = { { 0x8000, "vendor-specific"}, { 0x4000, "non-transitive"}, { 0, NULL}, }; static const struct tok bgp_extd_comm_subtype_values[] = { { BGP_EXT_COM_RT_0, "target"}, { BGP_EXT_COM_RT_1, "target"}, { BGP_EXT_COM_RT_2, "target"}, { BGP_EXT_COM_RO_0, "origin"}, { BGP_EXT_COM_RO_1, "origin"}, { BGP_EXT_COM_RO_2, "origin"}, { BGP_EXT_COM_LINKBAND, "link-BW"}, { BGP_EXT_COM_VPN_ORIGIN, "ospf-domain"}, { BGP_EXT_COM_VPN_ORIGIN2, "ospf-domain"}, { BGP_EXT_COM_VPN_ORIGIN3, "ospf-domain"}, { BGP_EXT_COM_VPN_ORIGIN4, "ospf-domain"}, { BGP_EXT_COM_OSPF_RTYPE, "ospf-route-type"}, { BGP_EXT_COM_OSPF_RTYPE2, "ospf-route-type"}, { BGP_EXT_COM_ENCAP, "encapsulation"}, { BGP_EXT_COM_OSPF_RID, "ospf-router-id"}, { BGP_EXT_COM_OSPF_RID2, "ospf-router-id"}, { BGP_EXT_COM_L2INFO, "layer2-info"}, { BGP_EXT_COM_EIGRP_GEN, "eigrp-general-route (flag, tag)" }, { BGP_EXT_COM_EIGRP_METRIC_AS_DELAY, "eigrp-route-metric (AS, delay)" }, { BGP_EXT_COM_EIGRP_METRIC_REL_NH_BW, "eigrp-route-metric (reliability, nexthop, bandwidth)" }, { BGP_EXT_COM_EIGRP_METRIC_LOAD_MTU, "eigrp-route-metric (load, MTU)" }, { BGP_EXT_COM_EIGRP_EXT_REMAS_REMID, "eigrp-external-route (remote-AS, remote-ID)" }, { BGP_EXT_COM_EIGRP_EXT_REMPROTO_REMMETRIC, "eigrp-external-route (remote-proto, remote-metric)" }, { BGP_EXT_COM_SOURCE_AS, "source-AS" }, { BGP_EXT_COM_VRF_RT_IMP, "vrf-route-import"}, { BGP_EXT_COM_L2VPN_RT_0, "l2vpn-id"}, { BGP_EXT_COM_L2VPN_RT_1, "l2vpn-id"}, { 0, NULL}, }; /* RFC RFC5512 BGP Tunnel Encapsulation Attribute Tunnel Types */ #define BGP_ENCAP_TUNNEL_L2TPV3_IP 1 #define BGP_ENCAP_TUNNEL_GRE 2 #define BGP_ENCAP_TUNNEL_TRANSMIT 3 #define BGP_ENCAP_TUNNEL_IPSEC 4 #define BGP_ENCAP_TUNNEL_IP_IPSEC 5 #define BGP_ENCAP_TUNNEL_MPLS_IP 6 #define BGP_ENCAP_TUNNEL_IP_IP 7 #define BGP_ENCAP_TUNNEL_VXLAN 8 #define BGP_ENCAP_TUNNEL_NVGRE 9 #define BGP_ENCAP_TUNNEL_MPLS 10 #define BGP_ENCAP_TUNNEL_MPLS_GRE 11 #define BGP_ENCAP_TUNNEL_VXLAN_GPE 12 #define BGP_ENCAP_TUNNEL_MPLS_UDP 13 #define BGP_ENCAP_TUNNEL_IPV6 14 #define BGP_ENCAP_TUNNEL_SR_TE 15 #define BGP_ENCAP_TUNNEL_BARE 16 #define BGP_ENCAP_TUNNEL_SR 17 static const struct tok bgp_extd_comm_encap_tunnel_values[] = { { BGP_ENCAP_TUNNEL_L2TPV3_IP, "L2TPv3 over IP"}, { BGP_ENCAP_TUNNEL_GRE, "GRE"}, { BGP_ENCAP_TUNNEL_TRANSMIT, "Transmit Tunnel"}, { BGP_ENCAP_TUNNEL_IPSEC, "IPsec"}, { BGP_ENCAP_TUNNEL_IP_IPSEC, "IP in IP with IPsec"}, { BGP_ENCAP_TUNNEL_MPLS_IP, "MPLS in IP with IPsec"}, { BGP_ENCAP_TUNNEL_IP_IP, "IP in IP"}, { BGP_ENCAP_TUNNEL_VXLAN, "VXLAN"}, { BGP_ENCAP_TUNNEL_NVGRE, "NVGRE"}, { BGP_ENCAP_TUNNEL_MPLS, "MPLS"}, { BGP_ENCAP_TUNNEL_MPLS_GRE, "MPLS in GRE"}, { BGP_ENCAP_TUNNEL_VXLAN_GPE, "VXLAN GPE"}, { BGP_ENCAP_TUNNEL_MPLS_UDP, "MPLS in UDP"}, { BGP_ENCAP_TUNNEL_IPV6, "IPv6"}, { BGP_ENCAP_TUNNEL_SR_TE, "SR TE"}, { BGP_ENCAP_TUNNEL_BARE, "Bare"}, { BGP_ENCAP_TUNNEL_SR, "SR"}, { 0, NULL}, }; /* OSPF codes for BGP_EXT_COM_OSPF_RTYPE draft-rosen-vpns-ospf-bgp-mpls */ #define BGP_OSPF_RTYPE_RTR 1 /* OSPF Router LSA */ #define BGP_OSPF_RTYPE_NET 2 /* OSPF Network LSA */ #define BGP_OSPF_RTYPE_SUM 3 /* OSPF Summary LSA */ #define BGP_OSPF_RTYPE_EXT 5 /* OSPF External LSA, note that ASBR doesn't apply to MPLS-VPN */ #define BGP_OSPF_RTYPE_NSSA 7 /* OSPF NSSA External*/ #define BGP_OSPF_RTYPE_SHAM 129 /* OSPF-MPLS-VPN Sham link */ #define BGP_OSPF_RTYPE_METRIC_TYPE 0x1 /* LSB of RTYPE Options Field */ static const struct tok bgp_extd_comm_ospf_rtype_values[] = { { BGP_OSPF_RTYPE_RTR, "Router" }, { BGP_OSPF_RTYPE_NET, "Network" }, { BGP_OSPF_RTYPE_SUM, "Summary" }, { BGP_OSPF_RTYPE_EXT, "External" }, { BGP_OSPF_RTYPE_NSSA,"NSSA External" }, { BGP_OSPF_RTYPE_SHAM,"MPLS-VPN Sham" }, { 0, NULL }, }; /* ADD-PATH Send/Receive field values */ static const struct tok bgp_add_path_recvsend[] = { { 1, "Receive" }, { 2, "Send" }, { 3, "Both" }, { 0, NULL }, }; #define AS_STR_SIZE sizeof("xxxxx.xxxxx") /* * as_printf * * Convert an AS number into a string and return string pointer. * * Depending on bflag is set or not, AS number is converted into ASDOT notation * or plain number notation. * */ static char * as_printf(netdissect_options *ndo, char *str, size_t size, u_int asnum) { if (!ndo->ndo_bflag || asnum <= 0xFFFF) { snprintf(str, size, "%u", asnum); } else { snprintf(str, size, "%u.%u", asnum >> 16, asnum & 0xFFFF); } return str; } #define ITEMCHECK(minlen) if (itemlen < minlen) goto badtlv; int decode_prefix4(netdissect_options *ndo, const u_char *pptr, u_int itemlen, char *buf, size_t buflen) { nd_ipv4 addr; u_int plen, plenbytes; ITEMCHECK(1); plen = GET_U_1(pptr); if (32 < plen) return -1; itemlen -= 1; memset(&addr, 0, sizeof(addr)); plenbytes = (plen + 7) / 8; ITEMCHECK(plenbytes); GET_CPY_BYTES(&addr, pptr + 1, plenbytes); if (plen % 8) { ((u_char *)&addr)[plenbytes - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } snprintf(buf, buflen, "%s/%u", ipaddr_string(ndo, (const u_char *)&addr), plen); return 1 + plenbytes; badtlv: return -2; } static int decode_labeled_prefix4(netdissect_options *ndo, const u_char *pptr, u_int itemlen, char *buf, size_t buflen) { nd_ipv4 addr; u_int plen, plenbytes; /* prefix length and label = 4 bytes */ ND_TCHECK_4(pptr); ITEMCHECK(4); plen = GET_U_1(pptr); /* get prefix length */ /* this is one of the weirdnesses of rfc3107 the label length (actually the label + COS bits) is added to the prefix length; we also do only read out just one label - there is no real application for advertisement of stacked labels in a single BGP message */ if (24 > plen) return -1; plen-=24; /* adjust prefixlen - labellength */ if (32 < plen) return -1; itemlen -= 4; memset(&addr, 0, sizeof(addr)); plenbytes = (plen + 7) / 8; ITEMCHECK(plenbytes); GET_CPY_BYTES(&addr, pptr + 4, plenbytes); if (plen % 8) { ((u_char *)&addr)[plenbytes - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } /* the label may get offsetted by 4 bits so lets shift it right */ snprintf(buf, buflen, "%s/%u, label:%u %s", ipaddr_string(ndo, (const u_char *)&addr), plen, GET_BE_U_3(pptr + 1)>>4, ((GET_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" ); return 4 + plenbytes; trunc: return -2; badtlv: return -3; } /* * bgp_vpn_ip_print * * print an ipv4 or ipv6 address into a buffer dependent on address length. */ static char * bgp_vpn_ip_print(netdissect_options *ndo, const u_char *pptr, u_int addr_length) { /* worst case string is s fully formatted v6 address */ static char addr[sizeof("1234:5678:89ab:cdef:1234:5678:89ab:cdef")]; char *pos = addr; switch(addr_length) { case (sizeof(nd_ipv4) << 3): /* 32 */ snprintf(pos, sizeof(addr), "%s", GET_IPADDR_STRING(pptr)); break; case (sizeof(nd_ipv6) << 3): /* 128 */ snprintf(pos, sizeof(addr), "%s", GET_IP6ADDR_STRING(pptr)); break; default: snprintf(pos, sizeof(addr), "bogus address length %u", addr_length); break; } pos += strlen(pos); *(pos) = '\0'; return (addr); } /* * bgp_vpn_sg_print * * print an multicast s,g entry into a buffer. * the s,g entry is encoded like this. * * +-----------------------------------+ * | Multicast Source Length (1 octet) | * +-----------------------------------+ * | Multicast Source (Variable) | * +-----------------------------------+ * | Multicast Group Length (1 octet) | * +-----------------------------------+ * | Multicast Group (Variable) | * +-----------------------------------+ * * return the number of bytes read from the wire. */ static u_int bgp_vpn_sg_print(netdissect_options *ndo, const u_char *pptr, char *buf, size_t buflen) { uint8_t addr_length; u_int total_length, offset; total_length = 0; /* Source address length, encoded in bits */ addr_length = GET_U_1(pptr); pptr++; /* Source address */ ND_TCHECK_LEN(pptr, (addr_length >> 3)); total_length += (addr_length >> 3) + 1; offset = (u_int)strlen(buf); if (addr_length) { snprintf(buf + offset, buflen - offset, ", Source %s", bgp_vpn_ip_print(ndo, pptr, addr_length)); pptr += (addr_length >> 3); } /* Group address length, encoded in bits */ addr_length = GET_U_1(pptr); pptr++; /* Group address */ ND_TCHECK_LEN(pptr, (addr_length >> 3)); total_length += (addr_length >> 3) + 1; offset = (u_int)strlen(buf); if (addr_length) { snprintf(buf + offset, buflen - offset, ", Group %s", bgp_vpn_ip_print(ndo, pptr, addr_length)); pptr += (addr_length >> 3); } trunc: return (total_length); } /* Print an RFC 4364 Route Distinguisher */ const char * bgp_vpn_rd_print(netdissect_options *ndo, const u_char *pptr) { /* allocate space for the largest possible string */ static char rd[sizeof("xxxxx.xxxxx:xxxxx (xxx.xxx.xxx.xxx:xxxxx)")]; char *pos = rd; /* allocate space for the largest possible string */ char astostr[AS_STR_SIZE]; /* ok lets load the RD format */ switch (GET_BE_U_2(pptr)) { case 0: /* 2-byte-AS:number fmt */ snprintf(pos, sizeof(rd) - (pos - rd), "%u:%u (= %u.%u.%u.%u)", GET_BE_U_2(pptr + 2), GET_BE_U_4(pptr + 4), GET_U_1(pptr + 4), GET_U_1(pptr + 5), GET_U_1(pptr + 6), GET_U_1(pptr + 7)); break; case 1: /* IP-address:AS fmt */ snprintf(pos, sizeof(rd) - (pos - rd), "%u.%u.%u.%u:%u", GET_U_1(pptr + 2), GET_U_1(pptr + 3), GET_U_1(pptr + 4), GET_U_1(pptr + 5), GET_BE_U_2(pptr + 6)); break; case 2: /* 4-byte-AS:number fmt */ snprintf(pos, sizeof(rd) - (pos - rd), "%s:%u (%u.%u.%u.%u:%u)", as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_4(pptr + 2)), GET_BE_U_2(pptr + 6), GET_U_1(pptr + 2), GET_U_1(pptr + 3), GET_U_1(pptr + 4), GET_U_1(pptr + 5), GET_BE_U_2(pptr + 6)); break; default: snprintf(pos, sizeof(rd) - (pos - rd), "unknown RD format"); break; } pos += strlen(pos); *(pos) = '\0'; return (rd); } /* * Print an RFC 4360 Extended Community. */ static void bgp_extended_community_print(netdissect_options *ndo, const u_char *pptr) { union { /* copy buffer for bandwidth values */ float f; uint32_t i; } bw; /* allocate space for the largest possible string */ char astostr[AS_STR_SIZE]; switch (GET_BE_U_2(pptr)) { case BGP_EXT_COM_RT_0: case BGP_EXT_COM_RO_0: case BGP_EXT_COM_L2VPN_RT_0: ND_PRINT("%u:%u (= %s)", GET_BE_U_2(pptr + 2), GET_BE_U_4(pptr + 4), GET_IPADDR_STRING(pptr+4)); break; case BGP_EXT_COM_RT_1: case BGP_EXT_COM_RO_1: case BGP_EXT_COM_L2VPN_RT_1: case BGP_EXT_COM_VRF_RT_IMP: ND_PRINT("%s:%u", GET_IPADDR_STRING(pptr+2), GET_BE_U_2(pptr + 6)); break; case BGP_EXT_COM_RT_2: case BGP_EXT_COM_RO_2: ND_PRINT("%s:%u", as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_4(pptr + 2)), GET_BE_U_2(pptr + 6)); break; case BGP_EXT_COM_LINKBAND: bw.i = GET_BE_U_4(pptr + 2); ND_PRINT("bandwidth: %.3f Mbps", bw.f*8/1000000); break; case BGP_EXT_COM_VPN_ORIGIN: case BGP_EXT_COM_VPN_ORIGIN2: case BGP_EXT_COM_VPN_ORIGIN3: case BGP_EXT_COM_VPN_ORIGIN4: case BGP_EXT_COM_OSPF_RID: case BGP_EXT_COM_OSPF_RID2: ND_PRINT("%s", GET_IPADDR_STRING(pptr+2)); break; case BGP_EXT_COM_OSPF_RTYPE: case BGP_EXT_COM_OSPF_RTYPE2: ND_PRINT("area:%s, router-type:%s, metric-type:%s%s", GET_IPADDR_STRING(pptr+2), tok2str(bgp_extd_comm_ospf_rtype_values, "unknown (0x%02x)", GET_U_1((pptr + 6))), (GET_U_1(pptr + 7) & BGP_OSPF_RTYPE_METRIC_TYPE) ? "E2" : "", ((GET_U_1(pptr + 6) == BGP_OSPF_RTYPE_EXT) || (GET_U_1(pptr + 6) == BGP_OSPF_RTYPE_NSSA)) ? "E1" : ""); break; case BGP_EXT_COM_L2INFO: ND_PRINT("%s Control Flags [0x%02x]:MTU %u", tok2str(l2vpn_encaps_values, "unknown encaps", GET_U_1((pptr + 2))), GET_U_1((pptr + 3)), GET_BE_U_2(pptr + 4)); break; case BGP_EXT_COM_SOURCE_AS: ND_PRINT("AS %u", GET_BE_U_2(pptr + 2)); break; case BGP_EXT_COM_ENCAP: ND_PRINT("Tunnel type: %s", tok2str(bgp_extd_comm_encap_tunnel_values, "unknown encaps", GET_BE_U_2(pptr + 6))); break; default: ND_PRINT("%02x%02x%02x%02x%02x%02x", GET_U_1(pptr + 2), GET_U_1(pptr + 3), GET_U_1(pptr + 4), GET_U_1(pptr + 5), GET_U_1(pptr + 6), GET_U_1(pptr + 7)); break; } } /* * RFC4684 (Section 4)/RFC2858 (Section 4). * RTC membership prefix is structured as follows * [prefix-len] [origin-as] [route-target] * The route-target is encoded as RT ext-comms. * Prefix-len may be 0, 32..96 * * Note that pptr is not packet data - it is * a buffer owned by our caller - therefore GET_* * macros can not be used. */ static char * bgp_rt_prefix_print(netdissect_options *ndo, const u_char *pptr, u_int plen) { /* allocate space for the largest possible string */ char rtc_prefix_in_hex[20] = ""; u_int rtc_prefix_in_hex_len = 0; static char output[61]; /* max response string */ /* allocate space for the largest possible string */ char astostr[AS_STR_SIZE]; uint16_t ec_type = 0; u_int octet_count; u_int i; if (plen == 0) { snprintf(output, sizeof(output), "route-target: 0:0/0"); return (output); } /* hex representation of the prefix */ octet_count = (plen+7)/8; for (i=0; i plen) { ND_PRINT("\n\t (illegal prefix length)"); return -1; } /* With at least "origin AS", possibly with "route target". */ as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_4(pptr + 1)); plen -= 32; /* adjust prefix length */ if (64 < plen) { ND_PRINT("\n\t (illegal prefix length)"); return -1; } /* From now on (plen + 7) / 8 evaluates to { 0, 1, 2, ..., 8 } * and gives the number of octets in the variable-length "route * target" field inside this NLRI "prefix". Look for it. */ memset(&route_target, 0, sizeof(route_target)); num_octets = (plen + 7) / 8; GET_CPY_BYTES(&route_target, pptr + 5, num_octets); /* If mask-len is not on octet boundary, ensure all extra bits are 0 */ if (plen % 8) { ((u_char *)&route_target)[num_octets - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } ND_PRINT("\n\t origin AS: %s, %s", astostr, bgp_rt_prefix_print(ndo, (u_char *)&route_target, plen)); return 5 + num_octets; } static int decode_labeled_vpn_prefix4(netdissect_options *ndo, const u_char *pptr, char *buf, size_t buflen) { nd_ipv4 addr; u_int plen; plen = GET_U_1(pptr); /* get prefix length */ if ((24+64) > plen) return -1; plen -= (24+64); /* adjust prefixlen - labellength - RD len*/ if (32 < plen) return -1; memset(&addr, 0, sizeof(addr)); GET_CPY_BYTES(&addr, pptr + 12, (plen + 7) / 8); if (plen % 8) { ((u_char *)&addr)[(plen + 7) / 8 - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } /* the label may get offsetted by 4 bits so lets shift it right */ snprintf(buf, buflen, "RD: %s, %s/%u, label:%u %s", bgp_vpn_rd_print(ndo, pptr+4), ipaddr_string(ndo, (const u_char *)&addr), plen, GET_BE_U_3(pptr + 1)>>4, ((GET_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" ); return 12 + (plen + 7) / 8; } /* * +-------------------------------+ * | | * | RD:IPv4-address (12 octets) | * | | * +-------------------------------+ * | MDT Group-address (4 octets) | * +-------------------------------+ */ #define MDT_VPN_NLRI_LEN 16 static int decode_mdt_vpn_nlri(netdissect_options *ndo, const u_char *pptr, char *buf, size_t buflen) { const u_char *rd; const u_char *vpn_ip; /* if the NLRI is not predefined length, quit.*/ if (GET_U_1(pptr) != MDT_VPN_NLRI_LEN * 8) return -1; pptr++; /* RD */ ND_TCHECK_8(pptr); rd = pptr; pptr += 8; /* IPv4 address */ vpn_ip = pptr; pptr += sizeof(nd_ipv4); /* MDT Group Address */ snprintf(buf, buflen, "RD: %s, VPN IP Address: %s, MC Group Address: %s", bgp_vpn_rd_print(ndo, rd), GET_IPADDR_STRING(vpn_ip), GET_IPADDR_STRING(pptr)); return MDT_VPN_NLRI_LEN + 1; trunc: return -2; } #define BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI 1 #define BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI 2 #define BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI 3 #define BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF 4 #define BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE 5 #define BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN 6 #define BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN 7 static const struct tok bgp_multicast_vpn_route_type_values[] = { { BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI, "Intra-AS I-PMSI"}, { BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI, "Inter-AS I-PMSI"}, { BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI, "S-PMSI"}, { BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF, "Intra-AS Segment-Leaf"}, { BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE, "Source-Active"}, { BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN, "Shared Tree Join"}, { BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN, "Source Tree Join"}, { 0, NULL} }; static int decode_multicast_vpn(netdissect_options *ndo, const u_char *pptr, char *buf, size_t buflen) { /* allocate space for the largest possible string */ char astostr[AS_STR_SIZE]; uint8_t route_type, route_length; u_int addr_length, sg_length; u_int offset; route_type = GET_U_1(pptr); pptr++; route_length = GET_U_1(pptr); pptr++; snprintf(buf, buflen, "Route-Type: %s (%u), length: %u", tok2str(bgp_multicast_vpn_route_type_values, "Unknown", route_type), route_type, route_length); switch(route_type) { case BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_I_PMSI: ND_TCHECK_LEN(pptr, BGP_VPN_RD_LEN); offset = (u_int)strlen(buf); snprintf(buf + offset, buflen - offset, ", RD: %s, Originator %s", bgp_vpn_rd_print(ndo, pptr), bgp_vpn_ip_print(ndo, pptr + BGP_VPN_RD_LEN, (route_length - BGP_VPN_RD_LEN) << 3)); break; case BGP_MULTICAST_VPN_ROUTE_TYPE_INTER_AS_I_PMSI: ND_TCHECK_LEN(pptr, BGP_VPN_RD_LEN + 4); offset = (u_int)strlen(buf); snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %s", bgp_vpn_rd_print(ndo, pptr), as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_4(pptr + BGP_VPN_RD_LEN))); break; case BGP_MULTICAST_VPN_ROUTE_TYPE_S_PMSI: ND_TCHECK_LEN(pptr, BGP_VPN_RD_LEN); offset = (u_int)strlen(buf); snprintf(buf + offset, buflen - offset, ", RD: %s", bgp_vpn_rd_print(ndo, pptr)); pptr += BGP_VPN_RD_LEN; sg_length = bgp_vpn_sg_print(ndo, pptr, buf, buflen); addr_length = route_length - sg_length; ND_TCHECK_LEN(pptr, addr_length); offset = (u_int)strlen(buf); snprintf(buf + offset, buflen - offset, ", Originator %s", bgp_vpn_ip_print(ndo, pptr, addr_length << 3)); break; case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_ACTIVE: ND_TCHECK_LEN(pptr, BGP_VPN_RD_LEN); offset = (u_int)strlen(buf); snprintf(buf + offset, buflen - offset, ", RD: %s", bgp_vpn_rd_print(ndo, pptr)); pptr += BGP_VPN_RD_LEN; bgp_vpn_sg_print(ndo, pptr, buf, buflen); break; case BGP_MULTICAST_VPN_ROUTE_TYPE_SHARED_TREE_JOIN: /* fall through */ case BGP_MULTICAST_VPN_ROUTE_TYPE_SOURCE_TREE_JOIN: ND_TCHECK_LEN(pptr, BGP_VPN_RD_LEN + 4); offset = (u_int)strlen(buf); snprintf(buf + offset, buflen - offset, ", RD: %s, Source-AS %s", bgp_vpn_rd_print(ndo, pptr), as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_4(pptr + BGP_VPN_RD_LEN))); pptr += BGP_VPN_RD_LEN + 4; bgp_vpn_sg_print(ndo, pptr, buf, buflen); break; /* * no per route-type printing yet. */ case BGP_MULTICAST_VPN_ROUTE_TYPE_INTRA_AS_SEG_LEAF: default: break; } return route_length + 2; trunc: return -2; } /* * As I remember, some versions of systems have an snprintf() that * returns -1 if the buffer would have overflowed. If the return * value is negative, set buflen to 0, to indicate that we've filled * the buffer up. * * If the return value is greater than buflen, that means that * the buffer would have overflowed; again, set buflen to 0 in * that case. */ #define UPDATE_BUF_BUFLEN(buf, buflen, stringlen) \ if (stringlen<0) \ buflen=0; \ else if ((u_int)stringlen>buflen) \ buflen=0; \ else { \ buflen-=stringlen; \ buf+=stringlen; \ } static int decode_labeled_vpn_l2(netdissect_options *ndo, const u_char *pptr, char *buf, size_t buflen) { u_int plen, tlen, tlv_type, tlv_len, ttlv_len; int stringlen; plen = GET_BE_U_2(pptr); tlen = plen; pptr += 2; /* Old and new L2VPN NLRI share AFI/SAFI * -> Assume a 12 Byte-length NLRI is auto-discovery-only * and > 17 as old format. Complain for the middle case */ if (plen == 12) { /* assume AD-only with RD, BGPNH */ ND_TCHECK_LEN(pptr, 12); buf[0] = '\0'; stringlen = snprintf(buf, buflen, "RD: %s, BGPNH: %s", bgp_vpn_rd_print(ndo, pptr), GET_IPADDR_STRING(pptr+8)); UPDATE_BUF_BUFLEN(buf, buflen, stringlen); pptr += 12; tlen -= 12; return plen + 2; } else if (plen > 17) { /* assume old format */ /* RD, ID, LBLKOFF, LBLBASE */ ND_TCHECK_LEN(pptr, 15); buf[0] = '\0'; stringlen = snprintf(buf, buflen, "RD: %s, CE-ID: %u, Label-Block Offset: %u, Label Base %u", bgp_vpn_rd_print(ndo, pptr), GET_BE_U_2(pptr + 8), GET_BE_U_2(pptr + 10), GET_BE_U_3(pptr + 12)>>4); /* the label is offsetted by 4 bits so lets shift it right */ UPDATE_BUF_BUFLEN(buf, buflen, stringlen); pptr += 15; tlen -= 15; /* ok now the variable part - lets read out TLVs*/ while (tlen != 0) { if (tlen < 3) { if (buflen != 0) { stringlen=snprintf(buf,buflen, "\n\t\tran past the end"); UPDATE_BUF_BUFLEN(buf, buflen, stringlen); } return plen + 2; } tlv_type = GET_U_1(pptr); pptr++; tlv_len = GET_BE_U_2(pptr); /* length, in *bits* */ ttlv_len = (tlv_len + 7)/8; /* length, in *bytes* */ pptr += 2; switch(tlv_type) { case 1: if (buflen != 0) { stringlen=snprintf(buf,buflen, "\n\t\tcircuit status vector (%u) length: %u: 0x", tlv_type, tlv_len); UPDATE_BUF_BUFLEN(buf, buflen, stringlen); } while (ttlv_len != 0) { if (tlen < 1) { if (buflen != 0) { stringlen=snprintf(buf,buflen, " (ran past the end)"); UPDATE_BUF_BUFLEN(buf, buflen, stringlen); } return plen + 2; } ND_TCHECK_1(pptr); if (buflen != 0) { stringlen=snprintf(buf,buflen, "%02x", GET_U_1(pptr)); pptr++; UPDATE_BUF_BUFLEN(buf, buflen, stringlen); } ttlv_len--; tlen--; } break; default: if (buflen != 0) { stringlen=snprintf(buf,buflen, "\n\t\tunknown TLV #%u, length: %u", tlv_type, tlv_len); UPDATE_BUF_BUFLEN(buf, buflen, stringlen); } if (tlen < ttlv_len) { if (buflen != 0) { stringlen=snprintf(buf,buflen, " (ran past the end)"); UPDATE_BUF_BUFLEN(buf, buflen, stringlen); } return plen + 2; } tlen -= ttlv_len; break; } } return plen + 2; } else { /* complain bitterly ? */ /* fall through */ goto trunc; } trunc: return -2; } int decode_prefix6(netdissect_options *ndo, const u_char *pd, u_int itemlen, char *buf, size_t buflen) { nd_ipv6 addr; u_int plen, plenbytes; ITEMCHECK(1); plen = GET_U_1(pd); if (128 < plen) return -1; itemlen -= 1; memset(&addr, 0, sizeof(addr)); plenbytes = (plen + 7) / 8; ITEMCHECK(plenbytes); GET_CPY_BYTES(&addr, pd + 1, plenbytes); if (plen % 8) { addr[plenbytes - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } snprintf(buf, buflen, "%s/%u", ip6addr_string(ndo, (const u_char *)&addr), plen); return 1 + plenbytes; badtlv: return -2; } static int decode_labeled_prefix6(netdissect_options *ndo, const u_char *pptr, u_int itemlen, char *buf, size_t buflen) { nd_ipv6 addr; u_int plen, plenbytes; /* prefix length and label = 4 bytes */ ND_TCHECK_4(pptr); ITEMCHECK(4); plen = GET_U_1(pptr); /* get prefix length */ if (24 > plen) return -1; plen -= 24; /* adjust prefixlen - labellength */ if (128 < plen) return -1; itemlen -= 4; memset(&addr, 0, sizeof(addr)); plenbytes = (plen + 7) / 8; GET_CPY_BYTES(&addr, pptr + 4, plenbytes); if (plen % 8) { addr[plenbytes - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } /* the label may get offsetted by 4 bits so lets shift it right */ snprintf(buf, buflen, "%s/%u, label:%u %s", ip6addr_string(ndo, (const u_char *)&addr), plen, GET_BE_U_3(pptr + 1)>>4, ((GET_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" ); return 4 + plenbytes; trunc: return -2; badtlv: return -3; } static int decode_labeled_vpn_prefix6(netdissect_options *ndo, const u_char *pptr, char *buf, size_t buflen) { nd_ipv6 addr; u_int plen; plen = GET_U_1(pptr); /* get prefix length */ if ((24+64) > plen) return -1; plen -= (24+64); /* adjust prefixlen - labellength - RD len*/ if (128 < plen) return -1; memset(&addr, 0, sizeof(addr)); GET_CPY_BYTES(&addr, pptr + 12, (plen + 7) / 8); if (plen % 8) { addr[(plen + 7) / 8 - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } /* the label may get offsetted by 4 bits so lets shift it right */ snprintf(buf, buflen, "RD: %s, %s/%u, label:%u %s", bgp_vpn_rd_print(ndo, pptr+4), ip6addr_string(ndo, (const u_char *)&addr), plen, GET_BE_U_3(pptr + 1)>>4, ((GET_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" ); return 12 + (plen + 7) / 8; } static int decode_clnp_prefix(netdissect_options *ndo, const u_char *pptr, char *buf, size_t buflen) { uint8_t addr[19]; u_int plen; plen = GET_U_1(pptr); /* get prefix length */ if (152 < plen) return -1; memset(&addr, 0, sizeof(addr)); GET_CPY_BYTES(&addr, pptr + 4, (plen + 7) / 8); if (plen % 8) { addr[(plen + 7) / 8 - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } /* Cannot use GET_ISONSAP_STRING (not packet buffer pointer) */ snprintf(buf, buflen, "%s/%u", isonsap_string(ndo, addr,(plen + 7) / 8), plen); return 1 + (plen + 7) / 8; } static int decode_labeled_vpn_clnp_prefix(netdissect_options *ndo, const u_char *pptr, char *buf, size_t buflen) { uint8_t addr[19]; u_int plen; plen = GET_U_1(pptr); /* get prefix length */ if ((24+64) > plen) return -1; plen -= (24+64); /* adjust prefixlen - labellength - RD len*/ if (152 < plen) return -1; memset(&addr, 0, sizeof(addr)); GET_CPY_BYTES(&addr, pptr + 12, (plen + 7) / 8); if (plen % 8) { addr[(plen + 7) / 8 - 1] &= ((0xff00 >> (plen % 8)) & 0xff); } /* the label may get offsetted by 4 bits so lets shift it right */ /* Cannot use GET_ISONSAP_STRING (not packet buffer pointer) */ snprintf(buf, buflen, "RD: %s, %s/%u, label:%u %s", bgp_vpn_rd_print(ndo, pptr+4), isonsap_string(ndo, addr,(plen + 7) / 8), plen, GET_BE_U_3(pptr + 1)>>4, ((GET_U_1(pptr + 3) & 1) == 0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" ); return 12 + (plen + 7) / 8; } /* * bgp_attr_get_as_size * * Try to find the size of the ASs encoded in an as-path. It is not obvious, as * both Old speakers that do not support 4 byte AS, and the new speakers that do * support, exchange AS-Path with the same path-attribute type value 0x02. */ static u_int bgp_attr_get_as_size(netdissect_options *ndo, uint8_t bgpa_type, const u_char *pptr, u_int len) { const u_char *tptr = pptr; /* * If the path attribute is the optional AS4 path type, then we already * know, that ASs must be encoded in 4 byte format. */ if (bgpa_type == BGPTYPE_AS4_PATH) { return 4; } /* * Let us assume that ASs are of 2 bytes in size, and check if the AS-Path * TLV is good. If not, ask the caller to try with AS encoded as 4 bytes * each. */ while (tptr < pptr + len) { /* * If we do not find a valid segment type, our guess might be wrong. */ if (GET_U_1(tptr) < BGP_AS_SEG_TYPE_MIN || GET_U_1(tptr) > BGP_AS_SEG_TYPE_MAX) { goto trunc; } tptr += 2 + GET_U_1(tptr + 1) * 2; } /* * If we correctly reached end of the AS path attribute data content, * then most likely ASs were indeed encoded as 2 bytes. */ if (tptr == pptr + len) { return 2; } trunc: /* * We can come here, either we did not have enough data, or if we * try to decode 4 byte ASs in 2 byte format. Either way, return 4, * so that calller can try to decode each AS as of 4 bytes. If indeed * there was not enough data, it will crib and end the parse anyways. */ return 4; } /* * The only way to know that a BGP UPDATE message is using add path is * by checking if the capability is in the OPEN message which we may have missed. * So this function checks if it is possible that the update could contain add path * and if so it checks that standard BGP doesn't make sense. */ static int check_add_path(netdissect_options *ndo, const u_char *pptr, u_int length, u_int max_prefix_length) { u_int offset, prefix_length; if (length < 5) { return 0; } /* * Scan through the NLRI information under the assumpetion that * it doesn't have path IDs. */ for (offset = 0; offset < length;) { offset += 4; if (!ND_TTEST_1(pptr + offset)) { /* We ran out of captured data; quit scanning. */ break; } prefix_length = GET_U_1(pptr + offset); /* * Add 4 to cover the path id * and check the prefix length isn't greater than 32/128. */ if (prefix_length > max_prefix_length) { return 0; } /* Add 1 for the prefix_length byte and prefix_length to cover the address */ offset += 1 + ((prefix_length + 7) / 8); } /* check we haven't gone past the end of the section */ if (offset > length) { return 0; } /* check it's not standard BGP */ for (offset = 0; offset < length; ) { if (!ND_TTEST_1(pptr + offset)) { /* We ran out of captured data; quit scanning. */ break; } prefix_length = GET_U_1(pptr + offset); /* * If the prefix_length is zero (0.0.0.0/0) * and since it's not the only address (length >= 5) * then it is add-path */ if (prefix_length < 1 || prefix_length > max_prefix_length) { return 1; } offset += 1 + ((prefix_length + 7) / 8); } if (offset > length) { return 1; } /* assume not add-path by default */ return 0; } static int bgp_mp_af_print(netdissect_options *ndo, const u_char *tptr, u_int tlen, uint16_t *afp, uint8_t *safip) { uint16_t af; uint8_t safi; af = GET_BE_U_2(tptr); *afp = af; safi = GET_U_1(tptr + 2); *safip = safi; ND_PRINT("\n\t AFI: %s (%u), %sSAFI: %s (%u)", tok2str(af_values, "Unknown AFI", af), af, (safi>128) ? "vendor specific " : "", /* 128 is meanwhile wellknown */ tok2str(bgp_safi_values, "Unknown SAFI", safi), safi); switch(af<<8 | safi) { case (AFNUM_INET<<8 | SAFNUM_UNICAST): case (AFNUM_INET<<8 | SAFNUM_MULTICAST): case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST): case (AFNUM_INET<<8 | SAFNUM_LABUNICAST): case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO): case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST): case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST): case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): case (AFNUM_INET<<8 | SAFNUM_MDT): case (AFNUM_INET6<<8 | SAFNUM_UNICAST): case (AFNUM_INET6<<8 | SAFNUM_MULTICAST): case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST): case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST): case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST): case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST): case (AFNUM_NSAP<<8 | SAFNUM_UNICAST): case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST): case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST): case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST): case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST): case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST): case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST): case (AFNUM_VPLS<<8 | SAFNUM_VPLS): break; default: ND_TCHECK_LEN(tptr, tlen); ND_PRINT("\n\t no AFI %u / SAFI %u decoder", af, safi); if (ndo->ndo_vflag <= 1) print_unknown_data(ndo, tptr, "\n\t ", tlen); return -1; } return 0; trunc: return -2; } static int bgp_nlri_print(netdissect_options *ndo, uint16_t af, uint8_t safi, const u_char *tptr, u_int len, char *buf, size_t buflen, int add_path4, int add_path6) { int advance; u_int path_id = 0; switch (af<<8 | safi) { case (AFNUM_INET<<8 | SAFNUM_UNICAST): case (AFNUM_INET<<8 | SAFNUM_MULTICAST): case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST): if (add_path4) { path_id = GET_BE_U_4(tptr); tptr += 4; } advance = decode_prefix4(ndo, tptr, len, buf, buflen); if (advance == -1) ND_PRINT("\n\t (illegal prefix length)"); else if (advance == -2) break; /* bytes left, but not enough */ else ND_PRINT("\n\t %s", buf); if (add_path4) { ND_PRINT(" Path Id: %u", path_id); advance += 4; } break; case (AFNUM_INET<<8 | SAFNUM_LABUNICAST): advance = decode_labeled_prefix4(ndo, tptr, len, buf, buflen); if (advance == -1) ND_PRINT("\n\t (illegal prefix length)"); else if (advance == -2) goto trunc; else if (advance == -3) break; /* bytes left, but not enough */ else ND_PRINT("\n\t %s", buf); break; case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST): case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST): advance = decode_labeled_vpn_prefix4(ndo, tptr, buf, buflen); if (advance == -1) ND_PRINT("\n\t (illegal prefix length)"); else ND_PRINT("\n\t %s", buf); break; case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO): advance = decode_rt_routing_info(ndo, tptr); break; case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): /* fall through */ case (AFNUM_INET6<<8 | SAFNUM_MULTICAST_VPN): advance = decode_multicast_vpn(ndo, tptr, buf, buflen); if (advance == -1) ND_PRINT("\n\t (illegal prefix length)"); else if (advance == -2) goto trunc; else ND_PRINT("\n\t %s", buf); break; case (AFNUM_INET<<8 | SAFNUM_MDT): advance = decode_mdt_vpn_nlri(ndo, tptr, buf, buflen); if (advance == -1) ND_PRINT("\n\t (illegal prefix length)"); else if (advance == -2) goto trunc; else ND_PRINT("\n\t %s", buf); break; case (AFNUM_INET6<<8 | SAFNUM_UNICAST): case (AFNUM_INET6<<8 | SAFNUM_MULTICAST): case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST): if (add_path6) { path_id = GET_BE_U_4(tptr); tptr += 4; } advance = decode_prefix6(ndo, tptr, len, buf, buflen); if (advance == -1) ND_PRINT("\n\t (illegal prefix length)"); else if (advance == -2) break; /* bytes left, but not enough */ else ND_PRINT("\n\t %s", buf); if (add_path6) { ND_PRINT(" Path Id: %u", path_id); advance += 4; } break; case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST): advance = decode_labeled_prefix6(ndo, tptr, len, buf, buflen); if (advance == -1) ND_PRINT("\n\t (illegal prefix length)"); else if (advance == -2) goto trunc; else if (advance == -3) break; /* bytes left, but not enough */ else ND_PRINT("\n\t %s", buf); break; case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST): case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST): advance = decode_labeled_vpn_prefix6(ndo, tptr, buf, buflen); if (advance == -1) ND_PRINT("\n\t (illegal prefix length)"); else ND_PRINT("\n\t %s", buf); break; case (AFNUM_VPLS<<8 | SAFNUM_VPLS): case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST): case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST): advance = decode_labeled_vpn_l2(ndo, tptr, buf, buflen); if (advance == -1) ND_PRINT("\n\t (illegal length)"); else if (advance == -2) goto trunc; else ND_PRINT("\n\t %s", buf); break; case (AFNUM_NSAP<<8 | SAFNUM_UNICAST): case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST): case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST): advance = decode_clnp_prefix(ndo, tptr, buf, buflen); if (advance == -1) ND_PRINT("\n\t (illegal prefix length)"); else ND_PRINT("\n\t %s", buf); break; case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST): case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST): advance = decode_labeled_vpn_clnp_prefix(ndo, tptr, buf, buflen); if (advance == -1) ND_PRINT("\n\t (illegal prefix length)"); else ND_PRINT("\n\t %s", buf); break; default: /* * This should not happen, we should have been protected * by bgp_mp_af_print()'s return value. */ ND_PRINT("\n\t ERROR: no AFI %u / SAFI %u decoder", af, safi); advance = -4; break; } return advance; trunc: /* we rely on the caller to recognize -2 return value */ return -2; } static int bgp_attr_print(netdissect_options *ndo, uint8_t atype, const u_char *pptr, u_int len, const unsigned attr_set_level) { /* allocate space for the largest possible string */ char astostr[AS_STR_SIZE]; u_int i; uint16_t af; uint8_t safi, snpa, nhlen; int advance; u_int tlen; const u_char *tptr; char buf[MAXHOSTNAMELEN + 100]; u_int as_size; int add_path4, add_path6; int ret; tptr = pptr; tlen = len; switch (atype) { case BGPTYPE_ORIGIN: if (len != 1) ND_PRINT("invalid len"); else { ND_PRINT("%s", tok2str(bgp_origin_values, "Unknown Origin Typecode", GET_U_1(tptr))); } break; /* * Process AS4 byte path and AS2 byte path attributes here. */ case BGPTYPE_AS4_PATH: case BGPTYPE_AS_PATH: if (len % 2) { ND_PRINT("invalid len"); break; } if (!len) { ND_PRINT("empty"); break; } /* * BGP updates exchanged between New speakers that support 4 * byte AS, ASs are always encoded in 4 bytes. There is no * definitive way to find this, just by the packet's * contents. So, check for packet's TLV's sanity assuming * 2 bytes first, and it does not pass, assume that ASs are * encoded in 4 bytes format and move on. */ as_size = bgp_attr_get_as_size(ndo, atype, pptr, len); while (tptr < pptr + len) { ND_PRINT("%s", tok2str(bgp_as_path_segment_open_values, "?", GET_U_1(tptr))); for (i = 0; i < GET_U_1(tptr + 1) * as_size; i += as_size) { ND_TCHECK_LEN(tptr + 2 + i, as_size); ND_PRINT("%s ", as_printf(ndo, astostr, sizeof(astostr), as_size == 2 ? GET_BE_U_2(tptr + i + 2) : GET_BE_U_4(tptr + i + 2))); } ND_PRINT("%s", tok2str(bgp_as_path_segment_close_values, "?", GET_U_1(tptr))); tptr += 2 + GET_U_1(tptr + 1) * as_size; } break; case BGPTYPE_NEXT_HOP: if (len != 4) ND_PRINT("invalid len"); else { ND_PRINT("%s", GET_IPADDR_STRING(tptr)); } break; case BGPTYPE_MULTI_EXIT_DISC: case BGPTYPE_LOCAL_PREF: if (len != 4) ND_PRINT("invalid len"); else { ND_PRINT("%u", GET_BE_U_4(tptr)); } break; case BGPTYPE_ATOMIC_AGGREGATE: if (len != 0) ND_PRINT("invalid len"); break; case BGPTYPE_AGGREGATOR: /* * Depending on the AS encoded is of 2 bytes or of 4 bytes, * the length of this PA can be either 6 bytes or 8 bytes. */ if (len != 6 && len != 8) { ND_PRINT("invalid len"); break; } ND_TCHECK_LEN(tptr, len); if (len == 6) { ND_PRINT(" AS #%s, origin %s", as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_2(tptr)), GET_IPADDR_STRING(tptr + 2)); } else { ND_PRINT(" AS #%s, origin %s", as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_4(tptr)), GET_IPADDR_STRING(tptr + 4)); } break; case BGPTYPE_AGGREGATOR4: if (len != 8) { ND_PRINT("invalid len"); break; } ND_PRINT(" AS #%s, origin %s", as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_4(tptr)), GET_IPADDR_STRING(tptr + 4)); break; case BGPTYPE_COMMUNITIES: if (len % 4) { ND_PRINT("invalid len"); break; } while (tlen != 0) { uint32_t comm; ND_TCHECK_4(tptr); if (tlen < 4) goto trunc; comm = GET_BE_U_4(tptr); switch (comm) { case BGP_COMMUNITY_NO_EXPORT: ND_PRINT(" NO_EXPORT"); break; case BGP_COMMUNITY_NO_ADVERT: ND_PRINT(" NO_ADVERTISE"); break; case BGP_COMMUNITY_NO_EXPORT_SUBCONFED: ND_PRINT(" NO_EXPORT_SUBCONFED"); break; default: ND_PRINT("%u:%u%s", (comm >> 16) & 0xffff, comm & 0xffff, (tlen>4) ? ", " : ""); break; } tlen -=4; tptr +=4; } break; case BGPTYPE_ORIGINATOR_ID: if (len != 4) { ND_PRINT("invalid len"); break; } ND_PRINT("%s",GET_IPADDR_STRING(tptr)); break; case BGPTYPE_CLUSTER_LIST: if (len % 4) { ND_PRINT("invalid len"); break; } while (tlen != 0) { if (tlen < 4) goto trunc; ND_PRINT("%s%s", GET_IPADDR_STRING(tptr), (tlen>4) ? ", " : ""); tlen -=4; tptr +=4; } break; case BGPTYPE_MP_REACH_NLRI: ND_TCHECK_3(tptr); if (tlen < 3) goto trunc; ret = bgp_mp_af_print(ndo, tptr, tlen, &af, &safi); if (ret == -2) goto trunc; if (ret < 0) break; tptr += 3; tlen -= 3; ND_TCHECK_1(tptr); if (tlen < 1) goto trunc; nhlen = GET_U_1(tptr); tptr++; tlen--; if (nhlen) { u_int nnh = 0; uint8_t tnhlen = nhlen; if (tlen < tnhlen) goto trunc; ND_PRINT("\n\t nexthop: "); while (tnhlen != 0) { if (nnh++ > 0) { ND_PRINT(", " ); } switch(af<<8 | safi) { case (AFNUM_INET<<8 | SAFNUM_UNICAST): case (AFNUM_INET<<8 | SAFNUM_MULTICAST): case (AFNUM_INET<<8 | SAFNUM_UNIMULTICAST): case (AFNUM_INET<<8 | SAFNUM_LABUNICAST): case (AFNUM_INET<<8 | SAFNUM_RT_ROUTING_INFO): case (AFNUM_INET<<8 | SAFNUM_MULTICAST_VPN): case (AFNUM_INET<<8 | SAFNUM_MDT): if (tnhlen < sizeof(nd_ipv4)) { ND_PRINT("invalid len"); tptr += tnhlen; tlen -= tnhlen; tnhlen = 0; } else { ND_PRINT("%s",GET_IPADDR_STRING(tptr)); tptr += sizeof(nd_ipv4); tnhlen -= sizeof(nd_ipv4); tlen -= sizeof(nd_ipv4); } break; case (AFNUM_INET<<8 | SAFNUM_VPNUNICAST): case (AFNUM_INET<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_INET<<8 | SAFNUM_VPNUNIMULTICAST): if (tnhlen < sizeof(nd_ipv4)+BGP_VPN_RD_LEN) { ND_PRINT("invalid len"); tptr += tnhlen; tlen -= tnhlen; tnhlen = 0; } else { ND_PRINT("RD: %s, %s", bgp_vpn_rd_print(ndo, tptr), GET_IPADDR_STRING(tptr+BGP_VPN_RD_LEN)); tptr += (sizeof(nd_ipv4)+BGP_VPN_RD_LEN); tlen -= (sizeof(nd_ipv4)+BGP_VPN_RD_LEN); tnhlen -= (sizeof(nd_ipv4)+BGP_VPN_RD_LEN); } break; case (AFNUM_INET6<<8 | SAFNUM_UNICAST): case (AFNUM_INET6<<8 | SAFNUM_MULTICAST): case (AFNUM_INET6<<8 | SAFNUM_UNIMULTICAST): case (AFNUM_INET6<<8 | SAFNUM_LABUNICAST): if (tnhlen < sizeof(nd_ipv6)) { ND_PRINT("invalid len"); tptr += tnhlen; tlen -= tnhlen; tnhlen = 0; } else { ND_PRINT("%s", GET_IP6ADDR_STRING(tptr)); tptr += sizeof(nd_ipv6); tlen -= sizeof(nd_ipv6); tnhlen -= sizeof(nd_ipv6); } break; case (AFNUM_INET6<<8 | SAFNUM_VPNUNICAST): case (AFNUM_INET6<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_INET6<<8 | SAFNUM_VPNUNIMULTICAST): if (tnhlen < sizeof(nd_ipv6)+BGP_VPN_RD_LEN) { ND_PRINT("invalid len"); tptr += tnhlen; tlen -= tnhlen; tnhlen = 0; } else { ND_PRINT("RD: %s, %s", bgp_vpn_rd_print(ndo, tptr), GET_IP6ADDR_STRING(tptr+BGP_VPN_RD_LEN)); tptr += (sizeof(nd_ipv6)+BGP_VPN_RD_LEN); tlen -= (sizeof(nd_ipv6)+BGP_VPN_RD_LEN); tnhlen -= (sizeof(nd_ipv6)+BGP_VPN_RD_LEN); } break; case (AFNUM_VPLS<<8 | SAFNUM_VPLS): case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNICAST): case (AFNUM_L2VPN<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_L2VPN<<8 | SAFNUM_VPNUNIMULTICAST): if (tnhlen < sizeof(nd_ipv4)) { ND_PRINT("invalid len"); tptr += tnhlen; tlen -= tnhlen; tnhlen = 0; } else { ND_PRINT("%s", GET_IPADDR_STRING(tptr)); tptr += (sizeof(nd_ipv4)); tlen -= (sizeof(nd_ipv4)); tnhlen -= (sizeof(nd_ipv4)); } break; case (AFNUM_NSAP<<8 | SAFNUM_UNICAST): case (AFNUM_NSAP<<8 | SAFNUM_MULTICAST): case (AFNUM_NSAP<<8 | SAFNUM_UNIMULTICAST): ND_PRINT("%s", GET_ISONSAP_STRING(tptr, tnhlen)); tptr += tnhlen; tlen -= tnhlen; tnhlen = 0; break; case (AFNUM_NSAP<<8 | SAFNUM_VPNUNICAST): case (AFNUM_NSAP<<8 | SAFNUM_VPNMULTICAST): case (AFNUM_NSAP<<8 | SAFNUM_VPNUNIMULTICAST): if (tnhlen < BGP_VPN_RD_LEN+1) { ND_PRINT("invalid len"); tptr += tnhlen; tlen -= tnhlen; tnhlen = 0; } else { ND_TCHECK_LEN(tptr, tnhlen); ND_PRINT("RD: %s, %s", bgp_vpn_rd_print(ndo, tptr), GET_ISONSAP_STRING(tptr+BGP_VPN_RD_LEN,tnhlen-BGP_VPN_RD_LEN)); /* rfc986 mapped IPv4 address ? */ if (GET_BE_U_4(tptr + BGP_VPN_RD_LEN) == 0x47000601) ND_PRINT(" = %s", GET_IPADDR_STRING(tptr+BGP_VPN_RD_LEN+4)); /* rfc1888 mapped IPv6 address ? */ else if (GET_BE_U_3(tptr + BGP_VPN_RD_LEN) == 0x350000) ND_PRINT(" = %s", GET_IP6ADDR_STRING(tptr+BGP_VPN_RD_LEN+3)); tptr += tnhlen; tlen -= tnhlen; tnhlen = 0; } break; default: /* * bgp_mp_af_print() should have saved us from * an unsupported AFI/SAFI. */ ND_PRINT("ERROR: no AFI %u/SAFI %u nexthop decoder", af, safi); tptr += tnhlen; tlen -= tnhlen; tnhlen = 0; goto done; break; } } } ND_PRINT(", nh-length: %u", nhlen); /* As per RFC 2858; this is reserved in RFC 4760 */ if (tlen < 1) goto trunc; snpa = GET_U_1(tptr); tptr++; tlen--; if (snpa) { ND_PRINT("\n\t %u SNPA", snpa); for (/*nothing*/; snpa != 0; snpa--) { uint8_t snpalen; if (tlen < 1) goto trunc; snpalen = GET_U_1(tptr); ND_PRINT("\n\t %u bytes", snpalen); tptr++; tlen--; if (tlen < snpalen) goto trunc; ND_TCHECK_LEN(tptr, snpalen); tptr += snpalen; tlen -= snpalen; } } else { ND_PRINT(", no SNPA"); } add_path4 = check_add_path(ndo, tptr, (len-ND_BYTES_BETWEEN(tptr, pptr)), 32); add_path6 = check_add_path(ndo, tptr, (len-ND_BYTES_BETWEEN(tptr, pptr)), 128); while (tptr < pptr + len) { advance = bgp_nlri_print(ndo, af, safi, tptr, len, buf, sizeof(buf), add_path4, add_path6); if (advance == -2) goto trunc; if (advance < 0) break; tptr += advance; } break; case BGPTYPE_MP_UNREACH_NLRI: ND_TCHECK_LEN(tptr, BGP_MP_NLRI_MINSIZE); ret = bgp_mp_af_print(ndo, tptr, tlen, &af, &safi); if (ret == -2) goto trunc; if (ret < 0) break; if (len == BGP_MP_NLRI_MINSIZE) ND_PRINT("\n\t End-of-Rib Marker (empty NLRI)"); tptr += 3; add_path4 = check_add_path(ndo, tptr, (len-ND_BYTES_BETWEEN(tptr, pptr)), 32); add_path6 = check_add_path(ndo, tptr, (len-ND_BYTES_BETWEEN(tptr, pptr)), 128); while (tptr < pptr + len) { advance = bgp_nlri_print(ndo, af, safi, tptr, len, buf, sizeof(buf), add_path4, add_path6); if (advance == -2) goto trunc; if (advance < 0) break; tptr += advance; } break; case BGPTYPE_EXTD_COMMUNITIES: if (len % 8) { ND_PRINT("invalid len"); break; } while (tlen != 0) { uint16_t extd_comm; ND_TCHECK_2(tptr); if (tlen < 2) goto trunc; extd_comm=GET_BE_U_2(tptr); ND_PRINT("\n\t %s (0x%04x), Flags [%s]", tok2str(bgp_extd_comm_subtype_values, "unknown extd community typecode", extd_comm), extd_comm, bittok2str(bgp_extd_comm_flag_values, "none", extd_comm)); ND_TCHECK_8(tptr); if (tlen < 8) goto trunc; ND_PRINT(": "); bgp_extended_community_print(ndo, tptr); tlen -= 8; tptr += 8; } break; case BGPTYPE_PMSI_TUNNEL: { uint8_t tunnel_type, flags; ND_TCHECK_5(tptr); if (tlen < 5) goto trunc; flags = GET_U_1(tptr); tunnel_type = GET_U_1(tptr + 1); ND_PRINT("\n\t Tunnel-type %s (%u), Flags [%s], MPLS Label %u", tok2str(bgp_pmsi_tunnel_values, "Unknown", tunnel_type), tunnel_type, bittok2str(bgp_pmsi_flag_values, "none", flags), GET_BE_U_3(tptr + 2)>>4); tptr +=5; tlen -= 5; switch (tunnel_type) { case BGP_PMSI_TUNNEL_PIM_SM: /* fall through */ case BGP_PMSI_TUNNEL_PIM_BIDIR: ND_PRINT("\n\t Sender %s, P-Group %s", GET_IPADDR_STRING(tptr), GET_IPADDR_STRING(tptr+4)); break; case BGP_PMSI_TUNNEL_PIM_SSM: ND_PRINT("\n\t Root-Node %s, P-Group %s", GET_IPADDR_STRING(tptr), GET_IPADDR_STRING(tptr+4)); break; case BGP_PMSI_TUNNEL_INGRESS: ND_PRINT("\n\t Tunnel-Endpoint %s", GET_IPADDR_STRING(tptr)); break; case BGP_PMSI_TUNNEL_LDP_P2MP: /* fall through */ case BGP_PMSI_TUNNEL_LDP_MP2MP: ND_PRINT("\n\t Root-Node %s, LSP-ID 0x%08x", GET_IPADDR_STRING(tptr), GET_BE_U_4(tptr + 4)); break; case BGP_PMSI_TUNNEL_RSVP_P2MP: ND_PRINT("\n\t Extended-Tunnel-ID %s, P2MP-ID 0x%08x", GET_IPADDR_STRING(tptr), GET_BE_U_4(tptr + 4)); break; default: if (ndo->ndo_vflag <= 1) { print_unknown_data(ndo, tptr, "\n\t ", tlen); } } break; } case BGPTYPE_AIGP: { uint8_t type; uint16_t length; while (tlen >= 3) { type = GET_U_1(tptr); length = GET_BE_U_2(tptr + 1); tptr += 3; tlen -= 3; ND_PRINT("\n\t %s TLV (%u), length %u", tok2str(bgp_aigp_values, "Unknown", type), type, length); if (length < 3) goto trunc; length -= 3; /* * Check if we can read the TLV data. */ ND_TCHECK_LEN(tptr + 3, length); if (tlen < length) goto trunc; switch (type) { case BGP_AIGP_TLV: if (length < 8) goto trunc; ND_PRINT(", metric %" PRIu64, GET_BE_U_8(tptr)); break; default: if (ndo->ndo_vflag <= 1) { print_unknown_data(ndo, tptr,"\n\t ", length); } } tptr += length; tlen -= length; } break; } case BGPTYPE_ATTR_SET: ND_TCHECK_4(tptr); if (len < 4) goto trunc; ND_PRINT("\n\t Origin AS: %s", as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_4(tptr))); tptr += 4; len -= 4; while (len) { u_int aflags, alenlen, alen; ND_TCHECK_2(tptr); if (len < 2) { ND_PRINT(" [path attr too short]"); tptr += len; break; } aflags = GET_U_1(tptr); atype = GET_U_1(tptr + 1); tptr += 2; len -= 2; alenlen = bgp_attr_lenlen(aflags, tptr); ND_TCHECK_LEN(tptr, alenlen); if (len < alenlen) { ND_PRINT(" [path attr too short]"); tptr += len; break; } alen = bgp_attr_len(aflags, tptr); tptr += alenlen; len -= alenlen; ND_PRINT("\n\t %s (%u), length: %u", tok2str(bgp_attr_values, "Unknown Attribute", atype), atype, alen); if (aflags) { ND_PRINT(", Flags [%s%s%s%s", aflags & 0x80 ? "O" : "", aflags & 0x40 ? "T" : "", aflags & 0x20 ? "P" : "", aflags & 0x10 ? "E" : ""); if (aflags & 0xf) ND_PRINT("+%x", aflags & 0xf); ND_PRINT("]"); } ND_PRINT(": "); if (len < alen) { ND_PRINT(" [path attr too short]"); tptr += len; break; } /* * The protocol encoding per se allows ATTR_SET to be nested * as many times as the message can accommodate. This printer * used to be able to recurse into ATTR_SET contents until the * stack exhaustion, but now there is a limit on that (if live * protocol exchange goes that many levels deep, something is * probably wrong anyway). Feel free to refine this value if * you can find the spec with respective normative text. */ if (attr_set_level == 10) ND_PRINT("(too many nested levels, not recursing)"); else if (!bgp_attr_print(ndo, atype, tptr, alen, attr_set_level + 1)) return 0; tptr += alen; len -= alen; } break; case BGPTYPE_LARGE_COMMUNITY: if (len == 0 || len % 12) { ND_PRINT("invalid len"); break; } ND_PRINT("\n\t "); while (len != 0) { ND_PRINT("%u:%u:%u%s", GET_BE_U_4(tptr), GET_BE_U_4(tptr + 4), GET_BE_U_4(tptr + 8), (len > 12) ? ", " : ""); tptr += 12; /* * len will always be a multiple of 12, as per the above, * so this will never underflow. */ len -= 12; } break; default: ND_TCHECK_LEN(pptr, len); ND_PRINT("\n\t no Attribute %u decoder", atype); /* we have no decoder for the attribute */ if (ndo->ndo_vflag <= 1) print_unknown_data(ndo, pptr, "\n\t ", len); break; } done: if (ndo->ndo_vflag > 1 && len) { /* omit zero length attributes*/ ND_TCHECK_LEN(pptr, len); print_unknown_data(ndo, pptr, "\n\t ", len); } return 1; trunc: return 0; } static void bgp_capabilities_print(netdissect_options *ndo, const u_char *opt, u_int caps_len) { /* allocate space for the largest possible string */ char astostr[AS_STR_SIZE]; u_int cap_type, cap_len, tcap_len, cap_offset; u_int i = 0; while (i < caps_len) { ND_TCHECK_LEN(opt + i, BGP_CAP_HEADER_SIZE); cap_type=GET_U_1(opt + i); cap_len=GET_U_1(opt + i + 1); ND_PRINT("\n\t %s (%u), length: %u", tok2str(bgp_capcode_values, "Unknown", cap_type), cap_type, cap_len); ND_TCHECK_LEN(opt + 2 + i, cap_len); switch (cap_type) { case BGP_CAPCODE_MP: /* AFI (16 bits), Reserved (8 bits), SAFI (8 bits) */ if (cap_len < 4) { ND_PRINT(" (too short, < 4)"); return; } ND_PRINT("\n\t\tAFI %s (%u), SAFI %s (%u)", tok2str(af_values, "Unknown", GET_BE_U_2(opt + i + 2)), GET_BE_U_2(opt + i + 2), tok2str(bgp_safi_values, "Unknown", GET_U_1(opt + i + 5)), GET_U_1(opt + i + 5)); break; case BGP_CAPCODE_ML: cap_offset = 2; tcap_len = cap_len; while (tcap_len >= 4) { ND_PRINT( "\n\t\tAFI %s (%u), SAFI %s (%u), Count: %u", tok2str(af_values, "Unknown", GET_BE_U_2(opt + i + cap_offset)), GET_BE_U_2(opt + i + cap_offset), tok2str(bgp_safi_values, "Unknown", GET_U_1(opt + i + cap_offset + 2)), GET_U_1(opt + i + cap_offset + 2), GET_U_1(opt + i + cap_offset + 3)); tcap_len -= 4; cap_offset += 4; } break; case BGP_CAPCODE_RESTART: /* Restart Flags (4 bits), Restart Time in seconds (12 bits) */ if (cap_len < 2) { ND_PRINT(" (too short, < 2)"); return; } tcap_len=cap_len; ND_PRINT("\n\t\tRestart Flags: [%s], Restart Time %us", ((GET_U_1(opt + i + 2))&0x80) ? "R" : "none", GET_BE_U_2(opt + i + 2)&0xfff); tcap_len-=2; cap_offset=4; while(tcap_len>=4) { ND_PRINT("\n\t\t AFI %s (%u), SAFI %s (%u), Forwarding state preserved: %s", tok2str(af_values,"Unknown", GET_BE_U_2(opt + i + cap_offset)), GET_BE_U_2(opt + i + cap_offset), tok2str(bgp_safi_values,"Unknown", GET_U_1(opt + i + cap_offset + 2)), GET_U_1(opt + (i + cap_offset + 2)), ((GET_U_1(opt + (i + cap_offset + 3)))&0x80) ? "yes" : "no" ); tcap_len -= 4; cap_offset += 4; } break; case BGP_CAPCODE_RR: case BGP_CAPCODE_LLGR: case BGP_CAPCODE_RR_CISCO: break; case BGP_CAPCODE_AS_NEW: /* * Extract the 4 byte AS number encoded. */ if (cap_len < 4) { ND_PRINT(" (too short, < 4)"); return; } ND_PRINT("\n\t\t 4 Byte AS %s", as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_4(opt + i + 2))); break; case BGP_CAPCODE_ADD_PATH: if (cap_len == 0) { ND_PRINT(" (bogus)"); /* length */ break; } tcap_len=cap_len; cap_offset=2; while (tcap_len != 0) { if (tcap_len < 4) { nd_print_invalid(ndo); break; } ND_PRINT("\n\t\tAFI %s (%u), SAFI %s (%u), Send/Receive: %s", tok2str(af_values,"Unknown",GET_BE_U_2(opt + i + cap_offset)), GET_BE_U_2(opt + i + cap_offset), tok2str(bgp_safi_values,"Unknown",GET_U_1(opt + i + cap_offset + 2)), GET_U_1(opt + (i + cap_offset + 2)), tok2str(bgp_add_path_recvsend,"Bogus (0x%02x)",GET_U_1(opt + i + cap_offset + 3)) ); tcap_len -= 4; cap_offset += 4; } break; default: ND_PRINT("\n\t\tno decoder for Capability %u", cap_type); if (ndo->ndo_vflag <= 1) print_unknown_data(ndo, opt + i + 2, "\n\t\t", cap_len); break; } if (ndo->ndo_vflag > 1 && cap_len != 0) { print_unknown_data(ndo, opt + i + 2, "\n\t\t", cap_len); } i += BGP_CAP_HEADER_SIZE + cap_len; } return; trunc: nd_print_trunc(ndo); } static void bgp_open_print(netdissect_options *ndo, const u_char *dat, u_int length) { /* allocate space for the largest possible string */ char astostr[AS_STR_SIZE]; const struct bgp_open *bgp_open_header; u_int optslen; const struct bgp_opt *bgpopt; const u_char *opt; u_int i; ND_TCHECK_LEN(dat, BGP_OPEN_SIZE); if (length < BGP_OPEN_SIZE) goto trunc; bgp_open_header = (const struct bgp_open *)dat; ND_PRINT("\n\t Version %u, ", GET_U_1(bgp_open_header->bgpo_version)); ND_PRINT("my AS %s, ", as_printf(ndo, astostr, sizeof(astostr), GET_BE_U_2(bgp_open_header->bgpo_myas))); ND_PRINT("Holdtime %us, ", GET_BE_U_2(bgp_open_header->bgpo_holdtime)); ND_PRINT("ID %s", GET_IPADDR_STRING(bgp_open_header->bgpo_id)); optslen = GET_U_1(bgp_open_header->bgpo_optlen); ND_PRINT("\n\t Optional parameters, length: %u", optslen); opt = dat + BGP_OPEN_SIZE; length -= BGP_OPEN_SIZE; i = 0; while (i < optslen) { uint8_t opt_type, opt_len; ND_TCHECK_LEN(opt + i, BGP_OPT_SIZE); if (length < BGP_OPT_SIZE + i) goto trunc; bgpopt = (const struct bgp_opt *)(opt + i); opt_type = GET_U_1(bgpopt->bgpopt_type); opt_len = GET_U_1(bgpopt->bgpopt_len); if (BGP_OPT_SIZE + i + opt_len > optslen) { ND_PRINT("\n\t Option %u, length: %u, goes past the end of the options", opt_type, opt_len); break; } ND_PRINT("\n\t Option %s (%u), length: %u", tok2str(bgp_opt_values,"Unknown",opt_type), opt_type, opt_len); /* now let's decode the options we know*/ switch(opt_type) { case BGP_OPT_CAP: bgp_capabilities_print(ndo, opt + BGP_OPT_SIZE + i, opt_len); break; case BGP_OPT_AUTH: default: ND_PRINT("\n\t no decoder for option %u", opt_type); break; } i += BGP_OPT_SIZE + opt_len; } return; trunc: nd_print_trunc(ndo); } static void bgp_update_print(netdissect_options *ndo, const u_char *dat, u_int length) { const u_char *p; u_int withdrawn_routes_len; char buf[MAXHOSTNAMELEN + 100]; int wpfx; u_int len; int i; int add_path; u_int path_id = 0; ND_TCHECK_LEN(dat, BGP_SIZE); if (length < BGP_SIZE) goto trunc; p = dat + BGP_SIZE; length -= BGP_SIZE; /* Unfeasible routes */ ND_TCHECK_2(p); if (length < 2) goto trunc; withdrawn_routes_len = GET_BE_U_2(p); p += 2; length -= 2; if (withdrawn_routes_len > 1) { /* * Without keeping state from the original NLRI message, * it's not possible to tell if this a v4 or v6 route, * so only try to decode it if we're not v6 enabled. */ ND_TCHECK_LEN(p, withdrawn_routes_len); if (length < withdrawn_routes_len) goto trunc; ND_PRINT("\n\t Withdrawn routes:"); add_path = check_add_path(ndo, p, withdrawn_routes_len, 32); while (withdrawn_routes_len != 0) { if (add_path) { if (withdrawn_routes_len < 4) { p += withdrawn_routes_len; length -= withdrawn_routes_len; break; } path_id = GET_BE_U_4(p); p += 4; length -= 4; withdrawn_routes_len -= 4; } wpfx = decode_prefix4(ndo, p, withdrawn_routes_len, buf, sizeof(buf)); if (wpfx == -1) { ND_PRINT("\n\t (illegal prefix length)"); break; } else if (wpfx == -2) goto trunc; /* bytes left, but not enough */ else { ND_PRINT("\n\t %s", buf); if (add_path) { ND_PRINT(" Path Id: %u", path_id); } p += wpfx; length -= wpfx; withdrawn_routes_len -= wpfx; } } } else { ND_TCHECK_LEN(p, withdrawn_routes_len); if (length < withdrawn_routes_len) goto trunc; p += withdrawn_routes_len; length -= withdrawn_routes_len; } ND_TCHECK_2(p); if (length < 2) goto trunc; len = GET_BE_U_2(p); p += 2; length -= 2; if (withdrawn_routes_len == 0 && len == 0 && length == 0) { /* No withdrawn routes, no path attributes, no NLRI */ ND_PRINT("\n\t End-of-Rib Marker (empty NLRI)"); return; } if (len) { /* do something more useful!*/ while (len) { uint8_t aflags, atype, alenlen; uint16_t alen; ND_TCHECK_2(p); if (length < 2) goto trunc; if (len < 2) { ND_PRINT("\n\t [path attrs too short]"); p += len; length -= len; break; } aflags = GET_U_1(p); atype = GET_U_1(p + 1); p += 2; len -= 2; length -= 2; alenlen = bgp_attr_lenlen(aflags, p); ND_TCHECK_LEN(p, alenlen); if (length < alenlen) goto trunc; if (len < alenlen) { ND_PRINT("\n\t [path attrs too short]"); p += len; length -= len; break; } alen = bgp_attr_len(aflags, p); p += alenlen; len -= alenlen; length -= alenlen; ND_PRINT("\n\t %s (%u), length: %u", tok2str(bgp_attr_values, "Unknown Attribute", atype), atype, alen); if (aflags) { ND_PRINT(", Flags [%s%s%s%s", aflags & 0x80 ? "O" : "", aflags & 0x40 ? "T" : "", aflags & 0x20 ? "P" : "", aflags & 0x10 ? "E" : ""); if (aflags & 0xf) ND_PRINT("+%x", aflags & 0xf); ND_PRINT("]: "); } if (len < alen) { ND_PRINT(" [path attrs too short]"); p += len; length -= len; break; } if (length < alen) goto trunc; if (!bgp_attr_print(ndo, atype, p, alen, 0)) goto trunc; p += alen; len -= alen; length -= alen; } } if (length) { add_path = check_add_path(ndo, p, length, 32); ND_PRINT("\n\t Updated routes:"); while (length != 0) { if (add_path) { ND_TCHECK_4(p); if (length < 4) goto trunc; path_id = GET_BE_U_4(p); p += 4; length -= 4; } i = decode_prefix4(ndo, p, length, buf, sizeof(buf)); if (i == -1) { ND_PRINT("\n\t (illegal prefix length)"); break; } else if (i == -2) goto trunc; /* bytes left, but not enough */ else { ND_PRINT("\n\t %s", buf); if (add_path) { ND_PRINT(" Path Id: %u", path_id); } p += i; length -= i; } } } return; trunc: nd_print_trunc(ndo); } static void bgp_notification_print(netdissect_options *ndo, const u_char *dat, u_int length) { const struct bgp_notification *bgp_notification_header; const u_char *tptr; uint8_t bgpn_major, bgpn_minor; uint8_t shutdown_comm_length; uint8_t remainder_offset; ND_TCHECK_LEN(dat, BGP_NOTIFICATION_SIZE); if (lengthbgpn_major); bgpn_minor = GET_U_1(bgp_notification_header->bgpn_minor); ND_PRINT(", %s (%u)", tok2str(bgp_notify_major_values, "Unknown Error", bgpn_major), bgpn_major); switch (bgpn_major) { case BGP_NOTIFY_MAJOR_MSG: ND_PRINT(", subcode %s (%u)", tok2str(bgp_notify_minor_msg_values, "Unknown", bgpn_minor), bgpn_minor); break; case BGP_NOTIFY_MAJOR_OPEN: ND_PRINT(", subcode %s (%u)", tok2str(bgp_notify_minor_open_values, "Unknown", bgpn_minor), bgpn_minor); break; case BGP_NOTIFY_MAJOR_UPDATE: ND_PRINT(", subcode %s (%u)", tok2str(bgp_notify_minor_update_values, "Unknown", bgpn_minor), bgpn_minor); break; case BGP_NOTIFY_MAJOR_FSM: ND_PRINT(" subcode %s (%u)", tok2str(bgp_notify_minor_fsm_values, "Unknown", bgpn_minor), bgpn_minor); break; case BGP_NOTIFY_MAJOR_CAP: ND_PRINT(" subcode %s (%u)", tok2str(bgp_notify_minor_cap_values, "Unknown", bgpn_minor), bgpn_minor); break; case BGP_NOTIFY_MAJOR_CEASE: ND_PRINT(", subcode %s (%u)", tok2str(bgp_notify_minor_cease_values, "Unknown", bgpn_minor), bgpn_minor); /* draft-ietf-idr-cease-subcode-02 mentions optionally 7 bytes * for the maxprefix subtype, which may contain AFI, SAFI and MAXPREFIXES */ if(bgpn_minor == BGP_NOTIFY_MINOR_CEASE_MAXPRFX && length >= BGP_NOTIFICATION_SIZE + 7) { tptr = dat + BGP_NOTIFICATION_SIZE; ND_PRINT(", AFI %s (%u), SAFI %s (%u), Max Prefixes: %u", tok2str(af_values, "Unknown", GET_BE_U_2(tptr)), GET_BE_U_2(tptr), tok2str(bgp_safi_values, "Unknown", GET_U_1((tptr + 2))), GET_U_1((tptr + 2)), GET_BE_U_4(tptr + 3)); } /* * draft-ietf-idr-shutdown describes a method to send a communication * intended for human consumption regarding the Administrative Shutdown */ if ((bgpn_minor == BGP_NOTIFY_MINOR_CEASE_SHUT || bgpn_minor == BGP_NOTIFY_MINOR_CEASE_RESET) && length >= BGP_NOTIFICATION_SIZE + 1) { tptr = dat + BGP_NOTIFICATION_SIZE; shutdown_comm_length = GET_U_1(tptr); remainder_offset = 0; /* garbage, hexdump it all */ if (shutdown_comm_length > BGP_NOTIFY_MINOR_CEASE_ADMIN_SHUTDOWN_LEN || shutdown_comm_length > length - (BGP_NOTIFICATION_SIZE + 1)) { ND_PRINT(", invalid Shutdown Communication length"); } else if (shutdown_comm_length == 0) { ND_PRINT(", empty Shutdown Communication"); remainder_offset += 1; } /* a proper shutdown communication */ else { ND_TCHECK_LEN(tptr + 1, shutdown_comm_length); ND_PRINT(", Shutdown Communication (length: %u): \"", shutdown_comm_length); (void)nd_printn(ndo, tptr+1, shutdown_comm_length, NULL); ND_PRINT("\""); remainder_offset += shutdown_comm_length + 1; } /* if there is trailing data, hexdump it */ if(length - (remainder_offset + BGP_NOTIFICATION_SIZE) > 0) { ND_PRINT(", Data: (length: %u)", length - (remainder_offset + BGP_NOTIFICATION_SIZE)); hex_print(ndo, "\n\t\t", tptr + remainder_offset, length - (remainder_offset + BGP_NOTIFICATION_SIZE)); } } break; default: break; } return; trunc: nd_print_trunc(ndo); } static void bgp_route_refresh_print(netdissect_options *ndo, const u_char *pptr, u_int len) { const struct bgp_route_refresh *bgp_route_refresh_header; ND_TCHECK_LEN(pptr, BGP_ROUTE_REFRESH_SIZE); /* some little sanity checking */ if (lenafi)), GET_BE_U_2(bgp_route_refresh_header->afi), tok2str(bgp_safi_values,"Unknown", GET_U_1(bgp_route_refresh_header->safi)), GET_U_1(bgp_route_refresh_header->safi)); if (ndo->ndo_vflag > 1) { ND_TCHECK_LEN(pptr, len); print_unknown_data(ndo, pptr, "\n\t ", len); } return; trunc: nd_print_trunc(ndo); } static int bgp_pdu_print(netdissect_options *ndo, const u_char *dat, u_int length) { const struct bgp *bgp_header; uint8_t bgp_type; ND_TCHECK_LEN(dat, BGP_SIZE); bgp_header = (const struct bgp *)dat; bgp_type = GET_U_1(bgp_header->bgp_type); ND_PRINT("\n\t%s Message (%u), length: %u", tok2str(bgp_msg_values, "Unknown", bgp_type), bgp_type, length); switch (bgp_type) { case BGP_OPEN: bgp_open_print(ndo, dat, length); break; case BGP_UPDATE: bgp_update_print(ndo, dat, length); break; case BGP_NOTIFICATION: bgp_notification_print(ndo, dat, length); break; case BGP_KEEPALIVE: break; case BGP_ROUTE_REFRESH: bgp_route_refresh_print(ndo, dat, length); break; default: /* we have no decoder for the BGP message */ ND_TCHECK_LEN(dat, length); ND_PRINT("\n\t no Message %u decoder", bgp_type); print_unknown_data(ndo, dat, "\n\t ", length); break; } return 1; trunc: nd_print_trunc(ndo); return 0; } void bgp_print(netdissect_options *ndo, const u_char *dat, u_int length _U_) { const u_char *p; const u_char *ep = ndo->ndo_snapend; const u_char *start; const u_char marker[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; const struct bgp *bgp_header; uint16_t hlen; ndo->ndo_protocol = "bgp"; ND_PRINT(": BGP"); if (ndo->ndo_vflag < 1) /* lets be less chatty */ return; p = dat; start = p; while (p < ep) { if (!ND_TTEST_1(p)) break; if (GET_U_1(p) != 0xff) { p++; continue; } if (!ND_TTEST_LEN(p, sizeof(marker))) break; if (memcmp(p, marker, sizeof(marker)) != 0) { p++; continue; } /* found BGP header */ ND_TCHECK_LEN(p, BGP_SIZE); bgp_header = (const struct bgp *)p; if (start != p) nd_print_trunc(ndo); hlen = GET_BE_U_2(bgp_header->bgp_len); if (hlen < BGP_SIZE) { ND_PRINT("\nmessage length %u < %u", hlen, BGP_SIZE); nd_print_invalid(ndo); break; } if (ND_TTEST_LEN(p, hlen)) { if (!bgp_pdu_print(ndo, p, hlen)) return; p += hlen; start = p; } else { ND_PRINT("\n[|BGP %s]", tok2str(bgp_msg_values, "Unknown Message Type", GET_U_1(bgp_header->bgp_type))); break; } } return; trunc: nd_print_trunc(ndo); } tcpdump-4.99.1/print-otv.c0000644000026300017510000000432314057477727013551 0ustar mcrmcr/* * 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, and (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. * 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. * * Original code by Francesco Fondelli (francesco dot fondelli, gmail dot com) */ /* \summary: Overlay Transport Virtualization (OTV) printer */ /* specification: draft-hasmit-otv-04 */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "extract.h" #define OTV_HDR_LEN 8 /* * OTV header, draft-hasmit-otv-04 * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |R|R|R|R|I|R|R|R| Overlay ID | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Instance ID | Reserved | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ void otv_print(netdissect_options *ndo, const u_char *bp, u_int len) { uint8_t flags; ndo->ndo_protocol = "otv"; ND_PRINT("OTV, "); if (len < OTV_HDR_LEN) { ND_PRINT("[length %u < %u]", len, OTV_HDR_LEN); goto invalid; } flags = GET_U_1(bp); ND_PRINT("flags [%s] (0x%02x), ", flags & 0x08 ? "I" : ".", flags); bp += 1; ND_PRINT("overlay %u, ", GET_BE_U_3(bp)); bp += 3; ND_PRINT("instance %u\n", GET_BE_U_3(bp)); bp += 3; /* Reserved */ ND_TCHECK_1(bp); bp += 1; ether_print(ndo, bp, len - OTV_HDR_LEN, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL); return; invalid: nd_print_invalid(ndo); ND_TCHECK_LEN(bp, len); } tcpdump-4.99.1/print-tipc.c0000644000026300017510000002616514057477727013710 0ustar mcrmcr/* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 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. */ /* \summary: Transparent Inter-Process Communication (TIPC) protocol printer */ /* * specification: * https://web.archive.org/web/20150302152944/http://tipc.sourceforge.net/doc/draft-spec-tipc-07.html * https://web.archive.org/web/20161025110514/http://tipc.sourceforge.net/doc/tipc_message_formats.html */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" #include "ethertype.h" #include "extract.h" #define TIPC_USER_LOW_IMPORTANCE 0 #define TIPC_USER_MEDIUM_IMPORTANCE 1 #define TIPC_USER_HIGH_IMPORTANCE 2 #define TIPC_USER_CRITICAL_IMPORTANCE 3 #define TIPC_USER_BCAST_PROTOCOL 5 #define TIPC_USER_MSG_BUNDLER 6 #define TIPC_USER_LINK_PROTOCOL 7 #define TIPC_USER_CONN_MANAGER 8 #define TIPC_USER_CHANGEOVER_PROTOCOL 10 #define TIPC_USER_NAME_DISTRIBUTOR 11 #define TIPC_USER_MSG_FRAGMENTER 12 #define TIPC_USER_LINK_CONFIG 13 #define TIPC_CONN_MSG 0 #define TIPC_DIRECT_MSG 1 #define TIPC_NAMED_MSG 2 #define TIPC_MCAST_MSG 3 #define TIPC_ZONE(addr) (((addr) >> 24) & 0xFF) #define TIPC_CLUSTER(addr) (((addr) >> 12) & 0xFFF) #define TIPC_NODE(addr) (((addr) >> 0) & 0xFFF) struct tipc_pkthdr { nd_uint32_t w0; nd_uint32_t w1; }; #define TIPC_VER(w0) (((w0) >> 29) & 0x07) #define TIPC_USER(w0) (((w0) >> 25) & 0x0F) #define TIPC_HSIZE(w0) (((w0) >> 21) & 0x0F) #define TIPC_MSIZE(w0) (((w0) >> 0) & 0x1FFFF) #define TIPC_MTYPE(w1) (((w1) >> 29) & 0x07) #define TIPC_BROADCAST_ACK(w1) (((w1) >> 0) & 0xFFFF) #define TIPC_LINK_ACK(w2) (((w2) >> 16) & 0xFFFF) #define TIPC_LINK_SEQ(w2) (((w2) >> 0) & 0xFFFF) static const struct tok tipcuser_values[] = { { TIPC_USER_LOW_IMPORTANCE, "Low Importance Data payload" }, { TIPC_USER_MEDIUM_IMPORTANCE, "Medium Importance Data payload" }, { TIPC_USER_HIGH_IMPORTANCE, "High Importance Data payload" }, { TIPC_USER_CRITICAL_IMPORTANCE, "Critical Importance Data payload" }, { TIPC_USER_BCAST_PROTOCOL, "Broadcast Link Protocol internal" }, { TIPC_USER_MSG_BUNDLER, "Message Bundler Protocol internal" }, { TIPC_USER_LINK_PROTOCOL, "Link State Protocol internal" }, { TIPC_USER_CONN_MANAGER, "Connection Manager internal" }, { TIPC_USER_CHANGEOVER_PROTOCOL, "Link Changeover Protocol internal" }, { TIPC_USER_NAME_DISTRIBUTOR, "Name Table Update Protocol internal" }, { TIPC_USER_MSG_FRAGMENTER, "Message Fragmentation Protocol internal" }, { TIPC_USER_LINK_CONFIG, "Neighbor Detection Protocol internal" }, { 0, NULL } }; static const struct tok tipcmtype_values[] = { { TIPC_CONN_MSG, "CONN_MSG" }, { TIPC_DIRECT_MSG, "MCAST_MSG" }, { TIPC_NAMED_MSG, "NAMED_MSG" }, { TIPC_MCAST_MSG, "DIRECT_MSG" }, { 0, NULL } }; static const struct tok tipc_linkconf_mtype_values[] = { { 0, "Link request" }, { 1, "Link response" }, { 0, NULL } }; struct payload_tipc_pkthdr { nd_uint32_t w0; nd_uint32_t w1; nd_uint32_t w2; nd_uint32_t prev_node; nd_uint32_t orig_port; nd_uint32_t dest_port; nd_uint32_t orig_node; nd_uint32_t dest_node; nd_uint32_t name_type; nd_uint32_t w9; nd_uint32_t wA; }; struct internal_tipc_pkthdr { nd_uint32_t w0; nd_uint32_t w1; nd_uint32_t w2; nd_uint32_t prev_node; nd_uint32_t w4; nd_uint32_t w5; nd_uint32_t orig_node; nd_uint32_t dest_node; nd_uint32_t trans_seq; nd_uint32_t w9; }; #define TIPC_SEQ_GAP(w1) (((w1) >> 16) & 0x1FFF) #define TIPC_BC_GAP_AFTER(w2) (((w2) >> 16) & 0xFFFF) #define TIPC_BC_GAP_TO(w2) (((w2) >> 0) & 0xFFFF) #define TIPC_LAST_SENT_FRAG(w4) (((w4) >> 16) & 0xFFFF) #define TIPC_NEXT_SENT_FRAG(w4) (((w4) >> 0) & 0xFFFF) #define TIPC_SESS_NO(w5) (((w5) >> 16) & 0xFFFF) #define TIPC_MSG_CNT(w9) (((w9) >> 16) & 0xFFFF) #define TIPC_LINK_TOL(w9) (((w9) >> 0) & 0xFFFF) struct link_conf_tipc_pkthdr { nd_uint32_t w0; nd_uint32_t w1; nd_uint32_t dest_domain; nd_uint32_t prev_node; nd_uint32_t ntwrk_id; nd_uint32_t w5; nd_byte media_address[16]; }; #define TIPC_NODE_SIG(w1) (((w1) >> 0) & 0xFFFF) #define TIPC_MEDIA_ID(w5) (((w5) >> 0) & 0xFF) static void print_payload(netdissect_options *ndo, const struct payload_tipc_pkthdr *ap) { uint32_t w0, w1, w2; u_int user; u_int hsize; u_int msize; u_int mtype; u_int broadcast_ack; u_int link_ack; u_int link_seq; u_int prev_node; u_int orig_port; u_int dest_port; u_int orig_node; u_int dest_node; w0 = GET_BE_U_4(ap->w0); user = TIPC_USER(w0); hsize = TIPC_HSIZE(w0); msize = TIPC_MSIZE(w0); w1 = GET_BE_U_4(ap->w1); mtype = TIPC_MTYPE(w1); prev_node = GET_BE_U_4(ap->prev_node); orig_port = GET_BE_U_4(ap->orig_port); dest_port = GET_BE_U_4(ap->dest_port); if (hsize <= 6) { ND_PRINT("TIPC v%u.0 %u.%u.%u:%u > %u, headerlength %u bytes, MessageSize %u bytes, %s, messageType %s", TIPC_VER(w0), TIPC_ZONE(prev_node), TIPC_CLUSTER(prev_node), TIPC_NODE(prev_node), orig_port, dest_port, hsize*4, msize, tok2str(tipcuser_values, "unknown", user), tok2str(tipcmtype_values, "Unknown", mtype)); } else { orig_node = GET_BE_U_4(ap->orig_node); dest_node = GET_BE_U_4(ap->dest_node); ND_PRINT("TIPC v%u.0 %u.%u.%u:%u > %u.%u.%u:%u, headerlength %u bytes, MessageSize %u bytes, %s, messageType %s", TIPC_VER(w0), TIPC_ZONE(orig_node), TIPC_CLUSTER(orig_node), TIPC_NODE(orig_node), orig_port, TIPC_ZONE(dest_node), TIPC_CLUSTER(dest_node), TIPC_NODE(dest_node), dest_port, hsize*4, msize, tok2str(tipcuser_values, "unknown", user), tok2str(tipcmtype_values, "Unknown", mtype)); if (ndo->ndo_vflag) { broadcast_ack = TIPC_BROADCAST_ACK(w1); w2 = GET_BE_U_4(ap->w2); link_ack = TIPC_LINK_ACK(w2); link_seq = TIPC_LINK_SEQ(w2); ND_PRINT("\n\tPrevious Node %u.%u.%u, Broadcast Ack %u, Link Ack %u, Link Sequence %u", TIPC_ZONE(prev_node), TIPC_CLUSTER(prev_node), TIPC_NODE(prev_node), broadcast_ack, link_ack, link_seq); } } } static void print_internal(netdissect_options *ndo, const struct internal_tipc_pkthdr *ap) { uint32_t w0, w1, w2, w4, w5, w9; u_int user; u_int hsize; u_int msize; u_int mtype; u_int seq_gap; u_int broadcast_ack; u_int bc_gap_after; u_int bc_gap_to; u_int prev_node; u_int last_sent_frag; u_int next_sent_frag; u_int sess_no; u_int orig_node; u_int dest_node; u_int trans_seq; u_int msg_cnt; u_int link_tol; w0 = GET_BE_U_4(ap->w0); user = TIPC_USER(w0); hsize = TIPC_HSIZE(w0); msize = TIPC_MSIZE(w0); w1 = GET_BE_U_4(ap->w1); mtype = TIPC_MTYPE(w1); orig_node = GET_BE_U_4(ap->orig_node); dest_node = GET_BE_U_4(ap->dest_node); ND_PRINT("TIPC v%u.0 %u.%u.%u > %u.%u.%u, headerlength %u bytes, MessageSize %u bytes, %s, messageType %s (0x%08x)", TIPC_VER(w0), TIPC_ZONE(orig_node), TIPC_CLUSTER(orig_node), TIPC_NODE(orig_node), TIPC_ZONE(dest_node), TIPC_CLUSTER(dest_node), TIPC_NODE(dest_node), hsize*4, msize, tok2str(tipcuser_values, "unknown", user), tok2str(tipcmtype_values, "Unknown", mtype), w1); if (ndo->ndo_vflag) { seq_gap = TIPC_SEQ_GAP(w1); broadcast_ack = TIPC_BROADCAST_ACK(w1); w2 = GET_BE_U_4(ap->w2); bc_gap_after = TIPC_BC_GAP_AFTER(w2); bc_gap_to = TIPC_BC_GAP_TO(w2); prev_node = GET_BE_U_4(ap->prev_node); w4 = GET_BE_U_4(ap->w4); last_sent_frag = TIPC_LAST_SENT_FRAG(w4); next_sent_frag = TIPC_NEXT_SENT_FRAG(w4); w5 = GET_BE_U_4(ap->w5); sess_no = TIPC_SESS_NO(w5); trans_seq = GET_BE_U_4(ap->trans_seq); w9 = GET_BE_U_4(ap->w9); msg_cnt = TIPC_MSG_CNT(w9); link_tol = TIPC_LINK_TOL(w9); ND_PRINT("\n\tPrevious Node %u.%u.%u, Session No. %u, Broadcast Ack %u, Sequence Gap %u, Broadcast Gap After %u, Broadcast Gap To %u, Last Sent Packet No. %u, Next sent Packet No. %u, Transport Sequence %u, msg_count %u, Link Tolerance %u", TIPC_ZONE(prev_node), TIPC_CLUSTER(prev_node), TIPC_NODE(prev_node), sess_no, broadcast_ack, seq_gap, bc_gap_after, bc_gap_to, last_sent_frag, next_sent_frag, trans_seq, msg_cnt, link_tol); } } static void print_link_conf(netdissect_options *ndo, const struct link_conf_tipc_pkthdr *ap) { uint32_t w0, w1, w5; u_int user; u_int hsize; u_int msize; u_int mtype; u_int node_sig; u_int prev_node; u_int dest_domain; u_int ntwrk_id; u_int media_id; w0 = GET_BE_U_4(ap->w0); user = TIPC_USER(w0); hsize = TIPC_HSIZE(w0); msize = TIPC_MSIZE(w0); w1 = GET_BE_U_4(ap->w1); mtype = TIPC_MTYPE(w1); dest_domain = GET_BE_U_4(ap->dest_domain); prev_node = GET_BE_U_4(ap->prev_node); ND_PRINT("TIPC v%u.0 %u.%u.%u > %u.%u.%u, headerlength %u bytes, MessageSize %u bytes, %s, messageType %s", TIPC_VER(w0), TIPC_ZONE(prev_node), TIPC_CLUSTER(prev_node), TIPC_NODE(prev_node), TIPC_ZONE(dest_domain), TIPC_CLUSTER(dest_domain), TIPC_NODE(dest_domain), hsize*4, msize, tok2str(tipcuser_values, "unknown", user), tok2str(tipc_linkconf_mtype_values, "Unknown", mtype)); if (ndo->ndo_vflag) { node_sig = TIPC_NODE_SIG(w1); ntwrk_id = GET_BE_U_4(ap->ntwrk_id); w5 = GET_BE_U_4(ap->w5); media_id = TIPC_MEDIA_ID(w5); ND_PRINT("\n\tNodeSignature %u, network_id %u, media_id %u", node_sig, ntwrk_id, media_id); } } void tipc_print(netdissect_options *ndo, const u_char *bp, u_int length _U_, u_int caplen _U_) { const struct tipc_pkthdr *ap; uint32_t w0; u_int user; ndo->ndo_protocol = "tipc"; ap = (const struct tipc_pkthdr *)bp; w0 = GET_BE_U_4(ap->w0); user = TIPC_USER(w0); switch (user) { case TIPC_USER_LOW_IMPORTANCE: case TIPC_USER_MEDIUM_IMPORTANCE: case TIPC_USER_HIGH_IMPORTANCE: case TIPC_USER_CRITICAL_IMPORTANCE: case TIPC_USER_NAME_DISTRIBUTOR: case TIPC_USER_CONN_MANAGER: print_payload(ndo, (const struct payload_tipc_pkthdr *)bp); break; case TIPC_USER_LINK_CONFIG: print_link_conf(ndo, (const struct link_conf_tipc_pkthdr *)bp); break; case TIPC_USER_BCAST_PROTOCOL: case TIPC_USER_MSG_BUNDLER: case TIPC_USER_LINK_PROTOCOL: case TIPC_USER_CHANGEOVER_PROTOCOL: case TIPC_USER_MSG_FRAGMENTER: print_internal(ndo, (const struct internal_tipc_pkthdr *)bp); break; } } tcpdump-4.99.1/atime.awk0000644000026300017510000000102114057477727013236 0ustar mcrmcr$6 ~ /^ack/ && $5 !~ /[SFR]/ { # given a tcpdump ftp trace, output one line for each ack # in the form # # where is the time packet was acked (in seconds with # zero at time of first packet) and is the tcp sequence # number of the ack divided by 1024 (i.e., Kbytes acked). # # convert time to seconds n = split ($1,t,":") tim = t[1]*3600 + t[2]*60 + t[3] if (! tzero) { tzero = tim OFS = "\t" } # get packet sequence number printf "%7.2f\t%g\n", tim-tzero, $7/1024 } tcpdump-4.99.1/print-snmp.c0000644000026300017510000012444314057477734013722 0ustar mcrmcr/* * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 * John Robert LoVerso. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * * This implementation has been influenced by the CMU SNMP release, * by Steve Waldbusser. However, this shares no code with that system. * Additional ASN.1 insight gained from Marshall T. Rose's _The_Open_Book_. * Earlier forms of this implementation were derived and/or inspired by an * awk script originally written by C. Philip Wood of LANL (but later * heavily modified by John Robert LoVerso). The copyright notice for * that work is preserved below, even though it may not rightly apply * to this file. * * Support for SNMPv2c/SNMPv3 and the ability to link the module against * the libsmi was added by J. Schoenwaelder, Copyright (c) 1999. * * This started out as a very simple program, but the incremental decoding * (into the BE structure) complicated things. * # Los Alamos National Laboratory # # Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 # This software was produced under a U.S. Government contract # (W-7405-ENG-36) by Los Alamos National Laboratory, which is # operated by the University of California for the U.S. Department # of Energy. The U.S. Government is licensed to use, reproduce, # and distribute this software. Permission is granted to the # public to copy and use this software without charge, provided # that this Notice and any statement of authorship are reproduced # on all copies. Neither the Government nor the University makes # any warranty, express or implied, or assumes any liability or # responsibility for the use of this software. # @(#)snmp.awk.x 1.1 (LANL) 1/15/90 */ /* \summary: Simple Network Management Protocol (SNMP) printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include #include #ifdef USE_LIBSMI #include #endif #include "netdissect-ctype.h" #include "netdissect.h" #include "extract.h" #undef OPAQUE /* defined in */ /* * Universal ASN.1 types * (we only care about the tag values for those allowed in the Internet SMI) */ static const char *Universal[] = { "U-0", "Boolean", "Integer", #define INTEGER 2 "Bitstring", "String", #define STRING 4 "Null", #define ASN_NULL 5 "ObjID", #define OBJECTID 6 "ObjectDes", "U-8","U-9","U-10","U-11", /* 8-11 */ "U-12","U-13","U-14","U-15", /* 12-15 */ "Sequence", #define SEQUENCE 16 "Set" }; /* * Application-wide ASN.1 types from the Internet SMI and their tags */ static const char *Application[] = { "IpAddress", #define IPADDR 0 "Counter", #define COUNTER 1 "Gauge", #define GAUGE 2 "TimeTicks", #define TIMETICKS 3 "Opaque", #define OPAQUE 4 "C-5", "Counter64" #define COUNTER64 6 }; /* * Context-specific ASN.1 types for the SNMP PDUs and their tags */ static const char *Context[] = { "GetRequest", #define GETREQ 0 "GetNextRequest", #define GETNEXTREQ 1 "GetResponse", #define GETRESP 2 "SetRequest", #define SETREQ 3 "Trap", #define TRAP 4 "GetBulk", #define GETBULKREQ 5 "Inform", #define INFORMREQ 6 "V2Trap", #define V2TRAP 7 "Report" #define REPORT 8 }; #define NOTIFY_CLASS(x) (x == TRAP || x == V2TRAP || x == INFORMREQ) #define READ_CLASS(x) (x == GETREQ || x == GETNEXTREQ || x == GETBULKREQ) #define WRITE_CLASS(x) (x == SETREQ) #define RESPONSE_CLASS(x) (x == GETRESP) #define INTERNAL_CLASS(x) (x == REPORT) /* * Context-specific ASN.1 types for the SNMP Exceptions and their tags */ static const char *Exceptions[] = { "noSuchObject", #define NOSUCHOBJECT 0 "noSuchInstance", #define NOSUCHINSTANCE 1 "endOfMibView", #define ENDOFMIBVIEW 2 }; /* * Private ASN.1 types * The Internet SMI does not specify any */ static const char *Private[] = { "P-0" }; /* * error-status values for any SNMP PDU */ static const char *ErrorStatus[] = { "noError", "tooBig", "noSuchName", "badValue", "readOnly", "genErr", "noAccess", "wrongType", "wrongLength", "wrongEncoding", "wrongValue", "noCreation", "inconsistentValue", "resourceUnavailable", "commitFailed", "undoFailed", "authorizationError", "notWritable", "inconsistentName" }; #define DECODE_ErrorStatus(e) \ ( e >= 0 && (size_t)e < sizeof(ErrorStatus)/sizeof(ErrorStatus[0]) \ ? ErrorStatus[e] \ : (snprintf(errbuf, sizeof(errbuf), "err=%u", e), errbuf)) /* * generic-trap values in the SNMP Trap-PDU */ static const char *GenericTrap[] = { "coldStart", "warmStart", "linkDown", "linkUp", "authenticationFailure", "egpNeighborLoss", "enterpriseSpecific" #define GT_ENTERPRISE 6 }; #define DECODE_GenericTrap(t) \ ( t >= 0 && (size_t)t < sizeof(GenericTrap)/sizeof(GenericTrap[0]) \ ? GenericTrap[t] \ : (snprintf(buf, sizeof(buf), "gt=%d", t), buf)) /* * ASN.1 type class table * Ties together the preceding Universal, Application, Context, and Private * type definitions. */ #define defineCLASS(x) { "x", x, sizeof(x)/sizeof(x[0]) } /* not ANSI-C */ static const struct { const char *name; const char **Id; int numIDs; } Class[] = { defineCLASS(Universal), #define UNIVERSAL 0 defineCLASS(Application), #define APPLICATION 1 defineCLASS(Context), #define CONTEXT 2 defineCLASS(Private), #define PRIVATE 3 defineCLASS(Exceptions), #define EXCEPTIONS 4 }; /* * defined forms for ASN.1 types */ static const char *Form[] = { "Primitive", #define PRIMITIVE 0 "Constructed", #define CONSTRUCTED 1 }; /* * A structure for the OID tree for the compiled-in MIB. * This is stored as a general-order tree. */ static struct obj { const char *desc; /* name of object */ u_char oid; /* sub-id following parent */ u_char type; /* object type (unused) */ struct obj *child, *next; /* child and next sibling pointers */ } *objp = NULL; /* * Include the compiled in SNMP MIB. "mib.h" is produced by feeding * RFC-1156 format files into "makemib". "mib.h" MUST define at least * a value for `mibroot'. * * In particular, this is gross, as this is including initialized structures, * and by right shouldn't be an "include" file. */ #include "mib.h" /* * This defines a list of OIDs which will be abbreviated on output. * Currently, this includes the prefixes for the Internet MIB, the * private enterprises tree, and the experimental tree. */ #define OID_FIRST_OCTET(x, y) (((x)*40) + (y)) /* X.690 8.19.4 */ #ifndef NO_ABREV_MIB static const uint8_t mib_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 2, 1 }; #endif #ifndef NO_ABREV_ENTER static const uint8_t enterprises_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 4, 1 }; #endif #ifndef NO_ABREV_EXPERI static const uint8_t experimental_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 3 }; #endif #ifndef NO_ABBREV_SNMPMODS static const uint8_t snmpModules_oid[] = { OID_FIRST_OCTET(1, 3), 6, 1, 6, 3 }; #endif #define OBJ_ABBREV_ENTRY(prefix, obj) \ { prefix, &_ ## obj ## _obj, obj ## _oid, sizeof (obj ## _oid) } static const struct obj_abrev { const char *prefix; /* prefix for this abrev */ struct obj *node; /* pointer into object table */ const uint8_t *oid; /* ASN.1 encoded OID */ size_t oid_len; /* length of OID */ } obj_abrev_list[] = { #ifndef NO_ABREV_MIB /* .iso.org.dod.internet.mgmt.mib */ OBJ_ABBREV_ENTRY("", mib), #endif #ifndef NO_ABREV_ENTER /* .iso.org.dod.internet.private.enterprises */ OBJ_ABBREV_ENTRY("E:", enterprises), #endif #ifndef NO_ABREV_EXPERI /* .iso.org.dod.internet.experimental */ OBJ_ABBREV_ENTRY("X:", experimental), #endif #ifndef NO_ABBREV_SNMPMODS /* .iso.org.dod.internet.snmpV2.snmpModules */ OBJ_ABBREV_ENTRY("S:", snmpModules), #endif { 0,0,0,0 } }; /* * This is used in the OID print routine to walk down the object tree * rooted at `mibroot'. */ #define OBJ_PRINT(o, suppressdot) \ { \ if (objp) { \ do { \ if ((o) == objp->oid) \ break; \ } while ((objp = objp->next) != NULL); \ } \ if (objp) { \ ND_PRINT(suppressdot?"%s":".%s", objp->desc); \ objp = objp->child; \ } else \ ND_PRINT(suppressdot?"%u":".%u", (o)); \ } /* * This is the definition for the Any-Data-Type storage used purely for * temporary internal representation while decoding an ASN.1 data stream. */ struct be { uint32_t asnlen; union { const uint8_t *raw; int32_t integer; uint32_t uns; const u_char *str; uint64_t uns64; } data; u_short id; u_char form, class; /* tag info */ u_char type; #define BE_ANY 255 #define BE_NONE 0 #define BE_NULL 1 #define BE_OCTET 2 #define BE_OID 3 #define BE_INT 4 #define BE_UNS 5 #define BE_STR 6 #define BE_SEQ 7 #define BE_INETADDR 8 #define BE_PDU 9 #define BE_UNS64 10 #define BE_NOSUCHOBJECT 128 #define BE_NOSUCHINST 129 #define BE_ENDOFMIBVIEW 130 }; /* * SNMP versions recognized by this module */ static const char *SnmpVersion[] = { "SNMPv1", #define SNMP_VERSION_1 0 "SNMPv2c", #define SNMP_VERSION_2 1 "SNMPv2u", #define SNMP_VERSION_2U 2 "SNMPv3" #define SNMP_VERSION_3 3 }; /* * Defaults for SNMP PDU components */ #define DEF_COMMUNITY "public" /* * constants for ASN.1 decoding */ #define OIDMUX 40 #define ASNLEN_INETADDR 4 #define ASN_SHIFT7 7 #define ASN_SHIFT8 8 #define ASN_BIT8 0x80 #define ASN_LONGLEN 0x80 #define ASN_ID_BITS 0x1f #define ASN_FORM_BITS 0x20 #define ASN_FORM_SHIFT 5 #define ASN_CLASS_BITS 0xc0 #define ASN_CLASS_SHIFT 6 #define ASN_ID_EXT 0x1f /* extension ID in tag field */ /* * This decodes the next ASN.1 object in the stream pointed to by "p" * (and of real-length "len") and stores the intermediate data in the * provided BE object. * * This returns -l if it fails (i.e., the ASN.1 stream is not valid). * O/w, this returns the number of bytes parsed from "p". */ static int asn1_parse(netdissect_options *ndo, const u_char *p, u_int len, struct be *elem) { u_char form, class, id; u_int i, hdr; elem->asnlen = 0; elem->type = BE_ANY; if (len < 1) { ND_PRINT("[nothing to parse]"); return -1; } /* * it would be nice to use a bit field, but you can't depend on them. * +---+---+---+---+---+---+---+---+ * + class |frm| id | * +---+---+---+---+---+---+---+---+ * 7 6 5 4 3 2 1 0 */ id = GET_U_1(p) & ASN_ID_BITS; /* lower 5 bits, range 00-1f */ #ifdef notdef form = (GET_U_1(p) & 0xe0) >> 5; /* move upper 3 bits to lower 3 */ class = form >> 1; /* bits 7&6 -> bits 1&0, range 0-3 */ form &= 0x1; /* bit 5 -> bit 0, range 0-1 */ #else form = (u_char)(GET_U_1(p) & ASN_FORM_BITS) >> ASN_FORM_SHIFT; class = (u_char)(GET_U_1(p) & ASN_CLASS_BITS) >> ASN_CLASS_SHIFT; #endif elem->form = form; elem->class = class; elem->id = id; p++; len--; hdr = 1; /* extended tag field */ if (id == ASN_ID_EXT) { /* * The ID follows, as a sequence of octets with the * 8th bit set and the remaining 7 bits being * the next 7 bits of the value, terminated with * an octet with the 8th bit not set. * * First, assemble all the octets with the 8th * bit set. XXX - this doesn't handle a value * that won't fit in 32 bits. */ id = 0; while (GET_U_1(p) & ASN_BIT8) { if (len < 1) { ND_PRINT("[Xtagfield?]"); return -1; } id = (id << 7) | (GET_U_1(p) & ~ASN_BIT8); len--; hdr++; p++; } if (len < 1) { ND_PRINT("[Xtagfield?]"); return -1; } elem->id = id = (id << 7) | GET_U_1(p); --len; ++hdr; ++p; } if (len < 1) { ND_PRINT("[no asnlen]"); return -1; } elem->asnlen = GET_U_1(p); p++; len--; hdr++; if (elem->asnlen & ASN_BIT8) { uint32_t noct = elem->asnlen % ASN_BIT8; elem->asnlen = 0; if (len < noct) { ND_PRINT("[asnlen? %d<%d]", len, noct); return -1; } ND_TCHECK_LEN(p, noct); for (; noct != 0; len--, hdr++, noct--) { elem->asnlen = (elem->asnlen << ASN_SHIFT8) | GET_U_1(p); p++; } } if (len < elem->asnlen) { ND_PRINT("[len%dasnlen); return -1; } if (form >= sizeof(Form)/sizeof(Form[0])) { ND_PRINT("[form?%d]", form); return -1; } if (class >= sizeof(Class)/sizeof(Class[0])) { ND_PRINT("[class?%c/%d]", *Form[form], class); return -1; } if ((int)id >= Class[class].numIDs) { ND_PRINT("[id?%c/%s/%d]", *Form[form], Class[class].name, id); return -1; } ND_TCHECK_LEN(p, elem->asnlen); switch (form) { case PRIMITIVE: switch (class) { case UNIVERSAL: switch (id) { case STRING: elem->type = BE_STR; elem->data.str = p; break; case INTEGER: { int32_t data; elem->type = BE_INT; data = 0; if (elem->asnlen == 0) { ND_PRINT("[asnlen=0]"); return -1; } if (GET_U_1(p) & ASN_BIT8) /* negative */ data = -1; for (i = elem->asnlen; i != 0; p++, i--) data = (data << ASN_SHIFT8) | GET_U_1(p); elem->data.integer = data; break; } case OBJECTID: elem->type = BE_OID; elem->data.raw = (const uint8_t *)p; break; case ASN_NULL: elem->type = BE_NULL; elem->data.raw = NULL; break; default: elem->type = BE_OCTET; elem->data.raw = (const uint8_t *)p; ND_PRINT("[P/U/%s]", Class[class].Id[id]); break; } break; case APPLICATION: switch (id) { case IPADDR: elem->type = BE_INETADDR; elem->data.raw = (const uint8_t *)p; break; case COUNTER: case GAUGE: case TIMETICKS: { uint32_t data; elem->type = BE_UNS; data = 0; for (i = elem->asnlen; i != 0; p++, i--) data = (data << 8) + GET_U_1(p); elem->data.uns = data; break; } case COUNTER64: { uint64_t data64; elem->type = BE_UNS64; data64 = 0; for (i = elem->asnlen; i != 0; p++, i--) data64 = (data64 << 8) + GET_U_1(p); elem->data.uns64 = data64; break; } default: elem->type = BE_OCTET; elem->data.raw = (const uint8_t *)p; ND_PRINT("[P/A/%s]", Class[class].Id[id]); break; } break; case CONTEXT: switch (id) { case NOSUCHOBJECT: elem->type = BE_NOSUCHOBJECT; elem->data.raw = NULL; break; case NOSUCHINSTANCE: elem->type = BE_NOSUCHINST; elem->data.raw = NULL; break; case ENDOFMIBVIEW: elem->type = BE_ENDOFMIBVIEW; elem->data.raw = NULL; break; } break; default: ND_PRINT("[P/%s/%s]", Class[class].name, Class[class].Id[id]); elem->type = BE_OCTET; elem->data.raw = (const uint8_t *)p; break; } break; case CONSTRUCTED: switch (class) { case UNIVERSAL: switch (id) { case SEQUENCE: elem->type = BE_SEQ; elem->data.raw = (const uint8_t *)p; break; default: elem->type = BE_OCTET; elem->data.raw = (const uint8_t *)p; ND_PRINT("C/U/%s", Class[class].Id[id]); break; } break; case CONTEXT: elem->type = BE_PDU; elem->data.raw = (const uint8_t *)p; break; default: elem->type = BE_OCTET; elem->data.raw = (const uint8_t *)p; ND_PRINT("C/%s/%s", Class[class].name, Class[class].Id[id]); break; } break; } p += elem->asnlen; len -= elem->asnlen; return elem->asnlen + hdr; trunc: nd_print_trunc(ndo); return -1; } static int asn1_print_octets(netdissect_options *ndo, struct be *elem) { const u_char *p = (const u_char *)elem->data.raw; uint32_t asnlen = elem->asnlen; uint32_t i; ND_TCHECK_LEN(p, asnlen); for (i = asnlen; i != 0; p++, i--) ND_PRINT("_%.2x", GET_U_1(p)); return 0; trunc: nd_print_trunc(ndo); return -1; } static int asn1_print_string(netdissect_options *ndo, struct be *elem) { int printable = 1, first = 1; const u_char *p; uint32_t asnlen = elem->asnlen; uint32_t i; p = elem->data.str; ND_TCHECK_LEN(p, asnlen); for (i = asnlen; printable && i != 0; p++, i--) printable = ND_ASCII_ISPRINT(GET_U_1(p)); p = elem->data.str; if (printable) { ND_PRINT("\""); if (nd_printn(ndo, p, asnlen, ndo->ndo_snapend)) { ND_PRINT("\""); goto trunc; } ND_PRINT("\""); } else { for (i = asnlen; i != 0; p++, i--) { ND_PRINT(first ? "%.2x" : "_%.2x", GET_U_1(p)); first = 0; } } return 0; trunc: nd_print_trunc(ndo); return -1; } /* * Display the ASN.1 object represented by the BE object. * This used to be an integral part of asn1_parse() before the intermediate * BE form was added. */ static int asn1_print(netdissect_options *ndo, struct be *elem) { const u_char *p; uint32_t asnlen = elem->asnlen; uint32_t i; switch (elem->type) { case BE_OCTET: if (asn1_print_octets(ndo, elem) == -1) return -1; break; case BE_NULL: break; case BE_OID: { int o = 0, first = -1; p = (const u_char *)elem->data.raw; i = asnlen; if (!ndo->ndo_nflag && asnlen > 2) { const struct obj_abrev *a = &obj_abrev_list[0]; for (; a->node; a++) { if (i < a->oid_len) continue; if (!ND_TTEST_LEN(p, a->oid_len)) continue; if (memcmp(a->oid, p, a->oid_len) == 0) { objp = a->node->child; i -= a->oid_len; p += a->oid_len; ND_PRINT("%s", a->prefix); first = 1; break; } } } for (; i != 0; p++, i--) { o = (o << ASN_SHIFT7) + (GET_U_1(p) & ~ASN_BIT8); if (GET_U_1(p) & ASN_LONGLEN) continue; /* * first subitem encodes two items with * 1st*OIDMUX+2nd * (see X.690:1997 clause 8.19 for the details) */ if (first < 0) { int s; if (!ndo->ndo_nflag) objp = mibroot; first = 0; s = o / OIDMUX; if (s > 2) s = 2; OBJ_PRINT(s, first); o -= s * OIDMUX; } OBJ_PRINT(o, first); if (--first < 0) first = 0; o = 0; } break; } case BE_INT: ND_PRINT("%d", elem->data.integer); break; case BE_UNS: ND_PRINT("%u", elem->data.uns); break; case BE_UNS64: ND_PRINT("%" PRIu64, elem->data.uns64); break; case BE_STR: if (asn1_print_string(ndo, elem) == -1) return -1; break; case BE_SEQ: ND_PRINT("Seq(%u)", elem->asnlen); break; case BE_INETADDR: if (asnlen != ASNLEN_INETADDR) ND_PRINT("[inetaddr len!=%d]", ASNLEN_INETADDR); p = (const u_char *)elem->data.raw; ND_TCHECK_LEN(p, asnlen); for (i = asnlen; i != 0; p++, i--) { ND_PRINT((i == asnlen) ? "%u" : ".%u", GET_U_1(p)); } break; case BE_NOSUCHOBJECT: case BE_NOSUCHINST: case BE_ENDOFMIBVIEW: ND_PRINT("[%s]", Class[EXCEPTIONS].Id[elem->id]); break; case BE_PDU: ND_PRINT("%s(%u)", Class[CONTEXT].Id[elem->id], elem->asnlen); break; case BE_ANY: ND_PRINT("[BE_ANY!?]"); break; default: ND_PRINT("[be!?]"); break; } return 0; trunc: nd_print_trunc(ndo); return -1; } #ifdef notdef /* * This is a brute force ASN.1 printer: recurses to dump an entire structure. * This will work for any ASN.1 stream, not just an SNMP PDU. * * By adding newlines and spaces at the correct places, this would print in * Rose-Normal-Form. * * This is not currently used. */ static void asn1_decode(u_char *p, u_int length) { struct be elem; int i = 0; while (i >= 0 && length > 0) { i = asn1_parse(ndo, p, length, &elem); if (i >= 0) { ND_PRINT(" "); if (asn1_print(ndo, &elem) < 0) return; if (elem.type == BE_SEQ || elem.type == BE_PDU) { ND_PRINT(" {"); asn1_decode(elem.data.raw, elem.asnlen); ND_PRINT(" }"); } length -= i; p += i; } } } #endif #ifdef USE_LIBSMI struct smi2be { SmiBasetype basetype; int be; }; static const struct smi2be smi2betab[] = { { SMI_BASETYPE_INTEGER32, BE_INT }, { SMI_BASETYPE_OCTETSTRING, BE_STR }, { SMI_BASETYPE_OCTETSTRING, BE_INETADDR }, { SMI_BASETYPE_OBJECTIDENTIFIER, BE_OID }, { SMI_BASETYPE_UNSIGNED32, BE_UNS }, { SMI_BASETYPE_INTEGER64, BE_NONE }, { SMI_BASETYPE_UNSIGNED64, BE_UNS64 }, { SMI_BASETYPE_FLOAT32, BE_NONE }, { SMI_BASETYPE_FLOAT64, BE_NONE }, { SMI_BASETYPE_FLOAT128, BE_NONE }, { SMI_BASETYPE_ENUM, BE_INT }, { SMI_BASETYPE_BITS, BE_STR }, { SMI_BASETYPE_UNKNOWN, BE_NONE } }; static int smi_decode_oid(netdissect_options *ndo, struct be *elem, unsigned int *oid, unsigned int oidsize, unsigned int *oidlen) { const u_char *p = (const u_char *)elem->data.raw; uint32_t asnlen = elem->asnlen; uint32_t i = asnlen; int o = 0, first = -1; unsigned int firstval; for (*oidlen = 0; i != 0; p++, i--) { o = (o << ASN_SHIFT7) + (GET_U_1(p) & ~ASN_BIT8); if (GET_U_1(p) & ASN_LONGLEN) continue; /* * first subitem encodes two items with 1st*OIDMUX+2nd * (see X.690:1997 clause 8.19 for the details) */ if (first < 0) { first = 0; firstval = o / OIDMUX; if (firstval > 2) firstval = 2; o -= firstval * OIDMUX; if (*oidlen < oidsize) { oid[(*oidlen)++] = firstval; } } if (*oidlen < oidsize) { oid[(*oidlen)++] = o; } o = 0; } return 0; } static int smi_check_type(SmiBasetype basetype, int be) { int i; for (i = 0; smi2betab[i].basetype != SMI_BASETYPE_UNKNOWN; i++) { if (smi2betab[i].basetype == basetype && smi2betab[i].be == be) { return 1; } } return 0; } static int smi_check_a_range(SmiType *smiType, SmiRange *smiRange, struct be *elem) { int ok = 1; switch (smiType->basetype) { case SMI_BASETYPE_OBJECTIDENTIFIER: case SMI_BASETYPE_OCTETSTRING: if (smiRange->minValue.value.unsigned32 == smiRange->maxValue.value.unsigned32) { ok = (elem->asnlen == smiRange->minValue.value.unsigned32); } else { ok = (elem->asnlen >= smiRange->minValue.value.unsigned32 && elem->asnlen <= smiRange->maxValue.value.unsigned32); } break; case SMI_BASETYPE_INTEGER32: ok = (elem->data.integer >= smiRange->minValue.value.integer32 && elem->data.integer <= smiRange->maxValue.value.integer32); break; case SMI_BASETYPE_UNSIGNED32: ok = (elem->data.uns >= smiRange->minValue.value.unsigned32 && elem->data.uns <= smiRange->maxValue.value.unsigned32); break; case SMI_BASETYPE_UNSIGNED64: /* XXX */ break; /* case SMI_BASETYPE_INTEGER64: SMIng */ /* case SMI_BASETYPE_FLOAT32: SMIng */ /* case SMI_BASETYPE_FLOAT64: SMIng */ /* case SMI_BASETYPE_FLOAT128: SMIng */ case SMI_BASETYPE_ENUM: case SMI_BASETYPE_BITS: case SMI_BASETYPE_UNKNOWN: ok = 1; break; default: ok = 0; break; } return ok; } static int smi_check_range(SmiType *smiType, struct be *elem) { SmiRange *smiRange; int ok = 1; for (smiRange = smiGetFirstRange(smiType); smiRange; smiRange = smiGetNextRange(smiRange)) { ok = smi_check_a_range(smiType, smiRange, elem); if (ok) { break; } } if (ok) { SmiType *parentType; parentType = smiGetParentType(smiType); if (parentType) { ok = smi_check_range(parentType, elem); } } return ok; } static SmiNode * smi_print_variable(netdissect_options *ndo, struct be *elem, int *status) { unsigned int oid[128], oidlen; SmiNode *smiNode = NULL; unsigned int i; if (!nd_smi_module_loaded) { *status = asn1_print(ndo, elem); return NULL; } *status = smi_decode_oid(ndo, elem, oid, sizeof(oid) / sizeof(unsigned int), &oidlen); if (*status < 0) return NULL; smiNode = smiGetNodeByOID(oidlen, oid); if (! smiNode) { *status = asn1_print(ndo, elem); return NULL; } if (ndo->ndo_vflag) { ND_PRINT("%s::", smiGetNodeModule(smiNode)->name); } ND_PRINT("%s", smiNode->name); if (smiNode->oidlen < oidlen) { for (i = smiNode->oidlen; i < oidlen; i++) { ND_PRINT(".%u", oid[i]); } } *status = 0; return smiNode; } static int smi_print_value(netdissect_options *ndo, SmiNode *smiNode, u_short pduid, struct be *elem) { unsigned int i, oid[128], oidlen; SmiType *smiType; SmiNamedNumber *nn; int done = 0; if (! smiNode || ! (smiNode->nodekind & (SMI_NODEKIND_SCALAR | SMI_NODEKIND_COLUMN))) { return asn1_print(ndo, elem); } if (elem->type == BE_NOSUCHOBJECT || elem->type == BE_NOSUCHINST || elem->type == BE_ENDOFMIBVIEW) { return asn1_print(ndo, elem); } if (NOTIFY_CLASS(pduid) && smiNode->access < SMI_ACCESS_NOTIFY) { ND_PRINT("[notNotifyable]"); } if (READ_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_ONLY) { ND_PRINT("[notReadable]"); } if (WRITE_CLASS(pduid) && smiNode->access < SMI_ACCESS_READ_WRITE) { ND_PRINT("[notWritable]"); } if (RESPONSE_CLASS(pduid) && smiNode->access == SMI_ACCESS_NOT_ACCESSIBLE) { ND_PRINT("[noAccess]"); } smiType = smiGetNodeType(smiNode); if (! smiType) { return asn1_print(ndo, elem); } if (! smi_check_type(smiType->basetype, elem->type)) { ND_PRINT("[wrongType]"); } if (! smi_check_range(smiType, elem)) { ND_PRINT("[outOfRange]"); } /* resolve bits to named bits */ /* check whether instance identifier is valid */ /* apply display hints (integer, octetstring) */ /* convert instance identifier to index type values */ switch (elem->type) { case BE_OID: if (smiType->basetype == SMI_BASETYPE_BITS) { /* print bit labels */ } else { if (nd_smi_module_loaded && smi_decode_oid(ndo, elem, oid, sizeof(oid)/sizeof(unsigned int), &oidlen) == 0) { smiNode = smiGetNodeByOID(oidlen, oid); if (smiNode) { if (ndo->ndo_vflag) { ND_PRINT("%s::", smiGetNodeModule(smiNode)->name); } ND_PRINT("%s", smiNode->name); if (smiNode->oidlen < oidlen) { for (i = smiNode->oidlen; i < oidlen; i++) { ND_PRINT(".%u", oid[i]); } } done++; } } } break; case BE_INT: if (smiType->basetype == SMI_BASETYPE_ENUM) { for (nn = smiGetFirstNamedNumber(smiType); nn; nn = smiGetNextNamedNumber(nn)) { if (nn->value.value.integer32 == elem->data.integer) { ND_PRINT("%s", nn->name); ND_PRINT("(%d)", elem->data.integer); done++; break; } } } break; } if (! done) { return asn1_print(ndo, elem); } return 0; } #endif /* * General SNMP header * SEQUENCE { * version INTEGER {version-1(0)}, * community OCTET STRING, * data ANY -- PDUs * } * PDUs for all but Trap: (see rfc1157 from page 15 on) * SEQUENCE { * request-id INTEGER, * error-status INTEGER, * error-index INTEGER, * varbindlist SEQUENCE OF * SEQUENCE { * name ObjectName, * value ObjectValue * } * } * PDU for Trap: * SEQUENCE { * enterprise OBJECT IDENTIFIER, * agent-addr NetworkAddress, * generic-trap INTEGER, * specific-trap INTEGER, * time-stamp TimeTicks, * varbindlist SEQUENCE OF * SEQUENCE { * name ObjectName, * value ObjectValue * } * } */ /* * Decode SNMP varBind */ static void varbind_print(netdissect_options *ndo, u_short pduid, const u_char *np, u_int length) { struct be elem; int count = 0, ind; #ifdef USE_LIBSMI SmiNode *smiNode = NULL; #endif int status; /* Sequence of varBind */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_SEQ) { ND_PRINT("[!SEQ of varbind]"); asn1_print(ndo, &elem); return; } if ((u_int)count < length) ND_PRINT("[%d extra after SEQ of varbind]", length - count); /* descend */ length = elem.asnlen; np = (const u_char *)elem.data.raw; for (ind = 1; length > 0; ind++) { const u_char *vbend; u_int vblength; ND_PRINT(" "); /* Sequence */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_SEQ) { ND_PRINT("[!varbind]"); asn1_print(ndo, &elem); return; } vbend = np + count; vblength = length - count; /* descend */ length = elem.asnlen; np = (const u_char *)elem.data.raw; /* objName (OID) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_OID) { ND_PRINT("[objName!=OID]"); asn1_print(ndo, &elem); return; } #ifdef USE_LIBSMI smiNode = smi_print_variable(ndo, &elem, &status); #else status = asn1_print(ndo, &elem); #endif if (status < 0) return; length -= count; np += count; if (pduid != GETREQ && pduid != GETNEXTREQ && pduid != GETBULKREQ) ND_PRINT("="); /* objVal (ANY) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (pduid == GETREQ || pduid == GETNEXTREQ || pduid == GETBULKREQ) { if (elem.type != BE_NULL) { ND_PRINT("[objVal!=NULL]"); if (asn1_print(ndo, &elem) < 0) return; } } else { if (elem.type != BE_NULL) { #ifdef USE_LIBSMI status = smi_print_value(ndo, smiNode, pduid, &elem); #else status = asn1_print(ndo, &elem); #endif } if (status < 0) return; } length = vblength; np = vbend; } } /* * Decode SNMP PDUs: GetRequest, GetNextRequest, GetResponse, SetRequest, * GetBulk, Inform, V2Trap, and Report */ static void snmppdu_print(netdissect_options *ndo, u_short pduid, const u_char *np, u_int length) { struct be elem; int count = 0, error_status; /* reqId (Integer) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_INT) { ND_PRINT("[reqId!=INT]"); asn1_print(ndo, &elem); return; } if (ndo->ndo_vflag) ND_PRINT("R=%d ", elem.data.integer); length -= count; np += count; /* errorStatus (Integer) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_INT) { ND_PRINT("[errorStatus!=INT]"); asn1_print(ndo, &elem); return; } error_status = 0; if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT) && elem.data.integer != 0) { char errbuf[20]; ND_PRINT("[errorStatus(%s)!=0]", DECODE_ErrorStatus(elem.data.integer)); } else if (pduid == GETBULKREQ) { ND_PRINT(" N=%d", elem.data.integer); } else if (elem.data.integer != 0) { char errbuf[20]; ND_PRINT(" %s", DECODE_ErrorStatus(elem.data.integer)); error_status = elem.data.integer; } length -= count; np += count; /* errorIndex (Integer) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_INT) { ND_PRINT("[errorIndex!=INT]"); asn1_print(ndo, &elem); return; } if ((pduid == GETREQ || pduid == GETNEXTREQ || pduid == SETREQ || pduid == INFORMREQ || pduid == V2TRAP || pduid == REPORT) && elem.data.integer != 0) ND_PRINT("[errorIndex(%d)!=0]", elem.data.integer); else if (pduid == GETBULKREQ) ND_PRINT(" M=%d", elem.data.integer); else if (elem.data.integer != 0) { if (!error_status) ND_PRINT("[errorIndex(%d) w/o errorStatus]", elem.data.integer); else ND_PRINT("@%d", elem.data.integer); } else if (error_status) { ND_PRINT("[errorIndex==0]"); } length -= count; np += count; varbind_print(ndo, pduid, np, length); } /* * Decode SNMP Trap PDU */ static void trappdu_print(netdissect_options *ndo, const u_char *np, u_int length) { struct be elem; int count = 0, generic; ND_PRINT(" "); /* enterprise (oid) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_OID) { ND_PRINT("[enterprise!=OID]"); asn1_print(ndo, &elem); return; } if (asn1_print(ndo, &elem) < 0) return; length -= count; np += count; ND_PRINT(" "); /* agent-addr (inetaddr) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_INETADDR) { ND_PRINT("[agent-addr!=INETADDR]"); asn1_print(ndo, &elem); return; } if (asn1_print(ndo, &elem) < 0) return; length -= count; np += count; /* generic-trap (Integer) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_INT) { ND_PRINT("[generic-trap!=INT]"); asn1_print(ndo, &elem); return; } generic = elem.data.integer; { char buf[20]; ND_PRINT(" %s", DECODE_GenericTrap(generic)); } length -= count; np += count; /* specific-trap (Integer) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_INT) { ND_PRINT("[specific-trap!=INT]"); asn1_print(ndo, &elem); return; } if (generic != GT_ENTERPRISE) { if (elem.data.integer != 0) ND_PRINT("[specific-trap(%d)!=0]", elem.data.integer); } else ND_PRINT(" s=%d", elem.data.integer); length -= count; np += count; ND_PRINT(" "); /* time-stamp (TimeTicks) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_UNS) { /* XXX */ ND_PRINT("[time-stamp!=TIMETICKS]"); asn1_print(ndo, &elem); return; } if (asn1_print(ndo, &elem) < 0) return; length -= count; np += count; varbind_print(ndo, TRAP, np, length); } /* * Decode arbitrary SNMP PDUs. */ static void pdu_print(netdissect_options *ndo, const u_char *np, u_int length, int version) { struct be pdu; int count = 0; /* PDU (Context) */ if ((count = asn1_parse(ndo, np, length, &pdu)) < 0) return; if (pdu.type != BE_PDU) { ND_PRINT("[no PDU]"); return; } if ((u_int)count < length) ND_PRINT("[%d extra after PDU]", length - count); if (ndo->ndo_vflag) { ND_PRINT("{ "); } if (asn1_print(ndo, &pdu) < 0) return; ND_PRINT(" "); /* descend into PDU */ length = pdu.asnlen; np = (const u_char *)pdu.data.raw; if (version == SNMP_VERSION_1 && (pdu.id == GETBULKREQ || pdu.id == INFORMREQ || pdu.id == V2TRAP || pdu.id == REPORT)) { ND_PRINT("[v2 PDU in v1 message]"); return; } if (version == SNMP_VERSION_2 && pdu.id == TRAP) { ND_PRINT("[v1 PDU in v2 message]"); return; } switch (pdu.id) { case TRAP: trappdu_print(ndo, np, length); break; case GETREQ: case GETNEXTREQ: case GETRESP: case SETREQ: case GETBULKREQ: case INFORMREQ: case V2TRAP: case REPORT: snmppdu_print(ndo, pdu.id, np, length); break; } if (ndo->ndo_vflag) { ND_PRINT(" } "); } } /* * Decode a scoped SNMP PDU. */ static void scopedpdu_print(netdissect_options *ndo, const u_char *np, u_int length, int version) { struct be elem; int count = 0; /* Sequence */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_SEQ) { ND_PRINT("[!scoped PDU]"); asn1_print(ndo, &elem); return; } length = elem.asnlen; np = (const u_char *)elem.data.raw; /* contextEngineID (OCTET STRING) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_STR) { ND_PRINT("[contextEngineID!=STR]"); asn1_print(ndo, &elem); return; } length -= count; np += count; ND_PRINT("E="); if (asn1_print_octets(ndo, &elem) == -1) return; ND_PRINT(" "); /* contextName (OCTET STRING) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_STR) { ND_PRINT("[contextName!=STR]"); asn1_print(ndo, &elem); return; } length -= count; np += count; ND_PRINT("C="); if (asn1_print_string(ndo, &elem) == -1) return; ND_PRINT(" "); pdu_print(ndo, np, length, version); } /* * Decode SNMP Community Header (SNMPv1 and SNMPv2c) */ static void community_print(netdissect_options *ndo, const u_char *np, u_int length, int version) { struct be elem; int count = 0; /* Community (String) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_STR) { ND_PRINT("[comm!=STR]"); asn1_print(ndo, &elem); return; } /* default community */ if (!(elem.asnlen == sizeof(DEF_COMMUNITY) - 1 && strncmp((const char *)elem.data.str, DEF_COMMUNITY, sizeof(DEF_COMMUNITY) - 1) == 0)) { /* ! "public" */ ND_PRINT("C="); if (asn1_print_string(ndo, &elem) == -1) return; ND_PRINT(" "); } length -= count; np += count; pdu_print(ndo, np, length, version); } /* * Decode SNMPv3 User-based Security Message Header (SNMPv3) */ static void usm_print(netdissect_options *ndo, const u_char *np, u_int length) { struct be elem; int count = 0; /* Sequence */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_SEQ) { ND_PRINT("[!usm]"); asn1_print(ndo, &elem); return; } length = elem.asnlen; np = (const u_char *)elem.data.raw; /* msgAuthoritativeEngineID (OCTET STRING) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_STR) { ND_PRINT("[msgAuthoritativeEngineID!=STR]"); asn1_print(ndo, &elem); return; } length -= count; np += count; /* msgAuthoritativeEngineBoots (INTEGER) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_INT) { ND_PRINT("[msgAuthoritativeEngineBoots!=INT]"); asn1_print(ndo, &elem); return; } if (ndo->ndo_vflag) ND_PRINT("B=%d ", elem.data.integer); length -= count; np += count; /* msgAuthoritativeEngineTime (INTEGER) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_INT) { ND_PRINT("[msgAuthoritativeEngineTime!=INT]"); asn1_print(ndo, &elem); return; } if (ndo->ndo_vflag) ND_PRINT("T=%d ", elem.data.integer); length -= count; np += count; /* msgUserName (OCTET STRING) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_STR) { ND_PRINT("[msgUserName!=STR]"); asn1_print(ndo, &elem); return; } length -= count; np += count; ND_PRINT("U="); if (asn1_print_string(ndo, &elem) == -1) return; ND_PRINT(" "); /* msgAuthenticationParameters (OCTET STRING) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_STR) { ND_PRINT("[msgAuthenticationParameters!=STR]"); asn1_print(ndo, &elem); return; } length -= count; np += count; /* msgPrivacyParameters (OCTET STRING) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_STR) { ND_PRINT("[msgPrivacyParameters!=STR]"); asn1_print(ndo, &elem); return; } length -= count; np += count; if ((u_int)count < length) ND_PRINT("[%d extra after usm SEQ]", length - count); } /* * Decode SNMPv3 Message Header (SNMPv3) */ static void v3msg_print(netdissect_options *ndo, const u_char *np, u_int length) { struct be elem; int count = 0; u_char flags; int model; const u_char *xnp = np; int xlength = length; /* Sequence */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_SEQ) { ND_PRINT("[!message]"); asn1_print(ndo, &elem); return; } length = elem.asnlen; np = (const u_char *)elem.data.raw; if (ndo->ndo_vflag) { ND_PRINT("{ "); } /* msgID (INTEGER) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_INT) { ND_PRINT("[msgID!=INT]"); asn1_print(ndo, &elem); return; } length -= count; np += count; /* msgMaxSize (INTEGER) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_INT) { ND_PRINT("[msgMaxSize!=INT]"); asn1_print(ndo, &elem); return; } length -= count; np += count; /* msgFlags (OCTET STRING) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_STR) { ND_PRINT("[msgFlags!=STR]"); asn1_print(ndo, &elem); return; } if (elem.asnlen != 1) { ND_PRINT("[msgFlags size %d]", elem.asnlen); return; } flags = GET_U_1(elem.data.str); if (flags != 0x00 && flags != 0x01 && flags != 0x03 && flags != 0x04 && flags != 0x05 && flags != 0x07) { ND_PRINT("[msgFlags=0x%02X]", flags); return; } length -= count; np += count; ND_PRINT("F=%s%s%s ", flags & 0x01 ? "a" : "", flags & 0x02 ? "p" : "", flags & 0x04 ? "r" : ""); /* msgSecurityModel (INTEGER) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_INT) { ND_PRINT("[msgSecurityModel!=INT]"); asn1_print(ndo, &elem); return; } model = elem.data.integer; length -= count; np += count; if ((u_int)count < length) ND_PRINT("[%d extra after message SEQ]", length - count); if (ndo->ndo_vflag) { ND_PRINT("} "); } if (model == 3) { if (ndo->ndo_vflag) { ND_PRINT("{ USM "); } } else { ND_PRINT("[security model %d]", model); return; } np = xnp + (np - xnp); length = xlength - (np - xnp); /* msgSecurityParameters (OCTET STRING) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_STR) { ND_PRINT("[msgSecurityParameters!=STR]"); asn1_print(ndo, &elem); return; } length -= count; np += count; if (model == 3) { usm_print(ndo, elem.data.str, elem.asnlen); if (ndo->ndo_vflag) { ND_PRINT("} "); } } if (ndo->ndo_vflag) { ND_PRINT("{ ScopedPDU "); } scopedpdu_print(ndo, np, length, 3); if (ndo->ndo_vflag) { ND_PRINT("} "); } } /* * Decode SNMP header and pass on to PDU printing routines */ void snmp_print(netdissect_options *ndo, const u_char *np, u_int length) { struct be elem; int count = 0; int version = 0; ndo->ndo_protocol = "snmp"; ND_PRINT(" "); /* initial Sequence */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_SEQ) { ND_PRINT("[!init SEQ]"); asn1_print(ndo, &elem); return; } if ((u_int)count < length) ND_PRINT("[%d extra after iSEQ]", length - count); /* descend */ length = elem.asnlen; np = (const u_char *)elem.data.raw; /* Version (INTEGER) */ if ((count = asn1_parse(ndo, np, length, &elem)) < 0) return; if (elem.type != BE_INT) { ND_PRINT("[version!=INT]"); asn1_print(ndo, &elem); return; } switch (elem.data.integer) { case SNMP_VERSION_1: case SNMP_VERSION_2: case SNMP_VERSION_3: if (ndo->ndo_vflag) ND_PRINT("{ %s ", SnmpVersion[elem.data.integer]); break; default: ND_PRINT("SNMP [version = %d]", elem.data.integer); return; } version = elem.data.integer; length -= count; np += count; switch (version) { case SNMP_VERSION_1: case SNMP_VERSION_2: community_print(ndo, np, length, version); break; case SNMP_VERSION_3: v3msg_print(ndo, np, length); break; default: ND_PRINT("[version = %d]", elem.data.integer); break; } if (ndo->ndo_vflag) { ND_PRINT("} "); } } tcpdump-4.99.1/print-usb.c0000644000026300017510000001625714057477727013543 0ustar mcrmcr/* * Copyright 2009 Bert Vermeulen * * 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 Paolo Abeni.'' * The name of author may not 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. * * Support for USB packets * */ /* \summary: USB printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "extract.h" #ifdef DLT_USB_LINUX /* * possible transfer mode */ #define URB_TRANSFER_IN 0x80 #define URB_ISOCHRONOUS 0x0 #define URB_INTERRUPT 0x1 #define URB_CONTROL 0x2 #define URB_BULK 0x3 /* * possible event type */ #define URB_SUBMIT 'S' #define URB_COMPLETE 'C' #define URB_ERROR 'E' /* * USB setup header as defined in USB specification. * Appears at the front of each Control S-type packet in DLT_USB captures. */ typedef struct _usb_setup { nd_uint8_t bmRequestType; nd_uint8_t bRequest; nd_uint16_t wValue; nd_uint16_t wIndex; nd_uint16_t wLength; } pcap_usb_setup; /* * Information from the URB for Isochronous transfers. */ typedef struct _iso_rec { nd_int32_t error_count; nd_int32_t numdesc; } iso_rec; /* * Header prepended by linux kernel to each event. * Appears at the front of each packet in DLT_USB_LINUX captures. */ typedef struct _usb_header { nd_uint64_t id; nd_uint8_t event_type; nd_uint8_t transfer_type; nd_uint8_t endpoint_number; nd_uint8_t device_address; nd_uint16_t bus_id; nd_uint8_t setup_flag;/*if !=0 the urb setup header is not present*/ nd_uint8_t data_flag; /*if !=0 no urb data is present*/ nd_int64_t ts_sec; nd_int32_t ts_usec; nd_int32_t status; nd_uint32_t urb_len; nd_uint32_t data_len; /* amount of urb data really present in this event*/ pcap_usb_setup setup; } pcap_usb_header; /* * Header prepended by linux kernel to each event for the 2.6.31 * and later kernels; for the 2.6.21 through 2.6.30 kernels, the * "iso_rec" information, and the fields starting with "interval" * are zeroed-out padding fields. * * Appears at the front of each packet in DLT_USB_LINUX_MMAPPED captures. */ typedef struct _usb_header_mmapped { nd_uint64_t id; nd_uint8_t event_type; nd_uint8_t transfer_type; nd_uint8_t endpoint_number; nd_uint8_t device_address; nd_uint16_t bus_id; nd_uint8_t setup_flag;/*if !=0 the urb setup header is not present*/ nd_uint8_t data_flag; /*if !=0 no urb data is present*/ nd_int64_t ts_sec; nd_int32_t ts_usec; nd_int32_t status; nd_uint32_t urb_len; nd_uint32_t data_len; /* amount of urb data really present in this event*/ union { pcap_usb_setup setup; iso_rec iso; } s; nd_int32_t interval; /* for Interrupt and Isochronous events */ nd_int32_t start_frame; /* for Isochronous events */ nd_uint32_t xfer_flags; /* copy of URB's transfer flags */ nd_uint32_t ndesc; /* number of isochronous descriptors */ } pcap_usb_header_mmapped; /* * Isochronous descriptors; for isochronous transfers there might be * one or more of these at the beginning of the packet data. The * number of descriptors is given by the "ndesc" field in the header; * as indicated, in older kernels that don't put the descriptors at * the beginning of the packet, that field is zeroed out, so that field * can be trusted even in captures from older kernels. */ typedef struct _usb_isodesc { nd_int32_t status; nd_uint32_t offset; nd_uint32_t len; nd_byte pad[4]; } usb_isodesc; /* returns direction: 1=inbound 2=outbound -1=invalid */ static int get_direction(int transfer_type, int event_type) { int direction; direction = -1; switch(transfer_type){ case URB_BULK: case URB_CONTROL: case URB_ISOCHRONOUS: switch(event_type) { case URB_SUBMIT: direction = 2; break; case URB_COMPLETE: case URB_ERROR: direction = 1; break; default: direction = -1; } break; case URB_INTERRUPT: switch(event_type) { case URB_SUBMIT: direction = 1; break; case URB_COMPLETE: case URB_ERROR: direction = 2; break; default: direction = -1; } break; default: direction = -1; } return direction; } static void usb_header_print(netdissect_options *ndo, const pcap_usb_header *uh) { int direction; uint8_t transfer_type, event_type; ndo->ndo_protocol = "usb"; nd_print_protocol_caps(ndo); if (ndo->ndo_qflag) return; ND_PRINT(" "); transfer_type = GET_U_1(uh->transfer_type); switch(transfer_type) { case URB_ISOCHRONOUS: ND_PRINT("ISOCHRONOUS"); break; case URB_INTERRUPT: ND_PRINT("INTERRUPT"); break; case URB_CONTROL: ND_PRINT("CONTROL"); break; case URB_BULK: ND_PRINT("BULK"); break; default: ND_PRINT(" ?"); } event_type = GET_U_1(uh->event_type); switch(event_type) { case URB_SUBMIT: ND_PRINT(" SUBMIT"); break; case URB_COMPLETE: ND_PRINT(" COMPLETE"); break; case URB_ERROR: ND_PRINT(" ERROR"); break; default: ND_PRINT(" ?"); } direction = get_direction(transfer_type, event_type); if(direction == 1) ND_PRINT(" from"); else if(direction == 2) ND_PRINT(" to"); ND_PRINT(" %u:%u:%u", GET_HE_U_2(uh->bus_id), GET_U_1(uh->device_address), GET_U_1(uh->endpoint_number) & 0x7f); } /* * This is the top level routine of the printer for captures with a * 48-byte header. * * 'p' points to the header of the packet, 'h->ts' is the timestamp, * 'h->len' is the length of the packet off the wire, and 'h->caplen' * is the number of bytes actually captured. */ void usb_linux_48_byte_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h _U_, const u_char *p) { ndo->ndo_protocol = "usb_linux_48_byte"; ND_TCHECK_LEN(p, sizeof(pcap_usb_header)); ndo->ndo_ll_hdr_len += sizeof (pcap_usb_header); usb_header_print(ndo, (const pcap_usb_header *) p); } #ifdef DLT_USB_LINUX_MMAPPED /* * This is the top level routine of the printer for captures with a * 64-byte header. * * 'p' points to the header of the packet, 'h->ts' is the timestamp, * 'h->len' is the length of the packet off the wire, and 'h->caplen' * is the number of bytes actually captured. */ void usb_linux_64_byte_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h _U_, const u_char *p) { ndo->ndo_protocol = "usb_linux_64_byte"; ND_TCHECK_LEN(p, sizeof(pcap_usb_header_mmapped)); ndo->ndo_ll_hdr_len += sizeof (pcap_usb_header_mmapped); usb_header_print(ndo, (const pcap_usb_header *) p); } #endif /* DLT_USB_LINUX_MMAPPED */ #endif /* DLT_USB_LINUX */ tcpdump-4.99.1/varattrs.h0000644000026300017510000000460214057477727013462 0ustar mcrmcr/* -*- Mode: c; tab-width: 8; indent-tabs-mode: 1; c-basic-offset: 8; -*- */ /* * Copyright (c) 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 the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the Computer Systems * Engineering Group at Lawrence Berkeley Laboratory. * 4. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef varattrs_h #define varattrs_h #include "compiler-tests.h" /* * Attributes to apply to variables, using various compiler-specific * extensions. */ #if __has_attribute(unused) \ || ND_IS_AT_LEAST_GNUC_VERSION(2,0) /* * Compiler with support for __attribute__((unused)), or GCC 2.0 and * later, so it supports __attribute__((unused)). */ #define _U_ __attribute__((unused)) #else /* * We don't know of any way to mark a variable as unused. */ #define _U_ #endif #endif tcpdump-4.99.1/ospf.h0000644000026300017510000002430214057477734012560 0ustar mcrmcr/* * Copyright (c) 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. * * OSPF support contributed by Jeffrey Honig (jch@mitchell.cit.cornell.edu) */ #define OSPF_TYPE_HELLO 1 /* Hello */ #define OSPF_TYPE_DD 2 /* Database Description */ #define OSPF_TYPE_LS_REQ 3 /* Link State Request */ #define OSPF_TYPE_LS_UPDATE 4 /* Link State Update */ #define OSPF_TYPE_LS_ACK 5 /* Link State Ack */ /* Options field * * +------------------------------------+ * | DN | O | DC | L | N/P | MC | E | T | * +------------------------------------+ * */ #define OSPF_OPTION_MT 0x01 /* MT bit: multi-topology */ #define OSPF_OPTION_E 0x02 /* E bit: External routes advertised */ #define OSPF_OPTION_MC 0x04 /* MC bit: Multicast capable */ #define OSPF_OPTION_NP 0x08 /* N/P bit: NSSA capable */ #define OSPF_OPTION_L 0x10 /* L bit: Packet contains LLS data block */ #define OSPF_OPTION_DC 0x20 /* DC bit: Demand circuit capable */ #define OSPF_OPTION_O 0x40 /* O bit: Opaque LSA capable */ #define OSPF_OPTION_DN 0x80 /* DN bit: Up/Down Bit capable - draft-ietf-ospf-2547-dnbit-04 */ /* ospf_authtype */ #define OSPF_AUTH_NONE 0 /* No auth-data */ #define OSPF_AUTH_SIMPLE 1 /* Simple password */ #define OSPF_AUTH_SIMPLE_LEN 8 /* max length of simple authentication */ #define OSPF_AUTH_MD5 2 /* MD5 authentication */ #define OSPF_AUTH_MD5_LEN 16 /* length of MD5 authentication */ /* db_flags */ #define OSPF_DB_INIT 0x04 #define OSPF_DB_MORE 0x02 #define OSPF_DB_MASTER 0x01 #define OSPF_DB_RESYNC 0x08 /* RFC4811 */ /* ls_type */ #define LS_TYPE_ROUTER 1 /* router link */ #define LS_TYPE_NETWORK 2 /* network link */ #define LS_TYPE_SUM_IP 3 /* summary link */ #define LS_TYPE_SUM_ABR 4 /* summary area link */ #define LS_TYPE_ASE 5 /* ASE */ #define LS_TYPE_GROUP 6 /* Group membership (multicast */ /* extensions 23 July 1991) */ #define LS_TYPE_NSSA 7 /* rfc3101 - Not so Stubby Areas */ #define LS_TYPE_OPAQUE_LL 9 /* rfc2370 - Opaque Link Local */ #define LS_TYPE_OPAQUE_AL 10 /* rfc2370 - Opaque Link Local */ #define LS_TYPE_OPAQUE_DW 11 /* rfc2370 - Opaque Domain Wide */ #define LS_OPAQUE_TYPE_TE 1 /* rfc3630 */ #define LS_OPAQUE_TYPE_GRACE 3 /* rfc3623 */ #define LS_OPAQUE_TYPE_RI 4 /* draft-ietf-ospf-cap-03 */ #define LS_OPAQUE_TE_TLV_ROUTER 1 /* rfc3630 */ #define LS_OPAQUE_TE_TLV_LINK 2 /* rfc3630 */ #define LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE 1 /* rfc3630 */ #define LS_OPAQUE_TE_LINK_SUBTLV_LINK_ID 2 /* rfc3630 */ #define LS_OPAQUE_TE_LINK_SUBTLV_LOCAL_IP 3 /* rfc3630 */ #define LS_OPAQUE_TE_LINK_SUBTLV_REMOTE_IP 4 /* rfc3630 */ #define LS_OPAQUE_TE_LINK_SUBTLV_TE_METRIC 5 /* rfc3630 */ #define LS_OPAQUE_TE_LINK_SUBTLV_MAX_BW 6 /* rfc3630 */ #define LS_OPAQUE_TE_LINK_SUBTLV_MAX_RES_BW 7 /* rfc3630 */ #define LS_OPAQUE_TE_LINK_SUBTLV_UNRES_BW 8 /* rfc3630 */ #define LS_OPAQUE_TE_LINK_SUBTLV_ADMIN_GROUP 9 /* rfc3630 */ #define LS_OPAQUE_TE_LINK_SUBTLV_LINK_LOCAL_REMOTE_ID 11 /* rfc4203 */ #define LS_OPAQUE_TE_LINK_SUBTLV_LINK_PROTECTION_TYPE 14 /* rfc4203 */ #define LS_OPAQUE_TE_LINK_SUBTLV_INTF_SW_CAP_DESCR 15 /* rfc4203 */ #define LS_OPAQUE_TE_LINK_SUBTLV_SHARED_RISK_GROUP 16 /* rfc4203 */ #define LS_OPAQUE_TE_LINK_SUBTLV_BW_CONSTRAINTS 17 /* rfc4124 */ #define LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_PTP 1 /* rfc3630 */ #define LS_OPAQUE_TE_LINK_SUBTLV_LINK_TYPE_MA 2 /* rfc3630 */ #define LS_OPAQUE_GRACE_TLV_PERIOD 1 /* rfc3623 */ #define LS_OPAQUE_GRACE_TLV_REASON 2 /* rfc3623 */ #define LS_OPAQUE_GRACE_TLV_INT_ADDRESS 3 /* rfc3623 */ #define LS_OPAQUE_GRACE_TLV_REASON_UNKNOWN 0 /* rfc3623 */ #define LS_OPAQUE_GRACE_TLV_REASON_SW_RESTART 1 /* rfc3623 */ #define LS_OPAQUE_GRACE_TLV_REASON_SW_UPGRADE 2 /* rfc3623 */ #define LS_OPAQUE_GRACE_TLV_REASON_CP_SWITCH 3 /* rfc3623 */ #define LS_OPAQUE_RI_TLV_CAP 1 /* draft-ietf-ospf-cap-03 */ /* rla_link.link_type */ #define RLA_TYPE_ROUTER 1 /* point-to-point to another router */ #define RLA_TYPE_TRANSIT 2 /* connection to transit network */ #define RLA_TYPE_STUB 3 /* connection to stub network */ #define RLA_TYPE_VIRTUAL 4 /* virtual link */ /* rla_flags */ #define RLA_FLAG_B 0x01 #define RLA_FLAG_E 0x02 #define RLA_FLAG_W1 0x04 #define RLA_FLAG_W2 0x08 /* sla_tosmetric breakdown */ #define SLA_MASK_TOS 0x7f000000 #define SLA_MASK_METRIC 0x00ffffff #define SLA_SHIFT_TOS 24 /* asla_tosmetric breakdown */ #define ASLA_FLAG_EXTERNAL 0x80000000 #define ASLA_MASK_TOS 0x7f000000 #define ASLA_SHIFT_TOS 24 #define ASLA_MASK_METRIC 0x00ffffff /* multicast vertex type */ #define MCLA_VERTEX_ROUTER 1 #define MCLA_VERTEX_NETWORK 2 /* Link-Local-Signaling */ #define OSPF_LLS_HDRLEN 4U /* RFC5613 Section 2.2 */ #define OSPF_LLS_EO 1 /* RFC4811, RFC4812 */ #define OSPF_LLS_MD5 2 /* RFC4813 */ #define OSPF_LLS_EO_LR 0x00000001 /* RFC4811 */ #define OSPF_LLS_EO_RS 0x00000002 /* RFC4812 */ /* * TOS metric struct (will be 0 or more in router links update) */ struct tos_metric { nd_uint8_t tos_type; nd_uint8_t reserved; nd_uint16_t tos_metric; }; struct tos_link { nd_uint8_t link_type; nd_uint8_t link_tos_count; nd_uint16_t tos_metric; }; union un_tos { struct tos_link link; struct tos_metric metrics; }; /* link state advertisement header */ struct lsa_hdr { nd_uint16_t ls_age; nd_uint8_t ls_options; nd_uint8_t ls_type; union { nd_ipv4 lsa_id; struct { /* opaque LSAs change the LSA-ID field */ nd_uint8_t opaque_type; nd_uint24_t opaque_id; } opaque_field; } un_lsa_id; nd_ipv4 ls_router; nd_uint32_t ls_seq; nd_uint16_t ls_chksum; nd_uint16_t ls_length; }; /* link state advertisement */ struct lsa { struct lsa_hdr ls_hdr; /* Link state types */ union { /* Router links advertisements */ struct { nd_uint8_t rla_flags; nd_byte rla_zero; nd_uint16_t rla_count; struct rlalink { nd_ipv4 link_id; nd_ipv4 link_data; union un_tos un_tos; } rla_link[1]; /* may repeat */ } un_rla; /* Network links advertisements */ struct { nd_ipv4 nla_mask; nd_ipv4 nla_router[1]; /* may repeat */ } un_nla; /* Summary links advertisements */ struct { nd_ipv4 sla_mask; nd_uint32_t sla_tosmetric[1]; /* may repeat */ } un_sla; /* AS external links advertisements */ struct { nd_ipv4 asla_mask; struct aslametric { nd_uint32_t asla_tosmetric; nd_ipv4 asla_forward; nd_ipv4 asla_tag; } asla_metric[1]; /* may repeat */ } un_asla; /* Multicast group membership */ struct mcla { nd_uint32_t mcla_vtype; nd_ipv4 mcla_vid; } un_mcla[1]; /* Opaque TE LSA */ struct { nd_uint16_t type; nd_uint16_t length; nd_byte data[1]; /* may repeat */ } un_te_lsa_tlv[1]; /* may repeat */ /* Opaque Grace LSA */ struct { nd_uint16_t type; nd_uint16_t length; nd_byte data[1]; /* may repeat */ } un_grace_tlv[1]; /* may repeat */ /* Opaque Router information LSA */ struct { nd_uint16_t type; nd_uint16_t length; nd_byte data[1]; /* may repeat */ } un_ri_tlv[1]; /* may repeat */ /* Unknown LSA */ struct unknown { nd_byte data[1]; /* may repeat */ } un_unknown[1]; } lsa_un; }; #define OSPF_AUTH_SIZE 8 /* * the main header */ struct ospfhdr { nd_uint8_t ospf_version; nd_uint8_t ospf_type; nd_uint16_t ospf_len; nd_ipv4 ospf_routerid; nd_ipv4 ospf_areaid; nd_uint16_t ospf_chksum; nd_uint16_t ospf_authtype; nd_byte ospf_authdata[OSPF_AUTH_SIZE]; union { /* Hello packet */ struct { nd_ipv4 hello_mask; nd_uint16_t hello_helloint; nd_uint8_t hello_options; nd_uint8_t hello_priority; nd_uint32_t hello_deadint; nd_ipv4 hello_dr; nd_ipv4 hello_bdr; nd_ipv4 hello_neighbor[1]; /* may repeat */ } un_hello; /* Database Description packet */ struct { nd_uint16_t db_ifmtu; nd_uint8_t db_options; nd_uint8_t db_flags; nd_uint32_t db_seq; struct lsa_hdr db_lshdr[1]; /* may repeat */ } un_db; /* Link State Request */ struct lsr { nd_uint32_t ls_type; union { nd_ipv4 ls_stateid; struct { /* opaque LSAs change the LSA-ID field */ nd_uint8_t opaque_type; nd_uint24_t opaque_id; } opaque_field; } un_ls_stateid; nd_ipv4 ls_router; } un_lsr[1]; /* may repeat */ /* Link State Update */ struct { nd_uint32_t lsu_count; struct lsa lsu_lsa[1]; /* may repeat */ } un_lsu; /* Link State Acknowledgement */ struct { struct lsa_hdr lsa_lshdr[1]; /* may repeat */ } un_lsa ; } ospf_un ; }; #define ospf_hello ospf_un.un_hello #define ospf_db ospf_un.un_db #define ospf_lsr ospf_un.un_lsr #define ospf_lsu ospf_un.un_lsu #define ospf_lsa ospf_un.un_lsa tcpdump-4.99.1/print-lmp.c0000644000026300017510000011131214057477727013526 0ustar mcrmcr/* * 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, and (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. * 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. * * Original code by Hannes Gredler (hannes@gredler.at) * Support for LMP service discovery extensions (defined by OIF UNI 1.0) * added by Manu Pathak (mapathak@cisco.com), May 2005 */ /* \summary: Link Management Protocol (LMP) printer */ /* specification: RFC 4204 */ /* OIF UNI 1.0: https://web.archive.org/web/20160401194747/http://www.oiforum.com/public/documents/OIF-UNI-01.0.pdf */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "extract.h" #include "addrtoname.h" #include "gmpls.h" /* * LMP common header * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Vers | (Reserved) | Flags | Msg Type | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | LMP Length | (Reserved) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ struct lmp_common_header { nd_uint16_t version_res; nd_uint8_t flags; nd_uint8_t msg_type; nd_uint16_t length; nd_byte reserved[2]; }; #define LMP_VERSION 1 #define LMP_EXTRACT_VERSION(x) (((x)&0xf000)>>12) static const struct tok lmp_header_flag_values[] = { { 0x01, "Control Channel Down"}, { 0x02, "LMP restart"}, { 0, NULL} }; static const struct tok lmp_obj_te_link_flag_values[] = { { 0x01, "Fault Management Supported"}, { 0x02, "Link Verification Supported"}, { 0, NULL} }; static const struct tok lmp_obj_data_link_flag_values[] = { { 0x01, "Data Link Port"}, { 0x02, "Allocated for user traffic"}, { 0x04, "Failed link"}, { 0, NULL} }; static const struct tok lmp_obj_channel_status_values[] = { { 1, "Signal Okay"}, { 2, "Signal Degraded"}, { 3, "Signal Fail"}, { 0, NULL} }; static const struct tok lmp_obj_begin_verify_flag_values[] = { { 0x0001, "Verify all links"}, { 0x0002, "Data link type"}, { 0, NULL} }; static const struct tok lmp_obj_begin_verify_error_values[] = { { 0x01, "Link Verification Procedure Not supported"}, { 0x02, "Unwilling to verify"}, { 0x04, "Unsupported verification transport mechanism"}, { 0x08, "Link-Id configuration error"}, { 0x10, "Unknown object c-type"}, { 0, NULL} }; static const struct tok lmp_obj_link_summary_error_values[] = { { 0x01, "Unacceptable non-negotiable LINK-SUMMARY parameters"}, { 0x02, "Renegotiate LINK-SUMMARY parameters"}, { 0x04, "Invalid TE-LINK Object"}, { 0x08, "Invalid DATA-LINK Object"}, { 0x10, "Unknown TE-LINK Object c-type"}, { 0x20, "Unknown DATA-LINK Object c-type"}, { 0, NULL} }; /* Service Config Supported Protocols Flags */ static const struct tok lmp_obj_service_config_sp_flag_values[] = { { 0x01, "RSVP Supported"}, { 0x02, "LDP Supported"}, { 0, NULL} }; /* Service Config Client Port Service Attribute Transparency Flags */ static const struct tok lmp_obj_service_config_cpsa_tp_flag_values[] = { { 0x01, "Path/VC Overhead Transparency Supported"}, { 0x02, "Line/MS Overhead Transparency Supported"}, { 0x04, "Section/RS Overhead Transparency Supported"}, { 0, NULL} }; /* Service Config Client Port Service Attribute Contiguous Concatenation Types Flags */ static const struct tok lmp_obj_service_config_cpsa_cct_flag_values[] = { { 0x01, "Contiguous Concatenation Types Supported"}, { 0, NULL} }; /* Service Config Network Service Attributes Transparency Flags */ static const struct tok lmp_obj_service_config_nsa_transparency_flag_values[] = { { 0x01, "Standard SOH/RSOH Transparency Supported"}, { 0x02, "Standard LOH/MSOH Transparency Supported"}, { 0, NULL} }; /* Service Config Network Service Attributes TCM Monitoring Flags */ static const struct tok lmp_obj_service_config_nsa_tcm_flag_values[] = { { 0x01, "Transparent Tandem Connection Monitoring Supported"}, { 0, NULL} }; /* Network Service Attributes Network Diversity Flags */ static const struct tok lmp_obj_service_config_nsa_network_diversity_flag_values[] = { { 0x01, "Node Diversity Supported"}, { 0x02, "Link Diversity Supported"}, { 0x04, "SRLG Diversity Supported"}, { 0, NULL} }; #define LMP_MSGTYPE_CONFIG 1 #define LMP_MSGTYPE_CONFIG_ACK 2 #define LMP_MSGTYPE_CONFIG_NACK 3 #define LMP_MSGTYPE_HELLO 4 #define LMP_MSGTYPE_VERIFY_BEGIN 5 #define LMP_MSGTYPE_VERIFY_BEGIN_ACK 6 #define LMP_MSGTYPE_VERIFY_BEGIN_NACK 7 #define LMP_MSGTYPE_VERIFY_END 8 #define LMP_MSGTYPE_VERIFY_END_ACK 9 #define LMP_MSGTYPE_TEST 10 #define LMP_MSGTYPE_TEST_STATUS_SUCCESS 11 #define LMP_MSGTYPE_TEST_STATUS_FAILURE 12 #define LMP_MSGTYPE_TEST_STATUS_ACK 13 #define LMP_MSGTYPE_LINK_SUMMARY 14 #define LMP_MSGTYPE_LINK_SUMMARY_ACK 15 #define LMP_MSGTYPE_LINK_SUMMARY_NACK 16 #define LMP_MSGTYPE_CHANNEL_STATUS 17 #define LMP_MSGTYPE_CHANNEL_STATUS_ACK 18 #define LMP_MSGTYPE_CHANNEL_STATUS_REQ 19 #define LMP_MSGTYPE_CHANNEL_STATUS_RESP 20 /* LMP Service Discovery message types defined by UNI 1.0 */ #define LMP_MSGTYPE_SERVICE_CONFIG 50 #define LMP_MSGTYPE_SERVICE_CONFIG_ACK 51 #define LMP_MSGTYPE_SERVICE_CONFIG_NACK 52 static const struct tok lmp_msg_type_values[] = { { LMP_MSGTYPE_CONFIG, "Config"}, { LMP_MSGTYPE_CONFIG_ACK, "Config ACK"}, { LMP_MSGTYPE_CONFIG_NACK, "Config NACK"}, { LMP_MSGTYPE_HELLO, "Hello"}, { LMP_MSGTYPE_VERIFY_BEGIN, "Begin Verify"}, { LMP_MSGTYPE_VERIFY_BEGIN_ACK, "Begin Verify ACK"}, { LMP_MSGTYPE_VERIFY_BEGIN_NACK, "Begin Verify NACK"}, { LMP_MSGTYPE_VERIFY_END, "End Verify"}, { LMP_MSGTYPE_VERIFY_END_ACK, "End Verify ACK"}, { LMP_MSGTYPE_TEST, "Test"}, { LMP_MSGTYPE_TEST_STATUS_SUCCESS, "Test Status Success"}, { LMP_MSGTYPE_TEST_STATUS_FAILURE, "Test Status Failure"}, { LMP_MSGTYPE_TEST_STATUS_ACK, "Test Status ACK"}, { LMP_MSGTYPE_LINK_SUMMARY, "Link Summary"}, { LMP_MSGTYPE_LINK_SUMMARY_ACK, "Link Summary ACK"}, { LMP_MSGTYPE_LINK_SUMMARY_NACK, "Link Summary NACK"}, { LMP_MSGTYPE_CHANNEL_STATUS, "Channel Status"}, { LMP_MSGTYPE_CHANNEL_STATUS_ACK, "Channel Status ACK"}, { LMP_MSGTYPE_CHANNEL_STATUS_REQ, "Channel Status Request"}, { LMP_MSGTYPE_CHANNEL_STATUS_RESP, "Channel Status Response"}, { LMP_MSGTYPE_SERVICE_CONFIG, "Service Config"}, { LMP_MSGTYPE_SERVICE_CONFIG_ACK, "Service Config ACK"}, { LMP_MSGTYPE_SERVICE_CONFIG_NACK, "Service Config NACK"}, { 0, NULL} }; /* * LMP object header * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * |N| C-Type | Class | Length | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | * // (object contents) // * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ struct lmp_object_header { nd_uint8_t ctype; nd_uint8_t class_num; nd_uint16_t length; }; #define LMP_OBJ_CC_ID 1 #define LMP_OBJ_NODE_ID 2 #define LMP_OBJ_LINK_ID 3 #define LMP_OBJ_INTERFACE_ID 4 #define LMP_OBJ_MESSAGE_ID 5 #define LMP_OBJ_CONFIG 6 #define LMP_OBJ_HELLO 7 #define LMP_OBJ_VERIFY_BEGIN 8 #define LMP_OBJ_VERIFY_BEGIN_ACK 9 #define LMP_OBJ_VERIFY_ID 10 #define LMP_OBJ_TE_LINK 11 #define LMP_OBJ_DATA_LINK 12 #define LMP_OBJ_CHANNEL_STATUS 13 #define LMP_OBJ_CHANNEL_STATUS_REQ 14 #define LMP_OBJ_ERROR_CODE 20 #define LMP_OBJ_SERVICE_CONFIG 51 /* defined in UNI 1.0 */ static const struct tok lmp_obj_values[] = { { LMP_OBJ_CC_ID, "Control Channel ID" }, { LMP_OBJ_NODE_ID, "Node ID" }, { LMP_OBJ_LINK_ID, "Link ID" }, { LMP_OBJ_INTERFACE_ID, "Interface ID" }, { LMP_OBJ_MESSAGE_ID, "Message ID" }, { LMP_OBJ_CONFIG, "Configuration" }, { LMP_OBJ_HELLO, "Hello" }, { LMP_OBJ_VERIFY_BEGIN, "Verify Begin" }, { LMP_OBJ_VERIFY_BEGIN_ACK, "Verify Begin ACK" }, { LMP_OBJ_VERIFY_ID, "Verify ID" }, { LMP_OBJ_TE_LINK, "TE Link" }, { LMP_OBJ_DATA_LINK, "Data Link" }, { LMP_OBJ_CHANNEL_STATUS, "Channel Status" }, { LMP_OBJ_CHANNEL_STATUS_REQ, "Channel Status Request" }, { LMP_OBJ_ERROR_CODE, "Error Code" }, { LMP_OBJ_SERVICE_CONFIG, "Service Config" }, { 0, NULL} }; #define INT_SWITCHING_TYPE_SUBOBJ 1 #define WAVELENGTH_SUBOBJ 2 static const struct tok lmp_data_link_subobj[] = { { INT_SWITCHING_TYPE_SUBOBJ, "Interface Switching Type" }, { WAVELENGTH_SUBOBJ , "Wavelength" }, { 0, NULL} }; #define LMP_CTYPE_IPV4 1 #define LMP_CTYPE_IPV6 2 #define LMP_CTYPE_LOC 1 #define LMP_CTYPE_RMT 2 #define LMP_CTYPE_UNMD 3 #define LMP_CTYPE_IPV4_LOC 1 #define LMP_CTYPE_IPV4_RMT 2 #define LMP_CTYPE_IPV6_LOC 3 #define LMP_CTYPE_IPV6_RMT 4 #define LMP_CTYPE_UNMD_LOC 5 #define LMP_CTYPE_UNMD_RMT 6 #define LMP_CTYPE_1 1 #define LMP_CTYPE_2 2 #define LMP_CTYPE_HELLO_CONFIG 1 #define LMP_CTYPE_HELLO 1 #define LMP_CTYPE_BEGIN_VERIFY_ERROR 1 #define LMP_CTYPE_LINK_SUMMARY_ERROR 2 /* C-Types for Service Config Object */ #define LMP_CTYPE_SERVICE_CONFIG_SP 1 #define LMP_CTYPE_SERVICE_CONFIG_CPSA 2 #define LMP_CTYPE_SERVICE_CONFIG_TRANSPARENCY_TCM 3 #define LMP_CTYPE_SERVICE_CONFIG_NETWORK_DIVERSITY 4 /* * Different link types allowed in the Client Port Service Attributes * subobject defined for LMP Service Discovery in the UNI 1.0 spec */ #define LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SDH 5 /* UNI 1.0 Sec 9.4.2 */ #define LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SONET 6 /* UNI 1.0 Sec 9.4.2 */ /* * the ctypes are not globally unique so for * translating it to strings we build a table based * on objects offsetted by the ctype */ static const struct tok lmp_ctype_values[] = { { 256*LMP_OBJ_CC_ID+LMP_CTYPE_LOC, "Local" }, { 256*LMP_OBJ_CC_ID+LMP_CTYPE_RMT, "Remote" }, { 256*LMP_OBJ_NODE_ID+LMP_CTYPE_LOC, "Local" }, { 256*LMP_OBJ_NODE_ID+LMP_CTYPE_RMT, "Remote" }, { 256*LMP_OBJ_LINK_ID+LMP_CTYPE_IPV4_LOC, "IPv4 Local" }, { 256*LMP_OBJ_LINK_ID+LMP_CTYPE_IPV4_RMT, "IPv4 Remote" }, { 256*LMP_OBJ_LINK_ID+LMP_CTYPE_IPV6_LOC, "IPv6 Local" }, { 256*LMP_OBJ_LINK_ID+LMP_CTYPE_IPV6_RMT, "IPv6 Remote" }, { 256*LMP_OBJ_LINK_ID+LMP_CTYPE_UNMD_LOC, "Unnumbered Local" }, { 256*LMP_OBJ_LINK_ID+LMP_CTYPE_UNMD_RMT, "Unnumbered Remote" }, { 256*LMP_OBJ_INTERFACE_ID+LMP_CTYPE_IPV4_LOC, "IPv4 Local" }, { 256*LMP_OBJ_INTERFACE_ID+LMP_CTYPE_IPV4_RMT, "IPv4 Remote" }, { 256*LMP_OBJ_INTERFACE_ID+LMP_CTYPE_IPV6_LOC, "IPv6 Local" }, { 256*LMP_OBJ_INTERFACE_ID+LMP_CTYPE_IPV6_RMT, "IPv6 Remote" }, { 256*LMP_OBJ_INTERFACE_ID+LMP_CTYPE_UNMD_LOC, "Unnumbered Local" }, { 256*LMP_OBJ_INTERFACE_ID+LMP_CTYPE_UNMD_RMT, "Unnumbered Remote" }, { 256*LMP_OBJ_MESSAGE_ID+LMP_CTYPE_1, "1" }, { 256*LMP_OBJ_MESSAGE_ID+LMP_CTYPE_2, "2" }, { 256*LMP_OBJ_CONFIG+LMP_CTYPE_1, "1" }, { 256*LMP_OBJ_HELLO+LMP_CTYPE_1, "1" }, { 256*LMP_OBJ_VERIFY_BEGIN+LMP_CTYPE_1, "1" }, { 256*LMP_OBJ_VERIFY_BEGIN_ACK+LMP_CTYPE_1, "1" }, { 256*LMP_OBJ_VERIFY_ID+LMP_CTYPE_1, "1" }, { 256*LMP_OBJ_TE_LINK+LMP_CTYPE_IPV4, "IPv4" }, { 256*LMP_OBJ_TE_LINK+LMP_CTYPE_IPV6, "IPv6" }, { 256*LMP_OBJ_TE_LINK+LMP_CTYPE_UNMD, "Unnumbered" }, { 256*LMP_OBJ_DATA_LINK+LMP_CTYPE_IPV4, "IPv4" }, { 256*LMP_OBJ_DATA_LINK+LMP_CTYPE_IPV6, "IPv6" }, { 256*LMP_OBJ_DATA_LINK+LMP_CTYPE_UNMD, "Unnumbered" }, { 256*LMP_OBJ_CHANNEL_STATUS+LMP_CTYPE_IPV4, "IPv4" }, { 256*LMP_OBJ_CHANNEL_STATUS+LMP_CTYPE_IPV6, "IPv6" }, { 256*LMP_OBJ_CHANNEL_STATUS+LMP_CTYPE_UNMD, "Unnumbered" }, { 256*LMP_OBJ_CHANNEL_STATUS_REQ+LMP_CTYPE_IPV4, "IPv4" }, { 256*LMP_OBJ_CHANNEL_STATUS_REQ+LMP_CTYPE_IPV6, "IPv6" }, { 256*LMP_OBJ_CHANNEL_STATUS_REQ+LMP_CTYPE_UNMD, "Unnumbered" }, { 256*LMP_OBJ_ERROR_CODE+LMP_CTYPE_1, "1" }, { 256*LMP_OBJ_ERROR_CODE+LMP_CTYPE_2, "2" }, { 256*LMP_OBJ_SERVICE_CONFIG+LMP_CTYPE_SERVICE_CONFIG_SP, "1" }, { 256*LMP_OBJ_SERVICE_CONFIG+LMP_CTYPE_SERVICE_CONFIG_CPSA, "2" }, { 256*LMP_OBJ_SERVICE_CONFIG+LMP_CTYPE_SERVICE_CONFIG_TRANSPARENCY_TCM, "3" }, { 256*LMP_OBJ_SERVICE_CONFIG+LMP_CTYPE_SERVICE_CONFIG_NETWORK_DIVERSITY, "4" }, { 0, NULL} }; static int lmp_print_data_link_subobjs(netdissect_options *ndo, const u_char *obj_tptr, int total_subobj_len, int offset) { int hexdump = FALSE; int subobj_type, subobj_len; union { /* int to float conversion buffer */ float f; uint32_t i; } bw; while (total_subobj_len > 0 && hexdump == FALSE ) { subobj_type = GET_U_1(obj_tptr + offset); subobj_len = GET_U_1(obj_tptr + offset + 1); ND_PRINT("\n\t Subobject, Type: %s (%u), Length: %u", tok2str(lmp_data_link_subobj, "Unknown", subobj_type), subobj_type, subobj_len); if (subobj_len < 4) { ND_PRINT(" (too short)"); break; } if ((subobj_len % 4) != 0) { ND_PRINT(" (not a multiple of 4)"); break; } if (total_subobj_len < subobj_len) { ND_PRINT(" (goes past the end of the object)"); break; } switch(subobj_type) { case INT_SWITCHING_TYPE_SUBOBJ: ND_PRINT("\n\t Switching Type: %s (%u)", tok2str(gmpls_switch_cap_values, "Unknown", GET_U_1(obj_tptr + offset + 2)), GET_U_1(obj_tptr + offset + 2)); ND_PRINT("\n\t Encoding Type: %s (%u)", tok2str(gmpls_encoding_values, "Unknown", GET_U_1(obj_tptr + offset + 3)), GET_U_1(obj_tptr + offset + 3)); bw.i = GET_BE_U_4(obj_tptr + offset + 4); ND_PRINT("\n\t Min Reservable Bandwidth: %.3f Mbps", bw.f*8/1000000); bw.i = GET_BE_U_4(obj_tptr + offset + 8); ND_PRINT("\n\t Max Reservable Bandwidth: %.3f Mbps", bw.f*8/1000000); break; case WAVELENGTH_SUBOBJ: ND_PRINT("\n\t Wavelength: %u", GET_BE_U_4(obj_tptr + offset + 4)); break; default: /* Any Unknown Subobject ==> Exit loop */ hexdump=TRUE; break; } total_subobj_len-=subobj_len; offset+=subobj_len; } return (hexdump); } void lmp_print(netdissect_options *ndo, const u_char *pptr, u_int length) { const struct lmp_common_header *lmp_com_header; const u_char *tptr,*obj_tptr; u_int version_res, tlen, lmp_obj_len, lmp_obj_ctype, obj_tlen; int hexdump; u_int offset; u_int link_type; union { /* int to float conversion buffer */ float f; uint32_t i; } bw; ndo->ndo_protocol = "lmp"; tptr=pptr; lmp_com_header = (const struct lmp_common_header *)pptr; ND_TCHECK_SIZE(lmp_com_header); version_res = GET_BE_U_2(lmp_com_header->version_res); /* * Sanity checking of the header. */ if (LMP_EXTRACT_VERSION(version_res) != LMP_VERSION) { ND_PRINT("LMP version %u packet not supported", LMP_EXTRACT_VERSION(version_res)); return; } /* in non-verbose mode just lets print the basic Message Type*/ if (ndo->ndo_vflag < 1) { ND_PRINT("LMPv%u %s Message, length: %u", LMP_EXTRACT_VERSION(version_res), tok2str(lmp_msg_type_values, "unknown (%u)",GET_U_1(lmp_com_header->msg_type)), length); return; } /* ok they seem to want to know everything - lets fully decode it */ tlen=GET_BE_U_2(lmp_com_header->length); ND_PRINT("\n\tLMPv%u, msg-type: %s, Flags: [%s], length: %u", LMP_EXTRACT_VERSION(version_res), tok2str(lmp_msg_type_values, "unknown, type: %u",GET_U_1(lmp_com_header->msg_type)), bittok2str(lmp_header_flag_values,"none",GET_U_1(lmp_com_header->flags)), tlen); if (tlen < sizeof(struct lmp_common_header)) { ND_PRINT(" (too short)"); return; } if (tlen > length) { ND_PRINT(" (too long)"); tlen = length; } tptr+=sizeof(struct lmp_common_header); tlen-=sizeof(struct lmp_common_header); while(tlen>0) { const struct lmp_object_header *lmp_obj_header = (const struct lmp_object_header *)tptr; lmp_obj_len=GET_BE_U_2(lmp_obj_header->length); lmp_obj_ctype=GET_U_1(lmp_obj_header->ctype)&0x7f; ND_PRINT("\n\t %s Object (%u), Class-Type: %s (%u) Flags: [%snegotiable], length: %u", tok2str(lmp_obj_values, "Unknown", GET_U_1(lmp_obj_header->class_num)), GET_U_1(lmp_obj_header->class_num), tok2str(lmp_ctype_values, "Unknown", (GET_U_1(lmp_obj_header->class_num)<<8)+lmp_obj_ctype), lmp_obj_ctype, GET_U_1(lmp_obj_header->ctype)&0x80 ? "" : "non-", lmp_obj_len); if (lmp_obj_len < 4) { ND_PRINT(" (too short)"); return; } if ((lmp_obj_len % 4) != 0) { ND_PRINT(" (not a multiple of 4)"); return; } obj_tptr=tptr+sizeof(struct lmp_object_header); obj_tlen=lmp_obj_len-sizeof(struct lmp_object_header); /* did we capture enough for fully decoding the object ? */ ND_TCHECK_LEN(tptr, lmp_obj_len); hexdump=FALSE; switch(GET_U_1(lmp_obj_header->class_num)) { case LMP_OBJ_CC_ID: switch(lmp_obj_ctype) { case LMP_CTYPE_LOC: case LMP_CTYPE_RMT: if (obj_tlen != 4) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Control Channel ID: %u (0x%08x)", GET_BE_U_4(obj_tptr), GET_BE_U_4(obj_tptr)); break; default: hexdump=TRUE; } break; case LMP_OBJ_LINK_ID: case LMP_OBJ_INTERFACE_ID: switch(lmp_obj_ctype) { case LMP_CTYPE_IPV4_LOC: case LMP_CTYPE_IPV4_RMT: if (obj_tlen != 4) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t IPv4 Link ID: %s (0x%08x)", GET_IPADDR_STRING(obj_tptr), GET_BE_U_4(obj_tptr)); break; case LMP_CTYPE_IPV6_LOC: case LMP_CTYPE_IPV6_RMT: if (obj_tlen != 16) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t IPv6 Link ID: %s (0x%08x)", GET_IP6ADDR_STRING(obj_tptr), GET_BE_U_4(obj_tptr)); break; case LMP_CTYPE_UNMD_LOC: case LMP_CTYPE_UNMD_RMT: if (obj_tlen != 4) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Link ID: %u (0x%08x)", GET_BE_U_4(obj_tptr), GET_BE_U_4(obj_tptr)); break; default: hexdump=TRUE; } break; case LMP_OBJ_MESSAGE_ID: switch(lmp_obj_ctype) { case LMP_CTYPE_1: if (obj_tlen != 4) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Message ID: %u (0x%08x)", GET_BE_U_4(obj_tptr), GET_BE_U_4(obj_tptr)); break; case LMP_CTYPE_2: if (obj_tlen != 4) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Message ID Ack: %u (0x%08x)", GET_BE_U_4(obj_tptr), GET_BE_U_4(obj_tptr)); break; default: hexdump=TRUE; } break; case LMP_OBJ_NODE_ID: switch(lmp_obj_ctype) { case LMP_CTYPE_LOC: case LMP_CTYPE_RMT: if (obj_tlen != 4) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Node ID: %s (0x%08x)", GET_IPADDR_STRING(obj_tptr), GET_BE_U_4(obj_tptr)); break; default: hexdump=TRUE; } break; case LMP_OBJ_CONFIG: switch(lmp_obj_ctype) { case LMP_CTYPE_HELLO_CONFIG: if (obj_tlen != 4) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Hello Interval: %u\n\t Hello Dead Interval: %u", GET_BE_U_2(obj_tptr), GET_BE_U_2(obj_tptr + 2)); break; default: hexdump=TRUE; } break; case LMP_OBJ_HELLO: switch(lmp_obj_ctype) { case LMP_CTYPE_HELLO: if (obj_tlen != 8) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Tx Seq: %u, Rx Seq: %u", GET_BE_U_4(obj_tptr), GET_BE_U_4(obj_tptr + 4)); break; default: hexdump=TRUE; } break; case LMP_OBJ_TE_LINK: switch(lmp_obj_ctype) { case LMP_CTYPE_IPV4: if (obj_tlen != 12) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Flags: [%s]", bittok2str(lmp_obj_te_link_flag_values, "none", GET_U_1(obj_tptr))); ND_PRINT("\n\t Local Link-ID: %s (0x%08x)" "\n\t Remote Link-ID: %s (0x%08x)", GET_IPADDR_STRING(obj_tptr+4), GET_BE_U_4(obj_tptr + 4), GET_IPADDR_STRING(obj_tptr+8), GET_BE_U_4(obj_tptr + 8)); break; case LMP_CTYPE_IPV6: if (obj_tlen != 36) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Flags: [%s]", bittok2str(lmp_obj_te_link_flag_values, "none", GET_U_1(obj_tptr))); ND_PRINT("\n\t Local Link-ID: %s (0x%08x)" "\n\t Remote Link-ID: %s (0x%08x)", GET_IP6ADDR_STRING(obj_tptr+4), GET_BE_U_4(obj_tptr + 4), GET_IP6ADDR_STRING(obj_tptr+20), GET_BE_U_4(obj_tptr + 20)); break; case LMP_CTYPE_UNMD: if (obj_tlen != 12) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Flags: [%s]", bittok2str(lmp_obj_te_link_flag_values, "none", GET_U_1(obj_tptr))); ND_PRINT("\n\t Local Link-ID: %u (0x%08x)" "\n\t Remote Link-ID: %u (0x%08x)", GET_BE_U_4(obj_tptr + 4), GET_BE_U_4(obj_tptr + 4), GET_BE_U_4(obj_tptr + 8), GET_BE_U_4(obj_tptr + 8)); break; default: hexdump=TRUE; } break; case LMP_OBJ_DATA_LINK: switch(lmp_obj_ctype) { case LMP_CTYPE_IPV4: if (obj_tlen < 12) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Flags: [%s]", bittok2str(lmp_obj_data_link_flag_values, "none", GET_U_1(obj_tptr))); ND_PRINT("\n\t Local Interface ID: %s (0x%08x)" "\n\t Remote Interface ID: %s (0x%08x)", GET_IPADDR_STRING(obj_tptr+4), GET_BE_U_4(obj_tptr + 4), GET_IPADDR_STRING(obj_tptr+8), GET_BE_U_4(obj_tptr + 8)); if (lmp_print_data_link_subobjs(ndo, obj_tptr, obj_tlen - 12, 12)) hexdump=TRUE; break; case LMP_CTYPE_IPV6: if (obj_tlen < 36) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Flags: [%s]", bittok2str(lmp_obj_data_link_flag_values, "none", GET_U_1(obj_tptr))); ND_PRINT("\n\t Local Interface ID: %s (0x%08x)" "\n\t Remote Interface ID: %s (0x%08x)", GET_IP6ADDR_STRING(obj_tptr+4), GET_BE_U_4(obj_tptr + 4), GET_IP6ADDR_STRING(obj_tptr+20), GET_BE_U_4(obj_tptr + 20)); if (lmp_print_data_link_subobjs(ndo, obj_tptr, obj_tlen - 36, 36)) hexdump=TRUE; break; case LMP_CTYPE_UNMD: if (obj_tlen < 12) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Flags: [%s]", bittok2str(lmp_obj_data_link_flag_values, "none", GET_U_1(obj_tptr))); ND_PRINT("\n\t Local Interface ID: %u (0x%08x)" "\n\t Remote Interface ID: %u (0x%08x)", GET_BE_U_4(obj_tptr + 4), GET_BE_U_4(obj_tptr + 4), GET_BE_U_4(obj_tptr + 8), GET_BE_U_4(obj_tptr + 8)); if (lmp_print_data_link_subobjs(ndo, obj_tptr, obj_tlen - 12, 12)) hexdump=TRUE; break; default: hexdump=TRUE; } break; case LMP_OBJ_VERIFY_BEGIN: switch(lmp_obj_ctype) { case LMP_CTYPE_1: if (obj_tlen != 20) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Flags: %s", bittok2str(lmp_obj_begin_verify_flag_values, "none", GET_BE_U_2(obj_tptr))); ND_PRINT("\n\t Verify Interval: %u", GET_BE_U_2(obj_tptr + 2)); ND_PRINT("\n\t Data links: %u", GET_BE_U_4(obj_tptr + 4)); ND_PRINT("\n\t Encoding type: %s", tok2str(gmpls_encoding_values, "Unknown", GET_U_1((obj_tptr + 8)))); ND_PRINT("\n\t Verify Transport Mechanism: %u (0x%x)%s", GET_BE_U_2(obj_tptr + 10), GET_BE_U_2(obj_tptr + 10), GET_BE_U_2(obj_tptr + 10)&8000 ? " (Payload test messages capable)" : ""); bw.i = GET_BE_U_4(obj_tptr + 12); ND_PRINT("\n\t Transmission Rate: %.3f Mbps",bw.f*8/1000000); ND_PRINT("\n\t Wavelength: %u", GET_BE_U_4(obj_tptr + 16)); break; default: hexdump=TRUE; } break; case LMP_OBJ_VERIFY_BEGIN_ACK: switch(lmp_obj_ctype) { case LMP_CTYPE_1: if (obj_tlen != 4) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Verify Dead Interval: %u" "\n\t Verify Transport Response: %u", GET_BE_U_2(obj_tptr), GET_BE_U_2(obj_tptr + 2)); break; default: hexdump=TRUE; } break; case LMP_OBJ_VERIFY_ID: switch(lmp_obj_ctype) { case LMP_CTYPE_1: if (obj_tlen != 4) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Verify ID: %u", GET_BE_U_4(obj_tptr)); break; default: hexdump=TRUE; } break; case LMP_OBJ_CHANNEL_STATUS: switch(lmp_obj_ctype) { case LMP_CTYPE_IPV4: offset = 0; /* Decode pairs: */ while (offset+8 <= obj_tlen) { ND_PRINT("\n\t Interface ID: %s (0x%08x)", GET_IPADDR_STRING(obj_tptr+offset), GET_BE_U_4(obj_tptr + offset)); ND_PRINT("\n\t\t Active: %s (%u)", (GET_BE_U_4(obj_tptr + offset + 4)>>31) ? "Allocated" : "Non-allocated", (GET_BE_U_4(obj_tptr + offset + 4)>>31)); ND_PRINT("\n\t\t Direction: %s (%u)", (GET_BE_U_4(obj_tptr + offset + 4)>>30)&0x1 ? "Transmit" : "Receive", (GET_BE_U_4(obj_tptr + offset + 4)>>30)&0x1); ND_PRINT("\n\t\t Channel Status: %s (%u)", tok2str(lmp_obj_channel_status_values, "Unknown", GET_BE_U_4(obj_tptr + offset + 4)&0x3FFFFFF), GET_BE_U_4(obj_tptr + offset + 4)&0x3FFFFFF); offset+=8; } break; case LMP_CTYPE_IPV6: offset = 0; /* Decode pairs: */ while (offset+20 <= obj_tlen) { ND_PRINT("\n\t Interface ID: %s (0x%08x)", GET_IP6ADDR_STRING(obj_tptr+offset), GET_BE_U_4(obj_tptr + offset)); ND_PRINT("\n\t\t Active: %s (%u)", (GET_BE_U_4(obj_tptr + offset + 16)>>31) ? "Allocated" : "Non-allocated", (GET_BE_U_4(obj_tptr + offset + 16)>>31)); ND_PRINT("\n\t\t Direction: %s (%u)", (GET_BE_U_4(obj_tptr + offset + 16)>>30)&0x1 ? "Transmit" : "Receive", (GET_BE_U_4(obj_tptr + offset + 16)>>30)&0x1); ND_PRINT("\n\t\t Channel Status: %s (%u)", tok2str(lmp_obj_channel_status_values, "Unknown", GET_BE_U_4(obj_tptr + offset + 16)&0x3FFFFFF), GET_BE_U_4(obj_tptr + offset + 16)&0x3FFFFFF); offset+=20; } break; case LMP_CTYPE_UNMD: offset = 0; /* Decode pairs: */ while (offset+8 <= obj_tlen) { ND_PRINT("\n\t Interface ID: %u (0x%08x)", GET_BE_U_4(obj_tptr + offset), GET_BE_U_4(obj_tptr + offset)); ND_PRINT("\n\t\t Active: %s (%u)", (GET_BE_U_4(obj_tptr + offset + 4)>>31) ? "Allocated" : "Non-allocated", (GET_BE_U_4(obj_tptr + offset + 4)>>31)); ND_PRINT("\n\t\t Direction: %s (%u)", (GET_BE_U_4(obj_tptr + offset + 4)>>30)&0x1 ? "Transmit" : "Receive", (GET_BE_U_4(obj_tptr + offset + 4)>>30)&0x1); ND_PRINT("\n\t\t Channel Status: %s (%u)", tok2str(lmp_obj_channel_status_values, "Unknown", GET_BE_U_4(obj_tptr + offset + 4)&0x3FFFFFF), GET_BE_U_4(obj_tptr + offset + 4)&0x3FFFFFF); offset+=8; } break; default: hexdump=TRUE; } break; case LMP_OBJ_CHANNEL_STATUS_REQ: switch(lmp_obj_ctype) { case LMP_CTYPE_IPV4: offset = 0; while (offset+4 <= obj_tlen) { ND_PRINT("\n\t Interface ID: %s (0x%08x)", GET_IPADDR_STRING(obj_tptr+offset), GET_BE_U_4(obj_tptr + offset)); offset+=4; } break; case LMP_CTYPE_IPV6: offset = 0; while (offset+16 <= obj_tlen) { ND_PRINT("\n\t Interface ID: %s (0x%08x)", GET_IP6ADDR_STRING(obj_tptr+offset), GET_BE_U_4(obj_tptr + offset)); offset+=16; } break; case LMP_CTYPE_UNMD: offset = 0; while (offset+4 <= obj_tlen) { ND_PRINT("\n\t Interface ID: %u (0x%08x)", GET_BE_U_4(obj_tptr + offset), GET_BE_U_4(obj_tptr + offset)); offset+=4; } break; default: hexdump=TRUE; } break; case LMP_OBJ_ERROR_CODE: switch(lmp_obj_ctype) { case LMP_CTYPE_BEGIN_VERIFY_ERROR: if (obj_tlen != 4) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Error Code: %s", bittok2str(lmp_obj_begin_verify_error_values, "none", GET_BE_U_4(obj_tptr))); break; case LMP_CTYPE_LINK_SUMMARY_ERROR: if (obj_tlen != 4) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Error Code: %s", bittok2str(lmp_obj_link_summary_error_values, "none", GET_BE_U_4(obj_tptr))); break; default: hexdump=TRUE; } break; case LMP_OBJ_SERVICE_CONFIG: switch (lmp_obj_ctype) { case LMP_CTYPE_SERVICE_CONFIG_SP: if (obj_tlen != 4) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Flags: %s", bittok2str(lmp_obj_service_config_sp_flag_values, "none", GET_U_1(obj_tptr))); ND_PRINT("\n\t UNI Version: %u", GET_U_1(obj_tptr + 1)); break; case LMP_CTYPE_SERVICE_CONFIG_CPSA: if (obj_tlen != 16) { ND_PRINT(" (not correct for object)"); break; } link_type = GET_U_1(obj_tptr); ND_PRINT("\n\t Link Type: %s (%u)", tok2str(lmp_sd_service_config_cpsa_link_type_values, "Unknown", link_type), link_type); switch (link_type) { case LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SDH: ND_PRINT("\n\t Signal Type: %s (%u)", tok2str(lmp_sd_service_config_cpsa_signal_type_sdh_values, "Unknown", GET_U_1(obj_tptr + 1)), GET_U_1(obj_tptr + 1)); break; case LMP_SD_SERVICE_CONFIG_CPSA_LINK_TYPE_SONET: ND_PRINT("\n\t Signal Type: %s (%u)", tok2str(lmp_sd_service_config_cpsa_signal_type_sonet_values, "Unknown", GET_U_1(obj_tptr + 1)), GET_U_1(obj_tptr + 1)); break; } ND_PRINT("\n\t Transparency: %s", bittok2str(lmp_obj_service_config_cpsa_tp_flag_values, "none", GET_U_1(obj_tptr + 2))); ND_PRINT("\n\t Contiguous Concatenation Types: %s", bittok2str(lmp_obj_service_config_cpsa_cct_flag_values, "none", GET_U_1(obj_tptr + 3))); ND_PRINT("\n\t Minimum NCC: %u", GET_BE_U_2(obj_tptr + 4)); ND_PRINT("\n\t Maximum NCC: %u", GET_BE_U_2(obj_tptr + 6)); ND_PRINT("\n\t Minimum NVC:%u", GET_BE_U_2(obj_tptr + 8)); ND_PRINT("\n\t Maximum NVC:%u", GET_BE_U_2(obj_tptr + 10)); ND_PRINT("\n\t Local Interface ID: %s (0x%08x)", GET_IPADDR_STRING(obj_tptr+12), GET_BE_U_4(obj_tptr + 12)); break; case LMP_CTYPE_SERVICE_CONFIG_TRANSPARENCY_TCM: if (obj_tlen != 8) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Transparency Flags: %s", bittok2str( lmp_obj_service_config_nsa_transparency_flag_values, "none", GET_BE_U_4(obj_tptr))); ND_PRINT("\n\t TCM Monitoring Flags: %s", bittok2str( lmp_obj_service_config_nsa_tcm_flag_values, "none", GET_U_1(obj_tptr + 7))); break; case LMP_CTYPE_SERVICE_CONFIG_NETWORK_DIVERSITY: if (obj_tlen != 4) { ND_PRINT(" (not correct for object)"); break; } ND_PRINT("\n\t Diversity: Flags: %s", bittok2str( lmp_obj_service_config_nsa_network_diversity_flag_values, "none", GET_U_1(obj_tptr + 3))); break; default: hexdump = TRUE; } break; default: if (ndo->ndo_vflag <= 1) print_unknown_data(ndo,obj_tptr,"\n\t ",obj_tlen); break; } /* do we want to see an additionally hexdump ? */ if (ndo->ndo_vflag > 1 || hexdump==TRUE) print_unknown_data(ndo,tptr+sizeof(struct lmp_object_header),"\n\t ", lmp_obj_len-sizeof(struct lmp_object_header)); if (tlen < lmp_obj_len) { ND_PRINT(" [remaining objects length %u < %u]", tlen, lmp_obj_len); nd_print_invalid(ndo); break; } tptr+=lmp_obj_len; tlen-=lmp_obj_len; } } tcpdump-4.99.1/netdissect.h0000644000026300017510000010602014057477734013754 0ustar mcrmcr/* * Copyright (c) 1988-1997 * The Regents of the University of California. All rights reserved. * * Copyright (c) 1998-2012 Michael Richardson * The TCPDUMP project * * 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. */ #ifndef netdissect_h #define netdissect_h #ifdef HAVE_OS_PROTO_H #include "os-proto.h" #endif #include #include #include "status-exit-codes.h" /* * Data types corresponding to multi-byte integral values within data * structures. These are defined as arrays of octets, so that they're * not aligned on their "natural" boundaries, and so that you *must* * use the EXTRACT_ macros to extract them (which you should be doing * *anyway*, so as not to assume a particular byte order or alignment * in your code). * * We even want EXTRACT_U_1 used for 8-bit integral values, so we * define nd_uint8_t and nd_int8_t as arrays as well. */ typedef unsigned char nd_uint8_t[1]; typedef unsigned char nd_uint16_t[2]; typedef unsigned char nd_uint24_t[3]; typedef unsigned char nd_uint32_t[4]; typedef unsigned char nd_uint40_t[5]; typedef unsigned char nd_uint48_t[6]; typedef unsigned char nd_uint56_t[7]; typedef unsigned char nd_uint64_t[8]; typedef signed char nd_int8_t[1]; /* * "unsigned char" so that sign extension isn't done on the * individual bytes while they're being assembled. */ typedef unsigned char nd_int32_t[4]; typedef unsigned char nd_int64_t[8]; #define FMAXINT (4294967296.0) /* floating point rep. of MAXINT */ /* * Use this for IPv4 addresses and netmasks. * * It's defined as an array of octets, so that it's not guaranteed to * be aligned on its "natural" boundary (in some packet formats, it * *isn't* so aligned). We have separate EXTRACT_ calls for them; * sometimes you want the host-byte-order value, other times you want * the network-byte-order value. * * Don't use EXTRACT_BE_U_4() on them, use EXTRACT_IPV4_TO_HOST_ORDER() * if you want them in host byte order and EXTRACT_IPV4_TO_NETWORK_ORDER() * if you want them in network byte order (which you want with system APIs * that expect network-order IPv4 addresses, such as inet_ntop()). * * If, on your little-endian machine (e.g., an "IBM-compatible PC", no matter * what the OS, or an Intel Mac, no matter what the OS), you get the wrong * answer, and you've used EXTRACT_BE_U_4(), do *N*O*T* "fix" this by using * EXTRACT_LE_U_4(), fix it by using EXTRACT_IPV4_TO_NETWORK_ORDER(), * otherwise you're breaking the result on big-endian machines (e.g., * most PowerPC/Power ISA machines, System/390 and z/Architecture, SPARC, * etc.). * * Yes, people do this; that's why Wireshark has tvb_get_ipv4(), to extract * an IPv4 address from a packet data buffer; it was introduced in reaction * to somebody who *had* done that. */ typedef unsigned char nd_ipv4[4]; /* * Use this for IPv6 addresses and netmasks. */ typedef unsigned char nd_ipv6[16]; /* * Use this for MAC addresses. */ #define MAC_ADDR_LEN 6U /* length of MAC addresses */ typedef unsigned char nd_mac_addr[MAC_ADDR_LEN]; /* * Use this for blobs of bytes; make them arrays of nd_byte. */ typedef unsigned char nd_byte; /* * Round up x to a multiple of y; y must be a power of 2. */ #ifndef roundup2 #define roundup2(x, y) (((x)+((u_int)((y)-1)))&(~((u_int)((y)-1)))) #endif #include #include #include "ip.h" /* struct ip for nextproto4_cksum() */ #include "ip6.h" /* struct ip6 for nextproto6_cksum() */ #ifndef HAVE_STRLCAT extern size_t strlcat (char *, const char *, size_t); #endif #ifndef HAVE_STRLCPY extern size_t strlcpy (char *, const char *, size_t); #endif #ifndef HAVE_STRDUP extern char *strdup (const char *str); #endif #ifndef HAVE_STRSEP extern char *strsep(char **, const char *); #endif struct tok { u_int v; /* value */ const char *s; /* string */ }; extern const char *tok2strbuf(const struct tok *, const char *, u_int, char *buf, size_t bufsize); /* tok2str is deprecated */ extern const char *tok2str(const struct tok *, const char *, u_int); extern char *bittok2str(const struct tok *, const char *, u_int); extern char *bittok2str_nosep(const struct tok *, const char *, u_int); /* Initialize netdissect. */ extern int nd_init(char *, size_t); /* Clean up netdissect. */ extern void nd_cleanup(void); /* Do we have libsmi support? */ extern int nd_have_smi_support(void); /* Load an SMI module. */ extern int nd_load_smi_module(const char *, char *, size_t); /* Flag indicating whether an SMI module has been loaded. */ extern int nd_smi_module_loaded; /* Version number of the SMI library, or NULL if we don't have libsmi support. */ extern const char *nd_smi_version_string(void); typedef struct netdissect_options netdissect_options; #define IF_PRINTER_ARGS (netdissect_options *, const struct pcap_pkthdr *, const u_char *) typedef void (*if_printer) IF_PRINTER_ARGS; /* * In case the data in a buffer needs to be processed by being decrypted, * decompressed, etc. before it's dissected, we can't process it in place, * we have to allocate a new buffer for the processed data. * * We keep a stack of those buffers; when we allocate a new buffer, we * push the current one onto a stack, and when we're done with the new * buffer, we free the current buffer and pop the previous one off the * stack. * * A buffer has a beginnning and end pointer, and a link to the previous * buffer on the stack. * * In other cases, we temporarily adjust the snapshot end to reflect a * packet-length field in the packet data and, when finished dissecting * that part of the packet, restore the old snapshot end. We keep that * on the stack with null buffer pointer, meaning there's nothing to * free. */ struct netdissect_saved_packet_info { u_char *ndspi_buffer; /* pointer to allocated buffer data */ const u_char *ndspi_packetp; /* saved beginning of data */ const u_char *ndspi_snapend; /* saved end of data */ struct netdissect_saved_packet_info *ndspi_prev; /* previous buffer on the stack */ }; /* 'val' value(s) for longjmp */ #define ND_TRUNCATED 1 struct netdissect_options { int ndo_bflag; /* print 4 byte ASes in ASDOT notation */ int ndo_eflag; /* print ethernet header */ int ndo_fflag; /* don't translate "foreign" IP address */ int ndo_Kflag; /* don't check IP, TCP or UDP checksums */ int ndo_nflag; /* leave addresses as numbers */ int ndo_Nflag; /* remove domains from printed host names */ int ndo_qflag; /* quick (shorter) output */ int ndo_Sflag; /* print raw TCP sequence numbers */ int ndo_tflag; /* print packet arrival time */ int ndo_uflag; /* Print undecoded NFS handles */ int ndo_vflag; /* verbosity level */ int ndo_xflag; /* print packet in hex */ int ndo_Xflag; /* print packet in hex/ASCII */ int ndo_Aflag; /* print packet only in ASCII observing TAB, * LF, CR and SPACE as graphical chars */ int ndo_Hflag; /* dissect 802.11s draft mesh standard */ const char *ndo_protocol; /* protocol */ jmp_buf ndo_early_end; /* jmp_buf for setjmp()/longjmp() */ void *ndo_last_mem_p; /* pointer to the last allocated memory chunk */ int ndo_packet_number; /* print a packet number in the beginning of line */ int ndo_suppress_default_print; /* don't use default_print() for unknown packet types */ int ndo_tstamp_precision; /* requested time stamp precision */ const char *program_name; /* Name of the program using the library */ char *ndo_espsecret; struct sa_list *ndo_sa_list_head; /* used by print-esp.c */ struct sa_list *ndo_sa_default; char *ndo_sigsecret; /* Signature verification secret key */ int ndo_packettype; /* as specified by -T */ int ndo_snaplen; int ndo_ll_hdr_len; /* link-layer header length */ /*global pointers to beginning and end of current packet (during printing) */ const u_char *ndo_packetp; const u_char *ndo_snapend; /* stack of saved packet boundary and buffer information */ struct netdissect_saved_packet_info *ndo_packet_info_stack; /* pointer to the if_printer function */ if_printer ndo_if_printer; /* pointer to void function to output stuff */ void (*ndo_default_print)(netdissect_options *, const u_char *bp, u_int length); /* pointer to function to do regular output */ int (*ndo_printf)(netdissect_options *, const char *fmt, ...) PRINTFLIKE_FUNCPTR(2, 3); /* pointer to function to output errors */ void NORETURN_FUNCPTR (*ndo_error)(netdissect_options *, status_exit_codes_t status, const char *fmt, ...) PRINTFLIKE_FUNCPTR(3, 4); /* pointer to function to output warnings */ void (*ndo_warning)(netdissect_options *, const char *fmt, ...) PRINTFLIKE_FUNCPTR(2, 3); }; extern int nd_push_buffer(netdissect_options *, u_char *, const u_char *, const u_char *); extern int nd_push_snapend(netdissect_options *, const u_char *); extern void nd_change_snapend(netdissect_options *, const u_char *); extern void nd_pop_packet_info(netdissect_options *); extern void nd_pop_all_packet_info(netdissect_options *); #define PT_VAT 1 /* Visual Audio Tool */ #define PT_WB 2 /* distributed White Board */ #define PT_RPC 3 /* Remote Procedure Call */ #define PT_RTP 4 /* Real-Time Applications protocol */ #define PT_RTCP 5 /* Real-Time Applications control protocol */ #define PT_SNMP 6 /* Simple Network Management Protocol */ #define PT_CNFP 7 /* Cisco NetFlow protocol */ #define PT_TFTP 8 /* trivial file transfer protocol */ #define PT_AODV 9 /* Ad-hoc On-demand Distance Vector Protocol */ #define PT_CARP 10 /* Common Address Redundancy Protocol */ #define PT_RADIUS 11 /* RADIUS authentication Protocol */ #define PT_ZMTP1 12 /* ZeroMQ Message Transport Protocol 1.0 */ #define PT_VXLAN 13 /* Virtual eXtensible Local Area Network */ #define PT_PGM 14 /* [UDP-encapsulated] Pragmatic General Multicast */ #define PT_PGM_ZMTP1 15 /* ZMTP/1.0 inside PGM (native or UDP-encapsulated) */ #define PT_LMP 16 /* Link Management Protocol */ #define PT_RESP 17 /* RESP */ #define PT_PTP 18 /* PTP */ #define PT_SOMEIP 19 /* Autosar SOME/IP Protocol */ #define PT_DOMAIN 20 /* Domain Name System (DNS) */ #define ND_MIN(a,b) ((a)>(b)?(b):(a)) #define ND_MAX(a,b) ((b)>(a)?(b):(a)) /* For source or destination ports tests (UDP, TCP, ...) */ #define IS_SRC_OR_DST_PORT(p) (sport == (p) || dport == (p)) /* * Maximum snapshot length. This should be enough to capture the full * packet on most network interfaces. * * * Somewhat arbitrary, but chosen to be: * * 1) big enough for maximum-size Linux loopback packets (65549) * and some USB packets captured with USBPcap: * * https://desowin.org/usbpcap/ * * (> 131072, < 262144) * * and * * 2) small enough not to cause attempts to allocate huge amounts of * memory; some applications might use the snapshot length in a * savefile header to control the size of the buffer they allocate, * so a size of, say, 2^31-1 might not work well. * * XXX - does it need to be bigger still? Note that, for versions of * libpcap with pcap_create()/pcap_activate(), if no -s flag is specified * or -s 0 is specified, we won't set the snapshot length at all, and will * let libpcap choose a snapshot length; newer versions may choose a bigger * value than 262144 for D-Bus, for example. */ #define MAXIMUM_SNAPLEN 262144 /* * True if "l" bytes from "p" were captured. * * The "ndo->ndo_snapend - (l) <= ndo->ndo_snapend" checks to make sure * "l" isn't so large that "ndo->ndo_snapend - (l)" underflows. * * The check is for <= rather than < because "l" might be 0. * * We cast the pointers to uintptr_t to make sure that the compiler * doesn't optimize away any of these tests (which it is allowed to * do, as adding an integer to, or subtracting an integer from, a * pointer assumes that the pointer is a pointer to an element of an * array and that the result of the addition or subtraction yields a * pointer to another member of the array, so that, for example, if * you subtract a positive integer from a pointer, the result is * guaranteed to be less than the original pointer value). See * * https://www.kb.cert.org/vuls/id/162289 */ /* * Test in two parts to avoid these warnings: * comparison of unsigned expression >= 0 is always true [-Wtype-limits], * comparison is always true due to limited range of data type [-Wtype-limits]. */ #define IS_NOT_NEGATIVE(x) (((x) > 0) || ((x) == 0)) #define ND_TTEST_LEN(p, l) \ (IS_NOT_NEGATIVE(l) && \ ((uintptr_t)ndo->ndo_snapend - (l) <= (uintptr_t)ndo->ndo_snapend && \ (uintptr_t)(p) <= (uintptr_t)ndo->ndo_snapend - (l))) /* True if "*(p)" was captured */ #define ND_TTEST_SIZE(p) ND_TTEST_LEN(p, sizeof(*(p))) /* Bail out if "l" bytes from "p" were not captured */ #ifdef ND_LONGJMP_FROM_TCHECK #define ND_TCHECK_LEN(p, l) if (!ND_TTEST_LEN(p, l)) nd_trunc_longjmp(ndo) #else #define ND_TCHECK_LEN(p, l) if (!ND_TTEST_LEN(p, l)) goto trunc #endif /* Bail out if "*(p)" was not captured */ #define ND_TCHECK_SIZE(p) ND_TCHECK_LEN(p, sizeof(*(p))) /* * Number of bytes between two pointers. */ #define ND_BYTES_BETWEEN(p1, p2) ((u_int)(((const uint8_t *)(p1)) - (const uint8_t *)(p2))) /* * Number of bytes remaining in the captured data, starting at the * byte pointed to by the argument. */ #define ND_BYTES_AVAILABLE_AFTER(p) ND_BYTES_BETWEEN(ndo->ndo_snapend, (p)) #define ND_PRINT(...) (ndo->ndo_printf)(ndo, __VA_ARGS__) #define ND_DEFAULTPRINT(ap, length) (*ndo->ndo_default_print)(ndo, ap, length) extern void ts_print(netdissect_options *, const struct timeval *); extern void signed_relts_print(netdissect_options *, int32_t); extern void unsigned_relts_print(netdissect_options *, uint32_t); extern void fn_print_char(netdissect_options *, u_char); extern void fn_print_str(netdissect_options *, const u_char *); extern u_int nd_printztn(netdissect_options *, const u_char *, u_int, const u_char *); extern int nd_printn(netdissect_options *, const u_char *, u_int, const u_char *); extern void nd_printjnp(netdissect_options *, const u_char *, u_int); /* * Flags for txtproto_print(). */ #define RESP_CODE_SECOND_TOKEN 0x00000001 /* response code is second token in response line */ extern void txtproto_print(netdissect_options *, const u_char *, u_int, const char **, u_int); #if (defined(__i386__) || defined(_M_IX86) || defined(__X86__) || defined(__x86_64__) || defined(_M_X64)) || \ (defined(__arm__) || defined(_M_ARM) || defined(__aarch64__)) || \ (defined(__m68k__) && (!defined(__mc68000__) && !defined(__mc68010__))) || \ (defined(__ppc__) || defined(__ppc64__) || defined(_M_PPC) || defined(_ARCH_PPC) || defined(_ARCH_PPC64)) || \ (defined(__s390__) || defined(__s390x__) || defined(__zarch__)) || \ defined(__vax__) /* * The procesor natively handles unaligned loads, so just use memcpy() * and memcmp(), to enable those optimizations. * * XXX - are those all the x86 tests we need? * XXX - do we need to worry about ARMv1 through ARMv5, which didn't * support unaligned loads, and, if so, do we need to worry about all * of them, or just some of them, e.g. ARMv5? * XXX - are those the only 68k tests we need not to generated * unaligned accesses if the target is the 68000 or 68010? * XXX - are there any tests we don't need, because some definitions are for * compilers that also predefine the GCC symbols? * XXX - do we need to test for both 32-bit and 64-bit versions of those * architectures in all cases? */ #define UNALIGNED_MEMCPY(p, q, l) memcpy((p), (q), (l)) #define UNALIGNED_MEMCMP(p, q, l) memcmp((p), (q), (l)) #else /* * The processor doesn't natively handle unaligned loads, * and the compiler might "helpfully" optimize memcpy() * and memcmp(), when handed pointers that would normally * be properly aligned, into sequences that assume proper * alignment. * * Do copies and compares of possibly-unaligned data by * calling routines that wrap memcpy() and memcmp(), to * prevent that optimization. */ extern void unaligned_memcpy(void *, const void *, size_t); extern int unaligned_memcmp(const void *, const void *, size_t); #define UNALIGNED_MEMCPY(p, q, l) unaligned_memcpy((p), (q), (l)) #define UNALIGNED_MEMCMP(p, q, l) unaligned_memcmp((p), (q), (l)) #endif #define PLURAL_SUFFIX(n) \ (((n) != 1) ? "s" : "") extern const char *tok2strary_internal(const char **, int, const char *, int); #define tok2strary(a,f,i) tok2strary_internal(a, sizeof(a)/sizeof(a[0]),f,i) struct uint_tokary { u_int uintval; const struct tok *tokary; }; extern const struct tok *uint2tokary_internal(const struct uint_tokary[], const size_t, const u_int); #define uint2tokary(a, i) uint2tokary_internal(a, sizeof(a)/sizeof(a[0]), i) extern if_printer lookup_printer(int); #define ND_DEBUG {printf(" [%s:%d %s] ", __FILE__, __LINE__, __func__); fflush(stdout);} /* The DLT printer routines */ extern void ap1394_if_print IF_PRINTER_ARGS; extern void arcnet_if_print IF_PRINTER_ARGS; extern void arcnet_linux_if_print IF_PRINTER_ARGS; extern void atm_if_print IF_PRINTER_ARGS; extern void bt_if_print IF_PRINTER_ARGS; extern void brcm_tag_if_print IF_PRINTER_ARGS; extern void brcm_tag_prepend_if_print IF_PRINTER_ARGS; extern void chdlc_if_print IF_PRINTER_ARGS; extern void cip_if_print IF_PRINTER_ARGS; extern void dsa_if_print IF_PRINTER_ARGS; extern void edsa_if_print IF_PRINTER_ARGS; extern void enc_if_print IF_PRINTER_ARGS; extern void ether_if_print IF_PRINTER_ARGS; extern void fddi_if_print IF_PRINTER_ARGS; extern void fr_if_print IF_PRINTER_ARGS; extern void ieee802_11_if_print IF_PRINTER_ARGS; extern void ieee802_11_radio_avs_if_print IF_PRINTER_ARGS; extern void ieee802_11_radio_if_print IF_PRINTER_ARGS; extern void ieee802_15_4_if_print IF_PRINTER_ARGS; extern void ieee802_15_4_tap_if_print IF_PRINTER_ARGS; extern void ipfc_if_print IF_PRINTER_ARGS; extern void ipoib_if_print IF_PRINTER_ARGS; extern void ipnet_if_print IF_PRINTER_ARGS; extern void juniper_atm1_if_print IF_PRINTER_ARGS; extern void juniper_atm2_if_print IF_PRINTER_ARGS; extern void juniper_chdlc_if_print IF_PRINTER_ARGS; extern void juniper_es_if_print IF_PRINTER_ARGS; extern void juniper_ether_if_print IF_PRINTER_ARGS; extern void juniper_frelay_if_print IF_PRINTER_ARGS; extern void juniper_ggsn_if_print IF_PRINTER_ARGS; extern void juniper_mfr_if_print IF_PRINTER_ARGS; extern void juniper_mlfr_if_print IF_PRINTER_ARGS; extern void juniper_mlppp_if_print IF_PRINTER_ARGS; extern void juniper_monitor_if_print IF_PRINTER_ARGS; extern void juniper_ppp_if_print IF_PRINTER_ARGS; extern void juniper_pppoe_atm_if_print IF_PRINTER_ARGS; extern void juniper_pppoe_if_print IF_PRINTER_ARGS; extern void juniper_services_if_print IF_PRINTER_ARGS; extern void ltalk_if_print IF_PRINTER_ARGS; extern void mfr_if_print IF_PRINTER_ARGS; extern void netanalyzer_if_print IF_PRINTER_ARGS; extern void netanalyzer_transparent_if_print IF_PRINTER_ARGS; extern void nflog_if_print IF_PRINTER_ARGS; extern void null_if_print IF_PRINTER_ARGS; extern void pflog_if_print IF_PRINTER_ARGS; extern void pktap_if_print IF_PRINTER_ARGS; extern void ppi_if_print IF_PRINTER_ARGS; extern void ppp_bsdos_if_print IF_PRINTER_ARGS; extern void ppp_hdlc_if_print IF_PRINTER_ARGS; extern void ppp_if_print IF_PRINTER_ARGS; extern void pppoe_if_print IF_PRINTER_ARGS; extern void prism_if_print IF_PRINTER_ARGS; extern void raw_if_print IF_PRINTER_ARGS; extern void sl_bsdos_if_print IF_PRINTER_ARGS; extern void sl_if_print IF_PRINTER_ARGS; extern void sll_if_print IF_PRINTER_ARGS; extern void sll2_if_print IF_PRINTER_ARGS; extern void sunatm_if_print IF_PRINTER_ARGS; extern void symantec_if_print IF_PRINTER_ARGS; extern void token_if_print IF_PRINTER_ARGS; extern void unsupported_if_print IF_PRINTER_ARGS; extern void usb_linux_48_byte_if_print IF_PRINTER_ARGS; extern void usb_linux_64_byte_if_print IF_PRINTER_ARGS; extern void vsock_if_print IF_PRINTER_ARGS; /* * Structure passed to some printers to allow them to print * link-layer address information if ndo_eflag isn't set * (because they are for protocols that don't have their * own addresses, so that we'd want to report link-layer * address information). * * This contains a pointer to an address and a pointer to a routine * to which we pass that pointer in order to get a string. */ struct lladdr_info { const char *(*addr_string)(netdissect_options *, const u_char *); const u_char *addr; }; /* The printer routines. */ extern void aarp_print(netdissect_options *, const u_char *, u_int); extern int ah_print(netdissect_options *, const u_char *); extern void ahcp_print(netdissect_options *, const u_char *, u_int); extern void aodv_print(netdissect_options *, const u_char *, u_int, int); extern void aoe_print(netdissect_options *, const u_char *, const u_int); extern int arista_ethertype_print(netdissect_options *,const u_char *, u_int); extern void arp_print(netdissect_options *, const u_char *, u_int, u_int); extern void ascii_print(netdissect_options *, const u_char *, u_int); extern void atalk_print(netdissect_options *, const u_char *, u_int); extern void atm_print(netdissect_options *, u_int, u_int, u_int, const u_char *, u_int, u_int); extern void babel_print(netdissect_options *, const u_char *, u_int); extern void bcm_li_print(netdissect_options *, const u_char *, u_int); extern void beep_print(netdissect_options *, const u_char *, u_int); extern void bfd_print(netdissect_options *, const u_char *, u_int, u_int); extern void bgp_print(netdissect_options *, const u_char *, u_int); extern const char *bgp_vpn_rd_print(netdissect_options *, const u_char *); extern void bootp_print(netdissect_options *, const u_char *, u_int); extern void calm_fast_print(netdissect_options *, const u_char *, u_int, const struct lladdr_info *); extern void carp_print(netdissect_options *, const u_char *, u_int, u_int); extern void cdp_print(netdissect_options *, const u_char *, u_int); extern void cfm_print(netdissect_options *, const u_char *, u_int); extern u_int chdlc_print(netdissect_options *, const u_char *, u_int); extern void cisco_autorp_print(netdissect_options *, const u_char *, u_int); extern void cnfp_print(netdissect_options *, const u_char *); extern void dccp_print(netdissect_options *, const u_char *, const u_char *, u_int); extern void decnet_print(netdissect_options *, const u_char *, u_int, u_int); extern void dhcp6_print(netdissect_options *, const u_char *, u_int); extern int dstopt_process(netdissect_options *, const u_char *); extern void dtp_print(netdissect_options *, const u_char *, u_int); extern void dvmrp_print(netdissect_options *, const u_char *, u_int); extern void eap_print(netdissect_options *, const u_char *, u_int); extern void eapol_print(netdissect_options *, const u_char *); extern void egp_print(netdissect_options *, const u_char *, u_int); extern void eigrp_print(netdissect_options *, const u_char *, u_int); extern void esp_print(netdissect_options *, const u_char *, u_int, const u_char *, u_int, int, u_int); extern u_int ether_print(netdissect_options *, const u_char *, u_int, u_int, void (*)(netdissect_options *, const u_char *), const u_char *); extern u_int ether_switch_tag_print(netdissect_options *, const u_char *, u_int, u_int, void (*)(netdissect_options *, const u_char *), u_int); extern int ethertype_print(netdissect_options *, u_short, const u_char *, u_int, u_int, const struct lladdr_info *, const struct lladdr_info *); extern u_int fddi_print(netdissect_options *, const u_char *, u_int, u_int); extern void forces_print(netdissect_options *, const u_char *, u_int); extern u_int fr_print(netdissect_options *, const u_char *, u_int); extern int frag6_print(netdissect_options *, const u_char *, const u_char *); extern void ftp_print(netdissect_options *, const u_char *, u_int); extern void geneve_print(netdissect_options *, const u_char *, u_int); extern void geonet_print(netdissect_options *, const u_char *, u_int, const struct lladdr_info *); extern void gre_print(netdissect_options *, const u_char *, u_int); extern int hbhopt_process(netdissect_options *, const u_char *, int *, uint32_t *); extern void hex_and_ascii_print(netdissect_options *, const char *, const u_char *, u_int); extern void hex_print(netdissect_options *, const char *ident, const u_char *cp, u_int); extern void hex_print_with_offset(netdissect_options *, const char *ident, const u_char *cp, u_int, u_int); extern void hncp_print(netdissect_options *, const u_char *, u_int); extern void hsrp_print(netdissect_options *, const u_char *, u_int); extern void http_print(netdissect_options *, const u_char *, u_int); extern void icmp6_print(netdissect_options *, const u_char *, u_int, const u_char *, int); extern void icmp_print(netdissect_options *, const u_char *, u_int, const u_char *, int); extern u_int ieee802_15_4_print(netdissect_options *, const u_char *, u_int); extern u_int ieee802_11_radio_print(netdissect_options *, const u_char *, u_int, u_int); extern void igmp_print(netdissect_options *, const u_char *, u_int); extern void igrp_print(netdissect_options *, const u_char *, u_int); extern void ip6_print(netdissect_options *, const u_char *, u_int); extern void ipN_print(netdissect_options *, const u_char *, u_int); extern void ip_print(netdissect_options *, const u_char *, u_int); extern void ipcomp_print(netdissect_options *, const u_char *); extern void ipx_netbios_print(netdissect_options *, const u_char *, u_int); extern void ipx_print(netdissect_options *, const u_char *, u_int); extern void isakmp_print(netdissect_options *, const u_char *, u_int, const u_char *); extern void isakmp_rfc3948_print(netdissect_options *, const u_char *, u_int, const u_char *, int, int, u_int); extern void isoclns_print(netdissect_options *, const u_char *, u_int); extern void krb_print(netdissect_options *, const u_char *); extern void l2tp_print(netdissect_options *, const u_char *, u_int); extern void lane_print(netdissect_options *, const u_char *, u_int, u_int); extern void ldp_print(netdissect_options *, const u_char *, u_int); extern void lisp_print(netdissect_options *, const u_char *, u_int); extern u_int llap_print(netdissect_options *, const u_char *, u_int); extern int llc_print(netdissect_options *, const u_char *, u_int, u_int, const struct lladdr_info *, const struct lladdr_info *); extern void lldp_print(netdissect_options *, const u_char *, u_int); extern void lmp_print(netdissect_options *, const u_char *, u_int); extern void loopback_print(netdissect_options *, const u_char *, u_int); extern void lspping_print(netdissect_options *, const u_char *, u_int); extern void lwapp_control_print(netdissect_options *, const u_char *, u_int, int); extern void lwapp_data_print(netdissect_options *, const u_char *, u_int); extern void lwres_print(netdissect_options *, const u_char *, u_int); extern void m3ua_print(netdissect_options *, const u_char *, const u_int); extern int macsec_print(netdissect_options *, const u_char **, u_int *, u_int *, u_int *, const struct lladdr_info *, const struct lladdr_info *); extern u_int mfr_print(netdissect_options *, const u_char *, u_int); extern void mobile_print(netdissect_options *, const u_char *, u_int); extern int mobility_print(netdissect_options *, const u_char *, const u_char *); extern void mpcp_print(netdissect_options *, const u_char *, u_int); extern void mpls_print(netdissect_options *, const u_char *, u_int); extern int mptcp_print(netdissect_options *, const u_char *, u_int, u_char); extern void msdp_print(netdissect_options *, const u_char *, u_int); extern void msnlb_print(netdissect_options *, const u_char *); extern void nbt_tcp_print(netdissect_options *, const u_char *, u_int); extern void nbt_udp137_print(netdissect_options *, const u_char *, u_int); extern void nbt_udp138_print(netdissect_options *, const u_char *, u_int); extern void netbeui_print(netdissect_options *, u_short, const u_char *, u_int); extern void nfsreply_print(netdissect_options *, const u_char *, u_int, const u_char *); extern void nfsreply_noaddr_print(netdissect_options *, const u_char *, u_int, const u_char *); extern void nfsreq_noaddr_print(netdissect_options *, const u_char *, u_int, const u_char *); extern const u_char *fqdn_print(netdissect_options *, const u_char *, const u_char *); extern void domain_print(netdissect_options *, const u_char *, u_int, int, int); extern void nsh_print(netdissect_options *, const u_char *, u_int); extern void ntp_print(netdissect_options *, const u_char *, u_int); extern void oam_print(netdissect_options *, const u_char *, u_int, u_int); extern void olsr_print(netdissect_options *, const u_char *, u_int, int); extern void openflow_print(netdissect_options *, const u_char *, u_int); extern void ospf6_print(netdissect_options *, const u_char *, u_int); extern void ospf_print(netdissect_options *, const u_char *, u_int, const u_char *); extern int ospf_grace_lsa_print(netdissect_options *, const u_char *, u_int); extern int ospf_te_lsa_print(netdissect_options *, const u_char *, u_int); extern void otv_print(netdissect_options *, const u_char *, u_int); extern void pgm_print(netdissect_options *, const u_char *, u_int, const u_char *); extern void pim_print(netdissect_options *, const u_char *, u_int, const u_char *); extern void pimv1_print(netdissect_options *, const u_char *, u_int); extern u_int ppp_print(netdissect_options *, const u_char *, u_int); extern u_int pppoe_print(netdissect_options *, const u_char *, u_int); extern void pptp_print(netdissect_options *, const u_char *); extern void ptp_print(netdissect_options *, const u_char *, u_int); extern int print_unknown_data(netdissect_options *, const u_char *, const char *, u_int); extern const char *q922_string(netdissect_options *, const u_char *, u_int); extern void q933_print(netdissect_options *, const u_char *, u_int); extern void radius_print(netdissect_options *, const u_char *, u_int); extern void resp_print(netdissect_options *, const u_char *, u_int); extern void rip_print(netdissect_options *, const u_char *, u_int); extern void ripng_print(netdissect_options *, const u_char *, unsigned int); extern void rpki_rtr_print(netdissect_options *, const u_char *, u_int); extern void rrcp_print(netdissect_options *, const u_char *, u_int, const struct lladdr_info *, const struct lladdr_info *); extern void rsvp_print(netdissect_options *, const u_char *, u_int); extern int rt6_print(netdissect_options *, const u_char *, const u_char *); extern void rtsp_print(netdissect_options *, const u_char *, u_int); extern void rx_print(netdissect_options *, const u_char *, u_int, uint16_t, uint16_t, const u_char *); extern void sctp_print(netdissect_options *, const u_char *, const u_char *, u_int); extern void sflow_print(netdissect_options *, const u_char *, u_int); extern void ssh_print(netdissect_options *, const u_char *, u_int); extern void sip_print(netdissect_options *, const u_char *, u_int); extern void slow_print(netdissect_options *, const u_char *, u_int); extern void smb_tcp_print(netdissect_options *, const u_char *, u_int); extern void smtp_print(netdissect_options *, const u_char *, u_int); extern int snap_print(netdissect_options *, const u_char *, u_int, u_int, const struct lladdr_info *, const struct lladdr_info *, u_int); extern void snmp_print(netdissect_options *, const u_char *, u_int); extern void stp_print(netdissect_options *, const u_char *, u_int); extern void sunrpc_print(netdissect_options *, const u_char *, u_int, const u_char *); extern void syslog_print(netdissect_options *, const u_char *, u_int); extern void tcp_print(netdissect_options *, const u_char *, u_int, const u_char *, int); extern void telnet_print(netdissect_options *, const u_char *, u_int); extern void tftp_print(netdissect_options *, const u_char *, u_int); extern void timed_print(netdissect_options *, const u_char *); extern void tipc_print(netdissect_options *, const u_char *, u_int, u_int); extern u_int token_print(netdissect_options *, const u_char *, u_int, u_int); extern void udld_print(netdissect_options *, const u_char *, u_int); extern void udp_print(netdissect_options *, const u_char *, u_int, const u_char *, int, u_int); extern int vjc_print(netdissect_options *, const u_char *, u_short); extern void vqp_print(netdissect_options *, const u_char *, u_int); extern void vrrp_print(netdissect_options *, const u_char *, u_int, const u_char *, int); extern void vtp_print(netdissect_options *, const u_char *, const u_int); extern void vxlan_gpe_print(netdissect_options *, const u_char *, u_int); extern void vxlan_print(netdissect_options *, const u_char *, u_int); extern void wb_print(netdissect_options *, const u_char *, u_int); extern void zep_print(netdissect_options *, const u_char *, u_int); extern void zephyr_print(netdissect_options *, const u_char *, u_int); extern void zmtp1_print(netdissect_options *, const u_char *, u_int); extern void zmtp1_datagram_print(netdissect_options *, const u_char *, const u_int); extern void someip_print(netdissect_options *, const u_char *, const u_int); /* checksum routines */ extern void init_checksum(void); extern uint16_t verify_crc10_cksum(uint16_t, const u_char *, int); extern uint16_t create_osi_cksum(const uint8_t *, int, int); struct cksum_vec { const uint8_t *ptr; int len; }; extern uint16_t in_cksum(const struct cksum_vec *, int); extern uint16_t in_cksum_shouldbe(uint16_t, uint16_t); /* IP protocol demuxing routines */ extern void ip_demux_print(netdissect_options *, const u_char *, u_int, u_int, int, u_int, uint8_t, const u_char *); extern uint16_t nextproto4_cksum(netdissect_options *, const struct ip *, const uint8_t *, u_int, u_int, uint8_t); /* in print-ip6.c */ extern uint16_t nextproto6_cksum(netdissect_options *, const struct ip6_hdr *, const uint8_t *, u_int, u_int, uint8_t); /* Utilities */ extern void nd_print_trunc(netdissect_options *); extern void nd_print_protocol(netdissect_options *); extern void nd_print_protocol_caps(netdissect_options *); extern void nd_print_invalid(netdissect_options *); extern int mask2plen(uint32_t); extern int mask62plen(const u_char *); extern const char *dnnum_string(netdissect_options *, u_short); extern int decode_prefix4(netdissect_options *, const u_char *, u_int, char *, size_t); extern int decode_prefix6(netdissect_options *, const u_char *, u_int, char *, size_t); extern void esp_decodesecret_print(netdissect_options *); extern int esp_decrypt_buffer_by_ikev2_print(netdissect_options *, int, const u_char spii[8], const u_char spir[8], const u_char *, const u_char *); #endif /* netdissect_h */ tcpdump-4.99.1/oui.h0000644000026300017510000001242614057477727012413 0ustar mcrmcr/* * 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, and (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. * 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. * * Original code by Hannes Gredler (hannes@gredler.at) */ extern const struct tok oui_values[]; extern const struct tok smi_values[]; #define OUI_ENCAP_ETHER 0x000000 /* encapsulated Ethernet */ #define OUI_CISCO 0x00000c /* Cisco protocols */ #define OUI_IANA 0x00005E /* IANA */ #define OUI_NORTEL 0x000081 /* Nortel SONMP */ #define OUI_CISCO_90 0x0000f8 /* Cisco bridging */ #define OUI_RFC2684 0x0080c2 /* RFC 2427/2684 bridged Ethernet */ #define OUI_ATM_FORUM 0x00A03E /* ATM Forum */ #define OUI_CABLE_BPDU 0x00E02F /* DOCSIS spanning tree BPDU */ #define OUI_APPLETALK 0x080007 /* Appletalk */ #define OUI_JUNIPER 0x009069 /* Juniper */ #define OUI_HP 0x080009 /* Hewlett-Packard */ #define OUI_IEEE_8021_PRIVATE 0x0080c2 /* IEEE 802.1 Organisation Specific - Annex F */ #define OUI_IEEE_8023_PRIVATE 0x00120f /* IEEE 802.3 Organisation Specific - Annex G */ #define OUI_TIA 0x0012bb /* TIA - Telecommunications Industry Association - ANSI/TIA-1057- 2006 */ #define OUI_DCBX 0x001B21 /* DCBX */ #define OUI_NICIRA 0x002320 /* Nicira Networks */ #define OUI_BSN 0x5c16c7 /* Big Switch Networks */ #define OUI_VELLO 0xb0d2f5 /* Vello Systems */ #define OUI_HP2 0x002481 /* HP too */ #define OUI_HPLABS 0x0004ea /* HP-Labs */ #define OUI_INFOBLOX 0x748771 /* Infoblox Inc */ #define OUI_ONLAB 0xa42305 /* Open Networking Lab */ #define OUI_FREESCALE 0x00049f /* Freescale */ #define OUI_NETRONOME 0x0015ad /* Netronome */ #define OUI_BROADCOM 0x001018 /* Broadcom */ #define OUI_PMC_SIERRA 0x00e004 /* PMC-Sierra */ #define OUI_ERICSSON 0xd0f0db /* Ericsson */ /* * These are SMI Network Management Private Enterprise Codes for * organizations; see * * https://www.iana.org/assignments/enterprise-numbers * * for a list. * * List taken from Ethereal's epan/sminmpec.h. */ #define SMI_IETF 0 /* reserved - used by the IETF in L2TP? */ #define SMI_ACC 5 #define SMI_CISCO 9 #define SMI_HEWLETT_PACKARD 11 #define SMI_SUN_MICROSYSTEMS 42 #define SMI_MERIT 61 #define SMI_AT_AND_T 74 #define SMI_MOTOROLA 161 #define SMI_SHIVA 166 #define SMI_ERICSSON 193 #define SMI_CISCO_VPN5000 255 #define SMI_LIVINGSTON 307 #define SMI_MICROSOFT 311 #define SMI_3COM 429 #define SMI_ASCEND 529 #define SMI_BAY 1584 #define SMI_FOUNDRY 1991 #define SMI_VERSANET 2180 #define SMI_REDBACK 2352 #define SMI_JUNIPER 2636 #define SMI_APTIS 2637 #define SMI_DT_AG 2937 #define SMI_IXIA 3054 #define SMI_CISCO_VPN3000 3076 #define SMI_COSINE 3085 #define SMI_SHASTA 3199 #define SMI_NETSCREEN 3224 #define SMI_NOMADIX 3309 #define SMI_T_MOBILE 3414 #define SMI_BROADBAND_FORUM 3561 #define SMI_ZTE 3902 #define SMI_SIEMENS 4329 #define SMI_CABLELABS 4491 #define SMI_UNISPHERE 4874 #define SMI_CISCO_BBSM 5263 #define SMI_THE3GPP2 5535 #define SMI_SKT_TELECOM 5806 #define SMI_IP_UNPLUGGED 5925 #define SMI_ISSANNI 5948 #define SMI_NETSCALER 5951 #define SMI_DE_TE_MOBIL 6490 #define SMI_QUINTUM 6618 #define SMI_INTERLINK 6728 #define SMI_CNCTC 7951 #define SMI_STARENT_NETWORKS 8164 #define SMI_COLUBRIS 8744 #define SMI_THE3GPP 10415 #define SMI_GEMTEK_SYSTEMS 10529 #define SMI_BARRACUDA 10704 #define SMI_ERICSSON_PKT_CORE 10923 #define SMI_DACOM 11665 #define SMI_COLUMBIA_UNIVERSITY 11862 #define SMI_FORTINET 12356 #define SMI_VERIZON 12951 #define SMI_PLIXER 13745 #define SMI_WIFI_ALLIANCE 14122 #define SMI_T_SYSTEMS_NOVA 16787 #define SMI_CHINATELECOM_GUANZHOU 20942 #define SMI_GIGAMON 26866 #define SMI_CACE 32622 /* Greater than 32,767 need to be tagged unsigned. */ #define SMI_NTOP 35632u #define SMI_ERICSSON_CANADA_INC 46098u tcpdump-4.99.1/pcap-missing.h0000644000026300017510000000346314057477727014212 0ustar mcrmcr/* * Copyright (c) 1988-2002 * 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. */ #ifndef netdissect_pcap_missing_h #define netdissect_pcap_missing_h /* * Declarations of functions that might be missing from libpcap. */ #ifndef HAVE_PCAP_LIST_DATALINKS extern int pcap_list_datalinks(pcap_t *, int **); #endif #ifndef HAVE_PCAP_DATALINK_NAME_TO_VAL /* * We assume no platform has one but not the other. */ extern int pcap_datalink_name_to_val(const char *); extern const char *pcap_datalink_val_to_name(int); #endif #ifndef HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION extern const char *pcap_datalink_val_to_description(int); #endif #ifndef HAVE_PCAP_DUMP_FTELL extern long pcap_dump_ftell(pcap_dumper_t *); #endif #endif /* netdissect_pcap_missing_h */ tcpdump-4.99.1/print-rpki-rtr.c0000644000026300017510000002500314057477734014507 0ustar mcrmcr/* * Copyright (c) 1998-2011 The TCPDUMP project * * 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, and (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. * 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. * * Original code by Hannes Gredler (hannes@gredler.at) */ /* \summary: Resource Public Key Infrastructure (RPKI) to Router Protocol printer */ /* specification: RFC 6810 */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "extract.h" #include "addrtoname.h" /* * RPKI/Router PDU header * * Here's what the PDU header looks like. * The length does include the version and length fields. */ typedef struct rpki_rtr_pdu_ { nd_uint8_t version; /* Version number */ nd_uint8_t pdu_type; /* PDU type */ union { nd_uint16_t session_id; /* Session id */ nd_uint16_t error_code; /* Error code */ } u; nd_uint32_t length; } rpki_rtr_pdu; /* * IPv4 Prefix PDU. */ typedef struct rpki_rtr_pdu_ipv4_prefix_ { rpki_rtr_pdu pdu_header; nd_uint8_t flags; nd_uint8_t prefix_length; nd_uint8_t max_length; nd_uint8_t zero; nd_ipv4 prefix; nd_uint32_t as; } rpki_rtr_pdu_ipv4_prefix; /* * IPv6 Prefix PDU. */ typedef struct rpki_rtr_pdu_ipv6_prefix_ { rpki_rtr_pdu pdu_header; nd_uint8_t flags; nd_uint8_t prefix_length; nd_uint8_t max_length; nd_uint8_t zero; nd_ipv6 prefix; nd_uint32_t as; } rpki_rtr_pdu_ipv6_prefix; /* * Error report PDU. */ typedef struct rpki_rtr_pdu_error_report_ { rpki_rtr_pdu pdu_header; nd_uint32_t encapsulated_pdu_length; /* Encapsulated PDU length */ /* Copy of Erroneous PDU (variable, optional) */ /* Length of Error Text (4 octets in network byte order) */ /* Arbitrary Text of Error Diagnostic Message (variable, optional) */ } rpki_rtr_pdu_error_report; /* * PDU type codes */ #define RPKI_RTR_SERIAL_NOTIFY_PDU 0 #define RPKI_RTR_SERIAL_QUERY_PDU 1 #define RPKI_RTR_RESET_QUERY_PDU 2 #define RPKI_RTR_CACHE_RESPONSE_PDU 3 #define RPKI_RTR_IPV4_PREFIX_PDU 4 #define RPKI_RTR_IPV6_PREFIX_PDU 6 #define RPKI_RTR_END_OF_DATA_PDU 7 #define RPKI_RTR_CACHE_RESET_PDU 8 #define RPKI_RTR_ERROR_REPORT_PDU 10 static const struct tok rpki_rtr_pdu_values[] = { { RPKI_RTR_SERIAL_NOTIFY_PDU, "Serial Notify" }, { RPKI_RTR_SERIAL_QUERY_PDU, "Serial Query" }, { RPKI_RTR_RESET_QUERY_PDU, "Reset Query" }, { RPKI_RTR_CACHE_RESPONSE_PDU, "Cache Response" }, { RPKI_RTR_IPV4_PREFIX_PDU, "IPV4 Prefix" }, { RPKI_RTR_IPV6_PREFIX_PDU, "IPV6 Prefix" }, { RPKI_RTR_END_OF_DATA_PDU, "End of Data" }, { RPKI_RTR_CACHE_RESET_PDU, "Cache Reset" }, { RPKI_RTR_ERROR_REPORT_PDU, "Error Report" }, { 0, NULL} }; static const struct tok rpki_rtr_error_codes[] = { { 0, "Corrupt Data" }, { 1, "Internal Error" }, { 2, "No Data Available" }, { 3, "Invalid Request" }, { 4, "Unsupported Protocol Version" }, { 5, "Unsupported PDU Type" }, { 6, "Withdrawal of Unknown Record" }, { 7, "Duplicate Announcement Received" }, { 0, NULL} }; /* * Build a indentation string for a given indentation level. * XXX this should be really in util.c */ static char * indent_string (u_int indent) { static char buf[20]; u_int idx; idx = 0; buf[idx] = '\0'; /* * Does the static buffer fit ? */ if (sizeof(buf) < ((indent/8) + (indent %8) + 2)) { return buf; } /* * Heading newline. */ buf[idx] = '\n'; idx++; while (indent >= 8) { buf[idx] = '\t'; idx++; indent -= 8; } while (indent > 0) { buf[idx] = ' '; idx++; indent--; } /* * Trailing zero. */ buf[idx] = '\0'; return buf; } /* * Print a single PDU. */ static u_int rpki_rtr_pdu_print(netdissect_options *ndo, const u_char *tptr, const u_int len, const u_char recurse, const u_int indent) { const rpki_rtr_pdu *pdu_header; u_int pdu_type, pdu_len, hexdump; const u_char *msg; /* Protocol Version */ if (GET_U_1(tptr) != 0) { /* Skip the rest of the input buffer because even if this is * a well-formed PDU of a future RPKI-Router protocol version * followed by a well-formed PDU of RPKI-Router protocol * version 0, there is no way to know exactly how to skip the * current PDU. */ ND_PRINT("%sRPKI-RTRv%u (unknown)", indent_string(8), GET_U_1(tptr)); return len; } if (len < sizeof(rpki_rtr_pdu)) { ND_PRINT("(%u bytes is too few to decode)", len); goto invalid; } ND_TCHECK_LEN(tptr, sizeof(rpki_rtr_pdu)); pdu_header = (const rpki_rtr_pdu *)tptr; pdu_type = GET_U_1(pdu_header->pdu_type); pdu_len = GET_BE_U_4(pdu_header->length); /* Do not check bounds with pdu_len yet, do it in the case blocks * below to make it possible to decode at least the beginning of * a truncated Error Report PDU or a truncated encapsulated PDU. */ hexdump = FALSE; ND_PRINT("%sRPKI-RTRv%u, %s PDU (%u), length: %u", indent_string(8), GET_U_1(pdu_header->version), tok2str(rpki_rtr_pdu_values, "Unknown", pdu_type), pdu_type, pdu_len); if (pdu_len < sizeof(rpki_rtr_pdu) || pdu_len > len) goto invalid; switch (pdu_type) { /* * The following PDUs share the message format. */ case RPKI_RTR_SERIAL_NOTIFY_PDU: case RPKI_RTR_SERIAL_QUERY_PDU: case RPKI_RTR_END_OF_DATA_PDU: if (pdu_len != sizeof(rpki_rtr_pdu) + 4) goto invalid; msg = (const u_char *)(pdu_header + 1); ND_PRINT("%sSession ID: 0x%04x, Serial: %u", indent_string(indent+2), GET_BE_U_2(pdu_header->u.session_id), GET_BE_U_4(msg)); break; /* * The following PDUs share the message format. */ case RPKI_RTR_RESET_QUERY_PDU: case RPKI_RTR_CACHE_RESET_PDU: if (pdu_len != sizeof(rpki_rtr_pdu)) goto invalid; /* no additional boundary to check */ /* * Zero payload PDUs. */ break; case RPKI_RTR_CACHE_RESPONSE_PDU: if (pdu_len != sizeof(rpki_rtr_pdu)) goto invalid; /* no additional boundary to check */ ND_PRINT("%sSession ID: 0x%04x", indent_string(indent+2), GET_BE_U_2(pdu_header->u.session_id)); break; case RPKI_RTR_IPV4_PREFIX_PDU: { const rpki_rtr_pdu_ipv4_prefix *pdu; if (pdu_len != sizeof(rpki_rtr_pdu_ipv4_prefix)) goto invalid; pdu = (const rpki_rtr_pdu_ipv4_prefix *)tptr; ND_PRINT("%sIPv4 Prefix %s/%u-%u, origin-as %u, flags 0x%02x", indent_string(indent+2), GET_IPADDR_STRING(pdu->prefix), GET_U_1(pdu->prefix_length), GET_U_1(pdu->max_length), GET_BE_U_4(pdu->as), GET_U_1(pdu->flags)); } break; case RPKI_RTR_IPV6_PREFIX_PDU: { const rpki_rtr_pdu_ipv6_prefix *pdu; if (pdu_len != sizeof(rpki_rtr_pdu_ipv6_prefix)) goto invalid; pdu = (const rpki_rtr_pdu_ipv6_prefix *)tptr; ND_PRINT("%sIPv6 Prefix %s/%u-%u, origin-as %u, flags 0x%02x", indent_string(indent+2), GET_IP6ADDR_STRING(pdu->prefix), GET_U_1(pdu->prefix_length), GET_U_1(pdu->max_length), GET_BE_U_4(pdu->as), GET_U_1(pdu->flags)); } break; case RPKI_RTR_ERROR_REPORT_PDU: { const rpki_rtr_pdu_error_report *pdu; u_int encapsulated_pdu_length, text_length, tlen, error_code; tlen = sizeof(rpki_rtr_pdu); /* Do not test for the "Length of Error Text" data element yet. */ if (pdu_len < tlen + 4) goto invalid; ND_TCHECK_LEN(tptr, tlen + 4); /* Safe up to and including the "Length of Encapsulated PDU" * data element, more data elements may be present. */ pdu = (const rpki_rtr_pdu_error_report *)tptr; encapsulated_pdu_length = GET_BE_U_4(pdu->encapsulated_pdu_length); tlen += 4; error_code = GET_BE_U_2(pdu->pdu_header.u.error_code); ND_PRINT("%sError code: %s (%u), Encapsulated PDU length: %u", indent_string(indent+2), tok2str(rpki_rtr_error_codes, "Unknown", error_code), error_code, encapsulated_pdu_length); if (encapsulated_pdu_length) { /* Section 5.10 of RFC 6810 says: * "An Error Report PDU MUST NOT be sent for an Error Report PDU." * * However, as far as the protocol encoding goes Error Report PDUs can * happen to be nested in each other, however many times, in which case * the decoder should still print such semantically incorrect PDUs. * * That said, "the Erroneous PDU field MAY be truncated" (ibid), thus * to keep things simple this implementation decodes only the two * outermost layers of PDUs and makes bounds checks in the outer and * the inner PDU independently. */ if (pdu_len < tlen + encapsulated_pdu_length) goto invalid; if (! recurse) { ND_TCHECK_LEN(tptr, tlen + encapsulated_pdu_length); } else { ND_PRINT("%s-----encapsulated PDU-----", indent_string(indent+4)); rpki_rtr_pdu_print(ndo, tptr + tlen, encapsulated_pdu_length, 0, indent + 2); } tlen += encapsulated_pdu_length; } if (pdu_len < tlen + 4) goto invalid; ND_TCHECK_LEN(tptr, tlen + 4); /* Safe up to and including the "Length of Error Text" data element, * one more data element may be present. */ /* * Extract, trail-zero and print the Error message. */ text_length = GET_BE_U_4(tptr + tlen); tlen += 4; if (text_length) { if (pdu_len < tlen + text_length) goto invalid; /* nd_printn() makes the bounds check */ ND_PRINT("%sError text: ", indent_string(indent+2)); (void)nd_printn(ndo, tptr + tlen, text_length, NULL); } } break; default: ND_TCHECK_LEN(tptr, pdu_len); /* * Unknown data, please hexdump. */ hexdump = TRUE; } /* do we also want to see a hex dump ? */ if (ndo->ndo_vflag > 1 || (ndo->ndo_vflag && hexdump)) { print_unknown_data(ndo,tptr,"\n\t ", pdu_len); } return pdu_len; invalid: nd_print_invalid(ndo); ND_TCHECK_LEN(tptr, len); return len; } void rpki_rtr_print(netdissect_options *ndo, const u_char *pptr, u_int len) { ndo->ndo_protocol = "rpki_rtr"; if (!ndo->ndo_vflag) { ND_PRINT(", RPKI-RTR"); return; } while (len) { u_int pdu_len = rpki_rtr_pdu_print(ndo, pptr, len, 1, 8); len -= pdu_len; pptr += pdu_len; } } tcpdump-4.99.1/print-geonet.c0000644000026300017510000001500314057477727014217 0ustar mcrmcr/* * Copyright (c) 2013 The TCPDUMP project * * 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, and (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. * 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. * * Original code by Ola Martin Lykkja (ola.lykkja@q-free.com) */ /* \summary: ISO CALM FAST and ETSI GeoNetworking printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "extract.h" #include "addrtoname.h" /* ETSI TS 102 636-5-1 V1.1.1 (2011-02) Intelligent Transport Systems (ITS); Vehicular Communications; GeoNetworking; Part 5: Transport Protocols; Sub-part 1: Basic Transport Protocol ETSI TS 102 636-4-1 V1.1.1 (2011-06) Intelligent Transport Systems (ITS); Vehicular communications; GeoNetworking; Part 4: Geographical addressing and forwarding for point-to-point and point-to-multipoint communications; Sub-part 1: Media-Independent Functionality */ #define GEONET_ADDR_LEN 8 static const struct tok msg_type_values[] = { { 0, "CAM" }, { 1, "DENM" }, { 101, "TPEGM" }, { 102, "TSPDM" }, { 103, "VPM" }, { 104, "SRM" }, { 105, "SLAM" }, { 106, "ecoCAM" }, { 107, "ITM" }, { 150, "SA" }, { 0, NULL } }; static void print_btp_body(netdissect_options *ndo, const u_char *bp) { u_int msg_type; /* Assuming ItsPduHeader */ ND_PRINT("; ItsPduHeader v:%u", GET_U_1(bp)); msg_type = GET_U_1(bp + 1); ND_PRINT(" t:%u-%s", msg_type, tok2str(msg_type_values, "unknown (%u)", msg_type)); } /* EN 302 636-5-1 V2.2.1 Section 7.2: BTP-A header */ static void print_btp(netdissect_options *ndo, const u_char *bp) { ND_PRINT("; BTP Dst:%u", GET_BE_U_2(bp + 0)); ND_PRINT(" Src:%u", GET_BE_U_2(bp + 2)); } static void print_long_pos_vector(netdissect_options *ndo, const u_char *bp) { ND_PRINT("GN_ADDR:%s ", GET_LINKADDR_STRING(bp, LINKADDR_OTHER, GEONET_ADDR_LEN)); ND_PRINT("lat:%u ", GET_BE_U_4(bp + 12)); ND_PRINT("lon:%u", GET_BE_U_4(bp + 16)); } /* * This is the top level routine of the printer. 'p' points * to the geonet header of the packet. */ void geonet_print(netdissect_options *ndo, const u_char *bp, u_int length, const struct lladdr_info *src) { u_int version; u_int next_hdr; u_int hdr_type; u_int hdr_subtype; uint16_t payload_length; u_int hop_limit; const char *next_hdr_txt = "Unknown"; const char *hdr_type_txt = "Unknown"; int hdr_size = -1; ndo->ndo_protocol = "geonet"; ND_PRINT("GeoNet "); if (src != NULL) ND_PRINT("src:%s", (src->addr_string)(ndo, src->addr)); ND_PRINT("; "); /* Process Common Header */ if (length < 36) { ND_PRINT(" (common header length %u < 36)", length); goto invalid; } version = GET_U_1(bp) >> 4; next_hdr = GET_U_1(bp) & 0x0f; hdr_type = GET_U_1(bp + 1) >> 4; hdr_subtype = GET_U_1(bp + 1) & 0x0f; payload_length = GET_BE_U_2(bp + 4); hop_limit = GET_U_1(bp + 7); switch (next_hdr) { case 0: next_hdr_txt = "Any"; break; case 1: next_hdr_txt = "BTP-A"; break; case 2: next_hdr_txt = "BTP-B"; break; case 3: next_hdr_txt = "IPv6"; break; } switch (hdr_type) { case 0: hdr_type_txt = "Any"; break; case 1: hdr_type_txt = "Beacon"; break; case 2: hdr_type_txt = "GeoUnicast"; break; case 3: switch (hdr_subtype) { case 0: hdr_type_txt = "GeoAnycastCircle"; break; case 1: hdr_type_txt = "GeoAnycastRect"; break; case 2: hdr_type_txt = "GeoAnycastElipse"; break; } break; case 4: switch (hdr_subtype) { case 0: hdr_type_txt = "GeoBroadcastCircle"; break; case 1: hdr_type_txt = "GeoBroadcastRect"; break; case 2: hdr_type_txt = "GeoBroadcastElipse"; break; } break; case 5: switch (hdr_subtype) { case 0: hdr_type_txt = "TopoScopeBcast-SH"; break; case 1: hdr_type_txt = "TopoScopeBcast-MH"; break; } break; case 6: switch (hdr_subtype) { case 0: hdr_type_txt = "LocService-Request"; break; case 1: hdr_type_txt = "LocService-Reply"; break; } break; } ND_PRINT("v:%u ", version); ND_PRINT("NH:%u-%s ", next_hdr, next_hdr_txt); ND_PRINT("HT:%u-%u-%s ", hdr_type, hdr_subtype, hdr_type_txt); ND_PRINT("HopLim:%u ", hop_limit); ND_PRINT("Payload:%u ", payload_length); print_long_pos_vector(ndo, bp + 8); /* Skip Common Header */ ND_TCHECK_LEN(bp, 36); length -= 36; bp += 36; /* Process Extended Headers */ switch (hdr_type) { case 0: /* Any */ hdr_size = 0; break; case 1: /* Beacon */ hdr_size = 0; break; case 2: /* GeoUnicast */ break; case 3: switch (hdr_subtype) { case 0: /* GeoAnycastCircle */ break; case 1: /* GeoAnycastRect */ break; case 2: /* GeoAnycastElipse */ break; } break; case 4: switch (hdr_subtype) { case 0: /* GeoBroadcastCircle */ break; case 1: /* GeoBroadcastRect */ break; case 2: /* GeoBroadcastElipse */ break; } break; case 5: switch (hdr_subtype) { case 0: /* TopoScopeBcast-SH */ hdr_size = 0; break; case 1: /* TopoScopeBcast-MH */ hdr_size = 68 - 36; break; } break; case 6: switch (hdr_subtype) { case 0: /* LocService-Request */ break; case 1: /* LocService-Reply */ break; } break; } /* Skip Extended headers */ if (hdr_size >= 0) { if (length < (u_int)hdr_size) { ND_PRINT(" (header size %d > %u)", hdr_size, length); goto invalid; } ND_TCHECK_LEN(bp, hdr_size); length -= hdr_size; bp += hdr_size; switch (next_hdr) { case 0: /* Any */ break; case 1: case 2: /* BTP A/B */ if (length < 4) { ND_PRINT(" (BTP length %u < 4)", length); goto invalid; } print_btp(ndo, bp); length -= 4; bp += 4; if (length >= 2) { /* * XXX - did print_btp_body() * return if length < 2 * because this is optional, * or was that just not * reporting genuine errors? */ print_btp_body(ndo, bp); } break; case 3: /* IPv6 */ break; } } /* Print user data part */ if (ndo->ndo_vflag) ND_DEFAULTPRINT(bp, length); return; invalid: nd_print_invalid(ndo); /* XXX - print the remaining data as hex? */ } tcpdump-4.99.1/print-aodv.c0000644000026300017510000003752014057477734013675 0ustar mcrmcr/* * Copyright (c) 2003 Bruce M. Simpson * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Bruce M. Simpson. * 4. Neither the name of Bruce M. Simpson nor the names of co- * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY Bruce M. Simpson AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Bruce M. Simpson OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* \summary: Ad hoc On-Demand Distance Vector (AODV) Routing printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" #include "addrtoname.h" #include "extract.h" /* * RFC 3561 */ struct aodv_rreq { nd_uint8_t rreq_type; /* AODV message type (1) */ nd_uint8_t rreq_flags; /* various flags */ nd_uint8_t rreq_zero0; /* reserved, set to zero */ nd_uint8_t rreq_hops; /* number of hops from originator */ nd_uint32_t rreq_id; /* request ID */ nd_ipv4 rreq_da; /* destination IPv4 address */ nd_uint32_t rreq_ds; /* destination sequence number */ nd_ipv4 rreq_oa; /* originator IPv4 address */ nd_uint32_t rreq_os; /* originator sequence number */ }; struct aodv_rreq6 { nd_uint8_t rreq_type; /* AODV message type (1) */ nd_uint8_t rreq_flags; /* various flags */ nd_uint8_t rreq_zero0; /* reserved, set to zero */ nd_uint8_t rreq_hops; /* number of hops from originator */ nd_uint32_t rreq_id; /* request ID */ nd_ipv6 rreq_da; /* destination IPv6 address */ nd_uint32_t rreq_ds; /* destination sequence number */ nd_ipv6 rreq_oa; /* originator IPv6 address */ nd_uint32_t rreq_os; /* originator sequence number */ }; struct aodv_rreq6_draft_01 { nd_uint8_t rreq_type; /* AODV message type (16) */ nd_uint8_t rreq_flags; /* various flags */ nd_uint8_t rreq_zero0; /* reserved, set to zero */ nd_uint8_t rreq_hops; /* number of hops from originator */ nd_uint32_t rreq_id; /* request ID */ nd_uint32_t rreq_ds; /* destination sequence number */ nd_uint32_t rreq_os; /* originator sequence number */ nd_ipv6 rreq_da; /* destination IPv6 address */ nd_ipv6 rreq_oa; /* originator IPv6 address */ }; #define RREQ_JOIN 0x80 /* join (reserved for multicast */ #define RREQ_REPAIR 0x40 /* repair (reserved for multicast */ #define RREQ_GRAT 0x20 /* gratuitous RREP */ #define RREQ_DEST 0x10 /* destination only */ #define RREQ_UNKNOWN 0x08 /* unknown destination sequence num */ #define RREQ_FLAGS_MASK 0xF8 /* mask for rreq_flags */ struct aodv_rrep { nd_uint8_t rrep_type; /* AODV message type (2) */ nd_uint8_t rrep_flags; /* various flags */ nd_uint8_t rrep_ps; /* prefix size */ nd_uint8_t rrep_hops; /* number of hops from o to d */ nd_ipv4 rrep_da; /* destination IPv4 address */ nd_uint32_t rrep_ds; /* destination sequence number */ nd_ipv4 rrep_oa; /* originator IPv4 address */ nd_uint32_t rrep_life; /* lifetime of this route */ }; struct aodv_rrep6 { nd_uint8_t rrep_type; /* AODV message type (2) */ nd_uint8_t rrep_flags; /* various flags */ nd_uint8_t rrep_ps; /* prefix size */ nd_uint8_t rrep_hops; /* number of hops from o to d */ nd_ipv6 rrep_da; /* destination IPv6 address */ nd_uint32_t rrep_ds; /* destination sequence number */ nd_ipv6 rrep_oa; /* originator IPv6 address */ nd_uint32_t rrep_life; /* lifetime of this route */ }; struct aodv_rrep6_draft_01 { nd_uint8_t rrep_type; /* AODV message type (17) */ nd_uint8_t rrep_flags; /* various flags */ nd_uint8_t rrep_ps; /* prefix size */ nd_uint8_t rrep_hops; /* number of hops from o to d */ nd_uint32_t rrep_ds; /* destination sequence number */ nd_ipv6 rrep_da; /* destination IPv6 address */ nd_ipv6 rrep_oa; /* originator IPv6 address */ nd_uint32_t rrep_life; /* lifetime of this route */ }; #define RREP_REPAIR 0x80 /* repair (reserved for multicast */ #define RREP_ACK 0x40 /* acknowledgement required */ #define RREP_FLAGS_MASK 0xC0 /* mask for rrep_flags */ #define RREP_PREFIX_MASK 0x1F /* mask for prefix size */ struct rerr_unreach { nd_ipv4 u_da; /* IPv4 address */ nd_uint32_t u_ds; /* sequence number */ }; struct rerr_unreach6 { nd_ipv6 u_da; /* IPv6 address */ nd_uint32_t u_ds; /* sequence number */ }; struct rerr_unreach6_draft_01 { nd_ipv6 u_da; /* IPv6 address */ nd_uint32_t u_ds; /* sequence number */ }; struct aodv_rerr { nd_uint8_t rerr_type; /* AODV message type (3 or 18) */ nd_uint8_t rerr_flags; /* various flags */ nd_uint8_t rerr_zero0; /* reserved, set to zero */ nd_uint8_t rerr_dc; /* destination count */ }; #define RERR_NODELETE 0x80 /* don't delete the link */ #define RERR_FLAGS_MASK 0x80 /* mask for rerr_flags */ struct aodv_rrep_ack { nd_uint8_t ra_type; nd_uint8_t ra_zero0; }; #define AODV_RREQ 1 /* route request */ #define AODV_RREP 2 /* route response */ #define AODV_RERR 3 /* error report */ #define AODV_RREP_ACK 4 /* route response acknowledgement */ #define AODV_V6_DRAFT_01_RREQ 16 /* IPv6 route request */ #define AODV_V6_DRAFT_01_RREP 17 /* IPv6 route response */ #define AODV_V6_DRAFT_01_RERR 18 /* IPv6 error report */ #define AODV_V6_DRAFT_01_RREP_ACK 19 /* IPV6 route response acknowledgment */ struct aodv_ext { nd_uint8_t type; /* extension type */ nd_uint8_t length; /* extension length */ }; struct aodv_hello { struct aodv_ext eh; /* extension header */ nd_uint32_t interval; /* expect my next hello in * (n) ms * NOTE: this is not aligned */ }; #define AODV_EXT_HELLO 1 static void aodv_extension(netdissect_options *ndo, const struct aodv_ext *ep, u_int length) { const struct aodv_hello *ah; ND_TCHECK_SIZE(ep); switch (GET_U_1(ep->type)) { case AODV_EXT_HELLO: ah = (const struct aodv_hello *)(const void *)ep; ND_TCHECK_SIZE(ah); if (length < sizeof(struct aodv_hello)) goto trunc; if (GET_U_1(ep->length) < 4) { ND_PRINT("\n\text HELLO - bad length %u", GET_U_1(ep->length)); break; } ND_PRINT("\n\text HELLO %u ms", GET_BE_U_4(ah->interval)); break; default: ND_PRINT("\n\text %u %u", GET_U_1(ep->type), GET_U_1(ep->length)); break; } return; trunc: nd_print_trunc(ndo); } static void aodv_rreq(netdissect_options *ndo, const u_char *dat, u_int length) { u_int i; const struct aodv_rreq *ap = (const struct aodv_rreq *)dat; ND_TCHECK_SIZE(ap); if (length < sizeof(*ap)) goto trunc; ND_PRINT(" rreq %u %s%s%s%s%shops %u id 0x%08x\n" "\tdst %s seq %u src %s seq %u", length, GET_U_1(ap->rreq_type) & RREQ_JOIN ? "[J]" : "", GET_U_1(ap->rreq_type) & RREQ_REPAIR ? "[R]" : "", GET_U_1(ap->rreq_type) & RREQ_GRAT ? "[G]" : "", GET_U_1(ap->rreq_type) & RREQ_DEST ? "[D]" : "", GET_U_1(ap->rreq_type) & RREQ_UNKNOWN ? "[U] " : " ", GET_U_1(ap->rreq_hops), GET_BE_U_4(ap->rreq_id), GET_IPADDR_STRING(ap->rreq_da), GET_BE_U_4(ap->rreq_ds), GET_IPADDR_STRING(ap->rreq_oa), GET_BE_U_4(ap->rreq_os)); i = length - sizeof(*ap); if (i >= sizeof(struct aodv_ext)) aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); return; trunc: nd_print_trunc(ndo); } static void aodv_rrep(netdissect_options *ndo, const u_char *dat, u_int length) { u_int i; const struct aodv_rrep *ap = (const struct aodv_rrep *)dat; ND_TCHECK_SIZE(ap); if (length < sizeof(*ap)) goto trunc; ND_PRINT(" rrep %u %s%sprefix %u hops %u\n" "\tdst %s dseq %u src %s %u ms", length, GET_U_1(ap->rrep_type) & RREP_REPAIR ? "[R]" : "", GET_U_1(ap->rrep_type) & RREP_ACK ? "[A] " : " ", GET_U_1(ap->rrep_ps) & RREP_PREFIX_MASK, GET_U_1(ap->rrep_hops), GET_IPADDR_STRING(ap->rrep_da), GET_BE_U_4(ap->rrep_ds), GET_IPADDR_STRING(ap->rrep_oa), GET_BE_U_4(ap->rrep_life)); i = length - sizeof(*ap); if (i >= sizeof(struct aodv_ext)) aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); return; trunc: nd_print_trunc(ndo); } static void aodv_rerr(netdissect_options *ndo, const u_char *dat, u_int length) { u_int i, dc; const struct aodv_rerr *ap = (const struct aodv_rerr *)dat; const struct rerr_unreach *dp; ND_TCHECK_SIZE(ap); if (length < sizeof(*ap)) goto trunc; ND_PRINT(" rerr %s [items %u] [%u]:", GET_U_1(ap->rerr_flags) & RERR_NODELETE ? "[D]" : "", GET_U_1(ap->rerr_dc), length); dp = (const struct rerr_unreach *)(dat + sizeof(*ap)); i = length - sizeof(*ap); for (dc = GET_U_1(ap->rerr_dc); dc != 0; dc--) { ND_TCHECK_SIZE(dp); if (i < sizeof(*dp)) goto trunc; ND_PRINT(" {%s}(%u)", GET_IPADDR_STRING(dp->u_da), GET_BE_U_4(dp->u_ds)); dp++; i -= sizeof(*dp); } return; trunc: nd_print_trunc(ndo); } static void aodv_v6_rreq(netdissect_options *ndo, const u_char *dat, u_int length) { u_int i; const struct aodv_rreq6 *ap = (const struct aodv_rreq6 *)dat; ND_TCHECK_SIZE(ap); if (length < sizeof(*ap)) goto trunc; ND_PRINT(" v6 rreq %u %s%s%s%s%shops %u id 0x%08x\n" "\tdst %s seq %u src %s seq %u", length, GET_U_1(ap->rreq_type) & RREQ_JOIN ? "[J]" : "", GET_U_1(ap->rreq_type) & RREQ_REPAIR ? "[R]" : "", GET_U_1(ap->rreq_type) & RREQ_GRAT ? "[G]" : "", GET_U_1(ap->rreq_type) & RREQ_DEST ? "[D]" : "", GET_U_1(ap->rreq_type) & RREQ_UNKNOWN ? "[U] " : " ", GET_U_1(ap->rreq_hops), GET_BE_U_4(ap->rreq_id), GET_IP6ADDR_STRING(ap->rreq_da), GET_BE_U_4(ap->rreq_ds), GET_IP6ADDR_STRING(ap->rreq_oa), GET_BE_U_4(ap->rreq_os)); i = length - sizeof(*ap); if (i >= sizeof(struct aodv_ext)) aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); return; trunc: nd_print_trunc(ndo); } static void aodv_v6_rrep(netdissect_options *ndo, const u_char *dat, u_int length) { u_int i; const struct aodv_rrep6 *ap = (const struct aodv_rrep6 *)dat; ND_TCHECK_SIZE(ap); if (length < sizeof(*ap)) goto trunc; ND_PRINT(" rrep %u %s%sprefix %u hops %u\n" "\tdst %s dseq %u src %s %u ms", length, GET_U_1(ap->rrep_type) & RREP_REPAIR ? "[R]" : "", GET_U_1(ap->rrep_type) & RREP_ACK ? "[A] " : " ", GET_U_1(ap->rrep_ps) & RREP_PREFIX_MASK, GET_U_1(ap->rrep_hops), GET_IP6ADDR_STRING(ap->rrep_da), GET_BE_U_4(ap->rrep_ds), GET_IP6ADDR_STRING(ap->rrep_oa), GET_BE_U_4(ap->rrep_life)); i = length - sizeof(*ap); if (i >= sizeof(struct aodv_ext)) aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); return; trunc: nd_print_trunc(ndo); } static void aodv_v6_rerr(netdissect_options *ndo, const u_char *dat, u_int length) { u_int i, dc; const struct aodv_rerr *ap = (const struct aodv_rerr *)dat; const struct rerr_unreach6 *dp6; ND_TCHECK_SIZE(ap); if (length < sizeof(*ap)) goto trunc; ND_PRINT(" rerr %s [items %u] [%u]:", GET_U_1(ap->rerr_flags) & RERR_NODELETE ? "[D]" : "", GET_U_1(ap->rerr_dc), length); dp6 = (const struct rerr_unreach6 *)(const void *)(ap + 1); i = length - sizeof(*ap); for (dc = GET_U_1(ap->rerr_dc); dc != 0; dc--) { ND_TCHECK_SIZE(dp6); if (i < sizeof(*dp6)) goto trunc; ND_PRINT(" {%s}(%u)", GET_IP6ADDR_STRING(dp6->u_da), GET_BE_U_4(dp6->u_ds)); dp6++; i -= sizeof(*dp6); } return; trunc: nd_print_trunc(ndo); } static void aodv_v6_draft_01_rreq(netdissect_options *ndo, const u_char *dat, u_int length) { u_int i; const struct aodv_rreq6_draft_01 *ap = (const struct aodv_rreq6_draft_01 *)dat; ND_TCHECK_SIZE(ap); if (length < sizeof(*ap)) goto trunc; ND_PRINT(" rreq %u %s%s%s%s%shops %u id 0x%08x\n" "\tdst %s seq %u src %s seq %u", length, GET_U_1(ap->rreq_type) & RREQ_JOIN ? "[J]" : "", GET_U_1(ap->rreq_type) & RREQ_REPAIR ? "[R]" : "", GET_U_1(ap->rreq_type) & RREQ_GRAT ? "[G]" : "", GET_U_1(ap->rreq_type) & RREQ_DEST ? "[D]" : "", GET_U_1(ap->rreq_type) & RREQ_UNKNOWN ? "[U] " : " ", GET_U_1(ap->rreq_hops), GET_BE_U_4(ap->rreq_id), GET_IP6ADDR_STRING(ap->rreq_da), GET_BE_U_4(ap->rreq_ds), GET_IP6ADDR_STRING(ap->rreq_oa), GET_BE_U_4(ap->rreq_os)); i = length - sizeof(*ap); if (i >= sizeof(struct aodv_ext)) aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); return; trunc: nd_print_trunc(ndo); } static void aodv_v6_draft_01_rrep(netdissect_options *ndo, const u_char *dat, u_int length) { u_int i; const struct aodv_rrep6_draft_01 *ap = (const struct aodv_rrep6_draft_01 *)dat; ND_TCHECK_SIZE(ap); if (length < sizeof(*ap)) goto trunc; ND_PRINT(" rrep %u %s%sprefix %u hops %u\n" "\tdst %s dseq %u src %s %u ms", length, GET_U_1(ap->rrep_type) & RREP_REPAIR ? "[R]" : "", GET_U_1(ap->rrep_type) & RREP_ACK ? "[A] " : " ", GET_U_1(ap->rrep_ps) & RREP_PREFIX_MASK, GET_U_1(ap->rrep_hops), GET_IP6ADDR_STRING(ap->rrep_da), GET_BE_U_4(ap->rrep_ds), GET_IP6ADDR_STRING(ap->rrep_oa), GET_BE_U_4(ap->rrep_life)); i = length - sizeof(*ap); if (i >= sizeof(struct aodv_ext)) aodv_extension(ndo, (const struct aodv_ext *)(dat + sizeof(*ap)), i); return; trunc: nd_print_trunc(ndo); } static void aodv_v6_draft_01_rerr(netdissect_options *ndo, const u_char *dat, u_int length) { u_int i, dc; const struct aodv_rerr *ap = (const struct aodv_rerr *)dat; const struct rerr_unreach6_draft_01 *dp6; ND_TCHECK_SIZE(ap); if (length < sizeof(*ap)) goto trunc; ND_PRINT(" rerr %s [items %u] [%u]:", GET_U_1(ap->rerr_flags) & RERR_NODELETE ? "[D]" : "", GET_U_1(ap->rerr_dc), length); dp6 = (const struct rerr_unreach6_draft_01 *)(const void *)(ap + 1); i = length - sizeof(*ap); for (dc = GET_U_1(ap->rerr_dc); dc != 0; dc--) { ND_TCHECK_SIZE(dp6); if (i < sizeof(*dp6)) goto trunc; ND_PRINT(" {%s}(%u)", GET_IP6ADDR_STRING(dp6->u_da), GET_BE_U_4(dp6->u_ds)); dp6++; i -= sizeof(*dp6); } return; trunc: nd_print_trunc(ndo); } void aodv_print(netdissect_options *ndo, const u_char *dat, u_int length, int is_ip6) { uint8_t msg_type; ndo->ndo_protocol = "aodv"; /* * The message type is the first byte; make sure we have it * and then fetch it. */ msg_type = GET_U_1(dat); ND_PRINT(" aodv"); switch (msg_type) { case AODV_RREQ: if (is_ip6) aodv_v6_rreq(ndo, dat, length); else aodv_rreq(ndo, dat, length); break; case AODV_RREP: if (is_ip6) aodv_v6_rrep(ndo, dat, length); else aodv_rrep(ndo, dat, length); break; case AODV_RERR: if (is_ip6) aodv_v6_rerr(ndo, dat, length); else aodv_rerr(ndo, dat, length); break; case AODV_RREP_ACK: ND_PRINT(" rrep-ack %u", length); break; case AODV_V6_DRAFT_01_RREQ: aodv_v6_draft_01_rreq(ndo, dat, length); break; case AODV_V6_DRAFT_01_RREP: aodv_v6_draft_01_rrep(ndo, dat, length); break; case AODV_V6_DRAFT_01_RERR: aodv_v6_draft_01_rerr(ndo, dat, length); break; case AODV_V6_DRAFT_01_RREP_ACK: ND_PRINT(" rrep-ack %u", length); break; default: ND_PRINT(" type %u %u", msg_type, length); } } tcpdump-4.99.1/print-juniper.c0000644000026300017510000015135514057477727014425 0ustar mcrmcr/* NetBSD: print-juniper.c,v 1.2 2007/07/24 11:53:45 drochner Exp */ /* * 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, and (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. * 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. * * Original code by Hannes Gredler (hannes@gredler.at) */ /* \summary: DLT_JUNIPER_* printers */ #ifndef lint #else __RCSID("NetBSD: print-juniper.c,v 1.3 2007/07/25 06:31:32 dogcow Exp "); #endif #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include #include "netdissect.h" #include "addrtoname.h" #include "extract.h" #include "ppp.h" #include "llc.h" #include "nlpid.h" #include "ethertype.h" #include "atm.h" /* * If none of the Juniper DLT_s are defined, there's nothing to do. */ #if defined(DLT_JUNIPER_GGSN) || defined(DLT_JUNIPER_ES) || \ defined(DLT_JUNIPER_MONITOR) || defined(DLT_JUNIPER_SERVICES) || \ defined(DLT_JUNIPER_PPPOE) || defined(DLT_JUNIPER_ETHER) || \ defined(DLT_JUNIPER_PPP) || defined(DLT_JUNIPER_FRELAY) || \ defined(DLT_JUNIPER_CHDLC) || defined(DLT_JUNIPER_PPPOE_ATM) || \ defined(DLT_JUNIPER_MLPPP) || defined(DLT_JUNIPER_MFR) || \ defined(DLT_JUNIPER_MLFR) || defined(DLT_JUNIPER_ATM1) || \ defined(DLT_JUNIPER_ATM2) #define JUNIPER_BPF_OUT 0 /* Outgoing packet */ #define JUNIPER_BPF_IN 1 /* Incoming packet */ #define JUNIPER_BPF_PKT_IN 0x1 /* Incoming packet */ #define JUNIPER_BPF_NO_L2 0x2 /* L2 header stripped */ #define JUNIPER_BPF_IIF 0x4 /* IIF is valid */ #define JUNIPER_BPF_FILTER 0x40 /* BPF filtering is supported */ #define JUNIPER_BPF_EXT 0x80 /* extensions present */ #define JUNIPER_MGC_NUMBER 0x4d4743 /* = "MGC" */ #define JUNIPER_LSQ_COOKIE_RE (1 << 3) #define JUNIPER_LSQ_COOKIE_DIR (1 << 2) #define JUNIPER_LSQ_L3_PROTO_SHIFT 4 #define JUNIPER_LSQ_L3_PROTO_MASK (0x17 << JUNIPER_LSQ_L3_PROTO_SHIFT) #define JUNIPER_LSQ_L3_PROTO_IPV4 (0 << JUNIPER_LSQ_L3_PROTO_SHIFT) #define JUNIPER_LSQ_L3_PROTO_IPV6 (1 << JUNIPER_LSQ_L3_PROTO_SHIFT) #define JUNIPER_LSQ_L3_PROTO_MPLS (2 << JUNIPER_LSQ_L3_PROTO_SHIFT) #define JUNIPER_LSQ_L3_PROTO_ISO (3 << JUNIPER_LSQ_L3_PROTO_SHIFT) #define AS_PIC_COOKIE_LEN 8 #define JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE 1 #define JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE 2 #define JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE 3 #define JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE 4 #define JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE 5 #ifdef DLT_JUNIPER_ES static const struct tok juniper_ipsec_type_values[] = { { JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE, "ESP ENCR-AUTH" }, { JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE, "ESP ENCR-AH AUTH" }, { JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE, "ESP AUTH" }, { JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE, "AH AUTH" }, { JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE, "ESP ENCR" }, { 0, NULL} }; #endif static const struct tok juniper_direction_values[] = { { JUNIPER_BPF_IN, "In"}, { JUNIPER_BPF_OUT, "Out"}, { 0, NULL} }; /* codepoints for encoding extensions to a .pcap file */ enum { JUNIPER_EXT_TLV_IFD_IDX = 1, JUNIPER_EXT_TLV_IFD_NAME = 2, JUNIPER_EXT_TLV_IFD_MEDIATYPE = 3, JUNIPER_EXT_TLV_IFL_IDX = 4, JUNIPER_EXT_TLV_IFL_UNIT = 5, JUNIPER_EXT_TLV_IFL_ENCAPS = 6, JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE = 7, JUNIPER_EXT_TLV_TTP_IFL_ENCAPS = 8 }; /* 1 byte type and 1-byte length */ #define JUNIPER_EXT_TLV_OVERHEAD 2U static const struct tok jnx_ext_tlv_values[] = { { JUNIPER_EXT_TLV_IFD_IDX, "Device Interface Index" }, { JUNIPER_EXT_TLV_IFD_NAME,"Device Interface Name" }, { JUNIPER_EXT_TLV_IFD_MEDIATYPE, "Device Media Type" }, { JUNIPER_EXT_TLV_IFL_IDX, "Logical Interface Index" }, { JUNIPER_EXT_TLV_IFL_UNIT,"Logical Unit Number" }, { JUNIPER_EXT_TLV_IFL_ENCAPS, "Logical Interface Encapsulation" }, { JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE, "TTP derived Device Media Type" }, { JUNIPER_EXT_TLV_TTP_IFL_ENCAPS, "TTP derived Logical Interface Encapsulation" }, { 0, NULL } }; static const struct tok jnx_flag_values[] = { { JUNIPER_BPF_EXT, "Ext" }, { JUNIPER_BPF_FILTER, "Filter" }, { JUNIPER_BPF_IIF, "IIF" }, { JUNIPER_BPF_NO_L2, "no-L2" }, { JUNIPER_BPF_PKT_IN, "In" }, { 0, NULL } }; #define JUNIPER_IFML_ETHER 1 #define JUNIPER_IFML_FDDI 2 #define JUNIPER_IFML_TOKENRING 3 #define JUNIPER_IFML_PPP 4 #define JUNIPER_IFML_FRAMERELAY 5 #define JUNIPER_IFML_CISCOHDLC 6 #define JUNIPER_IFML_SMDSDXI 7 #define JUNIPER_IFML_ATMPVC 8 #define JUNIPER_IFML_PPP_CCC 9 #define JUNIPER_IFML_FRAMERELAY_CCC 10 #define JUNIPER_IFML_IPIP 11 #define JUNIPER_IFML_GRE 12 #define JUNIPER_IFML_PIM 13 #define JUNIPER_IFML_PIMD 14 #define JUNIPER_IFML_CISCOHDLC_CCC 15 #define JUNIPER_IFML_VLAN_CCC 16 #define JUNIPER_IFML_MLPPP 17 #define JUNIPER_IFML_MLFR 18 #define JUNIPER_IFML_ML 19 #define JUNIPER_IFML_LSI 20 #define JUNIPER_IFML_DFE 21 #define JUNIPER_IFML_ATM_CELLRELAY_CCC 22 #define JUNIPER_IFML_CRYPTO 23 #define JUNIPER_IFML_GGSN 24 #define JUNIPER_IFML_LSI_PPP 25 #define JUNIPER_IFML_LSI_CISCOHDLC 26 #define JUNIPER_IFML_PPP_TCC 27 #define JUNIPER_IFML_FRAMERELAY_TCC 28 #define JUNIPER_IFML_CISCOHDLC_TCC 29 #define JUNIPER_IFML_ETHERNET_CCC 30 #define JUNIPER_IFML_VT 31 #define JUNIPER_IFML_EXTENDED_VLAN_CCC 32 #define JUNIPER_IFML_ETHER_OVER_ATM 33 #define JUNIPER_IFML_MONITOR 34 #define JUNIPER_IFML_ETHERNET_TCC 35 #define JUNIPER_IFML_VLAN_TCC 36 #define JUNIPER_IFML_EXTENDED_VLAN_TCC 37 #define JUNIPER_IFML_CONTROLLER 38 #define JUNIPER_IFML_MFR 39 #define JUNIPER_IFML_LS 40 #define JUNIPER_IFML_ETHERNET_VPLS 41 #define JUNIPER_IFML_ETHERNET_VLAN_VPLS 42 #define JUNIPER_IFML_ETHERNET_EXTENDED_VLAN_VPLS 43 #define JUNIPER_IFML_LT 44 #define JUNIPER_IFML_SERVICES 45 #define JUNIPER_IFML_ETHER_VPLS_OVER_ATM 46 #define JUNIPER_IFML_FR_PORT_CCC 47 #define JUNIPER_IFML_FRAMERELAY_EXT_CCC 48 #define JUNIPER_IFML_FRAMERELAY_EXT_TCC 49 #define JUNIPER_IFML_FRAMERELAY_FLEX 50 #define JUNIPER_IFML_GGSNI 51 #define JUNIPER_IFML_ETHERNET_FLEX 52 #define JUNIPER_IFML_COLLECTOR 53 #define JUNIPER_IFML_AGGREGATOR 54 #define JUNIPER_IFML_LAPD 55 #define JUNIPER_IFML_PPPOE 56 #define JUNIPER_IFML_PPP_SUBORDINATE 57 #define JUNIPER_IFML_CISCOHDLC_SUBORDINATE 58 #define JUNIPER_IFML_DFC 59 #define JUNIPER_IFML_PICPEER 60 static const struct tok juniper_ifmt_values[] = { { JUNIPER_IFML_ETHER, "Ethernet" }, { JUNIPER_IFML_FDDI, "FDDI" }, { JUNIPER_IFML_TOKENRING, "Token-Ring" }, { JUNIPER_IFML_PPP, "PPP" }, { JUNIPER_IFML_PPP_SUBORDINATE, "PPP-Subordinate" }, { JUNIPER_IFML_FRAMERELAY, "Frame-Relay" }, { JUNIPER_IFML_CISCOHDLC, "Cisco-HDLC" }, { JUNIPER_IFML_SMDSDXI, "SMDS-DXI" }, { JUNIPER_IFML_ATMPVC, "ATM-PVC" }, { JUNIPER_IFML_PPP_CCC, "PPP-CCC" }, { JUNIPER_IFML_FRAMERELAY_CCC, "Frame-Relay-CCC" }, { JUNIPER_IFML_FRAMERELAY_EXT_CCC, "Extended FR-CCC" }, { JUNIPER_IFML_IPIP, "IP-over-IP" }, { JUNIPER_IFML_GRE, "GRE" }, { JUNIPER_IFML_PIM, "PIM-Encapsulator" }, { JUNIPER_IFML_PIMD, "PIM-Decapsulator" }, { JUNIPER_IFML_CISCOHDLC_CCC, "Cisco-HDLC-CCC" }, { JUNIPER_IFML_VLAN_CCC, "VLAN-CCC" }, { JUNIPER_IFML_EXTENDED_VLAN_CCC, "Extended-VLAN-CCC" }, { JUNIPER_IFML_MLPPP, "Multilink-PPP" }, { JUNIPER_IFML_MLFR, "Multilink-FR" }, { JUNIPER_IFML_MFR, "Multilink-FR-UNI-NNI" }, { JUNIPER_IFML_ML, "Multilink" }, { JUNIPER_IFML_LS, "LinkService" }, { JUNIPER_IFML_LSI, "LSI" }, { JUNIPER_IFML_ATM_CELLRELAY_CCC, "ATM-CCC-Cell-Relay" }, { JUNIPER_IFML_CRYPTO, "IPSEC-over-IP" }, { JUNIPER_IFML_GGSN, "GGSN" }, { JUNIPER_IFML_PPP_TCC, "PPP-TCC" }, { JUNIPER_IFML_FRAMERELAY_TCC, "Frame-Relay-TCC" }, { JUNIPER_IFML_FRAMERELAY_EXT_TCC, "Extended FR-TCC" }, { JUNIPER_IFML_CISCOHDLC_TCC, "Cisco-HDLC-TCC" }, { JUNIPER_IFML_ETHERNET_CCC, "Ethernet-CCC" }, { JUNIPER_IFML_VT, "VPN-Loopback-tunnel" }, { JUNIPER_IFML_ETHER_OVER_ATM, "Ethernet-over-ATM" }, { JUNIPER_IFML_ETHER_VPLS_OVER_ATM, "Ethernet-VPLS-over-ATM" }, { JUNIPER_IFML_MONITOR, "Monitor" }, { JUNIPER_IFML_ETHERNET_TCC, "Ethernet-TCC" }, { JUNIPER_IFML_VLAN_TCC, "VLAN-TCC" }, { JUNIPER_IFML_EXTENDED_VLAN_TCC, "Extended-VLAN-TCC" }, { JUNIPER_IFML_CONTROLLER, "Controller" }, { JUNIPER_IFML_ETHERNET_VPLS, "VPLS" }, { JUNIPER_IFML_ETHERNET_VLAN_VPLS, "VLAN-VPLS" }, { JUNIPER_IFML_ETHERNET_EXTENDED_VLAN_VPLS, "Extended-VLAN-VPLS" }, { JUNIPER_IFML_LT, "Logical-tunnel" }, { JUNIPER_IFML_SERVICES, "General-Services" }, { JUNIPER_IFML_PPPOE, "PPPoE" }, { JUNIPER_IFML_ETHERNET_FLEX, "Flexible-Ethernet-Services" }, { JUNIPER_IFML_FRAMERELAY_FLEX, "Flexible-FrameRelay" }, { JUNIPER_IFML_COLLECTOR, "Flow-collection" }, { JUNIPER_IFML_PICPEER, "PIC Peer" }, { JUNIPER_IFML_DFC, "Dynamic-Flow-Capture" }, {0, NULL} }; #define JUNIPER_IFLE_ATM_SNAP 2 #define JUNIPER_IFLE_ATM_NLPID 3 #define JUNIPER_IFLE_ATM_VCMUX 4 #define JUNIPER_IFLE_ATM_LLC 5 #define JUNIPER_IFLE_ATM_PPP_VCMUX 6 #define JUNIPER_IFLE_ATM_PPP_LLC 7 #define JUNIPER_IFLE_ATM_PPP_FUNI 8 #define JUNIPER_IFLE_ATM_CCC 9 #define JUNIPER_IFLE_FR_NLPID 10 #define JUNIPER_IFLE_FR_SNAP 11 #define JUNIPER_IFLE_FR_PPP 12 #define JUNIPER_IFLE_FR_CCC 13 #define JUNIPER_IFLE_ENET2 14 #define JUNIPER_IFLE_IEEE8023_SNAP 15 #define JUNIPER_IFLE_IEEE8023_LLC 16 #define JUNIPER_IFLE_PPP 17 #define JUNIPER_IFLE_CISCOHDLC 18 #define JUNIPER_IFLE_PPP_CCC 19 #define JUNIPER_IFLE_IPIP_NULL 20 #define JUNIPER_IFLE_PIM_NULL 21 #define JUNIPER_IFLE_GRE_NULL 22 #define JUNIPER_IFLE_GRE_PPP 23 #define JUNIPER_IFLE_PIMD_DECAPS 24 #define JUNIPER_IFLE_CISCOHDLC_CCC 25 #define JUNIPER_IFLE_ATM_CISCO_NLPID 26 #define JUNIPER_IFLE_VLAN_CCC 27 #define JUNIPER_IFLE_MLPPP 28 #define JUNIPER_IFLE_MLFR 29 #define JUNIPER_IFLE_LSI_NULL 30 #define JUNIPER_IFLE_AGGREGATE_UNUSED 31 #define JUNIPER_IFLE_ATM_CELLRELAY_CCC 32 #define JUNIPER_IFLE_CRYPTO 33 #define JUNIPER_IFLE_GGSN 34 #define JUNIPER_IFLE_ATM_TCC 35 #define JUNIPER_IFLE_FR_TCC 36 #define JUNIPER_IFLE_PPP_TCC 37 #define JUNIPER_IFLE_CISCOHDLC_TCC 38 #define JUNIPER_IFLE_ETHERNET_CCC 39 #define JUNIPER_IFLE_VT 40 #define JUNIPER_IFLE_ATM_EOA_LLC 41 #define JUNIPER_IFLE_EXTENDED_VLAN_CCC 42 #define JUNIPER_IFLE_ATM_SNAP_TCC 43 #define JUNIPER_IFLE_MONITOR 44 #define JUNIPER_IFLE_ETHERNET_TCC 45 #define JUNIPER_IFLE_VLAN_TCC 46 #define JUNIPER_IFLE_EXTENDED_VLAN_TCC 47 #define JUNIPER_IFLE_MFR 48 #define JUNIPER_IFLE_ETHERNET_VPLS 49 #define JUNIPER_IFLE_ETHERNET_VLAN_VPLS 50 #define JUNIPER_IFLE_ETHERNET_EXTENDED_VLAN_VPLS 51 #define JUNIPER_IFLE_SERVICES 52 #define JUNIPER_IFLE_ATM_ETHER_VPLS_ATM_LLC 53 #define JUNIPER_IFLE_FR_PORT_CCC 54 #define JUNIPER_IFLE_ATM_MLPPP_LLC 55 #define JUNIPER_IFLE_ATM_EOA_CCC 56 #define JUNIPER_IFLE_LT_VLAN 57 #define JUNIPER_IFLE_COLLECTOR 58 #define JUNIPER_IFLE_AGGREGATOR 59 #define JUNIPER_IFLE_LAPD 60 #define JUNIPER_IFLE_ATM_PPPOE_LLC 61 #define JUNIPER_IFLE_ETHERNET_PPPOE 62 #define JUNIPER_IFLE_PPPOE 63 #define JUNIPER_IFLE_PPP_SUBORDINATE 64 #define JUNIPER_IFLE_CISCOHDLC_SUBORDINATE 65 #define JUNIPER_IFLE_DFC 66 #define JUNIPER_IFLE_PICPEER 67 static const struct tok juniper_ifle_values[] = { { JUNIPER_IFLE_AGGREGATOR, "Aggregator" }, { JUNIPER_IFLE_ATM_CCC, "CCC over ATM" }, { JUNIPER_IFLE_ATM_CELLRELAY_CCC, "ATM CCC Cell Relay" }, { JUNIPER_IFLE_ATM_CISCO_NLPID, "CISCO compatible NLPID" }, { JUNIPER_IFLE_ATM_EOA_CCC, "Ethernet over ATM CCC" }, { JUNIPER_IFLE_ATM_EOA_LLC, "Ethernet over ATM LLC" }, { JUNIPER_IFLE_ATM_ETHER_VPLS_ATM_LLC, "Ethernet VPLS over ATM LLC" }, { JUNIPER_IFLE_ATM_LLC, "ATM LLC" }, { JUNIPER_IFLE_ATM_MLPPP_LLC, "MLPPP over ATM LLC" }, { JUNIPER_IFLE_ATM_NLPID, "ATM NLPID" }, { JUNIPER_IFLE_ATM_PPPOE_LLC, "PPPoE over ATM LLC" }, { JUNIPER_IFLE_ATM_PPP_FUNI, "PPP over FUNI" }, { JUNIPER_IFLE_ATM_PPP_LLC, "PPP over ATM LLC" }, { JUNIPER_IFLE_ATM_PPP_VCMUX, "PPP over ATM VCMUX" }, { JUNIPER_IFLE_ATM_SNAP, "ATM SNAP" }, { JUNIPER_IFLE_ATM_SNAP_TCC, "ATM SNAP TCC" }, { JUNIPER_IFLE_ATM_TCC, "ATM VCMUX TCC" }, { JUNIPER_IFLE_ATM_VCMUX, "ATM VCMUX" }, { JUNIPER_IFLE_CISCOHDLC, "C-HDLC" }, { JUNIPER_IFLE_CISCOHDLC_CCC, "C-HDLC CCC" }, { JUNIPER_IFLE_CISCOHDLC_SUBORDINATE, "C-HDLC via dialer" }, { JUNIPER_IFLE_CISCOHDLC_TCC, "C-HDLC TCC" }, { JUNIPER_IFLE_COLLECTOR, "Collector" }, { JUNIPER_IFLE_CRYPTO, "Crypto" }, { JUNIPER_IFLE_ENET2, "Ethernet" }, { JUNIPER_IFLE_ETHERNET_CCC, "Ethernet CCC" }, { JUNIPER_IFLE_ETHERNET_EXTENDED_VLAN_VPLS, "Extended VLAN VPLS" }, { JUNIPER_IFLE_ETHERNET_PPPOE, "PPPoE over Ethernet" }, { JUNIPER_IFLE_ETHERNET_TCC, "Ethernet TCC" }, { JUNIPER_IFLE_ETHERNET_VLAN_VPLS, "VLAN VPLS" }, { JUNIPER_IFLE_ETHERNET_VPLS, "VPLS" }, { JUNIPER_IFLE_EXTENDED_VLAN_CCC, "Extended VLAN CCC" }, { JUNIPER_IFLE_EXTENDED_VLAN_TCC, "Extended VLAN TCC" }, { JUNIPER_IFLE_FR_CCC, "FR CCC" }, { JUNIPER_IFLE_FR_NLPID, "FR NLPID" }, { JUNIPER_IFLE_FR_PORT_CCC, "FR CCC" }, { JUNIPER_IFLE_FR_PPP, "FR PPP" }, { JUNIPER_IFLE_FR_SNAP, "FR SNAP" }, { JUNIPER_IFLE_FR_TCC, "FR TCC" }, { JUNIPER_IFLE_GGSN, "GGSN" }, { JUNIPER_IFLE_GRE_NULL, "GRE NULL" }, { JUNIPER_IFLE_GRE_PPP, "PPP over GRE" }, { JUNIPER_IFLE_IPIP_NULL, "IPIP" }, { JUNIPER_IFLE_LAPD, "LAPD" }, { JUNIPER_IFLE_LSI_NULL, "LSI Null" }, { JUNIPER_IFLE_LT_VLAN, "LT VLAN" }, { JUNIPER_IFLE_MFR, "MFR" }, { JUNIPER_IFLE_MLFR, "MLFR" }, { JUNIPER_IFLE_MLPPP, "MLPPP" }, { JUNIPER_IFLE_MONITOR, "Monitor" }, { JUNIPER_IFLE_PIMD_DECAPS, "PIMd" }, { JUNIPER_IFLE_PIM_NULL, "PIM Null" }, { JUNIPER_IFLE_PPP, "PPP" }, { JUNIPER_IFLE_PPPOE, "PPPoE" }, { JUNIPER_IFLE_PPP_CCC, "PPP CCC" }, { JUNIPER_IFLE_PPP_SUBORDINATE, "" }, { JUNIPER_IFLE_PPP_TCC, "PPP TCC" }, { JUNIPER_IFLE_SERVICES, "General Services" }, { JUNIPER_IFLE_VLAN_CCC, "VLAN CCC" }, { JUNIPER_IFLE_VLAN_TCC, "VLAN TCC" }, { JUNIPER_IFLE_VT, "VT" }, {0, NULL} }; struct juniper_cookie_table_t { uint32_t pictype; /* pic type */ uint8_t cookie_len; /* cookie len */ const char *s; /* pic name */ }; static const struct juniper_cookie_table_t juniper_cookie_table[] = { #ifdef DLT_JUNIPER_ATM1 { DLT_JUNIPER_ATM1, 4, "ATM1"}, #endif #ifdef DLT_JUNIPER_ATM2 { DLT_JUNIPER_ATM2, 8, "ATM2"}, #endif #ifdef DLT_JUNIPER_MLPPP { DLT_JUNIPER_MLPPP, 2, "MLPPP"}, #endif #ifdef DLT_JUNIPER_MLFR { DLT_JUNIPER_MLFR, 2, "MLFR"}, #endif #ifdef DLT_JUNIPER_MFR { DLT_JUNIPER_MFR, 4, "MFR"}, #endif #ifdef DLT_JUNIPER_PPPOE { DLT_JUNIPER_PPPOE, 0, "PPPoE"}, #endif #ifdef DLT_JUNIPER_PPPOE_ATM { DLT_JUNIPER_PPPOE_ATM, 0, "PPPoE ATM"}, #endif #ifdef DLT_JUNIPER_GGSN { DLT_JUNIPER_GGSN, 8, "GGSN"}, #endif #ifdef DLT_JUNIPER_MONITOR { DLT_JUNIPER_MONITOR, 8, "MONITOR"}, #endif #ifdef DLT_JUNIPER_SERVICES { DLT_JUNIPER_SERVICES, 8, "AS"}, #endif #ifdef DLT_JUNIPER_ES { DLT_JUNIPER_ES, 0, "ES"}, #endif { 0, 0, NULL } }; struct juniper_l2info_t { uint32_t length; uint32_t caplen; uint32_t pictype; uint8_t direction; u_int header_len; uint8_t cookie_len; uint8_t cookie_type; uint8_t cookie[8]; u_int bundle; uint16_t proto; uint8_t flags; }; #define LS_COOKIE_ID 0x54 #define AS_COOKIE_ID 0x47 #define LS_MLFR_COOKIE_LEN 4 #define ML_MLFR_COOKIE_LEN 2 #define LS_MFR_COOKIE_LEN 6 #define ATM1_COOKIE_LEN 4 #define ATM2_COOKIE_LEN 8 #define ATM2_PKT_TYPE_MASK 0x70 #define ATM2_GAP_COUNT_MASK 0x3F #define JUNIPER_PROTO_NULL 1 #define JUNIPER_PROTO_IPV4 2 #define JUNIPER_PROTO_IPV6 6 #define MFR_BE_MASK 0xc0 #ifdef DLT_JUNIPER_GGSN static const struct tok juniper_protocol_values[] = { { JUNIPER_PROTO_NULL, "Null" }, { JUNIPER_PROTO_IPV4, "IPv4" }, { JUNIPER_PROTO_IPV6, "IPv6" }, { 0, NULL} }; #endif static int ip_heuristic_guess(netdissect_options *, const u_char *, u_int); #ifdef DLT_JUNIPER_ATM2 static int juniper_ppp_heuristic_guess(netdissect_options *, const u_char *, u_int); #endif static int juniper_parse_header(netdissect_options *, const u_char *, const struct pcap_pkthdr *, struct juniper_l2info_t *); #ifdef DLT_JUNIPER_GGSN void juniper_ggsn_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { struct juniper_l2info_t l2info; struct juniper_ggsn_header { nd_uint8_t svc_id; nd_uint8_t flags_len; nd_uint8_t proto; nd_uint8_t flags; nd_uint16_t vlan_id; nd_byte res[2]; }; const struct juniper_ggsn_header *gh; uint8_t proto; ndo->ndo_protocol = "juniper_ggsn"; memset(&l2info, 0, sizeof(l2info)); l2info.pictype = DLT_JUNIPER_GGSN; if (juniper_parse_header(ndo, p, h, &l2info) == 0) { ndo->ndo_ll_hdr_len += l2info.header_len; return; } p+=l2info.header_len; gh = (struct juniper_ggsn_header *)&l2info.cookie; ND_TCHECK_SIZE(gh); proto = GET_U_1(gh->proto); if (ndo->ndo_eflag) { ND_PRINT("proto %s (%u), vlan %u: ", tok2str(juniper_protocol_values,"Unknown",proto), proto, GET_BE_U_2(gh->vlan_id)); } switch (proto) { case JUNIPER_PROTO_IPV4: ip_print(ndo, p, l2info.length); break; case JUNIPER_PROTO_IPV6: ip6_print(ndo, p, l2info.length); break; default: if (!ndo->ndo_eflag) ND_PRINT("unknown GGSN proto (%u)", proto); } ndo->ndo_ll_hdr_len += l2info.header_len; return; trunc: nd_print_trunc(ndo); ndo->ndo_ll_hdr_len += l2info.header_len; } #endif #ifdef DLT_JUNIPER_ES void juniper_es_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { struct juniper_l2info_t l2info; struct juniper_ipsec_header { nd_uint16_t sa_index; nd_uint8_t ttl; nd_uint8_t type; nd_uint32_t spi; nd_ipv4 src_ip; nd_ipv4 dst_ip; }; u_int rewrite_len,es_type_bundle; const struct juniper_ipsec_header *ih; ndo->ndo_protocol = "juniper_es"; memset(&l2info, 0, sizeof(l2info)); l2info.pictype = DLT_JUNIPER_ES; if (juniper_parse_header(ndo, p, h, &l2info) == 0) { ndo->ndo_ll_hdr_len += l2info.header_len; return; } p+=l2info.header_len; ih = (const struct juniper_ipsec_header *)p; ND_TCHECK_SIZE(ih); switch (GET_U_1(ih->type)) { case JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE: case JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE: rewrite_len = 0; es_type_bundle = 1; break; case JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE: case JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE: case JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE: rewrite_len = 16; es_type_bundle = 0; break; default: ND_PRINT("ES Invalid type %u, length %u", GET_U_1(ih->type), l2info.length); ndo->ndo_ll_hdr_len += l2info.header_len; return; } l2info.length-=rewrite_len; p+=rewrite_len; if (ndo->ndo_eflag) { if (!es_type_bundle) { ND_PRINT("ES SA, index %u, ttl %u type %s (%u), spi %u, Tunnel %s > %s, length %u\n", GET_BE_U_2(ih->sa_index), GET_U_1(ih->ttl), tok2str(juniper_ipsec_type_values,"Unknown",GET_U_1(ih->type)), GET_U_1(ih->type), GET_BE_U_4(ih->spi), GET_IPADDR_STRING(ih->src_ip), GET_IPADDR_STRING(ih->dst_ip), l2info.length); } else { ND_PRINT("ES SA, index %u, ttl %u type %s (%u), length %u\n", GET_BE_U_2(ih->sa_index), GET_U_1(ih->ttl), tok2str(juniper_ipsec_type_values,"Unknown",GET_U_1(ih->type)), GET_U_1(ih->type), l2info.length); } } ip_print(ndo, p, l2info.length); ndo->ndo_ll_hdr_len += l2info.header_len; return; trunc: nd_print_trunc(ndo); ndo->ndo_ll_hdr_len += l2info.header_len; } #endif #ifdef DLT_JUNIPER_MONITOR void juniper_monitor_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { struct juniper_l2info_t l2info; struct juniper_monitor_header { nd_uint8_t pkt_type; nd_byte padding; nd_uint16_t iif; nd_uint32_t service_id; }; const struct juniper_monitor_header *mh; ndo->ndo_protocol = "juniper_monitor"; memset(&l2info, 0, sizeof(l2info)); l2info.pictype = DLT_JUNIPER_MONITOR; if (juniper_parse_header(ndo, p, h, &l2info) == 0) { ndo->ndo_ll_hdr_len += l2info.header_len; return; } p+=l2info.header_len; mh = (const struct juniper_monitor_header *)p; ND_TCHECK_SIZE(mh); if (ndo->ndo_eflag) ND_PRINT("service-id %u, iif %u, pkt-type %u: ", GET_BE_U_4(mh->service_id), GET_BE_U_2(mh->iif), GET_U_1(mh->pkt_type)); /* no proto field - lets guess by first byte of IP header*/ ip_heuristic_guess (ndo, p, l2info.length); ndo->ndo_ll_hdr_len += l2info.header_len; return; trunc: nd_print_trunc(ndo); ndo->ndo_ll_hdr_len += l2info.header_len; } #endif #ifdef DLT_JUNIPER_SERVICES void juniper_services_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { struct juniper_l2info_t l2info; struct juniper_services_header { nd_uint8_t svc_id; nd_uint8_t flags_len; nd_uint16_t svc_set_id; nd_byte pad; nd_uint24_t dir_iif; }; const struct juniper_services_header *sh; ndo->ndo_protocol = "juniper_services"; memset(&l2info, 0, sizeof(l2info)); l2info.pictype = DLT_JUNIPER_SERVICES; if (juniper_parse_header(ndo, p, h, &l2info) == 0) { ndo->ndo_ll_hdr_len += l2info.header_len; return; } p+=l2info.header_len; sh = (const struct juniper_services_header *)p; ND_TCHECK_SIZE(sh); if (ndo->ndo_eflag) ND_PRINT("service-id %u flags 0x%02x service-set-id 0x%04x iif %u: ", GET_U_1(sh->svc_id), GET_U_1(sh->flags_len), GET_BE_U_2(sh->svc_set_id), GET_BE_U_3(sh->dir_iif)); /* no proto field - lets guess by first byte of IP header*/ ip_heuristic_guess (ndo, p, l2info.length); ndo->ndo_ll_hdr_len += l2info.header_len; return; trunc: nd_print_trunc(ndo); ndo->ndo_ll_hdr_len += l2info.header_len; } #endif #ifdef DLT_JUNIPER_PPPOE void juniper_pppoe_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { struct juniper_l2info_t l2info; ndo->ndo_protocol = "juniper_pppoe"; memset(&l2info, 0, sizeof(l2info)); l2info.pictype = DLT_JUNIPER_PPPOE; if (juniper_parse_header(ndo, p, h, &l2info) == 0) { ndo->ndo_ll_hdr_len += l2info.header_len; return; } p+=l2info.header_len; /* this DLT contains nothing but raw ethernet frames */ ether_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL); ndo->ndo_ll_hdr_len += l2info.header_len; } #endif #ifdef DLT_JUNIPER_ETHER void juniper_ether_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { struct juniper_l2info_t l2info; ndo->ndo_protocol = "juniper_ether"; memset(&l2info, 0, sizeof(l2info)); l2info.pictype = DLT_JUNIPER_ETHER; if (juniper_parse_header(ndo, p, h, &l2info) == 0) { ndo->ndo_ll_hdr_len += l2info.header_len; return; } p+=l2info.header_len; /* this DLT contains nothing but raw Ethernet frames */ ndo->ndo_ll_hdr_len += l2info.header_len + ether_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL); } #endif #ifdef DLT_JUNIPER_PPP void juniper_ppp_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { struct juniper_l2info_t l2info; ndo->ndo_protocol = "juniper_ppp"; memset(&l2info, 0, sizeof(l2info)); l2info.pictype = DLT_JUNIPER_PPP; if (juniper_parse_header(ndo, p, h, &l2info) == 0) { ndo->ndo_ll_hdr_len += l2info.header_len; return; } p+=l2info.header_len; /* this DLT contains nothing but raw ppp frames */ ppp_print(ndo, p, l2info.length); ndo->ndo_ll_hdr_len += l2info.header_len; } #endif #ifdef DLT_JUNIPER_FRELAY void juniper_frelay_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { struct juniper_l2info_t l2info; ndo->ndo_protocol = "juniper_frelay"; memset(&l2info, 0, sizeof(l2info)); l2info.pictype = DLT_JUNIPER_FRELAY; if (juniper_parse_header(ndo, p, h, &l2info) == 0) { ndo->ndo_ll_hdr_len += l2info.header_len; return; } p+=l2info.header_len; /* this DLT contains nothing but raw frame-relay frames */ fr_print(ndo, p, l2info.length); ndo->ndo_ll_hdr_len += l2info.header_len; } #endif #ifdef DLT_JUNIPER_CHDLC void juniper_chdlc_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { struct juniper_l2info_t l2info; ndo->ndo_protocol = "juniper_chdlc"; memset(&l2info, 0, sizeof(l2info)); l2info.pictype = DLT_JUNIPER_CHDLC; if (juniper_parse_header(ndo, p, h, &l2info) == 0) { ndo->ndo_ll_hdr_len += l2info.header_len; return; } p+=l2info.header_len; /* this DLT contains nothing but raw c-hdlc frames */ chdlc_print(ndo, p, l2info.length); ndo->ndo_ll_hdr_len += l2info.header_len; } #endif #ifdef DLT_JUNIPER_PPPOE_ATM void juniper_pppoe_atm_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { struct juniper_l2info_t l2info; uint16_t extracted_ethertype; ndo->ndo_protocol = "juniper_pppoe_atm"; memset(&l2info, 0, sizeof(l2info)); l2info.pictype = DLT_JUNIPER_PPPOE_ATM; if (juniper_parse_header(ndo, p, h, &l2info) == 0) { ndo->ndo_ll_hdr_len += l2info.header_len; return; } p+=l2info.header_len; extracted_ethertype = GET_BE_U_2(p); /* this DLT contains nothing but raw PPPoE frames, * prepended with a type field*/ if (ethertype_print(ndo, extracted_ethertype, p+ETHERTYPE_LEN, l2info.length-ETHERTYPE_LEN, l2info.caplen-ETHERTYPE_LEN, NULL, NULL) == 0) /* ether_type not known, probably it wasn't one */ ND_PRINT("unknown ethertype 0x%04x", extracted_ethertype); ndo->ndo_ll_hdr_len += l2info.header_len; } #endif #ifdef DLT_JUNIPER_MLPPP void juniper_mlppp_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { struct juniper_l2info_t l2info; ndo->ndo_protocol = "juniper_mlppp"; memset(&l2info, 0, sizeof(l2info)); l2info.pictype = DLT_JUNIPER_MLPPP; if (juniper_parse_header(ndo, p, h, &l2info) == 0) { ndo->ndo_ll_hdr_len += l2info.header_len; return; } /* suppress Bundle-ID if frame was captured on a child-link * best indicator if the cookie looks like a proto */ if (ndo->ndo_eflag && /* use EXTRACT_, not GET_ (not packet buffer pointer) */ EXTRACT_BE_U_2(&l2info.cookie) != PPP_OSI && /* use EXTRACT_, not GET_ (not packet buffer pointer) */ EXTRACT_BE_U_2(&l2info.cookie) != (PPP_ADDRESS << 8 | PPP_CONTROL)) ND_PRINT("Bundle-ID %u: ", l2info.bundle); p+=l2info.header_len; /* first try the LSQ protos */ switch(l2info.proto) { case JUNIPER_LSQ_L3_PROTO_IPV4: /* IP traffic going to the RE would not have a cookie * -> this must be incoming IS-IS over PPP */ if (l2info.cookie[4] == (JUNIPER_LSQ_COOKIE_RE|JUNIPER_LSQ_COOKIE_DIR)) ppp_print(ndo, p, l2info.length); else ip_print(ndo, p, l2info.length); ndo->ndo_ll_hdr_len += l2info.header_len; return; case JUNIPER_LSQ_L3_PROTO_IPV6: ip6_print(ndo, p,l2info.length); ndo->ndo_ll_hdr_len += l2info.header_len; return; case JUNIPER_LSQ_L3_PROTO_MPLS: mpls_print(ndo, p, l2info.length); ndo->ndo_ll_hdr_len += l2info.header_len; return; case JUNIPER_LSQ_L3_PROTO_ISO: isoclns_print(ndo, p, l2info.length); ndo->ndo_ll_hdr_len += l2info.header_len; return; default: break; } /* zero length cookie ? */ /* use EXTRACT_, not GET_ (not packet buffer pointer) */ switch (EXTRACT_BE_U_2(&l2info.cookie)) { case PPP_OSI: ppp_print(ndo, p - 2, l2info.length + 2); break; case (PPP_ADDRESS << 8 | PPP_CONTROL): /* fall through */ default: ppp_print(ndo, p, l2info.length); break; } ndo->ndo_ll_hdr_len += l2info.header_len; } #endif #ifdef DLT_JUNIPER_MFR void juniper_mfr_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { struct juniper_l2info_t l2info; ndo->ndo_protocol = "juniper_mfr"; memset(&l2info, 0, sizeof(l2info)); l2info.pictype = DLT_JUNIPER_MFR; if (juniper_parse_header(ndo, p, h, &l2info) == 0) { ndo->ndo_ll_hdr_len += l2info.header_len; return; } p+=l2info.header_len; /* child-link ? */ if (l2info.cookie_len == 0) { mfr_print(ndo, p, l2info.length); ndo->ndo_ll_hdr_len += l2info.header_len; return; } /* first try the LSQ protos */ if (l2info.cookie_len == AS_PIC_COOKIE_LEN) { switch(l2info.proto) { case JUNIPER_LSQ_L3_PROTO_IPV4: ip_print(ndo, p, l2info.length); ndo->ndo_ll_hdr_len += l2info.header_len; return; case JUNIPER_LSQ_L3_PROTO_IPV6: ip6_print(ndo, p,l2info.length); ndo->ndo_ll_hdr_len += l2info.header_len; return; case JUNIPER_LSQ_L3_PROTO_MPLS: mpls_print(ndo, p, l2info.length); ndo->ndo_ll_hdr_len += l2info.header_len; return; case JUNIPER_LSQ_L3_PROTO_ISO: isoclns_print(ndo, p, l2info.length); ndo->ndo_ll_hdr_len += l2info.header_len; return; default: break; } ndo->ndo_ll_hdr_len += l2info.header_len; return; } /* suppress Bundle-ID if frame was captured on a child-link */ /* use EXTRACT_, not GET_ (not packet buffer pointer) */ if (ndo->ndo_eflag && EXTRACT_BE_U_4(l2info.cookie) != 1) ND_PRINT("Bundle-ID %u, ", l2info.bundle); switch (l2info.proto) { case (LLCSAP_ISONS<<8 | LLCSAP_ISONS): isoclns_print(ndo, p + 1, l2info.length - 1); break; case (LLC_UI<<8 | NLPID_Q933): case (LLC_UI<<8 | NLPID_IP): case (LLC_UI<<8 | NLPID_IP6): /* pass IP{4,6} to the OSI layer for proper link-layer printing */ isoclns_print(ndo, p - 1, l2info.length + 1); break; default: ND_PRINT("unknown protocol 0x%04x, length %u", l2info.proto, l2info.length); } ndo->ndo_ll_hdr_len += l2info.header_len; } #endif #ifdef DLT_JUNIPER_MLFR void juniper_mlfr_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { struct juniper_l2info_t l2info; ndo->ndo_protocol = "juniper_mlfr"; memset(&l2info, 0, sizeof(l2info)); l2info.pictype = DLT_JUNIPER_MLFR; if (juniper_parse_header(ndo, p, h, &l2info) == 0) { ndo->ndo_ll_hdr_len += l2info.header_len; return; } p+=l2info.header_len; /* suppress Bundle-ID if frame was captured on a child-link */ /* use EXTRACT_, not GET_ (not packet buffer pointer) */ if (ndo->ndo_eflag && EXTRACT_BE_U_4(l2info.cookie) != 1) ND_PRINT("Bundle-ID %u, ", l2info.bundle); switch (l2info.proto) { case (LLC_UI): case (LLC_UI<<8): isoclns_print(ndo, p, l2info.length); break; case (LLC_UI<<8 | NLPID_Q933): case (LLC_UI<<8 | NLPID_IP): case (LLC_UI<<8 | NLPID_IP6): /* pass IP{4,6} to the OSI layer for proper link-layer printing */ isoclns_print(ndo, p - 1, l2info.length + 1); break; default: ND_PRINT("unknown protocol 0x%04x, length %u", l2info.proto, l2info.length); } ndo->ndo_ll_hdr_len += l2info.header_len; } #endif /* * ATM1 PIC cookie format * * +-----+-------------------------+-------------------------------+ * |fmtid| vc index | channel ID | * +-----+-------------------------+-------------------------------+ */ #ifdef DLT_JUNIPER_ATM1 void juniper_atm1_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { int llc_hdrlen; struct juniper_l2info_t l2info; ndo->ndo_protocol = "juniper_atm1"; memset(&l2info, 0, sizeof(l2info)); l2info.pictype = DLT_JUNIPER_ATM1; if (juniper_parse_header(ndo, p, h, &l2info) == 0) { ndo->ndo_ll_hdr_len += l2info.header_len; return; } p+=l2info.header_len; if (l2info.cookie[0] == 0x80) { /* OAM cell ? */ oam_print(ndo, p, l2info.length, ATM_OAM_NOHEC); ndo->ndo_ll_hdr_len += l2info.header_len; return; } if (GET_BE_U_3(p) == 0xfefe03 || /* NLPID encaps ? */ GET_BE_U_3(p) == 0xaaaa03) { /* SNAP encaps ? */ llc_hdrlen = llc_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL); if (llc_hdrlen > 0) { ndo->ndo_ll_hdr_len += l2info.header_len; return; } } if (GET_U_1(p) == 0x03) { /* Cisco style NLPID encaps ? */ isoclns_print(ndo, p + 1, l2info.length - 1); /* FIXME check if frame was recognized */ ndo->ndo_ll_hdr_len += l2info.header_len; return; } if (ip_heuristic_guess(ndo, p, l2info.length) != 0) { /* last try - vcmux encaps ? */ ndo->ndo_ll_hdr_len += l2info.header_len; return; } ndo->ndo_ll_hdr_len += l2info.header_len; } #endif /* * ATM2 PIC cookie format * * +-------------------------------+---------+---+-----+-----------+ * | channel ID | reserv |AAL| CCRQ| gap cnt | * +-------------------------------+---------+---+-----+-----------+ */ #ifdef DLT_JUNIPER_ATM2 void juniper_atm2_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { int llc_hdrlen; struct juniper_l2info_t l2info; ndo->ndo_protocol = "juniper_atm2"; memset(&l2info, 0, sizeof(l2info)); l2info.pictype = DLT_JUNIPER_ATM2; if (juniper_parse_header(ndo, p, h, &l2info) == 0) { ndo->ndo_ll_hdr_len += l2info.header_len; return; } p+=l2info.header_len; if (l2info.cookie[7] & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */ oam_print(ndo, p, l2info.length, ATM_OAM_NOHEC); ndo->ndo_ll_hdr_len += l2info.header_len; return; } if (GET_BE_U_3(p) == 0xfefe03 || /* NLPID encaps ? */ GET_BE_U_3(p) == 0xaaaa03) { /* SNAP encaps ? */ llc_hdrlen = llc_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL); if (llc_hdrlen > 0) { ndo->ndo_ll_hdr_len += l2info.header_len; return; } } if (l2info.direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */ /* use EXTRACT_, not GET_ (not packet buffer pointer) */ (EXTRACT_BE_U_4(l2info.cookie) & ATM2_GAP_COUNT_MASK)) { ether_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL); ndo->ndo_ll_hdr_len += l2info.header_len; return; } if (GET_U_1(p) == 0x03) { /* Cisco style NLPID encaps ? */ isoclns_print(ndo, p + 1, l2info.length - 1); /* FIXME check if frame was recognized */ ndo->ndo_ll_hdr_len += l2info.header_len; return; } if(juniper_ppp_heuristic_guess(ndo, p, l2info.length) != 0) { /* PPPoA vcmux encaps ? */ ndo->ndo_ll_hdr_len += l2info.header_len; return; } if (ip_heuristic_guess(ndo, p, l2info.length) != 0) { /* last try - vcmux encaps ? */ ndo->ndo_ll_hdr_len += l2info.header_len; return; } ndo->ndo_ll_hdr_len += l2info.header_len; } /* try to guess, based on all PPP protos that are supported in * a juniper router if the payload data is encapsulated using PPP */ static int juniper_ppp_heuristic_guess(netdissect_options *ndo, const u_char *p, u_int length) { switch(GET_BE_U_2(p)) { case PPP_IP : case PPP_OSI : case PPP_MPLS_UCAST : case PPP_MPLS_MCAST : case PPP_IPCP : case PPP_OSICP : case PPP_MPLSCP : case PPP_LCP : case PPP_PAP : case PPP_CHAP : case PPP_ML : case PPP_IPV6 : case PPP_IPV6CP : ppp_print(ndo, p, length); break; default: return 0; /* did not find a ppp header */ break; } return 1; /* we printed a ppp packet */ } #endif static int ip_heuristic_guess(netdissect_options *ndo, const u_char *p, u_int length) { switch(GET_U_1(p)) { case 0x45: case 0x46: case 0x47: case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: case 0x4d: case 0x4e: case 0x4f: ip_print(ndo, p, length); break; case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x65: case 0x66: case 0x67: case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: case 0x6d: case 0x6e: case 0x6f: ip6_print(ndo, p, length); break; default: return 0; /* did not find a ip header */ break; } return 1; /* we printed an v4/v6 packet */ } static int juniper_read_tlv_value(netdissect_options *ndo, const u_char *p, u_int tlv_type, u_int tlv_len) { int tlv_value; /* TLVs < 128 are little endian encoded */ if (tlv_type < 128) { switch (tlv_len) { case 1: tlv_value = GET_U_1(p); break; case 2: tlv_value = GET_LE_U_2(p); break; case 3: tlv_value = GET_LE_U_3(p); break; case 4: tlv_value = GET_LE_U_4(p); break; default: tlv_value = -1; break; } } else { /* TLVs >= 128 are big endian encoded */ switch (tlv_len) { case 1: tlv_value = GET_U_1(p); break; case 2: tlv_value = GET_BE_U_2(p); break; case 3: tlv_value = GET_BE_U_3(p); break; case 4: tlv_value = GET_BE_U_4(p); break; default: tlv_value = -1; break; } } return tlv_value; } static int juniper_parse_header(netdissect_options *ndo, const u_char *p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info) { const struct juniper_cookie_table_t *lp = juniper_cookie_table; u_int idx, jnx_ext_len, jnx_header_len = 0; uint8_t tlv_type,tlv_len; #ifdef DLT_JUNIPER_ATM2 uint32_t control_word; #endif int tlv_value; const u_char *tptr; l2info->header_len = 0; l2info->cookie_len = 0; l2info->proto = 0; l2info->length = h->len; l2info->caplen = h->caplen; l2info->flags = GET_U_1(p + 3); l2info->direction = GET_U_1(p + 3) & JUNIPER_BPF_PKT_IN; if (GET_BE_U_3(p) != JUNIPER_MGC_NUMBER) { /* magic number found ? */ ND_PRINT("no magic-number found!"); return 0; } if (ndo->ndo_eflag) /* print direction */ ND_PRINT("%3s ", tok2str(juniper_direction_values, "---", l2info->direction)); /* magic number + flags */ jnx_header_len = 4; if (ndo->ndo_vflag > 1) ND_PRINT("\n\tJuniper PCAP Flags [%s]", bittok2str(jnx_flag_values, "none", l2info->flags)); /* extensions present ? - calculate how much bytes to skip */ if ((l2info->flags & JUNIPER_BPF_EXT ) == JUNIPER_BPF_EXT ) { tptr = p+jnx_header_len; /* ok to read extension length ? */ jnx_ext_len = GET_BE_U_2(tptr); jnx_header_len += 2; tptr +=2; /* nail up the total length - * just in case something goes wrong * with TLV parsing */ jnx_header_len += jnx_ext_len; if (ndo->ndo_vflag > 1) ND_PRINT(", PCAP Extension(s) total length %u", jnx_ext_len); ND_TCHECK_LEN(tptr, jnx_ext_len); while (jnx_ext_len > JUNIPER_EXT_TLV_OVERHEAD) { tlv_type = GET_U_1(tptr); tptr++; tlv_len = GET_U_1(tptr); tptr++; tlv_value = 0; /* sanity checks */ if (tlv_type == 0 || tlv_len == 0) break; if (tlv_len+JUNIPER_EXT_TLV_OVERHEAD > jnx_ext_len) goto trunc; if (ndo->ndo_vflag > 1) ND_PRINT("\n\t %s Extension TLV #%u, length %u, value ", tok2str(jnx_ext_tlv_values,"Unknown",tlv_type), tlv_type, tlv_len); tlv_value = juniper_read_tlv_value(ndo, tptr, tlv_type, tlv_len); switch (tlv_type) { case JUNIPER_EXT_TLV_IFD_NAME: /* FIXME */ break; case JUNIPER_EXT_TLV_IFD_MEDIATYPE: case JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE: if (tlv_value != -1) { if (ndo->ndo_vflag > 1) ND_PRINT("%s (%u)", tok2str(juniper_ifmt_values, "Unknown", tlv_value), tlv_value); } break; case JUNIPER_EXT_TLV_IFL_ENCAPS: case JUNIPER_EXT_TLV_TTP_IFL_ENCAPS: if (tlv_value != -1) { if (ndo->ndo_vflag > 1) ND_PRINT("%s (%u)", tok2str(juniper_ifle_values, "Unknown", tlv_value), tlv_value); } break; case JUNIPER_EXT_TLV_IFL_IDX: /* fall through */ case JUNIPER_EXT_TLV_IFL_UNIT: case JUNIPER_EXT_TLV_IFD_IDX: default: if (tlv_value != -1) { if (ndo->ndo_vflag > 1) ND_PRINT("%u", tlv_value); } break; } tptr+=tlv_len; jnx_ext_len -= tlv_len+JUNIPER_EXT_TLV_OVERHEAD; } if (ndo->ndo_vflag > 1) ND_PRINT("\n\t-----original packet-----\n\t"); } if ((l2info->flags & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) { if (ndo->ndo_eflag) ND_PRINT("no-L2-hdr, "); /* there is no link-layer present - * perform the v4/v6 heuristics * to figure out what it is */ ND_TCHECK_1(p + (jnx_header_len + 4)); if (ip_heuristic_guess(ndo, p + jnx_header_len + 4, l2info->length - (jnx_header_len + 4)) == 0) ND_PRINT("no IP-hdr found!"); l2info->header_len=jnx_header_len+4; return 0; /* stop parsing the output further */ } l2info->header_len = jnx_header_len; p+=l2info->header_len; l2info->length -= l2info->header_len; l2info->caplen -= l2info->header_len; /* search through the cookie table and copy values matching for our PIC type */ ND_TCHECK_1(p); while (lp->s != NULL) { if (lp->pictype == l2info->pictype) { l2info->cookie_len += lp->cookie_len; switch (GET_U_1(p)) { case LS_COOKIE_ID: l2info->cookie_type = LS_COOKIE_ID; l2info->cookie_len += 2; break; case AS_COOKIE_ID: l2info->cookie_type = AS_COOKIE_ID; l2info->cookie_len = 8; break; default: l2info->bundle = l2info->cookie[0]; break; } #ifdef DLT_JUNIPER_MFR /* MFR child links don't carry cookies */ if (l2info->pictype == DLT_JUNIPER_MFR && (GET_U_1(p) & MFR_BE_MASK) == MFR_BE_MASK) { l2info->cookie_len = 0; } #endif l2info->header_len += l2info->cookie_len; l2info->length -= l2info->cookie_len; l2info->caplen -= l2info->cookie_len; if (ndo->ndo_eflag) ND_PRINT("%s-PIC, cookie-len %u", lp->s, l2info->cookie_len); if (l2info->cookie_len > 8) { nd_print_invalid(ndo); return 0; } if (l2info->cookie_len > 0) { ND_TCHECK_LEN(p, l2info->cookie_len); if (ndo->ndo_eflag) ND_PRINT(", cookie 0x"); for (idx = 0; idx < l2info->cookie_len; idx++) { l2info->cookie[idx] = GET_U_1(p + idx); /* copy cookie data */ if (ndo->ndo_eflag) ND_PRINT("%02x", GET_U_1(p + idx)); } } if (ndo->ndo_eflag) ND_PRINT(": "); /* print demarc b/w L2/L3*/ l2info->proto = GET_BE_U_2(p + l2info->cookie_len); break; } ++lp; } p+=l2info->cookie_len; /* DLT_ specific parsing */ switch(l2info->pictype) { #ifdef DLT_JUNIPER_MLPPP case DLT_JUNIPER_MLPPP: switch (l2info->cookie_type) { case LS_COOKIE_ID: l2info->bundle = l2info->cookie[1]; break; case AS_COOKIE_ID: /* use EXTRACT_, not GET_ (not packet buffer pointer) */ l2info->bundle = (EXTRACT_BE_U_2(&l2info->cookie[6])>>3)&0xfff; l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK; break; default: l2info->bundle = l2info->cookie[0]; break; } break; #endif #ifdef DLT_JUNIPER_MLFR case DLT_JUNIPER_MLFR: switch (l2info->cookie_type) { case LS_COOKIE_ID: l2info->bundle = l2info->cookie[1]; l2info->proto = GET_BE_U_2(p); l2info->header_len += 2; l2info->length -= 2; l2info->caplen -= 2; break; case AS_COOKIE_ID: /* use EXTRACT_, not GET_ (not packet buffer pointer) */ l2info->bundle = (EXTRACT_BE_U_2(&l2info->cookie[6])>>3)&0xfff; l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK; break; default: l2info->bundle = l2info->cookie[0]; l2info->header_len += 2; l2info->length -= 2; l2info->caplen -= 2; break; } break; #endif #ifdef DLT_JUNIPER_MFR case DLT_JUNIPER_MFR: switch (l2info->cookie_type) { case LS_COOKIE_ID: l2info->bundle = l2info->cookie[1]; l2info->proto = GET_BE_U_2(p); l2info->header_len += 2; l2info->length -= 2; l2info->caplen -= 2; break; case AS_COOKIE_ID: /* use EXTRACT_, not GET_ (not packet buffer pointer) */ l2info->bundle = (EXTRACT_BE_U_2(&l2info->cookie[6])>>3)&0xfff; l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK; break; default: l2info->bundle = l2info->cookie[0]; break; } break; #endif #ifdef DLT_JUNIPER_ATM2 case DLT_JUNIPER_ATM2: ND_TCHECK_4(p); /* ATM cell relay control word present ? */ if (l2info->cookie[7] & ATM2_PKT_TYPE_MASK) { control_word = GET_BE_U_4(p); /* some control word heuristics */ switch(control_word) { case 0: /* zero control word */ case 0x08000000: /* < JUNOS 7.4 control-word */ case 0x08380000: /* cntl word plus cell length (56) >= JUNOS 7.4*/ l2info->header_len += 4; break; default: break; } if (ndo->ndo_eflag) ND_PRINT("control-word 0x%08x ", control_word); } break; #endif #ifdef DLT_JUNIPER_GGSN case DLT_JUNIPER_GGSN: break; #endif #ifdef DLT_JUNIPER_ATM1 case DLT_JUNIPER_ATM1: break; #endif #ifdef DLT_JUNIPER_PPP case DLT_JUNIPER_PPP: break; #endif #ifdef DLT_JUNIPER_CHDLC case DLT_JUNIPER_CHDLC: break; #endif #ifdef DLT_JUNIPER_ETHER case DLT_JUNIPER_ETHER: break; #endif #ifdef DLT_JUNIPER_FRELAY case DLT_JUNIPER_FRELAY: break; #endif default: ND_PRINT("Unknown Juniper DLT_ type %u: ", l2info->pictype); break; } if (ndo->ndo_eflag) ND_PRINT("hlen %u, proto 0x%04x, ", l2info->header_len, l2info->proto); return 1; /* everything went ok so far. continue parsing */ trunc: nd_print_trunc(ndo); return 0; } #endif /* defined(DLT_JUNIPER_GGSN) || defined(DLT_JUNIPER_ES) || \ defined(DLT_JUNIPER_MONITOR) || defined(DLT_JUNIPER_SERVICES) || \ defined(DLT_JUNIPER_PPPOE) || defined(DLT_JUNIPER_ETHER) || \ defined(DLT_JUNIPER_PPP) || defined(DLT_JUNIPER_FRELAY) || \ defined(DLT_JUNIPER_CHDLC) || defined(DLT_JUNIPER_PPPOE_ATM) || \ defined(DLT_JUNIPER_MLPPP) || defined(DLT_JUNIPER_MFR) || \ defined(DLT_JUNIPER_MLFR) || defined(DLT_JUNIPER_ATM1) || \ defined(DLT_JUNIPER_ATM2) */ tcpdump-4.99.1/lbl/0000755000026300017510000000000014060212545012165 5ustar mcrmcrtcpdump-4.99.1/lbl/os-solaris2.h0000644000026300017510000000254014057477727014541 0ustar mcrmcr/* * Copyright (c) 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. */ /* Prototypes missing in SunOS 5 */ #if defined(_STDIO_H) && defined(HAVE_SETLINEBUF) int setlinebuf(FILE *); #endif char *strerror(int); int snprintf(char *, size_t, const char *, ...); tcpdump-4.99.1/lbl/os-sunos4.h0000644000026300017510000001366414057477727014247 0ustar mcrmcr/* * Copyright (c) 1989, 1990, 1993, 1994, 1995, 1996 * 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. */ /* Prototypes missing in SunOS 4 */ #ifdef FILE int _filbuf(FILE *); int _flsbuf(u_char, FILE *); int fclose(FILE *); int fflush(FILE *); int fgetc(FILE *); int fprintf(FILE *, const char *, ...); int fputc(int, FILE *); int fputs(const char *, FILE *); u_int fread(void *, u_int, u_int, FILE *); int fseek(FILE *, long, int); u_int fwrite(const void *, u_int, u_int, FILE *); int pclose(FILE *); void rewind(FILE *); void setbuf(FILE *, char *); int setlinebuf(FILE *); int ungetc(int, FILE *); int vfprintf(FILE *, const char *, ...); int vprintf(const char *, ...); #endif #if __GNUC__ <= 1 int read(int, char *, u_int); int write(int, char *, u_int); #endif long a64l(const char *); #ifdef __STDC__ struct sockaddr; #endif int accept(int, struct sockaddr *, int *); int bind(int, struct sockaddr *, int); int bcmp(const void *, const void *, u_int); void bcopy(const void *, void *, u_int); void bzero(void *, int); int chroot(const char *); int close(int); void closelog(void); int connect(int, struct sockaddr *, int); char *crypt(const char *, const char *); int daemon(int, int); int fchmod(int, int); int fchown(int, int, int); void endgrent(void); void endpwent(void); void endservent(void); #ifdef __STDC__ struct ether_addr; #endif struct ether_addr *ether_aton(const char *); int flock(int, int); #ifdef __STDC__ struct stat; #endif int fstat(int, struct stat *); #ifdef __STDC__ struct statfs; #endif int fstatfs(int, struct statfs *); int fsync(int); #ifdef __STDC__ struct timeb; #endif int ftime(struct timeb *); int ftruncate(int, off_t); int getdtablesize(void); long gethostid(void); int gethostname(char *, int); int getopt(int, char * const *, const char *); int getpagesize(void); char *getpass(char *); int getpeername(int, struct sockaddr *, int *); int getpriority(int, int); #ifdef __STDC__ struct rlimit; #endif int getrlimit(int, struct rlimit *); int getsockname(int, struct sockaddr *, int *); int getsockopt(int, int, int, char *, int *); #ifdef __STDC__ struct timeval; struct timezone; #endif int gettimeofday(struct timeval *, struct timezone *); char *getusershell(void); char *getwd(char *); int initgroups(const char *, int); int ioctl(int, int, caddr_t); int iruserok(u_long, int, char *, char *); int isatty(int); int killpg(int, int); int listen(int, int); #ifdef __STDC__ struct utmp; #endif void login(struct utmp *); int logout(const char *); off_t lseek(int, off_t, int); int lstat(const char *, struct stat *); int mkstemp(char *); char *mktemp(char *); int munmap(caddr_t, int); void openlog(const char *, int, int); void perror(const char *); int printf(const char *, ...); int puts(const char *); long random(void); int readlink(const char *, char *, int); #ifdef __STDC__ struct iovec; #endif int readv(int, struct iovec *, int); int recv(int, char *, u_int, int); int recvfrom(int, char *, u_int, int, struct sockaddr *, int *); int rename(const char *, const char *); int rcmd(char **, u_short, char *, char *, char *, int *); int rresvport(int *); int send(int, char *, u_int, int); int sendto(int, char *, u_int, int, struct sockaddr *, int); int setenv(const char *, const char *, int); int seteuid(int); int setpriority(int, int, int); int select(int, fd_set *, fd_set *, fd_set *, struct timeval *); int setpgrp(int, int); void setpwent(void); int setrlimit(int, struct rlimit *); void setservent(int); int setsockopt(int, int, int, char *, int); int shutdown(int, int); int sigblock(int); void (*signal (int, void (*) (int))) (int); int sigpause(int); int sigsetmask(int); #ifdef __STDC__ struct sigvec; #endif int sigvec(int, struct sigvec *, struct sigvec*); int snprintf(char *, size_t, const char *, ...); int socket(int, int, int); int socketpair(int, int, int, int *); int symlink(const char *, const char *); void srandom(int); int sscanf(char *, const char *, ...); int stat(const char *, struct stat *); int statfs(char *, struct statfs *); char *strerror(int); #ifdef __STDC__ struct tm; #endif int strftime(char *, int, char *, struct tm *); long strtol(const char *, char **, int); void sync(void); void syslog(int, const char *, ...); int system(const char *); long tell(int); time_t time(time_t *); char *timezone(int, int); int tolower(int); int toupper(int); int truncate(char *, off_t); void unsetenv(const char *); int vfork(void); int vsprintf(char *, const char *, ...); int writev(int, struct iovec *, int); #ifdef __STDC__ struct rusage; #endif int utimes(const char *, struct timeval *); #if __GNUC__ <= 1 int wait(int *); pid_t wait3(int *, int, struct rusage *); #endif /* Ugly signal hacking */ #ifdef SIG_ERR #undef SIG_ERR #define SIG_ERR (void (*)(int))-1 #undef SIG_DFL #define SIG_DFL (void (*)(int))0 #undef SIG_IGN #define SIG_IGN (void (*)(int))1 #ifdef KERNEL #undef SIG_CATCH #define SIG_CATCH (void (*)(int))2 #endif #undef SIG_HOLD #define SIG_HOLD (void (*)(int))3 #endif tcpdump-4.99.1/lbl/os-osf4.h0000644000026300017510000000246614057477727013665 0ustar mcrmcr/* * Copyright (c) 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. */ /* Prototypes missing in Digital UNIX 4.x */ int snprintf(char *, size_t, const char *, ...); int vsnprintf(char *, size_t, const char *, va_list); tcpdump-4.99.1/lbl/os-ultrix4.h0000644000026300017510000000312714057477727014420 0ustar mcrmcr/* * Copyright (c) 1990, 1993, 1994, 1995, 1996 * 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. */ /* Prototypes missing in Ultrix 4 */ int bcmp(const char *, const char *, u_int); void bcopy(const void *, void *, u_int); void bzero(void *, u_int); void endservent(void); int getopt(int, char * const *, const char *); #ifdef __STDC__ struct timeval; struct timezone; #endif int gettimeofday(struct timeval *, struct timezone *); int ioctl(int, int, caddr_t); int pfopen(char *, int); int setlinebuf(FILE *); int socket(int, int, int); tcpdump-4.99.1/print-forces.c0000644000026300017510000012301314057477734014216 0ustar mcrmcr/* * 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, and (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. * 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. * * Copyright (c) 2009 Mojatatu Networks, Inc * */ /* \summary: Forwarding and Control Element Separation (ForCES) Protocol printer */ /* specification: RFC 5810 */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" #include "extract.h" #define ForCES_VERS 1 #define ForCES_HDRL 24 #define ForCES_ALNL 4U #define TLV_HDRL 4 #define ILV_HDRL 8 #define TOM_RSVD 0x0 #define TOM_ASSNSETUP 0x1 #define TOM_ASSNTEARD 0x2 #define TOM_CONFIG 0x3 #define TOM_QUERY 0x4 #define TOM_EVENTNOT 0x5 #define TOM_PKTREDIR 0x6 #define TOM_HEARTBT 0x0F #define TOM_ASSNSETREP 0x11 #define TOM_CONFIGREP 0x13 #define TOM_QUERYREP 0x14 /* * tom_h Flags: resv1(8b):maxtlvs(4b):resv2(2b):mintlv(2b) */ #define ZERO_TTLV 0x01 #define ZERO_MORE_TTLV 0x02 #define ONE_MORE_TTLV 0x04 #define ZERO_TLV 0x00 #define ONE_TLV 0x10 #define TWO_TLV 0x20 #define MAX_TLV 0xF0 #define TTLV_T1 (ONE_MORE_TTLV|ONE_TLV) #define TTLV_T2 (ONE_MORE_TTLV|MAX_TLV) struct tom_h { uint32_t v; uint16_t flags; uint16_t op_msk; const char *s; int (*print) (netdissect_options *ndo, const u_char * pptr, u_int len, uint16_t op_msk, int indent); }; enum { TOM_RSV_I, TOM_ASS_I, TOM_AST_I, TOM_CFG_I, TOM_QRY_I, TOM_EVN_I, TOM_RED_I, TOM_HBT_I, TOM_ASR_I, TOM_CNR_I, TOM_QRR_I, _TOM_RSV_MAX }; #define TOM_MAX_IND (_TOM_RSV_MAX - 1) static int tom_valid(uint8_t tom) { if (tom > 0) { if (tom >= 0x7 && tom <= 0xe) return 0; if (tom == 0x10) return 0; if (tom > 0x14) return 0; return 1; } else return 0; } static const char * ForCES_node(uint32_t node) { if (node <= 0x3FFFFFFF) return "FE"; if (node >= 0x40000000 && node <= 0x7FFFFFFF) return "CE"; if (node >= 0xC0000000 && node <= 0xFFFFFFEF) return "AllMulticast"; if (node == 0xFFFFFFFD) return "AllCEsBroadcast"; if (node == 0xFFFFFFFE) return "AllFEsBroadcast"; if (node == 0xFFFFFFFF) return "AllBroadcast"; return "ForCESreserved"; } static const struct tok ForCES_ACKs[] = { {0x0, "NoACK"}, {0x1, "SuccessACK"}, {0x2, "FailureACK"}, {0x3, "AlwaysACK"}, {0, NULL} }; static const struct tok ForCES_EMs[] = { {0x0, "EMReserved"}, {0x1, "execute-all-or-none"}, {0x2, "execute-until-failure"}, {0x3, "continue-execute-on-failure"}, {0, NULL} }; static const struct tok ForCES_ATs[] = { {0x0, "Standalone"}, {0x1, "2PCtransaction"}, {0, NULL} }; static const struct tok ForCES_TPs[] = { {0x0, "StartofTransaction"}, {0x1, "MiddleofTransaction"}, {0x2, "EndofTransaction"}, {0x3, "abort"}, {0, NULL} }; /* * Structure of forces header, naked of TLVs. */ struct forcesh { nd_uint8_t fm_vrsvd; /* version and reserved */ #define ForCES_V(forcesh) (GET_U_1((forcesh)->fm_vrsvd) >> 4) nd_uint8_t fm_tom; /* type of message */ nd_uint16_t fm_len; /* total length * 4 bytes */ #define ForCES_BLN(forcesh) ((uint32_t)(GET_BE_U_2((forcesh)->fm_len) << 2)) nd_uint32_t fm_sid; /* Source ID */ #define ForCES_SID(forcesh) GET_BE_U_4((forcesh)->fm_sid) nd_uint32_t fm_did; /* Destination ID */ #define ForCES_DID(forcesh) GET_BE_U_4((forcesh)->fm_did) nd_uint8_t fm_cor[8]; /* correlator */ nd_uint32_t fm_flags; /* flags */ #define ForCES_ACK(forcesh) ((GET_BE_U_4((forcesh)->fm_flags)&0xC0000000) >> 30) #define ForCES_PRI(forcesh) ((GET_BE_U_4((forcesh)->fm_flags)&0x38000000) >> 27) #define ForCES_RS1(forcesh) ((GET_BE_U_4((forcesh)->fm_flags)&0x07000000) >> 24) #define ForCES_EM(forcesh) ((GET_BE_U_4((forcesh)->fm_flags)&0x00C00000) >> 22) #define ForCES_AT(forcesh) ((GET_BE_U_4((forcesh)->fm_flags)&0x00200000) >> 21) #define ForCES_TP(forcesh) ((GET_BE_U_4((forcesh)->fm_flags)&0x00180000) >> 19) #define ForCES_RS2(forcesh) ((GET_BE_U_4((forcesh)->fm_flags)&0x0007FFFF) >> 0) }; #define ForCES_HLN_VALID(fhl,tlen) ((tlen) >= ForCES_HDRL && \ (fhl) >= ForCES_HDRL && \ (fhl) == (tlen)) #define F_LFB_RSVD 0x0 #define F_LFB_FEO 0x1 #define F_LFB_FEPO 0x2 static const struct tok ForCES_LFBs[] = { {F_LFB_RSVD, "Invalid TLV"}, {F_LFB_FEO, "FEObj LFB"}, {F_LFB_FEPO, "FEProtoObj LFB"}, {0, NULL} }; /* this is defined in RFC5810 section A.2 */ /* https://www.iana.org/assignments/forces/forces.xhtml#oper-tlv-types */ enum { F_OP_RSV = 0, F_OP_SET = 1, F_OP_SETPROP = 2, F_OP_SETRESP = 3, F_OP_SETPRESP = 4, F_OP_DEL = 5, F_OP_DELRESP = 6, F_OP_GET = 7, F_OP_GETPROP = 8, F_OP_GETRESP = 9, F_OP_GETPRESP = 10, F_OP_REPORT = 11, F_OP_COMMIT = 12, F_OP_RCOMMIT = 13, F_OP_RTRCOMP = 14, _F_OP_MAX }; #define F_OP_MAX (_F_OP_MAX - 1) enum { B_OP_SET = 1 << (F_OP_SET - 1), B_OP_SETPROP = 1 << (F_OP_SETPROP - 1), B_OP_SETRESP = 1 << (F_OP_SETRESP - 1), B_OP_SETPRESP = 1 << (F_OP_SETPRESP - 1), B_OP_DEL = 1 << (F_OP_DEL - 1), B_OP_DELRESP = 1 << (F_OP_DELRESP - 1), B_OP_GET = 1 << (F_OP_GET - 1), B_OP_GETPROP = 1 << (F_OP_GETPROP - 1), B_OP_GETRESP = 1 << (F_OP_GETRESP - 1), B_OP_GETPRESP = 1 << (F_OP_GETPRESP - 1), B_OP_REPORT = 1 << (F_OP_REPORT - 1), B_OP_COMMIT = 1 << (F_OP_COMMIT - 1), B_OP_RCOMMIT = 1 << (F_OP_RCOMMIT - 1), B_OP_RTRCOMP = 1 << (F_OP_RTRCOMP - 1) }; struct optlv_h { uint16_t flags; uint16_t op_msk; const char *s; int (*print) (netdissect_options *ndo, const u_char * pptr, u_int len, uint16_t op_msk, int indent); }; static int genoptlv_print(netdissect_options *, const u_char * pptr, u_int len, uint16_t op_msk, int indent); static int recpdoptlv_print(netdissect_options *, const u_char * pptr, u_int len, uint16_t op_msk, int indent); static int invoptlv_print(netdissect_options *, const u_char * pptr, u_int len, uint16_t op_msk, int indent); #define OP_MIN_SIZ 8 struct pathdata_h { nd_uint16_t pflags; nd_uint16_t pIDcnt; }; #define B_FULLD 0x1 #define B_SPARD 0x2 #define B_RESTV 0x4 #define B_KEYIN 0x8 #define B_APPND 0x10 #define B_TRNG 0x20 static const struct optlv_h OPTLV_msg[F_OP_MAX + 1] = { /* F_OP_RSV */ {ZERO_TTLV, 0, "Invalid OPTLV", invoptlv_print}, /* F_OP_SET */ {TTLV_T2, B_FULLD | B_SPARD, " Set", recpdoptlv_print}, /* F_OP_SETPROP */ {TTLV_T2, B_FULLD | B_SPARD, " SetProp", recpdoptlv_print}, /* F_OP_SETRESP */ {TTLV_T2, B_RESTV, " SetResp", recpdoptlv_print}, /* F_OP_SETPRESP */ {TTLV_T2, B_RESTV, " SetPropResp", recpdoptlv_print}, /* F_OP_DEL */ {ZERO_TTLV, 0, " Del", recpdoptlv_print}, /* F_OP_DELRESP */ {TTLV_T2, B_RESTV, " DelResp", recpdoptlv_print}, /* F_OP_GET */ {ZERO_TTLV, 0, " Get", recpdoptlv_print}, /* F_OP_GETPROP */ {ZERO_TTLV, 0, " GetProp", recpdoptlv_print}, /* F_OP_GETRESP */ {TTLV_T2, B_FULLD | B_SPARD | B_RESTV, " GetResp", recpdoptlv_print}, /* F_OP_GETPRESP */ {TTLV_T2, B_FULLD | B_RESTV, " GetPropResp", recpdoptlv_print}, /* F_OP_REPORT */ {TTLV_T2, B_FULLD | B_SPARD, " Report", recpdoptlv_print}, /* F_OP_COMMIT */ {ZERO_TTLV, 0, " Commit", NULL}, /* F_OP_RCOMMIT */ {TTLV_T1, B_RESTV, " RCommit", genoptlv_print}, /* F_OP_RTRCOMP */ {ZERO_TTLV, 0, " RTRCOMP", NULL}, }; static const struct optlv_h * get_forces_optlv_h(uint16_t opt) { if (opt > F_OP_MAX || opt == F_OP_RSV) return &OPTLV_msg[F_OP_RSV]; return &OPTLV_msg[opt]; } #define IND_SIZE 256 #define IND_CHR ' ' #define IND_PREF '\n' #define IND_SUF 0x0 static char ind_buf[IND_SIZE]; static char * indent_pr(int indent, int nlpref) { int i = 0; char *r = ind_buf; if (indent > (IND_SIZE - 1)) indent = IND_SIZE - 1; if (nlpref) { r[i] = IND_PREF; i++; indent--; } while (--indent >= 0) r[i++] = IND_CHR; r[i] = IND_SUF; return r; } static int op_valid(uint16_t op, uint16_t mask) { if (op == 0) return 0; if (op <= F_OP_MAX) return (1 << (op - 1)) & mask; /* works only for 0x0001 through 0x0010 */ /* I guess we should allow vendor operations? */ if (op >= 0x8000) return 1; return 0; } #define F_TLV_RSVD 0x0000 #define F_TLV_REDR 0x0001 #define F_TLV_ASRS 0x0010 #define F_TLV_ASRT 0x0011 #define F_TLV_LFBS 0x1000 #define F_TLV_PDAT 0x0110 #define F_TLV_KEYI 0x0111 #define F_TLV_FULD 0x0112 #define F_TLV_SPAD 0x0113 #define F_TLV_REST 0x0114 #define F_TLV_METD 0x0115 #define F_TLV_REDD 0x0116 #define F_TLV_TRNG 0x0117 #define F_TLV_VNST 0x8000 static const struct tok ForCES_TLV[] = { {F_TLV_RSVD, "Invalid TLV"}, {F_TLV_REDR, "REDIRECT TLV"}, {F_TLV_ASRS, "ASResult TLV"}, {F_TLV_ASRT, "ASTreason TLV"}, {F_TLV_LFBS, "LFBselect TLV"}, {F_TLV_PDAT, "PATH-DATA TLV"}, {F_TLV_KEYI, "KEYINFO TLV"}, {F_TLV_FULD, "FULLDATA TLV"}, {F_TLV_SPAD, "SPARSEDATA TLV"}, {F_TLV_REST, "RESULT TLV"}, {F_TLV_METD, "METADATA TLV"}, {F_TLV_REDD, "REDIRECTDATA TLV"}, {0, NULL} }; #define TLV_HLN 4 static int ttlv_valid(uint16_t ttlv) { if (ttlv > 0) { if (ttlv == 1 || ttlv == 0x1000) return 1; if (ttlv >= 0x10 && ttlv <= 0x11) return 1; if (ttlv >= 0x110 && ttlv <= 0x116) return 1; if (ttlv >= 0x8000) return 0; /* XXX: */ } return 0; } struct forces_ilv { nd_uint32_t type; nd_uint32_t length; }; struct forces_tlv { nd_uint16_t type; nd_uint16_t length; }; #define F_ALN_LEN(len) roundup2(len, ForCES_ALNL) #define GET_TOP_TLV(fhdr) ((const struct forces_tlv *)((fhdr) + sizeof (struct forcesh))) #define TLV_SET_LEN(len) (F_ALN_LEN(TLV_HDRL) + (len)) #define TLV_DATA(tlvp) ((const void*)(((const char*)(tlvp)) + TLV_SET_LEN(0))) #define GO_NXT_TLV(tlv,rlen) ((rlen) -= F_ALN_LEN(GET_BE_U_2((tlv)->length)), \ (const struct forces_tlv*)(((const char*)(tlv)) \ + F_ALN_LEN(GET_BE_U_2((tlv)->length)))) #define ILV_SET_LEN(len) (F_ALN_LEN(ILV_HDRL) + (len)) #define ILV_DATA(ilvp) ((const void*)(((const char*)(ilvp)) + ILV_SET_LEN(0))) #define GO_NXT_ILV(ilv,rlen) ((rlen) -= F_ALN_LEN(GET_BE_U_4((ilv)->length)), \ (const struct forces_ilv *)(((const char*)(ilv)) \ + F_ALN_LEN(GET_BE_U_4((ilv)->length)))) #define INVALID_RLEN 1 #define INVALID_STLN 2 #define INVALID_LTLN 3 #define INVALID_ALEN 4 static const struct tok ForCES_TLV_err[] = { {INVALID_RLEN, "Invalid total length"}, {INVALID_STLN, "xLV too short"}, {INVALID_LTLN, "xLV too long"}, {INVALID_ALEN, "data padding missing"}, {0, NULL} }; static u_int tlv_valid(u_int tlvl, u_int rlen) { if (rlen < TLV_HDRL) return INVALID_RLEN; if (tlvl < TLV_HDRL) return INVALID_STLN; if (tlvl > rlen) return INVALID_LTLN; if (rlen < F_ALN_LEN(tlvl)) return INVALID_ALEN; return 0; } static int ilv_valid(netdissect_options *ndo, const struct forces_ilv *ilv, u_int rlen) { if (rlen < ILV_HDRL) return INVALID_RLEN; if (GET_BE_U_4(ilv->length) < ILV_HDRL) return INVALID_STLN; if (GET_BE_U_4(ilv->length) > rlen) return INVALID_LTLN; if (rlen < F_ALN_LEN(GET_BE_U_4(ilv->length))) return INVALID_ALEN; return 0; } static int lfbselect_print(netdissect_options *, const u_char * pptr, u_int len, uint16_t op_msk, int indent); static int redirect_print(netdissect_options *, const u_char * pptr, u_int len, uint16_t op_msk, int indent); static int asrtlv_print(netdissect_options *, const u_char * pptr, u_int len, uint16_t op_msk, int indent); static int asttlv_print(netdissect_options *, const u_char * pptr, u_int len, uint16_t op_msk, int indent); struct forces_lfbsh { nd_uint32_t class; nd_uint32_t instance; }; #define ASSNS_OPS (B_OP_REPORT) #define CFG_OPS (B_OP_SET|B_OP_SETPROP|B_OP_DEL|B_OP_COMMIT|B_OP_RTRCOMP) #define CFG_ROPS (B_OP_SETRESP|B_OP_SETPRESP|B_OP_DELRESP|B_OP_RCOMMIT) #define CFG_QY (B_OP_GET|B_OP_GETPROP) #define CFG_QYR (B_OP_GETRESP|B_OP_GETPRESP) #define CFG_EVN (B_OP_REPORT) static const struct tom_h ForCES_msg[TOM_MAX_IND + 1] = { /* TOM_RSV_I */ {TOM_RSVD, ZERO_TTLV, 0, "Invalid message", NULL}, /* TOM_ASS_I */ {TOM_ASSNSETUP, ZERO_MORE_TTLV | TWO_TLV, ASSNS_OPS, "Association Setup", lfbselect_print}, /* TOM_AST_I */ {TOM_ASSNTEARD, TTLV_T1, 0, "Association TearDown", asttlv_print}, /* TOM_CFG_I */ {TOM_CONFIG, TTLV_T2, CFG_OPS, "Config", lfbselect_print}, /* TOM_QRY_I */ {TOM_QUERY, TTLV_T2, CFG_QY, "Query", lfbselect_print}, /* TOM_EVN_I */ {TOM_EVENTNOT, TTLV_T1, CFG_EVN, "Event Notification", lfbselect_print}, /* TOM_RED_I */ {TOM_PKTREDIR, TTLV_T2, 0, "Packet Redirect", redirect_print}, /* TOM_HBT_I */ {TOM_HEARTBT, ZERO_TTLV, 0, "HeartBeat", NULL}, /* TOM_ASR_I */ {TOM_ASSNSETREP, TTLV_T1, 0, "Association Response", asrtlv_print}, /* TOM_CNR_I */ {TOM_CONFIGREP, TTLV_T2, CFG_ROPS, "Config Response", lfbselect_print}, /* TOM_QRR_I */ {TOM_QUERYREP, TTLV_T2, CFG_QYR, "Query Response", lfbselect_print}, }; static const struct tom_h * get_forces_tom(uint8_t tom) { int i; for (i = TOM_RSV_I; i <= TOM_MAX_IND; i++) { const struct tom_h *th = &ForCES_msg[i]; if (th->v == tom) return th; } return &ForCES_msg[TOM_RSV_I]; } struct pdata_ops { uint32_t v; uint16_t flags; uint16_t op_msk; const char *s; int (*print) (netdissect_options *, const u_char * pptr, u_int len, uint16_t op_msk, int indent); }; enum { PD_RSV_I, PD_SEL_I, PD_FDT_I, PD_SDT_I, PD_RES_I, PD_PDT_I, _PD_RSV_MAX }; #define PD_MAX_IND (_TOM_RSV_MAX - 1) static int pd_valid(uint16_t pd) { if (pd >= F_TLV_PDAT && pd <= F_TLV_REST) return 1; return 0; } static void chk_op_type(netdissect_options *ndo, uint16_t type, uint16_t msk, uint16_t omsk) { if (type != F_TLV_PDAT) { if (msk & B_KEYIN) { if (type != F_TLV_KEYI) { ND_PRINT("Based on flags expected KEYINFO TLV!\n"); } } else { if (!(msk & omsk)) { ND_PRINT("Illegal DATA encoding for type 0x%x programmed %x got %x\n", type, omsk, msk); } } } } #define F_SELKEY 1 #define F_SELTABRANGE 2 #define F_TABAPPEND 4 struct res_val { nd_uint8_t result; nd_uint8_t resv1; nd_uint16_t resv2; }; static int prestlv_print(netdissect_options *, const u_char * pptr, u_int len, uint16_t op_msk, int indent); static int pkeyitlv_print(netdissect_options *, const u_char * pptr, u_int len, uint16_t op_msk, int indent); static int fdatatlv_print(netdissect_options *, const u_char * pptr, u_int len, uint16_t op_msk, int indent); static int sdatatlv_print(netdissect_options *, const u_char * pptr, u_int len, uint16_t op_msk, int indent); static const struct pdata_ops ForCES_pdata[PD_MAX_IND + 1] = { /* PD_RSV_I */ {0, 0, 0, "Invalid message", NULL}, /* PD_SEL_I */ {F_TLV_KEYI, 0, 0, "KEYINFO TLV", pkeyitlv_print}, /* PD_FDT_I */ {F_TLV_FULD, 0, B_FULLD, "FULLDATA TLV", fdatatlv_print}, /* PD_SDT_I */ {F_TLV_SPAD, 0, B_SPARD, "SPARSEDATA TLV", sdatatlv_print}, /* PD_RES_I */ {F_TLV_REST, 0, B_RESTV, "RESULT TLV", prestlv_print}, /* PD_PDT_I */ {F_TLV_PDAT, 0, 0, "Inner PATH-DATA TLV", recpdoptlv_print}, }; static const struct pdata_ops * get_forces_pd(uint16_t pd) { int i; for (i = PD_RSV_I + 1; i <= PD_MAX_IND; i++) { const struct pdata_ops *pdo = &ForCES_pdata[i]; if (pdo->v == pd) return pdo; } return &ForCES_pdata[TOM_RSV_I]; } enum { E_SUCCESS, E_INVALID_HEADER, E_LENGTH_MISMATCH, E_VERSION_MISMATCH, E_INVALID_DESTINATION_PID, E_LFB_UNKNOWN, E_LFB_NOT_FOUND, E_LFB_INSTANCE_ID_NOT_FOUND, E_INVALID_PATH, E_COMPONENT_DOES_NOT_EXIST, E_EXISTS, E_NOT_FOUND, E_READ_ONLY, E_INVALID_ARRAY_CREATION, E_VALUE_OUT_OF_RANGE, E_CONTENTS_TOO_LONG, E_INVALID_PARAMETERS, E_INVALID_MESSAGE_TYPE, E_INVALID_FLAGS, E_INVALID_TLV, E_EVENT_ERROR, E_NOT_SUPPORTED, E_MEMORY_ERROR, E_INTERNAL_ERROR, /* 0x18-0xFE are reserved .. */ E_UNSPECIFIED_ERROR = 0XFF }; static const struct tok ForCES_errs[] = { {E_SUCCESS, "SUCCESS"}, {E_INVALID_HEADER, "INVALID HEADER"}, {E_LENGTH_MISMATCH, "LENGTH MISMATCH"}, {E_VERSION_MISMATCH, "VERSION MISMATCH"}, {E_INVALID_DESTINATION_PID, "INVALID DESTINATION PID"}, {E_LFB_UNKNOWN, "LFB UNKNOWN"}, {E_LFB_NOT_FOUND, "LFB NOT FOUND"}, {E_LFB_INSTANCE_ID_NOT_FOUND, "LFB INSTANCE ID NOT FOUND"}, {E_INVALID_PATH, "INVALID PATH"}, {E_COMPONENT_DOES_NOT_EXIST, "COMPONENT DOES NOT EXIST"}, {E_EXISTS, "EXISTS ALREADY"}, {E_NOT_FOUND, "NOT FOUND"}, {E_READ_ONLY, "READ ONLY"}, {E_INVALID_ARRAY_CREATION, "INVALID ARRAY CREATION"}, {E_VALUE_OUT_OF_RANGE, "VALUE OUT OF RANGE"}, {E_CONTENTS_TOO_LONG, "CONTENTS TOO LONG"}, {E_INVALID_PARAMETERS, "INVALID PARAMETERS"}, {E_INVALID_MESSAGE_TYPE, "INVALID MESSAGE TYPE"}, {E_INVALID_FLAGS, "INVALID FLAGS"}, {E_INVALID_TLV, "INVALID TLV"}, {E_EVENT_ERROR, "EVENT ERROR"}, {E_NOT_SUPPORTED, "NOT SUPPORTED"}, {E_MEMORY_ERROR, "MEMORY ERROR"}, {E_INTERNAL_ERROR, "INTERNAL ERROR"}, {E_UNSPECIFIED_ERROR, "UNSPECIFIED ERROR"}, {0, NULL} }; #define RESLEN 4 static int prestlv_print(netdissect_options *ndo, const u_char * pptr, u_int len, uint16_t op_msk _U_, int indent) { const struct forces_tlv *tlv = (const struct forces_tlv *)pptr; const u_char *tdp = (const u_char *) TLV_DATA(tlv); const struct res_val *r = (const struct res_val *)tdp; u_int dlen; uint8_t result; /* * pdatacnt_print() has ensured that len (the TLV length) * >= TLV_HDRL. */ dlen = len - TLV_HDRL; if (dlen != RESLEN) { ND_PRINT("illegal RESULT-TLV: %u bytes!\n", dlen); return -1; } ND_TCHECK_SIZE(r); result = GET_U_1(r->result); if (result >= 0x18 && result <= 0xFE) { ND_PRINT("illegal reserved result code: 0x%x!\n", result); return -1; } if (ndo->ndo_vflag >= 3) { char *ib = indent_pr(indent, 0); ND_PRINT("%s Result: %s (code 0x%x)\n", ib, tok2str(ForCES_errs, NULL, result), result); } return 0; trunc: nd_print_trunc(ndo); return -1; } static int fdatatlv_print(netdissect_options *ndo, const u_char * pptr, u_int len, uint16_t op_msk _U_, int indent) { const struct forces_tlv *tlv = (const struct forces_tlv *)pptr; u_int rlen; const u_char *tdp = (const u_char *) TLV_DATA(tlv); uint16_t type; /* * pdatacnt_print() or pkeyitlv_print() has ensured that len * (the TLV length) >= TLV_HDRL. */ rlen = len - TLV_HDRL; ND_TCHECK_SIZE(tlv); type = GET_BE_U_2(tlv->type); if (type != F_TLV_FULD) { ND_PRINT("Error: expecting FULLDATA!\n"); return -1; } if (ndo->ndo_vflag >= 3) { char *ib = indent_pr(indent + 2, 1); ND_PRINT("%s[", ib + 1); hex_print(ndo, ib, tdp, rlen); ND_PRINT("\n%s]", ib + 1); } return 0; trunc: nd_print_trunc(ndo); return -1; } static int sdatailv_print(netdissect_options *ndo, const u_char * pptr, u_int len, uint16_t op_msk _U_, int indent) { u_int rlen; const struct forces_ilv *ilv = (const struct forces_ilv *)pptr; int invilv; if (len < ILV_HDRL) { ND_PRINT("Error: BAD SPARSEDATA-TLV!\n"); return -1; } rlen = len; indent += 1; while (rlen != 0) { #if 0 ND_PRINT("Jamal - outstanding length <%u>\n", rlen); #endif char *ib = indent_pr(indent, 1); const u_char *tdp = (const u_char *) ILV_DATA(ilv); invilv = ilv_valid(ndo, ilv, rlen); if (invilv) { ND_PRINT("Error: %s, rlen %u\n", tok2str(ForCES_TLV_err, NULL, invilv), rlen); return -1; } if (ndo->ndo_vflag >= 3) { u_int ilvl = GET_BE_U_4(ilv->length); ND_PRINT("\n%s ILV: type %x length %u\n", ib + 1, GET_BE_U_4(ilv->type), ilvl); hex_print(ndo, "\t\t[", tdp, ilvl-ILV_HDRL); } ilv = GO_NXT_ILV(ilv, rlen); } return 0; } static int sdatatlv_print(netdissect_options *ndo, const u_char * pptr, u_int len, uint16_t op_msk, int indent) { const struct forces_tlv *tlv = (const struct forces_tlv *)pptr; u_int rlen; const u_char *tdp = (const u_char *) TLV_DATA(tlv); uint16_t type; /* * pdatacnt_print() has ensured that len (the TLV length) * >= TLV_HDRL. */ rlen = len - TLV_HDRL; ND_TCHECK_SIZE(tlv); type = GET_BE_U_2(tlv->type); if (type != F_TLV_SPAD) { ND_PRINT("Error: expecting SPARSEDATA!\n"); return -1; } return sdatailv_print(ndo, tdp, rlen, op_msk, indent); trunc: nd_print_trunc(ndo); return -1; } static int pkeyitlv_print(netdissect_options *ndo, const u_char * pptr, u_int len, uint16_t op_msk, int indent) { const struct forces_tlv *tlv = (const struct forces_tlv *)pptr; const u_char *tdp = (const u_char *) TLV_DATA(tlv); const u_char *dp = tdp + 4; const struct forces_tlv *kdtlv = (const struct forces_tlv *)dp; uint32_t id; char *ib = indent_pr(indent, 0); uint16_t type, tll; u_int invtlv; id = GET_BE_U_4(tdp); ND_PRINT("%sKeyinfo: Key 0x%x\n", ib, id); type = GET_BE_U_2(kdtlv->type); tll = GET_BE_U_2(kdtlv->length); invtlv = tlv_valid(tll, len); if (invtlv) { ND_PRINT("%s TLV type 0x%x len %u\n", tok2str(ForCES_TLV_err, NULL, invtlv), type, tll); return -1; } /* * At this point, tlv_valid() has ensured that the TLV * length is large enough but not too large (it doesn't * go past the end of the containing TLV). */ tll = GET_BE_U_2(kdtlv->length); dp = (const u_char *) TLV_DATA(kdtlv); return fdatatlv_print(ndo, dp, tll, op_msk, indent); } #define PTH_DESC_SIZE 12 static int pdatacnt_print(netdissect_options *ndo, const u_char * pptr, u_int len, uint16_t IDcnt, uint16_t op_msk, int indent) { u_int i; uint32_t id; char *ib = indent_pr(indent, 0); if ((op_msk & B_APPND) && ndo->ndo_vflag >= 3) { ND_PRINT("%sTABLE APPEND\n", ib); } for (i = 0; i < IDcnt; i++) { ND_TCHECK_4(pptr); if (len < 4) goto trunc; id = GET_BE_U_4(pptr); if (ndo->ndo_vflag >= 3) ND_PRINT("%sID#%02u: %u\n", ib, i + 1, id); len -= 4; pptr += 4; } if ((op_msk & B_TRNG) || (op_msk & B_KEYIN)) { if (op_msk & B_TRNG) { uint32_t starti, endi; if (len < PTH_DESC_SIZE) { ND_PRINT("pathlength %u with key/range too short %u\n", len, PTH_DESC_SIZE); return -1; } pptr += sizeof(struct forces_tlv); len -= sizeof(struct forces_tlv); starti = GET_BE_U_4(pptr); pptr += 4; len -= 4; endi = GET_BE_U_4(pptr); pptr += 4; len -= 4; if (ndo->ndo_vflag >= 3) ND_PRINT("%sTable range: [%u,%u]\n", ib, starti, endi); } if (op_msk & B_KEYIN) { const struct forces_tlv *keytlv; uint16_t tll; if (len < PTH_DESC_SIZE) { ND_PRINT("pathlength %u with key/range too short %u\n", len, PTH_DESC_SIZE); return -1; } /* skip keyid */ pptr += 4; len -= 4; keytlv = (const struct forces_tlv *)pptr; /* skip header */ pptr += sizeof(struct forces_tlv); len -= sizeof(struct forces_tlv); /* skip key content */ tll = GET_BE_U_2(keytlv->length); if (tll < TLV_HDRL) { ND_PRINT("key content length %u < %u\n", tll, TLV_HDRL); return -1; } tll -= TLV_HDRL; if (len < tll) { ND_PRINT("key content too short\n"); return -1; } pptr += tll; len -= tll; } } if (len) { const struct forces_tlv *pdtlv = (const struct forces_tlv *)pptr; uint16_t type; uint16_t tlvl, tll; u_int pad = 0; u_int aln; u_int invtlv; type = GET_BE_U_2(pdtlv->type); tlvl = GET_BE_U_2(pdtlv->length); invtlv = tlv_valid(tlvl, len); if (invtlv) { ND_PRINT("%s Outstanding bytes %u for TLV type 0x%x TLV len %u\n", tok2str(ForCES_TLV_err, NULL, invtlv), len, type, tlvl); goto pd_err; } /* * At this point, tlv_valid() has ensured that the TLV * length is large enough but not too large (it doesn't * go past the end of the containing TLV). */ tll = tlvl - TLV_HDRL; aln = F_ALN_LEN(tlvl); if (aln > tlvl) { if (aln > len) { ND_PRINT("Invalid padded pathdata TLV type 0x%x len %u missing %u pad bytes\n", type, tlvl, aln - len); } else { pad = aln - tlvl; } } if (pd_valid(type)) { const struct pdata_ops *ops = get_forces_pd(type); if (ndo->ndo_vflag >= 3 && ops->v != F_TLV_PDAT) { if (pad) ND_PRINT("%s %s (Length %u DataLen %u pad %u Bytes)\n", ib, ops->s, tlvl, tll, pad); else ND_PRINT("%s %s (Length %u DataLen %u Bytes)\n", ib, ops->s, tlvl, tll); } chk_op_type(ndo, type, op_msk, ops->op_msk); if (ops->print(ndo, (const u_char *)pdtlv, tll + pad + TLV_HDRL, op_msk, indent + 2) == -1) return -1; len -= (TLV_HDRL + pad + tll); } else { ND_PRINT("Invalid path data content type 0x%x len %u\n", type, tlvl); pd_err: if (tlvl) { hex_print(ndo, "Bad Data val\n\t [", pptr, len); ND_PRINT("]\n"); return -1; } } } return len; trunc: nd_print_trunc(ndo); return -1; } static int pdata_print(netdissect_options *ndo, const u_char * pptr, u_int len, uint16_t op_msk, int indent) { const struct pathdata_h *pdh = (const struct pathdata_h *)pptr; char *ib = indent_pr(indent, 0); u_int minsize = 0; int more_pd = 0; uint16_t idcnt = 0; ND_TCHECK_SIZE(pdh); if (len < sizeof(struct pathdata_h)) goto trunc; if (ndo->ndo_vflag >= 3) { ND_PRINT("\n%sPathdata: Flags 0x%x ID count %u\n", ib, GET_BE_U_2(pdh->pflags), GET_BE_U_2(pdh->pIDcnt)); } if (GET_BE_U_2(pdh->pflags) & F_SELKEY) { op_msk |= B_KEYIN; } /* Table GET Range operation */ if (GET_BE_U_2(pdh->pflags) & F_SELTABRANGE) { op_msk |= B_TRNG; } /* Table SET append operation */ if (GET_BE_U_2(pdh->pflags) & F_TABAPPEND) { op_msk |= B_APPND; } pptr += sizeof(struct pathdata_h); len -= sizeof(struct pathdata_h); idcnt = GET_BE_U_2(pdh->pIDcnt); minsize = idcnt * 4; if (len < minsize) { ND_PRINT("\t\t\ttruncated IDs expected %uB got %uB\n", minsize, len); hex_print(ndo, "\t\t\tID Data[", pptr, len); ND_PRINT("]\n"); return -1; } if ((op_msk & B_TRNG) && (op_msk & B_KEYIN)) { ND_PRINT("\t\t\tIllegal to have both Table ranges and keys\n"); return -1; } more_pd = pdatacnt_print(ndo, pptr, len, idcnt, op_msk, indent); if (more_pd > 0) { int consumed = len - more_pd; pptr += consumed; len = more_pd; /* XXX: Argh, recurse some more */ return recpdoptlv_print(ndo, pptr, len, op_msk, indent+1); } else return 0; trunc: nd_print_trunc(ndo); return -1; } static int genoptlv_print(netdissect_options *ndo, const u_char * pptr, u_int len, uint16_t op_msk, int indent) { const struct forces_tlv *pdtlv = (const struct forces_tlv *)pptr; uint16_t type; u_int tlvl; u_int invtlv; char *ib = indent_pr(indent, 0); type = GET_BE_U_2(pdtlv->type); tlvl = GET_BE_U_2(pdtlv->length); invtlv = tlv_valid(tlvl, len); ND_PRINT("genoptlvprint - %s TLV type 0x%x len %u\n", tok2str(ForCES_TLV, NULL, type), type, tlvl); if (!invtlv) { /* * At this point, tlv_valid() has ensured that the TLV * length is large enough but not too large (it doesn't * go past the end of the containing TLV). */ const u_char *dp = (const u_char *) TLV_DATA(pdtlv); if (!ttlv_valid(type)) { ND_PRINT("%s TLV type 0x%x len %u\n", tok2str(ForCES_TLV_err, NULL, invtlv), type, tlvl); return -1; } if (ndo->ndo_vflag >= 3) ND_PRINT("%s%s, length %u (data length %u Bytes)", ib, tok2str(ForCES_TLV, NULL, type), tlvl, tlvl - TLV_HDRL); return pdata_print(ndo, dp, tlvl - TLV_HDRL, op_msk, indent + 1); } else { ND_PRINT("\t\t\tInvalid ForCES TLV type=%x", type); return -1; } } static int recpdoptlv_print(netdissect_options *ndo, const u_char * pptr, u_int len, uint16_t op_msk, int indent) { const struct forces_tlv *pdtlv = (const struct forces_tlv *)pptr; while (len != 0) { uint16_t type, tlvl; u_int invtlv; char *ib; const u_char *dp; tlvl = GET_BE_U_2(pdtlv->length); invtlv = tlv_valid(tlvl, len); if (invtlv) { break; } /* * At this point, tlv_valid() has ensured that the TLV * length is large enough but not too large (it doesn't * go past the end of the containing TLV). */ ib = indent_pr(indent, 0); type = GET_BE_U_2(pdtlv->type); dp = (const u_char *) TLV_DATA(pdtlv); if (ndo->ndo_vflag >= 3) ND_PRINT("%s%s, length %u (data encapsulated %u Bytes)", ib, tok2str(ForCES_TLV, NULL, type), tlvl, tlvl - TLV_HDRL); if (pdata_print(ndo, dp, tlvl - TLV_HDRL, op_msk, indent + 1) == -1) return -1; pdtlv = GO_NXT_TLV(pdtlv, len); } if (len) { ND_PRINT("\n\t\tMessy PATHDATA TLV header, type (0x%x)\n\t\texcess of %u Bytes ", GET_BE_U_2(pdtlv->type), len - GET_BE_U_2(pdtlv->length)); return -1; } return 0; } static int invoptlv_print(netdissect_options *ndo, const u_char * pptr, u_int len, uint16_t op_msk _U_, int indent) { char *ib = indent_pr(indent, 1); if (ndo->ndo_vflag >= 3) { ND_PRINT("%sData[", ib + 1); hex_print(ndo, ib, pptr, len); ND_PRINT("%s]\n", ib); } return -1; } static int otlv_print(netdissect_options *ndo, const struct forces_tlv *otlv, uint16_t op_msk _U_, int indent) { int rc = 0; const u_char *dp = (const u_char *) TLV_DATA(otlv); uint16_t type; u_int tll; char *ib = indent_pr(indent, 0); const struct optlv_h *ops; /* * lfbselect_print() has ensured that GET_BE_U_2(otlv->length) * >= TLV_HDRL. */ type = GET_BE_U_2(otlv->type); tll = GET_BE_U_2(otlv->length) - TLV_HDRL; ops = get_forces_optlv_h(type); if (ndo->ndo_vflag >= 3) { ND_PRINT("%sOper TLV %s(0x%x) length %u\n", ib, ops->s, type, GET_BE_U_2(otlv->length)); } /* rest of ops must at least have 12B {pathinfo} */ if (tll < OP_MIN_SIZ) { ND_PRINT("\t\tOper TLV %s(0x%x) length %u\n", ops->s, type, GET_BE_U_2(otlv->length)); ND_PRINT("\t\tTruncated data size %u minimum required %u\n", tll, OP_MIN_SIZ); return invoptlv_print(ndo, dp, tll, ops->op_msk, indent); } /* XXX - do anything with ops->flags? */ if(ops->print) { rc = ops->print(ndo, dp, tll, ops->op_msk, indent + 1); } return rc; } #define ASTDLN 4 #define ASTMCD 255 static int asttlv_print(netdissect_options *ndo, const u_char * pptr, u_int len, uint16_t op_msk _U_, int indent) { uint32_t rescode; u_int dlen; char *ib = indent_pr(indent, 0); /* * forces_type_print() has ensured that len (the TLV length) * >= TLV_HDRL. */ dlen = len - TLV_HDRL; if (dlen != ASTDLN) { ND_PRINT("illegal ASTresult-TLV: %u bytes!\n", dlen); return -1; } rescode = GET_BE_U_4(pptr); if (rescode > ASTMCD) { ND_PRINT("illegal ASTresult result code: %u!\n", rescode); return -1; } if (ndo->ndo_vflag >= 3) { ND_PRINT("Teardown reason:\n%s", ib); switch (rescode) { case 0: ND_PRINT("Normal Teardown"); break; case 1: ND_PRINT("Loss of Heartbeats"); break; case 2: ND_PRINT("Out of bandwidth"); break; case 3: ND_PRINT("Out of Memory"); break; case 4: ND_PRINT("Application Crash"); break; default: ND_PRINT("Unknown Teardown reason"); break; } ND_PRINT("(%x)\n%s", rescode, ib); } return 0; } #define ASRDLN 4 #define ASRMCD 3 static int asrtlv_print(netdissect_options *ndo, const u_char * pptr, u_int len, uint16_t op_msk _U_, int indent) { uint32_t rescode; u_int dlen; char *ib = indent_pr(indent, 0); /* * forces_type_print() has ensured that len (the TLV length) * >= TLV_HDRL. */ dlen = len - TLV_HDRL; if (dlen != ASRDLN) { /* id, instance, oper tlv */ ND_PRINT("illegal ASRresult-TLV: %u bytes!\n", dlen); return -1; } rescode = GET_BE_U_4(pptr); if (rescode > ASRMCD) { ND_PRINT("illegal ASRresult result code: %u!\n", rescode); return -1; } if (ndo->ndo_vflag >= 3) { ND_PRINT("\n%s", ib); switch (rescode) { case 0: ND_PRINT("Success "); break; case 1: ND_PRINT("FE ID invalid "); break; case 2: ND_PRINT("permission denied "); break; default: ND_PRINT("Unknown "); break; } ND_PRINT("(%x)\n%s", rescode, ib); } return 0; } #if 0 /* * XXX - not used. */ static int gentltlv_print(netdissect_options *ndo, const u_char * pptr _U_, u_int len, uint16_t op_msk _U_, int indent _U_) { u_int dlen = len - TLV_HDRL; if (dlen < 4) { /* at least 32 bits must exist */ ND_PRINT("truncated TLV: %u bytes missing! ", 4 - dlen); return -1; } return 0; } #endif #define RD_MIN 8 static int print_metailv(netdissect_options *ndo, const u_char * pptr, uint16_t op_msk _U_, int indent) { u_int rlen; char *ib = indent_pr(indent, 0); /* XXX: check header length */ const struct forces_ilv *ilv = (const struct forces_ilv *)pptr; /* * print_metatlv() has ensured that len (what remains in the * ILV) >= ILV_HDRL. */ rlen = GET_BE_U_4(ilv->length) - ILV_HDRL; ND_PRINT("%sMetaID 0x%x length %u\n", ib, GET_BE_U_4(ilv->type), GET_BE_U_4(ilv->length)); if (ndo->ndo_vflag >= 3) { hex_print(ndo, "\t\t[", ILV_DATA(ilv), rlen); ND_PRINT(" ]\n"); } return 0; } static int print_metatlv(netdissect_options *ndo, const u_char * pptr, u_int len, uint16_t op_msk _U_, int indent) { u_int dlen; char *ib = indent_pr(indent, 0); u_int rlen; const struct forces_ilv *ilv = (const struct forces_ilv *)pptr; int invilv; /* * redirect_print() has ensured that len (what remains in the * TLV) >= TLV_HDRL. */ dlen = len - TLV_HDRL; rlen = dlen; ND_PRINT("\n%s METADATA length %u\n", ib, rlen); while (rlen != 0) { invilv = ilv_valid(ndo, ilv, rlen); if (invilv) { break; } /* * At this point, ilv_valid() has ensured that the ILV * length is large enough but not too large (it doesn't * go past the end of the containing TLV). */ print_metailv(ndo, (const u_char *) ilv, 0, indent + 1); ilv = GO_NXT_ILV(ilv, rlen); } return 0; } static int print_reddata(netdissect_options *ndo, const u_char * pptr, u_int len, uint16_t op_msk _U_, int indent) { u_int dlen; char *ib = indent_pr(indent, 0); u_int rlen; dlen = len - TLV_HDRL; rlen = dlen; ND_PRINT("\n%s Redirect Data length %u\n", ib, rlen); if (ndo->ndo_vflag >= 3) { ND_PRINT("\t\t["); hex_print(ndo, "\n\t\t", pptr, rlen); ND_PRINT("\n\t\t]"); } return 0; } static int redirect_print(netdissect_options *ndo, const u_char * pptr, u_int len, uint16_t op_msk _U_, int indent) { const struct forces_tlv *tlv = (const struct forces_tlv *)pptr; u_int dlen; u_int rlen; u_int invtlv; /* * forces_type_print() has ensured that len (the TLV length) * >= TLV_HDRL. */ dlen = len - TLV_HDRL; if (dlen <= RD_MIN) { ND_PRINT("\n\t\ttruncated Redirect TLV: %u bytes missing! ", RD_MIN - dlen); return -1; } rlen = dlen; indent += 1; while (rlen != 0) { uint16_t type, tlvl; type = GET_BE_U_2(tlv->type); tlvl = GET_BE_U_2(tlv->length); invtlv = tlv_valid(tlvl, rlen); if (invtlv) { ND_PRINT("Bad Redirect data\n"); break; } /* * At this point, tlv_valid() has ensured that the TLV * length is large enough but not too large (it doesn't * go past the end of the containing TLV). */ if (type == F_TLV_METD) { print_metatlv(ndo, (const u_char *) TLV_DATA(tlv), tlvl, 0, indent); } else if (type == F_TLV_REDD) { print_reddata(ndo, (const u_char *) TLV_DATA(tlv), tlvl, 0, indent); } else { ND_PRINT("Unknown REDIRECT TLV 0x%x len %u\n", type, tlvl); } tlv = GO_NXT_TLV(tlv, rlen); } if (rlen) { ND_PRINT("\n\t\tMessy Redirect TLV header, type (0x%x)\n\t\texcess of %u Bytes ", GET_BE_U_2(tlv->type), rlen - GET_BE_U_2(tlv->length)); return -1; } return 0; } #define OP_OFF 8 #define OP_MIN 12 static int lfbselect_print(netdissect_options *ndo, const u_char * pptr, u_int len, uint16_t op_msk, int indent) { const struct forces_lfbsh *lfbs; const struct forces_tlv *otlv; char *ib = indent_pr(indent, 0); u_int dlen; u_int rlen; u_int invtlv; /* * forces_type_print() has ensured that len (the TLV length) * >= TLV_HDRL. */ dlen = len - TLV_HDRL; if (dlen <= OP_MIN) { /* id, instance, oper tlv header .. */ ND_PRINT("\n\t\ttruncated lfb selector: %u bytes missing! ", OP_MIN - dlen); return -1; } /* * At this point, we know that dlen > OP_MIN; OP_OFF < OP_MIN, so * we also know that it's > OP_OFF. */ rlen = dlen - OP_OFF; lfbs = (const struct forces_lfbsh *)pptr; ND_TCHECK_SIZE(lfbs); if (ndo->ndo_vflag >= 3) { ND_PRINT("\n%s%s(Classid %x) instance %x\n", ib, tok2str(ForCES_LFBs, NULL, GET_BE_U_4(lfbs->class)), GET_BE_U_4(lfbs->class), GET_BE_U_4(lfbs->instance)); } otlv = (const struct forces_tlv *)(lfbs + 1); indent += 1; while (rlen != 0) { uint16_t type, tlvl; type = GET_BE_U_2(otlv->type); tlvl = GET_BE_U_2(otlv->length); invtlv = tlv_valid(tlvl, rlen); if (invtlv) break; /* * At this point, tlv_valid() has ensured that the TLV * length is large enough but not too large (it doesn't * go past the end of the containing TLV). */ if (op_valid(type, op_msk)) { otlv_print(ndo, otlv, 0, indent); } else { if (ndo->ndo_vflag < 3) ND_PRINT("\n"); ND_PRINT("\t\tINValid oper-TLV type 0x%x length %u for this ForCES message\n", type, tlvl); invoptlv_print(ndo, (const u_char *)otlv, rlen, 0, indent); } otlv = GO_NXT_TLV(otlv, rlen); } if (rlen) { ND_PRINT("\n\t\tMessy oper TLV header, type (0x%x)\n\t\texcess of %u Bytes ", GET_BE_U_2(otlv->type), rlen - GET_BE_U_2(otlv->length)); return -1; } return 0; trunc: nd_print_trunc(ndo); return -1; } static int forces_type_print(netdissect_options *ndo, const u_char * pptr, const struct forcesh *fhdr _U_, u_int mlen, const struct tom_h *tops) { const struct forces_tlv *tltlv; u_int rlen; u_int invtlv; int rc = 0; u_int ttlv = 0; /* * forces_print() has already checked that mlen >= ForCES_HDRL * by calling ForCES_HLN_VALID(). */ rlen = mlen - ForCES_HDRL; if (rlen > TLV_HLN) { if (tops->flags & ZERO_TTLV) { ND_PRINT("<0x%x>Illegal Top level TLV!\n", tops->flags); return -1; } } else { if (tops->flags & ZERO_MORE_TTLV) return 0; if (tops->flags & ONE_MORE_TTLV) { ND_PRINT("\tTop level TLV Data missing!\n"); return -1; } } if (tops->flags & ZERO_TTLV) { return 0; } ttlv = tops->flags >> 4; tltlv = GET_TOP_TLV(pptr); /*XXX: 15 top level tlvs will probably be fine You are nuts if you send more ;-> */ while (rlen != 0) { uint16_t type, tlvl; type = GET_BE_U_2(tltlv->type); tlvl = GET_BE_U_2(tltlv->length); invtlv = tlv_valid(tlvl, rlen); if (invtlv) break; /* * At this point, tlv_valid() has ensured that the TLV * length is large enough but not too large (it doesn't * go past the end of the packet). */ if (!ttlv_valid(type)) { ND_PRINT("\n\tInvalid ForCES Top TLV type=0x%x", type); return -1; } if (ndo->ndo_vflag >= 3) ND_PRINT("\t%s, length %u (data length %u Bytes)", tok2str(ForCES_TLV, NULL, type), tlvl, tlvl - TLV_HDRL); rc = tops->print(ndo, (const u_char *) TLV_DATA(tltlv), tlvl, tops->op_msk, 9); if (rc < 0) { return -1; } tltlv = GO_NXT_TLV(tltlv, rlen); ttlv--; if (ttlv <= 0) break; } /* * XXX - if ttlv != 0, does that mean that the packet was too * short, and didn't have *enough* TLVs in it? */ if (rlen) { ND_PRINT("\tMess TopTLV header: min %u, total %u advertised %u ", TLV_HDRL, rlen, GET_BE_U_2(tltlv->length)); return -1; } return 0; } void forces_print(netdissect_options *ndo, const u_char * pptr, u_int len) { const struct forcesh *fhdr; u_int mlen; uint32_t flg_raw; uint8_t tom; const struct tom_h *tops; int rc = 0; ndo->ndo_protocol = "forces"; fhdr = (const struct forcesh *)pptr; ND_TCHECK_SIZE(fhdr); tom = GET_U_1(fhdr->fm_tom); if (!tom_valid(tom)) { ND_PRINT("Invalid ForCES message type %u\n", tom); goto error; } mlen = ForCES_BLN(fhdr); tops = get_forces_tom(tom); if (tops->v == TOM_RSVD) { ND_PRINT("\n\tUnknown ForCES message type=0x%x", tom); goto error; } ND_PRINT("\n\tForCES %s ", tops->s); if (!ForCES_HLN_VALID(mlen, len)) { ND_PRINT("Illegal ForCES pkt len - min %u, total recvd %u, advertised %u ", ForCES_HDRL, len, ForCES_BLN(fhdr)); goto error; } flg_raw = GET_BE_U_4(pptr + 20); if (ndo->ndo_vflag >= 1) { ND_PRINT("\n\tForCES Version %u len %uB flags 0x%08x ", ForCES_V(fhdr), mlen, flg_raw); ND_PRINT("\n\tSrcID 0x%x(%s) DstID 0x%x(%s) Correlator 0x%" PRIx64, ForCES_SID(fhdr), ForCES_node(ForCES_SID(fhdr)), ForCES_DID(fhdr), ForCES_node(ForCES_DID(fhdr)), GET_BE_U_8(fhdr->fm_cor)); } if (ndo->ndo_vflag >= 2) { ND_PRINT("\n\tForCES flags:\n\t %s(0x%x), prio=%u, %s(0x%x),\n\t %s(0x%x), %s(0x%x)\n", tok2str(ForCES_ACKs, "ACKUnknown", ForCES_ACK(fhdr)), ForCES_ACK(fhdr), ForCES_PRI(fhdr), tok2str(ForCES_EMs, "EMUnknown", ForCES_EM(fhdr)), ForCES_EM(fhdr), tok2str(ForCES_ATs, "ATUnknown", ForCES_AT(fhdr)), ForCES_AT(fhdr), tok2str(ForCES_TPs, "TPUnknown", ForCES_TP(fhdr)), ForCES_TP(fhdr)); ND_PRINT("\t Extra flags: rsv(b5-7) 0x%x rsv(b13-31) 0x%x\n", ForCES_RS1(fhdr), ForCES_RS2(fhdr)); } rc = forces_type_print(ndo, pptr, fhdr, mlen, tops); if (rc < 0) { error: hex_print(ndo, "\n\t[", pptr, len); ND_PRINT("\n\t]"); return; } if (ndo->ndo_vflag >= 4) { ND_PRINT("\n\t Raw ForCES message\n\t ["); hex_print(ndo, "\n\t ", pptr, len); ND_PRINT("\n\t ]"); } return; trunc: nd_print_trunc(ndo); } tcpdump-4.99.1/print-gre.c0000644000026300017510000002125414057477727013520 0ustar mcrmcr/* $OpenBSD: print-gre.c,v 1.6 2002/10/30 03:04:04 fgsch Exp $ */ /* * Copyright (c) 2002 Jason L. Wright (jason@thought.net) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* \summary: Generic Routing Encapsulation (GRE) printer */ /* * netdissect printer for GRE - Generic Routing Encapsulation * RFC1701 (GRE), RFC1702 (GRE IPv4), and RFC2637 (Enhanced GRE) */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" #include "addrtostr.h" #include "extract.h" #include "ethertype.h" #define GRE_CP 0x8000 /* checksum present */ #define GRE_RP 0x4000 /* routing present */ #define GRE_KP 0x2000 /* key present */ #define GRE_SP 0x1000 /* sequence# present */ #define GRE_sP 0x0800 /* source routing */ #define GRE_AP 0x0080 /* acknowledgment# present */ static const struct tok gre_flag_values[] = { { GRE_CP, "checksum present"}, { GRE_RP, "routing present"}, { GRE_KP, "key present"}, { GRE_SP, "sequence# present"}, { GRE_sP, "source routing present"}, { GRE_AP, "ack present"}, { 0, NULL } }; #define GRE_RECRS_MASK 0x0700 /* recursion count */ #define GRE_VERS_MASK 0x0007 /* protocol version */ /* source route entry types */ #define GRESRE_IP 0x0800 /* IP */ #define GRESRE_ASN 0xfffe /* ASN */ static void gre_print_0(netdissect_options *, const u_char *, u_int); static void gre_print_1(netdissect_options *, const u_char *, u_int); static int gre_sre_print(netdissect_options *, uint16_t, uint8_t, uint8_t, const u_char *, u_int); static int gre_sre_ip_print(netdissect_options *, uint8_t, uint8_t, const u_char *, u_int); static int gre_sre_asn_print(netdissect_options *, uint8_t, uint8_t, const u_char *, u_int); void gre_print(netdissect_options *ndo, const u_char *bp, u_int length) { u_int len = length, vers; ndo->ndo_protocol = "gre"; ND_TCHECK_2(bp); if (len < 2) goto trunc; vers = GET_BE_U_2(bp) & GRE_VERS_MASK; ND_PRINT("GREv%u",vers); switch(vers) { case 0: gre_print_0(ndo, bp, len); break; case 1: gre_print_1(ndo, bp, len); break; default: ND_PRINT(" ERROR: unknown-version"); break; } return; trunc: nd_print_trunc(ndo); } static void gre_print_0(netdissect_options *ndo, const u_char *bp, u_int length) { u_int len = length; uint16_t flags, prot; /* 16 bits ND_TCHECKed in gre_print() */ flags = GET_BE_U_2(bp); if (ndo->ndo_vflag) ND_PRINT(", Flags [%s]", bittok2str(gre_flag_values,"none",flags)); len -= 2; bp += 2; ND_TCHECK_2(bp); if (len < 2) goto trunc; prot = GET_BE_U_2(bp); len -= 2; bp += 2; if ((flags & GRE_CP) | (flags & GRE_RP)) { ND_TCHECK_2(bp); if (len < 2) goto trunc; if (ndo->ndo_vflag) ND_PRINT(", sum 0x%x", GET_BE_U_2(bp)); bp += 2; len -= 2; ND_TCHECK_2(bp); if (len < 2) goto trunc; ND_PRINT(", off 0x%x", GET_BE_U_2(bp)); bp += 2; len -= 2; } if (flags & GRE_KP) { ND_TCHECK_4(bp); if (len < 4) goto trunc; ND_PRINT(", key=0x%x", GET_BE_U_4(bp)); bp += 4; len -= 4; } if (flags & GRE_SP) { ND_TCHECK_4(bp); if (len < 4) goto trunc; ND_PRINT(", seq %u", GET_BE_U_4(bp)); bp += 4; len -= 4; } if (flags & GRE_RP) { for (;;) { uint16_t af; uint8_t sreoff; uint8_t srelen; ND_TCHECK_4(bp); if (len < 4) goto trunc; af = GET_BE_U_2(bp); sreoff = GET_U_1(bp + 2); srelen = GET_U_1(bp + 3); bp += 4; len -= 4; if (af == 0 && srelen == 0) break; if (!gre_sre_print(ndo, af, sreoff, srelen, bp, len)) goto trunc; if (len < srelen) goto trunc; bp += srelen; len -= srelen; } } if (ndo->ndo_eflag) ND_PRINT(", proto %s (0x%04x)", tok2str(ethertype_values,"unknown",prot), prot); ND_PRINT(", length %u",length); if (ndo->ndo_vflag < 1) ND_PRINT(": "); /* put in a colon as protocol demarc */ else ND_PRINT("\n\t"); /* if verbose go multiline */ switch (prot) { case ETHERTYPE_IP: ip_print(ndo, bp, len); break; case ETHERTYPE_IPV6: ip6_print(ndo, bp, len); break; case ETHERTYPE_MPLS: mpls_print(ndo, bp, len); break; case ETHERTYPE_IPX: ipx_print(ndo, bp, len); break; case ETHERTYPE_ATALK: atalk_print(ndo, bp, len); break; case ETHERTYPE_GRE_ISO: isoclns_print(ndo, bp, len); break; case ETHERTYPE_TEB: ether_print(ndo, bp, len, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL); break; default: ND_PRINT("gre-proto-0x%x", prot); } return; trunc: nd_print_trunc(ndo); } static void gre_print_1(netdissect_options *ndo, const u_char *bp, u_int length) { u_int len = length; uint16_t flags, prot; /* 16 bits ND_TCHECKed in gre_print() */ flags = GET_BE_U_2(bp); len -= 2; bp += 2; if (ndo->ndo_vflag) ND_PRINT(", Flags [%s]", bittok2str(gre_flag_values,"none",flags)); ND_TCHECK_2(bp); if (len < 2) goto trunc; prot = GET_BE_U_2(bp); len -= 2; bp += 2; if (flags & GRE_KP) { uint32_t k; ND_TCHECK_4(bp); if (len < 4) goto trunc; k = GET_BE_U_4(bp); ND_PRINT(", call %u", k & 0xffff); len -= 4; bp += 4; } if (flags & GRE_SP) { ND_TCHECK_4(bp); if (len < 4) goto trunc; ND_PRINT(", seq %u", GET_BE_U_4(bp)); bp += 4; len -= 4; } if (flags & GRE_AP) { ND_TCHECK_4(bp); if (len < 4) goto trunc; ND_PRINT(", ack %u", GET_BE_U_4(bp)); bp += 4; len -= 4; } if ((flags & GRE_SP) == 0) ND_PRINT(", no-payload"); if (ndo->ndo_eflag) ND_PRINT(", proto %s (0x%04x)", tok2str(ethertype_values,"unknown",prot), prot); ND_PRINT(", length %u",length); if ((flags & GRE_SP) == 0) return; if (ndo->ndo_vflag < 1) ND_PRINT(": "); /* put in a colon as protocol demarc */ else ND_PRINT("\n\t"); /* if verbose go multiline */ switch (prot) { case ETHERTYPE_PPP: ppp_print(ndo, bp, len); break; default: ND_PRINT("gre-proto-0x%x", prot); break; } return; trunc: nd_print_trunc(ndo); } static int gre_sre_print(netdissect_options *ndo, uint16_t af, uint8_t sreoff, uint8_t srelen, const u_char *bp, u_int len) { int ret; switch (af) { case GRESRE_IP: ND_PRINT(", (rtaf=ip"); ret = gre_sre_ip_print(ndo, sreoff, srelen, bp, len); ND_PRINT(")"); break; case GRESRE_ASN: ND_PRINT(", (rtaf=asn"); ret = gre_sre_asn_print(ndo, sreoff, srelen, bp, len); ND_PRINT(")"); break; default: ND_PRINT(", (rtaf=0x%x)", af); ret = 1; } return (ret); } static int gre_sre_ip_print(netdissect_options *ndo, uint8_t sreoff, uint8_t srelen, const u_char *bp, u_int len) { const u_char *up = bp; char buf[INET_ADDRSTRLEN]; if (sreoff & 3) { ND_PRINT(", badoffset=%u", sreoff); return (1); } if (srelen & 3) { ND_PRINT(", badlength=%u", srelen); return (1); } if (sreoff >= srelen) { ND_PRINT(", badoff/len=%u/%u", sreoff, srelen); return (1); } while (srelen != 0) { ND_TCHECK_4(bp); if (len < 4) return (0); addrtostr(bp, buf, sizeof(buf)); ND_PRINT(" %s%s", ((bp - up) == sreoff) ? "*" : "", buf); bp += 4; len -= 4; srelen -= 4; } return (1); trunc: return 0; } static int gre_sre_asn_print(netdissect_options *ndo, uint8_t sreoff, uint8_t srelen, const u_char *bp, u_int len) { const u_char *up = bp; if (sreoff & 1) { ND_PRINT(", badoffset=%u", sreoff); return (1); } if (srelen & 1) { ND_PRINT(", badlength=%u", srelen); return (1); } if (sreoff >= srelen) { ND_PRINT(", badoff/len=%u/%u", sreoff, srelen); return (1); } while (srelen != 0) { ND_TCHECK_2(bp); if (len < 2) return (0); ND_PRINT(" %s%x", ((bp - up) == sreoff) ? "*" : "", GET_BE_U_2(bp)); bp += 2; len -= 2; srelen -= 2; } return (1); trunc: return 0; } tcpdump-4.99.1/ah.h0000644000026300017510000000605514057477727012210 0ustar mcrmcr/* $NetBSD: ah.h,v 1.12 2000/07/23 05:23:04 itojun Exp $ */ /* $KAME: ah.h,v 1.12 2000/07/20 17:41:01 itojun Exp $ */ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project 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 BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* * RFC4302 authentication header. */ #ifndef ND_AH_H_ #define ND_AH_H_ /* * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Next Header | Payload Len | RESERVED | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Security Parameters Index (SPI) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Sequence Number Field | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | | * + Integrity Check Value-ICV (variable) | * | | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * Figure 1. AH Format */ struct ah { nd_uint8_t ah_nxt; /* Next Header */ nd_uint8_t ah_len; /* Payload Len in 32bit words minus 2 */ nd_uint16_t ah_reserved; /* Reserved for future use */ nd_uint32_t ah_spi; /* Security Parameters Index */ nd_uint32_t ah_seq; /* Sequence Number Field */ /* variable size, 32bit bound*/ /* Integrity Check Value-ICV */ }; #endif /* ND_AH_H_ */ tcpdump-4.99.1/print-cip.c0000644000026300017510000000441014057477727013511 0ustar mcrmcr/* * Marko Kiiskila carnil@cs.tut.fi * * Tampere University of Technology - Telecommunications Laboratory * * Permission to use, copy, modify and distribute this * software and its documentation is hereby granted, * provided that both the copyright notice and this * permission notice appear in all copies of the software, * derivative works or modified versions, and any portions * thereof, that both notices appear in supporting * documentation, and that the use of this software is * acknowledged in any publications resulting from using * the software. * * TUT ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" * CONDITION AND DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS * SOFTWARE. * */ /* \summary: Linux Classical IP over ATM printer */ #ifdef HAVE_CONFIG_H #include #endif #include #include "netdissect-stdinc.h" #define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "addrtoname.h" static const unsigned char rfcllc[] = { 0xaa, /* DSAP: non-ISO */ 0xaa, /* SSAP: non-ISO */ 0x03, /* Ctrl: Unnumbered Information Command PDU */ 0x00, /* OUI: EtherType */ 0x00, 0x00 }; /* * This is the top level routine of the printer. 'p' points * to the LLC/SNAP or raw header of the packet, 'h->ts' is the timestamp, * 'h->len' is the length of the packet off the wire, and 'h->caplen' * is the number of bytes actually captured. */ void cip_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { u_int caplen = h->caplen; u_int length = h->len; int llc_hdrlen; ndo->ndo_protocol = "cip"; if (ndo->ndo_eflag) /* * There is no MAC-layer header, so just print the length. */ ND_PRINT("%u: ", length); ND_TCHECK_LEN(p, sizeof(rfcllc)); if (memcmp(rfcllc, p, sizeof(rfcllc)) == 0) { /* * LLC header is present. Try to print it & higher layers. */ llc_hdrlen = llc_print(ndo, p, length, caplen, NULL, NULL); if (llc_hdrlen < 0) { /* packet type not known, print raw packet */ if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); llc_hdrlen = -llc_hdrlen; } } else { /* * LLC header is absent; treat it as just IP. */ llc_hdrlen = 0; ip_print(ndo, p, length); } ndo->ndo_ll_hdr_len += llc_hdrlen; } tcpdump-4.99.1/netdissect-alloc.h0000644000026300017510000000212314057477727015045 0ustar mcrmcr/* * Copyright (c) 2018 The TCPDUMP project * 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, and (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. * 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. */ #ifndef netdissect_alloc_h #define netdissect_alloc_h #include #include "netdissect-stdinc.h" #include "netdissect.h" typedef struct nd_mem_chunk { void *prev_mem_p; /* variable size data */ } nd_mem_chunk_t; void nd_add_alloc_list(netdissect_options *, nd_mem_chunk_t *); void * nd_malloc(netdissect_options *, size_t); void nd_free_all(netdissect_options *); #endif /* netdissect_alloc_h */ tcpdump-4.99.1/print-cdp.c0000644000026300017510000003047614057477734013515 0ustar mcrmcr/* * Copyright (c) 1992, 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. * * Code by Gert Doering, SpaceNet GmbH, gert@space.net * * Reference documentation: * https://web.archive.org/web/20000914194913/http://www.cisco.com/univercd/cc/td/doc/product/lan/trsrb/frames.pdf */ /* \summary: Cisco Discovery Protocol (CDP) printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include #define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "addrtoname.h" #include "extract.h" #include "nlpid.h" #define CDP_HEADER_LEN 4 #define CDP_HEADER_VERSION_OFFSET 0 #define CDP_HEADER_TTL_OFFSET 1 #define CDP_HEADER_CHECKSUM_OFFSET 2 #define CDP_TLV_HEADER_LEN 4 #define CDP_TLV_TYPE_OFFSET 0 #define CDP_TLV_LEN_OFFSET 2 static const struct tok cdp_capability_values[] = { { 0x01, "Router" }, { 0x02, "Transparent Bridge" }, { 0x04, "Source Route Bridge" }, { 0x08, "L2 Switch" }, { 0x10, "L3 capable" }, { 0x20, "IGMP snooping" }, { 0x40, "L1 capable" }, { 0, NULL } }; static void cdp_print_addr(netdissect_options *, const u_char *, u_int); static void cdp_print_prefixes(netdissect_options *, const u_char *, u_int); static void cdp_print_string(netdissect_options *ndo, const u_char *cp, const u_int len) { ND_PRINT("'"); (void)nd_printn(ndo, cp, len, NULL); ND_PRINT("'"); } static void cdp_print_power(netdissect_options *ndo, const u_char *cp, const u_int len) { u_int val = 0; switch (len) { case 1: val = GET_U_1(cp); break; case 2: val = GET_BE_U_2(cp); break; case 3: val = GET_BE_U_3(cp); break; } ND_PRINT("%1.2fW", val / 1000.0); } static void cdp_print_capability(netdissect_options *ndo, const u_char *cp, const u_int len _U_) { uint32_t val = GET_BE_U_4(cp); ND_PRINT("(0x%08x): %s", val, bittok2str(cdp_capability_values, "none", val)); } /* Rework the version string to get a nice indentation. */ static void cdp_print_version(netdissect_options *ndo, const u_char *cp, const u_int len) { unsigned i; ND_PRINT("\n\t "); for (i = 0; i < len; i++) { u_char c = GET_U_1(cp + i); if (c == '\n') ND_PRINT("\n\t "); else fn_print_char(ndo, c); } } static void cdp_print_uint16(netdissect_options *ndo, const u_char *cp, const u_int len _U_) { ND_PRINT("%u", GET_BE_U_2(cp)); } static void cdp_print_duplex(netdissect_options *ndo, const u_char *cp, const u_int len _U_) { ND_PRINT("%s", GET_U_1(cp) ? "full": "half"); } /* https://www.cisco.com/c/en/us/td/docs/voice_ip_comm/cata/186/2_12_m/english/release/notes/186rn21m.html * plus more details from other sources * * There are apparently versions of the request with both * 2 bytes and 3 bytes of value. The 3 bytes of value * appear to be a 1-byte application type followed by a * 2-byte VLAN ID; the 2 bytes of value are unknown * (they're 0x20 0x00 in some captures I've seen; that * is not a valid VLAN ID, as VLAN IDs are 12 bits). * * The replies all appear to be 3 bytes long. */ static void cdp_print_ata186(netdissect_options *ndo, const u_char *cp, const u_int len) { if (len == 2) ND_PRINT("unknown 0x%04x", GET_BE_U_2(cp)); else ND_PRINT("app %u, vlan %u", GET_U_1(cp), GET_BE_U_2(cp + 1)); } static void cdp_print_mtu(netdissect_options *ndo, const u_char *cp, const u_int len _U_) { ND_PRINT("%u bytes", GET_BE_U_4(cp)); } static void cdp_print_uint8x(netdissect_options *ndo, const u_char *cp, const u_int len _U_) { ND_PRINT("0x%02x", GET_U_1(cp)); } static void cdp_print_phys_loc(netdissect_options *ndo, const u_char *cp, const u_int len) { ND_PRINT("0x%02x", GET_U_1(cp)); if (len > 1) { ND_PRINT("/"); (void)nd_printn(ndo, cp + 1, len - 1, NULL); } } struct cdp_tlvinfo { const char *name; void (*printer)(netdissect_options *ndo, const u_char *, u_int); int min_len, max_len; }; #define T_DEV_ID 0x01 #define T_MAX 0x17 static const struct cdp_tlvinfo cdptlvs[T_MAX + 1] = { /* 0x00 */ [ T_DEV_ID ] = { "Device-ID", cdp_print_string, -1, -1 }, [ 0x02 ] = { "Address", cdp_print_addr, -1, -1 }, [ 0x03 ] = { "Port-ID", cdp_print_string, -1, -1 }, [ 0x04 ] = { "Capability", cdp_print_capability, 4, 4 }, [ 0x05 ] = { "Version String", cdp_print_version, -1, -1 }, [ 0x06 ] = { "Platform", cdp_print_string, -1, -1 }, [ 0x07 ] = { "Prefixes", cdp_print_prefixes, -1, -1 }, /* not documented */ [ 0x08 ] = { "Protocol-Hello option", NULL, -1, -1 }, /* CDPv2 */ [ 0x09 ] = { "VTP Management Domain", cdp_print_string, -1, -1 }, /* CDPv2 */ [ 0x0a ] = { "Native VLAN ID", cdp_print_uint16, 2, 2 }, /* CDPv2 */ [ 0x0b ] = { "Duplex", cdp_print_duplex, 1, 1 }, /* 0x0c */ /* 0x0d */ /* incomplete doc. */ [ 0x0e ] = { "ATA-186 VoIP VLAN assignment", cdp_print_ata186, 3, 3 }, /* incomplete doc. */ [ 0x0f ] = { "ATA-186 VoIP VLAN request", cdp_print_ata186, 2, 3 }, /* not documented */ [ 0x10 ] = { "power consumption", cdp_print_power, 1, 3 }, /* not documented */ [ 0x11 ] = { "MTU", cdp_print_mtu, 4, 4 }, /* not documented */ [ 0x12 ] = { "AVVID trust bitmap", cdp_print_uint8x, 1, 1 }, /* not documented */ [ 0x13 ] = { "AVVID untrusted ports CoS", cdp_print_uint8x, 1, 1 }, /* not documented */ [ 0x14 ] = { "System Name", cdp_print_string, -1, -1 }, /* not documented */ [ 0x15 ] = { "System Object ID (not decoded)", NULL, -1, -1 }, [ 0x16 ] = { "Management Addresses", cdp_print_addr, 4, -1 }, /* not documented */ [ 0x17 ] = { "Physical Location", cdp_print_phys_loc, 1, -1 }, }; void cdp_print(netdissect_options *ndo, const u_char *tptr, u_int length) { u_int orig_length = length; uint16_t checksum; ndo->ndo_protocol = "cdp"; if (length < CDP_HEADER_LEN) { ND_PRINT(" (packet length %u < %u)", length, CDP_HEADER_LEN); goto invalid; } ND_PRINT("CDPv%u, ttl: %us", GET_U_1(tptr + CDP_HEADER_VERSION_OFFSET), GET_U_1(tptr + CDP_HEADER_TTL_OFFSET)); checksum = GET_BE_U_2(tptr + CDP_HEADER_CHECKSUM_OFFSET); if (ndo->ndo_vflag) ND_PRINT(", checksum: 0x%04x (unverified), length %u", checksum, orig_length); tptr += CDP_HEADER_LEN; length -= CDP_HEADER_LEN; while (length) { u_int type, len; const struct cdp_tlvinfo *info; const char *name; u_char covered = 0; if (length < CDP_TLV_HEADER_LEN) { ND_PRINT(" (remaining packet length %u < %u)", length, CDP_TLV_HEADER_LEN); goto invalid; } type = GET_BE_U_2(tptr + CDP_TLV_TYPE_OFFSET); len = GET_BE_U_2(tptr + CDP_TLV_LEN_OFFSET); /* object length includes the 4 bytes header length */ info = type <= T_MAX ? &cdptlvs[type] : NULL; name = (info && info->name) ? info->name : "unknown field type"; if (len < CDP_TLV_HEADER_LEN) { if (ndo->ndo_vflag) ND_PRINT("\n\t%s (0x%02x), TLV length: %u byte%s (too short)", name, type, len, PLURAL_SUFFIX(len)); else ND_PRINT(", %s TLV length %u too short", name, len); goto invalid; } if (len > length) { ND_PRINT(" (TLV length %u > %u)", len, length); goto invalid; } tptr += CDP_TLV_HEADER_LEN; length -= CDP_TLV_HEADER_LEN; len -= CDP_TLV_HEADER_LEN; /* In non-verbose mode just print Device-ID. */ if (!ndo->ndo_vflag && type == T_DEV_ID) ND_PRINT(", Device-ID "); else if (ndo->ndo_vflag) ND_PRINT("\n\t%s (0x%02x), value length: %u byte%s: ", name, type, len, PLURAL_SUFFIX(len)); if (info) { if ((info->min_len > 0 && len < (unsigned)info->min_len) || (info->max_len > 0 && len > (unsigned)info->max_len)) ND_PRINT(" (malformed TLV)"); else if (ndo->ndo_vflag || type == T_DEV_ID) { if (info->printer) info->printer(ndo, tptr, len); else ND_TCHECK_LEN(tptr, len); /* * When the type is defined without a printer, * do not print the hex dump. */ covered = 1; } } if (!covered) { ND_TCHECK_LEN(tptr, len); print_unknown_data(ndo, tptr, "\n\t ", len); } tptr += len; length -= len; } if (ndo->ndo_vflag < 1) ND_PRINT(", length %u", orig_length); return; invalid: nd_print_invalid(ndo); ND_TCHECK_LEN(tptr, length); } /* * Protocol type values. * * PT_NLPID means that the protocol type field contains an OSI NLPID. * * PT_IEEE_802_2 means that the protocol type field contains an IEEE 802.2 * LLC header that specifies that the payload is for that protocol. */ #define PT_NLPID 1 /* OSI NLPID */ #define PT_IEEE_802_2 2 /* IEEE 802.2 LLC header */ static void cdp_print_addr(netdissect_options *ndo, const u_char * p, u_int l) { u_int num; static const u_char prot_ipv6[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00, 0x86, 0xdd }; if (l < 4) { ND_PRINT(" (not enough space for num)"); goto invalid; } num = GET_BE_U_4(p); p += 4; l -= 4; while (num) { u_int pt, pl, al; if (l < 2) { ND_PRINT(" (not enough space for PT+PL)"); goto invalid; } pt = GET_U_1(p); /* type of "protocol" field */ pl = GET_U_1(p + 1); /* length of "protocol" field */ p += 2; l -= 2; if (l < pl + 2) { ND_PRINT(" (not enough space for P+AL)"); goto invalid; } /* Skip the protocol for now. */ al = GET_BE_U_2(p + pl); /* address length */ if (pt == PT_NLPID && pl == 1 && GET_U_1(p) == NLPID_IP && al == 4) { /* * IPv4: protocol type = NLPID, protocol length = 1 * (1-byte NLPID), protocol = 0xcc (NLPID for IPv4), * address length = 4 */ p += pl + 2; l -= pl + 2; /* p is just beyond al now. */ if (l < al) { ND_PRINT(" (not enough space for A)"); goto invalid; } ND_PRINT("IPv4 (%u) %s", num, GET_IPADDR_STRING(p)); p += al; l -= al; } else if (pt == PT_IEEE_802_2 && pl == 8 && memcmp(p, prot_ipv6, 8) == 0 && al == 16) { /* * IPv6: protocol type = IEEE 802.2 header, * protocol length = 8 (size of LLC+SNAP header), * protocol = LLC+SNAP header with the IPv6 * Ethertype, address length = 16 */ p += pl + 2; l -= pl + 2; /* p is just beyond al now. */ if (l < al) { ND_PRINT(" (not enough space for A)"); goto invalid; } ND_PRINT("IPv6 (%u) %s", num, GET_IP6ADDR_STRING(p)); p += al; l -= al; } else { /* * Generic case: just print raw data */ ND_PRINT("pt=0x%02x, pl=%u, pb=", pt, pl); while (pl != 0) { ND_PRINT(" %02x", GET_U_1(p)); p++; l--; pl--; } ND_PRINT(", al=%u, a=", al); p += 2; l -= 2; /* p is just beyond al now. */ if (l < al) { ND_PRINT(" (not enough space for A)"); goto invalid; } while (al != 0) { ND_PRINT(" %02x", GET_U_1(p)); p++; l--; al--; } } num--; if (num) ND_PRINT(" "); } if (l) ND_PRINT(" (%u bytes of stray data)", l); return; invalid: ND_TCHECK_LEN(p, l); } static void cdp_print_prefixes(netdissect_options *ndo, const u_char * p, u_int l) { if (l % 5) { ND_PRINT(" [length %u is not a multiple of 5]", l); goto invalid; } ND_PRINT(" IPv4 Prefixes (%u):", l / 5); while (l > 0) { ND_PRINT(" %u.%u.%u.%u/%u", GET_U_1(p), GET_U_1(p + 1), GET_U_1(p + 2), GET_U_1(p + 3), GET_U_1(p + 4)); l -= 5; p += 5; } return; invalid: ND_TCHECK_LEN(p, l); } tcpdump-4.99.1/print-sunatm.c0000644000026300017510000000637714057477727014263 0ustar mcrmcr/* * Copyright (c) 1997 Yen Yen Lim and North Dakota State University * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Yen Yen Lim and North Dakota State University * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* \summary: SunATM DLPI capture printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "extract.h" #include "atm.h" /* SunATM header for ATM packet */ #define DIR_POS 0 /* Direction (0x80 = transmit, 0x00 = receive) */ #define VPI_POS 1 /* VPI */ #define VCI_POS 2 /* VCI */ #define PKT_BEGIN_POS 4 /* Start of the ATM packet */ /* Protocol type values in the bottom for bits of the byte at SUNATM_DIR_POS. */ #define PT_LANE 0x01 /* LANE */ #define PT_LLC 0x02 /* LLC encapsulation */ /* * This is the top level routine of the printer. 'p' points * to the SunATM pseudo-header for the packet, 'h->ts' is the timestamp, * 'h->len' is the length of the packet off the wire, and 'h->caplen' * is the number of bytes actually captured. */ void sunatm_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { u_int caplen = h->caplen; u_int length = h->len; u_short vci; u_char vpi; u_int traftype; ndo->ndo_protocol = "sunatm"; if (ndo->ndo_eflag) { ND_PRINT(GET_U_1(p + DIR_POS) & 0x80 ? "Tx: " : "Rx: "); } switch (GET_U_1(p + DIR_POS) & 0x0f) { case PT_LANE: traftype = ATM_LANE; break; case PT_LLC: traftype = ATM_LLC; break; default: traftype = ATM_UNKNOWN; break; } vpi = GET_U_1(p + VPI_POS); vci = GET_BE_U_2(p + VCI_POS); p += PKT_BEGIN_POS; caplen -= PKT_BEGIN_POS; length -= PKT_BEGIN_POS; ndo->ndo_ll_hdr_len += PKT_BEGIN_POS; atm_print(ndo, vpi, vci, traftype, p, length, caplen); } tcpdump-4.99.1/print-aoe.c0000644000026300017510000002420214057477734013501 0ustar mcrmcr/* * Copyright (c) 2014 The TCPDUMP project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* \summary: ATA over Ethernet (AoE) protocol printer */ /* specification: * https://web.archive.org/web/20161025044402/http://brantleycoilecompany.com/AoEr11.pdf */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "extract.h" #include "addrtoname.h" #define AOE_V1 1 #define ATA_SECTOR_SIZE 512 #define AOEV1_CMD_ISSUE_ATA_COMMAND 0 #define AOEV1_CMD_QUERY_CONFIG_INFORMATION 1 #define AOEV1_CMD_MAC_MASK_LIST 2 #define AOEV1_CMD_RESERVE_RELEASE 3 static const struct tok cmdcode_str[] = { { AOEV1_CMD_ISSUE_ATA_COMMAND, "Issue ATA Command" }, { AOEV1_CMD_QUERY_CONFIG_INFORMATION, "Query Config Information" }, { AOEV1_CMD_MAC_MASK_LIST, "MAC Mask List" }, { AOEV1_CMD_RESERVE_RELEASE, "Reserve/Release" }, { 0, NULL } }; #define AOEV1_COMMON_HDR_LEN 10U /* up to but w/o Arg */ #define AOEV1_ISSUE_ARG_LEN 12U /* up to but w/o Data */ #define AOEV1_QUERY_ARG_LEN 8U /* up to but w/o Config String */ #define AOEV1_MAC_ARG_LEN 4U /* up to but w/o Directive 0 */ #define AOEV1_RESERVE_ARG_LEN 2U /* up to but w/o Ethernet address 0 */ #define AOEV1_MAX_CONFSTR_LEN 1024U #define AOEV1_FLAG_R 0x08 #define AOEV1_FLAG_E 0x04 static const struct tok aoev1_flag_str[] = { { AOEV1_FLAG_R, "Response" }, { AOEV1_FLAG_E, "Error" }, { 0x02, "MBZ-1" }, { 0x01, "MBZ-0" }, { 0, NULL } }; static const struct tok aoev1_errcode_str[] = { { 1, "Unrecognized command code" }, { 2, "Bad argument parameter" }, { 3, "Device unavailable" }, { 4, "Config string present" }, { 5, "Unsupported version" }, { 6, "Target is reserved" }, { 0, NULL } }; #define AOEV1_AFLAG_E 0x40 #define AOEV1_AFLAG_D 0x10 #define AOEV1_AFLAG_A 0x02 #define AOEV1_AFLAG_W 0x01 static const struct tok aoev1_aflag_bitmap_str[] = { { 0x80, "MBZ-7" }, { AOEV1_AFLAG_E, "Ext48" }, { 0x20, "MBZ-5" }, { AOEV1_AFLAG_D, "Device" }, { 0x08, "MBZ-3" }, { 0x04, "MBZ-2" }, { AOEV1_AFLAG_A, "Async" }, { AOEV1_AFLAG_W, "Write" }, { 0, NULL } }; static const struct tok aoev1_ccmd_str[] = { { 0, "read config string" }, { 1, "test config string" }, { 2, "test config string prefix" }, { 3, "set config string" }, { 4, "force set config string" }, { 0, NULL } }; static const struct tok aoev1_mcmd_str[] = { { 0, "Read Mac Mask List" }, { 1, "Edit Mac Mask List" }, { 0, NULL } }; static const struct tok aoev1_merror_str[] = { { 1, "Unspecified Error" }, { 2, "Bad DCmd directive" }, { 3, "Mask list full" }, { 0, NULL } }; static const struct tok aoev1_dcmd_str[] = { { 0, "No Directive" }, { 1, "Add mac address to mask list" }, { 2, "Delete mac address from mask list" }, { 0, NULL } }; static const struct tok aoev1_rcmd_str[] = { { 0, "Read reserve list" }, { 1, "Set reserve list" }, { 2, "Force set reserve list" }, { 0, NULL } }; static void aoev1_issue_print(netdissect_options *ndo, const u_char *cp, u_int len) { if (len < AOEV1_ISSUE_ARG_LEN) goto invalid; /* AFlags */ ND_PRINT("\n\tAFlags: [%s]", bittok2str(aoev1_aflag_bitmap_str, "none", GET_U_1(cp))); cp += 1; len -= 1; /* Err/Feature */ ND_PRINT(", Err/Feature: %u", GET_U_1(cp)); cp += 1; len -= 1; /* Sector Count (not correlated with the length) */ ND_PRINT(", Sector Count: %u", GET_U_1(cp)); cp += 1; len -= 1; /* Cmd/Status */ ND_PRINT(", Cmd/Status: %u", GET_U_1(cp)); cp += 1; len -= 1; /* lba0 */ ND_PRINT("\n\tlba0: %u", GET_U_1(cp)); cp += 1; len -= 1; /* lba1 */ ND_PRINT(", lba1: %u", GET_U_1(cp)); cp += 1; len -= 1; /* lba2 */ ND_PRINT(", lba2: %u", GET_U_1(cp)); cp += 1; len -= 1; /* lba3 */ ND_PRINT(", lba3: %u", GET_U_1(cp)); cp += 1; len -= 1; /* lba4 */ ND_PRINT(", lba4: %u", GET_U_1(cp)); cp += 1; len -= 1; /* lba5 */ ND_PRINT(", lba5: %u", GET_U_1(cp)); cp += 1; len -= 1; /* Reserved */ ND_TCHECK_2(cp); cp += 2; len -= 2; /* Data */ if (len) ND_PRINT("\n\tData: %u bytes", len); return; invalid: nd_print_invalid(ndo); ND_TCHECK_LEN(cp, len); } static void aoev1_query_print(netdissect_options *ndo, const u_char *cp, u_int len) { uint16_t cslen; if (len < AOEV1_QUERY_ARG_LEN) goto invalid; /* Buffer Count */ ND_PRINT("\n\tBuffer Count: %u", GET_BE_U_2(cp)); cp += 2; len -= 2; /* Firmware Version */ ND_PRINT(", Firmware Version: %u", GET_BE_U_2(cp)); cp += 2; len -= 2; /* Sector Count */ ND_PRINT(", Sector Count: %u", GET_U_1(cp)); cp += 1; len -= 1; /* AoE/CCmd */ ND_PRINT(", AoE: %u, CCmd: %s", (GET_U_1(cp) & 0xF0) >> 4, tok2str(aoev1_ccmd_str, "Unknown (0x02x)", GET_U_1(cp) & 0x0F)); cp += 1; len -= 1; /* Config String Length */ cslen = GET_BE_U_2(cp); cp += 2; len -= 2; if (cslen > AOEV1_MAX_CONFSTR_LEN || cslen > len) goto invalid; /* Config String */ if (cslen) { ND_PRINT("\n\tConfig String (length %u): ", cslen); (void)nd_printn(ndo, cp, cslen, NULL); } return; invalid: nd_print_invalid(ndo); ND_TCHECK_LEN(cp, len); } static void aoev1_mac_print(netdissect_options *ndo, const u_char *cp, u_int len) { uint8_t dircount, i; if (len < AOEV1_MAC_ARG_LEN) goto invalid; /* Reserved */ cp += 1; len -= 1; /* MCmd */ ND_PRINT("\n\tMCmd: %s", tok2str(aoev1_mcmd_str, "Unknown (0x%02x)", GET_U_1(cp))); cp += 1; len -= 1; /* MError */ ND_PRINT(", MError: %s", tok2str(aoev1_merror_str, "Unknown (0x%02x)", GET_U_1(cp))); cp += 1; len -= 1; /* Dir Count */ dircount = GET_U_1(cp); cp += 1; len -= 1; ND_PRINT(", Dir Count: %u", dircount); if (dircount * 8U > len) goto invalid; /* directives */ for (i = 0; i < dircount; i++) { /* Reserved */ cp += 1; len -= 1; /* DCmd */ ND_PRINT("\n\t DCmd: %s", tok2str(aoev1_dcmd_str, "Unknown (0x%02x)", GET_U_1(cp))); cp += 1; len -= 1; /* Ethernet Address */ ND_PRINT(", Ethernet Address: %s", GET_ETHERADDR_STRING(cp)); cp += MAC_ADDR_LEN; len -= MAC_ADDR_LEN; } return; invalid: nd_print_invalid(ndo); ND_TCHECK_LEN(cp, len); } static void aoev1_reserve_print(netdissect_options *ndo, const u_char *cp, u_int len) { uint8_t nmacs, i; if (len < AOEV1_RESERVE_ARG_LEN || (len - AOEV1_RESERVE_ARG_LEN) % MAC_ADDR_LEN) goto invalid; /* RCmd */ ND_PRINT("\n\tRCmd: %s", tok2str(aoev1_rcmd_str, "Unknown (0x%02x)", GET_U_1(cp))); cp += 1; len -= 1; /* NMacs (correlated with the length) */ nmacs = GET_U_1(cp); cp += 1; len -= 1; ND_PRINT(", NMacs: %u", nmacs); if (nmacs * MAC_ADDR_LEN != len) goto invalid; /* addresses */ for (i = 0; i < nmacs; i++) { ND_PRINT("\n\tEthernet Address %u: %s", i, GET_ETHERADDR_STRING(cp)); cp += MAC_ADDR_LEN; len -= MAC_ADDR_LEN; } return; invalid: nd_print_invalid(ndo); ND_TCHECK_LEN(cp, len); } /* cp points to the Ver/Flags octet */ static void aoev1_print(netdissect_options *ndo, const u_char *cp, u_int len) { uint8_t flags, command; void (*cmd_decoder)(netdissect_options *, const u_char *, u_int); if (len < AOEV1_COMMON_HDR_LEN) goto invalid; /* Flags */ flags = GET_U_1(cp) & 0x0F; ND_PRINT(", Flags: [%s]", bittok2str(aoev1_flag_str, "none", flags)); cp += 1; len -= 1; if (! ndo->ndo_vflag) return; /* Error */ if (flags & AOEV1_FLAG_E) ND_PRINT("\n\tError: %s", tok2str(aoev1_errcode_str, "Invalid (%u)", GET_U_1(cp))); cp += 1; len -= 1; /* Major */ ND_PRINT("\n\tMajor: 0x%04x", GET_BE_U_2(cp)); cp += 2; len -= 2; /* Minor */ ND_PRINT(", Minor: 0x%02x", GET_U_1(cp)); cp += 1; len -= 1; /* Command */ command = GET_U_1(cp); cp += 1; len -= 1; ND_PRINT(", Command: %s", tok2str(cmdcode_str, "Unknown (0x%02x)", command)); /* Tag */ ND_PRINT(", Tag: 0x%08x", GET_BE_U_4(cp)); cp += 4; len -= 4; /* Arg */ cmd_decoder = command == AOEV1_CMD_ISSUE_ATA_COMMAND ? aoev1_issue_print : command == AOEV1_CMD_QUERY_CONFIG_INFORMATION ? aoev1_query_print : command == AOEV1_CMD_MAC_MASK_LIST ? aoev1_mac_print : command == AOEV1_CMD_RESERVE_RELEASE ? aoev1_reserve_print : NULL; if (cmd_decoder != NULL) cmd_decoder(ndo, cp, len); return; invalid: nd_print_invalid(ndo); ND_TCHECK_LEN(cp, len); } void aoe_print(netdissect_options *ndo, const u_char *cp, const u_int len) { uint8_t ver; ndo->ndo_protocol = "aoe"; ND_PRINT("AoE length %u", len); if (len < 1) goto invalid; /* Ver/Flags */ ver = (GET_U_1(cp) & 0xF0) >> 4; /* Don't advance cp yet: low order 4 bits are version-specific. */ ND_PRINT(", Ver %u", ver); switch (ver) { case AOE_V1: aoev1_print(ndo, cp, len); break; } return; invalid: nd_print_invalid(ndo); ND_TCHECK_LEN(cp, len); } tcpdump-4.99.1/print-raw.c0000644000026300017510000000307014057477727013530 0ustar mcrmcr/* * Copyright (c) 1996 * 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. */ /* \summary: Raw IP printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" /* * The DLT_RAW packet has no header. It contains a raw IP packet. */ void raw_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { ndo->ndo_protocol = "raw"; ndo->ndo_ll_hdr_len += 0; if (ndo->ndo_eflag) ND_PRINT("ip: "); ipN_print(ndo, p, h->len); } tcpdump-4.99.1/print-dtp.c0000644000026300017510000000612414057477727013531 0ustar mcrmcr/* * Copyright (c) 1998-2007 The TCPDUMP project * * 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, and (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. * 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. * * Original code by Carles Kishimoto */ /* \summary: Dynamic Trunking Protocol (DTP) printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "addrtoname.h" #include "extract.h" #define DTP_HEADER_LEN 1 #define DTP_DOMAIN_TLV 0x0001 #define DTP_STATUS_TLV 0x0002 #define DTP_DTP_TYPE_TLV 0x0003 #define DTP_NEIGHBOR_TLV 0x0004 static const struct tok dtp_tlv_values[] = { { DTP_DOMAIN_TLV, "Domain" }, { DTP_STATUS_TLV, "Status" }, { DTP_DTP_TYPE_TLV, "DTP type" }, { DTP_NEIGHBOR_TLV, "Neighbor" }, { 0, NULL} }; void dtp_print(netdissect_options *ndo, const u_char *tptr, u_int length) { ndo->ndo_protocol = "dtp"; if (length < DTP_HEADER_LEN) { ND_PRINT("[zero packet length]"); goto invalid; } ND_PRINT("DTPv%u, length %u", GET_U_1(tptr), length); /* * In non-verbose mode, just print version. */ if (ndo->ndo_vflag < 1) { return; } tptr += DTP_HEADER_LEN; length -= DTP_HEADER_LEN; while (length) { uint16_t type, len; if (length < 4) { ND_PRINT("[%u bytes remaining]", length); goto invalid; } type = GET_BE_U_2(tptr); len = GET_BE_U_2(tptr + 2); /* XXX: should not be but sometimes it is, see the test captures */ if (type == 0) return; ND_PRINT("\n\t%s (0x%04x) TLV, length %u", tok2str(dtp_tlv_values, "Unknown", type), type, len); /* infinite loop check */ if (len < 4 || len > length) { ND_PRINT("[invalid TLV length %u]", len); goto invalid; } switch (type) { case DTP_DOMAIN_TLV: ND_PRINT(", "); nd_printjnp(ndo, tptr+4, len-4); break; case DTP_STATUS_TLV: case DTP_DTP_TYPE_TLV: if (len != 5) goto invalid; ND_PRINT(", 0x%x", GET_U_1(tptr + 4)); break; case DTP_NEIGHBOR_TLV: if (len != 10) goto invalid; ND_PRINT(", %s", GET_ETHERADDR_STRING(tptr+4)); break; default: ND_TCHECK_LEN(tptr, len); break; } tptr += len; length -= len; } return; invalid: nd_print_invalid(ndo); ND_TCHECK_LEN(tptr, length); } tcpdump-4.99.1/config.h.in0000644000026300017510000002016714060212545013445 0ustar mcrmcr/* config.h.in. Generated from configure.ac by autoheader. */ /* Define to 1 if arpa/inet.h declares `ether_ntohost' */ #undef ARPA_INET_H_DECLARES_ETHER_NTOHOST /* define if you want to build the possibly-buggy SMB printer */ #undef ENABLE_SMB /* Define to 1 if you have the `bpf_dump' function. */ #undef HAVE_BPF_DUMP /* capsicum support available */ #undef HAVE_CAPSICUM /* Define to 1 if you have the `cap_enter' function. */ #undef HAVE_CAP_ENTER /* Define to 1 if you have the `cap_ioctls_limit' function. */ #undef HAVE_CAP_IOCTLS_LIMIT /* Define to 1 if you have the header file. */ #undef HAVE_CAP_NG_H /* Define to 1 if you have the `cap_rights_limit' function. */ #undef HAVE_CAP_RIGHTS_LIMIT /* Casper support available */ #undef HAVE_CASPER /* Define to 1 if you have the declaration of `ether_ntohost' */ #undef HAVE_DECL_ETHER_NTOHOST /* Define to 1 if you have the `ether_ntohost' function. */ #undef HAVE_ETHER_NTOHOST /* Define to 1 if you have the `EVP_CIPHER_CTX_new' function. */ #undef HAVE_EVP_CIPHER_CTX_NEW /* Define to 1 if you have the `EVP_DecryptInit_ex' function. */ #undef HAVE_EVP_DECRYPTINIT_EX /* Define to 1 if you have the header file. */ #undef HAVE_FCNTL_H /* Define to 1 if you have the `fork' function. */ #undef HAVE_FORK /* Define to 1 if you have the `getopt_long' function. */ #undef HAVE_GETOPT_LONG /* define if you have getrpcbynumber() */ #undef HAVE_GETRPCBYNUMBER /* Define to 1 if you have the `getservent' function. */ #undef HAVE_GETSERVENT /* Define to 1 if you have the header file. */ #undef HAVE_INTTYPES_H /* Define to 1 if you have the `cap-ng' library (-lcap-ng). */ #undef HAVE_LIBCAP_NG /* Define to 1 if you have the `crypto' library (-lcrypto). */ #undef HAVE_LIBCRYPTO /* Define to 1 if you have the `rpc' library (-lrpc). */ #undef HAVE_LIBRPC /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the header file. */ #undef HAVE_NET_IF_H /* Define to 1 if you have the header file. */ #undef HAVE_NET_IF_PFLOG_H /* Define to 1 if you have the header file. */ #undef HAVE_NET_PFVAR_H /* Define to 1 if you have the `openat' function. */ #undef HAVE_OPENAT /* Define to 1 if you have the header file. */ #undef HAVE_OPENSSL_EVP_H /* define if the OS provides AF_INET6 and struct in6_addr */ #undef HAVE_OS_IPV6_SUPPORT /* if there's an os_proto.h for this platform, to use additional prototypes */ #undef HAVE_OS_PROTO_H /* Define to 1 if you have the `pcap_breakloop' function. */ #undef HAVE_PCAP_BREAKLOOP /* Define to 1 if you have the `pcap_create' function. */ #undef HAVE_PCAP_CREATE /* define if libpcap has pcap_datalink_name_to_val() */ #undef HAVE_PCAP_DATALINK_NAME_TO_VAL /* define if libpcap has pcap_datalink_val_to_description() */ #undef HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION /* define if libpcap has pcap_debug */ #undef HAVE_PCAP_DEBUG /* Define to 1 if you have the `pcap_dump_flush' function. */ #undef HAVE_PCAP_DUMP_FLUSH /* Define to 1 if you have the `pcap_dump_ftell' function. */ #undef HAVE_PCAP_DUMP_FTELL /* Define to 1 if you have the `pcap_dump_ftell64' function. */ #undef HAVE_PCAP_DUMP_FTELL64 /* Define to 1 if you have the `pcap_findalldevs' function. */ #undef HAVE_PCAP_FINDALLDEVS /* Define to 1 if you have the `pcap_findalldevs_ex' function. */ #undef HAVE_PCAP_FINDALLDEVS_EX /* Define to 1 if you have the `pcap_free_datalinks' function. */ #undef HAVE_PCAP_FREE_DATALINKS /* Define to 1 if the system has the type `pcap_if_t'. */ #undef HAVE_PCAP_IF_T /* Define to 1 if you have the `pcap_lib_version' function. */ #undef HAVE_PCAP_LIB_VERSION /* define if libpcap has pcap_list_datalinks() */ #undef HAVE_PCAP_LIST_DATALINKS /* Define to 1 if you have the `pcap_open' function. */ #undef HAVE_PCAP_OPEN /* Define to 1 if you have the header file. */ #undef HAVE_PCAP_PCAP_INTTYPES_H /* Define to 1 if you have the `pcap_setdirection' function. */ #undef HAVE_PCAP_SETDIRECTION /* Define to 1 if you have the `pcap_set_datalink' function. */ #undef HAVE_PCAP_SET_DATALINK /* Define to 1 if you have the `pcap_set_immediate_mode' function. */ #undef HAVE_PCAP_SET_IMMEDIATE_MODE /* Define to 1 if you have the `pcap_set_optimizer_debug' function. */ #undef HAVE_PCAP_SET_OPTIMIZER_DEBUG /* Define to 1 if you have the `pcap_set_parser_debug' function. */ #undef HAVE_PCAP_SET_PARSER_DEBUG /* Define to 1 if you have the `pcap_set_tstamp_precision' function. */ #undef HAVE_PCAP_SET_TSTAMP_PRECISION /* Define to 1 if you have the `pcap_set_tstamp_type' function. */ #undef HAVE_PCAP_SET_TSTAMP_TYPE /* define if libpcap has pcap_version */ #undef HAVE_PCAP_VERSION /* Define to 1 if you have the `pfopen' function. */ #undef HAVE_PFOPEN /* Define to 1 if you have the header file. */ #undef HAVE_RPC_RPCENT_H /* Define to 1 if you have the header file. */ #undef HAVE_RPC_RPC_H /* Define to 1 if you have the `setlinebuf' function. */ #undef HAVE_SETLINEBUF /* Define to 1 if you have the header file. */ #undef HAVE_STDINT_H /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H /* Define to 1 if you have the `strdup' function. */ #undef HAVE_STRDUP /* Define to 1 if you have the `strftime' function. */ #undef HAVE_STRFTIME /* Define to 1 if you have the header file. */ #undef HAVE_STRINGS_H /* Define to 1 if you have the header file. */ #undef HAVE_STRING_H /* Define to 1 if you have the `strlcat' function. */ #undef HAVE_STRLCAT /* Define to 1 if you have the `strlcpy' function. */ #undef HAVE_STRLCPY /* Define to 1 if you have the `strsep' function. */ #undef HAVE_STRSEP /* Define to 1 if the system has the type `struct ether_addr'. */ #undef HAVE_STRUCT_ETHER_ADDR /* Define to 1 if you have the header file. */ #undef HAVE_SYS_STAT_H /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H /* Define to 1 if the system has the type `uintptr_t'. */ #undef HAVE_UINTPTR_T /* Define to 1 if you have the header file. */ #undef HAVE_UNISTD_H /* Define to 1 if you have the `vfork' function. */ #undef HAVE_VFORK /* define if libpcap has yydebug */ #undef HAVE_YYDEBUG /* Define to 1 if netinet/ether.h declares `ether_ntohost' */ #undef NETINET_ETHER_H_DECLARES_ETHER_NTOHOST /* Define to 1 if netinet/if_ether.h declares `ether_ntohost' */ #undef NETINET_IF_ETHER_H_DECLARES_ETHER_NTOHOST /* Define to 1 if net/ethernet.h declares `ether_ntohost' */ #undef NET_ETHERNET_H_DECLARES_ETHER_NTOHOST /* Define to the address where bug reports for this package should be sent. */ #undef PACKAGE_BUGREPORT /* Define to the full name of this package. */ #undef PACKAGE_NAME /* Define to the full name and version of this package. */ #undef PACKAGE_STRING /* Define to the one symbol short name of this package. */ #undef PACKAGE_TARNAME /* Define to the home page for this package. */ #undef PACKAGE_URL /* Define to the version of this package. */ #undef PACKAGE_VERSION /* Define to 1 if you have the ANSI C header files. */ #undef STDC_HEADERS /* Define to 1 if sys/ethernet.h declares `ether_ntohost' */ #undef SYS_ETHERNET_H_DECLARES_ETHER_NTOHOST /* define if you have ether_ntohost() and it works */ #undef USE_ETHER_NTOHOST /* Define if you enable support for libsmi */ #undef USE_LIBSMI /* define if should chroot when dropping privileges */ #undef WITH_CHROOT /* define if should drop privileges by default */ #undef WITH_USER /* define on AIX to get certain functions */ #undef _SUN /* to handle Ultrix compilers that don't support const in prototypes */ #undef const /* Define as token for inline if inlining supported */ #undef inline /* Define to `uint16_t' if u_int16_t not defined. */ #undef u_int16_t /* Define to `uint32_t' if u_int32_t not defined. */ #undef u_int32_t /* Define to `uint64_t' if u_int64_t not defined. */ #undef u_int64_t /* Define to `uint8_t' if u_int8_t not defined. */ #undef u_int8_t /* Define to the type of an unsigned integer type wide enough to hold a pointer, if such a type exists, and if the system does not define it. */ #undef uintptr_t tcpdump-4.99.1/CMakeLists.txt0000644000026300017510000011757114057477727014215 0ustar mcrmcrif(WIN32) # # We need 3.12 or later, so that we can set policy CMP0074; see # below. cmake_minimum_required(VERSION 3.12) else(WIN32) # # For now, require only 2.8.6, just in case somebody is # configuring with CMake on a "long-term support" version # of some OS and that version supplies an older version of # CMake. # # If this is ever updated to CMake 3.1 or later, remove the # stuff in cmake/Modules/FindPCAP.cmake that appends subdirectories # of directories from CMAKE_PREFIX_PATH to the PKG_CONFIG_PATH # environment variable when running pkg-config, to make sure # it finds any .pc file from there. # cmake_minimum_required(VERSION 2.8.6) endif(WIN32) # # We want find_path() and find_library() to honor {packagename}_ROOT, # as that appears to be the standard way to say "hey, look here for # this package" from the command line. # if(POLICY CMP0074) cmake_policy(SET CMP0074 NEW) endif() set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules) project(tcpdump) # # For checking if a compiler flag works and adding it if it does. # include(CheckCCompilerFlag) macro(check_and_add_compiler_option _option) message(STATUS "Checking C compiler flag ${_option}") string(REPLACE "=" "-" _temp_option_variable ${_option}) string(REGEX REPLACE "^-" "" _option_variable ${_temp_option_variable}) check_c_compiler_flag("${_option}" ${_option_variable}) if(${${_option_variable}}) set(C_ADDITIONAL_FLAGS "${C_ADDITIONAL_FLAGS} ${_option}") endif() endmacro() # # If we're building with Visual Studio, we require Visual Studio 2015, # in order to get sufficient C99 compatibility. Check for that. # # If not, try the appropriate flag for the compiler to enable C99 # features. # set(C_ADDITIONAL_FLAGS "") if(MSVC) if(MSVC_VERSION LESS 1900) message(FATAL_ERROR "Visual Studio 2015 or later is required") endif() # # Treat source files as being in UTF-8 with MSVC if it's not using # the Clang front end. # We assume that UTF-8 source is OK with other compilers and with # MSVC if it's using the Clang front end. # if(NOT ${CMAKE_C_COMPILER} MATCHES "clang*") set(C_ADDITIONAL_FLAGS "${C_ADDITIONAL_FLAGS} /utf-8") endif(NOT ${CMAKE_C_COMPILER} MATCHES "clang*") else(MSVC) # # Try to enable as many C99 features as we can. # At minimum, we want C++/C99-style // comments. # # Newer versions of compilers might default to supporting C99, but # older versions may require a special flag. # # Prior to CMake 3.1, setting CMAKE_C_STANDARD will not have any effect, # so, unless and until we require CMake 3.1 or later, we have to do it # ourselves on pre-3.1 CMake, so we just do it ourselves on all versions # of CMake. # # Note: with CMake 3.1 through 3.5, the only compilers for which CMake # handles CMAKE_C_STANDARD are GCC and Clang. 3.6 adds support only # for Intel C; 3.9 adds support for PGI C, Sun C, and IBM XL C, and # 3.10 adds support for Cray C and IAR C, but no version of CMake has # support for HP C. Therefore, even if we use CMAKE_C_STANDARD with # compilers for which CMake supports it, we may still have to do it # ourselves on other compilers. # # See the CMake documentation for the CMAKE__COMPILER_ID variables # for a list of compiler IDs. # # XXX - this just tests whether the option works and adds it if it does. # We don't test whether it's necessary in order to get the C99 features # that we use; if we ever have a user who tries to compile with a compiler # that can't be made to support those features, we can add a test to make # sure we actually *have* C99 support. # if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang") check_and_add_compiler_option("-std=gnu99") elseif(CMAKE_C_COMPILER_ID MATCHES "XL") # # We want support for extensions picked up for GNU C compatibility, # so we use -qlanglvl=extc99. # check_and_add_compiler_option("-qlanglvl=extc99") elseif(CMAKE_C_COMPILER_ID MATCHES "HP") check_and_add_compiler_option("-AC99") elseif(CMAKE_C_COMPILER_ID MATCHES "Sun") check_and_add_compiler_option("-xc99") elseif(CMAKE_C_COMPILER_ID MATCHES "Intel") check_and_add_compiler_option("-c99") endif() endif(MSVC) set(LIBRARY_NAME netdissect) ################################################################### # Parameters ################################################################### option(WITH_SMI "Build with libsmi, if available" ON) option(WITH_CRYPTO "Build with OpenSSL/libressl libcrypto, if available" ON) option(WITH_CAPSICUM "Build with Capsicum security functions, if available" ON) option(WITH_CAP_NG "Use libcap-ng, if available" ON) option(ENABLE_SMB "Build with the SMB dissector" OFF) # # String parameters. Neither of them are set, initially; only if the # user explicitly configures them are they set. # # WITH_CHROOT is STRING, not PATH, as the directory need not exist # when CMake is run. # set(WITH_CHROOT CACHE STRING "Directory to which to chroot when dropping privileges") set(WITH_USER CACHE STRING "User to whom to set the UID when dropping privileges") # # By default, build universal with the appropriate set of architectures # for the OS on which we're doing the build. # if(APPLE AND "${CMAKE_OSX_ARCHITECTURES}" STREQUAL "") # # Get the major version of Darwin. # string(REGEX MATCH "^([0-9]+)" SYSTEM_VERSION_MAJOR "${CMAKE_SYSTEM_VERSION}") if(SYSTEM_VERSION_MAJOR EQUAL 9) # # Leopard. Build for x86 and 32-bit PowerPC, with # x86 first. (That's what Apple does.) # set(CMAKE_OSX_ARCHITECTURES "i386;ppc") elseif(SYSTEM_VERSION_MAJOR EQUAL 10) # # Snow Leopard. Build for x86-64 and x86, with # x86-64 first. (That's what Apple does.) # set(CMAKE_OSX_ARCHITECTURES "x86_64;i386") endif() endif() ################################################################### # Versioning ################################################################### # Get, parse, format and set tcpdump's version string from # [tcpdump_root]/VERSION for later use. # Get MAJOR, MINOR, PATCH & SUFFIX file(STRINGS ${tcpdump_SOURCE_DIR}/VERSION PACKAGE_VERSION LIMIT_COUNT 1 # Read only the first line ) ###################################### # Project settings ###################################### add_definitions(-DHAVE_CONFIG_H) include_directories( ${CMAKE_CURRENT_BINARY_DIR} ${tcpdump_SOURCE_DIR} ) if(MSVC) add_definitions(-D__STDC__) add_definitions(-D_CRT_SECURE_NO_WARNINGS) endif(MSVC) if(MSVC) if (USE_STATIC_RT) MESSAGE(STATUS "Use STATIC runtime") set(NAME_RT MT) set (CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MT") set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MT") set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MT") set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd") set (CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} /MT") set (CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /MT") set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MT") set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MTd") else (USE_STATIC_RT) MESSAGE(STATUS "Use DYNAMIC runtime") set(NAME_RT MD) set (CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /MD") set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /MD") set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /MD") set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MDd") set (CMAKE_C_FLAGS_MINSIZEREL "${CMAKE_C_FLAGS_MINSIZEREL} /MD") set (CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} /MD") set (CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /MD") set (CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /MDd") endif (USE_STATIC_RT) endif(MSVC) ################################################################### # Detect available platform features ################################################################### include(CMakePushCheckState) include(CheckIncludeFile) include(CheckIncludeFiles) include(CheckFunctionExists) include(CheckLibraryExists) include(CheckSymbolExists) include(CheckStructHasMember) include(CheckVariableExists) include(CheckTypeSize) # # Header files. # check_include_file(fcntl.h HAVE_FCNTL_H) check_include_file(rpc/rpc.h HAVE_RPC_RPC_H) check_include_file(net/if.h HAVE_NET_IF_H) if(HAVE_RPC_RPC_H) check_include_files("rpc/rpc.h;rpc/rpcent.h" HAVE_RPC_RPCENT_H) endif(HAVE_RPC_RPC_H) if(NOT WIN32) check_include_files("sys/types.h;sys/socket.h;net/if.h;net/pfvar.h" HAVE_NET_PFVAR_H) if(HAVE_NET_PFVAR_H) check_include_files("sys/types.h;sys/socket.h;net/if.h;net/pfvar.h;net/if_pflog.h" HAVE_NET_IF_PFLOG_H) if(HAVE_NET_IF_PFLOG_H) set(LOCALSRC print-pflog.c ${LOCALSRC}) endif(HAVE_NET_IF_PFLOG_H) endif(HAVE_NET_PFVAR_H) endif(NOT WIN32) # # Functions. # check_function_exists(strlcat HAVE_STRLCAT) check_function_exists(strlcpy HAVE_STRLCPY) check_function_exists(strdup HAVE_STRDUP) check_function_exists(strsep HAVE_STRSEP) # # Find library needed for gethostbyaddr. # NOTE: if you hand check_library_exists as its last argument a variable # that's been set, it skips the test, so we need different variables. # set(TCPDUMP_LINK_LIBRARIES "") if(WIN32) # # We need winsock2.h and ws2tcpip.h. # cmake_push_check_state() set(CMAKE_REQUIRED_LIBRARIES ws2_32) check_symbol_exists(gethostbyaddr "winsock2.h;ws2tcpip.h" LIBWS2_32_HAS_GETHOSTBYADDR) cmake_pop_check_state() if(LIBWS2_32_HAS_GETHOSTBYADDR) set(TCPDUMP_LINK_LIBRARIES ws2_32 ${TCPDUMP_LINK_LIBRARIES}) else(LIBWS2_32_HAS_GETHOSTBYADDR) message(FATAL_ERROR "gethostbyaddr is required, but wasn't found") endif(LIBWS2_32_HAS_GETHOSTBYADDR) else(WIN32) check_function_exists(gethostbyaddr STDLIBS_HAVE_GETHOSTBYADDR) if(NOT STDLIBS_HAVE_GETHOSTBYADDR) check_library_exists(socket gethostbyaddr "" LIBSOCKET_HAS_GETHOSTBYADDR) if(LIBSOCKET_HAS_GETHOSTBYADDR) set(TCPDUMP_LINK_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} socket) else(LIBSOCKET_HAS_GETHOSTBYADDR) check_library_exists(nsl gethostbyaddr "" LIBNSL_HAS_GETHOSTBYADDR) if(LIBNSL_HAS_GETHOSTBYADDR) set(TCPDUMP_LINK_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} nsl) else(LIBNSL_HAS_GETHOSTBYADDR) message(FATAL_ERROR "gethostbyaddr is required, but wasn't found") endif(LIBNSL_HAS_GETHOSTBYADDR) endif(LIBSOCKET_HAS_GETHOSTBYADDR) endif(NOT STDLIBS_HAVE_GETHOSTBYADDR) endif(WIN32) # # This may require additional libraries. # cmake_push_check_state() set(CMAKE_REQUIRED_LIBRARIES ${TCPDUMP_LINK_LIBRARIES}) check_function_exists(getservent STDLIBS_HAVE_GETSERVENT) if(STDLIBS_HAVE_GETSERVENT) set(HAVE_GETSERVENT TRUE) else(STDLIBS_HAVE_GETSERVENT) # # Some platforms may need -lsocket for getservent. # set(CMAKE_REQUIRED_LIBRARIES socket ${TCPDUMP_LINK_LIBRARIES}) check_function_exists(getservent LIBSOCKET_HAS_GETSERVENT) if(LIBSOCKET_HAS_GETSERVENT) set(HAVE_GETSERVENT TRUE) set(TCPDUMP_LINK_LIBRARIES socket ${TCPDUMP_LINK_LIBRARIES}) endif(LIBSOCKET_HAS_GETSERVENT) endif(STDLIBS_HAVE_GETSERVENT) cmake_pop_check_state() # # Make sure we have vsnprintf() and snprintf(); we require them. # We use check_symbol_exists(), as they aren't necessarily external # functions - in Visual Studio, for example, they're inline functions # calling a common external function. # check_symbol_exists(vsnprintf "stdio.h" HAVE_VSNPRINTF) if(NOT HAVE_VSNPRINTF) message(FATAL_ERROR "vsnprintf() is required but wasn't found") endif(NOT HAVE_VSNPRINTF) check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF) if(NOT HAVE_SNPRINTF) message(FATAL_ERROR "snprintf() is required but wasn't found") endif() check_function_exists(getopt_long HAVE_GETOPT_LONG) check_function_exists(strftime HAVE_STRFTIME) check_function_exists(setlinebuf HAVE_SETLINEBUF) # # For Windows, don't need to waste time checking for fork() or vfork(). # if(NOT WIN32) check_function_exists(fork HAVE_FORK) check_function_exists(vfork HAVE_VFORK) endif(NOT WIN32) # # Some platforms may need -lnsl for getrpcbynumber. # cmake_push_check_state() set(CMAKE_REQUIRED_LIBRARIES ${TCPDUMP_LINK_LIBRARIES}) check_function_exists(getrpcbynumber STDLIBS_HAVE_GETRPCBYNUMBER) if(STDLIBS_HAVE_GETRPCBYNUMBER) set(HAVE_GETRPCBYNUMBER TRUE) else(STDLIBS_HAVE_GETRPCBYNUMBER) set(CMAKE_REQUIRED_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} nsl) check_function_exists(getrpcbynumber LIBNSL_HAS_GETRPCBYNUMBER) if(LIBNSL_HAS_GETRPCBYNUMBER) set(HAVE_GETRPCBYNUMBER TRUE) set(TCPDUMP_LINK_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} nsl) endif(LIBNSL_HAS_GETRPCBYNUMBER) endif(STDLIBS_HAVE_GETRPCBYNUMBER) cmake_pop_check_state() # # This requires the libraries we require, as ether_ntohost might be # in one of those libraries. That means we have to do this after # we check for those libraries. # # You are in a twisty little maze of UN*Xes, all different. # Some might not have ether_ntohost(). # Some might have it and declare it in . # Some might have it and declare it in # Some might have it and declare it in . # Some might have it and declare it in . # Some might have it and declare it in . # Some might have it and not declare it in any header file. # # Before you is a C compiler. # cmake_push_check_state() set(CMAKE_REQUIRED_LIBRARIES ${TCPDUMP_LINK_LIBRARIES}) check_function_exists(ether_ntohost HAVE_ETHER_NTOHOST) if(HAVE_ETHER_NTOHOST) # # OK, we have ether_ntohost(). We don't check whether it's buggy, # as we assume any system that has CMake is likely to be new enough # that, if it has ether_ntohost(), whatever bug is checked for in # autotools is fixed; we just decide to use it. # set(USE_ETHER_NTOHOST TRUE) # # Is it declared in ? # # This test fails if we don't have or if we do # but it doesn't declare ether_ntohost(). # check_symbol_exists(ether_ntohost net/ethernet.h NET_ETHERNET_H_DECLARES_ETHER_NTOHOST) if(NET_ETHERNET_H_DECLARES_ETHER_NTOHOST) # # Yes - we have it declared. # set(HAVE_DECL_ETHER_NTOHOST TRUE) endif() # # Did that succeed? # if(NOT HAVE_DECL_ETHER_NTOHOST) # # No - how about , as on Linux? # # This test fails if we don't have # or if we do but it doesn't declare ether_ntohost(). # check_symbol_exists(ether_ntohost netinet/ether.h NETINET_ETHER_H_DECLARES_ETHER_NTOHOST) if(NETINET_ETHER_H_DECLARES_ETHER_NTOHOST) # # Yes - we have it declared. # set(HAVE_DECL_ETHER_NTOHOST TRUE) endif() endif() # # Did that succeed? # if(NOT HAVE_DECL_ETHER_NTOHOST) # # No - how about , as on Solaris 10 and later? # # This test fails if we don't have # or if we do but it doesn't declare ether_ntohost(). # check_symbol_exists(ether_ntohost sys/ethernet.h SYS_ETHERNET_H_DECLARES_ETHER_NTOHOST) if(SYS_ETHERNET_H_DECLARES_ETHER_NTOHOST) # # Yes - we have it declared. # set(HAVE_DECL_ETHER_NTOHOST TRUE) endif() endif() # # Did that succeed? # if(NOT HAVE_DECL_ETHER_NTOHOST) # # No, how about , as on AIX? # # This test fails if we don't have # or if we do but it doesn't declare ether_ntohost(). # check_symbol_exists(ether_ntohost arpa/inet.h ARPA_INET_H_DECLARES_ETHER_NTOHOST) if(ARPA_INET_H_DECLARES_ETHER_NTOHOST) # # Yes - we have it declared. # set(HAVE_DECL_ETHER_NTOHOST TRUE) endif() endif() # # Did that succeed? # if(NOT HAVE_DECL_ETHER_NTOHOST) # # No, how about ? # On some platforms, it requires and # , and we always include it with # both of them, so test it with both of them. # # This test fails if we don't have # and the headers we include before it, or if we do but # doesn't declare ether_ntohost(). # check_symbol_exists(ether_ntohost "sys/types.h;sys/socket.h;net/if.h;netinet/in.h;netinet/if_ether.h" NETINET_IF_ETHER_H_DECLARES_ETHER_NTOHOST) if(NETINET_IF_ETHER_H_DECLARES_ETHER_NTOHOST) # # Yes - we have it declared. # set(HAVE_DECL_ETHER_NTOHOST TRUE) endif() endif() # # After all that, is ether_ntohost() declared? # if(NOT HAVE_DECL_ETHER_NTOHOST) # # No, we'll have to declare it ourselves. # Do we have "struct ether_addr" if we include? # check_struct_has_member("struct ether_addr" octet "sys/types.h;sys/socket.h;net/if.h;netinet/in.h;netinet/if_ether.h" HAVE_STRUCT_ETHER_ADDR) endif() endif() cmake_pop_check_state() # # Data types. # # XXX - there's no check_struct() macro that's like check_struct_has_member() # except that it only checks for the existence of the structure type, # so we use check_struct_has_member() and look for ss_family. # # # Check for IPv6 support. # We just check for AF_INET6 and struct in6_addr. # cmake_push_check_state() if(WIN32) set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h ws2tcpip.h) check_symbol_exists(AF_INET6 "sys/types.h;ws2tcpip.h" HAVE_AF_INET6) else(WIN32) set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h sys/socket.h netinet/in.h) check_symbol_exists(AF_INET6 "sys/types.h;sys/socket.h;netinet/in.h" HAVE_AF_INET6) endif(WIN32) check_type_size("struct in6_addr" HAVE_STRUCT_IN6_ADDR) cmake_pop_check_state() if(HAVE_AF_INET6 AND HAVE_STRUCT_IN6_ADDR) set(HAVE_OS_IPV6_SUPPORT TRUE) endif(HAVE_AF_INET6 AND HAVE_STRUCT_IN6_ADDR) ###################################### # External dependencies ###################################### # # libpcap/WinPcap/Npcap. # First, find it. # find_package(PCAP REQUIRED) include_directories(${PCAP_INCLUDE_DIRS}) cmake_push_check_state() # # Now check headers. # set(CMAKE_REQUIRED_INCLUDES ${PCAP_INCLUDE_DIRS}) # # Check whether we have pcap/pcap-inttypes.h. # If we do, we use that to get the C99 types defined. # check_include_file(pcap/pcap-inttypes.h HAVE_PCAP_PCAP_INTTYPES_H) # # Check for various functions in libpcap/WinPcap/Npcap. # cmake_push_check_state() set(CMAKE_REQUIRED_LIBRARIES ${PCAP_LIBRARIES}) # # Check for "pcap_list_datalinks()" and use a substitute version if # it's not present. If it is present, check for "pcap_free_datalinks()"; # if it's not present, we don't replace it for now. (We could do so # on UN*X, but not on Windows, where hilarity ensues if a program # built with one version of the MSVC support library tries to free # something allocated by a library built with another version of # the MSVC support library.) # check_function_exists(pcap_list_datalinks HAVE_PCAP_LIST_DATALINKS) if(HAVE_PCAP_LIST_DATALINKS) check_function_exists(pcap_free_datalinks HAVE_PCAP_FREE_DATALINKS) endif(HAVE_PCAP_LIST_DATALINKS) # # Check for "pcap_datalink_name_to_val()", and use a substitute # version if it's not present. If it is present, check for # "pcap_datalink_val_to_description()", and if we don't have it, # use a substitute version. # check_function_exists(pcap_datalink_name_to_val HAVE_PCAP_DATALINK_NAME_TO_VAL) if(HAVE_PCAP_DATALINK_NAME_TO_VAL) check_function_exists(pcap_datalink_val_to_description HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION) endif(HAVE_PCAP_DATALINK_NAME_TO_VAL) # # Check for "pcap_set_datalink()"; you can't substitute for it if # it's absent (it has hooks into libpcap), so just define the # HAVE_ value if it's there. # check_function_exists(pcap_set_datalink HAVE_PCAP_SET_DATALINK) # # Check for "pcap_breakloop()"; you can't substitute for it if # it's absent (it has hooks into the live capture routines), # so just define the HAVE_ value if it's there. # check_function_exists(pcap_breakloop HAVE_PCAP_BREAKLOOP) # # Check for "pcap_dump_ftell()"; we use a substitute version # if it's not present. # check_function_exists(pcap_dump_ftell HAVE_PCAP_DUMP_FTELL) # # Do we have the new open API? Check for pcap_create() and for # pcap_statustostr(), and assume that, if we have both of them, # we also have pcap_activate() and the other new routines # introduced in libpcap 1.0.0. (We check for pcap_statustostr() # as well, because WinPcap 4.1.3 screwed up and exported pcap_create() # but not other routines such as pcap_statustostr(), even though it # defined them and even though you really want pcap_statustostr() to # get strings corresponding to some of the status returns from the # new routines.) # check_function_exists(pcap_statustostr HAVE_PCAP_STATUSTOSTR) # # If we don't have pcap_statustostr(), don't check for pcap_create(), # so we pretend we don't have it. # if(HAVE_PCAP_STATUSTOSTR) check_function_exists(pcap_create HAVE_PCAP_CREATE) endif(HAVE_PCAP_STATUSTOSTR) if(HAVE_PCAP_CREATE) # # OK, do we have pcap_set_tstamp_type? If so, assume we have # pcap_list_tstamp_types and pcap_free_tstamp_types as well. # check_function_exists(pcap_set_tstamp_type HAVE_PCAP_SET_TSTAMP_TYPE) # # And do we have pcap_set_tstamp_precision? If so, we assume # we also have pcap_open_offline_with_tstamp_precision. # check_function_exists(pcap_set_tstamp_precision HAVE_PCAP_SET_TSTAMP_PRECISION) endif(HAVE_PCAP_CREATE) # # Check for a miscellaneous collection of functions which we use # if we have them. # check_function_exists(pcap_findalldevs HAVE_PCAP_FINDALLDEVS) if(HAVE_PCAP_FINDALLDEVS) # # Check for libpcap having pcap_findalldevs() but the pcap.h header # not having pcap_if_t; some versions of Mac OS X shipped with pcap.h # from 0.6 and libpcap 0.8, so that libpcap had pcap_findalldevs but # pcap.h didn't have pcap_if_t. # cmake_push_check_state() set(CMAKE_REQUIRED_INCLUDES ${PCAP_INCLUDE_DIRS}) set(CMAKE_EXTRA_INCLUDE_FILES pcap.h) check_type_size(pcap_if_t PCAP_IF_T) cmake_pop_check_state() endif(HAVE_PCAP_FINDALLDEVS) check_function_exists(pcap_dump_flush HAVE_PCAP_DUMP_FLUSH) check_function_exists(pcap_lib_version HAVE_PCAP_LIB_VERSION) if(NOT HAVE_PCAP_LIB_VERSION) # Check for the pcap_version string variable and set HAVE_PCAP_VERSION endif(NOT HAVE_PCAP_LIB_VERSION) check_function_exists(pcap_setdirection HAVE_PCAP_SETDIRECTION) check_function_exists(pcap_set_immediate_mode HAVE_PCAP_SET_IMMEDIATE_MODE) check_function_exists(pcap_dump_ftell64 HAVE_PCAP_DUMP_FTELL64) check_function_exists(pcap_open HAVE_PCAP_OPEN) check_function_exists(pcap_findalldevs_ex HAVE_PCAP_FINDALLDEVS_EX) # # On Windows, check for pcap_wsockinit(); if we don't have it, check for # wsockinit(). # if(WIN32) check_function_exists(pcap_wsockinit HAVE_PCAP_WSOCKINIT) if(NOT HAVE_PCAP_WSOCKINIT) check_function_exists(wsockinit HAVE_WSOCKINIT) endif(NOT HAVE_PCAP_WSOCKINIT) endif(WIN32) # # Check for special debugging functions # check_function_exists(pcap_set_parser_debug HAVE_PCAP_SET_PARSER_DEBUG) if(NOT HAVE_PCAP_SET_PARSER_DEBUG) # Check whether libpcap defines pcap_debug or yydebug check_variable_exists(pcap_debug HAVE_PCAP_DEBUG) if(NOT HAVE_PCAP_DEBUG) check_variable_exists(yydebug HAVE_YYDEBUG) endif(NOT HAVE_PCAP_DEBUG) endif(NOT HAVE_PCAP_SET_PARSER_DEBUG) check_function_exists(pcap_set_optimizer_debug HAVE_PCAP_SET_OPTIMIZER_DEBUG) check_function_exists(bpf_dump HAVE_BPF_DUMP) cmake_pop_check_state() # # We have libpcap. # include_directories(SYSTEM ${PCAP_INCLUDE_DIRS}) set(TCPDUMP_LINK_LIBRARIES ${PCAP_LIBRARIES} ${TCPDUMP_LINK_LIBRARIES}) # # Optional libraries. # # # libsmi. # if(WITH_SMI) find_package(SMI) if(SMI_FOUND) include_directories(SYSTEM ${SMI_INCLUDE_DIRS}) set(TCPDUMP_LINK_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} ${SMI_LIBRARIES}) set(USE_LIBSMI ON) endif(SMI_FOUND) endif(WITH_SMI) # # OpenSSL/libressl libcrypto. # if(WITH_CRYPTO) find_package(CRYPTO) if(CRYPTO_FOUND) # # Check for some headers and functions. # check_include_file(openssl/evp.h HAVE_OPENSSL_EVP_H) # # 1) do we have EVP_CIPHER_CTX_new? # If so, we use it to allocate an EVP_CIPHER_CTX, as # EVP_CIPHER_CTX may be opaque; otherwise, we allocate # it ourselves. # cmake_push_check_state() set(CMAKE_REQUIRED_LIBRARIES "${CRYPTO_LIBRARIES}") check_function_exists(EVP_CIPHER_CTX_new HAVE_EVP_CIPHER_CTX_NEW) # # 2) do we have EVP_DecryptInit_ex()? # If so, we use it, because we need to be able to make two # "initialize the cipher" calls, one with the cipher and key, # and one with the IV, and, as of OpenSSL 1.1, You Can't Do That # with EVP_DecryptInit(), because a call to EVP_DecryptInit() will # unconditionally clear the context, and if you don't supply a # cipher, it'll clear the cipher, rendering the context unusable # and causing a crash. # check_function_exists(EVP_DecryptInit_ex HAVE_EVP_DECRYPTINIT_EX) cmake_pop_check_state() # # We have libcrypto. # include_directories(SYSTEM ${CRYPTO_INCLUDE_DIRS}) set(TCPDUMP_LINK_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} ${CRYPTO_LIBRARIES}) set(HAVE_LIBCRYPTO ON) endif(CRYPTO_FOUND) endif(WITH_CRYPTO) # # Capsicum sandboxing. # Some of this is in the system library, some of it is in other libraries. # if(WITH_CAPSICUM) check_include_files("sys/capsicum.h" HAVE_SYS_CAPSICUM_H) if(HAVE_SYS_CAPSICUM_H) check_function_exists(cap_enter HAVE_CAP_ENTER) check_function_exists(cap_rights_limit HAVE_CAP_RIGHTS_LIMIT) check_function_exists(cap_ioctls_limit HAVE_CAP_IOCTLS_LIMIT) check_function_exists(openat HAVE_OPENAT) if(HAVE_CAP_ENTER AND HAVE_CAP_RIGHTS_LIMIT AND HAVE_CAP_IOCTLS_LIMIT AND HAVE_OPENAT) # # OK, we have the functions we need to support Capsicum. # set(HAVE_CAPSICUM TRUE) # # OK, can we use Casper? # check_library_exists(casper cap_init "" HAVE_CAP_INIT) if(HAVE_CAP_INIT) cmake_push_check_state() set(CMAKE_REQUIRED_LIBRARIES casper) check_library_exists(cap_dns cap_gethostbyaddr "" HAVE_CAP_GETHOSTBYADDR) cmake_pop_check_state() if(HAVE_CAP_GETHOSTBYADDR) set(HAVE_CASPER TRUE) set(TCPDUMP_LINK_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} casper cap_dns) endif(HAVE_CAP_GETHOSTBYADDR) endif(HAVE_CAP_INIT) endif(HAVE_CAP_ENTER AND HAVE_CAP_RIGHTS_LIMIT AND HAVE_CAP_IOCTLS_LIMIT AND HAVE_OPENAT) endif(HAVE_SYS_CAPSICUM_H) endif(WITH_CAPSICUM) # # libcap-ng. # if(WITH_CAP_NG) check_include_file(cap-ng.h HAVE_CAP_NG_H) check_library_exists(cap-ng capng_change_id "" HAVE_LIBCAP_NG) if(HAVE_LIBCAP_NG) set(TCPDUMP_LINK_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} cap-ng) endif(HAVE_LIBCAP_NG) endif(WITH_CAP_NG) ################################################################### # Warning options ################################################################### # # Check and add warning options if we have a .devel file. # if(EXISTS ${CMAKE_SOURCE_DIR}/.devel OR EXISTS ${CMAKE_BINARY_DIR}/.devel) # # Warning options. # if(MSVC AND NOT ${CMAKE_C_COMPILER} MATCHES "clang*") # # MSVC, with Microsoft's front end and code generator. # "MSVC" is also set for Microsoft's compiler with a Clang # front end and their code generator ("Clang/C2"), so we # check for clang.exe and treat that differently. # check_and_add_compiler_option(-Wall) # # Disable some pointless warnings that /Wall turns on. # # Unfortunately, MSVC does not appear to have an equivalent # to "__attribute__((unused))" to mark a particular function # parameter as being known to be unused, so that the compiler # won't warn about it (for example, the function might have # that parameter because a pointer to it is being used, and # the signature of that function includes that parameter). # C++ lets you give a parameter a type but no name, but C # doesn't have that. # check_and_add_compiler_option(-wd4100) # # In theory, we care whether somebody uses f() rather than # f(void) to declare a function with no arguments, but, in # practice, there are places in the Windows header files # that appear to do that, so we squelch that warning. # check_and_add_compiler_option(-wd4255) # # Windows FD_SET() generates this, so we suppress it. # check_and_add_compiler_option(-wd4548) # # Perhaps testing something #defined to be 0 with #ifdef is an # error, and it should be tested with #if, but perhaps it's # not, and Microsoft does that in its headers, so we squelch # that warning. # check_and_add_compiler_option(-wd4574) # # The Windows headers also test not-defined values in #if, so # we don't want warnings about that, either. # check_and_add_compiler_option(-wd4668) # # We do *not* care whether some function is, or isn't, going to be # expanded inline. # check_and_add_compiler_option(-wd4710) check_and_add_compiler_option(-wd4711) # # We do *not* care whether we're adding padding bytes after # structure members. # check_and_add_compiler_option(-wd4820) # # We do *not* care about every single place the compiler would # have inserted Spectre mitigation if only we had told it to # do so with /Qspectre. I guess the theory is that it's seeing # bounds checks that would prevent out-of-bounds loads and that # those out-of-bounds loads could be done speculatively and that # the Spectre attack could detect the value of the out-of-bounds # data *if* it's within our address space, but unless I'm # missing something I don't see that as being any form of # security hole. # # XXX - add /Qspectre if that is really worth doing. # check_and_add_compiler_option(-wd5045) # # We do *not* care whether a structure had padding added at # the end because of __declspec(align) - *we* don't use # __declspec(align), because the only structures whose layout # we precisely specify are those that get overlayed on packet # data, and in those every element is an array of octets so # that we have full control over the size and aligmnet, and, # apparently, jmp_buf has such a declaration on x86, meaning # that everything that includes netdissect.h, i.e. almost every # file in tcpdump, gets a warning. # check_and_add_compiler_option(-wd4324) else() # # Other compilers, including MSVC with a Clang front end and # Microsoft's code generator. We currently treat them as if # they might support GCC-style -W options. # check_and_add_compiler_option(-W) check_and_add_compiler_option(-Wall) check_and_add_compiler_option(-Wassign-enum) check_and_add_compiler_option(-Wcast-qual) check_and_add_compiler_option(-Wmissing-prototypes) check_and_add_compiler_option(-Wmissing-variable-declarations) check_and_add_compiler_option(-Wold-style-definition) check_and_add_compiler_option(-Wpedantic) check_and_add_compiler_option(-Wpointer-arith) check_and_add_compiler_option(-Wpointer-sign) check_and_add_compiler_option(-Wshadow) check_and_add_compiler_option(-Wsign-compare) check_and_add_compiler_option(-Wstrict-prototypes) check_and_add_compiler_option(-Wunreachable-code-return) check_and_add_compiler_option(-Wused-but-marked-unused) check_and_add_compiler_option(-Wwrite-strings) endif() endif() ###################################### # Input files ###################################### if(ENABLE_SMB) # # We allow the SMB dissector to be omitted. # set(LOCALSRC ${LOCALSRC} print-smb.c smbutil.c) endif(ENABLE_SMB) set(NETDISSECT_SOURCE_LIST_C addrtoname.c addrtostr.c af.c ascii_strcasecmp.c checksum.c cpack.c gmpls.c in_cksum.c ipproto.c l2vpn.c machdep.c netdissect.c netdissect-alloc.c nlpid.c oui.c ntp.c parsenfsfh.c print.c print-802_11.c print-802_15_4.c print-ah.c print-ahcp.c print-aodv.c print-aoe.c print-ap1394.c print-arcnet.c print-arista.c print-arp.c print-ascii.c print-atalk.c print-atm.c print-babel.c print-bcm-li.c print-beep.c print-bfd.c print-bgp.c print-bootp.c print-brcmtag.c print-bt.c print-calm-fast.c print-carp.c print-cdp.c print-cfm.c print-chdlc.c print-cip.c print-cnfp.c print-dccp.c print-decnet.c print-dhcp6.c print-domain.c print-dsa.c print-dtp.c print-dvmrp.c print-eap.c print-egp.c print-eigrp.c print-enc.c print-esp.c print-ether.c print-fddi.c print-forces.c print-fr.c print-frag6.c print-ftp.c print-geneve.c print-geonet.c print-gre.c print-hncp.c print-hsrp.c print-http.c print-icmp.c print-icmp6.c print-igmp.c print-igrp.c print-ip-demux.c print-ip.c print-ip6.c print-ip6opts.c print-ipcomp.c print-ipfc.c print-ipnet.c print-ipoib.c print-ipx.c print-isakmp.c print-isoclns.c print-juniper.c print-krb.c print-l2tp.c print-lane.c print-ldp.c print-lisp.c print-llc.c print-lldp.c print-lmp.c print-loopback.c print-lspping.c print-lwapp.c print-lwres.c print-m3ua.c print-macsec.c print-mobile.c print-mobility.c print-mpcp.c print-mpls.c print-mptcp.c print-msdp.c print-msnlb.c print-nflog.c print-nfs.c print-nsh.c print-ntp.c print-null.c print-olsr.c print-openflow-1.0.c print-openflow-1.3.c print-openflow.c print-ospf.c print-ospf6.c print-otv.c print-pgm.c print-pim.c print-pktap.c print-ppi.c print-ppp.c print-pppoe.c print-pptp.c print-ptp.c print-radius.c print-raw.c print-resp.c print-rip.c print-ripng.c print-rpki-rtr.c print-rrcp.c print-rsvp.c print-rt6.c print-rtsp.c print-rx.c print-sctp.c print-sflow.c print-sip.c print-sl.c print-sll.c print-slow.c print-smtp.c print-snmp.c print-someip.c print-ssh.c print-stp.c print-sunatm.c print-sunrpc.c print-symantec.c print-syslog.c print-tcp.c print-telnet.c print-tftp.c print-timed.c print-tipc.c print-token.c print-udld.c print-udp.c print-unsupported.c print-usb.c print-vjc.c print-vqp.c print-vrrp.c print-vsock.c print-vtp.c print-vxlan-gpe.c print-vxlan.c print-wb.c print-zep.c print-zephyr.c print-zeromq.c ${LOCALSRC} signature.c strtoaddr.c util-print.c ) # # Replace missing functions # foreach(FUNC strlcat strlcpy strdup strsep getservent getopt_long) string(TOUPPER ${FUNC} FUNC_UPPERCASE) set(HAVE_FUNC_UPPERCASE HAVE_${FUNC_UPPERCASE}) if(NOT ${HAVE_FUNC_UPPERCASE}) set(NETDISSECT_SOURCE_LIST_C ${NETDISSECT_SOURCE_LIST_C} missing/${FUNC}.c) endif() endforeach() add_library(netdissect STATIC ${NETDISSECT_SOURCE_LIST_C} ) if(NOT C_ADDITIONAL_FLAGS STREQUAL "") set_target_properties(netdissect PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS}) endif() set(TCPDUMP_SOURCE_LIST_C fptype.c tcpdump.c) if(NOT HAVE_BPF_DUMP) set(TCPDUMP_SOURCE_LIST_C ${TCPDUMP_SOURCE_LIST_C} bpf_dump.c) endif(NOT HAVE_BPF_DUMP) if(NOT HAVE_PCAP_DUMP_FTELL) set(TCPDUMP_SOURCE_LIST_C ${TCPDUMP_SOURCE_LIST_C} missing/pcap_dump_ftell.c) endif(NOT HAVE_PCAP_DUMP_FTELL) if(NOT HAVE_PCAP_LIST_DATALINKS) set(TCPDUMP_SOURCE_LIST_C ${TCPDUMP_SOURCE_LIST_C} missing/datalinks.c) endif(NOT HAVE_PCAP_LIST_DATALINKS) if((NOT HAVE_PCAP_DATALINK_NAME_TO_VAL) OR (NOT HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION)) set(TCPDUMP_SOURCE_LIST_C ${TCPDUMP_SOURCE_LIST_C} missing/dlnames.c) endif((NOT HAVE_PCAP_DATALINK_NAME_TO_VAL) OR (NOT HAVE_PCAP_DATALINK_VAL_TO_DESCRIPTION)) set(PROJECT_SOURCE_LIST_C ${NETDISSECT_SOURCE_LIST_C} ${TCPDUMP_SOURCE_LIST_C}) file(GLOB PROJECT_SOURCE_LIST_H *.h ) source_group("Source Files" FILES ${PROJECT_SOURCE_LIST_C}) source_group("Header Files" FILES ${PROJECT_SOURCE_LIST_H}) ###################################### # Register targets ###################################### add_executable(tcpdump ${TCPDUMP_SOURCE_LIST_C}) if(NOT C_ADDITIONAL_FLAGS STREQUAL "") set_target_properties(tcpdump PROPERTIES COMPILE_FLAGS ${C_ADDITIONAL_FLAGS}) endif() target_link_libraries(tcpdump netdissect ${TCPDUMP_LINK_LIBRARIES}) ###################################### # Write out the config.h file ###################################### configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmakeconfig.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) ###################################### # Install tcpdump and man pages ###################################### # # "Define GNU standard installation directories", which actually # are also defined, to some degree, by autotools, and at least # some of which are general UN*X conventions. # include(GNUInstallDirs) set(MAN1_EXPAND tcpdump.1.in) if(WIN32) # XXX TODO where to install on Windows? else(WIN32) install(TARGETS tcpdump DESTINATION bin) endif(WIN32) # On UN*X, and on Windows when not using MSVC, process man pages and # arrange that they be installed. if(NOT MSVC) # # Man pages. # # For each section of the manual for which we have man pages # that require macro expansion, do the expansion. # set(MAN1 "") foreach(TEMPLATE_MANPAGE ${MAN1_EXPAND}) string(REPLACE ".in" "" MANPAGE ${TEMPLATE_MANPAGE}) configure_file(${CMAKE_SOURCE_DIR}/${TEMPLATE_MANPAGE} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE} @ONLY) set(MAN1 ${MAN1} ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE}) endforeach(TEMPLATE_MANPAGE) install(FILES ${MAN1} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) endif(NOT MSVC) # uninstall target configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY) add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) # # Tcpdump tests # We try to find the Perl interpreter and, if we do, we have the check # rule run tests/TESTrun with it, because just trying to run the TESTrun # script as a command won't work on Windows. # find_program(PERL perl) if(PERL) message(STATUS "Found perl at ${PERL}") add_custom_target(check COMMAND ${PERL} ${CMAKE_SOURCE_DIR}/tests/TESTrun) else() message(STATUS "Didn't find perl") endif() tcpdump-4.99.1/print-igmp.c0000644000026300017510000002075614057477727013705 0ustar mcrmcr/* * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996 * 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. */ /* \summary: Internet Group Management Protocol (IGMP) printer */ /* * specification: * * RFC 2236 for IGMPv2 * RFC 3376 for IGMPv3 * draft-asaeda-mboned-mtrace-v2 for the mtrace message */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" #include "addrtoname.h" #include "extract.h" #ifndef IN_CLASSD #define IN_CLASSD(i) (((int32_t)(i) & 0xf0000000) == 0xe0000000) #endif /* (following from ipmulti/mrouted/prune.h) */ /* * The packet format for a traceroute request. */ struct tr_query { nd_uint32_t tr_src; /* traceroute source */ nd_uint32_t tr_dst; /* traceroute destination */ nd_uint32_t tr_raddr; /* traceroute response address */ nd_uint8_t tr_rttl; /* response ttl */ nd_uint24_t tr_qid; /* qid */ }; /* * Traceroute response format. A traceroute response has a tr_query at the * beginning, followed by one tr_resp for each hop taken. */ struct tr_resp { nd_uint32_t tr_qarr; /* query arrival time */ nd_uint32_t tr_inaddr; /* incoming interface address */ nd_uint32_t tr_outaddr; /* outgoing interface address */ nd_uint32_t tr_rmtaddr; /* parent address in source tree */ nd_uint32_t tr_vifin; /* input packet count on interface */ nd_uint32_t tr_vifout; /* output packet count on interface */ nd_uint32_t tr_pktcnt; /* total incoming packets for src-grp */ nd_uint8_t tr_rproto; /* routing proto deployed on router */ nd_uint8_t tr_fttl; /* ttl required to forward on outvif */ nd_uint8_t tr_smask; /* subnet mask for src addr */ nd_uint8_t tr_rflags; /* forwarding error codes */ }; /* defs within mtrace */ #define TR_QUERY 1 #define TR_RESP 2 /* fields for tr_rflags (forwarding error codes) */ #define TR_NO_ERR 0 #define TR_WRONG_IF 1 #define TR_PRUNED 2 #define TR_OPRUNED 3 #define TR_SCOPED 4 #define TR_NO_RTE 5 #define TR_NO_FWD 7 #define TR_NO_SPACE 0x81 #define TR_OLD_ROUTER 0x82 /* fields for tr_rproto (routing protocol) */ #define TR_PROTO_DVMRP 1 #define TR_PROTO_MOSPF 2 #define TR_PROTO_PIM 3 #define TR_PROTO_CBT 4 /* igmpv3 report types */ static const struct tok igmpv3report2str[] = { { 1, "is_in" }, { 2, "is_ex" }, { 3, "to_in" }, { 4, "to_ex" }, { 5, "allow" }, { 6, "block" }, { 0, NULL } }; static void print_mtrace(netdissect_options *ndo, const char *typename, const u_char *bp, u_int len) { const struct tr_query *tr = (const struct tr_query *)(bp + 8); if (len < 8 + sizeof (struct tr_query)) { ND_PRINT(" [invalid len %u]", len); return; } ND_PRINT("%s %u: %s to %s reply-to %s", typename, GET_BE_U_3(tr->tr_qid), GET_IPADDR_STRING(tr->tr_src), GET_IPADDR_STRING(tr->tr_dst), GET_IPADDR_STRING(tr->tr_raddr)); if (IN_CLASSD(GET_BE_U_4(tr->tr_raddr))) ND_PRINT(" with-ttl %u", GET_U_1(tr->tr_rttl)); } static void print_igmpv3_report(netdissect_options *ndo, const u_char *bp, u_int len) { u_int group, nsrcs, ngroups; u_int i, j; /* Minimum len is 16, and should be a multiple of 4 */ if (len < 16 || len & 0x03) { ND_PRINT(" [invalid len %u]", len); return; } ngroups = GET_BE_U_2(bp + 6); ND_PRINT(", %u group record(s)", ngroups); if (ndo->ndo_vflag > 0) { /* Print the group records */ group = 8; for (i=0; indo_vflag == 1) ND_PRINT(", %u source(s)", nsrcs); else { /* Print the sources */ ND_PRINT(" {"); for (j=0; j> 4) + 3); } if (mrc != 100) { ND_PRINT(" [max resp time "); if (mrt < 600) { ND_PRINT("%.1fs", mrt * 0.1); } else { unsigned_relts_print(ndo, mrt / 10); } ND_PRINT("]"); } if (GET_BE_U_4(bp + 4) == 0) return; ND_PRINT(" [gaddr %s", GET_IPADDR_STRING(bp + 4)); nsrcs = GET_BE_U_2(bp + 10); if (nsrcs > 0) { if (len < 12 + (nsrcs << 2)) ND_PRINT(" [invalid number of sources]"); else if (ndo->ndo_vflag > 1) { ND_PRINT(" {"); for (i=0; indo_protocol = "igmp"; if (ndo->ndo_qflag) { ND_PRINT("igmp"); return; } switch (GET_U_1(bp)) { case 0x11: ND_PRINT("igmp query"); if (len >= 12) print_igmpv3_query(ndo, bp, len); else { if (GET_U_1(bp + 1)) { ND_PRINT(" v2"); if (GET_U_1(bp + 1) != 100) ND_PRINT(" [max resp time %u]", GET_U_1(bp + 1)); } else ND_PRINT(" v1"); if (GET_BE_U_4(bp + 4)) ND_PRINT(" [gaddr %s]", GET_IPADDR_STRING(bp + 4)); if (len != 8) ND_PRINT(" [len %u]", len); } break; case 0x12: ND_PRINT("igmp v1 report %s", GET_IPADDR_STRING(bp + 4)); if (len != 8) ND_PRINT(" [len %u]", len); break; case 0x16: ND_PRINT("igmp v2 report %s", GET_IPADDR_STRING(bp + 4)); break; case 0x22: ND_PRINT("igmp v3 report"); print_igmpv3_report(ndo, bp, len); break; case 0x17: ND_PRINT("igmp leave %s", GET_IPADDR_STRING(bp + 4)); break; case 0x13: ND_PRINT("igmp dvmrp"); if (len < 8) ND_PRINT(" [len %u]", len); else dvmrp_print(ndo, bp, len); break; case 0x14: ND_PRINT("igmp pimv1"); pimv1_print(ndo, bp, len); break; case 0x1e: print_mtrace(ndo, "mresp", bp, len); break; case 0x1f: print_mtrace(ndo, "mtrace", bp, len); break; default: ND_PRINT("igmp-%u", GET_U_1(bp)); break; } if (ndo->ndo_vflag && len >= 4 && ND_TTEST_LEN(bp, len)) { /* Check the IGMP checksum */ vec[0].ptr = bp; vec[0].len = len; if (in_cksum(vec, 1)) ND_PRINT(" bad igmp cksum %x!", GET_BE_U_2(bp + 2)); } } tcpdump-4.99.1/print-timed.c0000644000026300017510000001215214057477727014042 0ustar mcrmcr/* * Copyright (c) 2000 Ben Smithurst * 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. */ /* \summary: Berkeley UNIX Time Synchronization Protocol */ /* specification: https://docs.freebsd.org/44doc/smm/12.timed/paper.pdf */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" #include "extract.h" struct tsp_timeval { nd_int32_t tv_sec; nd_int32_t tv_usec; }; struct tsp { nd_uint8_t tsp_type; nd_uint8_t tsp_vers; nd_uint16_t tsp_seq; union { struct tsp_timeval tspu_time; nd_int8_t tspu_hopcnt; } tsp_u; nd_byte tsp_name[256]; /* null-terminated string up to 256 */ }; #define tsp_time tsp_u.tspu_time #define tsp_hopcnt tsp_u.tspu_hopcnt /* * Command types. */ #define TSP_ANY 0 /* match any types */ #define TSP_ADJTIME 1 /* send adjtime */ #define TSP_ACK 2 /* generic acknowledgement */ #define TSP_MASTERREQ 3 /* ask for master's name */ #define TSP_MASTERACK 4 /* acknowledge master request */ #define TSP_SETTIME 5 /* send network time */ #define TSP_MASTERUP 6 /* inform slaves that master is up */ #define TSP_SLAVEUP 7 /* slave is up but not polled */ #define TSP_ELECTION 8 /* advance candidature for master */ #define TSP_ACCEPT 9 /* support candidature of master */ #define TSP_REFUSE 10 /* reject candidature of master */ #define TSP_CONFLICT 11 /* two or more masters present */ #define TSP_RESOLVE 12 /* masters' conflict resolution */ #define TSP_QUIT 13 /* reject candidature if master is up */ #define TSP_DATE 14 /* reset the time (date command) */ #define TSP_DATEREQ 15 /* remote request to reset the time */ #define TSP_DATEACK 16 /* acknowledge time setting */ #define TSP_TRACEON 17 /* turn tracing on */ #define TSP_TRACEOFF 18 /* turn tracing off */ #define TSP_MSITE 19 /* find out master's site */ #define TSP_MSITEREQ 20 /* remote master's site request */ #define TSP_TEST 21 /* for testing election algo */ #define TSP_SETDATE 22 /* New from date command */ #define TSP_SETDATEREQ 23 /* New remote for above */ #define TSP_LOOP 24 /* loop detection packet */ static const struct tok tsptype_str[] = { { TSP_ANY, "TSP_ANY" }, { TSP_ADJTIME, "TSP_ADJTIME" }, { TSP_ACK, "TSP_ACK" }, { TSP_MASTERREQ, "TSP_MASTERREQ" }, { TSP_MASTERACK, "TSP_MASTERACK" }, { TSP_SETTIME, "TSP_SETTIME" }, { TSP_MASTERUP, "TSP_MASTERUP" }, { TSP_SLAVEUP, "TSP_SLAVEUP" }, { TSP_ELECTION, "TSP_ELECTION" }, { TSP_ACCEPT, "TSP_ACCEPT" }, { TSP_REFUSE, "TSP_REFUSE" }, { TSP_CONFLICT, "TSP_CONFLICT" }, { TSP_RESOLVE, "TSP_RESOLVE" }, { TSP_QUIT, "TSP_QUIT" }, { TSP_DATE, "TSP_DATE" }, { TSP_DATEREQ, "TSP_DATEREQ" }, { TSP_DATEACK, "TSP_DATEACK" }, { TSP_TRACEON, "TSP_TRACEON" }, { TSP_TRACEOFF, "TSP_TRACEOFF" }, { TSP_MSITE, "TSP_MSITE" }, { TSP_MSITEREQ, "TSP_MSITEREQ" }, { TSP_TEST, "TSP_TEST" }, { TSP_SETDATE, "TSP_SETDATE" }, { TSP_SETDATEREQ, "TSP_SETDATEREQ" }, { TSP_LOOP, "TSP_LOOP" }, { 0, NULL } }; void timed_print(netdissect_options *ndo, const u_char *bp) { const struct tsp *tsp = (const struct tsp *)bp; uint8_t tsp_type; int sec, usec; ndo->ndo_protocol = "timed"; tsp_type = GET_U_1(tsp->tsp_type); ND_PRINT("%s", tok2str(tsptype_str, "(tsp_type %#x)", tsp_type)); ND_PRINT(" vers %u", GET_U_1(tsp->tsp_vers)); ND_PRINT(" seq %u", GET_BE_U_2(tsp->tsp_seq)); switch (tsp_type) { case TSP_LOOP: ND_PRINT(" hopcnt %u", GET_U_1(tsp->tsp_hopcnt)); break; case TSP_SETTIME: case TSP_ADJTIME: case TSP_SETDATE: case TSP_SETDATEREQ: sec = GET_BE_S_4(tsp->tsp_time.tv_sec); usec = GET_BE_S_4(tsp->tsp_time.tv_usec); /* XXX The comparison below is always false? */ if (usec < 0) /* invalid, skip the rest of the packet */ return; ND_PRINT(" time "); if (sec < 0 && usec != 0) { sec++; if (sec == 0) ND_PRINT("-"); usec = 1000000 - usec; } ND_PRINT("%d.%06d", sec, usec); break; } ND_PRINT(" name "); nd_printjnp(ndo, tsp->tsp_name, sizeof(tsp->tsp_name)); } tcpdump-4.99.1/print-sctp.c0000644000026300017510000005316514057477734013720 0ustar mcrmcr/* Copyright (c) 2001 NETLAB, Temple University * Copyright (c) 2001 Protocol Engineering Lab, University of Delaware * * Jerry Heinz * John Fiore * Armando L. Caro Jr. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of the University nor of the Laboratory may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ /* \summary: Stream Control Transmission Protocol (SCTP) printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" #include "addrtoname.h" #include "extract.h" #include "ip.h" #include "ip6.h" /* Definitions from: * * SCTP reference Implementation Copyright (C) 1999 Cisco And Motorola * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * 3. Neither the name of Cisco nor of Motorola may be used * to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * This file is part of the SCTP reference Implementation * * * Please send any bug reports or fixes you make to one of the following email * addresses: * * rstewar1@email.mot.com * kmorneau@cisco.com * qxie1@email.mot.com * * Any bugs reported given to us we will try to fix... any fixes shared will * be incorporated into the next SCTP release. */ /* The valid defines for all message * types know to SCTP. 0 is reserved */ #define SCTP_DATA 0x00 #define SCTP_INITIATION 0x01 #define SCTP_INITIATION_ACK 0x02 #define SCTP_SELECTIVE_ACK 0x03 #define SCTP_HEARTBEAT_REQUEST 0x04 #define SCTP_HEARTBEAT_ACK 0x05 #define SCTP_ABORT_ASSOCIATION 0x06 #define SCTP_SHUTDOWN 0x07 #define SCTP_SHUTDOWN_ACK 0x08 #define SCTP_OPERATION_ERR 0x09 #define SCTP_COOKIE_ECHO 0x0a #define SCTP_COOKIE_ACK 0x0b #define SCTP_ECN_ECHO 0x0c #define SCTP_ECN_CWR 0x0d #define SCTP_SHUTDOWN_COMPLETE 0x0e #define SCTP_FORWARD_CUM_TSN 0xc0 #define SCTP_RELIABLE_CNTL 0xc1 #define SCTP_RELIABLE_CNTL_ACK 0xc2 static const struct tok sctp_chunkid_str[] = { { SCTP_DATA, "DATA" }, { SCTP_INITIATION, "INIT" }, { SCTP_INITIATION_ACK, "INIT ACK" }, { SCTP_SELECTIVE_ACK, "SACK" }, { SCTP_HEARTBEAT_REQUEST, "HB REQ" }, { SCTP_HEARTBEAT_ACK, "HB ACK" }, { SCTP_ABORT_ASSOCIATION, "ABORT" }, { SCTP_SHUTDOWN, "SHUTDOWN" }, { SCTP_SHUTDOWN_ACK, "SHUTDOWN ACK" }, { SCTP_OPERATION_ERR, "OP ERR" }, { SCTP_COOKIE_ECHO, "COOKIE ECHO" }, { SCTP_COOKIE_ACK, "COOKIE ACK" }, { SCTP_ECN_ECHO, "ECN ECHO" }, { SCTP_ECN_CWR, "ECN CWR" }, { SCTP_SHUTDOWN_COMPLETE, "SHUTDOWN COMPLETE" }, { SCTP_FORWARD_CUM_TSN, "FOR CUM TSN" }, { SCTP_RELIABLE_CNTL, "REL CTRL" }, { SCTP_RELIABLE_CNTL_ACK, "REL CTRL ACK" }, { 0, NULL } }; /* Data Chuck Specific Flags */ #define SCTP_DATA_FRAG_MASK 0x03 #define SCTP_DATA_MIDDLE_FRAG 0x00 #define SCTP_DATA_LAST_FRAG 0x01 #define SCTP_DATA_FIRST_FRAG 0x02 #define SCTP_DATA_NOT_FRAG 0x03 #define SCTP_DATA_UNORDERED 0x04 #define SCTP_ADDRMAX 60 #define CHAN_HP 6704 #define CHAN_MP 6705 #define CHAN_LP 6706 /* the sctp common header */ struct sctpHeader{ nd_uint16_t source; nd_uint16_t destination; nd_uint32_t verificationTag; nd_uint32_t adler32; }; /* various descriptor parsers */ struct sctpChunkDesc{ nd_uint8_t chunkID; nd_uint8_t chunkFlg; nd_uint16_t chunkLength; }; struct sctpParamDesc{ nd_uint16_t paramType; nd_uint16_t paramLength; }; struct sctpRelChunkDesc{ struct sctpChunkDesc chk; nd_uint32_t serialNumber; }; struct sctpVendorSpecificParam { struct sctpParamDesc p; /* type must be 0xfffe */ nd_uint32_t vendorId; /* vendor ID from RFC 1700 */ nd_uint16_t vendorSpecificType; nd_uint16_t vendorSpecificLen; }; /* Structures for the control parts */ /* Sctp association init request/ack */ /* this is used for init ack, too */ struct sctpInitiation{ nd_uint32_t initTag; /* tag of mine */ nd_uint32_t rcvWindowCredit; /* rwnd */ nd_uint16_t NumPreopenStreams; /* OS */ nd_uint16_t MaxInboundStreams; /* MIS */ nd_uint32_t initialTSN; /* optional param's follow in sctpParamDesc form */ }; struct sctpV4IpAddress{ struct sctpParamDesc p; /* type is set to SCTP_IPV4_PARAM_TYPE, len=10 */ nd_ipv4 ipAddress; }; struct sctpV6IpAddress{ struct sctpParamDesc p; /* type is set to SCTP_IPV6_PARAM_TYPE, len=22 */ nd_ipv6 ipAddress; }; struct sctpDNSName{ struct sctpParamDesc param; nd_byte name[1]; }; struct sctpCookiePreserve{ struct sctpParamDesc p; /* type is set to SCTP_COOKIE_PRESERVE, len=8 */ nd_uint32_t extraTime; }; struct sctpTimeStamp{ nd_uint32_t ts_sec; nd_uint32_t ts_usec; }; /* this guy is for use when * I have a initiate message gloming the * things together. */ struct sctpUnifiedInit{ struct sctpChunkDesc uh; struct sctpInitiation initm; }; struct sctpSendableInit{ struct sctpHeader mh; struct sctpUnifiedInit msg; }; /* Selective Acknowledgement * has the following structure with * a optional amount of trailing int's * on the last part (based on the numberOfDesc * field). */ struct sctpSelectiveAck{ nd_uint32_t highestConseqTSN; nd_uint32_t updatedRwnd; nd_uint16_t numberOfdesc; nd_uint16_t numDupTsns; }; struct sctpSelectiveFrag{ nd_uint16_t fragmentStart; nd_uint16_t fragmentEnd; }; struct sctpUnifiedSack{ struct sctpChunkDesc uh; struct sctpSelectiveAck sack; }; /* for the abort and shutdown ACK * we must carry the init tag in the common header. Just the * common header is all that is needed with a chunk descriptor. */ struct sctpUnifiedAbort{ struct sctpChunkDesc uh; }; struct sctpUnifiedAbortLight{ struct sctpHeader mh; struct sctpChunkDesc uh; }; struct sctpUnifiedAbortHeavy{ struct sctpHeader mh; struct sctpChunkDesc uh; nd_uint16_t causeCode; nd_uint16_t causeLen; }; /* For the graceful shutdown we must carry * the tag (in common header) and the highest consequitive acking value */ struct sctpShutdown { nd_uint32_t TSN_Seen; }; struct sctpUnifiedShutdown{ struct sctpChunkDesc uh; struct sctpShutdown shut; }; /* in the unified message we add the trailing * stream id since it is the only message * that is defined as a operation error. */ struct sctpOpErrorCause{ nd_uint16_t cause; nd_uint16_t causeLen; }; struct sctpUnifiedOpError{ struct sctpChunkDesc uh; struct sctpOpErrorCause c; }; struct sctpUnifiedStreamError{ struct sctpHeader mh; struct sctpChunkDesc uh; struct sctpOpErrorCause c; nd_uint16_t strmNum; nd_uint16_t reserved; }; struct staleCookieMsg{ struct sctpHeader mh; struct sctpChunkDesc uh; struct sctpOpErrorCause c; nd_uint32_t moretime; }; /* the following is used in all sends * where nothing is needed except the * chunk/type i.e. shutdownAck Abort */ struct sctpUnifiedSingleMsg{ struct sctpHeader mh; struct sctpChunkDesc uh; }; struct sctpDataPart{ nd_uint32_t TSN; nd_uint16_t streamId; nd_uint16_t sequence; nd_uint32_t payloadtype; }; struct sctpUnifiedDatagram{ struct sctpChunkDesc uh; struct sctpDataPart dp; }; struct sctpECN_echo{ struct sctpChunkDesc uh; nd_uint32_t Lowest_TSN; }; struct sctpCWR{ struct sctpChunkDesc uh; nd_uint32_t TSN_reduced_at; }; static const struct tok ForCES_channels[] = { { CHAN_HP, "ForCES HP" }, { CHAN_MP, "ForCES MP" }, { CHAN_LP, "ForCES LP" }, { 0, NULL } }; /* data chunk's payload protocol identifiers */ #define SCTP_PPID_IUA 1 #define SCTP_PPID_M2UA 2 #define SCTP_PPID_M3UA 3 #define SCTP_PPID_SUA 4 #define SCTP_PPID_M2PA 5 #define SCTP_PPID_V5UA 6 #define SCTP_PPID_H248 7 #define SCTP_PPID_BICC 8 #define SCTP_PPID_TALI 9 #define SCTP_PPID_DUA 10 #define SCTP_PPID_ASAP 11 #define SCTP_PPID_ENRP 12 #define SCTP_PPID_H323 13 #define SCTP_PPID_QIPC 14 #define SCTP_PPID_SIMCO 15 #define SCTP_PPID_DDPSC 16 #define SCTP_PPID_DDPSSC 17 #define SCTP_PPID_S1AP 18 #define SCTP_PPID_RUA 19 #define SCTP_PPID_HNBAP 20 #define SCTP_PPID_FORCES_HP 21 #define SCTP_PPID_FORCES_MP 22 #define SCTP_PPID_FORCES_LP 23 #define SCTP_PPID_SBC_AP 24 #define SCTP_PPID_NBAP 25 /* 26 */ #define SCTP_PPID_X2AP 27 static const struct tok PayloadProto_idents[] = { { SCTP_PPID_IUA, "ISDN Q.921" }, { SCTP_PPID_M2UA, "M2UA" }, { SCTP_PPID_M3UA, "M3UA" }, { SCTP_PPID_SUA, "SUA" }, { SCTP_PPID_M2PA, "M2PA" }, { SCTP_PPID_V5UA, "V5.2" }, { SCTP_PPID_H248, "H.248" }, { SCTP_PPID_BICC, "BICC" }, { SCTP_PPID_TALI, "TALI" }, { SCTP_PPID_DUA, "DUA" }, { SCTP_PPID_ASAP, "ASAP" }, { SCTP_PPID_ENRP, "ENRP" }, { SCTP_PPID_H323, "H.323" }, { SCTP_PPID_QIPC, "Q.IPC" }, { SCTP_PPID_SIMCO, "SIMCO" }, { SCTP_PPID_DDPSC, "DDPSC" }, { SCTP_PPID_DDPSSC, "DDPSSC" }, { SCTP_PPID_S1AP, "S1AP" }, { SCTP_PPID_RUA, "RUA" }, { SCTP_PPID_HNBAP, "HNBAP" }, { SCTP_PPID_FORCES_HP, "ForCES HP" }, { SCTP_PPID_FORCES_MP, "ForCES MP" }, { SCTP_PPID_FORCES_LP, "ForCES LP" }, { SCTP_PPID_SBC_AP, "SBc-AP" }, { SCTP_PPID_NBAP, "NBAP" }, /* 26 */ { SCTP_PPID_X2AP, "X2AP" }, { 0, NULL } }; static int isForCES_port(u_short Port) { if (Port == CHAN_HP) return 1; if (Port == CHAN_MP) return 1; if (Port == CHAN_LP) return 1; return 0; } void sctp_print(netdissect_options *ndo, const u_char *bp, /* beginning of sctp packet */ const u_char *bp2, /* beginning of enclosing */ u_int sctpPacketLength) /* ip packet */ { u_int sctpPacketLengthRemaining; const struct sctpHeader *sctpPktHdr; const struct ip *ip; const struct ip6_hdr *ip6; uint8_t chunkID; u_short sourcePort, destPort; u_int chunkCount; const struct sctpChunkDesc *chunkDescPtr; const char *sep; int isforces = 0; ndo->ndo_protocol = "sctp"; if (sctpPacketLength < sizeof(struct sctpHeader)) { ND_PRINT("truncated-sctp - %zu bytes missing!", sizeof(struct sctpHeader) - sctpPacketLength); return; } sctpPktHdr = (const struct sctpHeader*) bp; ND_TCHECK_SIZE(sctpPktHdr); sctpPacketLengthRemaining = sctpPacketLength; sourcePort = GET_BE_U_2(sctpPktHdr->source); destPort = GET_BE_U_2(sctpPktHdr->destination); ip = (const struct ip *)bp2; if (IP_V(ip) == 6) ip6 = (const struct ip6_hdr *)bp2; else ip6 = NULL; if (ip6) { ND_PRINT("%s.%u > %s.%u: sctp", GET_IP6ADDR_STRING(ip6->ip6_src), sourcePort, GET_IP6ADDR_STRING(ip6->ip6_dst), destPort); } else { ND_PRINT("%s.%u > %s.%u: sctp", GET_IPADDR_STRING(ip->ip_src), sourcePort, GET_IPADDR_STRING(ip->ip_dst), destPort); } if (isForCES_port(sourcePort)) { ND_PRINT("[%s]", tok2str(ForCES_channels, NULL, sourcePort)); isforces = 1; } if (isForCES_port(destPort)) { ND_PRINT("[%s]", tok2str(ForCES_channels, NULL, destPort)); isforces = 1; } bp += sizeof(struct sctpHeader); sctpPacketLengthRemaining -= sizeof(struct sctpHeader); if (ndo->ndo_vflag >= 2) sep = "\n\t"; else sep = " ("; /* cycle through all chunks, printing information on each one */ for (chunkCount = 0, chunkDescPtr = (const struct sctpChunkDesc *)bp; sctpPacketLengthRemaining != 0; chunkCount++) { uint16_t chunkLength, chunkLengthRemaining; uint16_t align; chunkDescPtr = (const struct sctpChunkDesc *)bp; if (sctpPacketLengthRemaining < sizeof(*chunkDescPtr)) { ND_PRINT("%s%u) [chunk descriptor cut off at end of packet]", sep, chunkCount+1); break; } ND_TCHECK_SIZE(chunkDescPtr); chunkLength = GET_BE_U_2(chunkDescPtr->chunkLength); if (chunkLength < sizeof(*chunkDescPtr)) { ND_PRINT("%s%u) [Bad chunk length %u, < size of chunk descriptor]", sep, chunkCount+1, chunkLength); break; } chunkLengthRemaining = chunkLength; align = chunkLength % 4; if (align != 0) align = 4 - align; if (sctpPacketLengthRemaining < align) { ND_PRINT("%s%u) [Bad chunk length %u, > remaining data in packet]", sep, chunkCount+1, chunkLength); break; } ND_TCHECK_LEN(bp, chunkLength); bp += sizeof(*chunkDescPtr); sctpPacketLengthRemaining -= sizeof(*chunkDescPtr); chunkLengthRemaining -= sizeof(*chunkDescPtr); ND_PRINT("%s%u) ", sep, chunkCount+1); chunkID = GET_U_1(chunkDescPtr->chunkID); ND_PRINT("[%s] ", tok2str(sctp_chunkid_str, "Unknown chunk type: 0x%x", chunkID)); switch (chunkID) { case SCTP_DATA : { const struct sctpDataPart *dataHdrPtr; uint8_t chunkFlg; uint32_t ppid; uint16_t payload_size; chunkFlg = GET_U_1(chunkDescPtr->chunkFlg); if ((chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED) ND_PRINT("(U)"); if ((chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) ND_PRINT("(B)"); if ((chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) ND_PRINT("(E)"); if( ((chunkFlg & SCTP_DATA_UNORDERED) == SCTP_DATA_UNORDERED) || ((chunkFlg & SCTP_DATA_FIRST_FRAG) == SCTP_DATA_FIRST_FRAG) || ((chunkFlg & SCTP_DATA_LAST_FRAG) == SCTP_DATA_LAST_FRAG) ) ND_PRINT(" "); if (chunkLengthRemaining < sizeof(*dataHdrPtr)) { ND_PRINT("bogus chunk length %u]", chunkLength); return; } dataHdrPtr=(const struct sctpDataPart*)bp; ppid = GET_BE_U_4(dataHdrPtr->payloadtype); ND_PRINT("[TSN: %u] ", GET_BE_U_4(dataHdrPtr->TSN)); ND_PRINT("[SID: %u] ", GET_BE_U_2(dataHdrPtr->streamId)); ND_PRINT("[SSEQ %u] ", GET_BE_U_2(dataHdrPtr->sequence)); ND_PRINT("[PPID %s] ", tok2str(PayloadProto_idents, "0x%x", ppid)); if (!isforces) { isforces = (ppid == SCTP_PPID_FORCES_HP) || (ppid == SCTP_PPID_FORCES_MP) || (ppid == SCTP_PPID_FORCES_LP); } bp += sizeof(*dataHdrPtr); sctpPacketLengthRemaining -= sizeof(*dataHdrPtr); chunkLengthRemaining -= sizeof(*dataHdrPtr); payload_size = chunkLengthRemaining; if (payload_size == 0) { ND_PRINT("bogus chunk length %u]", chunkLength); return; } if (isforces) { forces_print(ndo, bp, payload_size); /* ndo_protocol reassignment after forces_print() call */ ndo->ndo_protocol = "sctp"; } else if (ndo->ndo_vflag >= 2) { /* if verbose output is specified */ /* at the command line */ switch (ppid) { case SCTP_PPID_M3UA : m3ua_print(ndo, bp, payload_size); /* ndo_protocol reassignment after m3ua_print() call */ ndo->ndo_protocol = "sctp"; break; default: ND_PRINT("[Payload"); if (!ndo->ndo_suppress_default_print) { ND_PRINT(":"); ND_DEFAULTPRINT(bp, payload_size); } ND_PRINT("]"); break; } } bp += payload_size; sctpPacketLengthRemaining -= payload_size; chunkLengthRemaining -= payload_size; break; } case SCTP_INITIATION : { const struct sctpInitiation *init; if (chunkLengthRemaining < sizeof(*init)) { ND_PRINT("bogus chunk length %u]", chunkLength); return; } init=(const struct sctpInitiation*)bp; ND_PRINT("[init tag: %u] ", GET_BE_U_4(init->initTag)); ND_PRINT("[rwnd: %u] ", GET_BE_U_4(init->rcvWindowCredit)); ND_PRINT("[OS: %u] ", GET_BE_U_2(init->NumPreopenStreams)); ND_PRINT("[MIS: %u] ", GET_BE_U_2(init->MaxInboundStreams)); ND_PRINT("[init TSN: %u] ", GET_BE_U_4(init->initialTSN)); bp += sizeof(*init); sctpPacketLengthRemaining -= sizeof(*init); chunkLengthRemaining -= sizeof(*init); #if 0 /* ALC you can add code for optional params here */ if( chunkLengthRemaining != 0 ) ND_PRINT(" @@@@@ UNFINISHED @@@@@@%s\n", "Optional params present, but not printed."); #endif bp += chunkLengthRemaining; sctpPacketLengthRemaining -= chunkLengthRemaining; chunkLengthRemaining = 0; break; } case SCTP_INITIATION_ACK : { const struct sctpInitiation *init; if (chunkLengthRemaining < sizeof(*init)) { ND_PRINT("bogus chunk length %u]", chunkLength); return; } init=(const struct sctpInitiation*)bp; ND_PRINT("[init tag: %u] ", GET_BE_U_4(init->initTag)); ND_PRINT("[rwnd: %u] ", GET_BE_U_4(init->rcvWindowCredit)); ND_PRINT("[OS: %u] ", GET_BE_U_2(init->NumPreopenStreams)); ND_PRINT("[MIS: %u] ", GET_BE_U_2(init->MaxInboundStreams)); ND_PRINT("[init TSN: %u] ", GET_BE_U_4(init->initialTSN)); bp += sizeof(*init); sctpPacketLengthRemaining -= sizeof(*init); chunkLengthRemaining -= sizeof(*init); #if 0 /* ALC you can add code for optional params here */ if( chunkLengthRemaining != 0 ) ND_PRINT(" @@@@@ UNFINISHED @@@@@@%s\n", "Optional params present, but not printed."); #endif bp += chunkLengthRemaining; sctpPacketLengthRemaining -= chunkLengthRemaining; chunkLengthRemaining = 0; break; } case SCTP_SELECTIVE_ACK: { const struct sctpSelectiveAck *sack; const struct sctpSelectiveFrag *frag; u_int fragNo, tsnNo; const u_char *dupTSN; if (chunkLengthRemaining < sizeof(*sack)) { ND_PRINT("bogus chunk length %u]", chunkLength); return; } sack=(const struct sctpSelectiveAck*)bp; ND_PRINT("[cum ack %u] ", GET_BE_U_4(sack->highestConseqTSN)); ND_PRINT("[a_rwnd %u] ", GET_BE_U_4(sack->updatedRwnd)); ND_PRINT("[#gap acks %u] ", GET_BE_U_2(sack->numberOfdesc)); ND_PRINT("[#dup tsns %u] ", GET_BE_U_2(sack->numDupTsns)); bp += sizeof(*sack); sctpPacketLengthRemaining -= sizeof(*sack); chunkLengthRemaining -= sizeof(*sack); /* print gaps */ for (fragNo=0; chunkLengthRemaining != 0 && fragNo < GET_BE_U_2(sack->numberOfdesc); bp += sizeof(*frag), sctpPacketLengthRemaining -= sizeof(*frag), chunkLengthRemaining -= sizeof(*frag), fragNo++) { if (chunkLengthRemaining < sizeof(*frag)) { ND_PRINT("bogus chunk length %u]", chunkLength); return; } frag = (const struct sctpSelectiveFrag *)bp; ND_PRINT("\n\t\t[gap ack block #%u: start = %u, end = %u] ", fragNo+1, GET_BE_U_4(sack->highestConseqTSN) + GET_BE_U_2(frag->fragmentStart), GET_BE_U_4(sack->highestConseqTSN) + GET_BE_U_2(frag->fragmentEnd)); } /* print duplicate TSNs */ for (tsnNo=0; chunkLengthRemaining != 0 && tsnNonumDupTsns); bp += 4, sctpPacketLengthRemaining -= 4, chunkLengthRemaining -= 4, tsnNo++) { if (chunkLengthRemaining < 4) { ND_PRINT("bogus chunk length %u]", chunkLength); return; } dupTSN = (const u_char *)bp; ND_PRINT("\n\t\t[dup TSN #%u: %u] ", tsnNo+1, GET_BE_U_4(dupTSN)); } break; } default : { bp += chunkLengthRemaining; sctpPacketLengthRemaining -= chunkLengthRemaining; chunkLengthRemaining = 0; break; } } /* * Any extra stuff at the end of the chunk? * XXX - report this? */ bp += chunkLengthRemaining; sctpPacketLengthRemaining -= chunkLengthRemaining; if (ndo->ndo_vflag < 2) sep = ", ("; if (align != 0) { /* * Fail if the alignment padding isn't in the captured data. * Otherwise, skip it. */ ND_TCHECK_LEN(bp, align); bp += align; sctpPacketLengthRemaining -= align; } } return; trunc: nd_print_trunc(ndo); } tcpdump-4.99.1/print-pktap.c0000644000026300017510000001252514057477727014063 0ustar mcrmcr/* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 2000 * 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. */ /* \summary: Apple's DLT_PKTAP printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "extract.h" #ifdef DLT_PKTAP /* * XXX - these are little-endian in the captures I've seen, but Apple * no longer make any big-endian machines (Macs use x86, iOS machines * use ARM and run it little-endian), so that might be by definition * or they might be host-endian. * * If a big-endian PKTAP file ever shows up, and it comes from a * big-endian machine, presumably these are host-endian, and we need * to just fetch the fields directly in tcpdump but byte-swap them * to host byte order in libpcap. */ typedef struct pktap_header { nd_uint32_t pkt_len; /* length of pktap header */ nd_uint32_t pkt_rectype; /* type of record */ nd_uint32_t pkt_dlt; /* DLT type of this packet */ char pkt_ifname[24]; /* interface name */ nd_uint32_t pkt_flags; nd_uint32_t pkt_pfamily; /* "protocol family" */ nd_uint32_t pkt_llhdrlen; /* link-layer header length? */ nd_uint32_t pkt_lltrlrlen; /* link-layer trailer length? */ nd_uint32_t pkt_pid; /* process ID */ char pkt_cmdname[20]; /* command name */ nd_uint32_t pkt_svc_class; /* "service class" */ nd_uint16_t pkt_iftype; /* "interface type" */ nd_uint16_t pkt_ifunit; /* unit number of interface? */ nd_uint32_t pkt_epid; /* "effective process ID" */ char pkt_ecmdname[20]; /* "effective command name" */ } pktap_header_t; /* * Record types. */ #define PKT_REC_NONE 0 /* nothing follows the header */ #define PKT_REC_PACKET 1 /* a packet follows the header */ static void pktap_header_print(netdissect_options *ndo, const u_char *bp, u_int length) { const pktap_header_t *hdr; uint32_t dlt, hdrlen; const char *dltname; hdr = (const pktap_header_t *)bp; dlt = GET_LE_U_4(hdr->pkt_dlt); hdrlen = GET_LE_U_4(hdr->pkt_len); dltname = pcap_datalink_val_to_name(dlt); if (!ndo->ndo_qflag) { ND_PRINT("DLT %s (%u) len %u", (dltname != NULL ? dltname : "UNKNOWN"), dlt, hdrlen); } else { ND_PRINT("%s", (dltname != NULL ? dltname : "UNKNOWN")); } ND_PRINT(", length %u: ", length); } /* * This is the top level routine of the printer. 'p' points * to the ether header of the packet, 'h->ts' is the timestamp, * 'h->len' is the length of the packet off the wire, and 'h->caplen' * is the number of bytes actually captured. */ void pktap_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p) { uint32_t dlt, hdrlen, rectype; u_int caplen = h->caplen; u_int length = h->len; if_printer printer; const pktap_header_t *hdr; struct pcap_pkthdr nhdr; ndo->ndo_protocol = "pktap"; if (length < sizeof(pktap_header_t)) { ND_PRINT(" (packet too short, %u < %zu)", length, sizeof(pktap_header_t)); goto invalid; } hdr = (const pktap_header_t *)p; dlt = GET_LE_U_4(hdr->pkt_dlt); hdrlen = GET_LE_U_4(hdr->pkt_len); if (hdrlen < sizeof(pktap_header_t)) { /* * Claimed header length < structure length. * XXX - does this just mean some fields aren't * being supplied, or is it truly an error (i.e., * is the length supplied so that the header can * be expanded in the future)? */ ND_PRINT(" (pkt_len too small, %u < %zu)", hdrlen, sizeof(pktap_header_t)); goto invalid; } if (hdrlen > length) { ND_PRINT(" (pkt_len too big, %u > %u)", hdrlen, length); goto invalid; } ND_TCHECK_LEN(p, hdrlen); if (ndo->ndo_eflag) pktap_header_print(ndo, p, length); length -= hdrlen; caplen -= hdrlen; p += hdrlen; rectype = GET_LE_U_4(hdr->pkt_rectype); switch (rectype) { case PKT_REC_NONE: ND_PRINT("no data"); break; case PKT_REC_PACKET: printer = lookup_printer(dlt); if (printer != NULL) { nhdr = *h; nhdr.caplen = caplen; nhdr.len = length; printer(ndo, &nhdr, p); hdrlen += ndo->ndo_ll_hdr_len; } else { if (!ndo->ndo_eflag) pktap_header_print(ndo, (const u_char *)hdr, length + hdrlen); if (!ndo->ndo_suppress_default_print) ND_DEFAULTPRINT(p, caplen); } break; } ndo->ndo_ll_hdr_len += hdrlen; return; invalid: nd_print_invalid(ndo); } #endif /* DLT_PKTAP */ tcpdump-4.99.1/print-eigrp.c0000644000026300017510000004730114057477734014050 0ustar mcrmcr/* * Copyright (c) 1998-2004 Hannes Gredler * The TCPDUMP project * * 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, and (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. * 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. */ /* \summary: Enhanced Interior Gateway Routing Protocol (EIGRP) printer */ /* * specification: * * https://web.archive.org/web/20190722221712/https://www.rhyshaden.com/eigrp.htm * RFC 7868 */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include #include "netdissect.h" #include "extract.h" #include "addrtoname.h" struct eigrp_common_header { nd_uint8_t version; nd_uint8_t opcode; nd_uint16_t checksum; nd_uint32_t flags; nd_uint32_t seq; nd_uint32_t ack; nd_uint16_t vrid; nd_uint16_t asn; }; #define EIGRP_VERSION 2 #define EIGRP_OPCODE_UPDATE 1 #define EIGRP_OPCODE_QUERY 3 #define EIGRP_OPCODE_REPLY 4 #define EIGRP_OPCODE_HELLO 5 #define EIGRP_OPCODE_IPXSAP 6 #define EIGRP_OPCODE_PROBE 7 static const struct tok eigrp_opcode_values[] = { { EIGRP_OPCODE_UPDATE, "Update" }, { EIGRP_OPCODE_QUERY, "Query" }, { EIGRP_OPCODE_REPLY, "Reply" }, { EIGRP_OPCODE_HELLO, "Hello" }, { EIGRP_OPCODE_IPXSAP, "IPX SAP" }, { EIGRP_OPCODE_PROBE, "Probe" }, { 0, NULL} }; static const struct tok eigrp_common_header_flag_values[] = { { 0x01, "Init" }, { 0x02, "Conditionally Received" }, { 0x04, "Restart" }, { 0x08, "End-of-Table" }, { 0, NULL} }; struct eigrp_tlv_header { nd_uint16_t type; nd_uint16_t length; }; #define EIGRP_TLV_GENERAL_PARM 0x0001 #define EIGRP_TLV_AUTH 0x0002 #define EIGRP_TLV_SEQ 0x0003 #define EIGRP_TLV_SW_VERSION 0x0004 #define EIGRP_TLV_MCAST_SEQ 0x0005 #define EIGRP_TLV_IP_INT 0x0102 #define EIGRP_TLV_IP_EXT 0x0103 #define EIGRP_TLV_AT_INT 0x0202 #define EIGRP_TLV_AT_EXT 0x0203 #define EIGRP_TLV_AT_CABLE_SETUP 0x0204 #define EIGRP_TLV_IPX_INT 0x0302 #define EIGRP_TLV_IPX_EXT 0x0303 static const struct tok eigrp_tlv_values[] = { { EIGRP_TLV_GENERAL_PARM, "General Parameters"}, { EIGRP_TLV_AUTH, "Authentication"}, { EIGRP_TLV_SEQ, "Sequence"}, { EIGRP_TLV_SW_VERSION, "Software Version"}, { EIGRP_TLV_MCAST_SEQ, "Next Multicast Sequence"}, { EIGRP_TLV_IP_INT, "IP Internal routes"}, { EIGRP_TLV_IP_EXT, "IP External routes"}, { EIGRP_TLV_AT_INT, "AppleTalk Internal routes"}, { EIGRP_TLV_AT_EXT, "AppleTalk External routes"}, { EIGRP_TLV_AT_CABLE_SETUP, "AppleTalk Cable setup"}, { EIGRP_TLV_IPX_INT, "IPX Internal routes"}, { EIGRP_TLV_IPX_EXT, "IPX External routes"}, { 0, NULL} }; struct eigrp_tlv_general_parm_t { nd_uint8_t k1; nd_uint8_t k2; nd_uint8_t k3; nd_uint8_t k4; nd_uint8_t k5; nd_uint8_t res; nd_uint16_t holdtime; }; struct eigrp_tlv_sw_version_t { nd_uint8_t ios_major; nd_uint8_t ios_minor; nd_uint8_t eigrp_major; nd_uint8_t eigrp_minor; }; struct eigrp_tlv_ip_int_t { nd_ipv4 nexthop; nd_uint32_t delay; nd_uint32_t bandwidth; nd_uint24_t mtu; nd_uint8_t hopcount; nd_uint8_t reliability; nd_uint8_t load; nd_byte reserved[2]; nd_uint8_t plen; nd_uint8_t destination; /* variable length [1-4] bytes encoding */ }; struct eigrp_tlv_ip_ext_t { nd_ipv4 nexthop; nd_ipv4 origin_router; nd_uint32_t origin_as; nd_uint32_t tag; nd_uint32_t metric; nd_byte reserved[2]; nd_uint8_t proto_id; nd_uint8_t flags; nd_uint32_t delay; nd_uint32_t bandwidth; nd_uint24_t mtu; nd_uint8_t hopcount; nd_uint8_t reliability; nd_uint8_t load; nd_byte reserved2[2]; nd_uint8_t plen; nd_uint8_t destination; /* variable length [1-4] bytes encoding */ }; struct eigrp_tlv_at_cable_setup_t { nd_uint16_t cable_start; nd_uint16_t cable_end; nd_uint32_t router_id; }; struct eigrp_tlv_at_int_t { nd_byte nexthop[4]; nd_uint32_t delay; nd_uint32_t bandwidth; nd_uint24_t mtu; nd_uint8_t hopcount; nd_uint8_t reliability; nd_uint8_t load; nd_byte reserved[2]; nd_uint16_t cable_start; nd_uint16_t cable_end; }; struct eigrp_tlv_at_ext_t { nd_byte nexthop[4]; nd_uint32_t origin_router; nd_uint32_t origin_as; nd_uint32_t tag; nd_uint8_t proto_id; nd_uint8_t flags; nd_uint16_t metric; nd_uint32_t delay; nd_uint32_t bandwidth; nd_uint24_t mtu; nd_uint8_t hopcount; nd_uint8_t reliability; nd_uint8_t load; nd_byte reserved2[2]; nd_uint16_t cable_start; nd_uint16_t cable_end; }; static const struct tok eigrp_ext_proto_id_values[] = { { 0x01, "IGRP" }, { 0x02, "EIGRP" }, { 0x03, "Static" }, { 0x04, "RIP" }, { 0x05, "Hello" }, { 0x06, "OSPF" }, { 0x07, "IS-IS" }, { 0x08, "EGP" }, { 0x09, "BGP" }, { 0x0a, "IDRP" }, { 0x0b, "Connected" }, { 0, NULL} }; void eigrp_print(netdissect_options *ndo, const u_char *pptr, u_int len) { const struct eigrp_common_header *eigrp_com_header; const struct eigrp_tlv_header *eigrp_tlv_header; const u_char *tptr,*tlv_tptr; u_int tlen,eigrp_tlv_len,eigrp_tlv_type,tlv_tlen, byte_length, bit_length; uint8_t prefix[4]; union { const struct eigrp_tlv_general_parm_t *eigrp_tlv_general_parm; const struct eigrp_tlv_sw_version_t *eigrp_tlv_sw_version; const struct eigrp_tlv_ip_int_t *eigrp_tlv_ip_int; const struct eigrp_tlv_ip_ext_t *eigrp_tlv_ip_ext; const struct eigrp_tlv_at_cable_setup_t *eigrp_tlv_at_cable_setup; const struct eigrp_tlv_at_int_t *eigrp_tlv_at_int; const struct eigrp_tlv_at_ext_t *eigrp_tlv_at_ext; } tlv_ptr; ndo->ndo_protocol = "eigrp"; tptr=pptr; eigrp_com_header = (const struct eigrp_common_header *)pptr; ND_TCHECK_SIZE(eigrp_com_header); /* * Sanity checking of the header. */ if (GET_U_1(eigrp_com_header->version) != EIGRP_VERSION) { ND_PRINT("EIGRP version %u packet not supported", GET_U_1(eigrp_com_header->version)); return; } /* in non-verbose mode just lets print the basic Message Type*/ if (ndo->ndo_vflag < 1) { ND_PRINT("EIGRP %s, length: %u", tok2str(eigrp_opcode_values, "unknown (%u)",GET_U_1(eigrp_com_header->opcode)), len); return; } /* ok they seem to want to know everything - lets fully decode it */ if (len < sizeof(struct eigrp_common_header)) { ND_PRINT("EIGRP %s, length: %u (too short, < %zu)", tok2str(eigrp_opcode_values, "unknown (%u)",GET_U_1(eigrp_com_header->opcode)), len, sizeof(struct eigrp_common_header)); return; } tlen=len-sizeof(struct eigrp_common_header); ND_PRINT("\n\tEIGRP v%u, opcode: %s (%u), chksum: 0x%04x, Flags: [%s]" "\n\tseq: 0x%08x, ack: 0x%08x, VRID: %u, AS: %u, length: %u", GET_U_1(eigrp_com_header->version), tok2str(eigrp_opcode_values, "unknown, type: %u",GET_U_1(eigrp_com_header->opcode)), GET_U_1(eigrp_com_header->opcode), GET_BE_U_2(eigrp_com_header->checksum), bittok2str(eigrp_common_header_flag_values, "none", GET_BE_U_4(eigrp_com_header->flags)), GET_BE_U_4(eigrp_com_header->seq), GET_BE_U_4(eigrp_com_header->ack), GET_BE_U_2(eigrp_com_header->vrid), GET_BE_U_2(eigrp_com_header->asn), tlen); tptr+=sizeof(struct eigrp_common_header); while(tlen>0) { /* did we capture enough for fully decoding the object header ? */ ND_TCHECK_LEN(tptr, sizeof(struct eigrp_tlv_header)); eigrp_tlv_header = (const struct eigrp_tlv_header *)tptr; eigrp_tlv_len=GET_BE_U_2(eigrp_tlv_header->length); eigrp_tlv_type=GET_BE_U_2(eigrp_tlv_header->type); if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header) || eigrp_tlv_len > tlen) { print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t ",tlen); return; } ND_PRINT("\n\t %s TLV (0x%04x), length: %u", tok2str(eigrp_tlv_values, "Unknown", eigrp_tlv_type), eigrp_tlv_type, eigrp_tlv_len); if (eigrp_tlv_len < sizeof(struct eigrp_tlv_header)) { ND_PRINT(" (too short, < %zu)", sizeof(struct eigrp_tlv_header)); break; } tlv_tptr=tptr+sizeof(struct eigrp_tlv_header); tlv_tlen=eigrp_tlv_len-sizeof(struct eigrp_tlv_header); /* did we capture enough for fully decoding the object ? */ ND_TCHECK_LEN(tptr, eigrp_tlv_len); switch(eigrp_tlv_type) { case EIGRP_TLV_GENERAL_PARM: tlv_ptr.eigrp_tlv_general_parm = (const struct eigrp_tlv_general_parm_t *)tlv_tptr; if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_general_parm)) { ND_PRINT(" (too short, < %zu)", sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_general_parm)); break; } ND_PRINT("\n\t holdtime: %us, k1 %u, k2 %u, k3 %u, k4 %u, k5 %u", GET_BE_U_2(tlv_ptr.eigrp_tlv_general_parm->holdtime), GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k1), GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k2), GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k3), GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k4), GET_U_1(tlv_ptr.eigrp_tlv_general_parm->k5)); break; case EIGRP_TLV_SW_VERSION: tlv_ptr.eigrp_tlv_sw_version = (const struct eigrp_tlv_sw_version_t *)tlv_tptr; if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_sw_version)) { ND_PRINT(" (too short, < %zu)", sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_sw_version)); break; } ND_PRINT("\n\t IOS version: %u.%u, EIGRP version %u.%u", GET_U_1(tlv_ptr.eigrp_tlv_sw_version->ios_major), GET_U_1(tlv_ptr.eigrp_tlv_sw_version->ios_minor), GET_U_1(tlv_ptr.eigrp_tlv_sw_version->eigrp_major), GET_U_1(tlv_ptr.eigrp_tlv_sw_version->eigrp_minor)); break; case EIGRP_TLV_IP_INT: tlv_ptr.eigrp_tlv_ip_int = (const struct eigrp_tlv_ip_int_t *)tlv_tptr; if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_ip_int)) { ND_PRINT(" (too short, < %zu)", sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_ip_int)); break; } bit_length = GET_U_1(tlv_ptr.eigrp_tlv_ip_int->plen); if (bit_length > 32) { ND_PRINT("\n\t illegal prefix length %u",bit_length); break; } byte_length = (bit_length + 7) / 8; /* variable length encoding */ memset(prefix, 0, 4); GET_CPY_BYTES(prefix, tlv_ptr.eigrp_tlv_ip_int->destination, byte_length); ND_PRINT("\n\t IPv4 prefix: %15s/%u, nexthop: ", ipaddr_string(ndo, prefix), /* local buffer, not packet data; don't use GET_IPADDR_STRING() */ bit_length); if (GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_int->nexthop) == 0) ND_PRINT("self"); else ND_PRINT("%s", GET_IPADDR_STRING(tlv_ptr.eigrp_tlv_ip_int->nexthop)); ND_PRINT("\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_int->delay)/100), GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_int->bandwidth), GET_BE_U_3(tlv_ptr.eigrp_tlv_ip_int->mtu), GET_U_1(tlv_ptr.eigrp_tlv_ip_int->hopcount), GET_U_1(tlv_ptr.eigrp_tlv_ip_int->reliability), GET_U_1(tlv_ptr.eigrp_tlv_ip_int->load)); break; case EIGRP_TLV_IP_EXT: tlv_ptr.eigrp_tlv_ip_ext = (const struct eigrp_tlv_ip_ext_t *)tlv_tptr; if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_ip_ext)) { ND_PRINT(" (too short, < %zu)", sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_ip_ext)); break; } bit_length = GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->plen); if (bit_length > 32) { ND_PRINT("\n\t illegal prefix length %u",bit_length); break; } byte_length = (bit_length + 7) / 8; /* variable length encoding */ memset(prefix, 0, 4); GET_CPY_BYTES(prefix, tlv_ptr.eigrp_tlv_ip_ext->destination, byte_length); ND_PRINT("\n\t IPv4 prefix: %15s/%u, nexthop: ", ipaddr_string(ndo, prefix), /* local buffer, not packet data; don't use GET_IPADDR_STRING() */ bit_length); if (GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->nexthop) == 0) ND_PRINT("self"); else ND_PRINT("%s", GET_IPADDR_STRING(tlv_ptr.eigrp_tlv_ip_ext->nexthop)); ND_PRINT("\n\t origin-router %s, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u", GET_IPADDR_STRING(tlv_ptr.eigrp_tlv_ip_ext->origin_router), GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->origin_as), tok2str(eigrp_ext_proto_id_values,"unknown",GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->proto_id)), GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->flags), GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->tag), GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->metric)); ND_PRINT("\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->delay)/100), GET_BE_U_4(tlv_ptr.eigrp_tlv_ip_ext->bandwidth), GET_BE_U_3(tlv_ptr.eigrp_tlv_ip_ext->mtu), GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->hopcount), GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->reliability), GET_U_1(tlv_ptr.eigrp_tlv_ip_ext->load)); break; case EIGRP_TLV_AT_CABLE_SETUP: tlv_ptr.eigrp_tlv_at_cable_setup = (const struct eigrp_tlv_at_cable_setup_t *)tlv_tptr; if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_cable_setup)) { ND_PRINT(" (too short, < %zu)", sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_cable_setup)); break; } ND_PRINT("\n\t Cable-range: %u-%u, Router-ID %u", GET_BE_U_2(tlv_ptr.eigrp_tlv_at_cable_setup->cable_start), GET_BE_U_2(tlv_ptr.eigrp_tlv_at_cable_setup->cable_end), GET_BE_U_4(tlv_ptr.eigrp_tlv_at_cable_setup->router_id)); break; case EIGRP_TLV_AT_INT: tlv_ptr.eigrp_tlv_at_int = (const struct eigrp_tlv_at_int_t *)tlv_tptr; if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_int)) { ND_PRINT(" (too short, < %zu)", sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_int)); break; } ND_PRINT("\n\t Cable-Range: %u-%u, nexthop: ", GET_BE_U_2(tlv_ptr.eigrp_tlv_at_int->cable_start), GET_BE_U_2(tlv_ptr.eigrp_tlv_at_int->cable_end)); if (GET_BE_U_4(tlv_ptr.eigrp_tlv_at_int->nexthop) == 0) ND_PRINT("self"); else ND_PRINT("%u.%u", GET_BE_U_2(&tlv_ptr.eigrp_tlv_at_int->nexthop[0]), GET_BE_U_2(&tlv_ptr.eigrp_tlv_at_int->nexthop[2])); ND_PRINT("\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (GET_BE_U_4(tlv_ptr.eigrp_tlv_at_int->delay)/100), GET_BE_U_4(tlv_ptr.eigrp_tlv_at_int->bandwidth), GET_BE_U_3(tlv_ptr.eigrp_tlv_at_int->mtu), GET_U_1(tlv_ptr.eigrp_tlv_at_int->hopcount), GET_U_1(tlv_ptr.eigrp_tlv_at_int->reliability), GET_U_1(tlv_ptr.eigrp_tlv_at_int->load)); break; case EIGRP_TLV_AT_EXT: tlv_ptr.eigrp_tlv_at_ext = (const struct eigrp_tlv_at_ext_t *)tlv_tptr; if (tlv_tlen < sizeof(*tlv_ptr.eigrp_tlv_at_ext)) { ND_PRINT(" (too short, < %zu)", sizeof(struct eigrp_tlv_header) + sizeof(*tlv_ptr.eigrp_tlv_at_ext)); break; } ND_PRINT("\n\t Cable-Range: %u-%u, nexthop: ", GET_BE_U_2(tlv_ptr.eigrp_tlv_at_ext->cable_start), GET_BE_U_2(tlv_ptr.eigrp_tlv_at_ext->cable_end)); if (GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->nexthop) == 0) ND_PRINT("self"); else ND_PRINT("%u.%u", GET_BE_U_2(&tlv_ptr.eigrp_tlv_at_ext->nexthop[0]), GET_BE_U_2(&tlv_ptr.eigrp_tlv_at_ext->nexthop[2])); ND_PRINT("\n\t origin-router %u, origin-as %u, origin-proto %s, flags [0x%02x], tag 0x%08x, metric %u", GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->origin_router), GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->origin_as), tok2str(eigrp_ext_proto_id_values,"unknown",GET_U_1(tlv_ptr.eigrp_tlv_at_ext->proto_id)), GET_U_1(tlv_ptr.eigrp_tlv_at_ext->flags), GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->tag), GET_BE_U_2(tlv_ptr.eigrp_tlv_at_ext->metric)); ND_PRINT("\n\t delay %u ms, bandwidth %u Kbps, mtu %u, hop %u, reliability %u, load %u", (GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->delay)/100), GET_BE_U_4(tlv_ptr.eigrp_tlv_at_ext->bandwidth), GET_BE_U_3(tlv_ptr.eigrp_tlv_at_ext->mtu), GET_U_1(tlv_ptr.eigrp_tlv_at_ext->hopcount), GET_U_1(tlv_ptr.eigrp_tlv_at_ext->reliability), GET_U_1(tlv_ptr.eigrp_tlv_at_ext->load)); break; /* * FIXME those are the defined TLVs that lack a decoder * you are welcome to contribute code ;-) */ case EIGRP_TLV_AUTH: case EIGRP_TLV_SEQ: case EIGRP_TLV_MCAST_SEQ: case EIGRP_TLV_IPX_INT: case EIGRP_TLV_IPX_EXT: default: if (ndo->ndo_vflag <= 1) print_unknown_data(ndo,tlv_tptr,"\n\t ",tlv_tlen); break; } /* do we want to see an additionally hexdump ? */ if (ndo->ndo_vflag > 1) print_unknown_data(ndo,tptr+sizeof(struct eigrp_tlv_header),"\n\t ", eigrp_tlv_len-sizeof(struct eigrp_tlv_header)); tptr+=eigrp_tlv_len; tlen-=eigrp_tlv_len; } return; trunc: nd_print_trunc(ndo); } tcpdump-4.99.1/print-cfm.c0000644000026300017510000005746514057477727013525 0ustar mcrmcr/* * Copyright (c) 1998-2006 The TCPDUMP project * * 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, and (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. * 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. * * Original code by Hannes Gredler (hannes@gredler.at) */ /* \summary: IEEE 802.1ag Connectivity Fault Management (CFM) protocols printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" #include "extract.h" #include "addrtoname.h" #include "oui.h" #include "af.h" struct cfm_common_header_t { nd_uint8_t mdlevel_version; nd_uint8_t opcode; nd_uint8_t flags; nd_uint8_t first_tlv_offset; }; #define CFM_VERSION 0 #define CFM_EXTRACT_VERSION(x) ((x)&0x1f) #define CFM_EXTRACT_MD_LEVEL(x) (((x)&0xe0)>>5) #define CFM_OPCODE_CCM 1 #define CFM_OPCODE_LBR 2 #define CFM_OPCODE_LBM 3 #define CFM_OPCODE_LTR 4 #define CFM_OPCODE_LTM 5 static const struct tok cfm_opcode_values[] = { { CFM_OPCODE_CCM, "Continuity Check Message"}, { CFM_OPCODE_LBR, "Loopback Reply"}, { CFM_OPCODE_LBM, "Loopback Message"}, { CFM_OPCODE_LTR, "Linktrace Reply"}, { CFM_OPCODE_LTM, "Linktrace Message"}, { 0, NULL} }; /* * Message Formats. */ struct cfm_ccm_t { nd_uint32_t sequence; nd_uint16_t ma_epi; nd_byte names[48]; nd_byte itu_t_y_1731[16]; }; /* * Timer Bases for the CCM Interval field. * Expressed in units of seconds. */ static const float ccm_interval_base[8] = {0.0f, 0.003333f, 0.01f, 0.1f, 1.0f, 10.0f, 60.0f, 600.0f}; #define CCM_INTERVAL_MIN_MULTIPLIER 3.25 #define CCM_INTERVAL_MAX_MULTIPLIER 3.5 #define CFM_CCM_RDI_FLAG 0x80 #define CFM_EXTRACT_CCM_INTERVAL(x) ((x)&0x07) #define CFM_CCM_MD_FORMAT_8021 0 #define CFM_CCM_MD_FORMAT_NONE 1 #define CFM_CCM_MD_FORMAT_DNS 2 #define CFM_CCM_MD_FORMAT_MAC 3 #define CFM_CCM_MD_FORMAT_CHAR 4 static const struct tok cfm_md_nameformat_values[] = { { CFM_CCM_MD_FORMAT_8021, "IEEE 802.1"}, { CFM_CCM_MD_FORMAT_NONE, "No MD Name present"}, { CFM_CCM_MD_FORMAT_DNS, "DNS string"}, { CFM_CCM_MD_FORMAT_MAC, "MAC + 16Bit Integer"}, { CFM_CCM_MD_FORMAT_CHAR, "Character string"}, { 0, NULL} }; #define CFM_CCM_MA_FORMAT_8021 0 #define CFM_CCM_MA_FORMAT_VID 1 #define CFM_CCM_MA_FORMAT_CHAR 2 #define CFM_CCM_MA_FORMAT_INT 3 #define CFM_CCM_MA_FORMAT_VPN 4 static const struct tok cfm_ma_nameformat_values[] = { { CFM_CCM_MA_FORMAT_8021, "IEEE 802.1"}, { CFM_CCM_MA_FORMAT_VID, "Primary VID"}, { CFM_CCM_MA_FORMAT_CHAR, "Character string"}, { CFM_CCM_MA_FORMAT_INT, "16Bit Integer"}, { CFM_CCM_MA_FORMAT_VPN, "RFC2685 VPN-ID"}, { 0, NULL} }; struct cfm_lbm_t { nd_uint32_t transaction_id; }; struct cfm_ltm_t { nd_uint32_t transaction_id; nd_uint8_t ttl; nd_mac_addr original_mac; nd_mac_addr target_mac; }; static const struct tok cfm_ltm_flag_values[] = { { 0x80, "Use Forwarding-DB only"}, { 0, NULL} }; struct cfm_ltr_t { nd_uint32_t transaction_id; nd_uint8_t ttl; nd_uint8_t replay_action; }; static const struct tok cfm_ltr_flag_values[] = { { 0x80, "UseFDB Only"}, { 0x40, "FwdYes"}, { 0x20, "Terminal MEP"}, { 0, NULL} }; static const struct tok cfm_ltr_replay_action_values[] = { { 1, "Exact Match"}, { 2, "Filtering DB"}, { 3, "MIP CCM DB"}, { 0, NULL} }; #define CFM_TLV_END 0 #define CFM_TLV_SENDER_ID 1 #define CFM_TLV_PORT_STATUS 2 #define CFM_TLV_INTERFACE_STATUS 3 #define CFM_TLV_DATA 4 #define CFM_TLV_REPLY_INGRESS 5 #define CFM_TLV_REPLY_EGRESS 6 #define CFM_TLV_PRIVATE 31 static const struct tok cfm_tlv_values[] = { { CFM_TLV_END, "End"}, { CFM_TLV_SENDER_ID, "Sender ID"}, { CFM_TLV_PORT_STATUS, "Port status"}, { CFM_TLV_INTERFACE_STATUS, "Interface status"}, { CFM_TLV_DATA, "Data"}, { CFM_TLV_REPLY_INGRESS, "Reply Ingress"}, { CFM_TLV_REPLY_EGRESS, "Reply Egress"}, { CFM_TLV_PRIVATE, "Organization Specific"}, { 0, NULL} }; /* * TLVs */ struct cfm_tlv_header_t { nd_uint8_t type; nd_uint16_t length; }; /* FIXME define TLV formats */ static const struct tok cfm_tlv_port_status_values[] = { { 1, "Blocked"}, { 2, "Up"}, { 0, NULL} }; static const struct tok cfm_tlv_interface_status_values[] = { { 1, "Up"}, { 2, "Down"}, { 3, "Testing"}, { 5, "Dormant"}, { 6, "not present"}, { 7, "lower Layer down"}, { 0, NULL} }; #define CFM_CHASSIS_ID_CHASSIS_COMPONENT 1 #define CFM_CHASSIS_ID_INTERFACE_ALIAS 2 #define CFM_CHASSIS_ID_PORT_COMPONENT 3 #define CFM_CHASSIS_ID_MAC_ADDRESS 4 #define CFM_CHASSIS_ID_NETWORK_ADDRESS 5 #define CFM_CHASSIS_ID_INTERFACE_NAME 6 #define CFM_CHASSIS_ID_LOCAL 7 static const struct tok cfm_tlv_senderid_chassisid_values[] = { { 0, "Reserved"}, { CFM_CHASSIS_ID_CHASSIS_COMPONENT, "Chassis component"}, { CFM_CHASSIS_ID_INTERFACE_ALIAS, "Interface alias"}, { CFM_CHASSIS_ID_PORT_COMPONENT, "Port component"}, { CFM_CHASSIS_ID_MAC_ADDRESS, "MAC address"}, { CFM_CHASSIS_ID_NETWORK_ADDRESS, "Network address"}, { CFM_CHASSIS_ID_INTERFACE_NAME, "Interface name"}, { CFM_CHASSIS_ID_LOCAL, "Locally assigned"}, { 0, NULL} }; static int cfm_network_addr_print(netdissect_options *ndo, const u_char *tptr, const u_int length) { u_int network_addr_type; u_int hexdump = FALSE; /* * Although AFIs are typically 2 octets wide, * 802.1ab specifies that this field width * is only one octet. */ if (length < 1) { ND_PRINT("\n\t Network Address Type (invalid, no data"); return hexdump; } /* The calling function must make any due ND_TCHECK calls. */ network_addr_type = GET_U_1(tptr); ND_PRINT("\n\t Network Address Type %s (%u)", tok2str(af_values, "Unknown", network_addr_type), network_addr_type); /* * Resolve the passed in Address. */ switch(network_addr_type) { case AFNUM_INET: if (length != 1 + 4) { ND_PRINT("(invalid IPv4 address length %u)", length - 1); hexdump = TRUE; break; } ND_PRINT(", %s", GET_IPADDR_STRING(tptr + 1)); break; case AFNUM_INET6: if (length != 1 + 16) { ND_PRINT("(invalid IPv6 address length %u)", length - 1); hexdump = TRUE; break; } ND_PRINT(", %s", GET_IP6ADDR_STRING(tptr + 1)); break; default: hexdump = TRUE; break; } return hexdump; } void cfm_print(netdissect_options *ndo, const u_char *pptr, u_int length) { const struct cfm_common_header_t *cfm_common_header; uint8_t mdlevel_version, opcode, flags, first_tlv_offset; const struct cfm_tlv_header_t *cfm_tlv_header; const uint8_t *tptr, *tlv_ptr; const uint8_t *namesp; u_int names_data_remaining; uint8_t md_nameformat, md_namelength; const uint8_t *md_name; uint8_t ma_nameformat, ma_namelength; const uint8_t *ma_name; u_int hexdump, tlen, cfm_tlv_len, cfm_tlv_type, ccm_interval; union { const struct cfm_ccm_t *cfm_ccm; const struct cfm_lbm_t *cfm_lbm; const struct cfm_ltm_t *cfm_ltm; const struct cfm_ltr_t *cfm_ltr; } msg_ptr; ndo->ndo_protocol = "cfm"; tptr=pptr; cfm_common_header = (const struct cfm_common_header_t *)pptr; if (length < sizeof(*cfm_common_header)) goto tooshort; ND_TCHECK_SIZE(cfm_common_header); /* * Sanity checking of the header. */ mdlevel_version = GET_U_1(cfm_common_header->mdlevel_version); if (CFM_EXTRACT_VERSION(mdlevel_version) != CFM_VERSION) { ND_PRINT("CFMv%u not supported, length %u", CFM_EXTRACT_VERSION(mdlevel_version), length); return; } opcode = GET_U_1(cfm_common_header->opcode); ND_PRINT("CFMv%u %s, MD Level %u, length %u", CFM_EXTRACT_VERSION(mdlevel_version), tok2str(cfm_opcode_values, "unknown (%u)", opcode), CFM_EXTRACT_MD_LEVEL(mdlevel_version), length); /* * In non-verbose mode just print the opcode and md-level. */ if (ndo->ndo_vflag < 1) { return; } flags = GET_U_1(cfm_common_header->flags); first_tlv_offset = GET_U_1(cfm_common_header->first_tlv_offset); ND_PRINT("\n\tFirst TLV offset %u", first_tlv_offset); tptr += sizeof(struct cfm_common_header_t); tlen = length - sizeof(struct cfm_common_header_t); /* * Sanity check the first TLV offset. */ if (first_tlv_offset > tlen) { ND_PRINT(" (too large, must be <= %u)", tlen); return; } switch (opcode) { case CFM_OPCODE_CCM: msg_ptr.cfm_ccm = (const struct cfm_ccm_t *)tptr; if (first_tlv_offset < sizeof(*msg_ptr.cfm_ccm)) { ND_PRINT(" (too small 1, must be >= %zu)", sizeof(*msg_ptr.cfm_ccm)); return; } if (tlen < sizeof(*msg_ptr.cfm_ccm)) goto tooshort; ND_TCHECK_SIZE(msg_ptr.cfm_ccm); ccm_interval = CFM_EXTRACT_CCM_INTERVAL(flags); ND_PRINT(", Flags [CCM Interval %u%s]", ccm_interval, flags & CFM_CCM_RDI_FLAG ? ", RDI" : ""); /* * Resolve the CCM interval field. */ if (ccm_interval) { ND_PRINT("\n\t CCM Interval %.3fs" ", min CCM Lifetime %.3fs, max CCM Lifetime %.3fs", ccm_interval_base[ccm_interval], ccm_interval_base[ccm_interval] * CCM_INTERVAL_MIN_MULTIPLIER, ccm_interval_base[ccm_interval] * CCM_INTERVAL_MAX_MULTIPLIER); } ND_PRINT("\n\t Sequence Number 0x%08x, MA-End-Point-ID 0x%04x", GET_BE_U_4(msg_ptr.cfm_ccm->sequence), GET_BE_U_2(msg_ptr.cfm_ccm->ma_epi)); namesp = msg_ptr.cfm_ccm->names; names_data_remaining = sizeof(msg_ptr.cfm_ccm->names); /* * Resolve the MD fields. */ md_nameformat = GET_U_1(namesp); namesp++; names_data_remaining--; /* We know this is != 0 */ if (md_nameformat != CFM_CCM_MD_FORMAT_NONE) { md_namelength = GET_U_1(namesp); namesp++; names_data_remaining--; /* We know this is !=0 */ ND_PRINT("\n\t MD Name Format %s (%u), MD Name length %u", tok2str(cfm_md_nameformat_values, "Unknown", md_nameformat), md_nameformat, md_namelength); /* * -3 for the MA short name format and length and one byte * of MA short name. */ if (md_namelength > names_data_remaining - 3) { ND_PRINT(" (too large, must be <= %u)", names_data_remaining - 2); return; } md_name = namesp; ND_PRINT("\n\t MD Name: "); switch (md_nameformat) { case CFM_CCM_MD_FORMAT_DNS: case CFM_CCM_MD_FORMAT_CHAR: nd_printjnp(ndo, md_name, md_namelength); break; case CFM_CCM_MD_FORMAT_MAC: if (md_namelength == MAC_ADDR_LEN) { ND_PRINT("\n\t MAC %s", GET_ETHERADDR_STRING(md_name)); } else { ND_PRINT("\n\t MAC (length invalid)"); } break; /* FIXME add printers for those MD formats - hexdump for now */ case CFM_CCM_MA_FORMAT_8021: default: print_unknown_data(ndo, md_name, "\n\t ", md_namelength); } namesp += md_namelength; names_data_remaining -= md_namelength; } else { ND_PRINT("\n\t MD Name Format %s (%u)", tok2str(cfm_md_nameformat_values, "Unknown", md_nameformat), md_nameformat); } /* * Resolve the MA fields. */ ma_nameformat = GET_U_1(namesp); namesp++; names_data_remaining--; /* We know this is != 0 */ ma_namelength = GET_U_1(namesp); namesp++; names_data_remaining--; /* We know this is != 0 */ ND_PRINT("\n\t MA Name-Format %s (%u), MA name length %u", tok2str(cfm_ma_nameformat_values, "Unknown", ma_nameformat), ma_nameformat, ma_namelength); if (ma_namelength > names_data_remaining) { ND_PRINT(" (too large, must be <= %u)", names_data_remaining); return; } ma_name = namesp; ND_PRINT("\n\t MA Name: "); switch (ma_nameformat) { case CFM_CCM_MA_FORMAT_CHAR: nd_printjnp(ndo, ma_name, ma_namelength); break; /* FIXME add printers for those MA formats - hexdump for now */ case CFM_CCM_MA_FORMAT_8021: case CFM_CCM_MA_FORMAT_VID: case CFM_CCM_MA_FORMAT_INT: case CFM_CCM_MA_FORMAT_VPN: default: print_unknown_data(ndo, ma_name, "\n\t ", ma_namelength); } break; case CFM_OPCODE_LTM: msg_ptr.cfm_ltm = (const struct cfm_ltm_t *)tptr; if (first_tlv_offset < sizeof(*msg_ptr.cfm_ltm)) { ND_PRINT(" (too small 4, must be >= %zu)", sizeof(*msg_ptr.cfm_ltm)); return; } if (tlen < sizeof(*msg_ptr.cfm_ltm)) goto tooshort; ND_TCHECK_SIZE(msg_ptr.cfm_ltm); ND_PRINT(", Flags [%s]", bittok2str(cfm_ltm_flag_values, "none", flags)); ND_PRINT("\n\t Transaction-ID 0x%08x, ttl %u", GET_BE_U_4(msg_ptr.cfm_ltm->transaction_id), GET_U_1(msg_ptr.cfm_ltm->ttl)); ND_PRINT("\n\t Original-MAC %s, Target-MAC %s", GET_ETHERADDR_STRING(msg_ptr.cfm_ltm->original_mac), GET_ETHERADDR_STRING(msg_ptr.cfm_ltm->target_mac)); break; case CFM_OPCODE_LTR: msg_ptr.cfm_ltr = (const struct cfm_ltr_t *)tptr; if (first_tlv_offset < sizeof(*msg_ptr.cfm_ltr)) { ND_PRINT(" (too small 5, must be >= %zu)", sizeof(*msg_ptr.cfm_ltr)); return; } if (tlen < sizeof(*msg_ptr.cfm_ltr)) goto tooshort; ND_TCHECK_SIZE(msg_ptr.cfm_ltr); ND_PRINT(", Flags [%s]", bittok2str(cfm_ltr_flag_values, "none", flags)); ND_PRINT("\n\t Transaction-ID 0x%08x, ttl %u", GET_BE_U_4(msg_ptr.cfm_ltr->transaction_id), GET_U_1(msg_ptr.cfm_ltr->ttl)); ND_PRINT("\n\t Replay-Action %s (%u)", tok2str(cfm_ltr_replay_action_values, "Unknown", GET_U_1(msg_ptr.cfm_ltr->replay_action)), GET_U_1(msg_ptr.cfm_ltr->replay_action)); break; /* * No message decoder yet. * Hexdump everything up until the start of the TLVs */ case CFM_OPCODE_LBR: case CFM_OPCODE_LBM: default: print_unknown_data(ndo, tptr, "\n\t ", tlen - first_tlv_offset); break; } tptr += first_tlv_offset; tlen -= first_tlv_offset; while (tlen > 0) { cfm_tlv_header = (const struct cfm_tlv_header_t *)tptr; /* Enough to read the tlv type ? */ cfm_tlv_type = GET_U_1(cfm_tlv_header->type); ND_PRINT("\n\t%s TLV (0x%02x)", tok2str(cfm_tlv_values, "Unknown", cfm_tlv_type), cfm_tlv_type); if (cfm_tlv_type == CFM_TLV_END) { /* Length is "Not present if the Type field is 0." */ return; } /* do we have the full tlv header ? */ if (tlen < sizeof(struct cfm_tlv_header_t)) goto tooshort; ND_TCHECK_LEN(tptr, sizeof(struct cfm_tlv_header_t)); cfm_tlv_len=GET_BE_U_2(cfm_tlv_header->length); ND_PRINT(", length %u", cfm_tlv_len); tptr += sizeof(struct cfm_tlv_header_t); tlen -= sizeof(struct cfm_tlv_header_t); tlv_ptr = tptr; /* do we have the full tlv ? */ if (tlen < cfm_tlv_len) goto tooshort; ND_TCHECK_LEN(tptr, cfm_tlv_len); hexdump = FALSE; switch(cfm_tlv_type) { case CFM_TLV_PORT_STATUS: if (cfm_tlv_len < 1) { ND_PRINT(" (too short, must be >= 1)"); return; } ND_PRINT(", Status: %s (%u)", tok2str(cfm_tlv_port_status_values, "Unknown", GET_U_1(tptr)), GET_U_1(tptr)); break; case CFM_TLV_INTERFACE_STATUS: if (cfm_tlv_len < 1) { ND_PRINT(" (too short, must be >= 1)"); return; } ND_PRINT(", Status: %s (%u)", tok2str(cfm_tlv_interface_status_values, "Unknown", GET_U_1(tptr)), GET_U_1(tptr)); break; case CFM_TLV_PRIVATE: if (cfm_tlv_len < 4) { ND_PRINT(" (too short, must be >= 4)"); return; } ND_PRINT(", Vendor: %s (%u), Sub-Type %u", tok2str(oui_values,"Unknown", GET_BE_U_3(tptr)), GET_BE_U_3(tptr), GET_U_1(tptr + 3)); hexdump = TRUE; break; case CFM_TLV_SENDER_ID: { u_int chassis_id_type, chassis_id_length; u_int mgmt_addr_length; if (cfm_tlv_len < 1) { ND_PRINT(" (too short, must be >= 1)"); goto next_tlv; } /* * Get the Chassis ID length and check it. * IEEE 802.1Q-2014 Section 21.5.3.1 */ chassis_id_length = GET_U_1(tptr); tptr++; tlen--; cfm_tlv_len--; if (chassis_id_length) { /* * IEEE 802.1Q-2014 Section 21.5.3.2: Chassis ID Subtype, references * IEEE 802.1AB-2005 Section 9.5.2.2, subsequently * IEEE 802.1AB-2016 Section 8.5.2.2: chassis ID subtype */ if (cfm_tlv_len < 1) { ND_PRINT("\n\t (TLV too short)"); goto next_tlv; } chassis_id_type = GET_U_1(tptr); cfm_tlv_len--; ND_PRINT("\n\t Chassis-ID Type %s (%u), Chassis-ID length %u", tok2str(cfm_tlv_senderid_chassisid_values, "Unknown", chassis_id_type), chassis_id_type, chassis_id_length); if (cfm_tlv_len < chassis_id_length) { ND_PRINT("\n\t (TLV too short)"); goto next_tlv; } /* IEEE 802.1Q-2014 Section 21.5.3.3: Chassis ID */ switch (chassis_id_type) { case CFM_CHASSIS_ID_MAC_ADDRESS: if (chassis_id_length != MAC_ADDR_LEN) { ND_PRINT(" (invalid MAC address length)"); hexdump = TRUE; break; } ND_PRINT("\n\t MAC %s", GET_ETHERADDR_STRING(tptr + 1)); break; case CFM_CHASSIS_ID_NETWORK_ADDRESS: hexdump |= cfm_network_addr_print(ndo, tptr + 1, chassis_id_length); break; case CFM_CHASSIS_ID_INTERFACE_NAME: /* fall through */ case CFM_CHASSIS_ID_INTERFACE_ALIAS: case CFM_CHASSIS_ID_LOCAL: case CFM_CHASSIS_ID_CHASSIS_COMPONENT: case CFM_CHASSIS_ID_PORT_COMPONENT: nd_printjnp(ndo, tptr + 1, chassis_id_length); break; default: hexdump = TRUE; break; } cfm_tlv_len -= chassis_id_length; tptr += 1 + chassis_id_length; tlen -= 1 + chassis_id_length; } /* * Check if there is a Management Address. * IEEE 802.1Q-2014 Section 21.5.3.4: Management Address Domain Length * This and all subsequent fields are not present if the TLV length * allows only the above fields. */ if (cfm_tlv_len == 0) { /* No, there isn't; we're done. */ break; } /* Here mgmt_addr_length stands for the management domain length. */ mgmt_addr_length = GET_U_1(tptr); tptr++; tlen--; cfm_tlv_len--; ND_PRINT("\n\t Management Address Domain Length %u", mgmt_addr_length); if (mgmt_addr_length) { /* IEEE 802.1Q-2014 Section 21.5.3.5: Management Address Domain */ if (cfm_tlv_len < mgmt_addr_length) { ND_PRINT("\n\t (TLV too short)"); goto next_tlv; } cfm_tlv_len -= mgmt_addr_length; /* * XXX - this is an OID; print it as such. */ hex_print(ndo, "\n\t Management Address Domain: ", tptr, mgmt_addr_length); tptr += mgmt_addr_length; tlen -= mgmt_addr_length; /* * IEEE 802.1Q-2014 Section 21.5.3.6: Management Address Length * This field is present if Management Address Domain Length is not 0. */ if (cfm_tlv_len < 1) { ND_PRINT(" (Management Address Length is missing)"); hexdump = TRUE; break; } /* Here mgmt_addr_length stands for the management address length. */ mgmt_addr_length = GET_U_1(tptr); tptr++; tlen--; cfm_tlv_len--; ND_PRINT("\n\t Management Address Length %u", mgmt_addr_length); if (mgmt_addr_length) { /* IEEE 802.1Q-2014 Section 21.5.3.7: Management Address */ if (cfm_tlv_len < mgmt_addr_length) { ND_PRINT("\n\t (TLV too short)"); return; } cfm_tlv_len -= mgmt_addr_length; /* * XXX - this is a TransportDomain; print it as such. */ hex_print(ndo, "\n\t Management Address: ", tptr, mgmt_addr_length); tptr += mgmt_addr_length; tlen -= mgmt_addr_length; } } break; } /* * FIXME those are the defined TLVs that lack a decoder * you are welcome to contribute code ;-) */ case CFM_TLV_DATA: case CFM_TLV_REPLY_INGRESS: case CFM_TLV_REPLY_EGRESS: default: hexdump = TRUE; break; } /* do we want to see an additional hexdump ? */ if (hexdump || ndo->ndo_vflag > 1) print_unknown_data(ndo, tlv_ptr, "\n\t ", cfm_tlv_len); next_tlv: tptr+=cfm_tlv_len; tlen-=cfm_tlv_len; } return; tooshort: ND_PRINT("\n\t\t packet is too short"); return; trunc: nd_print_trunc(ndo); } tcpdump-4.99.1/print-syslog.c0000644000026300017510000001037514057477734014263 0ustar mcrmcr/* * Copyright (c) 1998-2004 Hannes Gredler * The TCPDUMP project * * 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, and (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. * 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. */ /* \summary: Syslog protocol printer */ /* specification: RFC 3164 (not RFC 5424) */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" #include "extract.h" /* * tokenlists and #defines taken from Ethereal - Network traffic analyzer * by Gerald Combs */ #define SYSLOG_SEVERITY_MASK 0x0007 /* 0000 0000 0000 0111 */ #define SYSLOG_FACILITY_MASK 0x03f8 /* 0000 0011 1111 1000 */ #define SYSLOG_MAX_DIGITS 3 /* The maximum number of priority digits to read in. */ static const struct tok syslog_severity_values[] = { { 0, "emergency" }, { 1, "alert" }, { 2, "critical" }, { 3, "error" }, { 4, "warning" }, { 5, "notice" }, { 6, "info" }, { 7, "debug" }, { 0, NULL }, }; static const struct tok syslog_facility_values[] = { { 0, "kernel" }, { 1, "user" }, { 2, "mail" }, { 3, "daemon" }, { 4, "auth" }, { 5, "syslog" }, { 6, "lpr" }, { 7, "news" }, { 8, "uucp" }, { 9, "cron" }, { 10, "authpriv" }, { 11, "ftp" }, { 12, "ntp" }, { 13, "security" }, { 14, "console" }, { 15, "cron" }, { 16, "local0" }, { 17, "local1" }, { 18, "local2" }, { 19, "local3" }, { 20, "local4" }, { 21, "local5" }, { 22, "local6" }, { 23, "local7" }, { 0, NULL }, }; void syslog_print(netdissect_options *ndo, const u_char *pptr, u_int len) { uint16_t msg_off = 0; uint16_t pri = 0; uint16_t facility,severity; ndo->ndo_protocol = "syslog"; /* extract decimal figures that are * encapsulated within < > tags * based on this decimal figure extract the * severity and facility values */ if (GET_U_1(pptr) != '<') goto invalid; msg_off++; while (msg_off <= SYSLOG_MAX_DIGITS && GET_U_1(pptr + msg_off) >= '0' && GET_U_1(pptr + msg_off) <= '9') { pri = pri * 10 + (GET_U_1(pptr + msg_off) - '0'); msg_off++; } if (GET_U_1(pptr + msg_off) != '>') goto invalid; msg_off++; facility = (pri & SYSLOG_FACILITY_MASK) >> 3; severity = pri & SYSLOG_SEVERITY_MASK; if (ndo->ndo_vflag < 1 ) { ND_PRINT("SYSLOG %s.%s, length: %u", tok2str(syslog_facility_values, "unknown (%u)", facility), tok2str(syslog_severity_values, "unknown (%u)", severity), len); return; } ND_PRINT("SYSLOG, length: %u\n\tFacility %s (%u), Severity %s (%u)\n\tMsg: ", len, tok2str(syslog_facility_values, "unknown (%u)", facility), facility, tok2str(syslog_severity_values, "unknown (%u)", severity), severity); /* print the syslog text in verbose mode */ /* * RFC 3164 Section 4.1.3: "There is no ending delimiter to this part. * The MSG part of the syslog packet MUST contain visible (printing) * characters." * * RFC 5424 Section 8.2: "This document does not impose any mandatory * restrictions on the MSG or PARAM-VALUE content. As such, they MAY * contain control characters, including the NUL character." * * Hence, to aid in protocol debugging, print the full MSG without * beautification to make it clear what was transmitted on the wire. */ if (len > msg_off) (void)nd_printn(ndo, pptr + msg_off, len - msg_off, NULL); if (ndo->ndo_vflag > 1) print_unknown_data(ndo, pptr, "\n\t", len); return; invalid: nd_print_invalid(ndo); } tcpdump-4.99.1/print-sip.c0000644000026300017510000000245214057477727013535 0ustar mcrmcr/* * 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, and (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. * 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. * * Original code by Hannes Gredler (hannes@gredler.at) * Turned into common "text protocol" code, which this uses, by * Guy Harris. */ /* \summary: Session Initiation Protocol (SIP) printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" static const char *sipcmds[] = { "ACK", "BYE", "CANCEL", "DO", "INFO", "INVITE", "MESSAGE", "NOTIFY", "OPTIONS", "PRACK", "QAUTH", "REFER", "REGISTER", "SPRACK", "SUBSCRIBE", "UPDATE", "PUBLISH", NULL }; void sip_print(netdissect_options *ndo, const u_char *pptr, u_int len) { ndo->ndo_protocol = "sip"; txtproto_print(ndo, pptr, len, sipcmds, RESP_CODE_SECOND_TOKEN); } tcpdump-4.99.1/fptype.h0000644000026300017510000000352614057477727013127 0ustar mcrmcr/* * Copyright (c) 1982, 1986, 1993 * 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 the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ extern void float_type_check(uint32_t); tcpdump-4.99.1/l2vpn.c0000644000026300017510000000656614057477727012663 0ustar mcrmcr/* * 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, and (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. * 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. * * Original code by Hannes Gredler (hannes@gredler.at) */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" #include "l2vpn.h" /* * BGP Layer 2 Encapsulation Types * * RFC 6624 * * https://www.iana.org/assignments/bgp-parameters/bgp-parameters.xhtml#bgp-l2-encapsulation-types-registry */ const struct tok l2vpn_encaps_values[] = { { 0, "Reserved"}, { 1, "Frame Relay"}, { 2, "ATM AAL5 SDU VCC transport"}, { 3, "ATM transparent cell transport"}, { 4, "Ethernet (VLAN) Tagged Mode"}, { 5, "Ethernet Raw Mode"}, { 6, "Cisco HDLC"}, { 7, "PPP"}, { 8, "SONET/SDH Circuit Emulation Service over MPLS"}, { 9, "ATM n-to-one VCC cell transport"}, { 10, "ATM n-to-one VPC cell transport"}, { 11, "IP layer 2 transport"}, { 15, "Frame Relay Port mode"}, { 17, "Structure-agnostic E1 over packet"}, { 18, "Structure-agnostic T1 (DS1) over packet"}, { 19, "VPLS"}, { 20, "Structure-agnostic T3 (DS3) over packet"}, { 21, "Nx64kbit/s Basic Service using Structure-aware"}, { 25, "Frame Relay DLCI"}, { 40, "Structure-agnostic E3 over packet"}, { 41, "Octet-aligned playload for Structure-agnostic DS1 circuits"}, { 42, "E1 Nx64kbit/s with CAS using Structure-aware"}, { 43, "DS1 (ESF) Nx64kbit/s with CAS using Structure-aware"}, { 44, "DS1 (SF) Nx64kbit/s with CAS using Structure-aware"}, { 0, NULL} }; /* * MPLS Pseudowire Types * * RFC 4446 * * https://www.iana.org/assignments/pwe3-parameters/pwe3-parameters.xhtml#pwe3-parameters-2 */ const struct tok mpls_pw_types_values[] = { { 0x0000, "Reserved"}, { 0x0001, "Frame Relay DLCI (Martini Mode)"}, { 0x0002, "ATM AAL5 SDU VCC transport"}, { 0x0003, "ATM transparent cell transport"}, { 0x0004, "Ethernet VLAN"}, { 0x0005, "Ethernet"}, { 0x0006, "Cisco-HDLC"}, { 0x0007, "PPP"}, { 0x0008, "SONET/SDH Circuit Emulation Service over MPLS"}, { 0x0009, "ATM n-to-one VCC cell transport"}, { 0x000a, "ATM n-to-one VPC cell transport"}, { 0x000b, "IP Layer2 Transport"}, { 0x000c, "ATM one-to-one VCC Cell Mode"}, { 0x000d, "ATM one-to-one VPC Cell Mode"}, { 0x000e, "ATM AAL5 PDU VCC transport"}, { 0x000f, "Frame-Relay Port mode"}, { 0x0010, "SONET/SDH Circuit Emulation over Packet"}, { 0x0011, "Structure-agnostic E1 over Packet"}, { 0x0012, "Structure-agnostic T1 (DS1) over Packet"}, { 0x0013, "Structure-agnostic E3 over Packet"}, { 0x0014, "Structure-agnostic T3 (DS3) over Packet"}, { 0x0015, "CESoPSN basic mode"}, { 0x0016, "TDMoIP basic mode"}, { 0x0017, "CESoPSN TDM with CAS"}, { 0x0018, "TDMoIP TDM with CAS"}, { 0x0019, "Frame Relay DLCI"}, { 0x0040, "IP-interworking"}, { 0, NULL} }; tcpdump-4.99.1/print-ip-demux.c0000644000026300017510000001233414057477727014472 0ustar mcrmcr/* * Copyright (c) 1988, 1989, 1990, 1991, 1992, 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. */ /* \summary: IPv4/IPv6 payload printer */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #include "netdissect.h" #include "addrtoname.h" #include "extract.h" #include "ip.h" #include "ipproto.h" void ip_demux_print(netdissect_options *ndo, const u_char *bp, u_int length, u_int ver, int fragmented, u_int ttl_hl, uint8_t nh, const u_char *iph) { int advance; const char *p_name; advance = 0; again: switch (nh) { case IPPROTO_AH: if (!ND_TTEST_1(bp)) { ndo->ndo_protocol = "ah"; nd_print_trunc(ndo); break; } nh = GET_U_1(bp); advance = ah_print(ndo, bp); if (advance <= 0) break; bp += advance; length -= advance; goto again; case IPPROTO_ESP: { esp_print(ndo, bp, length, iph, ver, fragmented, ttl_hl); /* * Either this has decrypted the payload and * printed it, in which case there's nothing more * to do, or it hasn't, in which case there's * nothing more to do. */ break; } case IPPROTO_IPCOMP: { ipcomp_print(ndo, bp); /* * Either this has decompressed the payload and * printed it, in which case there's nothing more * to do, or it hasn't, in which case there's * nothing more to do. */ break; } case IPPROTO_SCTP: sctp_print(ndo, bp, iph, length); break; case IPPROTO_DCCP: dccp_print(ndo, bp, iph, length); break; case IPPROTO_TCP: tcp_print(ndo, bp, length, iph, fragmented); break; case IPPROTO_UDP: udp_print(ndo, bp, length, iph, fragmented, ttl_hl); break; case IPPROTO_ICMP: if (ver == 4) icmp_print(ndo, bp, length, iph, fragmented); else { ND_PRINT("[%s requires IPv4]", tok2str(ipproto_values,"unknown",nh)); nd_print_invalid(ndo); } break; case IPPROTO_ICMPV6: if (ver == 6) icmp6_print(ndo, bp, length, iph, fragmented); else { ND_PRINT("[%s requires IPv6]", tok2str(ipproto_values,"unknown",nh)); nd_print_invalid(ndo); } break; case IPPROTO_PIGP: /* * XXX - the current IANA protocol number assignments * page lists 9 as "any private interior gateway * (used by Cisco for their IGRP)" and 88 as * "EIGRP" from Cisco. * * Recent BSD headers define * IP_PROTO_PIGP as 9 and IP_PROTO_IGRP as 88. * We define IP_PROTO_PIGP as 9 and * IP_PROTO_EIGRP as 88; those names better * match was the current protocol number * assignments say. */ igrp_print(ndo, bp, length); break; case IPPROTO_EIGRP: eigrp_print(ndo, bp, length); break; case IPPROTO_ND: ND_PRINT(" nd %u", length); break; case IPPROTO_EGP: egp_print(ndo, bp, length); break; case IPPROTO_OSPF: if (ver == 6) ospf6_print(ndo, bp, length); else ospf_print(ndo, bp, length, iph); break; case IPPROTO_IGMP: if (ver == 4) igmp_print(ndo, bp, length); else { ND_PRINT("[%s requires IPv4]", tok2str(ipproto_values,"unknown",nh)); nd_print_invalid(ndo); } break; case IPPROTO_IPV4: /* ipv4-in-ip encapsulation */ ip_print(ndo, bp, length); break; case IPPROTO_IPV6: /* ip6-in-ip encapsulation */ ip6_print(ndo, bp, length); break; case IPPROTO_RSVP: rsvp_print(ndo, bp, length); break; case IPPROTO_GRE: gre_print(ndo, bp, length); break; case IPPROTO_MOBILE: mobile_print(ndo, bp, length); break; case IPPROTO_PIM: pim_print(ndo, bp, length, iph); break; case IPPROTO_VRRP: if (ndo->ndo_packettype == PT_CARP) { carp_print(ndo, bp, length, ttl_hl); } else { vrrp_print(ndo, bp, length, iph, ttl_hl); } break; case IPPROTO_PGM: pgm_print(ndo, bp, length, iph); break; case IPPROTO_ETHERNET: if (ver == 6) ether_print(ndo, bp, length, ND_BYTES_AVAILABLE_AFTER(bp), NULL, NULL); else { ND_PRINT("[%s requires IPv6]", tok2str(ipproto_values,"unknown",nh)); nd_print_invalid(ndo); } break; case IPPROTO_NONE: ND_PRINT("no next header"); break; default: if (ndo->ndo_nflag==0 && (p_name = netdb_protoname(nh)) != NULL) ND_PRINT(" %s", p_name); else ND_PRINT(" ip-proto-%u", nh); ND_PRINT(" %u", length); break; } } tcpdump-4.99.1/print-udld.c0000644000026300017510000001346314057477734013674 0ustar mcrmcr/* * Copyright (c) 1998-2007 The TCPDUMP project * * 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, and (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. * 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. * * Original code by Carles Kishimoto */ /* \summary: Cisco UniDirectional Link Detection (UDLD) protocol printer */ /* specification: RFC 5171 */ #ifdef HAVE_CONFIG_H #include #endif #include "netdissect-stdinc.h" #define ND_LONGJMP_FROM_TCHECK #include "netdissect.h" #include "extract.h" #define UDLD_HEADER_LEN 4 #define UDLD_TLV_HEADER_LEN 4 #define UDLD_DEVICE_ID_TLV 0x0001 #define UDLD_PORT_ID_TLV 0x0002 #define UDLD_ECHO_TLV 0x0003 #define UDLD_MESSAGE_INTERVAL_TLV 0x0004 #define UDLD_TIMEOUT_INTERVAL_TLV 0x0005 #define UDLD_DEVICE_NAME_TLV 0x0006 #define UDLD_SEQ_NUMBER_TLV 0x0007 static const struct tok udld_tlv_values[] = { { UDLD_DEVICE_ID_TLV, "Device-ID TLV"}, { UDLD_PORT_ID_TLV, "Port-ID TLV"}, { UDLD_ECHO_TLV, "Echo TLV"}, { UDLD_MESSAGE_INTERVAL_TLV, "Message Interval TLV"}, { UDLD_TIMEOUT_INTERVAL_TLV, "Timeout Interval TLV"}, { UDLD_DEVICE_NAME_TLV, "Device Name TLV"}, { UDLD_SEQ_NUMBER_TLV,"Sequence Number TLV"}, { 0, NULL} }; static const struct tok udld_code_values[] = { { 0x00, "Reserved"}, { 0x01, "Probe message"}, { 0x02, "Echo message"}, { 0x03, "Flush message"}, { 0, NULL} }; static const struct tok udld_flags_bitmap_str[] = { { 1U << 0, "RT" }, { 1U << 1, "RSY" }, { 1U << 2, "MBZ-2" }, { 1U << 3, "MBZ-3" }, { 1U << 4, "MBZ-4" }, { 1U << 5, "MBZ-5" }, { 1U << 6, "MBZ-6" }, { 1U << 7, "MBZ-7" }, { 0, NULL} }; /* * UDLD's Protocol Data Unit format: * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Ver | Opcode | Flags | Checksum | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | List of TLVs (variable length list) | * | ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * TLV format: * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | TYPE | LENGTH | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | VALUE | * | ... | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * LENGTH: Length in bytes of the Type, Length, and Value fields. */ #define UDLD_EXTRACT_VERSION(x) (((x)&0xe0)>>5) #define UDLD_EXTRACT_OPCODE(x) ((x)&0x1f) void udld_print(netdissect_options *ndo, const u_char *tptr, u_int length) { uint8_t ver, code, flags; ndo->ndo_protocol = "udld"; if (length < UDLD_HEADER_LEN) goto invalid; ver = UDLD_EXTRACT_VERSION(GET_U_1(tptr)); code = UDLD_EXTRACT_OPCODE(GET_U_1(tptr)); tptr += 1; length -= 1; flags = GET_U_1(tptr); tptr += 1; length -= 1; ND_PRINT("UDLDv%u, Code %s (%x), Flags [%s] (0x%02x), length %u", ver, tok2str(udld_code_values, "Reserved", code), code, bittok2str(udld_flags_bitmap_str, "none", flags), flags, length + 2); /* * In non-verbose mode, just print version and opcode type */ if (ndo->ndo_vflag < 1) { goto tcheck_remainder; } ND_PRINT("\n\tChecksum 0x%04x (unverified)", GET_BE_U_2(tptr)); tptr += 2; length -= 2; while (length) { uint16_t type, len; if (length < UDLD_TLV_HEADER_LEN) goto invalid; type = GET_BE_U_2(tptr); tptr += 2; length -= 2; len = GET_BE_U_2(tptr); tptr += 2; length -= 2; ND_PRINT("\n\t%s (0x%04x) TLV, length %u", tok2str(udld_tlv_values, "Unknown", type), type, len); /* infinite loop check */ if (len <= UDLD_TLV_HEADER_LEN) goto invalid; len -= UDLD_TLV_HEADER_LEN; if (length < len) goto invalid; switch (type) { case UDLD_DEVICE_ID_TLV: case UDLD_PORT_ID_TLV: case UDLD_DEVICE_NAME_TLV: ND_PRINT(", "); nd_printjnp(ndo, tptr, len); break; case UDLD_ECHO_TLV: ND_PRINT(", "); (void)nd_printn(ndo, tptr, len, NULL); break; case UDLD_MESSAGE_INTERVAL_TLV: case UDLD_TIMEOUT_INTERVAL_TLV: if (len != 1) goto invalid; ND_PRINT(", %us", (GET_U_1(tptr))); break; case UDLD_SEQ_NUMBER_TLV: if (len != 4) goto invalid; ND_PRINT(", %u", GET_BE_U_4(tptr)); break; default: ND_TCHECK_LEN(tptr, len); break; } tptr += len; length -= len; } return; invalid: nd_print_invalid(ndo); tcheck_remainder: ND_TCHECK_LEN(tptr, length); } tcpdump-4.99.1/README.md0000644000026300017510000002165614057477727012732 0ustar mcrmcr# TCPDUMP 4.x.y by [The Tcpdump Group](https://www.tcpdump.org/) **To report a security issue please send an e-mail to security@tcpdump.org.** To report bugs and other problems, contribute patches, request a feature, provide generic feedback etc please see the [guidelines for contributing](CONTRIBUTING) in the tcpdump source tree root. Anonymous Git is available via https://github.com/the-tcpdump-group/tcpdump.git This directory contains source code for tcpdump, a tool for network monitoring and data acquisition. Over the past few years, tcpdump has been steadily improved by the excellent contributions from the Internet community (just browse through the [change log](CHANGES)). We are grateful for all the input. ### Supported platforms In many operating systems tcpdump is available as a native package or port, which simplifies installation of updates and long-term maintenance. However, the native packages are sometimes a few versions behind and to try a more recent snapshot it will take to compile tcpdump from the source code. tcpdump compiles and works on at least the following platforms: * AIX * DragonFly BSD * FreeBSD * Haiku * HP-UX 11i * GNU/Linux * {Mac} OS X / macOS * NetBSD * OpenBSD * OpenWrt * Solaris * Windows (requires WinPcap or Npcap, and Visual Studio with CMake) ### Dependency on libpcap Tcpdump uses libpcap, a system-independent interface for user-level packet capture. Before building tcpdump, you must first retrieve and build libpcap. Once libpcap is built (either install it or make sure it's in `../libpcap`), you can build tcpdump using the procedure in the [installation guide](INSTALL.txt). ### Origins of tcpdump The program is loosely based on SMI's "etherfind" although none of the etherfind code remains. It was originally written by Van Jacobson as part of an ongoing research project to investigate and improve TCP and Internet gateway performance. The parts of the program originally taken from Sun's etherfind were later re-written by Steven McCanne of LBL. To insure that there would be no vestige of proprietary code in tcpdump, Steve wrote these pieces from the specification given by the manual entry, with no access to the source of tcpdump or etherfind. ```text formerly from Lawrence Berkeley National Laboratory Network Research Group ftp://ftp.ee.lbl.gov/old/tcpdump.tar.Z (3.4) ``` ### See also Richard Stevens gives an excellent treatment of the Internet protocols in his book *"TCP/IP Illustrated, Volume 1"*. If you want to learn more about tcpdump and how to interpret its output, pick up this book. Another tool that tcpdump users might find useful is [tcpslice](https://github.com/the-tcpdump-group/tcpslice). It is a program that can be used to extract portions of tcpdump binary trace files. ### The original LBL README by Steve McCanne, Craig Leres and Van Jacobson ``` This directory also contains some short awk programs intended as examples of ways to reduce tcpdump data when you're tracking particular network problems: send-ack.awk Simplifies the tcpdump trace for an ftp (or other unidirectional tcp transfer). Since we assume that one host only sends and the other only acks, all address information is left off and we just note if the packet is a "send" or an "ack". There is one output line per line of the original trace. Field 1 is the packet time in decimal seconds, relative to the start of the conversation. Field 2 is delta-time from last packet. Field 3 is packet type/direction. "Send" means data going from sender to receiver, "ack" means an ack going from the receiver to the sender. A preceding "*" indicates that the data is a retransmission. A preceding "-" indicates a hole in the sequence space (i.e., missing packet(s)), a "#" means an odd-size (not max seg size) packet. Field 4 has the packet flags (same format as raw trace). Field 5 is the sequence number (start seq. num for sender, next expected seq number for acks). The number in parens following an ack is the delta-time from the first send of the packet to the ack. A number in parens following a send is the delta-time from the first send of the packet to the current send (on duplicate packets only). Duplicate sends or acks have a number in square brackets showing the number of duplicates so far. Here is a short sample from near the start of an ftp: 3.00 0.20 send . 512 3.20 0.20 ack . 1024 (0.20) 3.20 0.00 send P 1024 3.40 0.20 ack . 1536 (0.20) 3.80 0.40 * send . 0 (3.80) [2] 3.82 0.02 * ack . 1536 (0.62) [2] Three seconds into the conversation, bytes 512 through 1023 were sent. 200ms later they were acked. Shortly thereafter bytes 1024-1535 were sent and again acked after 200ms. Then, for no apparent reason, 0-511 is retransmitted, 3.8 seconds after its initial send (the round trip time for this ftp was 1sec, +-500ms). Since the receiver is expecting 1536, 1536 is re-acked when 0 arrives. packetdat.awk Computes chunk summary data for an ftp (or similar unidirectional tcp transfer). [A "chunk" refers to a chunk of the sequence space -- essentially the packet sequence number divided by the max segment size.] A summary line is printed showing the number of chunks, the number of packets it took to send that many chunks (if there are no lost or duplicated packets, the number of packets should equal the number of chunks) and the number of acks. Following the summary line is one line of information per chunk. The line contains eight fields: 1 - the chunk number 2 - the start sequence number for this chunk 3 - time of first send 4 - time of last send 5 - time of first ack 6 - time of last ack 7 - number of times chunk was sent 8 - number of times chunk was acked (all times are in decimal seconds, relative to the start of the conversation.) As an example, here is the first part of the output for an ftp trace: # 134 chunks. 536 packets sent. 508 acks. 1 1 0.00 5.80 0.20 0.20 4 1 2 513 0.28 6.20 0.40 0.40 4 1 3 1025 1.16 6.32 1.20 1.20 4 1 4 1561 1.86 15.00 2.00 2.00 6 1 5 2049 2.16 15.44 2.20 2.20 5 1 6 2585 2.64 16.44 2.80 2.80 5 1 7 3073 3.00 16.66 3.20 3.20 4 1 8 3609 3.20 17.24 3.40 5.82 4 11 9 4097 6.02 6.58 6.20 6.80 2 5 This says that 134 chunks were transferred (about 70K since the average packet size was 512 bytes). It took 536 packets to transfer the data (i.e., on the average each chunk was transmitted four times). Looking at, say, chunk 4, we see it represents the 512 bytes of sequence space from 1561 to 2048. It was first sent 1.86 seconds into the conversation. It was last sent 15 seconds into the conversation and was sent a total of 6 times (i.e., it was retransmitted every 2 seconds on the average). It was acked once, 140ms after it first arrived. stime.awk atime.awk Output one line per send or ack, respectively, in the form