浏览代码

Se agrega hook

Espinoza Guillermo 6 年之前
父节点
当前提交
94e363fefb

+ 27 - 0
hooks/kea-cm-hook/Makefile

@@ -0,0 +1,27 @@
+
+KEA_MSG_COMPILER ?= /opt/kea/bin/kea-msg-compiler
+KEA_INCLUDE ?= ~/kea-1.3.0/src/lib
+KEA_LIB ?= /opt/kea/lib/
+
+OBJECTS = src/messages.o src/logger.o src/load.o src/callouts.o src/version.o
+DEPS = $(OBJECTS:.o=.d)
+CXXFLAGS = -I $(KEA_INCLUDE) -g -fPIC -Wno-deprecated -std=c++11
+LDFLAGS = -L $(KEA_LIB) -shared -lkea-dhcpsrv -lkea-dhcp++ -lkea-hooks -lkea-log -lkea-util -lkea-exceptions
+
+kea-hook-flowdat.so: $(OBJECTS)
+	$(CXX) -o $@ $(CXXFLAGS) $(LDFLAGS) $(OBJECTS)
+
+%.o: %.cc
+	$(CXX) -MMD -MP -c $(CXXFLAGS) -o $@ $<
+
+# Compile messages (for logging)
+src/messages.h src/messages.cc: s-messages
+s-messages: src/messages.mes
+	$(KEA_MSG_COMPILER) -d src/ $<
+	touch $@
+
+clean:
+	rm -f src/*.o *.so
+	rm -f src/messages.h src/messages.cc s-messages
+
+-include $(DEPS)

+ 104 - 0
hooks/kea-cm-hook/kea4-dhcp.conf

@@ -0,0 +1,104 @@
+    {
+            "Dhcp4": {
+                "control-socket": {
+                    "socket-name": "/tmp/kea-dhcp4-ctrl.sock",
+                    "socket-type": "unix"
+                },
+                    "interfaces-config": {
+        "interfaces": [ "*" ]
+    },
+                "lease-database": {
+                    "lfc-interval": 3600,
+                    "type": "memfile"
+                },
+                "subnet4": [
+                    {
+                        "subnet": "10.42.0.0/16",
+                        "pools": [
+                            {
+                                "pool": "10.42.40.150 - 10.42.40.250"
+                            }
+                        ]
+                    },
+                    {
+                        "subnet": "10.72.0.0/16",
+                        "pools": [
+                            {
+                                "pool": "10.72.40.150 - 10.72.40.250"
+                            }
+                        ]
+                    },
+                    {
+                        "subnet": "10.62.0.0/16",
+                        "pools": [
+                            {
+                                "pool": "10.62.40.150 - 10.62.40.250"
+                            }
+                        ]
+                    },
+                    {
+                        "subnet": "10.65.0.0/16",
+                        "pools": [
+                            {
+                                "pool": "10.65.0.10 - 10.65.10.254"
+                            }
+                        ]
+                    }
+                ],
+                "hooks-libraries": [
+                    {
+                        "library": "/kea-cm-hook/kea-hook-flowdat.so",
+                        "parameters": {
+                            "option122": {
+                                "200.50.168.115": [
+                                    "0005ca9d1160",
+                                    "001311836bea",
+                                    "001cea29f3c4",
+                                    "001e46b6c800",
+                                    "00237406d524",
+                                    "0023746d0120",
+                                    "0023ed6734f5",
+                                    "008ef234ec20",
+                                    "5c571abff352",
+                                    "bc14014ff2b8",
+                                    "e83efce89f72"
+                                ]
+                            },
+                            "remote-id-map": {
+                                "active": [
+                                    "0005ca9d1160",
+                                    "001311836bea",
+                                    "001cea29f3c4",
+                                    "001e46b6c800",
+                                    "00237406d524",
+                                    "0023746d0120",
+                                    "0023ed6734f5",
+                                    "008ef234ec20",
+                                    "5c571abff352",
+                                    "bc14014ff2b8",
+                                    "e83efce89f72"
+                                ],
+                                "suspended": []
+                            }
+                        }
+                    }
+                ]
+            },
+            "Logging": {
+                "loggers": [
+                    {
+                        "debuglevel": 0,
+                        "name": "kea-dhcp4",
+                        "output_options": [
+                            {
+                                "flush": true,
+                                "maxsize": 10240000,
+                                "maxver": 1,
+                                "output": "/usr/local/var/log/kea-dhcp4.log"
+                            }
+                        ],
+                        "severity": "INFO"
+                    }
+                ]
+            }
+    }

+ 250 - 0
hooks/kea-cm-hook/src/callouts.cc

@@ -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"

+ 12 - 0
hooks/kea-cm-hook/src/common.h

@@ -0,0 +1,12 @@
+#include <string>
+#include <map>
+
+extern "C" {
+
+/* From load.cc */
+
+/* Maps of the cablemodem states */
+extern std::map<std::string, std::string> cm_map;
+extern std::map<std::string, std::string> option122_map;
+
+}

