callouts.cc 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. #include <hooks/hooks.h>
  2. #include <dhcp/pkt4.h>
  3. #include <dhcp/hwaddr.h>
  4. #include <dhcpsrv/subnet.h>
  5. #include <dhcpsrv/lease.h>
  6. #include <util/strutil.h>
  7. #include <dhcp/option_string.h>
  8. #include <dhcp/option4_addrlst.h>
  9. #include <dhcp/docsis3_option_defs.h>
  10. #include <string>
  11. #include <vector>
  12. #include <boost/foreach.hpp>
  13. #include "logger.h"
  14. #include "common.h"
  15. using namespace isc::dhcp;
  16. using namespace isc::hooks;
  17. extern "C" {
  18. #include <numeric> //inner_product
  19. #include <functional> //plus, equal_to, not2
  20. #include <string>
  21. #include <stdexcept>
  22. std::string getMacFromPacket(Pkt4Ptr);
  23. enum HostType{ CABLEMODEM, EMTA, CPE};
  24. std::string HostClass[] = { "cm", "mta", "cpe"};
  25. HostType getHostType(Pkt4Ptr pkt)
  26. {
  27. HostType rtr = CPE;
  28. std::string cm_mac = getMacFromPacket(pkt);
  29. //Non Empty MAC
  30. if (cm_mac.size() != 0) {
  31. //std::string chwdr = pkt->getMAC(HWAddr::HWADDR_SOURCE_RAW)->toText(false);
  32. std::string chwdr = pkt->getHWAddr()->toText(false);
  33. isc::util::str::uppercase(chwdr);
  34. chwdr.erase(std::remove(chwdr.begin(), chwdr.end(), ':'), chwdr.end());
  35. std::string opt82mac = "";
  36. if (pkt->getOption(DHO_DHCP_AGENT_OPTIONS)) {
  37. opt82mac = pkt->getOption(DHO_DHCP_AGENT_OPTIONS)->toHexString(false).substr(6,12);
  38. std::vector<uint8_t> binary;
  39. isc::util::str::decodeFormattedHexString(opt82mac, binary);
  40. }
  41. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> hwaddr: " + chwdr);
  42. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> remoteid: " + opt82mac);
  43. if (chwdr == opt82mac) {
  44. rtr = CABLEMODEM;
  45. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> option 82 mac == chwdr ==> CABLEMODEM");
  46. } else {
  47. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> dou't " + chwdr + " !== " + opt82mac);
  48. if (pkt->getOption(DHO_VENDOR_CLASS_IDENTIFIER)) {
  49. std::string docsis_vendor_class = pkt->getOption(DHO_VENDOR_CLASS_IDENTIFIER)->toString().substr(0,6);
  50. std::string pktc_vendor_class = pkt->getOption(DHO_VENDOR_CLASS_IDENTIFIER)->toString().substr(0,4);
  51. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> Checking Vendor Class ID");
  52. if (docsis_vendor_class.compare("docsis") == 0) {
  53. rtr = CABLEMODEM;
  54. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> docsis en vendor class ==> CABLEMODEM");
  55. } else {
  56. if (pktc_vendor_class.compare("pktc") == 0) {
  57. rtr = EMTA;
  58. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> pktc en vendor class ==> EMTA");
  59. } else {
  60. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> vendor class unknown");
  61. }
  62. }
  63. } else {
  64. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> no vendor class");
  65. }
  66. }
  67. } else {
  68. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> Empty MAC fomr getMacFromPacket ==> CPE " + std::to_string(cm_mac.size()));
  69. if (pkt->isRelayed()) {
  70. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getHostType -> Packet Relayed");
  71. }
  72. //LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("HWAddr " + pkt->getMAC(HWAddr::HWADDR_SOURCE_ANY)->toText());
  73. }
  74. return rtr;
  75. }
  76. /**
  77. * Get the cablemodem mac from (option 82) or if vendor_class is *docsis* get the c_hwaddr
  78. */
  79. std::string getMacFromPacket(Pkt4Ptr pkt)
  80. {
  81. std::string rtr = "";
  82. if (pkt->getOption(DHO_DHCP_AGENT_OPTIONS)) {
  83. //rtr = pkt->getOption(DHO_DHCP_AGENT_OPTIONS)->toHexString(false).substr(26,12);
  84. rtr = pkt->getOption(DHO_DHCP_AGENT_OPTIONS)->toHexString(false).substr(6,12);
  85. std::vector<uint8_t> binary;
  86. isc::util::str::decodeFormattedHexString(rtr, binary);
  87. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getMacFromPacket -> from option 82 " + rtr);
  88. } else if(pkt->getOption(DHO_VENDOR_CLASS_IDENTIFIER)) {
  89. std::string docsis_vendor_class = pkt->getOption(DHO_VENDOR_CLASS_IDENTIFIER)->toString().substr(2,6);
  90. if (docsis_vendor_class.compare("docsis") == 0) {
  91. rtr = pkt->getMAC(HWAddr::HWADDR_SOURCE_RAW)->toText(false);
  92. isc::util::str::uppercase(rtr);
  93. rtr.erase(std::remove(rtr.begin(), rtr.end(), ':'), rtr.end());
  94. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("getMacFromPacket -> is vendor class 'docsis' chwaddr..." + rtr);
  95. }
  96. }
  97. return rtr;
  98. }
  99. /* IPv4 callouts */
  100. int pkt4_receive(CalloutHandle& handle)
  101. {
  102. Pkt4Ptr query;
  103. handle.getArgument("query4", query);
  104. std::vector<std::string> list_class;
  105. std::string mac = getMacFromPacket(query);
  106. HWAddrPtr remote_id;
  107. HostType ht = getHostType(query);
  108. list_class.push_back(HostClass[ht]);
  109. std::map<std::string,std::string>::iterator it = cm_map.find(mac);
  110. if (it != cm_map.end()) {
  111. list_class.push_back(cm_map[mac]);
  112. }
  113. std::string me, me2;
  114. BOOST_FOREACH(me, list_class) {
  115. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("pkt4_receive -> class : " + me);
  116. BOOST_FOREACH(me2, list_class) {
  117. if (me.compare(me2) != 0) {
  118. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("pkt4_receive -> class : " + me + "-" + me2);
  119. query->addClass(me + "-" + me2);
  120. }
  121. }
  122. query->addClass(me);
  123. }
  124. return 0;
  125. }
  126. int pkt4_send(CalloutHandle& handle)
  127. {
  128. Pkt4Ptr response;
  129. Pkt4Ptr query;
  130. handle.getArgument("response4", response);
  131. handle.getArgument("query4", query);
  132. uint8_t ufile_name[128] = "";
  133. std::string mac;
  134. HostType ht = getHostType(query);
  135. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("pkt4_send -> HostType : " + std::to_string(ht));
  136. if (ht == CABLEMODEM or ht == EMTA) {
  137. mac = getMacFromPacket(query);
  138. }
  139. //OptionStringPtr asc1(new OptionString(Option::V4, 43, "http://asc-test.org:7547/"));
  140. //OptionStringPtr asc2(new OptionString(Option::V4, 125, "http://asc-test.org:7547/"));
  141. //
  142. //response->addOption(asc1);
  143. //response->addOption(asc2);
  144. if (ht == CABLEMODEM) {
  145. std::string file = mac + ".bin";
  146. isc::util::str::lowercase(file);
  147. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("pkt4_send -> CM file : " + file);
  148. strcpy((char*)ufile_name, file.c_str());
  149. response->setFile(ufile_name, strlen((char *)ufile_name));
  150. std::map<std::string,std::string>::iterator it = option122_map.find(mac);
  151. if (it != option122_map.end()) {
  152. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("pkt4_send -> cablemodem " + mac + " found for MTA Activation on " + option122_map[mac]);
  153. Option4AddrLstPtr opt_server(new Option4AddrLst(1));
  154. opt_server->setAddress(isc::asiolink::IOAddress("255.255.255.255"));
  155. OptionStringPtr opt_basic1(new OptionString(Option::V4, 6, "BASIC.1"));
  156. OptionPtr option1(new Option(Option::V4, 122));
  157. option1->addOption(opt_server);
  158. option1->addOption(opt_basic1);
  159. response->addOption(option1);
  160. } else {
  161. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("pkt4_send -> cablemodem " + mac + " not found for MTA Activation");
  162. }
  163. }
  164. if (ht == EMTA) {
  165. std::string file = mac + ".mta.bin";
  166. isc::util::str::lowercase(file);
  167. std::map<std::string,std::string>::iterator it = option122_map.find(mac);
  168. if (it != option122_map.end()) {
  169. std::string file = mac + ".mta.bin";
  170. isc::util::str::lowercase(file);
  171. LOG_INFO(runscript_logger, FLOWDAT_DEBUG_STRING).arg("pkt4_send -> EMTA file : " + file);
  172. strcpy((char*)ufile_name, file.c_str());
  173. response->setFile(ufile_name, strlen((char *)ufile_name));
  174. isc::util::str::lowercase(mac);
  175. OptionStringPtr opt_domain(new OptionString(Option::V4, DHO_HOST_NAME, mac));
  176. response->addOption(opt_domain);
  177. }
  178. }
  179. return 0;
  180. }
  181. } // end extern "C"