#include #include #include #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 #include #include "mysql_connection.h" MySQLConnection conn; std::string getMacFromPacket(Pkt4Ptr); /** * 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(6,12); std::vector binary; isc::util::str::decodeFormattedHexString(rtr, binary); } 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()); } } return rtr; } 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->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("hwaddr: " + chwdr); LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("remoteid: "+opt82mac); if (chwdr == opt82mac) { rtr = CABLEMODEM; LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("option 82 mac == chwdr ==> CABLEMODEM"); } else { LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("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("Checking Vendor Class ID"); if (docsis_vendor_class.compare("docsis") == 0) { rtr = CABLEMODEM; LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("docsis en vendor class ==> CABLEMODEM"); } else { if (pktc_vendor_class.compare("pktc") == 0) { rtr = EMTA; LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("pktc en vendor class ==> EMTA"); } else { LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("vendor class unknown"); } } } else { LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("no vendor class"); } } } else { LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("Empty MAC fomr getMacFromPacket ==> CPE " + std::to_string(cm_mac.size())); if (pkt->isRelayed()) { LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("Pakcet Relayed"); } } return rtr; } /* IPv4 callouts */ int pkt4_receive(CalloutHandle& handle) { Pkt4Ptr query; handle.getArgument("query4", query); // Busco la class para la mac que viene en el paquete // en fd3_dhcp.host, si no existe el host cargado no tiene class std::string mac = getMacFromPacket(query); std::string MAC = mac; std::transform(mac.begin(), mac.end(), mac.begin(), ::tolower); std::string sql_query = "SELECT state FROM `host` WHERE `mac` LIKE '" + mac + "';"; std::string class_map = conn.executeQuery((sql_query).c_str()); if (class_map != "") { cm_map[MAC] = class_map; LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("cablemodem " + mac + " class " + class_map); } else { LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("cablemodem " + mac + " class not found "); } std::vector list_class; 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("class : " + me); BOOST_FOREACH(me2, list_class) { if (me.compare(me2) != 0) { LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("class : " + me + "-" + me2); query->addClass(me + "-" + me2); } } query->addClass(me); Host::IdentifierType type; std::vector id((me + "-" + mac).begin(), (me + "-" + mac).end()); type = Host::IDENT_FLEX; handle.setArgument("id_value", id); handle.setArgument("id_type", type); } 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("ht : " + std::to_string(ht)); if (ht == CABLEMODEM or ht == EMTA) { mac = getMacFromPacket(query); } if (ht == CABLEMODEM) { std::string file = mac + ".bin"; isc::util::str::lowercase(file); LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("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("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("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); } return 0; } // @TODO: Implementar para DHCPv6 /* IPv6 callouts */ int pkt6_receive(CalloutHandle& handle) { std::vector env; Pkt6Ptr query; handle.getArgument("query6", query); // std::string mac = getMacFromPacket(query); // std::string class_map = conn->executeQuery("SELECT state FROM fd3_dhcp.host WHERE mac=" + string(mac)); // cm_map[mac] = class_map; return 0; } } // end extern "C"