|
@@ -0,0 +1,250 @@
|
|
|
+#include <hooks/hooks.h>
|
|
|
+#include <dhcp/pkt4.h>
|
|
|
+#include <dhcp/hwaddr.h>
|
|
|
+#include <dhcpsrv/subnet.h>
|
|
|
+#include <dhcpsrv/lease.h>
|
|
|
+#include <util/strutil.h>
|
|
|
+#include <dhcp/option_string.h>
|
|
|
+#include <dhcp/option4_addrlst.h>
|
|
|
+#include <dhcp/docsis3_option_defs.h>
|
|
|
+#include <string>
|
|
|
+#include <vector>
|
|
|
+
|
|
|
+#include <boost/foreach.hpp>
|
|
|
+
|
|
|
+#include "logger.h"
|
|
|
+#include "common.h"
|
|
|
+
|
|
|
+using namespace isc::dhcp;
|
|
|
+using namespace isc::hooks;
|
|
|
+
|
|
|
+extern "C" {
|
|
|
+
|
|
|
+#include <numeric> //inner_product
|
|
|
+#include <functional> //plus, equal_to, not2
|
|
|
+#include <string>
|
|
|
+#include <stdexcept>
|
|
|
+
|
|
|
+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<uint8_t> 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");
|
|
|
+ }
|
|
|
+ //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<uint8_t> 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<std::string> list_class;
|
|
|
+
|
|
|
+
|
|
|
+ std::string mac = getMacFromPacket(query);
|
|
|
+ HWAddrPtr remote_id;
|
|
|
+
|
|
|
+ HostType ht = getHostType(query);
|
|
|
+
|
|
|
+ list_class.push_back(HostClass[ht]);
|
|
|
+ std::map<std::string,std::string>::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);
|
|
|
+ }
|
|
|
+
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+
|
|
|
+ //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("file : " + file);
|
|
|
+ strcpy((char*)ufile_name, file.c_str());
|
|
|
+ response->setFile(ufile_name, strlen((char *)ufile_name));
|
|
|
+
|
|
|
+ std::map<std::string,std::string>::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<std::string,std::string>::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("file : " + file);
|
|
|
+ // strcpy((char*)ufile_name, file.c_str());
|
|
|
+ // response->setFile(ufile_name, strlen((char *)ufile_name));
|
|
|
+ // response->setSiaddr(isc::asiolink::IOAddress(option122_map[mac]));
|
|
|
+
|
|
|
+ // OptionStringPtr tftp_server(new OptionString(Option::V4, DOCSIS3_V4_TFTP_SERVERS,option122_map[mac]));
|
|
|
+
|
|
|
+ // OptionPtr option1(new Option(Option::V4, 122));
|
|
|
+
|
|
|
+ // Option4AddrLstPtr opt_server(new Option4AddrLst(3)); //SubOption 1
|
|
|
+ // opt_server->setAddress(isc::asiolink::IOAddress(option122_map[mac]));
|
|
|
+
|
|
|
+
|
|
|
+ // OptionStringPtr opt_basic1(new OptionString(Option::V4, 6, "BASIC.1"));
|
|
|
+
|
|
|
+ // option1->addOption(opt_server);
|
|
|
+ // option1->addOption(opt_basic1);
|
|
|
+
|
|
|
+ // response->addOption(option1);
|
|
|
+
|
|
|
+
|
|
|
+ // response->addOption(tftp_server);
|
|
|
+
|
|
|
+ //}
|
|
|
+ }
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+} // end extern "C"
|