+ 99 - 0
hooks/kea-cm-hook/src/load.cc

@@ -0,0 +1,99 @@
+#include <hooks/hooks.h>
+#include <map>
+#include <boost/foreach.hpp>
+
+#include "logger.h"
+#include "common.h"
+
+
+using namespace isc::hooks;
+using namespace isc::data;
+
+std::map<std::string, std::string> cm_map;
+std::map<std::string, std::string> option122_map;
+
+extern "C" {
+
+int loadMappging(std::string base_map_config, LibraryHandle& handle, std::map<std::string, std::string>& map){
+
+    ConstElementPtr curr_map = handle.getParameter(base_map_config);
+    if (Element::map != curr_map->getType()){
+        LOG_ERROR(runscript_logger, RUNSCRIPT_MISTYPED_PARAM).arg(base_map_config);
+        return 1;
+    }
+
+    std::map<std::string, ConstElementPtr> map_config = curr_map->mapValue();;
+    std::pair<std::string, ConstElementPtr> me; 
+
+    BOOST_FOREACH(me, map_config) {
+	std::string class_to_map = me.first;
+	std::cout << me.first << "\n";
+	ConstElementPtr table = me.second;
+	if(table->getType() != Element::list){
+		LOG_ERROR(runscript_logger, RUNSCRIPT_MISTYPED_PARAM).arg(base_map_config + "." + me.first);
+		return 1;
+	} 
+	const std::vector<ElementPtr> mac_list = table->listValue();
+	for(int i = 0; i < mac_list.size(); i++) {
+		ElementPtr it = mac_list[i];
+		if(it->getType() != Element::string){
+			LOG_ERROR(runscript_logger, RUNSCRIPT_MISTYPED_PARAM).arg(base_map_config + "." + me.first + "[" + std::to_string(i) + "]");
+			return 1;
+		}
+		std::cout << mac_list[i]->stringValue() << "\n";
+		std::string mac = mac_list[i]->stringValue();
+		std::transform(mac.begin(), mac.end(),mac.begin(), ::toupper);
+
+		map[mac] = class_to_map;
+	}
+    }
+
+    return 0;
+}
+
+int load(LibraryHandle& handle) {
+
+
+    if(loadMappging("option122", handle, option122_map))
+	return 1;
+
+    if(loadMappging("remote-id-map", handle, cm_map))
+	return 1;
+   
+    //ConstElementPtr remote_id_map = handle.getParameter("remote-id-map");
+    //if (Element::map != remote_id_map->getType()){
+    //    LOG_ERROR(runscript_logger, RUNSCRIPT_MISTYPED_PARAM).arg("remote-id-map");
+    //    return 1;
+    //}
+
+    //std::map<std::string, ConstElementPtr> map_config = remote_id_map->mapValue();;
+    //std::pair<std::string, ConstElementPtr> me; 
+    //BOOST_FOREACH(me, map_config) {
+    //    std::string class_to_map = me.first;
+    //    std::cout << me.first << "\n";
+    //    ConstElementPtr table = me.second;
+    //    if(table->getType() != Element::list){
+    //    	LOG_ERROR(runscript_logger, RUNSCRIPT_MISTYPED_PARAM).arg("remote-id-map." + me.first);
+    //    	return 1;
+    //    } 
+    //    const std::vector<ElementPtr> mac_list = table->listValue();
+    //    for(int i = 0; i < mac_list.size(); i++) { 
+    //    	ElementPtr it = mac_list[i];
+    //    	if(it->getType() != Element::string){
+    //    		LOG_ERROR(runscript_logger, RUNSCRIPT_MISTYPED_PARAM).arg("remote-id-map." + me.first + "[" + std::to_string(i) + "]");
+    //    		return 1;
+    //    	}
+    //    	std::cout << mac_list[i]->stringValue() << "\n";
+    //    	std::string mac = mac_list[i]->stringValue();
+    //    	std::transform(mac.begin(), mac.end(),mac.begin(), ::toupper);
+
+    //    	cm_map[mac] = class_to_map;
+    //    }
+    //}
+
+    return 0;
+}
+
+
+
+} // end extern "C"

