callouts.cc 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  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. env.push_back("KEA_LEASE4_DEBUG=" + lease->toText());
  83. }
  84. void extract_lease6(std::vector<std::string>& env, const Lease6Ptr lease)
  85. {
  86. env.push_back("KEA_LEASE6_TYPE=" + lease->typeToText(lease->type_));
  87. env.push_back("KEA_LEASE6_STATE=" + lease->basicStatesToText(lease->state_));
  88. extract_bool(env, "KEA_LEASE6_IS_EXPIRED", lease->expired());
  89. env.push_back("KEA_LEASE6_ADDRESS=" + lease->addr_.toText());
  90. if (lease->type_ == Lease::TYPE_PD) {
  91. env.push_back("KEA_LEASE6_DELEGATED_PREFIX=" + lease->addr_.toText() + "/" + std::to_string(lease->prefixlen_));
  92. env.push_back("KEA_LEASE6_DELEGATED_PREFIXLEN=" + std::to_string(lease->prefixlen_));
  93. }
  94. env.push_back("KEA_LEASE6_HWADDR=" + lease->hwaddr_->toText(false));
  95. env.push_back("KEA_LEASE6_HOSTNAME=" + lease->hostname_);
  96. env.push_back("KEA_LEASE6_CLIENT_DUID=" + lease->duid_->toText());
  97. env.push_back("KEA_LEASE6_CLIENT_LAST_TRANSMISSION=" + std::to_string(lease->cltt_));
  98. env.push_back("KEA_LEASE6_RENEW_TIMER=" + std::to_string(lease->t1_));
  99. env.push_back("KEA_LEASE6_REBIND_TIMER=" + std::to_string(lease->t2_));
  100. env.push_back("KEA_LEASE6_VALID_LIFETIME=" + std::to_string(lease->valid_lft_));
  101. env.push_back("KEA_LEASE6_PREFERRED_LIFETIME=" + std::to_string(lease->preferred_lft_));
  102. env.push_back("KEA_LEASE6_IAID=" + std::to_string(lease->iaid_));
  103. env.push_back("KEA_LEASE6_DEBUG=" + lease->toText());
  104. }
  105. /* IPv4 callouts */
  106. int pkt4_receive(CalloutHandle& handle) {
  107. std::vector<std::string> env;
  108. Pkt4Ptr query;
  109. handle.getArgument("query4", query);
  110. extract_query4(env, query);
  111. /* Run script */
  112. int ret;
  113. ret = run_script("pkt4_receive", env);
  114. return 0;
  115. }
  116. int pkt4_send(CalloutHandle& handle) {
  117. std::vector<std::string> env;
  118. Pkt4Ptr response;
  119. Pkt4Ptr query;
  120. handle.getArgument("response4", response);
  121. extract_response4(env, response);
  122. handle.getArgument("query4", query);
  123. extract_query4(env, query);
  124. /* Run script */
  125. int ret;
  126. ret = run_script("pkt4_send", env);
  127. return 0;
  128. }
  129. int subnet4_select(CalloutHandle& handle) {
  130. std::vector<std::string> env;
  131. Pkt4Ptr query;
  132. Subnet4Ptr subnet;
  133. handle.getArgument("query4", query);
  134. extract_query4(env, query);
  135. handle.getArgument("subnet4", subnet);
  136. extract_subnet4(env, subnet);
  137. /* Run script */
  138. int ret;
  139. ret = run_script("subnet4_select", env);
  140. return 0;
  141. }
  142. int lease4_select(CalloutHandle& handle) {
  143. std::vector<std::string> env;
  144. Pkt4Ptr query;
  145. Subnet4Ptr subnet;
  146. bool fake_allocation;
  147. Lease4Ptr lease;
  148. handle.getArgument("query4", query);
  149. extract_query4(env, query);
  150. handle.getArgument("subnet4", subnet);
  151. extract_subnet4(env, subnet);
  152. handle.getArgument("fake_allocation", fake_allocation);
  153. extract_bool(env, "KEA_FAKE_ALLOCATION", fake_allocation);
  154. handle.getArgument("lease4", lease);
  155. extract_lease4(env, lease);
  156. /* Run script */
  157. int ret;
  158. ret = run_script("lease4_select", env);
  159. return 0;
  160. }
  161. int lease4_renew(CalloutHandle& handle) {
  162. std::vector<std::string> env;
  163. Pkt4Ptr query;
  164. Subnet4Ptr subnet;
  165. Lease4Ptr lease;
  166. handle.getArgument("query4", query);
  167. extract_query4(env, query);
  168. handle.getArgument("subnet4", subnet);
  169. extract_subnet4(env, subnet);
  170. /* TODO: what is this? Is it different from what is in the query? */
  171. //handle.getArgument("clientid", XX);
  172. //handle.getArgument("hwaddr", XX);
  173. handle.getArgument("lease4", lease);
  174. extract_lease4(env, lease);
  175. /* Run script */
  176. int ret;
  177. ret = run_script("lease4_renew", env);
  178. return 0;
  179. }
  180. int lease4_release(CalloutHandle& handle) {
  181. std::vector<std::string> env;
  182. Pkt4Ptr query;
  183. Lease4Ptr lease;
  184. handle.getArgument("query4", query);
  185. extract_query4(env, query);
  186. handle.getArgument("lease4", lease);
  187. extract_lease4(env, lease);
  188. /* Run script */
  189. int ret;
  190. ret = run_script("lease4_release", env);
  191. return 0;
  192. }
  193. int lease4_decline(CalloutHandle& handle) {
  194. std::vector<std::string> env;
  195. Pkt4Ptr query;
  196. Lease4Ptr lease;
  197. handle.getArgument("query4", query);
  198. extract_query4(env, query);
  199. handle.getArgument("lease4", lease);
  200. extract_lease4(env, lease);
  201. /* Run script */
  202. int ret;
  203. ret = run_script("lease4_decline", env);
  204. return 0;
  205. }
  206. int lease4_expire(CalloutHandle& handle) {
  207. std::vector<std::string> env;
  208. Lease4Ptr lease;
  209. bool remove_lease;
  210. handle.getArgument("lease4", lease);
  211. extract_lease4(env, lease);
  212. handle.getArgument("remove_lease", remove_lease);
  213. extract_bool(env, "KEA_REMOVE_LEASE", remove_lease);
  214. /* Run script */
  215. int ret;
  216. ret = run_script("lease4_expire", env);
  217. return 0;
  218. }
  219. int lease4_recover(CalloutHandle& handle) {
  220. std::vector<std::string> env;
  221. Lease4Ptr lease;
  222. handle.getArgument("lease4", lease);
  223. extract_lease4(env, lease);
  224. /* Run script */
  225. int ret;
  226. ret = run_script("lease4_recover", env);
  227. return 0;
  228. }
  229. /* IPv6 callouts */
  230. int pkt6_receive(CalloutHandle& handle) {
  231. std::vector<std::string> env;
  232. Pkt6Ptr query;
  233. handle.getArgument("query6", query);
  234. extract_query6(env, query);
  235. /* Run script */
  236. int ret;
  237. ret = run_script("pkt6_receive", env);
  238. return 0;
  239. }
  240. int pkt6_send(CalloutHandle& handle) {
  241. std::vector<std::string> env;
  242. Pkt6Ptr query, response;
  243. handle.getArgument("query6", query);
  244. extract_query6(env, query);
  245. handle.getArgument("response6", response);
  246. extract_response6(env, response);
  247. /* Run script */
  248. int ret;
  249. ret = run_script("pkt6_send", env);
  250. return 0;
  251. }
  252. int subnet6_select(CalloutHandle& handle) {
  253. std::vector<std::string> env;
  254. Pkt6Ptr query;
  255. Subnet6Ptr subnet;
  256. handle.getArgument("query6", query);
  257. extract_query6(env, query);
  258. handle.getArgument("subnet6", subnet);
  259. extract_subnet6(env, subnet);
  260. /* Run script */
  261. int ret;
  262. ret = run_script("subnet6_select", env);
  263. return 0;
  264. }
  265. int lease6_select(CalloutHandle& handle) {
  266. std::vector<std::string> env;
  267. Pkt6Ptr query;
  268. Subnet6Ptr subnet;
  269. bool fake_allocation;
  270. Lease6Ptr lease;
  271. handle.getArgument("query6", query);
  272. extract_query6(env, query);
  273. handle.getArgument("subnet6", subnet);
  274. extract_subnet6(env, subnet);
  275. handle.getArgument("fake_allocation", fake_allocation);
  276. extract_bool(env, "KEA_FAKE_ALLOCATION", fake_allocation);
  277. handle.getArgument("lease6", lease);
  278. extract_lease6(env, lease);
  279. /* Run script */
  280. int ret;
  281. ret = run_script("lease6_select", env);
  282. return 0;
  283. }
  284. int lease6_renew(CalloutHandle& handle) {
  285. std::vector<std::string> env;
  286. Pkt6Ptr query;
  287. Lease6Ptr lease;
  288. boost::shared_ptr<Option6IA> ia_na;
  289. boost::shared_ptr<Option6IA> ia_pd;
  290. handle.getArgument("query6", query);
  291. extract_query6(env, query);
  292. handle.getArgument("lease6", lease);
  293. extract_lease6(env, lease);
  294. try {
  295. handle.getArgument("ia_na", ia_na);
  296. /* TODO: use ia_na */
  297. } catch (const NoSuchArgument&) { }
  298. try {
  299. handle.getArgument("ia_pd", ia_pd);
  300. /* TODO: use ia_pd */
  301. } catch (const NoSuchArgument&) { }
  302. /* Run script */
  303. int ret;
  304. ret = run_script("lease6_renew", env);
  305. return 0;
  306. }
  307. int lease6_rebind(CalloutHandle& handle) {
  308. std::vector<std::string> env;
  309. Pkt6Ptr query;
  310. Lease6Ptr lease;
  311. boost::shared_ptr<Option6IA> ia_na;
  312. boost::shared_ptr<Option6IA> ia_pd;
  313. handle.getArgument("query6", query);
  314. extract_query6(env, query);
  315. handle.getArgument("lease6", lease);
  316. extract_lease6(env, lease);
  317. try {
  318. handle.getArgument("ia_na", ia_na);
  319. /* TODO: use ia_na */
  320. } catch (const NoSuchArgument&) { }
  321. try {
  322. handle.getArgument("ia_pd", ia_pd);
  323. /* TODO: use ia_pd */
  324. } catch (const NoSuchArgument&) { }
  325. /* Run script */
  326. int ret;
  327. ret = run_script("lease6_rebind", env);
  328. return 0;
  329. }
  330. int lease6_decline(CalloutHandle& handle) {
  331. std::vector<std::string> env;
  332. Pkt6Ptr query;
  333. Lease6Ptr lease;
  334. handle.getArgument("query6", query);
  335. extract_query6(env, query);
  336. handle.getArgument("lease6", lease);
  337. extract_lease6(env, lease);
  338. /* Run script */
  339. int ret;
  340. ret = run_script("lease6_decline", env);
  341. return 0;
  342. }
  343. int lease6_release(CalloutHandle& handle) {
  344. std::vector<std::string> env;
  345. Pkt6Ptr query;
  346. Lease6Ptr lease;
  347. handle.getArgument("query6", query);
  348. extract_query6(env, query);
  349. handle.getArgument("lease6", lease);
  350. extract_lease6(env, lease);
  351. /* Run script */
  352. int ret;
  353. ret = run_script("lease6_release", env);
  354. return 0;
  355. }
  356. int lease6_expire(CalloutHandle& handle) {
  357. std::vector<std::string> env;
  358. Lease6Ptr lease;
  359. bool remove_lease;
  360. handle.getArgument("lease6", lease);
  361. extract_lease6(env, lease);
  362. handle.getArgument("remove_lease", remove_lease);
  363. extract_bool(env, "KEA_REMOVE_LEASE", remove_lease);
  364. /* Run script */
  365. int ret;
  366. ret = run_script("lease6_expire", env);
  367. return 0;
  368. }
  369. int lease6_recover(CalloutHandle& handle) {
  370. std::vector<std::string> env;
  371. Lease6Ptr lease;
  372. handle.getArgument("lease6", lease);
  373. extract_lease6(env, lease);
  374. /* Run script */
  375. int ret;
  376. ret = run_script("lease6_recover", env);
  377. return 0;
  378. }
  379. } // end extern "C"