lease_cmds.cc 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895
  1. // Copyright (C) 2017 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this
  5. // file, You can obtain one at http://mozilla.org/MPL/2.0/.
  6. #include <config.h>
  7. #include <lease_cmds.h>
  8. #include <config/command_mgr.h>
  9. #include <lease_parser.h>
  10. #include <cc/command_interpreter.h>
  11. #include <cc/data.h>
  12. #include <asiolink/io_address.h>
  13. #include <lease_cmds_log.h>
  14. #include <dhcpsrv/cfgmgr.h>
  15. #include <dhcpsrv/lease_mgr.h>
  16. #include <dhcpsrv/lease_mgr_factory.h>
  17. #include <dhcpsrv/subnet_id.h>
  18. #include <dhcp/duid.h>
  19. #include <util/encode/hex.h>
  20. #include <util/strutil.h>
  21. #include <exceptions/exceptions.h>
  22. #include <boost/bind.hpp>
  23. #include <string>
  24. using namespace isc::dhcp;
  25. using namespace isc::data;
  26. using namespace isc::config;
  27. using namespace isc::asiolink;
  28. using namespace std;
  29. namespace isc {
  30. namespace lease_cmds {
  31. /// @brief Wrapper class around reservation command handlers.
  32. class LeaseCmdsImpl {
  33. public:
  34. LeaseCmdsImpl();
  35. ~LeaseCmdsImpl();
  36. /// @brief Parameters specified for reservation-get and reservation-del
  37. ///
  38. /// As both call types (get and delete) need specify which reservation to
  39. /// act on, they have the same set of parameters. In particular, those
  40. /// two call types support the following sets of parameters:
  41. /// - address
  42. /// - subnet-id, identifier-type, identifier-value (v4)
  43. /// - subnet-id, lease-type, iaid, identifier-type, identifier-value (v6)
  44. ///
  45. /// This class stores those parameters and is used to pass them around.
  46. class Parameters {
  47. public:
  48. /// @brief specifies type of query (by IP addr, by hwaddr, by DUID)
  49. typedef enum {
  50. TYPE_ADDR, ///< query by IP address (either v4 or v6)
  51. TYPE_HWADDR, ///< query by hardware address (v4 only)
  52. TYPE_DUID ///< query by DUID (v6 only)
  53. } Type;
  54. /// @brief Specifies subnet-id (always used)
  55. SubnetID subnet_id;
  56. /// @brief Specifies IPv4/v6 address (used when query_type is TYPE_ADDR)
  57. IOAddress addr;
  58. /// @brief Specifies hardware address (used when query_type is TYPE_HWADDR)
  59. HWAddrPtr hwaddr;
  60. /// @brief Specifies identifier value (used when query_type is TYPE_DUID)
  61. isc::dhcp::DuidPtr duid;
  62. /// @brief Attempts to covert text to one of specified types
  63. ///
  64. /// Supported values are: "address", hw-address and duid.
  65. ///
  66. /// @param txt text to be converted
  67. /// @return value converted to Parameters::Type
  68. /// @throw BadValue if unsupported type is specified
  69. static Type txtToType(const std::string& txt) {
  70. if (txt == "address") {
  71. return (Parameters::TYPE_ADDR);
  72. } else if (txt == "hw-address") {
  73. return (Parameters::TYPE_HWADDR);
  74. } else if (txt == "duid") {
  75. return (Parameters::TYPE_DUID);
  76. } else {
  77. isc_throw(BadValue, "Incorrect identifier type: "
  78. << txt << ", the only supported values are: "
  79. "address, hw-address, duid");
  80. }
  81. }
  82. /// @brief specifies parameter types (true = query by address, false =
  83. /// query by identifier-type,identifier)
  84. Type query_type;
  85. /// @brief Lease type (NA,TA or PD) used for v6 leases
  86. Lease::Type lease_type;
  87. /// @brief IAID identifier used for v6 leases
  88. uint32_t iaid;
  89. /// @brief Default constructor.
  90. Parameters()
  91. :addr("::"), query_type(TYPE_ADDR), lease_type(Lease::TYPE_NA),
  92. iaid(0) {
  93. }
  94. };
  95. private:
  96. /// @brief Registers commands:
  97. ///
  98. /// Registers:
  99. /// - lease4-add
  100. /// - lease6-add
  101. /// - lease4-get
  102. /// - lease6-get
  103. /// - lease4-del
  104. /// - lease6-del
  105. /// - lease4-update
  106. /// - lease6-update
  107. /// - lease4-wipe
  108. /// - lease6-wipe
  109. /// @throw Unexpected if CommandMgr is not available (should not happen)
  110. void registerCommands();
  111. /// @brief Deregisters commands:
  112. ///
  113. /// Deregisters:
  114. /// - lease4-add
  115. /// - lease6-add
  116. /// - lease4-get
  117. /// - lease6-get
  118. /// - lease4-del
  119. /// - lease6-del
  120. /// - lease4-update
  121. /// - lease6-update
  122. /// - lease4-wipe
  123. /// - lease6-wipe
  124. ///
  125. /// @throw Unexpected if CommandMgr is not available (should not happen)
  126. void deregisterCommands();
  127. /// @brief lease4-add, lease6-add command handler
  128. ///
  129. /// This command attempts to add a lease.
  130. ///
  131. /// An example full command looks as follows. Note that the args
  132. /// parameter is expected to contain the "arguments" portion of it.
  133. /// This function covers both v4 and v6 leases.
  134. ///
  135. /// Example command for v4:
  136. /// {
  137. /// "command": "lease4-add",
  138. /// "parameters": {
  139. /// "address": "192.0.2.1",
  140. /// "hwaddr": "00:01:02:03:04:05",
  141. /// "client-id": "this-is-a-client",
  142. /// "valid-lft": 3600,
  143. /// "expire": 12345678,
  144. /// "subnet-id": 1,
  145. /// "fqdn-fwd": true,
  146. /// "fqdn-rev": true,
  147. /// "hostname": "myhost.example.org",
  148. /// "state": 0
  149. /// }
  150. /// }
  151. /// Example command for v6:
  152. /// {
  153. /// "command": "lease6-add",
  154. /// "arguments": {
  155. /// "subnet-id": 66,
  156. /// "ip-address": "2001:db8:abcd::",
  157. /// "type": "IA_PD",
  158. /// "prefix-len": 48,
  159. /// "duid": "01:02:03:04:05:06:07:08",
  160. /// "iaid": 1234,
  161. /// "preferred-lft": 500,
  162. /// "valid-lft": 1000,
  163. /// "expire": 12345678,
  164. /// "fqdn-fwd": true,
  165. /// "fqdn-rev": true,
  166. /// "hostname": "urania.example.org""
  167. /// }
  168. /// }
  169. ///
  170. /// @param command should be 'lease4-add' or 'lease6-add'
  171. /// @param args must contain host reservation definition.
  172. /// @return result of the operation
  173. static ConstElementPtr
  174. leaseAddHandler(const string& command, ConstElementPtr args);
  175. /// @brief lease4-get, lease6-get command handler
  176. ///
  177. /// This command attempts to retrieve a lease that match selected criteria.
  178. /// The following types of parameters are supported:
  179. /// - (subnet-id, address) for both v4 and v6
  180. /// - (subnet-id, identifier-type, identifier) for v4
  181. /// - (subnet-id, type, iana, identifier-type, identifier) for v6
  182. ///
  183. /// Example command for query by (subnet-id, address):
  184. /// {
  185. /// "command": "lease4-get",
  186. /// "arguments": {
  187. /// "subnet-id": 1,
  188. /// "ip-address": "192.0.2.202"
  189. /// }
  190. /// }
  191. ///
  192. /// Example command for query by (subnet-id, identifier-type, identifier)
  193. /// {
  194. /// "command": "lease4-get",
  195. /// "arguments": {
  196. /// "subnet-id": 1,
  197. /// "identifier-type": "hw-address",
  198. /// "identifier": "00:01:02:03:04:05"
  199. /// }
  200. /// }
  201. ///
  202. /// Example command for query by (subnet-id, type, iana, identifier-type,
  203. /// identifier):
  204. /// {
  205. /// "command": "lease6-get",
  206. /// "arguments": {
  207. /// "subnet-id": 66,
  208. /// "iaid": 42,
  209. /// "type": "IA_NA",
  210. /// "identifier-type": "duid",
  211. /// "identifier": "77:77:77:77:77:77:77:77"
  212. /// }
  213. /// }
  214. /// @param command "lease4-get" or "lease6-get"
  215. /// @param args must contain host reservation definition.
  216. /// @return result of the operation (includes lease details, if found)
  217. static ConstElementPtr
  218. leaseGetHandler(const string& command, ConstElementPtr args);
  219. /// @brief lease4-del command handler
  220. ///
  221. /// This command attempts to delete an IPv4 lease that match selected
  222. /// criteria. Two types of parameters are supported: (subnet-id, address) or
  223. /// (subnet-id, identifier-type, identifier).
  224. ///
  225. /// Example command for deletion by (subnet-id, address):
  226. /// {
  227. /// "command": "lease4-del",
  228. /// "arguments": {
  229. /// "subnet-id": 1,
  230. /// "ip-address": "192.0.2.202"
  231. /// }
  232. /// }
  233. ///
  234. /// Example command for deletion by (subnet-id, identifier-type, identifier)
  235. /// {
  236. /// "command": "lease4-del",
  237. /// "arguments": {
  238. /// "subnet-id": 1,
  239. /// "identifier-type": "hw-address",
  240. /// "identifier": "00:01:02:03:04:05"
  241. /// }
  242. /// }";
  243. /// @param command should be 'lease4-del' (but it's ignored)
  244. /// @param args must contain host reservation definition.
  245. /// @return result of the operation (host will be included as parameters, if found)
  246. static ConstElementPtr
  247. lease4DelHandler(const string& command, ConstElementPtr args);
  248. /// @brief lease6-del command handler
  249. ///
  250. /// This command attempts to delete a lease that match selected criteria.
  251. /// Two types of parameters are supported: (subnet-id, address) or
  252. /// (subnet-id, type, iaid, identifier-type, identifier).
  253. ///
  254. /// Example command for deletion by (subnet-id, address):
  255. /// {
  256. /// "command": "lease6-del",
  257. /// "arguments": {
  258. /// "subnet-id": 1,
  259. /// "ip-address": "192.0.2.202"
  260. /// }
  261. /// }
  262. ///
  263. /// Example command for deletion by (subnet-id, type, iaid, identifier-type,
  264. /// identifier):
  265. /// {
  266. /// "command": "lease6-del",
  267. /// "arguments": {
  268. /// "subnet-id": 1,
  269. /// "type": "IA_NA",
  270. /// "iaid": 123456,
  271. /// "identifier-type": "hw-address",
  272. /// "identifier": "00:01:02:03:04:05"
  273. /// }
  274. /// }";
  275. /// @param command should be 'lease6-del' (but it's ignored)
  276. /// @param args must contain host reservation definition.
  277. /// @return result of the operation (host will be included as parameters, if found)
  278. static ConstElementPtr
  279. lease6DelHandler(const string& command, ConstElementPtr args);
  280. /// @brief lease4-update handler
  281. ///
  282. /// This command attempts to update existing IPv4 lease. The parameters
  283. /// specified will replace existing lease. The only condition is that
  284. /// the IP address must not change. If you want to change the IP address,
  285. /// please use lease4-del and lease4-add instead.
  286. ///
  287. /// Example command:
  288. /// {
  289. /// "command": "lease4-update",
  290. /// "arguments": {
  291. /// "subnet-id": 44,
  292. /// "ip-address": "192.0.2.1",
  293. /// "hw-address": "1a:1b:1c:1d:1e:1f",
  294. /// "hostname": "newhostname.example.org"
  295. /// }
  296. /// };
  297. ///
  298. /// @param command - should be "lease4-update", but it is ignored
  299. /// @param args arguments that describe the lease being updated.
  300. static ConstElementPtr
  301. lease4UpdateHandler(const string& command, ConstElementPtr args);
  302. /// @brief lease6-update handler
  303. ///
  304. /// This command attempts to update existing IPv6 lease. The parameters
  305. /// specified will replace existing lease. The only condition is that
  306. /// the IP address must not change. If you want to change the IP address,
  307. /// please use lease6-del and lease6-add instead.
  308. ///
  309. /// Example command:
  310. /// {
  311. /// "command": "lease6-update",
  312. /// "arguments": {
  313. /// "subnet-id": 66,
  314. /// "ip-address": "2001:db8::1",
  315. /// "iaid": 7654321,
  316. /// "duid": "88:88:88:88:88:88:88:88",
  317. /// "hostname": "newhostname.example.org"
  318. /// }
  319. /// }";
  320. ///
  321. /// @param command - should be "lease6-update" (but it is ignored)
  322. /// @param args arguments that describe the lease being updated.
  323. static ConstElementPtr
  324. lease6UpdateHandler(const string& command, ConstElementPtr args);
  325. /// @brief lease4-wipe handler
  326. ///
  327. /// This commands attempts to remove all IPv4 leases from a specific
  328. /// subnet. Currently the leases are removed from the database,
  329. /// without any processing (like calling hooks or doing DDNS
  330. /// cleanups).
  331. ///
  332. /// Example command:
  333. /// {\n"
  334. /// "command": "lease4-wipe",\n"
  335. /// "arguments": {"
  336. /// "subnet-id": 44
  337. /// }\n"
  338. /// }";
  339. /// @param command - should be "lease4-wipe" (but is ignored)
  340. /// @param args arguments that describe the lease being updated.
  341. static ConstElementPtr
  342. lease4WipeHandler(const string& command, ConstElementPtr args);
  343. /// @brief lease6-wipe handler
  344. ///
  345. /// This commands attempts to remove all IPv4 leases from a specific
  346. /// subnet. Currently the leases are removed from the database,
  347. /// without any processing (like calling hooks or doing DDNS
  348. /// cleanups).
  349. ///
  350. /// Example command:
  351. /// {\n"
  352. /// "command": "lease4-wipe",\n"
  353. /// "arguments": {"
  354. /// "subnet-id": 44
  355. /// }\n"
  356. /// }";
  357. /// @param command - should be "lease4-wipe" (but is ignored)
  358. /// @param args arguments that describe the lease being updated.
  359. static ConstElementPtr
  360. lease6WipeHandler(const string& command, ConstElementPtr args);
  361. /// @brief Extracts parameters required for reservation-get and reservation-del
  362. ///
  363. /// See @ref Parameters class for detailed description of what is expected
  364. /// in the args structure.
  365. ///
  366. /// @param v6 whether addresses allowed are v4 (false) or v6 (true)
  367. /// @param args arguments passed to command
  368. /// @return parsed parameters
  369. /// @throw BadValue if input arguments don't make sense.
  370. static Parameters getParameters(bool v6, const ConstElementPtr& args);
  371. };
  372. LeaseCmdsImpl::LeaseCmdsImpl() {
  373. registerCommands();
  374. }
  375. LeaseCmdsImpl::~LeaseCmdsImpl() {
  376. deregisterCommands();
  377. }
  378. void LeaseCmdsImpl::registerCommands() {
  379. /// @todo: Use registration mechanism once #5314 is merged.
  380. /// See #5321 discussion.
  381. CommandMgr::instance().registerCommand("lease4-add",
  382. boost::bind(&LeaseCmdsImpl::leaseAddHandler, _1, _2));
  383. CommandMgr::instance().registerCommand("lease6-add",
  384. boost::bind(&LeaseCmdsImpl::leaseAddHandler, _1, _2));
  385. CommandMgr::instance().registerCommand("lease4-get",
  386. boost::bind(&LeaseCmdsImpl::leaseGetHandler, _1, _2));
  387. CommandMgr::instance().registerCommand("lease6-get",
  388. boost::bind(&LeaseCmdsImpl::leaseGetHandler, _1, _2));
  389. CommandMgr::instance().registerCommand("lease4-del",
  390. boost::bind(&LeaseCmdsImpl::lease4DelHandler, _1, _2));
  391. CommandMgr::instance().registerCommand("lease6-del",
  392. boost::bind(&LeaseCmdsImpl::lease6DelHandler, _1, _2));
  393. CommandMgr::instance().registerCommand("lease4-update",
  394. boost::bind(&LeaseCmdsImpl::lease4UpdateHandler, _1, _2));
  395. CommandMgr::instance().registerCommand("lease6-update",
  396. boost::bind(&LeaseCmdsImpl::lease6UpdateHandler, _1, _2));
  397. CommandMgr::instance().registerCommand("lease4-wipe",
  398. boost::bind(&LeaseCmdsImpl::lease4WipeHandler, _1, _2));
  399. CommandMgr::instance().registerCommand("lease6-wipe",
  400. boost::bind(&LeaseCmdsImpl::lease6WipeHandler, _1, _2));
  401. }
  402. void LeaseCmdsImpl::deregisterCommands() {
  403. /// @todo: Use deregistration mechanism once #5321 discussion is done
  404. CommandMgr::instance().deregisterCommand("lease4-add");
  405. CommandMgr::instance().deregisterCommand("lease6-add");
  406. CommandMgr::instance().deregisterCommand("lease4-get");
  407. CommandMgr::instance().deregisterCommand("lease6-get");
  408. CommandMgr::instance().deregisterCommand("lease4-del");
  409. CommandMgr::instance().deregisterCommand("lease6-del");
  410. CommandMgr::instance().deregisterCommand("lease4-update");
  411. CommandMgr::instance().deregisterCommand("lease6-update");
  412. CommandMgr::instance().deregisterCommand("lease4-wipe");
  413. CommandMgr::instance().deregisterCommand("lease6-wipe");
  414. }
  415. ConstElementPtr
  416. LeaseCmdsImpl::leaseAddHandler(const std::string& name,
  417. ConstElementPtr params) {
  418. bool v4 = (name == "lease4-add");
  419. string txt = "(missing parameters)";
  420. if (params) {
  421. txt = params->str();
  422. }
  423. try {
  424. if (!params) {
  425. isc_throw(isc::BadValue, "no parameters specified for the command");
  426. }
  427. ConstSrvConfigPtr config = CfgMgr::instance().getCurrentCfg();
  428. Lease4Ptr lease4;
  429. Lease6Ptr lease6;
  430. if (v4) {
  431. Lease4Parser parser;
  432. lease4 = parser.parse(config, params);
  433. // checkLeaseIntegrity(config, lease4);
  434. if (lease4) {
  435. LeaseMgrFactory::instance().addLease(lease4);
  436. }
  437. } else {
  438. Lease6Parser parser;
  439. lease6 = parser.parse(config, params);
  440. // checkLeaseIntegrity(config, lease6);
  441. if (lease6) {
  442. LeaseMgrFactory::instance().addLease(lease6);
  443. }
  444. }
  445. } catch (const std::exception& ex) {
  446. LOG_ERROR(lease_cmds_logger, v4 ? LEASE_CMDS_ADD4_FAILED : LEASE_CMDS_ADD6_FAILED)
  447. .arg(txt)
  448. .arg(ex.what());
  449. return (createAnswer(CONTROL_RESULT_ERROR, ex.what()));
  450. }
  451. LOG_INFO(lease_cmds_logger,
  452. v4 ? LEASE_CMDS_ADD4 : LEASE_CMDS_ADD6).arg(txt);
  453. return (createAnswer(CONTROL_RESULT_SUCCESS, "Lease added."));
  454. }
  455. LeaseCmdsImpl::Parameters
  456. LeaseCmdsImpl::getParameters(bool v6, const ConstElementPtr& params) {
  457. Parameters x;
  458. if (!params || params->getType() != Element::map) {
  459. isc_throw(BadValue, "Parameters missing or are not a map.");
  460. }
  461. // We support several sets of parameters for leaseX-get/lease-del:
  462. // lease-get(type, address)
  463. // lease-get(type, subnet-id, identifier-type, identifier)
  464. if (params->contains("type")) {
  465. string t = params->get("type")->stringValue();
  466. if (t == "IA_NA" || t == "0") {
  467. x.lease_type = Lease::TYPE_NA;
  468. } else if (t == "IA_TA" || t == "1") {
  469. x.lease_type = Lease::TYPE_TA;
  470. } else if (t == "IA_PD" || t == "2") {
  471. x.lease_type = Lease::TYPE_PD;
  472. } else if (t == "V4" || t == "3") {
  473. x.lease_type = Lease::TYPE_V4;
  474. } else {
  475. isc_throw(BadValue, "Invalid lease type specified: "
  476. << t << ", only supported values are: IA_NA, IA_TA,"
  477. << " IA_PD and V4");
  478. }
  479. }
  480. ConstElementPtr tmp = params->get("ip-address");
  481. if (tmp) {
  482. if (tmp->getType() != Element::string) {
  483. isc_throw(BadValue, "'ip-address' is not a string.");
  484. }
  485. x.addr = IOAddress(tmp->stringValue());
  486. if ((v6 && !x.addr.isV6()) || (!v6 && !x.addr.isV4())) {
  487. stringstream txt;
  488. txt << "Invalid " << (v6 ? "IPv6" : "IPv4")
  489. << " address specified: " << tmp->stringValue();
  490. isc_throw(BadValue, txt.str());
  491. }
  492. x.query_type = Parameters::TYPE_ADDR;
  493. return (x);
  494. }
  495. tmp = params->get("subnet-id");
  496. if (!tmp) {
  497. isc_throw(BadValue, "Mandatory 'subnet-id' parameter missing.");
  498. }
  499. if (tmp->getType() != Element::integer) {
  500. isc_throw(BadValue, "'subnet-id' parameter is not integer.");
  501. }
  502. x.subnet_id = tmp->intValue();
  503. if (params->contains("iaid")) {
  504. x.iaid = params->get("iaid")->intValue();
  505. }
  506. // No address specified. Ok, so it must be identifier based query.
  507. // "identifier-type": "duid",
  508. // "identifier": "aa:bb:cc:dd:ee:..."
  509. ConstElementPtr type = params->get("identifier-type");
  510. ConstElementPtr ident = params->get("identifier");
  511. if (!type || type->getType() != Element::string) {
  512. isc_throw(BadValue, "No 'ip-address' provided"
  513. " and 'identifier-type' is either missing or not a string.");
  514. }
  515. if (!ident || ident->getType() != Element::string) {
  516. isc_throw(BadValue, "No 'ip-address' provided"
  517. " and 'identifier' is either missing or not a string.");
  518. }
  519. // Got the parameters. Let's see if their values make sense.
  520. // Try to convert identifier-type
  521. x.query_type = Parameters::txtToType(type->stringValue());
  522. switch (x.query_type) {
  523. case Parameters::TYPE_HWADDR: {
  524. HWAddr hw = HWAddr::fromText(ident->stringValue());
  525. x.hwaddr = HWAddrPtr(new HWAddr(hw));
  526. break;
  527. }
  528. case Parameters::TYPE_DUID: {
  529. DUID duid = DUID::fromText(ident->stringValue());
  530. x.duid = DuidPtr(new DUID(duid));
  531. break;
  532. }
  533. case Parameters::TYPE_ADDR: {
  534. // We should never get here. The address clause should have been caught
  535. // earlier.
  536. return (x);
  537. }
  538. default: {
  539. isc_throw(BadValue, "Identifier type " << type->stringValue() <<
  540. " is not supported.");
  541. }
  542. }
  543. return (x);
  544. }
  545. ConstElementPtr
  546. LeaseCmdsImpl::leaseGetHandler(const std::string& name, ConstElementPtr params) {
  547. Parameters p;
  548. Lease4Ptr lease4;
  549. Lease6Ptr lease6;
  550. bool v4 = (name == "lease4-get");
  551. try {
  552. p = getParameters(!v4, params);
  553. switch (p.query_type) {
  554. case Parameters::TYPE_ADDR: {
  555. // Query by address
  556. if (v4) {
  557. lease4 = LeaseMgrFactory::instance().getLease4(p.addr);
  558. } else {
  559. lease6 = LeaseMgrFactory::instance().getLease6(p.lease_type, p.addr);
  560. }
  561. break;
  562. }
  563. case Parameters::TYPE_HWADDR:
  564. if (v4) {
  565. if (!p.hwaddr) {
  566. return (createAnswer(CONTROL_RESULT_ERROR,
  567. "Program error: Query by hw-address "
  568. "requires hwaddr to be specified"));
  569. }
  570. lease4 = LeaseMgrFactory::instance().getLease4(*p.hwaddr, p.subnet_id);
  571. } else {
  572. return (createAnswer(CONTROL_RESULT_ERROR,
  573. "Query by hw-address is not allowed in v6."));
  574. }
  575. break;
  576. case Parameters::TYPE_DUID:
  577. if (!v4) {
  578. if (!p.duid) {
  579. return (createAnswer(CONTROL_RESULT_ERROR,
  580. "Program error: Query by duid "
  581. "requires duid to be specified"));
  582. }
  583. lease6 = LeaseMgrFactory::instance().getLease6(p.lease_type, *p.duid,
  584. p.iaid, p.subnet_id);
  585. } else {
  586. return (createAnswer(CONTROL_RESULT_ERROR,
  587. "Query by duid is not allowed in v4."));
  588. }
  589. break;
  590. default: {
  591. stringstream tmp;
  592. tmp << "Unknown query type: " << static_cast<int>(p.query_type);
  593. return (createAnswer(CONTROL_RESULT_ERROR, tmp.str()));
  594. }
  595. }
  596. } catch (const std::exception& ex) {
  597. return (createAnswer(CONTROL_RESULT_ERROR, ex.what()));
  598. }
  599. ElementPtr lease_json;
  600. if (v4 && lease4) {
  601. lease_json = lease4->toElement();
  602. return (createAnswer(CONTROL_RESULT_SUCCESS, "IPv4 lease found.", lease_json));
  603. }
  604. if (!v4 && lease6) {
  605. lease_json = lease6->toElement();
  606. return (createAnswer(CONTROL_RESULT_SUCCESS, "IPv6 lease found.", lease_json));
  607. }
  608. // If we got here, the lease has not been found.
  609. return (createAnswer(CONTROL_RESULT_EMPTY, "Lease not found."));
  610. }
  611. ConstElementPtr
  612. LeaseCmdsImpl::lease4DelHandler(const std::string& , ConstElementPtr params) {
  613. Parameters p;
  614. Lease4Ptr lease4;
  615. IOAddress addr(IOAddress::IPV4_ZERO_ADDRESS());
  616. try {
  617. p = getParameters(false, params);
  618. switch (p.query_type) {
  619. case Parameters::TYPE_ADDR: {
  620. // If address was specified explicitly, let's use it as is.
  621. addr = p.addr;
  622. break;
  623. }
  624. case Parameters::TYPE_HWADDR:
  625. if (!p.hwaddr) {
  626. return (createAnswer(CONTROL_RESULT_ERROR,
  627. "Program error: Query by hw-address "
  628. "requires hwaddr to be specified"));
  629. }
  630. // Let's see if there's such a lease at all.
  631. lease4 = LeaseMgrFactory::instance().getLease4(*p.hwaddr, p.subnet_id);
  632. if (!lease4) {
  633. return (createAnswer(CONTROL_RESULT_EMPTY, "IPv4 lease not found."));
  634. }
  635. // Found it, can use it as is.
  636. addr = lease4->addr_;
  637. break;
  638. case Parameters::TYPE_DUID:
  639. return (createAnswer(CONTROL_RESULT_ERROR,
  640. "Delete by duid is not allowed in v4."));
  641. break;
  642. default: {
  643. stringstream tmp;
  644. tmp << "Unknown query type: " << static_cast<int>(p.query_type);
  645. return (createAnswer(CONTROL_RESULT_ERROR, tmp.str()));
  646. }
  647. }
  648. if (LeaseMgrFactory::instance().deleteLease(addr)) {
  649. return (createAnswer(CONTROL_RESULT_SUCCESS, "IPv4 lease deleted."));
  650. } else {
  651. return (createAnswer(CONTROL_RESULT_EMPTY, "IPv4 lease not found."));
  652. }
  653. } catch (const std::exception& ex) {
  654. return (createAnswer(CONTROL_RESULT_ERROR, ex.what()));
  655. }
  656. }
  657. ConstElementPtr
  658. LeaseCmdsImpl::lease6DelHandler(const std::string& , ConstElementPtr params) {
  659. Parameters p;
  660. Lease6Ptr lease6;
  661. IOAddress addr(IOAddress::IPV6_ZERO_ADDRESS());
  662. try {
  663. p = getParameters(true, params);
  664. switch (p.query_type) {
  665. case Parameters::TYPE_ADDR: {
  666. // If address was specified explicitly, let's use it as is.
  667. addr = p.addr;
  668. break;
  669. }
  670. case Parameters::TYPE_HWADDR:
  671. return (createAnswer(CONTROL_RESULT_ERROR,
  672. "Delete by hw-address is not allowed in v6."));
  673. case Parameters::TYPE_DUID:
  674. if (!p.duid) {
  675. return (createAnswer(CONTROL_RESULT_ERROR,
  676. "Program error: Query by duid "
  677. "requires duid to be specified"));
  678. }
  679. // Let's see if there's such a lease at all.
  680. lease6 = LeaseMgrFactory::instance().getLease6(p.lease_type, *p.duid,
  681. p.iaid, p.subnet_id);
  682. if (!lease6) {
  683. return (createAnswer(CONTROL_RESULT_EMPTY, "IPv6 lease not found."));
  684. }
  685. // Found it, can use it as is.
  686. addr = lease6->addr_;
  687. break;
  688. default: {
  689. stringstream tmp;
  690. tmp << "Unknown query type: " << static_cast<int>(p.query_type);
  691. return (createAnswer(CONTROL_RESULT_ERROR, tmp.str()));
  692. }
  693. }
  694. if (LeaseMgrFactory::instance().deleteLease(addr)) {
  695. return (createAnswer(CONTROL_RESULT_SUCCESS, "IPv6 lease deleted."));
  696. } else {
  697. return (createAnswer(CONTROL_RESULT_EMPTY, "IPv6 lease not found."));
  698. }
  699. } catch (const std::exception& ex) {
  700. return (createAnswer(CONTROL_RESULT_ERROR, ex.what()));
  701. }
  702. }
  703. ConstElementPtr
  704. LeaseCmdsImpl::lease4UpdateHandler(const string& , ConstElementPtr params) {
  705. try {
  706. // We need the lease to be specified.
  707. if (!params) {
  708. isc_throw(isc::BadValue, "no parameters specified for lease4-update command");
  709. }
  710. // Get the parameters specified by the user first.
  711. ConstSrvConfigPtr config = CfgMgr::instance().getCurrentCfg();
  712. Lease4Ptr lease4;
  713. Lease4Parser parser;
  714. // The parser does sanity checks (if the address is in scope, if
  715. // subnet-id is valid, etc)
  716. lease4 = parser.parse(config, params);
  717. LeaseMgrFactory::instance().updateLease4(lease4);
  718. return (createAnswer(CONTROL_RESULT_SUCCESS, "IPv4 lease updated."));
  719. } catch (const std::exception& ex) {
  720. return (createAnswer(CONTROL_RESULT_ERROR, ex.what()));
  721. }
  722. }
  723. ConstElementPtr
  724. LeaseCmdsImpl::lease6UpdateHandler(const string& , ConstElementPtr params) {
  725. try {
  726. // We need the lease to be specified.
  727. if (!params) {
  728. isc_throw(isc::BadValue, "no parameters specified for lease6-update command");
  729. }
  730. // Get the parameters specified by the user first.
  731. ConstSrvConfigPtr config = CfgMgr::instance().getCurrentCfg();
  732. Lease6Ptr lease6;
  733. Lease6Parser parser;
  734. // The parser does sanity checks (if the address is in scope, if
  735. // subnet-id is valid, etc)
  736. lease6 = parser.parse(config, params);
  737. LeaseMgrFactory::instance().updateLease6(lease6);
  738. return (createAnswer(CONTROL_RESULT_SUCCESS, "IPv6 lease updated."));
  739. } catch (const std::exception& ex) {
  740. return (createAnswer(CONTROL_RESULT_ERROR, ex.what()));
  741. }
  742. }
  743. ConstElementPtr
  744. LeaseCmdsImpl::lease4WipeHandler(const string& /*cmd*/, ConstElementPtr params) {
  745. try {
  746. // The subnet-id is a mandatory parameter.
  747. if (!params) {
  748. isc_throw(isc::BadValue, "no parameters specified for lease4-wipe command");
  749. }
  750. SimpleParser parser;
  751. SubnetID id = parser.getUint32(params, "subnet-id");
  752. size_t num = LeaseMgrFactory::instance().wipeLeases4(id);
  753. stringstream tmp;
  754. tmp << "Deleted " << num << " IPv4 lease(s).";
  755. return (createAnswer(num ? CONTROL_RESULT_SUCCESS : CONTROL_RESULT_EMPTY,
  756. tmp.str()));
  757. } catch (const std::exception& ex) {
  758. return (createAnswer(CONTROL_RESULT_ERROR, ex.what()));
  759. }
  760. }
  761. ConstElementPtr
  762. LeaseCmdsImpl::lease6WipeHandler(const string& /*cmd*/, ConstElementPtr params) {
  763. try {
  764. // The subnet-id is a mandatory parameter.
  765. if (!params) {
  766. isc_throw(isc::BadValue, "no parameters specified for lease6-wipe command");
  767. }
  768. SimpleParser parser;
  769. SubnetID id = parser.getUint32(params, "subnet-id");
  770. size_t num = LeaseMgrFactory::instance().wipeLeases6(id);
  771. stringstream tmp;
  772. tmp << "Deleted " << num << " IPv6 lease(s).";
  773. return (createAnswer(num ? CONTROL_RESULT_SUCCESS : CONTROL_RESULT_EMPTY,
  774. tmp.str()));
  775. } catch (const std::exception& ex) {
  776. return (createAnswer(CONTROL_RESULT_ERROR, ex.what()));
  777. }
  778. }
  779. LeaseCmds::LeaseCmds()
  780. :impl_(new LeaseCmdsImpl()) {
  781. }
  782. LeaseCmds::~LeaseCmds() {
  783. impl_.reset();
  784. }
  785. };
  786. };