+ 3 - 0
hooks/kea-cm-hook/src/logger.cc

@@ -0,0 +1,3 @@
+#include "logger.h"
+
+isc::log::Logger runscript_logger("hook-ik-cablemodem");

+ 11 - 0
hooks/kea-cm-hook/src/logger.h

@@ -0,0 +1,11 @@
+#ifndef RUNSCRIPT_LOGGER_H
+#define RUNSCRIPT_LOGGER_H
+#include <log/logger.h>
+#include <log/message_initializer.h>
+#include <log/macros.h>
+
+#include "messages.h"
+
+extern isc::log::Logger runscript_logger;
+
+#endif

+ 30 - 0
hooks/kea-cm-hook/src/messages.mes

@@ -0,0 +1,30 @@
+% RUNSCRIPT_MISSING_PARAM required parameter "%1" missing in configuration
+A required parameter of this library hook is missing in the configuration,
+which prevents the library from working correctly.
+
+% RUNSCRIPT_MISTYPED_PARAM parameter "%1" in configuration has wrong type
+A parameter of this library hook is defined in the configuration but has the
+wrong type.  For instance, a string may have been passed as parameter while
+an integer was expected.
+
+% RUNSCRIPT_FORK_FAILED fork() failed with error: %1
+Running the user-defined script is done with fork + exec, and there was an error
+during the fork, possibly due to a lack of resources.
+
+% RUNSCRIPT_EXEC_FAILED exec() failed, please check that the script exists and is executable. Error: %1
+Attempting to execute the user-defined script failed.
+
+% RUNSCRIPT_WAITPID_FAILED waitpid() failed with error: %1
+The main hook process failed to wait for the child process to exit.
+The hook runs the user-defined script in a child process, and normally waits for it to exit.
+
+% RUNSCRIPT_WAITING_SCRIPT the user-defined script is running, and the main process is currently waiting
+The user-defined script has just been launched, and Kea is waiting for it to exit.
+This is useful to know, because if the user-defined script blocks, Kea will stay stuck
+at this point.
+
+% RUNSCRIPT_DEBUG_STRING %1
+Something somthing shomething
+
+% FLOWDAT_DEBUG_STRING %1
+Something somthing shomething

+ 7 - 0
hooks/kea-cm-hook/src/version.cc

@@ -0,0 +1,7 @@
+// version.cc
+#include <hooks/hooks.h>
+extern "C" {
+int version() {
+    return (KEA_HOOKS_VERSION);
+}
+}