dhcp6_srv_unittest.cc 65 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762
  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 <asiolink/io_address.h>
  16. #include <config/ccsession.h>
  17. #include <dhcp/dhcp6.h>
  18. #include <dhcp/duid.h>
  19. #include <dhcp/option.h>
  20. #include <dhcp/option_custom.h>
  21. #include <dhcp/option6_addrlst.h>
  22. #include <dhcp/option6_ia.h>
  23. #include <dhcp/option6_iaaddr.h>
  24. #include <dhcp/option_int_array.h>
  25. #include <dhcp6/config_parser.h>
  26. #include <dhcp6/dhcp6_srv.h>
  27. #include <dhcpsrv/cfgmgr.h>
  28. #include <dhcpsrv/lease_mgr.h>
  29. #include <dhcpsrv/lease_mgr_factory.h>
  30. #include <dhcpsrv/utils.h>
  31. #include <util/buffer.h>
  32. #include <util/range_utilities.h>
  33. #include <boost/scoped_ptr.hpp>
  34. #include <gtest/gtest.h>
  35. #include <unistd.h>
  36. #include <fstream>
  37. #include <iostream>
  38. #include <sstream>
  39. using namespace isc;
  40. using namespace isc::asiolink;
  41. using namespace isc::config;
  42. using namespace isc::data;
  43. using namespace isc::dhcp;
  44. using namespace isc::util;
  45. using namespace std;
  46. // namespace has to be named, because friends are defined in Dhcpv6Srv class
  47. // Maybe it should be isc::test?
  48. namespace {
  49. class NakedDhcpv6Srv: public Dhcpv6Srv {
  50. // "naked" Interface Manager, exposes internal members
  51. public:
  52. NakedDhcpv6Srv(uint16_t port) : Dhcpv6Srv(port) {
  53. // Open the "memfile" database for leases
  54. std::string memfile = "type=memfile";
  55. LeaseMgrFactory::create(memfile);
  56. }
  57. virtual ~NakedDhcpv6Srv() {
  58. // Close the lease database
  59. LeaseMgrFactory::destroy();
  60. }
  61. using Dhcpv6Srv::processSolicit;
  62. using Dhcpv6Srv::processRequest;
  63. using Dhcpv6Srv::processRenew;
  64. using Dhcpv6Srv::processRelease;
  65. using Dhcpv6Srv::createStatusCode;
  66. using Dhcpv6Srv::selectSubnet;
  67. using Dhcpv6Srv::sanityCheck;
  68. using Dhcpv6Srv::loadServerID;
  69. using Dhcpv6Srv::writeServerID;
  70. };
  71. static const char* DUID_FILE = "server-id-test.txt";
  72. // test fixture for any tests requiring blank/empty configuration
  73. // serves as base class for additional tests
  74. class NakedDhcpv6SrvTest : public ::testing::Test {
  75. public:
  76. NakedDhcpv6SrvTest() : rcode_(-1) {
  77. // it's ok if that fails. There should not be such a file anyway
  78. unlink(DUID_FILE);
  79. }
  80. // Generate IA_NA option with specified parameters
  81. boost::shared_ptr<Option6IA> generateIA(uint32_t iaid, uint32_t t1, uint32_t t2) {
  82. boost::shared_ptr<Option6IA> ia =
  83. boost::shared_ptr<Option6IA>(new Option6IA(D6O_IA_NA, iaid));
  84. ia->setT1(t1);
  85. ia->setT2(t2);
  86. return (ia);
  87. }
  88. /// @brief generates interface-id option, based on text
  89. ///
  90. /// @param iface_id textual representation of the interface-id content
  91. ///
  92. /// @return pointer to the option object
  93. OptionPtr generateInterfaceId(const string& iface_id) {
  94. OptionBuffer tmp(iface_id.begin(), iface_id.end());
  95. return OptionPtr(new Option(Option::V6, D6O_INTERFACE_ID, tmp));
  96. }
  97. // Generate client-id option
  98. OptionPtr generateClientId(size_t duid_size = 32) {
  99. OptionBuffer clnt_duid(duid_size);
  100. for (int i = 0; i < duid_size; i++) {
  101. clnt_duid[i] = 100 + i;
  102. }
  103. duid_ = DuidPtr(new DUID(clnt_duid));
  104. return (OptionPtr(new Option(Option::V6, D6O_CLIENTID,
  105. clnt_duid.begin(),
  106. clnt_duid.begin() + duid_size)));
  107. }
  108. // Checks if server response (ADVERTISE or REPLY) includes proper server-id.
  109. void checkServerId(const Pkt6Ptr& rsp, const OptionPtr& expected_srvid) {
  110. // check that server included its server-id
  111. OptionPtr tmp = rsp->getOption(D6O_SERVERID);
  112. EXPECT_EQ(tmp->getType(), expected_srvid->getType() );
  113. ASSERT_EQ(tmp->len(), expected_srvid->len() );
  114. EXPECT_TRUE(tmp->getData() == expected_srvid->getData());
  115. }
  116. // Checks if server response (ADVERTISE or REPLY) includes proper client-id.
  117. void checkClientId(const Pkt6Ptr& rsp, const OptionPtr& expected_clientid) {
  118. // check that server included our own client-id
  119. OptionPtr tmp = rsp->getOption(D6O_CLIENTID);
  120. ASSERT_TRUE(tmp);
  121. EXPECT_EQ(expected_clientid->getType(), tmp->getType());
  122. ASSERT_EQ(expected_clientid->len(), tmp->len());
  123. // check that returned client-id is valid
  124. EXPECT_TRUE(expected_clientid->getData() == tmp->getData());
  125. }
  126. // Checks if server response is a NAK
  127. void checkNakResponse(const Pkt6Ptr& rsp, uint8_t expected_message_type,
  128. uint32_t expected_transid,
  129. uint16_t expected_status_code) {
  130. // Check if we get response at all
  131. checkResponse(rsp, expected_message_type, expected_transid);
  132. // Check that IA_NA was returned
  133. OptionPtr option_ia_na = rsp->getOption(D6O_IA_NA);
  134. ASSERT_TRUE(option_ia_na);
  135. // check that the status is no address available
  136. boost::shared_ptr<Option6IA> ia = boost::dynamic_pointer_cast<Option6IA>(option_ia_na);
  137. ASSERT_TRUE(ia);
  138. checkIA_NAStatusCode(ia, expected_status_code);
  139. }
  140. // Checks that server rejected IA_NA, i.e. that it has no addresses and
  141. // that expected status code really appears there. In some limited cases
  142. // (reply to RELEASE) it may be used to verify positive case, where
  143. // IA_NA response is expected to not include address.
  144. //
  145. // Status code indicates type of error encountered (in theory it can also
  146. // indicate success, but servers typically don't send success status
  147. // as this is the default result and it saves bandwidth)
  148. void checkIA_NAStatusCode(const boost::shared_ptr<Option6IA>& ia,
  149. uint16_t expected_status_code) {
  150. // Make sure there is no address assigned.
  151. EXPECT_FALSE(ia->getOption(D6O_IAADDR));
  152. // T1, T2 should be zeroed
  153. EXPECT_EQ(0, ia->getT1());
  154. EXPECT_EQ(0, ia->getT2());
  155. boost::shared_ptr<OptionCustom> status =
  156. boost::dynamic_pointer_cast<OptionCustom>(ia->getOption(D6O_STATUS_CODE));
  157. // It is ok to not include status success as this is the default behavior
  158. if (expected_status_code == STATUS_Success && !status) {
  159. return;
  160. }
  161. EXPECT_TRUE(status);
  162. if (status) {
  163. // We don't have dedicated class for status code, so let's just interpret
  164. // first 2 bytes as status. Remainder of the status code option content is
  165. // just a text explanation what went wrong.
  166. EXPECT_EQ(static_cast<uint16_t>(expected_status_code),
  167. status->readInteger<uint16_t>(0));
  168. }
  169. }
  170. void checkMsgStatusCode(const Pkt6Ptr& msg, uint16_t expected_status) {
  171. boost::shared_ptr<OptionCustom> status =
  172. boost::dynamic_pointer_cast<OptionCustom>(msg->getOption(D6O_STATUS_CODE));
  173. // It is ok to not include status success as this is the default behavior
  174. if (expected_status == STATUS_Success && !status) {
  175. return;
  176. }
  177. EXPECT_TRUE(status);
  178. if (status) {
  179. // We don't have dedicated class for status code, so let's just interpret
  180. // first 2 bytes as status. Remainder of the status code option content is
  181. // just a text explanation what went wrong.
  182. EXPECT_EQ(static_cast<uint16_t>(expected_status),
  183. status->readInteger<uint16_t>(0));
  184. }
  185. }
  186. // Basic checks for generated response (message type and transaction-id).
  187. void checkResponse(const Pkt6Ptr& rsp, uint8_t expected_message_type,
  188. uint32_t expected_transid) {
  189. ASSERT_TRUE(rsp);
  190. EXPECT_EQ(expected_message_type, rsp->getType());
  191. EXPECT_EQ(expected_transid, rsp->getTransid());
  192. }
  193. virtual ~NakedDhcpv6SrvTest() {
  194. // Let's clean up if there is such a file.
  195. unlink(DUID_FILE);
  196. };
  197. // A DUID used in most tests (typically as client-id)
  198. DuidPtr duid_;
  199. int rcode_;
  200. ConstElementPtr comment_;
  201. };
  202. // Provides suport for tests against a preconfigured subnet6
  203. // extends upon NakedDhcp6SrvTest
  204. class Dhcpv6SrvTest : public NakedDhcpv6SrvTest {
  205. public:
  206. /// Name of the server-id file (used in server-id tests)
  207. // these are empty for now, but let's keep them around
  208. Dhcpv6SrvTest() {
  209. subnet_ = Subnet6Ptr(new Subnet6(IOAddress("2001:db8:1::"), 48, 1000,
  210. 2000, 3000, 4000));
  211. pool_ = Pool6Ptr(new Pool6(Pool6::TYPE_IA, IOAddress("2001:db8:1:1::"), 64));
  212. subnet_->addPool(pool_);
  213. CfgMgr::instance().deleteSubnets6();
  214. CfgMgr::instance().addSubnet6(subnet_);
  215. }
  216. // Checks that server response (ADVERTISE or REPLY) contains proper IA_NA option
  217. // It returns IAADDR option for each chaining with checkIAAddr method.
  218. boost::shared_ptr<Option6IAAddr> checkIA_NA(const Pkt6Ptr& rsp, uint32_t expected_iaid,
  219. uint32_t expected_t1, uint32_t expected_t2) {
  220. OptionPtr tmp = rsp->getOption(D6O_IA_NA);
  221. // Can't use ASSERT_TRUE() in method that returns something
  222. if (!tmp) {
  223. ADD_FAILURE() << "IA_NA option not present in response";
  224. return (boost::shared_ptr<Option6IAAddr>());
  225. }
  226. boost::shared_ptr<Option6IA> ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
  227. if (!ia) {
  228. ADD_FAILURE() << "IA_NA cannot convert option ptr to Option6";
  229. return (boost::shared_ptr<Option6IAAddr>());
  230. }
  231. EXPECT_EQ(expected_iaid, ia->getIAID());
  232. EXPECT_EQ(expected_t1, ia->getT1());
  233. EXPECT_EQ(expected_t2, ia->getT2());
  234. tmp = ia->getOption(D6O_IAADDR);
  235. boost::shared_ptr<Option6IAAddr> addr = boost::dynamic_pointer_cast<Option6IAAddr>(tmp);
  236. return (addr);
  237. }
  238. // Check that generated IAADDR option contains expected address
  239. // and lifetime values match the configured subnet
  240. void checkIAAddr(const boost::shared_ptr<Option6IAAddr>& addr,
  241. const IOAddress& expected_addr,
  242. uint32_t /* expected_preferred */,
  243. uint32_t /* expected_valid */) {
  244. // Check that the assigned address is indeed from the configured pool.
  245. // Note that when comparing addresses, we compare the textual
  246. // representation. IOAddress does not support being streamed to
  247. // an ostream, which means it can't be used in EXPECT_EQ.
  248. EXPECT_TRUE(subnet_->inPool(addr->getAddress()));
  249. EXPECT_EQ(expected_addr.toText(), addr->getAddress().toText());
  250. EXPECT_EQ(addr->getPreferred(), subnet_->getPreferred());
  251. EXPECT_EQ(addr->getValid(), subnet_->getValid());
  252. }
  253. // Checks if the lease sent to client is present in the database
  254. // and is valid when checked agasint the configured subnet
  255. Lease6Ptr checkLease(const DuidPtr& duid, const OptionPtr& ia_na,
  256. boost::shared_ptr<Option6IAAddr> addr) {
  257. boost::shared_ptr<Option6IA> ia = boost::dynamic_pointer_cast<Option6IA>(ia_na);
  258. Lease6Ptr lease = LeaseMgrFactory::instance().getLease6(addr->getAddress());
  259. if (!lease) {
  260. cout << "Lease for " << addr->getAddress().toText()
  261. << " not found in the database backend.";
  262. return (Lease6Ptr());
  263. }
  264. EXPECT_EQ(addr->getAddress().toText(), lease->addr_.toText());
  265. EXPECT_TRUE(*lease->duid_ == *duid);
  266. EXPECT_EQ(ia->getIAID(), lease->iaid_);
  267. EXPECT_EQ(subnet_->getID(), lease->subnet_id_);
  268. return (lease);
  269. }
  270. ~Dhcpv6SrvTest() {
  271. CfgMgr::instance().deleteSubnets6();
  272. };
  273. // A subnet used in most tests
  274. Subnet6Ptr subnet_;
  275. // A pool used in most tests
  276. Pool6Ptr pool_;
  277. };
  278. // This test verifies that incoming SOLICIT can be handled properly when
  279. // there are no subnets configured.
  280. //
  281. // This test sends a SOLICIT and the expected response
  282. // is an ADVERTISE with STATUS_NoAddrsAvail and no address provided in the
  283. // response
  284. TEST_F(NakedDhcpv6SrvTest, SolicitNoSubnet) {
  285. NakedDhcpv6Srv srv(0);
  286. Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
  287. sol->setRemoteAddr(IOAddress("fe80::abcd"));
  288. sol->addOption(generateIA(234, 1500, 3000));
  289. OptionPtr clientid = generateClientId();
  290. sol->addOption(clientid);
  291. // Pass it to the server and get an advertise
  292. Pkt6Ptr reply = srv.processSolicit(sol);
  293. // check that we get the right NAK
  294. checkNakResponse (reply, DHCPV6_ADVERTISE, 1234, STATUS_NoAddrsAvail);
  295. }
  296. // This test verifies that incoming REQUEST can be handled properly when
  297. // there are no subnets configured.
  298. //
  299. // This test sends a REQUEST and the expected response
  300. // is an REPLY with STATUS_NoAddrsAvail and no address provided in the
  301. // response
  302. TEST_F(NakedDhcpv6SrvTest, RequestNoSubnet) {
  303. NakedDhcpv6Srv srv(0);
  304. // Let's create a REQUEST
  305. Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234));
  306. req->setRemoteAddr(IOAddress("fe80::abcd"));
  307. boost::shared_ptr<Option6IA> ia = generateIA(234, 1500, 3000);
  308. // with a hint
  309. IOAddress hint("2001:db8:1:1::dead:beef");
  310. OptionPtr hint_opt(new Option6IAAddr(D6O_IAADDR, hint, 300, 500));
  311. ia->addOption(hint_opt);
  312. req->addOption(ia);
  313. OptionPtr clientid = generateClientId();
  314. req->addOption(clientid);
  315. // server-id is mandatory in REQUEST
  316. req->addOption(srv.getServerID());
  317. // Pass it to the server and hope for a REPLY
  318. Pkt6Ptr reply = srv.processRequest(req);
  319. // check that we get the right NAK
  320. checkNakResponse (reply, DHCPV6_REPLY, 1234, STATUS_NoAddrsAvail);
  321. }
  322. // This test verifies that incoming RENEW can be handled properly, even when
  323. // no subnets are configured.
  324. //
  325. // This test sends a RENEW and the expected response
  326. // is an REPLY with STATUS_NoBinding and no address provided in the
  327. // response
  328. TEST_F(NakedDhcpv6SrvTest, RenewNoSubnet) {
  329. NakedDhcpv6Srv srv(0);
  330. const IOAddress addr("2001:db8:1:1::cafe:babe");
  331. const uint32_t iaid = 234;
  332. // Generate client-id also duid_
  333. OptionPtr clientid = generateClientId();
  334. // Let's create a RENEW
  335. Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, 1234));
  336. req->setRemoteAddr(IOAddress("fe80::abcd"));
  337. boost::shared_ptr<Option6IA> ia = generateIA(iaid, 1500, 3000);
  338. OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
  339. ia->addOption(renewed_addr_opt);
  340. req->addOption(ia);
  341. req->addOption(clientid);
  342. // Server-id is mandatory in RENEW
  343. req->addOption(srv.getServerID());
  344. // Pass it to the server and hope for a REPLY
  345. Pkt6Ptr reply = srv.processRenew(req);
  346. // check that we get the right NAK
  347. checkNakResponse (reply, DHCPV6_REPLY, 1234, STATUS_NoBinding);
  348. }
  349. // This test verifies that incoming RELEASE can be handled properly, even when
  350. // no subnets are configured.
  351. //
  352. // This test sends a RELEASE and the expected response
  353. // is an REPLY with STATUS_NoBinding and no address provided in the
  354. // response
  355. TEST_F(NakedDhcpv6SrvTest, ReleaseNoSubnet) {
  356. NakedDhcpv6Srv srv(0);
  357. const IOAddress addr("2001:db8:1:1::cafe:babe");
  358. const uint32_t iaid = 234;
  359. // Generate client-id also duid_
  360. OptionPtr clientid = generateClientId();
  361. // Let's create a RELEASE
  362. Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, 1234));
  363. req->setRemoteAddr(IOAddress("fe80::abcd"));
  364. boost::shared_ptr<Option6IA> ia = generateIA(iaid, 1500, 3000);
  365. OptionPtr released_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
  366. ia->addOption(released_addr_opt);
  367. req->addOption(ia);
  368. req->addOption(clientid);
  369. // Server-id is mandatory in RELEASE
  370. req->addOption(srv.getServerID());
  371. // Pass it to the server and hope for a REPLY
  372. Pkt6Ptr reply = srv.processRelease(req);
  373. // check that we get the right NAK
  374. checkNakResponse (reply, DHCPV6_REPLY, 1234, STATUS_NoBinding);
  375. }
  376. // Test verifies that the Dhcpv6_srv class can be instantiated. It checks a mode
  377. // without open sockets and with sockets opened on a high port (to not require
  378. // root privileges).
  379. TEST_F(Dhcpv6SrvTest, basic) {
  380. // srv has stubbed interface detection. It will read
  381. // interfaces.txt instead. It will pretend to have detected
  382. // fe80::1234 link-local address on eth0 interface. Obviously
  383. // an attempt to bind this socket will fail.
  384. boost::scoped_ptr<Dhcpv6Srv> srv;
  385. ASSERT_NO_THROW( {
  386. // Skip opening any sockets
  387. srv.reset(new Dhcpv6Srv(0));
  388. });
  389. srv.reset();
  390. ASSERT_NO_THROW({
  391. // open an unpriviledged port
  392. srv.reset(new Dhcpv6Srv(DHCP6_SERVER_PORT + 10000));
  393. });
  394. }
  395. // Test checks that DUID is generated properly
  396. TEST_F(Dhcpv6SrvTest, DUID) {
  397. boost::scoped_ptr<Dhcpv6Srv> srv;
  398. ASSERT_NO_THROW( {
  399. srv.reset(new Dhcpv6Srv(0));
  400. });
  401. OptionPtr srvid = srv->getServerID();
  402. ASSERT_TRUE(srvid);
  403. EXPECT_EQ(D6O_SERVERID, srvid->getType());
  404. OutputBuffer buf(32);
  405. srvid->pack(buf);
  406. // length of the actual DUID
  407. size_t len = buf.getLength() - srvid->getHeaderLen();
  408. InputBuffer data(buf.getData(), buf.getLength());
  409. // ignore first four bytes (standard DHCPv6 header)
  410. data.readUint32();
  411. uint16_t duid_type = data.readUint16();
  412. cout << "Duid-type=" << duid_type << endl;
  413. switch(duid_type) {
  414. case DUID::DUID_LLT: {
  415. // DUID must contain at least 6 bytes long MAC
  416. // + 8 bytes of fixed header
  417. EXPECT_GE(14, len);
  418. uint16_t hw_type = data.readUint16();
  419. // there's no real way to find out "correct"
  420. // hardware type
  421. EXPECT_GT(hw_type, 0);
  422. // check that timer is counted since 1.1.2000,
  423. // not from 1.1.1970.
  424. uint32_t seconds = data.readUint32();
  425. EXPECT_LE(seconds, DUID_TIME_EPOCH);
  426. // this test will start failing after 2030.
  427. // Hopefully we will be at BIND12 by then.
  428. // MAC must not be zeros
  429. vector<uint8_t> mac(len-8);
  430. vector<uint8_t> zeros(len-8, 0);
  431. data.readVector(mac, len-8);
  432. EXPECT_TRUE(mac != zeros);
  433. break;
  434. }
  435. case DUID::DUID_EN: {
  436. // there's not much we can check. Just simple
  437. // check if it is not all zeros
  438. vector<uint8_t> content(len-2);
  439. data.readVector(content, len-2);
  440. EXPECT_FALSE(isRangeZero(content.begin(), content.end()));
  441. break;
  442. }
  443. case DUID::DUID_LL: {
  444. // not supported yet
  445. cout << "Test not implemented for DUID-LL." << endl;
  446. // No failure here. There's really no way for test LL DUID. It doesn't
  447. // even make sense to check if that Link Layer is actually present on
  448. // a physical interface. RFC3315 says a server should write its DUID
  449. // and keep it despite hardware changes.
  450. break;
  451. }
  452. case DUID::DUID_UUID: // not supported yet
  453. default:
  454. ADD_FAILURE() << "Not supported duid type=" << duid_type << endl;
  455. break;
  456. }
  457. }
  458. // This test checks if Option Request Option (ORO) is parsed correctly
  459. // and the requested options are actually assigned.
  460. TEST_F(Dhcpv6SrvTest, advertiseOptions) {
  461. ConstElementPtr x;
  462. string config = "{ \"interface\": [ \"all\" ],"
  463. "\"preferred-lifetime\": 3000,"
  464. "\"rebind-timer\": 2000, "
  465. "\"renew-timer\": 1000, "
  466. "\"subnet6\": [ { "
  467. " \"pool\": [ \"2001:db8:1::/64\" ],"
  468. " \"subnet\": \"2001:db8:1::/48\", "
  469. " \"option-data\": [ {"
  470. " \"name\": \"dns-servers\","
  471. " \"space\": \"dhcp6\","
  472. " \"code\": 23,"
  473. " \"data\": \"2001:db8:1234:FFFF::1, 2001:db8:1234:FFFF::2\","
  474. " \"csv-format\": True"
  475. " },"
  476. " {"
  477. " \"name\": \"subscriber-id\","
  478. " \"space\": \"dhcp6\","
  479. " \"code\": 38,"
  480. " \"data\": \"1234\","
  481. " \"csv-format\": False"
  482. " } ]"
  483. " } ],"
  484. "\"valid-lifetime\": 4000 }";
  485. ElementPtr json = Element::fromJSON(config);
  486. NakedDhcpv6Srv srv(0);
  487. EXPECT_NO_THROW(x = configureDhcp6Server(srv, json));
  488. ASSERT_TRUE(x);
  489. comment_ = parseAnswer(rcode_, x);
  490. ASSERT_EQ(0, rcode_);
  491. Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
  492. sol->setRemoteAddr(IOAddress("fe80::abcd"));
  493. sol->addOption(generateIA(234, 1500, 3000));
  494. OptionPtr clientid = generateClientId();
  495. sol->addOption(clientid);
  496. // Pass it to the server and get an advertise
  497. boost::shared_ptr<Pkt6> adv = srv.processSolicit(sol);
  498. // check if we get response at all
  499. ASSERT_TRUE(adv);
  500. // We have not requested any options so they should not
  501. // be included in the response.
  502. ASSERT_FALSE(adv->getOption(D6O_SUBSCRIBER_ID));
  503. ASSERT_FALSE(adv->getOption(D6O_NAME_SERVERS));
  504. // Let's now request some options. We expect that the server
  505. // will include them in its response.
  506. boost::shared_ptr<OptionIntArray<uint16_t> >
  507. option_oro(new OptionIntArray<uint16_t>(Option::V6, D6O_ORO));
  508. // Create vector with two option codes.
  509. std::vector<uint16_t> codes(2);
  510. codes[0] = D6O_SUBSCRIBER_ID;
  511. codes[1] = D6O_NAME_SERVERS;
  512. // Pass this code to option.
  513. option_oro->setValues(codes);
  514. // Append ORO to SOLICIT message.
  515. sol->addOption(option_oro);
  516. // Need to process SOLICIT again after requesting new option.
  517. adv = srv.processSolicit(sol);
  518. ASSERT_TRUE(adv);
  519. OptionPtr tmp = adv->getOption(D6O_NAME_SERVERS);
  520. ASSERT_TRUE(tmp);
  521. boost::shared_ptr<Option6AddrLst> reply_nameservers =
  522. boost::dynamic_pointer_cast<Option6AddrLst>(tmp);
  523. ASSERT_TRUE(reply_nameservers);
  524. Option6AddrLst::AddressContainer addrs = reply_nameservers->getAddresses();
  525. ASSERT_EQ(2, addrs.size());
  526. EXPECT_TRUE(addrs[0] == IOAddress("2001:db8:1234:FFFF::1"));
  527. EXPECT_TRUE(addrs[1] == IOAddress("2001:db8:1234:FFFF::2"));
  528. // There is a dummy option with code 1000 we requested from a server.
  529. // Expect that this option is in server's response.
  530. tmp = adv->getOption(D6O_SUBSCRIBER_ID);
  531. ASSERT_TRUE(tmp);
  532. // Check that the option contains valid data (from configuration).
  533. std::vector<uint8_t> data = tmp->getData();
  534. ASSERT_EQ(2, data.size());
  535. const uint8_t foo_expected[] = {
  536. 0x12, 0x34
  537. };
  538. EXPECT_EQ(0, memcmp(&data[0], foo_expected, 2));
  539. // more checks to be implemented
  540. }
  541. // There are no dedicated tests for Dhcpv6Srv::handleIA_NA and Dhcpv6Srv::assignLeases
  542. // as they are indirectly tested in Solicit and Request tests.
  543. // This test verifies that incoming SOLICIT can be handled properly, that an
  544. // ADVERTISE is generated, that the response has an address and that address
  545. // really belongs to the configured pool.
  546. //
  547. // This test sends a SOLICIT without any hint in IA_NA.
  548. //
  549. // constructed very simple SOLICIT message with:
  550. // - client-id option (mandatory)
  551. // - IA option (a request for address, without any addresses)
  552. //
  553. // expected returned ADVERTISE message:
  554. // - copy of client-id
  555. // - server-id
  556. // - IA that includes IAADDR
  557. TEST_F(Dhcpv6SrvTest, SolicitBasic) {
  558. NakedDhcpv6Srv srv(0);
  559. Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
  560. sol->setRemoteAddr(IOAddress("fe80::abcd"));
  561. sol->addOption(generateIA(234, 1500, 3000));
  562. OptionPtr clientid = generateClientId();
  563. sol->addOption(clientid);
  564. // Pass it to the server and get an advertise
  565. Pkt6Ptr reply = srv.processSolicit(sol);
  566. // check if we get response at all
  567. checkResponse(reply, DHCPV6_ADVERTISE, 1234);
  568. // check that IA_NA was returned and that there's an address included
  569. boost::shared_ptr<Option6IAAddr> addr = checkIA_NA(reply, 234, subnet_->getT1(),
  570. subnet_->getT2());
  571. ASSERT_TRUE(addr);
  572. // Check that the assigned address is indeed from the configured pool
  573. checkIAAddr(addr, addr->getAddress(), subnet_->getPreferred(), subnet_->getValid());
  574. // check DUIDs
  575. checkServerId(reply, srv.getServerID());
  576. checkClientId(reply, clientid);
  577. }
  578. // This test verifies that incoming SOLICIT can be handled properly, that an
  579. // ADVERTISE is generated, that the response has an address and that address
  580. // really belongs to the configured pool.
  581. //
  582. // This test sends a SOLICIT with IA_NA that contains a valid hint.
  583. //
  584. // constructed very simple SOLICIT message with:
  585. // - client-id option (mandatory)
  586. // - IA option (a request for address, with an address that belongs to the
  587. // configured pool, i.e. is valid as hint)
  588. //
  589. // expected returned ADVERTISE message:
  590. // - copy of client-id
  591. // - server-id
  592. // - IA that includes IAADDR
  593. TEST_F(Dhcpv6SrvTest, SolicitHint) {
  594. NakedDhcpv6Srv srv(0);
  595. // Let's create a SOLICIT
  596. Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
  597. sol->setRemoteAddr(IOAddress("fe80::abcd"));
  598. boost::shared_ptr<Option6IA> ia = generateIA(234, 1500, 3000);
  599. // with a valid hint
  600. IOAddress hint("2001:db8:1:1::dead:beef");
  601. ASSERT_TRUE(subnet_->inPool(hint));
  602. OptionPtr hint_opt(new Option6IAAddr(D6O_IAADDR, hint, 300, 500));
  603. ia->addOption(hint_opt);
  604. sol->addOption(ia);
  605. OptionPtr clientid = generateClientId();
  606. sol->addOption(clientid);
  607. // Pass it to the server and get an advertise
  608. Pkt6Ptr reply = srv.processSolicit(sol);
  609. // check if we get response at all
  610. checkResponse(reply, DHCPV6_ADVERTISE, 1234);
  611. OptionPtr tmp = reply->getOption(D6O_IA_NA);
  612. ASSERT_TRUE(tmp);
  613. // check that IA_NA was returned and that there's an address included
  614. boost::shared_ptr<Option6IAAddr> addr = checkIA_NA(reply, 234, subnet_->getT1(),
  615. subnet_->getT2());
  616. ASSERT_TRUE(addr);
  617. // check that we've got the address we requested
  618. checkIAAddr(addr, hint, subnet_->getPreferred(), subnet_->getValid());
  619. // check DUIDs
  620. checkServerId(reply, srv.getServerID());
  621. checkClientId(reply, clientid);
  622. }
  623. // This test verifies that incoming SOLICIT can be handled properly, that an
  624. // ADVERTISE is generated, that the response has an address and that address
  625. // really belongs to the configured pool.
  626. //
  627. // This test sends a SOLICIT with IA_NA that contains an invalid hint.
  628. //
  629. // constructed very simple SOLICIT message with:
  630. // - client-id option (mandatory)
  631. // - IA option (a request for address, with an address that does not
  632. // belong to the configured pool, i.e. is valid as hint)
  633. //
  634. // expected returned ADVERTISE message:
  635. // - copy of client-id
  636. // - server-id
  637. // - IA that includes IAADDR
  638. TEST_F(Dhcpv6SrvTest, SolicitInvalidHint) {
  639. NakedDhcpv6Srv srv(0);
  640. // Let's create a SOLICIT
  641. Pkt6Ptr sol = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
  642. sol->setRemoteAddr(IOAddress("fe80::abcd"));
  643. boost::shared_ptr<Option6IA> ia = generateIA(234, 1500, 3000);
  644. IOAddress hint("2001:db8:1::cafe:babe");
  645. ASSERT_FALSE(subnet_->inPool(hint));
  646. OptionPtr hint_opt(new Option6IAAddr(D6O_IAADDR, hint, 300, 500));
  647. ia->addOption(hint_opt);
  648. sol->addOption(ia);
  649. OptionPtr clientid = generateClientId();
  650. sol->addOption(clientid);
  651. // Pass it to the server and get an advertise
  652. Pkt6Ptr reply = srv.processSolicit(sol);
  653. // check if we get response at all
  654. checkResponse(reply, DHCPV6_ADVERTISE, 1234);
  655. // check that IA_NA was returned and that there's an address included
  656. boost::shared_ptr<Option6IAAddr> addr = checkIA_NA(reply, 234, subnet_->getT1(),
  657. subnet_->getT2());
  658. ASSERT_TRUE(addr);
  659. // Check that the assigned address is indeed from the configured pool
  660. checkIAAddr(addr, addr->getAddress(), subnet_->getPreferred(), subnet_->getValid());
  661. EXPECT_TRUE(subnet_->inPool(addr->getAddress()));
  662. // check DUIDs
  663. checkServerId(reply, srv.getServerID());
  664. checkClientId(reply, clientid);
  665. }
  666. /// @todo: Add a test that client sends hint that is in pool, but currently
  667. /// being used by a different client.
  668. // This test checks that the server is offering different addresses to different
  669. // clients in ADVERTISEs. Please note that ADVERTISE is not a guarantee that such
  670. // an address will be assigned. Had the pool was very small and contained only
  671. // 2 addresses, the third client would get the same advertise as the first one
  672. // and this is a correct behavior. It is REQUEST that will fail for the third
  673. // client. ADVERTISE is basically saying "if you send me a request, you will
  674. // probably get an address like this" (there are no guarantees).
  675. TEST_F(Dhcpv6SrvTest, ManySolicits) {
  676. NakedDhcpv6Srv srv(0);
  677. Pkt6Ptr sol1 = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
  678. Pkt6Ptr sol2 = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 2345));
  679. Pkt6Ptr sol3 = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 3456));
  680. sol1->setRemoteAddr(IOAddress("fe80::abcd"));
  681. sol2->setRemoteAddr(IOAddress("fe80::1223"));
  682. sol3->setRemoteAddr(IOAddress("fe80::3467"));
  683. sol1->addOption(generateIA(1, 1500, 3000));
  684. sol2->addOption(generateIA(2, 1500, 3000));
  685. sol3->addOption(generateIA(3, 1500, 3000));
  686. // different client-id sizes
  687. OptionPtr clientid1 = generateClientId(12);
  688. OptionPtr clientid2 = generateClientId(14);
  689. OptionPtr clientid3 = generateClientId(16);
  690. sol1->addOption(clientid1);
  691. sol2->addOption(clientid2);
  692. sol3->addOption(clientid3);
  693. // Pass it to the server and get an advertise
  694. Pkt6Ptr reply1 = srv.processSolicit(sol1);
  695. Pkt6Ptr reply2 = srv.processSolicit(sol2);
  696. Pkt6Ptr reply3 = srv.processSolicit(sol3);
  697. // check if we get response at all
  698. checkResponse(reply1, DHCPV6_ADVERTISE, 1234);
  699. checkResponse(reply2, DHCPV6_ADVERTISE, 2345);
  700. checkResponse(reply3, DHCPV6_ADVERTISE, 3456);
  701. // check that IA_NA was returned and that there's an address included
  702. boost::shared_ptr<Option6IAAddr> addr1 = checkIA_NA(reply1, 1, subnet_->getT1(),
  703. subnet_->getT2());
  704. boost::shared_ptr<Option6IAAddr> addr2 = checkIA_NA(reply2, 2, subnet_->getT1(),
  705. subnet_->getT2());
  706. boost::shared_ptr<Option6IAAddr> addr3 = checkIA_NA(reply3, 3, subnet_->getT1(),
  707. subnet_->getT2());
  708. ASSERT_TRUE(addr1);
  709. ASSERT_TRUE(addr2);
  710. ASSERT_TRUE(addr3);
  711. // Check that the assigned address is indeed from the configured pool
  712. checkIAAddr(addr1, addr1->getAddress(), subnet_->getPreferred(), subnet_->getValid());
  713. checkIAAddr(addr2, addr2->getAddress(), subnet_->getPreferred(), subnet_->getValid());
  714. checkIAAddr(addr3, addr3->getAddress(), subnet_->getPreferred(), subnet_->getValid());
  715. // check DUIDs
  716. checkServerId(reply1, srv.getServerID());
  717. checkServerId(reply2, srv.getServerID());
  718. checkServerId(reply3, srv.getServerID());
  719. checkClientId(reply1, clientid1);
  720. checkClientId(reply2, clientid2);
  721. checkClientId(reply3, clientid3);
  722. // Finally check that the addresses offered are different
  723. EXPECT_NE(addr1->getAddress().toText(), addr2->getAddress().toText());
  724. EXPECT_NE(addr2->getAddress().toText(), addr3->getAddress().toText());
  725. EXPECT_NE(addr3->getAddress().toText(), addr1->getAddress().toText());
  726. cout << "Offered address to client1=" << addr1->getAddress().toText() << endl;
  727. cout << "Offered address to client2=" << addr2->getAddress().toText() << endl;
  728. cout << "Offered address to client3=" << addr3->getAddress().toText() << endl;
  729. }
  730. // This test verifies that incoming REQUEST can be handled properly, that a
  731. // REPLY is generated, that the response has an address and that address
  732. // really belongs to the configured pool.
  733. //
  734. // This test sends a REQUEST with IA_NA that contains a valid hint.
  735. //
  736. // constructed very simple REQUEST message with:
  737. // - client-id option (mandatory)
  738. // - IA option (a request for address, with an address that belongs to the
  739. // configured pool, i.e. is valid as hint)
  740. //
  741. // expected returned REPLY message:
  742. // - copy of client-id
  743. // - server-id
  744. // - IA that includes IAADDR
  745. TEST_F(Dhcpv6SrvTest, RequestBasic) {
  746. NakedDhcpv6Srv srv(0);
  747. // Let's create a REQUEST
  748. Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234));
  749. req->setRemoteAddr(IOAddress("fe80::abcd"));
  750. boost::shared_ptr<Option6IA> ia = generateIA(234, 1500, 3000);
  751. // with a valid hint
  752. IOAddress hint("2001:db8:1:1::dead:beef");
  753. ASSERT_TRUE(subnet_->inPool(hint));
  754. OptionPtr hint_opt(new Option6IAAddr(D6O_IAADDR, hint, 300, 500));
  755. ia->addOption(hint_opt);
  756. req->addOption(ia);
  757. OptionPtr clientid = generateClientId();
  758. req->addOption(clientid);
  759. // server-id is mandatory in REQUEST
  760. req->addOption(srv.getServerID());
  761. // Pass it to the server and hope for a REPLY
  762. Pkt6Ptr reply = srv.processRequest(req);
  763. // check if we get response at all
  764. checkResponse(reply, DHCPV6_REPLY, 1234);
  765. OptionPtr tmp = reply->getOption(D6O_IA_NA);
  766. ASSERT_TRUE(tmp);
  767. // check that IA_NA was returned and that there's an address included
  768. boost::shared_ptr<Option6IAAddr> addr = checkIA_NA(reply, 234, subnet_->getT1(),
  769. subnet_->getT2());
  770. ASSERT_TRUE(addr);
  771. // check that we've got the address we requested
  772. checkIAAddr(addr, hint, subnet_->getPreferred(), subnet_->getValid());
  773. // check DUIDs
  774. checkServerId(reply, srv.getServerID());
  775. checkClientId(reply, clientid);
  776. // check that the lease is really in the database
  777. Lease6Ptr l = checkLease(duid_, reply->getOption(D6O_IA_NA), addr);
  778. EXPECT_TRUE(l);
  779. LeaseMgrFactory::instance().deleteLease(addr->getAddress());
  780. }
  781. // This test checks that the server is offering different addresses to different
  782. // clients in REQUEST. Please note that ADVERTISE is not a guarantee that such
  783. // and address will be assigned. Had the pool was very small and contained only
  784. // 2 addresses, the third client would get the same advertise as the first one
  785. // and this is a correct behavior. It is REQUEST that will fail for the third
  786. // client. ADVERTISE is basically saying "if you send me a request, you will
  787. // probably get an address like this" (there are no guarantees).
  788. TEST_F(Dhcpv6SrvTest, ManyRequests) {
  789. NakedDhcpv6Srv srv(0);
  790. ASSERT_TRUE(subnet_);
  791. Pkt6Ptr req1 = Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 1234));
  792. Pkt6Ptr req2 = Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 2345));
  793. Pkt6Ptr req3 = Pkt6Ptr(new Pkt6(DHCPV6_REQUEST, 3456));
  794. req1->setRemoteAddr(IOAddress("fe80::abcd"));
  795. req2->setRemoteAddr(IOAddress("fe80::1223"));
  796. req3->setRemoteAddr(IOAddress("fe80::3467"));
  797. req1->addOption(generateIA(1, 1500, 3000));
  798. req2->addOption(generateIA(2, 1500, 3000));
  799. req3->addOption(generateIA(3, 1500, 3000));
  800. // different client-id sizes
  801. OptionPtr clientid1 = generateClientId(12);
  802. OptionPtr clientid2 = generateClientId(14);
  803. OptionPtr clientid3 = generateClientId(16);
  804. req1->addOption(clientid1);
  805. req2->addOption(clientid2);
  806. req3->addOption(clientid3);
  807. // server-id is mandatory in REQUEST
  808. req1->addOption(srv.getServerID());
  809. req2->addOption(srv.getServerID());
  810. req3->addOption(srv.getServerID());
  811. // Pass it to the server and get an advertise
  812. Pkt6Ptr reply1 = srv.processRequest(req1);
  813. Pkt6Ptr reply2 = srv.processRequest(req2);
  814. Pkt6Ptr reply3 = srv.processRequest(req3);
  815. // check if we get response at all
  816. checkResponse(reply1, DHCPV6_REPLY, 1234);
  817. checkResponse(reply2, DHCPV6_REPLY, 2345);
  818. checkResponse(reply3, DHCPV6_REPLY, 3456);
  819. // check that IA_NA was returned and that there's an address included
  820. boost::shared_ptr<Option6IAAddr> addr1 = checkIA_NA(reply1, 1, subnet_->getT1(),
  821. subnet_->getT2());
  822. boost::shared_ptr<Option6IAAddr> addr2 = checkIA_NA(reply2, 2, subnet_->getT1(),
  823. subnet_->getT2());
  824. boost::shared_ptr<Option6IAAddr> addr3 = checkIA_NA(reply3, 3, subnet_->getT1(),
  825. subnet_->getT2());
  826. ASSERT_TRUE(addr1);
  827. ASSERT_TRUE(addr2);
  828. ASSERT_TRUE(addr3);
  829. // Check that the assigned address is indeed from the configured pool
  830. checkIAAddr(addr1, addr1->getAddress(), subnet_->getPreferred(), subnet_->getValid());
  831. checkIAAddr(addr2, addr2->getAddress(), subnet_->getPreferred(), subnet_->getValid());
  832. checkIAAddr(addr3, addr3->getAddress(), subnet_->getPreferred(), subnet_->getValid());
  833. // check DUIDs
  834. checkServerId(reply1, srv.getServerID());
  835. checkServerId(reply2, srv.getServerID());
  836. checkServerId(reply3, srv.getServerID());
  837. checkClientId(reply1, clientid1);
  838. checkClientId(reply2, clientid2);
  839. checkClientId(reply3, clientid3);
  840. // Finally check that the addresses offered are different
  841. EXPECT_NE(addr1->getAddress().toText(), addr2->getAddress().toText());
  842. EXPECT_NE(addr2->getAddress().toText(), addr3->getAddress().toText());
  843. EXPECT_NE(addr3->getAddress().toText(), addr1->getAddress().toText());
  844. cout << "Assigned address to client1=" << addr1->getAddress().toText() << endl;
  845. cout << "Assigned address to client2=" << addr2->getAddress().toText() << endl;
  846. cout << "Assigned address to client3=" << addr3->getAddress().toText() << endl;
  847. }
  848. // This test verifies that incoming (positive) RENEW can be handled properly, that a
  849. // REPLY is generated, that the response has an address and that address
  850. // really belongs to the configured pool and that lease is actually renewed.
  851. //
  852. // expected:
  853. // - returned REPLY message has copy of client-id
  854. // - returned REPLY message has server-id
  855. // - returned REPLY message has IA that includes IAADDR
  856. // - lease is actually renewed in LeaseMgr
  857. TEST_F(Dhcpv6SrvTest, RenewBasic) {
  858. NakedDhcpv6Srv srv(0);
  859. const IOAddress addr("2001:db8:1:1::cafe:babe");
  860. const uint32_t iaid = 234;
  861. // Generate client-id also duid_
  862. OptionPtr clientid = generateClientId();
  863. // Check that the address we are about to use is indeed in pool
  864. ASSERT_TRUE(subnet_->inPool(addr));
  865. // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
  866. // value on purpose. They should be updated during RENEW.
  867. Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr, duid_, iaid,
  868. 501, 502, 503, 504, subnet_->getID(), 0));
  869. lease->cltt_ = 1234;
  870. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
  871. // Check that the lease is really in the database
  872. Lease6Ptr l = LeaseMgrFactory::instance().getLease6(addr);
  873. ASSERT_TRUE(l);
  874. // Check that T1, T2, preferred, valid and cltt really set and not using
  875. // previous (500, 501, etc.) values
  876. EXPECT_NE(l->t1_, subnet_->getT1());
  877. EXPECT_NE(l->t2_, subnet_->getT2());
  878. EXPECT_NE(l->preferred_lft_, subnet_->getPreferred());
  879. EXPECT_NE(l->valid_lft_, subnet_->getValid());
  880. EXPECT_NE(l->cltt_, time(NULL));
  881. // Let's create a RENEW
  882. Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, 1234));
  883. req->setRemoteAddr(IOAddress("fe80::abcd"));
  884. boost::shared_ptr<Option6IA> ia = generateIA(iaid, 1500, 3000);
  885. OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
  886. ia->addOption(renewed_addr_opt);
  887. req->addOption(ia);
  888. req->addOption(clientid);
  889. // Server-id is mandatory in RENEW
  890. req->addOption(srv.getServerID());
  891. // Pass it to the server and hope for a REPLY
  892. Pkt6Ptr reply = srv.processRenew(req);
  893. // Check if we get response at all
  894. checkResponse(reply, DHCPV6_REPLY, 1234);
  895. OptionPtr tmp = reply->getOption(D6O_IA_NA);
  896. ASSERT_TRUE(tmp);
  897. // Check that IA_NA was returned and that there's an address included
  898. boost::shared_ptr<Option6IAAddr> addr_opt = checkIA_NA(reply, 234, subnet_->getT1(),
  899. subnet_->getT2());
  900. ASSERT_TRUE(addr_opt);
  901. // Check that we've got the address we requested
  902. checkIAAddr(addr_opt, addr, subnet_->getPreferred(), subnet_->getValid());
  903. // Check DUIDs
  904. checkServerId(reply, srv.getServerID());
  905. checkClientId(reply, clientid);
  906. // Check that the lease is really in the database
  907. l = checkLease(duid_, reply->getOption(D6O_IA_NA), addr_opt);
  908. ASSERT_TRUE(l);
  909. // Check that T1, T2, preferred, valid and cltt were really updated
  910. EXPECT_EQ(l->t1_, subnet_->getT1());
  911. EXPECT_EQ(l->t2_, subnet_->getT2());
  912. EXPECT_EQ(l->preferred_lft_, subnet_->getPreferred());
  913. EXPECT_EQ(l->valid_lft_, subnet_->getValid());
  914. // Checking for CLTT is a bit tricky if we want to avoid off by 1 errors
  915. int32_t cltt = static_cast<int32_t>(l->cltt_);
  916. int32_t expected = static_cast<int32_t>(time(NULL));
  917. // equality or difference by 1 between cltt and expected is ok.
  918. EXPECT_GE(1, abs(cltt - expected));
  919. EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr_opt->getAddress()));
  920. }
  921. // This test verifies that incoming (invalid) RENEW can be handled properly.
  922. //
  923. // This test checks 3 scenarios:
  924. // 1. there is no such lease at all
  925. // 2. there is such a lease, but it is assigned to a different IAID
  926. // 3. there is such a lease, but it belongs to a different client
  927. //
  928. // expected:
  929. // - returned REPLY message has copy of client-id
  930. // - returned REPLY message has server-id
  931. // - returned REPLY message has IA that includes STATUS-CODE
  932. // - No lease in LeaseMgr
  933. TEST_F(Dhcpv6SrvTest, RenewReject) {
  934. NakedDhcpv6Srv srv(0);
  935. const IOAddress addr("2001:db8:1:1::dead");
  936. const uint32_t transid = 1234;
  937. const uint32_t valid_iaid = 234;
  938. const uint32_t bogus_iaid = 456;
  939. // Quick sanity check that the address we're about to use is ok
  940. ASSERT_TRUE(subnet_->inPool(addr));
  941. // GenerateClientId() also sets duid_
  942. OptionPtr clientid = generateClientId();
  943. // Check that the lease is NOT in the database
  944. Lease6Ptr l = LeaseMgrFactory::instance().getLease6(addr);
  945. ASSERT_FALSE(l);
  946. // Let's create a RENEW
  947. Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RENEW, transid));
  948. req->setRemoteAddr(IOAddress("fe80::abcd"));
  949. boost::shared_ptr<Option6IA> ia = generateIA(bogus_iaid, 1500, 3000);
  950. OptionPtr renewed_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
  951. ia->addOption(renewed_addr_opt);
  952. req->addOption(ia);
  953. req->addOption(clientid);
  954. // Server-id is mandatory in RENEW
  955. req->addOption(srv.getServerID());
  956. // Case 1: No lease known to server
  957. // Pass it to the server and hope for a REPLY
  958. Pkt6Ptr reply = srv.processRenew(req);
  959. // Check if we get response at all
  960. checkResponse(reply, DHCPV6_REPLY, transid);
  961. OptionPtr tmp = reply->getOption(D6O_IA_NA);
  962. ASSERT_TRUE(tmp);
  963. // Check that IA_NA was returned and that there's an address included
  964. ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
  965. ASSERT_TRUE(ia);
  966. checkIA_NAStatusCode(ia, STATUS_NoBinding);
  967. // Check that there is no lease added
  968. l = LeaseMgrFactory::instance().getLease6(addr);
  969. ASSERT_FALSE(l);
  970. // CASE 2: Lease is known and belongs to this client, but to a different IAID
  971. // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
  972. // value on purpose. They should be updated during RENEW.
  973. Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr, duid_, valid_iaid,
  974. 501, 502, 503, 504, subnet_->getID(), 0));
  975. lease->cltt_ = 123; // Let's use it as an indicator that the lease
  976. // was NOT updated.
  977. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
  978. // Pass it to the server and hope for a REPLY
  979. reply = srv.processRenew(req);
  980. checkResponse(reply, DHCPV6_REPLY, transid);
  981. tmp = reply->getOption(D6O_IA_NA);
  982. ASSERT_TRUE(tmp);
  983. // Check that IA_NA was returned and that there's an address included
  984. ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
  985. ASSERT_TRUE(ia);
  986. checkIA_NAStatusCode(ia, STATUS_NoBinding);
  987. // There is a iaid mis-match, so server should respond that there is
  988. // no such address to renew.
  989. // CASE 3: Lease belongs to a client with different client-id
  990. req->delOption(D6O_CLIENTID);
  991. ia = boost::dynamic_pointer_cast<Option6IA>(req->getOption(D6O_IA_NA));
  992. ia->setIAID(valid_iaid); // Now iaid in renew matches that in leasemgr
  993. req->addOption(generateClientId(13)); // generate different DUID
  994. // (with length 13)
  995. reply = srv.processRenew(req);
  996. checkResponse(reply, DHCPV6_REPLY, transid);
  997. tmp = reply->getOption(D6O_IA_NA);
  998. ASSERT_TRUE(tmp);
  999. // Check that IA_NA was returned and that there's an address included
  1000. ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
  1001. ASSERT_TRUE(ia);
  1002. checkIA_NAStatusCode(ia, STATUS_NoBinding);
  1003. lease = LeaseMgrFactory::instance().getLease6(addr);
  1004. ASSERT_TRUE(lease);
  1005. // Verify that the lease was not updated.
  1006. EXPECT_EQ(123, lease->cltt_);
  1007. EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
  1008. }
  1009. // This test verifies that incoming (positive) RELEASE can be handled properly,
  1010. // that a REPLY is generated, that the response has status code and that the
  1011. // lease is indeed removed from the database.
  1012. //
  1013. // expected:
  1014. // - returned REPLY message has copy of client-id
  1015. // - returned REPLY message has server-id
  1016. // - returned REPLY message has IA that does not include an IAADDR
  1017. // - lease is actually removed from LeaseMgr
  1018. TEST_F(Dhcpv6SrvTest, ReleaseBasic) {
  1019. NakedDhcpv6Srv srv(0);
  1020. const IOAddress addr("2001:db8:1:1::cafe:babe");
  1021. const uint32_t iaid = 234;
  1022. // Generate client-id also duid_
  1023. OptionPtr clientid = generateClientId();
  1024. // Check that the address we are about to use is indeed in pool
  1025. ASSERT_TRUE(subnet_->inPool(addr));
  1026. // Note that preferred, valid, T1 and T2 timers and CLTT are set to invalid
  1027. // value on purpose. They should be updated during RENEW.
  1028. Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr, duid_, iaid,
  1029. 501, 502, 503, 504, subnet_->getID(), 0));
  1030. lease->cltt_ = 1234;
  1031. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
  1032. // Check that the lease is really in the database
  1033. Lease6Ptr l = LeaseMgrFactory::instance().getLease6(addr);
  1034. ASSERT_TRUE(l);
  1035. // Let's create a RELEASE
  1036. Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, 1234));
  1037. req->setRemoteAddr(IOAddress("fe80::abcd"));
  1038. boost::shared_ptr<Option6IA> ia = generateIA(iaid, 1500, 3000);
  1039. OptionPtr released_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
  1040. ia->addOption(released_addr_opt);
  1041. req->addOption(ia);
  1042. req->addOption(clientid);
  1043. // Server-id is mandatory in RELEASE
  1044. req->addOption(srv.getServerID());
  1045. // Pass it to the server and hope for a REPLY
  1046. Pkt6Ptr reply = srv.processRelease(req);
  1047. // Check if we get response at all
  1048. checkResponse(reply, DHCPV6_REPLY, 1234);
  1049. OptionPtr tmp = reply->getOption(D6O_IA_NA);
  1050. ASSERT_TRUE(tmp);
  1051. // Check that IA_NA was returned and that there's an address included
  1052. ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
  1053. checkIA_NAStatusCode(ia, STATUS_Success);
  1054. checkMsgStatusCode(reply, STATUS_Success);
  1055. // There should be no address returned in RELEASE (see RFC3315, 18.2.6)
  1056. EXPECT_FALSE(tmp->getOption(D6O_IAADDR));
  1057. // Check DUIDs
  1058. checkServerId(reply, srv.getServerID());
  1059. checkClientId(reply, clientid);
  1060. // Check that the lease is really gone in the database
  1061. // get lease by address
  1062. l = LeaseMgrFactory::instance().getLease6(addr);
  1063. ASSERT_FALSE(l);
  1064. // get lease by subnetid/duid/iaid combination
  1065. l = LeaseMgrFactory::instance().getLease6(*duid_, iaid, subnet_->getID());
  1066. ASSERT_FALSE(l);
  1067. }
  1068. // This test verifies that incoming (invalid) RELEASE can be handled properly.
  1069. //
  1070. // This test checks 3 scenarios:
  1071. // 1. there is no such lease at all
  1072. // 2. there is such a lease, but it is assigned to a different IAID
  1073. // 3. there is such a lease, but it belongs to a different client
  1074. //
  1075. // expected:
  1076. // - returned REPLY message has copy of client-id
  1077. // - returned REPLY message has server-id
  1078. // - returned REPLY message has IA that includes STATUS-CODE
  1079. // - No lease in LeaseMgr
  1080. TEST_F(Dhcpv6SrvTest, ReleaseReject) {
  1081. NakedDhcpv6Srv srv(0);
  1082. const IOAddress addr("2001:db8:1:1::dead");
  1083. const uint32_t transid = 1234;
  1084. const uint32_t valid_iaid = 234;
  1085. const uint32_t bogus_iaid = 456;
  1086. // Quick sanity check that the address we're about to use is ok
  1087. ASSERT_TRUE(subnet_->inPool(addr));
  1088. // GenerateClientId() also sets duid_
  1089. OptionPtr clientid = generateClientId();
  1090. // Check that the lease is NOT in the database
  1091. Lease6Ptr l = LeaseMgrFactory::instance().getLease6(addr);
  1092. ASSERT_FALSE(l);
  1093. // Let's create a RELEASE
  1094. Pkt6Ptr req = Pkt6Ptr(new Pkt6(DHCPV6_RELEASE, transid));
  1095. req->setRemoteAddr(IOAddress("fe80::abcd"));
  1096. boost::shared_ptr<Option6IA> ia = generateIA(bogus_iaid, 1500, 3000);
  1097. OptionPtr released_addr_opt(new Option6IAAddr(D6O_IAADDR, addr, 300, 500));
  1098. ia->addOption(released_addr_opt);
  1099. req->addOption(ia);
  1100. req->addOption(clientid);
  1101. // Server-id is mandatory in RENEW
  1102. req->addOption(srv.getServerID());
  1103. // Case 1: No lease known to server
  1104. SCOPED_TRACE("CASE 1: No lease known to server");
  1105. // Pass it to the server and hope for a REPLY
  1106. Pkt6Ptr reply = srv.processRelease(req);
  1107. // Check if we get response at all
  1108. checkResponse(reply, DHCPV6_REPLY, transid);
  1109. OptionPtr tmp = reply->getOption(D6O_IA_NA);
  1110. ASSERT_TRUE(tmp);
  1111. // Check that IA_NA was returned and that there's an address included
  1112. ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
  1113. ASSERT_TRUE(ia);
  1114. checkIA_NAStatusCode(ia, STATUS_NoBinding);
  1115. checkMsgStatusCode(reply, STATUS_NoBinding);
  1116. // Check that the lease is not there
  1117. l = LeaseMgrFactory::instance().getLease6(addr);
  1118. ASSERT_FALSE(l);
  1119. // CASE 2: Lease is known and belongs to this client, but to a different IAID
  1120. SCOPED_TRACE("CASE 2: Lease is known and belongs to this client, but to a different IAID");
  1121. Lease6Ptr lease(new Lease6(Lease6::LEASE_IA_NA, addr, duid_, valid_iaid,
  1122. 501, 502, 503, 504, subnet_->getID(), 0));
  1123. ASSERT_TRUE(LeaseMgrFactory::instance().addLease(lease));
  1124. // Pass it to the server and hope for a REPLY
  1125. reply = srv.processRelease(req);
  1126. checkResponse(reply, DHCPV6_REPLY, transid);
  1127. tmp = reply->getOption(D6O_IA_NA);
  1128. ASSERT_TRUE(tmp);
  1129. // Check that IA_NA was returned and that there's an address included
  1130. ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
  1131. ASSERT_TRUE(ia);
  1132. checkIA_NAStatusCode(ia, STATUS_NoBinding);
  1133. checkMsgStatusCode(reply, STATUS_NoBinding);
  1134. // Check that the lease is still there
  1135. l = LeaseMgrFactory::instance().getLease6(addr);
  1136. ASSERT_TRUE(l);
  1137. // CASE 3: Lease belongs to a client with different client-id
  1138. SCOPED_TRACE("CASE 3: Lease belongs to a client with different client-id");
  1139. req->delOption(D6O_CLIENTID);
  1140. ia = boost::dynamic_pointer_cast<Option6IA>(req->getOption(D6O_IA_NA));
  1141. ia->setIAID(valid_iaid); // Now iaid in renew matches that in leasemgr
  1142. req->addOption(generateClientId(13)); // generate different DUID
  1143. // (with length 13)
  1144. reply = srv.processRelease(req);
  1145. checkResponse(reply, DHCPV6_REPLY, transid);
  1146. tmp = reply->getOption(D6O_IA_NA);
  1147. ASSERT_TRUE(tmp);
  1148. // Check that IA_NA was returned and that there's an address included
  1149. ia = boost::dynamic_pointer_cast<Option6IA>(tmp);
  1150. ASSERT_TRUE(ia);
  1151. checkIA_NAStatusCode(ia, STATUS_NoBinding);
  1152. checkMsgStatusCode(reply, STATUS_NoBinding);
  1153. // Check that the lease is still there
  1154. l = LeaseMgrFactory::instance().getLease6(addr);
  1155. ASSERT_TRUE(l);
  1156. // Finally, let's cleanup the database
  1157. EXPECT_TRUE(LeaseMgrFactory::instance().deleteLease(addr));
  1158. }
  1159. // This test verifies if the status code option is generated properly.
  1160. TEST_F(Dhcpv6SrvTest, StatusCode) {
  1161. NakedDhcpv6Srv srv(0);
  1162. // a dummy content for client-id
  1163. uint8_t expected[] = {
  1164. 0x0, 0xD, // option code = 13
  1165. 0x0, 0x7, // option length = 7
  1166. 0x0, 0x3, // status code = 3
  1167. 0x41, 0x42, 0x43, 0x44, 0x45 // string value ABCDE
  1168. };
  1169. // Create the option.
  1170. OptionPtr status = srv.createStatusCode(3, "ABCDE");
  1171. // Allocate an output buffer. We will store the option
  1172. // in wire format here.
  1173. OutputBuffer buf(sizeof(expected));
  1174. // Prepare the wire format.
  1175. ASSERT_NO_THROW(status->pack(buf));
  1176. // Check that the option buffer has valid length (option header + data).
  1177. ASSERT_EQ(sizeof(expected), buf.getLength());
  1178. // Verify the contents of the option.
  1179. EXPECT_EQ(0, memcmp(expected, buf.getData(), sizeof(expected)));
  1180. }
  1181. // This test verifies if the sanityCheck() really checks options presence.
  1182. TEST_F(Dhcpv6SrvTest, sanityCheck) {
  1183. NakedDhcpv6Srv srv(0);
  1184. Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
  1185. // Set link-local sender address, so appropriate subnet can be
  1186. // selected for this packet.
  1187. pkt->setRemoteAddr(IOAddress("fe80::abcd"));
  1188. // client-id is optional for information-request, so
  1189. EXPECT_NO_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::OPTIONAL, Dhcpv6Srv::OPTIONAL));
  1190. // empty packet, no client-id, no server-id
  1191. EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::FORBIDDEN),
  1192. RFCViolation);
  1193. // This doesn't make much sense, but let's check it for completeness
  1194. EXPECT_NO_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::FORBIDDEN, Dhcpv6Srv::FORBIDDEN));
  1195. OptionPtr clientid = generateClientId();
  1196. pkt->addOption(clientid);
  1197. // client-id is mandatory, server-id is forbidden (as in SOLICIT or REBIND)
  1198. EXPECT_NO_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::FORBIDDEN));
  1199. pkt->addOption(srv.getServerID());
  1200. // both client-id and server-id are mandatory (as in REQUEST, RENEW, RELEASE, DECLINE)
  1201. EXPECT_NO_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::MANDATORY));
  1202. // sane section ends here, let's do some negative tests as well
  1203. pkt->addOption(clientid);
  1204. pkt->addOption(clientid);
  1205. // with more than one client-id it should throw, no matter what
  1206. EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::OPTIONAL, Dhcpv6Srv::OPTIONAL),
  1207. RFCViolation);
  1208. EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::OPTIONAL),
  1209. RFCViolation);
  1210. EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::OPTIONAL, Dhcpv6Srv::MANDATORY),
  1211. RFCViolation);
  1212. EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::MANDATORY),
  1213. RFCViolation);
  1214. pkt->delOption(D6O_CLIENTID);
  1215. pkt->delOption(D6O_CLIENTID);
  1216. // again we have only one client-id
  1217. // let's try different type of insanity - several server-ids
  1218. pkt->addOption(srv.getServerID());
  1219. pkt->addOption(srv.getServerID());
  1220. // with more than one server-id it should throw, no matter what
  1221. EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::OPTIONAL, Dhcpv6Srv::OPTIONAL),
  1222. RFCViolation);
  1223. EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::OPTIONAL),
  1224. RFCViolation);
  1225. EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::OPTIONAL, Dhcpv6Srv::MANDATORY),
  1226. RFCViolation);
  1227. EXPECT_THROW(srv.sanityCheck(pkt, Dhcpv6Srv::MANDATORY, Dhcpv6Srv::MANDATORY),
  1228. RFCViolation);
  1229. }
  1230. // This test verifies if selectSubnet() selects proper subnet for a given
  1231. // source address.
  1232. TEST_F(Dhcpv6SrvTest, selectSubnetAddr) {
  1233. NakedDhcpv6Srv srv(0);
  1234. Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4));
  1235. Subnet6Ptr subnet2(new Subnet6(IOAddress("2001:db8:2::"), 48, 1, 2, 3, 4));
  1236. Subnet6Ptr subnet3(new Subnet6(IOAddress("2001:db8:3::"), 48, 1, 2, 3, 4));
  1237. // CASE 1: We have only one subnet defined and we received local traffic.
  1238. // The only available subnet should be selected
  1239. CfgMgr::instance().deleteSubnets6();
  1240. CfgMgr::instance().addSubnet6(subnet1); // just a single subnet
  1241. Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
  1242. pkt->setRemoteAddr(IOAddress("fe80::abcd"));
  1243. Subnet6Ptr selected = srv.selectSubnet(pkt);
  1244. EXPECT_EQ(selected, subnet1);
  1245. // CASE 2: We have only one subnet defined and we received relayed traffic.
  1246. // We should NOT select it.
  1247. // Identical steps as in case 1, but repeated for clarity
  1248. CfgMgr::instance().deleteSubnets6();
  1249. CfgMgr::instance().addSubnet6(subnet1); // just a single subnet
  1250. pkt->setRemoteAddr(IOAddress("2001:db8:abcd::2345"));
  1251. selected = srv.selectSubnet(pkt);
  1252. EXPECT_FALSE(selected);
  1253. // CASE 3: We have three subnets defined and we received local traffic.
  1254. // Nothing should be selected.
  1255. CfgMgr::instance().deleteSubnets6();
  1256. CfgMgr::instance().addSubnet6(subnet1);
  1257. CfgMgr::instance().addSubnet6(subnet2);
  1258. CfgMgr::instance().addSubnet6(subnet3);
  1259. pkt->setRemoteAddr(IOAddress("fe80::abcd"));
  1260. selected = srv.selectSubnet(pkt);
  1261. EXPECT_FALSE(selected);
  1262. // CASE 4: We have three subnets defined and we received relayed traffic
  1263. // that came out of subnet 2. We should select subnet2 then
  1264. CfgMgr::instance().deleteSubnets6();
  1265. CfgMgr::instance().addSubnet6(subnet1);
  1266. CfgMgr::instance().addSubnet6(subnet2);
  1267. CfgMgr::instance().addSubnet6(subnet3);
  1268. pkt->setRemoteAddr(IOAddress("2001:db8:2::baca"));
  1269. selected = srv.selectSubnet(pkt);
  1270. EXPECT_EQ(selected, subnet2);
  1271. // CASE 5: We have three subnets defined and we received relayed traffic
  1272. // that came out of undefined subnet. We should select nothing
  1273. CfgMgr::instance().deleteSubnets6();
  1274. CfgMgr::instance().addSubnet6(subnet1);
  1275. CfgMgr::instance().addSubnet6(subnet2);
  1276. CfgMgr::instance().addSubnet6(subnet3);
  1277. pkt->setRemoteAddr(IOAddress("2001:db8:4::baca"));
  1278. selected = srv.selectSubnet(pkt);
  1279. EXPECT_FALSE(selected);
  1280. }
  1281. // This test verifies if selectSubnet() selects proper subnet for a given
  1282. // network interface name.
  1283. TEST_F(Dhcpv6SrvTest, selectSubnetIface) {
  1284. NakedDhcpv6Srv srv(0);
  1285. Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4));
  1286. Subnet6Ptr subnet2(new Subnet6(IOAddress("2001:db8:2::"), 48, 1, 2, 3, 4));
  1287. Subnet6Ptr subnet3(new Subnet6(IOAddress("2001:db8:3::"), 48, 1, 2, 3, 4));
  1288. subnet1->setIface("eth0");
  1289. subnet3->setIface("wifi1");
  1290. // CASE 1: We have only one subnet defined and it is available via eth0.
  1291. // Packet came from eth0. The only available subnet should be selected
  1292. CfgMgr::instance().deleteSubnets6();
  1293. CfgMgr::instance().addSubnet6(subnet1); // just a single subnet
  1294. Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
  1295. pkt->setIface("eth0");
  1296. Subnet6Ptr selected = srv.selectSubnet(pkt);
  1297. EXPECT_EQ(selected, subnet1);
  1298. // CASE 2: We have only one subnet defined and it is available via eth0.
  1299. // Packet came from eth1. We should not select it
  1300. CfgMgr::instance().deleteSubnets6();
  1301. CfgMgr::instance().addSubnet6(subnet1); // just a single subnet
  1302. pkt->setIface("eth1");
  1303. selected = srv.selectSubnet(pkt);
  1304. EXPECT_FALSE(selected);
  1305. // CASE 3: We have only 3 subnets defined, one over eth0, one remote and
  1306. // one over wifi1.
  1307. // Packet came from eth1. We should not select it
  1308. CfgMgr::instance().deleteSubnets6();
  1309. CfgMgr::instance().addSubnet6(subnet1);
  1310. CfgMgr::instance().addSubnet6(subnet2);
  1311. CfgMgr::instance().addSubnet6(subnet3);
  1312. pkt->setIface("eth0");
  1313. EXPECT_EQ(subnet1, srv.selectSubnet(pkt));
  1314. pkt->setIface("eth3"); // no such interface
  1315. EXPECT_EQ(Subnet6Ptr(), srv.selectSubnet(pkt)); // nothing selected
  1316. pkt->setIface("wifi1");
  1317. EXPECT_EQ(subnet3, srv.selectSubnet(pkt));
  1318. }
  1319. // This test verifies if selectSubnet() selects proper subnet for a given
  1320. // linkaddr in RELAY-FORW message
  1321. TEST_F(Dhcpv6SrvTest, selectSubnetRelayLinkaddr) {
  1322. NakedDhcpv6Srv srv(0);
  1323. Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4));
  1324. Subnet6Ptr subnet2(new Subnet6(IOAddress("2001:db8:2::"), 48, 1, 2, 3, 4));
  1325. Subnet6Ptr subnet3(new Subnet6(IOAddress("2001:db8:3::"), 48, 1, 2, 3, 4));
  1326. Pkt6::RelayInfo relay;
  1327. relay.linkaddr_ = IOAddress("2001:db8:2::1234");
  1328. relay.peeraddr_ = IOAddress("fe80::1");
  1329. // CASE 1: We have only one subnet defined and we received relayed traffic.
  1330. // The only available subnet should NOT be selected.
  1331. CfgMgr::instance().deleteSubnets6();
  1332. CfgMgr::instance().addSubnet6(subnet1); // just a single subnet
  1333. Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
  1334. pkt->relay_info_.push_back(relay);
  1335. Subnet6Ptr selected = srv.selectSubnet(pkt);
  1336. EXPECT_FALSE(selected);
  1337. // CASE 2: We have three subnets defined and we received relayed traffic.
  1338. // Nothing should be selected.
  1339. CfgMgr::instance().deleteSubnets6();
  1340. CfgMgr::instance().addSubnet6(subnet1);
  1341. CfgMgr::instance().addSubnet6(subnet2);
  1342. CfgMgr::instance().addSubnet6(subnet3);
  1343. selected = srv.selectSubnet(pkt);
  1344. EXPECT_EQ(selected, subnet2);
  1345. // CASE 3: We have three subnets defined and we received relayed traffic
  1346. // that came out of subnet 2. We should select subnet2 then
  1347. CfgMgr::instance().deleteSubnets6();
  1348. CfgMgr::instance().addSubnet6(subnet1);
  1349. CfgMgr::instance().addSubnet6(subnet2);
  1350. CfgMgr::instance().addSubnet6(subnet3);
  1351. // Source of the packet should have no meaning. Selection is based
  1352. // on linkaddr field in the relay
  1353. pkt->setRemoteAddr(IOAddress("2001:db8:1::baca"));
  1354. selected = srv.selectSubnet(pkt);
  1355. EXPECT_EQ(selected, subnet2);
  1356. // CASE 4: We have three subnets defined and we received relayed traffic
  1357. // that came out of undefined subnet. We should select nothing
  1358. CfgMgr::instance().deleteSubnets6();
  1359. CfgMgr::instance().addSubnet6(subnet1);
  1360. CfgMgr::instance().addSubnet6(subnet2);
  1361. CfgMgr::instance().addSubnet6(subnet3);
  1362. pkt->relay_info_.clear();
  1363. relay.linkaddr_ = IOAddress("2001:db8:4::1234");
  1364. pkt->relay_info_.push_back(relay);
  1365. selected = srv.selectSubnet(pkt);
  1366. EXPECT_FALSE(selected);
  1367. }
  1368. // This test verifies if selectSubnet() selects proper subnet for a given
  1369. // interface-id option
  1370. TEST_F(Dhcpv6SrvTest, selectSubnetRelayInterfaceId) {
  1371. NakedDhcpv6Srv srv(0);
  1372. Subnet6Ptr subnet1(new Subnet6(IOAddress("2001:db8:1::"), 48, 1, 2, 3, 4));
  1373. Subnet6Ptr subnet2(new Subnet6(IOAddress("2001:db8:2::"), 48, 1, 2, 3, 4));
  1374. Subnet6Ptr subnet3(new Subnet6(IOAddress("2001:db8:3::"), 48, 1, 2, 3, 4));
  1375. subnet1->setInterfaceId(generateInterfaceId("relay1"));
  1376. subnet2->setInterfaceId(generateInterfaceId("relay2"));
  1377. // CASE 1: We have only one subnet defined and it is for interface-id "relay1"
  1378. // Packet came with interface-id "relay2". We should not select subnet1
  1379. CfgMgr::instance().deleteSubnets6();
  1380. CfgMgr::instance().addSubnet6(subnet1); // just a single subnet
  1381. Pkt6Ptr pkt = Pkt6Ptr(new Pkt6(DHCPV6_SOLICIT, 1234));
  1382. Pkt6::RelayInfo relay;
  1383. relay.linkaddr_ = IOAddress("2001:db8:2::1234");
  1384. relay.peeraddr_ = IOAddress("fe80::1");
  1385. OptionPtr opt = generateInterfaceId("relay2");
  1386. relay.options_.insert(make_pair(opt->getType(), opt));
  1387. pkt->relay_info_.push_back(relay);
  1388. // There is only one subnet configured and we are outside of that subnet
  1389. Subnet6Ptr selected = srv.selectSubnet(pkt);
  1390. EXPECT_FALSE(selected);
  1391. // CASE 2: We have only one subnet defined and it is for interface-id "relay2"
  1392. // Packet came with interface-id "relay2". We should select it
  1393. CfgMgr::instance().deleteSubnets6();
  1394. CfgMgr::instance().addSubnet6(subnet2); // just a single subnet
  1395. selected = srv.selectSubnet(pkt);
  1396. EXPECT_EQ(selected, subnet2);
  1397. // CASE 3: We have only 3 subnets defined: one remote for interface-id "relay1",
  1398. // one remote for interface-id "relay2" and third local
  1399. // packet comes with interface-id "relay2". We should select subnet2
  1400. CfgMgr::instance().deleteSubnets6();
  1401. CfgMgr::instance().addSubnet6(subnet1);
  1402. CfgMgr::instance().addSubnet6(subnet2);
  1403. CfgMgr::instance().addSubnet6(subnet3);
  1404. EXPECT_EQ(subnet2, srv.selectSubnet(pkt));
  1405. }
  1406. // This test verifies if the server-id disk operations (read, write) are
  1407. // working properly.
  1408. TEST_F(Dhcpv6SrvTest, ServerID) {
  1409. NakedDhcpv6Srv srv(0);
  1410. string duid1_text = "01:ff:02:03:06:80:90:ab:cd:ef";
  1411. uint8_t duid1[] = { 0x01, 0xff, 2, 3, 6, 0x80, 0x90, 0xab, 0xcd, 0xef };
  1412. OptionBuffer expected_duid1(duid1, duid1 + sizeof(duid1));
  1413. fstream file1(DUID_FILE, ios::out | ios::trunc);
  1414. file1 << duid1_text;
  1415. file1.close();
  1416. // Test reading from a file
  1417. EXPECT_TRUE(srv.loadServerID(DUID_FILE));
  1418. ASSERT_TRUE(srv.getServerID());
  1419. ASSERT_EQ(sizeof(duid1) + Option::OPTION6_HDR_LEN, srv.getServerID()->len());
  1420. ASSERT_TRUE(expected_duid1 == srv.getServerID()->getData());
  1421. // Now test writing to a file
  1422. EXPECT_EQ(0, unlink(DUID_FILE));
  1423. EXPECT_NO_THROW(srv.writeServerID(DUID_FILE));
  1424. fstream file2(DUID_FILE, ios::in);
  1425. ASSERT_TRUE(file2.good());
  1426. string text;
  1427. file2 >> text;
  1428. file2.close();
  1429. EXPECT_EQ(duid1_text, text);
  1430. }
  1431. /// @todo: Add more negative tests for processX(), e.g. extend sanityCheck() test
  1432. /// to call processX() methods.
  1433. } // end of anonymous namespace