callouts.cc 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. #include <hooks/hooks.h>
  2. #include <dhcp/pkt4.h>
  3. #include <dhcp/dhcp6.h>
  4. #include <dhcp/pkt6.h>
  5. #include <dhcp/option6_ia.h>
  6. #include <dhcpsrv/subnet.h>
  7. #include <dhcpsrv/lease.h>
  8. #include <string>
  9. #include <vector>
  10. #include "runscript.h"
  11. using namespace isc::dhcp;
  12. using namespace isc::hooks;
  13. extern "C" {
  14. /* These are helpers that extract relevant information from Kea data
  15. * structures and store them in environment variables. */
  16. void extract_bool(std::vector<std::string>& env, const std::string variable, bool value)
  17. {
  18. env.push_back(variable + "=" + std::string(value ? "1" : "0"));
  19. }
  20. void extract_query4(std::vector<std::string>& env, const Pkt4Ptr query)
  21. {
  22. /* General information */
  23. env.push_back("KEA_QUERY4_TYPE=" + std::string(query->getName()));
  24. env.push_back("KEA_QUERY4_INTERFACE=" + query->getIface());
  25. /* Hardware address */
  26. HWAddrPtr hwaddr = query->getHWAddr();
  27. env.push_back("KEA_QUERY4_HWADDR_TYPE=" + std::to_string(hwaddr->htype_));
  28. env.push_back("KEA_QUERY4_HWADDR_SOURCE=" + std::to_string(hwaddr->source_));
  29. env.push_back("KEA_QUERY4_HWADDR=" + hwaddr->toText(false));
  30. /* Misc */
  31. env.push_back("KEA_QUERY4_RELAYED=" + std::to_string(query->isRelayed()));
  32. }
  33. void extract_query6(std::vector<std::string>& env, const Pkt6Ptr query)
  34. {
  35. /* General information */
  36. env.push_back("KEA_QUERY6_TYPE=" + std::string(query->getName()));
  37. env.push_back("KEA_QUERY6_INTERFACE=" + query->getIface());
  38. /* TODO */
  39. env.push_back("KEA_QUERY6_DUID=");
  40. env.push_back("KEA_QUERY6_HWADDR=");
  41. /* TODO: all options? Only common ones? Which format? */
  42. /* TODO */
  43. env.push_back("KEA_QUERY6_DEBUG=" + query->toText());
  44. }
  45. void extract_response4(std::vector<std::string>& env, const Pkt4Ptr response)
  46. {
  47. /* General information */
  48. env.push_back("KEA_RESPONSE4_TYPE=" + std::string(response->getName()));
  49. env.push_back("KEA_RESPONSE4_INTERFACE=" + response->getIface());
  50. }
  51. void extract_response6(std::vector<std::string>& env, const Pkt6Ptr response)
  52. {
  53. /* General information */
  54. env.push_back("KEA_RESPONSE6_TYPE=" + std::string(response->getName()));
  55. env.push_back("KEA_RESPONSE6_INTERFACE=" + response->getIface());
  56. /* TODO, this may not always exist in the response */
  57. env.push_back("KEA_RESPONSE6_ADDRESS=");
  58. env.push_back("KEA_RESPONSE6_PREFERRED_LIFETIME=");
  59. env.push_back("KEA_RESPONSE6_VALID_LIFETIME=");
  60. /* TODO */
  61. env.push_back("KEA_RESPONSE6_DEBUG=" + response->toText());
  62. }
  63. void extract_subnet4(std::vector<std::string>& env, const Subnet4Ptr subnet)
  64. {
  65. env.push_back("KEA_SUBNET4=" + subnet->toText());
  66. std::pair<isc::asiolink::IOAddress, uint8_t> prefix = subnet->get();
  67. /* Copy string to avoid use-after-free when we return from this function */
  68. env.push_back("KEA_SUBNET4_PREFIX=" + std::string(prefix.first.toText()));
  69. env.push_back("KEA_SUBNET4_PREFIXLEN=" + std::to_string(prefix.second));
  70. }
  71. void extract_subnet6(std::vector<std::string>& env, const Subnet6Ptr subnet)
  72. {
  73. env.push_back("KEA_SUBNET6=" + subnet->toText());
  74. std::pair<isc::asiolink::IOAddress, uint8_t> prefix = subnet->get();
  75. /* Copy string to avoid use-after-free when we return from this function */
  76. env.push_back("KEA_SUBNET6_PREFIX=" + std::string(prefix.first.toText()));
  77. env.push_back("KEA_SUBNET6_PREFIXLEN=" + std::to_string(prefix.second));
  78. }
  79. void extract_lease4(std::vector<std::string>& env, const Lease4Ptr lease)
  80. {
  81. env.push_back("KEA_LEASE4_ADDRESS=" + lease->addr_.toText());
  82. }
  83. void extract_lease6(std::vector<std::string>& env, const Lease6Ptr lease)
  84. {
  85. env.push_back("KEA_LEASE6_ADDRESS=" + lease->addr_.toText());
  86. }
  87. /* IPv4 callouts */
  88. int pkt4_receive(CalloutHandle& handle) {
  89. std::vector<std::string> env;
  90. Pkt4Ptr query;
  91. handle.getArgument("query4", query);
  92. extract_query4(env, query);
  93. /* Run script */
  94. int ret;
  95. ret = run_script("pkt4_receive", env);
  96. return 0;
  97. }
  98. int pkt4_send(CalloutHandle& handle) {
  99. std::vector<std::string> env;
  100. Pkt4Ptr response;
  101. Pkt4Ptr query;
  102. handle.getArgument("response4", response);
  103. extract_response4(env, response);
  104. handle.getArgument("query4", query);
  105. extract_query4(env, query);
  106. /* Run script */
  107. int ret;
  108. ret = run_script("pkt4_send", env);
  109. return 0;
  110. }
  111. int subnet4_select(CalloutHandle& handle) {
  112. std::vector<std::string> env;
  113. Pkt4Ptr query;
  114. Subnet4Ptr subnet;
  115. handle.getArgument("query4", query);
  116. extract_query4(env, query);
  117. handle.getArgument("subnet4", subnet);
  118. extract_subnet4(env, subnet);
  119. /* Run script */
  120. int ret;
  121. ret = run_script("subnet4_select", env);
  122. return 0;
  123. }
  124. int lease4_select(CalloutHandle& handle) {
  125. std::vector<std::string> env;
  126. Pkt4Ptr query;
  127. Subnet4Ptr subnet;
  128. bool fake_allocation;
  129. Lease4Ptr lease;
  130. handle.getArgument("query4", query);
  131. extract_query4(env, query);
  132. handle.getArgument("subnet4", subnet);
  133. extract_subnet4(env, subnet);
  134. handle.getArgument("fake_allocation", fake_allocation);
  135. extract_bool(env, "KEA_FAKE_ALLOCATION", fake_allocation);
  136. handle.getArgument("lease4", lease);
  137. extract_lease4(env, lease);
  138. /* Run script */
  139. int ret;
  140. ret = run_script("lease4_select", env);
  141. return 0;
  142. }
  143. int lease4_renew(CalloutHandle& handle) {
  144. std::vector<std::string> env;
  145. Pkt4Ptr query;
  146. Subnet4Ptr subnet;
  147. Lease4Ptr lease;
  148. handle.getArgument("query4", query);
  149. extract_query4(env, query);
  150. handle.getArgument("subnet4", subnet);
  151. extract_subnet4(env, subnet);
  152. /* TODO: what is this? Is it different from what is in the query? */
  153. //handle.getArgument("clientid", XX);
  154. //handle.getArgument("hwaddr", XX);
  155. handle.getArgument("lease4", lease);
  156. extract_lease4(env, lease);
  157. /* Run script */
  158. int ret;
  159. ret = run_script("lease4_renew", env);
  160. return 0;
  161. }
  162. int lease4_release(CalloutHandle& handle) {
  163. std::vector<std::string> env;
  164. Pkt4Ptr query;
  165. Lease4Ptr lease;
  166. handle.getArgument("query4", query);
  167. extract_query4(env, query);
  168. handle.getArgument("lease4", lease);
  169. extract_lease4(env, lease);
  170. /* Run script */
  171. int ret;
  172. ret = run_script("lease4_release", env);
  173. return 0;
  174. }
  175. int lease4_decline(CalloutHandle& handle) {
  176. std::vector<std::string> env;
  177. Pkt4Ptr query;
  178. Lease4Ptr lease;
  179. handle.getArgument("query4", query);
  180. extract_query4(env, query);
  181. handle.getArgument("lease4", lease);
  182. extract_lease4(env, lease);
  183. /* Run script */
  184. int ret;
  185. ret = run_script("lease4_decline", env);
  186. return 0;
  187. }
  188. int lease4_expire(CalloutHandle& handle) {
  189. std::vector<std::string> env;
  190. Lease4Ptr lease;
  191. bool remove_lease;
  192. handle.getArgument("lease4", lease);
  193. extract_lease4(env, lease);
  194. handle.getArgument("remove_lease", remove_lease);
  195. extract_bool(env, "KEA_REMOVE_LEASE", remove_lease);
  196. /* Run script */
  197. int ret;
  198. ret = run_script("lease4_expire", env);
  199. return 0;
  200. }
  201. int lease4_recover(CalloutHandle& handle) {
  202. std::vector<std::string> env;
  203. Lease4Ptr lease;
  204. handle.getArgument("lease4", lease);
  205. extract_lease4(env, lease);
  206. /* Run script */
  207. int ret;
  208. ret = run_script("lease4_recover", env);
  209. return 0;
  210. }
  211. /* IPv6 callouts */
  212. int pkt6_receive(CalloutHandle& handle) {
  213. std::vector<std::string> env;
  214. Pkt6Ptr query;
  215. handle.getArgument("query6", query);
  216. extract_query6(env, query);
  217. /* Run script */
  218. int ret;
  219. ret = run_script("pkt6_receive", env);
  220. return 0;
  221. }
  222. int pkt6_send(CalloutHandle& handle) {
  223. std::vector<std::string> env;
  224. Pkt6Ptr query, response;
  225. handle.getArgument("query6", query);
  226. extract_query6(env, query);
  227. handle.getArgument("response6", response);
  228. extract_response6(env, response);
  229. /* Run script */
  230. int ret;
  231. ret = run_script("pkt6_send", env);
  232. return 0;
  233. }
  234. int subnet6_select(CalloutHandle& handle) {
  235. std::vector<std::string> env;
  236. Pkt6Ptr query;
  237. Subnet6Ptr subnet;
  238. handle.getArgument("query6", query);
  239. extract_query6(env, query);
  240. handle.getArgument("subnet6", subnet);
  241. extract_subnet6(env, subnet);
  242. /* Run script */
  243. int ret;
  244. ret = run_script("subnet6_select", env);
  245. return 0;
  246. }
  247. int lease6_select(CalloutHandle& handle) {
  248. std::vector<std::string> env;
  249. Pkt6Ptr query;
  250. Subnet6Ptr subnet;
  251. bool fake_allocation;
  252. Lease6Ptr lease;
  253. handle.getArgument("query6", query);
  254. extract_query6(env, query);
  255. handle.getArgument("subnet6", subnet);
  256. extract_subnet6(env, subnet);
  257. handle.getArgument("fake_allocation", fake_allocation);
  258. extract_bool(env, "KEA_FAKE_ALLOCATION", fake_allocation);
  259. handle.getArgument("lease6", lease);
  260. extract_lease6(env, lease);
  261. /* Run script */
  262. int ret;
  263. ret = run_script("lease6_select", env);
  264. return 0;
  265. }
  266. int lease6_renew(CalloutHandle& handle) {
  267. std::vector<std::string> env;
  268. Pkt6Ptr query;
  269. Lease6Ptr lease;
  270. boost::shared_ptr<Option6IA> ia_na;
  271. boost::shared_ptr<Option6IA> ia_pd;
  272. handle.getArgument("query6", query);
  273. extract_query6(env, query);
  274. handle.getArgument("lease6", lease);
  275. extract_lease6(env, lease);
  276. try {
  277. handle.getArgument("ia_na", ia_na);
  278. /* TODO: use ia_na */
  279. } catch (const NoSuchArgument&) { }
  280. try {
  281. handle.getArgument("ia_pd", ia_pd);
  282. /* TODO: use ia_pd */
  283. } catch (const NoSuchArgument&) { }
  284. /* Run script */
  285. int ret;
  286. ret = run_script("lease6_renew", env);
  287. return 0;
  288. }
  289. int lease6_rebind(CalloutHandle& handle) {
  290. std::vector<std::string> env;
  291. Pkt6Ptr query;
  292. Lease6Ptr lease;
  293. boost::shared_ptr<Option6IA> ia_na;
  294. boost::shared_ptr<Option6IA> ia_pd;
  295. handle.getArgument("query6", query);
  296. extract_query6(env, query);
  297. handle.getArgument("lease6", lease);
  298. extract_lease6(env, lease);
  299. try {
  300. handle.getArgument("ia_na", ia_na);
  301. /* TODO: use ia_na */
  302. } catch (const NoSuchArgument&) { }
  303. try {
  304. handle.getArgument("ia_pd", ia_pd);
  305. /* TODO: use ia_pd */
  306. } catch (const NoSuchArgument&) { }
  307. /* Run script */
  308. int ret;
  309. ret = run_script("lease6_rebind", env);
  310. return 0;
  311. }
  312. int lease6_decline(CalloutHandle& handle) {
  313. std::vector<std::string> env;
  314. Pkt6Ptr query;
  315. Lease6Ptr lease;
  316. handle.getArgument("query6", query);
  317. extract_query6(env, query);
  318. handle.getArgument("lease6", lease);
  319. extract_lease6(env, lease);
  320. /* Run script */
  321. int ret;
  322. ret = run_script("lease6_decline", env);
  323. return 0;
  324. }
  325. int lease6_release(CalloutHandle& handle) {
  326. std::vector<std::string> env;
  327. Pkt6Ptr query;
  328. Lease6Ptr lease;
  329. handle.getArgument("query6", query);
  330. extract_query6(env, query);
  331. handle.getArgument("lease6", lease);
  332. extract_lease6(env, lease);
  333. /* Run script */
  334. int ret;
  335. ret = run_script("lease6_release", env);
  336. return 0;
  337. }
  338. int lease6_expire(CalloutHandle& handle) {
  339. std::vector<std::string> env;
  340. Lease6Ptr lease;
  341. bool remove_lease;
  342. handle.getArgument("lease6", lease);
  343. extract_lease6(env, lease);
  344. handle.getArgument("remove_lease", remove_lease);
  345. extract_bool(env, "KEA_REMOVE_LEASE", remove_lease);
  346. /* Run script */
  347. int ret;
  348. ret = run_script("lease6_expire", env);
  349. return 0;
  350. }
  351. int lease6_recover(CalloutHandle& handle) {
  352. std::vector<std::string> env;
  353. Lease6Ptr lease;
  354. handle.getArgument("lease6", lease);
  355. extract_lease6(env, lease);
  356. /* Run script */
  357. int ret;
  358. ret = run_script("lease6_recover", env);
  359. return 0;
  360. }
  361. } // end extern "C"