#include #include #include #include #include #include #include #include #include #include #include #include #include "logger.h" #include "common.h" using namespace isc::dhcp; using namespace isc::hooks; extern "C" { #include //inner_product #include //plus, equal_to, not2 #include #include std::string getMacFromPacket(Pkt4Ptr); enum HostType{ CABLEMODEM, EMTA, CPE}; std::string HostClass[] = { "cm", "mta", "cpe"}; HostType getHostType(Pkt4Ptr pkt) { HostType rtr = CPE; std::string cm_mac = getMacFromPacket(pkt); //Non Empty MAC if (cm_mac.size() != 0) { //std::string chwdr = pkt->getMAC(HWAddr::HWADDR_SOURCE_RAW)->toText(false); std::string chwdr = pkt->getHWAddr()->toText(false); isc::util::str::uppercase(chwdr); chwdr.erase(std::remove(chwdr.begin(), chwdr.end(), ':'), chwdr.end()); std::string opt82mac = ""; if (pkt->getOption(DHO_DHCP_AGENT_OPTIONS)) { opt82mac = pkt->getOption(DHO_DHCP_AGENT_OPTIONS)->toHexString(false).substr(6,12); std::vector binary; isc::util::str::decodeFormattedHexString(opt82mac, binary); } LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> hwaddr: " + chwdr); LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> remoteid: " + opt82mac); if (chwdr == opt82mac) { rtr = CABLEMODEM; LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> option 82 mac == chwdr ==> CABLEMODEM"); } else { LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> dou't " + chwdr + " !== " + opt82mac); if (pkt->getOption(DHO_VENDOR_CLASS_IDENTIFIER)) { std::string docsis_vendor_class = pkt->getOption(DHO_VENDOR_CLASS_IDENTIFIER)->toString().substr(0,6); std::string pktc_vendor_class = pkt->getOption(DHO_VENDOR_CLASS_IDENTIFIER)->toString().substr(0,4); LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> Checking Vendor Class ID"); if (docsis_vendor_class.compare("docsis") == 0) { rtr = CABLEMODEM; LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> docsis en vendor class ==> CABLEMODEM"); } else { if (pktc_vendor_class.compare("pktc") == 0) { rtr = EMTA; LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> pktc en vendor class ==> EMTA"); } else { LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> vendor class unknown"); } } } else { LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> no vendor class"); } } } else { LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> Empty MAC fomr getMacFromPacket ==> CPE " + std::to_string(cm_mac.size())); if (pkt->isRelayed()) { LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> Packet Relayed"); } //LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("HWAddr " + pkt->getMAC(HWAddr::HWADDR_SOURCE_ANY)->toText()); } return rtr; } /** * Get the cablemodem mac from (option 82) or if vendor_class is *docsis* get the c_hwaddr */ std::string getMacFromPacket(Pkt4Ptr pkt) { std::string rtr = ""; if (pkt->getOption(DHO_DHCP_AGENT_OPTIONS)) { //rtr = pkt->getOption(DHO_DHCP_AGENT_OPTIONS)->toHexString(false).substr(26,12); rtr = pkt->getOption(DHO_DHCP_AGENT_OPTIONS)->toHexString(false).substr(6,12); std::vector binary; isc::util::str::decodeFormattedHexString(rtr, binary); LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getMacFromPacket -> from option 82 " + rtr); } else if(pkt->getOption(DHO_VENDOR_CLASS_IDENTIFIER)) { std::string docsis_vendor_class = pkt->getOption(DHO_VENDOR_CLASS_IDENTIFIER)->toString().substr(2,6); if (docsis_vendor_class.compare("docsis") == 0) { rtr = pkt->getMAC(HWAddr::HWADDR_SOURCE_RAW)->toText(false); isc::util::str::uppercase(rtr); rtr.erase(std::remove(rtr.begin(), rtr.end(), ':'), rtr.end()); LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getMacFromPacket -> is vendor class 'docsis' chwaddr..." + rtr); } } return rtr; } /* IPv4 callouts */ int pkt4_receive(CalloutHandle& handle) { Pkt4Ptr query; handle.getArgument("query4", query); std::vector list_class; std::string mac = getMacFromPacket(query); HWAddrPtr remote_id; HostType ht = getHostType(query); list_class.push_back(HostClass[ht]); std::map::iterator it = cm_map.find(mac); if (it != cm_map.end()) { list_class.push_back(cm_map[mac]); } std::string me, me2; BOOST_FOREACH(me, list_class) { LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("pkt4_receive -> class : " + me); BOOST_FOREACH(me2, list_class) { if (me.compare(me2) != 0) { LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("pkt4_receive -> class : " + me + "-" + me2); query->addClass(me + "-" + me2); } } query->addClass(me); } return 0; } int pkt4_send(CalloutHandle& handle) { Pkt4Ptr response; Pkt4Ptr query; handle.getArgument("response4", response); handle.getArgument("query4", query); uint8_t ufile_name[128] = ""; std::string mac; HostType ht = getHostType(query); LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("pkt4_send -> HostType : " + std::to_string(ht)); if (ht == CABLEMODEM or ht == EMTA) { mac = getMacFromPacket(query); } //OptionStringPtr asc1(new OptionString(Option::V4, 43, "http://asc-test.org:7547/")); //OptionStringPtr asc2(new OptionString(Option::V4, 125, "http://asc-test.org:7547/")); // //response->addOption(asc1); //response->addOption(asc2); if (ht == CABLEMODEM) { std::string file = mac + ".bin"; isc::util::str::lowercase(file); LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("pkt4_send -> CM file : " + file); strcpy((char*)ufile_name, file.c_str()); response->setFile(ufile_name, strlen((char *)ufile_name)); std::map::iterator it = option122_map.find(mac); if (it != option122_map.end()) { LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("pkt4_send -> cablemodem " + mac + " found for MTA Activation on " + option122_map[mac]); OptionPtr option1(new Option(Option::V4, 122)); Option4AddrLstPtr opt_server(new Option4AddrLst(1)); opt_server->setAddress(isc::asiolink::IOAddress("255.255.255.255"));//option122_map[mac])); OptionStringPtr opt_basic1(new OptionString(Option::V4, 6, "BASIC.1")); option1->addOption(opt_server); option1->addOption(opt_basic1); response->addOption(option1); } else { LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("pkt4_send -> cablemodem " + mac + " not found for MTA Activation"); } } if (ht == EMTA) { std::string file = mac + ".mta.bin"; isc::util::str::lowercase(file); std::map::iterator it = option122_map.find(mac); if (it != option122_map.end()) { std::string file = mac + ".mta.bin"; isc::util::str::lowercase(file); LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("pkt4_send -> EMTA file : " + file); strcpy((char*)ufile_name, file.c_str()); response->setFile(ufile_name, strlen((char *)ufile_name)); isc::util::str::lowercase(mac); OptionStringPtr opt_domain(new OptionString(Option::V4, DHO_HOST_NAME, mac)); response->addOption(opt_domain); } } return 0; } } // end extern "C"