dhcp4_srv_unittest.cc 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324
  1. // Copyright (C) 2011-2013 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <config.h>
  15. #include <sstream>
  16. #include <asiolink/io_address.h>
  17. #include <dhcp/dhcp4.h>
  18. #include <dhcp/iface_mgr.h>
  19. #include <dhcp/option.h>
  20. #include <dhcp/option4_addrlst.h>
  21. #include <dhcp/option_custom.h>
  22. #include <dhcp/option_int_array.h>
  23. #include <dhcp4/dhcp4_srv.h>
  24. #include <dhcp4/dhcp4_log.h>
  25. #include <dhcpsrv/cfgmgr.h>
  26. #include <dhcpsrv/lease_mgr.h>
  27. #include <dhcpsrv/lease_mgr_factory.h>
  28. #include <dhcpsrv/utils.h>
  29. #include <gtest/gtest.h>
  30. #include <fstream>
  31. #include <iostream>
  32. #include <arpa/inet.h>
  33. using namespace std;
  34. using namespace isc;
  35. using namespace isc::dhcp;
  36. using namespace isc::asiolink;
  37. namespace {
  38. class NakedDhcpv4Srv: public Dhcpv4Srv {
  39. // "Naked" DHCPv4 server, exposes internal fields
  40. public:
  41. /// @brief Constructor.
  42. ///
  43. /// It disables configuration of broadcast options on
  44. /// sockets that are opened by the Dhcpv4Srv constructor.
  45. /// Also, disables the Direct V4 traffic as it requires
  46. /// use of raw sockets. Use of broadcast as well as raw
  47. /// sockets require root privileges, thus can't be used
  48. /// in unit testing.
  49. NakedDhcpv4Srv(uint16_t port = 0)
  50. : Dhcpv4Srv(port, "type=memfile", false, false) {
  51. }
  52. using Dhcpv4Srv::processDiscover;
  53. using Dhcpv4Srv::processRequest;
  54. using Dhcpv4Srv::processRelease;
  55. using Dhcpv4Srv::processDecline;
  56. using Dhcpv4Srv::processInform;
  57. using Dhcpv4Srv::getServerID;
  58. using Dhcpv4Srv::loadServerID;
  59. using Dhcpv4Srv::generateServerID;
  60. using Dhcpv4Srv::writeServerID;
  61. using Dhcpv4Srv::sanityCheck;
  62. using Dhcpv4Srv::srvidToString;
  63. };
  64. static const char* SRVID_FILE = "server-id-test.txt";
  65. class Dhcpv4SrvTest : public ::testing::Test {
  66. public:
  67. /// @brief Constructor
  68. ///
  69. /// Initializes common objects used in many tests.
  70. /// Also sets up initial configuration in CfgMgr.
  71. Dhcpv4SrvTest() {
  72. subnet_ = Subnet4Ptr(new Subnet4(IOAddress("192.0.2.0"), 24, 1000,
  73. 2000, 3000));
  74. pool_ = Pool4Ptr(new Pool4(IOAddress("192.0.2.100"), IOAddress("192.0.2.110")));
  75. subnet_->addPool(pool_);
  76. CfgMgr::instance().deleteSubnets4();
  77. CfgMgr::instance().addSubnet4(subnet_);
  78. // Add Router option.
  79. Option4AddrLstPtr opt_routers(new Option4AddrLst(DHO_ROUTERS));
  80. opt_routers->setAddress(IOAddress("192.0.2.2"));
  81. subnet_->addOption(opt_routers, false, "dhcp4");
  82. // it's ok if that fails. There should not be such a file anyway
  83. unlink(SRVID_FILE);
  84. }
  85. /// @brief Add 'Parameter Request List' option to the packet.
  86. ///
  87. /// This function PRL option comprising the following option codes:
  88. /// - 5 - Name Server
  89. /// - 15 - Domain Name
  90. /// - 7 - Log Server
  91. /// - 8 - Quotes Server
  92. /// - 9 - LPR Server
  93. ///
  94. /// @param pkt packet to add PRL option to.
  95. void addPrlOption(Pkt4Ptr& pkt) {
  96. OptionUint8ArrayPtr option_prl =
  97. OptionUint8ArrayPtr(new OptionUint8Array(Option::V4,
  98. DHO_DHCP_PARAMETER_REQUEST_LIST));
  99. // Let's request options that have been configured for the subnet.
  100. option_prl->addValue(DHO_DOMAIN_NAME_SERVERS);
  101. option_prl->addValue(DHO_DOMAIN_NAME);
  102. option_prl->addValue(DHO_LOG_SERVERS);
  103. option_prl->addValue(DHO_COOKIE_SERVERS);
  104. // Let's also request the option that hasn't been configured. In such
  105. // case server should ignore request for this particular option.
  106. option_prl->addValue(DHO_LPR_SERVERS);
  107. // And add 'Parameter Request List' option into the DISCOVER packet.
  108. pkt->addOption(option_prl);
  109. }
  110. /// @brief Configures options being requested in the PRL option.
  111. ///
  112. /// The lpr-servers option is NOT configured here although it is
  113. /// added to the 'Parameter Request List' option in the
  114. /// \ref addPrlOption. When requested option is not configured
  115. /// the server should not return it in its response. The goal
  116. /// of not configuring the requested option is to verify that
  117. /// the server will not return it.
  118. void configureRequestedOptions() {
  119. // dns-servers
  120. Option4AddrLstPtr
  121. option_dns_servers(new Option4AddrLst(DHO_DOMAIN_NAME_SERVERS));
  122. option_dns_servers->addAddress(IOAddress("192.0.2.1"));
  123. option_dns_servers->addAddress(IOAddress("192.0.2.100"));
  124. ASSERT_NO_THROW(subnet_->addOption(option_dns_servers, false, "dhcp4"));
  125. // domain-name
  126. OptionDefinition def("domain-name", DHO_DOMAIN_NAME, OPT_FQDN_TYPE);
  127. boost::shared_ptr<OptionCustom>
  128. option_domain_name(new OptionCustom(def, Option::V4));
  129. option_domain_name->writeFqdn("example.com");
  130. subnet_->addOption(option_domain_name, false, "dhcp4");
  131. // log-servers
  132. Option4AddrLstPtr option_log_servers(new Option4AddrLst(DHO_LOG_SERVERS));
  133. option_log_servers->addAddress(IOAddress("192.0.2.2"));
  134. option_log_servers->addAddress(IOAddress("192.0.2.10"));
  135. ASSERT_NO_THROW(subnet_->addOption(option_log_servers, false, "dhcp4"));
  136. // cookie-servers
  137. Option4AddrLstPtr option_cookie_servers(new Option4AddrLst(DHO_COOKIE_SERVERS));
  138. option_cookie_servers->addAddress(IOAddress("192.0.2.1"));
  139. ASSERT_NO_THROW(subnet_->addOption(option_cookie_servers, false, "dhcp4"));
  140. }
  141. /// @brief checks that the response matches request
  142. /// @param q query (client's message)
  143. /// @param a answer (server's message)
  144. void messageCheck(const boost::shared_ptr<Pkt4>& q,
  145. const boost::shared_ptr<Pkt4>& a) {
  146. ASSERT_TRUE(q);
  147. ASSERT_TRUE(a);
  148. EXPECT_EQ(q->getHops(), a->getHops());
  149. EXPECT_EQ(q->getIface(), a->getIface());
  150. EXPECT_EQ(q->getIndex(), a->getIndex());
  151. EXPECT_EQ(q->getGiaddr(), a->getGiaddr());
  152. // Check that bare minimum of required options are there.
  153. // We don't check options requested by a client. Those
  154. // are checked elsewhere.
  155. EXPECT_TRUE(a->getOption(DHO_SUBNET_MASK));
  156. EXPECT_TRUE(a->getOption(DHO_ROUTERS));
  157. EXPECT_TRUE(a->getOption(DHO_DHCP_SERVER_IDENTIFIER));
  158. EXPECT_TRUE(a->getOption(DHO_DHCP_LEASE_TIME));
  159. EXPECT_TRUE(a->getOption(DHO_SUBNET_MASK));
  160. EXPECT_TRUE(a->getOption(DHO_DOMAIN_NAME));
  161. EXPECT_TRUE(a->getOption(DHO_DOMAIN_NAME_SERVERS));
  162. // Check that something is offered
  163. EXPECT_TRUE(a->getYiaddr().toText() != "0.0.0.0");
  164. }
  165. /// @brief Check that requested options are present.
  166. ///
  167. /// @param pkt packet to be checked.
  168. void optionsCheck(const Pkt4Ptr& pkt) {
  169. // Check that the requested and configured options are returned
  170. // in the ACK message.
  171. EXPECT_TRUE(pkt->getOption(DHO_DOMAIN_NAME))
  172. << "domain-name not present in the response";
  173. EXPECT_TRUE(pkt->getOption(DHO_DOMAIN_NAME_SERVERS))
  174. << "dns-servers not present in the response";
  175. EXPECT_TRUE(pkt->getOption(DHO_LOG_SERVERS))
  176. << "log-servers not present in the response";
  177. EXPECT_TRUE(pkt->getOption(DHO_COOKIE_SERVERS))
  178. << "cookie-servers not present in the response";
  179. // Check that the requested but not configured options are not
  180. // returned in the ACK message.
  181. EXPECT_FALSE(pkt->getOption(DHO_LPR_SERVERS))
  182. << "domain-name present in the response but it is"
  183. << " expected not to be present";
  184. }
  185. /// @brief generates client-id option
  186. ///
  187. /// Generate client-id option of specified length
  188. /// Ids with different lengths are sufficent to generate
  189. /// unique ids. If more fine grained control is required,
  190. /// tests generate client-ids on their own.
  191. /// Sets client_id_ field.
  192. /// @param size size of the client-id to be generated
  193. OptionPtr generateClientId(size_t size = 4) {
  194. OptionBuffer clnt_id(size);
  195. for (int i = 0; i < size; i++) {
  196. clnt_id[i] = 100 + i;
  197. }
  198. client_id_ = ClientIdPtr(new ClientId(clnt_id));
  199. return (OptionPtr(new Option(Option::V4, DHO_DHCP_CLIENT_IDENTIFIER,
  200. clnt_id.begin(),
  201. clnt_id.begin() + size)));
  202. }
  203. /// @brief generate hardware address
  204. ///
  205. /// @param size size of the generated MAC address
  206. /// @param pointer to Hardware Address object
  207. HWAddrPtr generateHWAddr(size_t size = 6) {
  208. const uint8_t hw_type = 123; // Just a fake number (typically 6=HTYPE_ETHER, see dhcp4.h)
  209. OptionBuffer mac(size);
  210. for (int i = 0; i < size; ++i) {
  211. mac[i] = 50 + i;
  212. }
  213. return (HWAddrPtr(new HWAddr(mac, hw_type)));
  214. }
  215. /// Check that address was returned from proper range, that its lease
  216. /// lifetime is correct, that T1 and T2 are returned properly
  217. /// @param rsp response to be checked
  218. /// @param subnet subnet that should be used to verify assigned address
  219. /// and options
  220. /// @param t1_mandatory is T1 mandatory?
  221. /// @param t2_mandatory is T2 mandatory?
  222. void checkAddressParams(const Pkt4Ptr& rsp, const SubnetPtr subnet,
  223. bool t1_mandatory = false,
  224. bool t2_mandatory = false) {
  225. // Technically inPool implies inRange, but let's be on the safe
  226. // side and check both.
  227. EXPECT_TRUE(subnet->inRange(rsp->getYiaddr()));
  228. EXPECT_TRUE(subnet->inPool(rsp->getYiaddr()));
  229. // Check lease time
  230. OptionPtr opt = rsp->getOption(DHO_DHCP_LEASE_TIME);
  231. if (!opt) {
  232. ADD_FAILURE() << "Lease time option missing in response";
  233. } else {
  234. EXPECT_EQ(opt->getUint32(), subnet->getValid());
  235. }
  236. // Check T1 timer
  237. opt = rsp->getOption(DHO_DHCP_RENEWAL_TIME);
  238. if (opt) {
  239. EXPECT_EQ(opt->getUint32(), subnet->getT1());
  240. } else {
  241. if (t1_mandatory) {
  242. ADD_FAILURE() << "Required T1 option missing";
  243. }
  244. }
  245. // Check T2 timer
  246. opt = rsp->getOption(DHO_DHCP_REBINDING_TIME);
  247. if (opt) {
  248. EXPECT_EQ(opt->getUint32(), subnet->getT2());
  249. } else {
  250. if (t2_mandatory) {
  251. ADD_FAILURE() << "Required T2 option missing";
  252. }
  253. }
  254. }
  255. /// @brief Basic checks for generated response (message type and trans-id).
  256. ///
  257. /// @param rsp response packet to be validated
  258. /// @param expected_message_type expected message type
  259. /// @param expected_transid expected transaction-id
  260. void checkResponse(const Pkt4Ptr& rsp, uint8_t expected_message_type,
  261. uint32_t expected_transid) {
  262. ASSERT_TRUE(rsp);
  263. EXPECT_EQ(expected_message_type, rsp->getType());
  264. EXPECT_EQ(expected_transid, rsp->getTransid());
  265. }
  266. /// @brief Checks if the lease sent to client is present in the database
  267. ///
  268. /// @param rsp response packet to be validated
  269. /// @param client_id expected client-identifier (or NULL)
  270. /// @param HWAddr expected hardware address (not used now)
  271. /// @param expected_addr expected address
  272. Lease4Ptr checkLease(const Pkt4Ptr& rsp, const OptionPtr& client_id,
  273. const HWAddrPtr&, const IOAddress& expected_addr) {
  274. ClientIdPtr id;
  275. if (client_id) {
  276. OptionBuffer data = client_id->getData();
  277. id.reset(new ClientId(data));
  278. }
  279. Lease4Ptr lease = LeaseMgrFactory::instance().getLease4(expected_addr);
  280. if (!lease) {
  281. cout << "Lease for " << expected_addr.toText()
  282. << " not found in the database backend.";
  283. return (Lease4Ptr());
  284. }
  285. EXPECT_EQ(rsp->getYiaddr().toText(), expected_addr.toText());
  286. EXPECT_EQ(expected_addr.toText(), lease->addr_.toText());
  287. if (client_id) {
  288. EXPECT_TRUE(*lease->client_id_ == *id);
  289. }
  290. EXPECT_EQ(subnet_->getID(), lease->subnet_id_);
  291. return (lease);
  292. }
  293. /// @brief Checks if server response (OFFER, ACK, NAK) includes proper server-id
  294. /// @param rsp response packet to be validated
  295. /// @param expected_srvid expected value of server-id
  296. void checkServerId(const Pkt4Ptr& rsp, const OptionPtr& expected_srvid) {
  297. // Check that server included its server-id
  298. OptionPtr opt = rsp->getOption(DHO_DHCP_SERVER_IDENTIFIER);
  299. ASSERT_TRUE(opt);
  300. EXPECT_EQ(opt->getType(), expected_srvid->getType() );
  301. EXPECT_EQ(opt->len(), expected_srvid->len() );
  302. EXPECT_TRUE(opt->getData() == expected_srvid->getData());
  303. }
  304. /// @brief Checks if server response (OFFER, ACK, NAK) includes proper client-id
  305. /// @param rsp response packet to be validated
  306. /// @param expected_clientid expected value of client-id
  307. void checkClientId(const Pkt4Ptr& rsp, const OptionPtr& expected_clientid) {
  308. // check that server included our own client-id
  309. OptionPtr opt = rsp->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
  310. ASSERT_TRUE(opt);
  311. EXPECT_EQ(expected_clientid->getType(), opt->getType());
  312. EXPECT_EQ(expected_clientid->len(), opt->len());
  313. EXPECT_TRUE(expected_clientid->getData() == opt->getData());
  314. }
  315. /// @brief Tests if Discover or Request message is processed correctly
  316. ///
  317. /// @param msg_type DHCPDISCOVER or DHCPREQUEST
  318. /// @param client_addr client address
  319. /// @param relay_addr relay address
  320. void testDiscoverRequest(const uint8_t msg_type,
  321. const IOAddress& client_addr,
  322. const IOAddress& relay_addr) {
  323. boost::scoped_ptr<NakedDhcpv4Srv> srv(new NakedDhcpv4Srv(0));
  324. vector<uint8_t> mac(6);
  325. for (int i = 0; i < 6; i++) {
  326. mac[i] = i*10;
  327. }
  328. boost::shared_ptr<Pkt4> req(new Pkt4(msg_type, 1234));
  329. boost::shared_ptr<Pkt4> rsp;
  330. req->setIface("eth0");
  331. req->setIndex(17);
  332. req->setHWAddr(1, 6, mac);
  333. req->setRemoteAddr(IOAddress(client_addr));
  334. req->setGiaddr(relay_addr);
  335. // We are going to test that certain options are returned
  336. // in the response message when requested using 'Parameter
  337. // Request List' option. Let's configure those options that
  338. // are returned when requested.
  339. configureRequestedOptions();
  340. if (msg_type == DHCPDISCOVER) {
  341. ASSERT_NO_THROW(
  342. rsp = srv->processDiscover(req);
  343. );
  344. // Should return OFFER
  345. ASSERT_TRUE(rsp);
  346. EXPECT_EQ(DHCPOFFER, rsp->getType());
  347. } else {
  348. ASSERT_NO_THROW(
  349. rsp = srv->processRequest(req);
  350. );
  351. // Should return ACK
  352. ASSERT_TRUE(rsp);
  353. EXPECT_EQ(DHCPACK, rsp->getType());
  354. }
  355. if (relay_addr.toText() != "0.0.0.0") {
  356. // This is relayed message. It should be sent brsp to relay address.
  357. EXPECT_EQ(req->getGiaddr().toText(),
  358. rsp->getRemoteAddr().toText());
  359. } else if (client_addr.toText() != "0.0.0.0") {
  360. // This is a message from a client having an IP address.
  361. EXPECT_EQ(req->getRemoteAddr().toText(),
  362. rsp->getRemoteAddr().toText());
  363. } else {
  364. // This is a message from a client having no IP address yet.
  365. // If IfaceMgr supports direct traffic the response should
  366. // be sent to the new address assigned to the client.
  367. if (IfaceMgr::instance().isDirectResponseSupported()) {
  368. EXPECT_EQ(rsp->getYiaddr(),
  369. rsp->getRemoteAddr().toText());
  370. // If direct response to the client having no IP address is
  371. // not supported, response should go to broadcast.
  372. } else {
  373. EXPECT_EQ("255.255.255.255", rsp->getRemoteAddr().toText());
  374. }
  375. }
  376. messageCheck(req, rsp);
  377. // We did not request any options so these should not be present
  378. // in the RSP.
  379. EXPECT_FALSE(rsp->getOption(DHO_LOG_SERVERS));
  380. EXPECT_FALSE(rsp->getOption(DHO_COOKIE_SERVERS));
  381. EXPECT_FALSE(rsp->getOption(DHO_LPR_SERVERS));
  382. // Repeat the test but request some options.
  383. // Add 'Parameter Request List' option.
  384. addPrlOption(req);
  385. if (msg_type == DHCPDISCOVER) {
  386. ASSERT_NO_THROW(
  387. rsp = srv->processDiscover(req);
  388. );
  389. // Should return non-NULL packet.
  390. ASSERT_TRUE(rsp);
  391. EXPECT_EQ(DHCPOFFER, rsp->getType());
  392. } else {
  393. ASSERT_NO_THROW(
  394. rsp = srv->processRequest(req);
  395. );
  396. // Should return non-NULL packet.
  397. ASSERT_TRUE(rsp);
  398. EXPECT_EQ(DHCPACK, rsp->getType());
  399. }
  400. // Check that the requested options are returned.
  401. optionsCheck(rsp);
  402. }
  403. ~Dhcpv4SrvTest() {
  404. CfgMgr::instance().deleteSubnets4();
  405. // Let's clean up if there is such a file.
  406. unlink(SRVID_FILE);
  407. };
  408. /// @brief A subnet used in most tests
  409. Subnet4Ptr subnet_;
  410. /// @brief A pool used in most tests
  411. Pool4Ptr pool_;
  412. /// @brief A client-id used in most tests
  413. ClientIdPtr client_id_;
  414. };
  415. // Sanity check. Verifies that both Dhcpv4Srv and its derived
  416. // class NakedDhcpv4Srv can be instantiated and destroyed.
  417. TEST_F(Dhcpv4SrvTest, basic) {
  418. // Check that the base class can be instantiated
  419. Dhcpv4Srv* srv = NULL;
  420. ASSERT_NO_THROW({
  421. srv = new Dhcpv4Srv(DHCP4_SERVER_PORT + 10000);
  422. });
  423. delete srv;
  424. // Check that the derived class can be instantiated
  425. NakedDhcpv4Srv* naked_srv = NULL;
  426. ASSERT_NO_THROW({
  427. naked_srv = new NakedDhcpv4Srv(DHCP4_SERVER_PORT + 10000);
  428. });
  429. EXPECT_TRUE(naked_srv->getServerID());
  430. delete naked_srv;
  431. ASSERT_NO_THROW({
  432. naked_srv = new NakedDhcpv4Srv(0);
  433. });
  434. EXPECT_TRUE(naked_srv->getServerID());
  435. delete naked_srv;
  436. }
  437. // Verifies that DISCOVER received via relay can be processed correctly,
  438. // that the OFFER message generated in response is valid and
  439. // contains necessary options.
  440. //
  441. // Note: this test focuses on the packet correctness. There
  442. // are other tests that verify correctness of the allocation
  443. // engine. See DiscoverBasic, DiscoverHint, DiscoverNoClientId
  444. // and DiscoverInvalidHint.
  445. TEST_F(Dhcpv4SrvTest, processDiscoverRelay) {
  446. testDiscoverRequest(DHCPDISCOVER,
  447. IOAddress("192.0.2.56"),
  448. IOAddress("192.0.2.67"));
  449. }
  450. // Verifies that the non-relayed DISCOVER is processed correctly when
  451. // client source address is specified.
  452. TEST_F(Dhcpv4SrvTest, processDiscoverNoRelay) {
  453. testDiscoverRequest(DHCPDISCOVER,
  454. IOAddress("0.0.0.0"),
  455. IOAddress("192.0.2.67"));
  456. }
  457. // Verified that the non-relayed DISCOVER is processed correctly when
  458. // client source address is not specified.
  459. TEST_F(Dhcpv4SrvTest, processDiscoverNoClientAddr) {
  460. testDiscoverRequest(DHCPDISCOVER,
  461. IOAddress("0.0.0.0"),
  462. IOAddress("0.0.0.0"));
  463. }
  464. // Verifies that REQUEST received via relay can be processed correctly,
  465. // that the OFFER message generated in response is valid and
  466. // contains necessary options.
  467. //
  468. // Note: this test focuses on the packet correctness. There
  469. // are other tests that verify correctness of the allocation
  470. // engine. See DiscoverBasic, DiscoverHint, DiscoverNoClientId
  471. // and DiscoverInvalidHint.
  472. TEST_F(Dhcpv4SrvTest, processRequestRelay) {
  473. testDiscoverRequest(DHCPREQUEST,
  474. IOAddress("192.0.2.56"),
  475. IOAddress("192.0.2.67"));
  476. }
  477. // Verifies that the non-relayed REQUEST is processed correctly when
  478. // client source address is specified.
  479. TEST_F(Dhcpv4SrvTest, processRequestNoRelay) {
  480. testDiscoverRequest(DHCPREQUEST,
  481. IOAddress("0.0.0.0"),
  482. IOAddress("192.0.2.67"));
  483. }
  484. // Verified that the non-relayed REQUEST is processed correctly when
  485. // client source address is not specified.
  486. TEST_F(Dhcpv4SrvTest, processRequestNoClientAddr) {
  487. testDiscoverRequest(DHCPREQUEST,
  488. IOAddress("0.0.0.0"),
  489. IOAddress("0.0.0.0"));
  490. }
  491. TEST_F(Dhcpv4SrvTest, processRelease) {
  492. NakedDhcpv4Srv* srv = new NakedDhcpv4Srv();
  493. boost::shared_ptr<Pkt4> pkt(new Pkt4(DHCPRELEASE, 1234));
  494. // Should not throw
  495. EXPECT_NO_THROW(
  496. srv->processRelease(pkt);
  497. );
  498. delete srv;
  499. }
  500. TEST_F(Dhcpv4SrvTest, processDecline) {
  501. NakedDhcpv4Srv* srv = new NakedDhcpv4Srv();
  502. boost::shared_ptr<Pkt4> pkt(new Pkt4(DHCPDECLINE, 1234));
  503. // Should not throw
  504. EXPECT_NO_THROW(
  505. srv->processDecline(pkt);
  506. );
  507. delete srv;
  508. }
  509. TEST_F(Dhcpv4SrvTest, processInform) {
  510. NakedDhcpv4Srv* srv = new NakedDhcpv4Srv();
  511. boost::shared_ptr<Pkt4> pkt(new Pkt4(DHCPINFORM, 1234));
  512. // Should not throw
  513. EXPECT_NO_THROW(
  514. srv->processInform(pkt);
  515. );
  516. // Should return something
  517. EXPECT_TRUE(srv->processInform(pkt));
  518. // @todo Implement more reasonable tests before starting
  519. // work on processSomething() method.
  520. delete srv;
  521. }
  522. TEST_F(Dhcpv4SrvTest, serverReceivedPacketName) {
  523. // Check all possible packet types
  524. for (int itype = 0; itype < 256; ++itype) {
  525. uint8_t type = itype;
  526. switch (type) {
  527. case DHCPDECLINE:
  528. EXPECT_STREQ("DECLINE", Dhcpv4Srv::serverReceivedPacketName(type));
  529. break;
  530. case DHCPDISCOVER:
  531. EXPECT_STREQ("DISCOVER", Dhcpv4Srv::serverReceivedPacketName(type));
  532. break;
  533. case DHCPINFORM:
  534. EXPECT_STREQ("INFORM", Dhcpv4Srv::serverReceivedPacketName(type));
  535. break;
  536. case DHCPRELEASE:
  537. EXPECT_STREQ("RELEASE", Dhcpv4Srv::serverReceivedPacketName(type));
  538. break;
  539. case DHCPREQUEST:
  540. EXPECT_STREQ("REQUEST", Dhcpv4Srv::serverReceivedPacketName(type));
  541. break;
  542. default:
  543. EXPECT_STREQ("UNKNOWN", Dhcpv4Srv::serverReceivedPacketName(type));
  544. }
  545. }
  546. }
  547. // This test verifies that incoming DISCOVER can be handled properly, that an
  548. // OFFER is generated, that the response has an address and that address
  549. // really belongs to the configured pool.
  550. //
  551. // constructed very simple DISCOVER message with:
  552. // - client-id option
  553. //
  554. // expected returned OFFER message:
  555. // - copy of client-id
  556. // - server-id
  557. // - offered address
  558. TEST_F(Dhcpv4SrvTest, DiscoverBasic) {
  559. boost::scoped_ptr<NakedDhcpv4Srv> srv;
  560. ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
  561. Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
  562. dis->setRemoteAddr(IOAddress("192.0.2.1"));
  563. OptionPtr clientid = generateClientId();
  564. dis->addOption(clientid);
  565. // Pass it to the server and get an offer
  566. Pkt4Ptr offer = srv->processDiscover(dis);
  567. // Check if we get response at all
  568. checkResponse(offer, DHCPOFFER, 1234);
  569. // Check that address was returned from proper range, that its lease
  570. // lifetime is correct, that T1 and T2 are returned properly
  571. checkAddressParams(offer, subnet_);
  572. // Check identifiers
  573. checkServerId(offer, srv->getServerID());
  574. checkClientId(offer, clientid);
  575. }
  576. // This test verifies that incoming DISCOVER can be handled properly, that an
  577. // OFFER is generated, that the response has an address and that address
  578. // really belongs to the configured pool.
  579. //
  580. // constructed very simple DISCOVER message with:
  581. // - client-id option
  582. // - address set to specific value as hint
  583. //
  584. // expected returned OFFER message:
  585. // - copy of client-id
  586. // - server-id
  587. // - offered address
  588. TEST_F(Dhcpv4SrvTest, DiscoverHint) {
  589. boost::scoped_ptr<NakedDhcpv4Srv> srv;
  590. ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
  591. IOAddress hint("192.0.2.107");
  592. Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
  593. dis->setRemoteAddr(IOAddress("192.0.2.1"));
  594. OptionPtr clientid = generateClientId();
  595. dis->addOption(clientid);
  596. dis->setYiaddr(hint);
  597. // Pass it to the server and get an offer
  598. Pkt4Ptr offer = srv->processDiscover(dis);
  599. // Check if we get response at all
  600. checkResponse(offer, DHCPOFFER, 1234);
  601. // Check that address was returned from proper range, that its lease
  602. // lifetime is correct, that T1 and T2 are returned properly
  603. checkAddressParams(offer, subnet_);
  604. EXPECT_EQ(offer->getYiaddr().toText(), hint.toText());
  605. // Check identifiers
  606. checkServerId(offer, srv->getServerID());
  607. checkClientId(offer, clientid);
  608. }
  609. // This test verifies that incoming DISCOVER can be handled properly, that an
  610. // OFFER is generated, that the response has an address and that address
  611. // really belongs to the configured pool.
  612. //
  613. // constructed very simple DISCOVER message with:
  614. // - address set to specific value as hint
  615. //
  616. // expected returned OFFER message:
  617. // - copy of client-id
  618. // - server-id
  619. // - offered address
  620. TEST_F(Dhcpv4SrvTest, DiscoverNoClientId) {
  621. boost::scoped_ptr<NakedDhcpv4Srv> srv;
  622. ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
  623. IOAddress hint("192.0.2.107");
  624. Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
  625. dis->setRemoteAddr(IOAddress("192.0.2.1"));
  626. dis->setYiaddr(hint);
  627. // Pass it to the server and get an offer
  628. Pkt4Ptr offer = srv->processDiscover(dis);
  629. // Check if we get response at all
  630. checkResponse(offer, DHCPOFFER, 1234);
  631. // Check that address was returned from proper range, that its lease
  632. // lifetime is correct, that T1 and T2 are returned properly
  633. checkAddressParams(offer, subnet_);
  634. EXPECT_EQ(offer->getYiaddr().toText(), hint.toText());
  635. // Check identifiers
  636. checkServerId(offer, srv->getServerID());
  637. }
  638. // This test verifies that incoming DISCOVER can be handled properly, that an
  639. // OFFER is generated, that the response has an address and that address
  640. // really belongs to the configured pool.
  641. //
  642. // constructed very simple DISCOVER message with:
  643. // - client-id option
  644. // - address set to specific value as hint, but that hint is invalid
  645. //
  646. // expected returned OFFER message:
  647. // - copy of client-id
  648. // - server-id
  649. // - offered address (!= hint)
  650. TEST_F(Dhcpv4SrvTest, DiscoverInvalidHint) {
  651. boost::scoped_ptr<NakedDhcpv4Srv> srv;
  652. ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
  653. IOAddress hint("10.1.2.3");
  654. Pkt4Ptr dis = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
  655. dis->setRemoteAddr(IOAddress("192.0.2.107"));
  656. OptionPtr clientid = generateClientId();
  657. dis->addOption(clientid);
  658. dis->setYiaddr(hint);
  659. // Pass it to the server and get an offer
  660. Pkt4Ptr offer = srv->processDiscover(dis);
  661. // Check if we get response at all
  662. checkResponse(offer, DHCPOFFER, 1234);
  663. // Check that address was returned from proper range, that its lease
  664. // lifetime is correct, that T1 and T2 are returned properly
  665. checkAddressParams(offer, subnet_);
  666. EXPECT_NE(offer->getYiaddr().toText(), hint.toText());
  667. // Check identifiers
  668. checkServerId(offer, srv->getServerID());
  669. checkClientId(offer, clientid);
  670. }
  671. /// @todo: Add a test that client sends hint that is in pool, but currently
  672. /// being used by a different client.
  673. // This test checks that the server is offering different addresses to different
  674. // clients in OFFERs. Please note that OFFER is not a guarantee that such
  675. // an address will be assigned. Had the pool was very small and contained only
  676. // 2 addresses, the third client would get the same offer as the first one
  677. // and this is a correct behavior. It is REQUEST that will fail for the third
  678. // client. OFFER is basically saying "if you send me a request, you will
  679. // probably get an address like this" (there are no guarantees).
  680. TEST_F(Dhcpv4SrvTest, ManyDiscovers) {
  681. boost::scoped_ptr<NakedDhcpv4Srv> srv;
  682. ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
  683. Pkt4Ptr dis1 = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
  684. Pkt4Ptr dis2 = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 2345));
  685. Pkt4Ptr dis3 = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 3456));
  686. dis1->setRemoteAddr(IOAddress("192.0.2.1"));
  687. dis2->setRemoteAddr(IOAddress("192.0.2.2"));
  688. dis3->setRemoteAddr(IOAddress("192.0.2.3"));
  689. // Different client-id sizes
  690. OptionPtr clientid1 = generateClientId(4); // length 4
  691. OptionPtr clientid2 = generateClientId(5); // length 5
  692. OptionPtr clientid3 = generateClientId(6); // length 6
  693. dis1->addOption(clientid1);
  694. dis2->addOption(clientid2);
  695. dis3->addOption(clientid3);
  696. // Pass it to the server and get an offer
  697. Pkt4Ptr offer1 = srv->processDiscover(dis1);
  698. Pkt4Ptr offer2 = srv->processDiscover(dis2);
  699. Pkt4Ptr offer3 = srv->processDiscover(dis3);
  700. // Check if we get response at all
  701. checkResponse(offer1, DHCPOFFER, 1234);
  702. checkResponse(offer2, DHCPOFFER, 2345);
  703. checkResponse(offer3, DHCPOFFER, 3456);
  704. IOAddress addr1 = offer1->getYiaddr();
  705. IOAddress addr2 = offer2->getYiaddr();
  706. IOAddress addr3 = offer3->getYiaddr();
  707. // Check that the assigned address is indeed from the configured pool
  708. checkAddressParams(offer1, subnet_);
  709. checkAddressParams(offer2, subnet_);
  710. checkAddressParams(offer3, subnet_);
  711. // Check server-ids
  712. checkServerId(offer1, srv->getServerID());
  713. checkServerId(offer2, srv->getServerID());
  714. checkServerId(offer3, srv->getServerID());
  715. checkClientId(offer1, clientid1);
  716. checkClientId(offer2, clientid2);
  717. checkClientId(offer3, clientid3);
  718. // Finally check that the addresses offered are different
  719. EXPECT_NE(addr1.toText(), addr2.toText());
  720. EXPECT_NE(addr2.toText(), addr3.toText());
  721. EXPECT_NE(addr3.toText(), addr1.toText());
  722. cout << "Offered address to client1=" << addr1.toText() << endl;
  723. cout << "Offered address to client2=" << addr2.toText() << endl;
  724. cout << "Offered address to client3=" << addr3.toText() << endl;
  725. }
  726. // This test verifies that incoming REQUEST can be handled properly, that an
  727. // ACK is generated, that the response has an address and that address
  728. // really belongs to the configured pool.
  729. //
  730. // constructed a single REQUEST message with:
  731. // - client-id option
  732. // - hwaddr information
  733. // - requested address (that the client received in DISCOVER/OFFER exchange)
  734. //
  735. // expected returned ACK message:
  736. // - copy of client-id
  737. // - server-id
  738. // - assigned address
  739. //
  740. // Test verifies that the lease is actually in the database.
  741. TEST_F(Dhcpv4SrvTest, RequestBasic) {
  742. boost::scoped_ptr<NakedDhcpv4Srv> srv;
  743. ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
  744. IOAddress hint("192.0.2.107");
  745. Pkt4Ptr req = Pkt4Ptr(new Pkt4(DHCPREQUEST, 1234));
  746. req->setRemoteAddr(IOAddress("192.0.2.1"));
  747. OptionPtr clientid = generateClientId();
  748. req->addOption(clientid);
  749. req->setYiaddr(hint);
  750. // Pass it to the server and get an advertise
  751. Pkt4Ptr ack = srv->processRequest(req);
  752. // Check if we get response at all
  753. checkResponse(ack, DHCPACK, 1234);
  754. EXPECT_EQ(hint.toText(), ack->getYiaddr().toText());
  755. // Check that address was returned from proper range, that its lease
  756. // lifetime is correct, that T1 and T2 are returned properly
  757. checkAddressParams(ack, subnet_);
  758. // Check identifiers
  759. checkServerId(ack, srv->getServerID());
  760. checkClientId(ack, clientid);
  761. // Check that the lease is really in the database
  762. Lease4Ptr l = checkLease(ack, clientid, req->getHWAddr(), hint);
  763. ASSERT_TRUE(l);
  764. LeaseMgrFactory::instance().deleteLease(l->addr_);
  765. }
  766. // This test verifies that incoming REQUEST can be handled properly, that an
  767. // ACK is generated, that the response has an address and that address
  768. // really belongs to the configured pool.
  769. //
  770. // constructed 3 REQUEST messages with:
  771. // - client-id option (differs between messages)
  772. // - hwaddr information (differs between messages)
  773. //
  774. // expected returned ACK message:
  775. // - copy of client-id
  776. // - server-id
  777. // - assigned address (different for each client)
  778. TEST_F(Dhcpv4SrvTest, ManyRequests) {
  779. boost::scoped_ptr<NakedDhcpv4Srv> srv;
  780. ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
  781. const IOAddress req_addr1("192.0.2.105");
  782. const IOAddress req_addr2("192.0.2.101");
  783. const IOAddress req_addr3("192.0.2.109");
  784. const IOAddress relay("192.0.2.1");
  785. Pkt4Ptr req1 = Pkt4Ptr(new Pkt4(DHCPOFFER, 1234));
  786. Pkt4Ptr req2 = Pkt4Ptr(new Pkt4(DHCPOFFER, 2345));
  787. Pkt4Ptr req3 = Pkt4Ptr(new Pkt4(DHCPOFFER, 3456));
  788. req1->setRemoteAddr(relay);
  789. req2->setRemoteAddr(relay);
  790. req3->setRemoteAddr(relay);
  791. req1->setYiaddr(req_addr1);
  792. req2->setYiaddr(req_addr2);
  793. req3->setYiaddr(req_addr3);
  794. req1->setHWAddr(generateHWAddr(6));
  795. req2->setHWAddr(generateHWAddr(7));
  796. req3->setHWAddr(generateHWAddr(8));
  797. // Different client-id sizes
  798. OptionPtr clientid1 = generateClientId(4); // length 4
  799. OptionPtr clientid2 = generateClientId(5); // length 5
  800. OptionPtr clientid3 = generateClientId(6); // length 6
  801. req1->addOption(clientid1);
  802. req2->addOption(clientid2);
  803. req3->addOption(clientid3);
  804. // Pass it to the server and get an advertise
  805. Pkt4Ptr ack1 = srv->processRequest(req1);
  806. Pkt4Ptr ack2 = srv->processRequest(req2);
  807. Pkt4Ptr ack3 = srv->processRequest(req3);
  808. // Check if we get response at all
  809. checkResponse(ack1, DHCPACK, 1234);
  810. checkResponse(ack2, DHCPACK, 2345);
  811. checkResponse(ack3, DHCPACK, 3456);
  812. IOAddress addr1 = ack1->getYiaddr();
  813. IOAddress addr2 = ack2->getYiaddr();
  814. IOAddress addr3 = ack3->getYiaddr();
  815. // Check that every client received the address it requested
  816. EXPECT_EQ(req_addr1.toText(), addr1.toText());
  817. EXPECT_EQ(req_addr2.toText(), addr2.toText());
  818. EXPECT_EQ(req_addr3.toText(), addr3.toText());
  819. // Check that the assigned address is indeed from the configured pool
  820. checkAddressParams(ack1, subnet_);
  821. checkAddressParams(ack2, subnet_);
  822. checkAddressParams(ack3, subnet_);
  823. // Check DUIDs
  824. checkServerId(ack1, srv->getServerID());
  825. checkServerId(ack2, srv->getServerID());
  826. checkServerId(ack3, srv->getServerID());
  827. checkClientId(ack1, clientid1);
  828. checkClientId(ack2, clientid2);
  829. checkClientId(ack3, clientid3);
  830. // Check that leases are in the database
  831. Lease4Ptr l = checkLease(ack1, clientid1, req1->getHWAddr(), addr1);
  832. EXPECT_TRUE(l);
  833. l = checkLease(ack2, clientid2, req2->getHWAddr(), addr2);
  834. l = checkLease(ack3, clientid3, req3->getHWAddr(), addr3);
  835. // Finally check that the addresses offered are different
  836. EXPECT_NE(addr1.toText(), addr2.toText());
  837. EXPECT_NE(addr2.toText(), addr3.toText());
  838. EXPECT_NE(addr3.toText(), addr1.toText());
  839. cout << "Offered address to client1=" << addr1.toText() << endl;
  840. cout << "Offered address to client2=" << addr2.toText() << endl;
  841. cout << "Offered address to client3=" << addr3.toText() << endl;
  842. }
  843. // This test verifies that incoming (positive) REQUEST/Renewing can be handled properly, that a
  844. // REPLY is generated, that the response has an address and that address
  845. // really belongs to the configured pool and that lease is actually renewed.
  846. //
  847. // expected:
  848. // - returned REPLY message has copy of client-id
  849. // - returned REPLY message has server-id
  850. // - returned REPLY message has IA that includes IAADDR
  851. // - lease is actually renewed in LeaseMgr
  852. TEST_F(Dhcpv4SrvTest, RenewBasic) {
  853. boost::scoped_ptr<NakedDhcpv4Srv> srv;
  854. ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
  855. const IOAddress addr("192.0.2.106");
  856. const uint32_t temp_t1 = 50;
  857. const uint32_t temp_t2 = 75;
  858. const uint32_t temp_valid = 100;
  859. const time_t temp_timestamp = time(NULL) - 10;
  860. // Generate client-id also sets client_id_ member
  861. OptionPtr clientid = generateClientId();
  862. // Check that the address we are about to use is indeed in pool
  863. ASSERT_TRUE(subnet_->inPool(addr));
  864. // let's create a lease and put it in the LeaseMgr
  865. uint8_t hwaddr2[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
  866. Lease4Ptr used(new Lease4(IOAddress("192.0.2.106"), hwaddr2, sizeof(hwaddr2),
  867. &client_id_->getDuid()[0], client_id_->getDuid().size(),
  868. temp_valid, temp_t1, temp_t2, temp_timestamp,
  869. subnet_->getID()));
  870. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
  871. // Check that the lease is really in the database
  872. Lease4Ptr l = LeaseMgrFactory::instance().getLease4(addr);
  873. ASSERT_TRUE(l);
  874. // Check that T1, T2, preferred, valid and cltt really set.
  875. // Constructed lease looks as if it was assigned 10 seconds ago
  876. // EXPECT_EQ(l->t1_, temp_t1);
  877. // EXPECT_EQ(l->t2_, temp_t2);
  878. EXPECT_EQ(l->valid_lft_, temp_valid);
  879. EXPECT_EQ(l->cltt_, temp_timestamp);
  880. // Let's create a RENEW
  881. Pkt4Ptr req = Pkt4Ptr(new Pkt4(DHCPREQUEST, 1234));
  882. req->setRemoteAddr(IOAddress(addr));
  883. req->setYiaddr(addr);
  884. req->setCiaddr(addr); // client's address
  885. req->addOption(clientid);
  886. req->addOption(srv->getServerID());
  887. // Pass it to the server and hope for a REPLY
  888. Pkt4Ptr ack = srv->processRequest(req);
  889. // Check if we get response at all
  890. checkResponse(ack, DHCPACK, 1234);
  891. EXPECT_EQ(addr.toText(), ack->getYiaddr().toText());
  892. // Check that address was returned from proper range, that its lease
  893. // lifetime is correct, that T1 and T2 are returned properly
  894. checkAddressParams(ack, subnet_);
  895. // Check identifiers
  896. checkServerId(ack, srv->getServerID());
  897. checkClientId(ack, clientid);
  898. // Check that the lease is really in the database
  899. l = checkLease(ack, clientid, req->getHWAddr(), addr);
  900. ASSERT_TRUE(l);
  901. // Check that T1, T2, preferred, valid and cltt were really updated
  902. EXPECT_EQ(l->t1_, subnet_->getT1());
  903. EXPECT_EQ(l->t2_, subnet_->getT2());
  904. EXPECT_EQ(l->valid_lft_, subnet_->getValid());
  905. // Checking for CLTT is a bit tricky if we want to avoid off by 1 errors
  906. int32_t cltt = static_cast<int32_t>(l->cltt_);
  907. int32_t expected = static_cast<int32_t>(time(NULL));
  908. // Equality or difference by 1 between cltt and expected is ok.
  909. EXPECT_GE(1, abs(cltt - expected));
  910. EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
  911. }
  912. // @todo: Implement tests for rejecting renewals
  913. // This test verifies if the sanityCheck() really checks options presence.
  914. TEST_F(Dhcpv4SrvTest, sanityCheck) {
  915. boost::scoped_ptr<NakedDhcpv4Srv> srv;
  916. ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
  917. Pkt4Ptr pkt = Pkt4Ptr(new Pkt4(DHCPDISCOVER, 1234));
  918. // Client-id is optional for information-request, so
  919. EXPECT_NO_THROW(srv->sanityCheck(pkt, Dhcpv4Srv::OPTIONAL));
  920. // Empty packet, no server-id
  921. EXPECT_THROW(srv->sanityCheck(pkt, Dhcpv4Srv::MANDATORY), RFCViolation);
  922. pkt->addOption(srv->getServerID());
  923. // Server-id is mandatory and present = no exception
  924. EXPECT_NO_THROW(srv->sanityCheck(pkt, Dhcpv4Srv::MANDATORY));
  925. // Server-id is forbidden, but present => exception
  926. EXPECT_THROW(srv->sanityCheck(pkt, Dhcpv4Srv::FORBIDDEN),
  927. RFCViolation);
  928. }
  929. // This test verifies that incoming (positive) RELEASE can be handled properly.
  930. // As there is no REPLY in DHCPv4, the only thing to verify here is that
  931. // the lease is indeed removed from the database.
  932. TEST_F(Dhcpv4SrvTest, ReleaseBasic) {
  933. boost::scoped_ptr<NakedDhcpv4Srv> srv;
  934. ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
  935. const IOAddress addr("192.0.2.106");
  936. const uint32_t temp_t1 = 50;
  937. const uint32_t temp_t2 = 75;
  938. const uint32_t temp_valid = 100;
  939. const time_t temp_timestamp = time(NULL) - 10;
  940. // Generate client-id also duid_
  941. OptionPtr clientid = generateClientId();
  942. // Check that the address we are about to use is indeed in pool
  943. ASSERT_TRUE(subnet_->inPool(addr));
  944. // Let's create a lease and put it in the LeaseMgr
  945. uint8_t mac_addr[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
  946. HWAddrPtr hw(new HWAddr(mac_addr, sizeof(mac_addr), HTYPE_ETHER));
  947. Lease4Ptr used(new Lease4(addr, mac_addr, sizeof(mac_addr),
  948. &client_id_->getDuid()[0], client_id_->getDuid().size(),
  949. temp_valid, temp_t1, temp_t2, temp_timestamp,
  950. subnet_->getID()));
  951. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
  952. // Check that the lease is really in the database
  953. Lease4Ptr l = LeaseMgrFactory::instance().getLease4(addr);
  954. ASSERT_TRUE(l);
  955. // Let's create a RELEASE
  956. // Generate client-id also duid_
  957. Pkt4Ptr rel = Pkt4Ptr(new Pkt4(DHCPRELEASE, 1234));
  958. rel->setRemoteAddr(addr);
  959. rel->setYiaddr(addr);
  960. rel->addOption(clientid);
  961. rel->addOption(srv->getServerID());
  962. rel->setHWAddr(hw);
  963. // Pass it to the server and hope for a REPLY
  964. // Note: this is no response to RELEASE in DHCPv4
  965. EXPECT_NO_THROW(srv->processRelease(rel));
  966. // The lease should be gone from LeaseMgr
  967. l = LeaseMgrFactory::instance().getLease4(addr);
  968. EXPECT_FALSE(l);
  969. // Try to get the lease by hardware address
  970. // @todo: Uncomment this once trac2592 is implemented
  971. // Lease4Collection leases = LeaseMgrFactory::instance().getLease4(hw->hwaddr_);
  972. // EXPECT_EQ(leases.size(), 0);
  973. // Try to get it by hw/subnet_id combination
  974. l = LeaseMgrFactory::instance().getLease4(hw->hwaddr_, subnet_->getID());
  975. EXPECT_FALSE(l);
  976. // Try by client-id
  977. // @todo: Uncomment this once trac2592 is implemented
  978. //Lease4Collection leases = LeaseMgrFactory::instance().getLease4(*client_id_);
  979. //EXPECT_EQ(leases.size(), 0);
  980. // Try by client-id/subnet-id
  981. l = LeaseMgrFactory::instance().getLease4(*client_id_, subnet_->getID());
  982. EXPECT_FALSE(l);
  983. // Ok, the lease is *really* not there.
  984. }
  985. // This test verifies that incoming (invalid) RELEASE can be handled properly.
  986. //
  987. // This test checks 3 scenarios:
  988. // 1. there is no such lease at all
  989. // 2. there is such a lease, but it is assigned to a different IAID
  990. // 3. there is such a lease, but it belongs to a different client
  991. TEST_F(Dhcpv4SrvTest, ReleaseReject) {
  992. boost::scoped_ptr<NakedDhcpv4Srv> srv;
  993. ASSERT_NO_THROW(srv.reset(new NakedDhcpv4Srv(0)));
  994. const IOAddress addr("192.0.2.106");
  995. const uint32_t t1 = 50;
  996. const uint32_t t2 = 75;
  997. const uint32_t valid = 100;
  998. const time_t timestamp = time(NULL) - 10;
  999. // Let's create a lease and put it in the LeaseMgr
  1000. uint8_t bogus_mac_addr[] = { 0, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe};
  1001. HWAddrPtr bogus_hw(new HWAddr(bogus_mac_addr, sizeof(bogus_mac_addr), HTYPE_ETHER));
  1002. OptionPtr bogus_clientid = generateClientId(7); // different length
  1003. // Generate client-id also duid_
  1004. OptionPtr clientid = generateClientId();
  1005. // Check that the address we are about to use is indeed in pool
  1006. ASSERT_TRUE(subnet_->inPool(addr));
  1007. // Let's create a RELEASE
  1008. // Generate client-id also duid_
  1009. Pkt4Ptr rel = Pkt4Ptr(new Pkt4(DHCPRELEASE, 1234));
  1010. rel->setRemoteAddr(addr);
  1011. rel->setYiaddr(addr);
  1012. rel->addOption(clientid);
  1013. rel->addOption(srv->getServerID());
  1014. rel->setHWAddr(bogus_hw);
  1015. // Case 1: No lease known to server
  1016. SCOPED_TRACE("CASE 1: Lease is not known to the server");
  1017. // There is nothing to check here. The lease is not there and server does
  1018. // not send anything back. This case is enumerated here just for keeping
  1019. // parity with similar test in DHCPv6.
  1020. EXPECT_NO_THROW(srv->processRelease(rel));
  1021. // CASE 2: Lease is known and belongs to this client, but to a different hardware
  1022. SCOPED_TRACE("CASE 2: Lease is known and belongs to this client, but uses different HW addr");
  1023. // Let's create a lease and put it in the LeaseMgr
  1024. uint8_t mac_addr[] = { 0, 0x1, 0x2, 0x3, 0x4, 0x5};
  1025. HWAddrPtr hw(new HWAddr(mac_addr, sizeof(mac_addr), HTYPE_ETHER));
  1026. Lease4Ptr used(new Lease4(addr, mac_addr, sizeof(mac_addr),
  1027. &client_id_->getDuid()[0], client_id_->getDuid().size(),
  1028. valid, t1, t2, timestamp, subnet_->getID()));
  1029. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(used));
  1030. // Check that the lease is really in the database
  1031. Lease4Ptr l = LeaseMgrFactory::instance().getLease4(addr);
  1032. ASSERT_TRUE(l);
  1033. rel->setHWAddr(bogus_hw);
  1034. EXPECT_NO_THROW(srv->processRelease(rel));
  1035. // Check that the lease was not removed (due to hardware address mis-match)
  1036. l = LeaseMgrFactory::instance().getLease4(addr);
  1037. ASSERT_TRUE(l);
  1038. // CASE 3: Lease belongs to a client with different client-id
  1039. SCOPED_TRACE("CASE 3: Lease belongs to a client with different client-id");
  1040. rel->setHWAddr(hw); // proper HW address this time
  1041. rel->delOption(DHO_DHCP_CLIENT_IDENTIFIER);
  1042. rel->addOption(bogus_clientid); // but invalid client-id
  1043. OptionPtr x = rel->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
  1044. EXPECT_NO_THROW(srv->processRelease(rel));
  1045. // Check that the lease is still there
  1046. l = LeaseMgrFactory::instance().getLease4(addr);
  1047. ASSERT_TRUE(l);
  1048. // Final sanity check. Verify that with valid hw and client-id release is successful
  1049. rel->delOption(DHO_DHCP_CLIENT_IDENTIFIER);
  1050. rel->addOption(clientid);
  1051. // It should work this time
  1052. EXPECT_NO_THROW(srv->processRelease(rel));
  1053. // Check that the lease is not there
  1054. l = LeaseMgrFactory::instance().getLease4(addr);
  1055. EXPECT_FALSE(l);
  1056. }
  1057. // This test verifies if the server-id disk operations (read, write) are
  1058. // working properly.
  1059. TEST_F(Dhcpv4SrvTest, ServerID) {
  1060. NakedDhcpv4Srv srv(0);
  1061. string srvid_text = "192.0.2.100";
  1062. IOAddress srvid(srvid_text);
  1063. fstream file1(SRVID_FILE, ios::out | ios::trunc);
  1064. file1 << srvid_text;
  1065. file1.close();
  1066. // Test reading from a file
  1067. EXPECT_TRUE(srv.loadServerID(SRVID_FILE));
  1068. ASSERT_TRUE(srv.getServerID());
  1069. EXPECT_EQ(srvid_text, srv.srvidToString(srv.getServerID()));
  1070. // Now test writing to a file
  1071. EXPECT_EQ(0, unlink(SRVID_FILE));
  1072. EXPECT_NO_THROW(srv.writeServerID(SRVID_FILE));
  1073. fstream file2(SRVID_FILE, ios::in);
  1074. ASSERT_TRUE(file2.good());
  1075. string text;
  1076. file2 >> text;
  1077. file2.close();
  1078. EXPECT_EQ(srvid_text, text);
  1079. }
  1080. } // end of anonymous namespace