inform_unittest.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. // Copyright (C) 2014 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 <cc/data.h>
  17. #include <dhcp/dhcp4.h>
  18. #include <dhcp/tests/iface_mgr_test_config.h>
  19. #include <dhcp4/tests/dhcp4_test_utils.h>
  20. #include <dhcp4/tests/dhcp4_client.h>
  21. using namespace isc;
  22. using namespace isc::asiolink;
  23. using namespace isc::data;
  24. using namespace isc::dhcp;
  25. using namespace isc::dhcp::test;
  26. namespace {
  27. /// @brief Set of JSON configurations used throughout the Inform tests.
  28. ///
  29. /// - Configuration 0:
  30. /// - Used for testing direct traffic
  31. /// - 1 subnet: 10.0.0.0/24
  32. /// - 1 pool: 10.0.0.10-10.0.0.100
  33. /// - Router option present: 10.0.0.200 and 10.0.0.201
  34. /// - Domain Name Server option present: 10.0.0.202, 10.0.0.203.
  35. /// - Log Servers option present: 192.0.2.200 and 192.0.2.201
  36. /// - Quotes Servers option present: 192.0.2.202, 192.0.2.203.
  37. ///
  38. /// - Configuration 1:
  39. /// - Use for testing relayed messages
  40. /// - 1 subnet: 192.0.2.0/24
  41. /// - Router option present: 192.0.2.200 and 192.0.2.201
  42. /// - Domain Name Server option present: 192.0.2.202, 192.0.2.203.
  43. /// - Log Servers option present: 192.0.2.200 and 192.0.2.201
  44. /// - Quotes Servers option present: 192.0.2.202, 192.0.2.203.
  45. const char* INFORM_CONFIGS[] = {
  46. // Configuration 0
  47. "{ \"interfaces\": [ \"all\" ],"
  48. "\"valid-lifetime\": 600,"
  49. "\"subnet4\": [ { "
  50. " \"subnet\": \"10.0.0.0/24\", "
  51. " \"pool\": [ \"10.0.0.10-10.0.0.100\" ],"
  52. " \"option-data\": [ {"
  53. " \"name\": \"routers\","
  54. " \"code\": 3,"
  55. " \"data\": \"10.0.0.200,10.0.0.201\","
  56. " \"csv-format\": true,"
  57. " \"space\": \"dhcp4\""
  58. " },"
  59. " {"
  60. " \"name\": \"domain-name-servers\","
  61. " \"code\": 6,"
  62. " \"data\": \"10.0.0.202,10.0.0.203\","
  63. " \"csv-format\": true,"
  64. " \"space\": \"dhcp4\""
  65. " },"
  66. " {"
  67. " \"name\": \"log-servers\","
  68. " \"code\": 7,"
  69. " \"data\": \"10.0.0.200,10.0.0.201\","
  70. " \"csv-format\": true,"
  71. " \"space\": \"dhcp4\""
  72. " },"
  73. " {"
  74. " \"name\": \"cookie-servers\","
  75. " \"code\": 8,"
  76. " \"data\": \"10.0.0.202,10.0.0.203\","
  77. " \"csv-format\": true,"
  78. " \"space\": \"dhcp4\""
  79. " } ]"
  80. " } ]"
  81. "}",
  82. // Configuration 1
  83. "{ \"interfaces\": [ \"all\" ],"
  84. "\"valid-lifetime\": 600,"
  85. "\"subnet4\": [ { "
  86. " \"subnet\": \"192.0.2.0/24\", "
  87. " \"option-data\": [ {"
  88. " \"name\": \"routers\","
  89. " \"code\": 3,"
  90. " \"data\": \"192.0.2.200,192.0.2.201\","
  91. " \"csv-format\": true,"
  92. " \"space\": \"dhcp4\""
  93. " },"
  94. " {"
  95. " \"name\": \"domain-name-servers\","
  96. " \"code\": 6,"
  97. " \"data\": \"192.0.2.202,192.0.2.203\","
  98. " \"csv-format\": true,"
  99. " \"space\": \"dhcp4\""
  100. " },"
  101. " {"
  102. " \"name\": \"log-servers\","
  103. " \"code\": 7,"
  104. " \"data\": \"10.0.0.200,10.0.0.201\","
  105. " \"csv-format\": true,"
  106. " \"space\": \"dhcp4\""
  107. " },"
  108. " {"
  109. " \"name\": \"cookie-servers\","
  110. " \"code\": 8,"
  111. " \"data\": \"10.0.0.202,10.0.0.203\","
  112. " \"csv-format\": true,"
  113. " \"space\": \"dhcp4\""
  114. " } ]"
  115. " } ]"
  116. "}"
  117. };
  118. /// @brief Test fixture class for testing DHCPINFORM.
  119. class InformTest : public Dhcpv4SrvTest {
  120. public:
  121. /// @brief Constructor.
  122. ///
  123. /// Sets up fake interfaces.
  124. InformTest()
  125. : Dhcpv4SrvTest(),
  126. iface_mgr_test_config_(true) {
  127. IfaceMgr::instance().openSockets4();
  128. }
  129. /// @brief Interface Manager's fake configuration control.
  130. IfaceMgrTestConfig iface_mgr_test_config_;
  131. };
  132. // Test that directly connected client's DHCPINFORM message is processed and
  133. // DHCPACK message is sent back.
  134. TEST_F(InformTest, directClientBroadcast) {
  135. Dhcp4Client client;
  136. // Configure DHCP server.
  137. configure(INFORM_CONFIGS[0], *client.getServer());
  138. // Request some configuration when DHCPINFORM is sent.
  139. client.requestOptions(DHO_LOG_SERVERS, DHO_COOKIE_SERVERS);
  140. // Preconfigure the client with the IP address.
  141. client.createLease(IOAddress("10.0.0.56"), 600);
  142. // Send DHCPINFORM message to the server.
  143. ASSERT_NO_THROW(client.doInform());
  144. // Make sure that the server responded.
  145. ASSERT_TRUE(client.getContext().response_);
  146. Pkt4Ptr resp = client.getContext().response_;
  147. // Make sure that the server has responded with DHCPACK.
  148. ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
  149. // Response should have been unicast to the ciaddr.
  150. EXPECT_EQ(IOAddress("10.0.0.56"), resp->getLocalAddr());
  151. // Response must not be relayed.
  152. EXPECT_FALSE(resp->isRelayed());
  153. // Make sure that the server id is present.
  154. EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
  155. // Make sure that the Routers option has been received.
  156. ASSERT_EQ(2, client.config_.routers_.size());
  157. EXPECT_EQ("10.0.0.200", client.config_.routers_[0].toText());
  158. EXPECT_EQ("10.0.0.201", client.config_.routers_[1].toText());
  159. // Make sure that the DNS Servers option has been received.
  160. ASSERT_EQ(2, client.config_.dns_servers_.size());
  161. EXPECT_EQ("10.0.0.202", client.config_.dns_servers_[0].toText());
  162. EXPECT_EQ("10.0.0.203", client.config_.dns_servers_[1].toText());
  163. // Make sure that the Log Servers option has been received.
  164. ASSERT_EQ(2, client.config_.quotes_servers_.size());
  165. EXPECT_EQ("10.0.0.200", client.config_.routers_[0].toText());
  166. EXPECT_EQ("10.0.0.201", client.config_.routers_[1].toText());
  167. // Make sure that the Quotes Servers option has been received.
  168. ASSERT_EQ(2, client.config_.log_servers_.size());
  169. EXPECT_EQ("10.0.0.202", client.config_.dns_servers_[0].toText());
  170. EXPECT_EQ("10.0.0.203", client.config_.dns_servers_[1].toText());
  171. // Check that we can send another DHCPINFORM message using
  172. // different ciaddr and we will get the configuration.
  173. client.createLease(IOAddress("10.0.0.12"), 600);
  174. // This time do not request Quotes Servers option and it should not
  175. // be returned.
  176. client.requestOptions(DHO_LOG_SERVERS);
  177. // Send DHCPINFORM.
  178. ASSERT_NO_THROW(client.doInform());
  179. // Make sure that the server responded.
  180. resp = client.getContext().response_;
  181. ASSERT_TRUE(resp);
  182. // Make sure that the server has responded with DHCPACK.
  183. ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
  184. // Response should have been unicast to the ciaddr.
  185. EXPECT_EQ(IOAddress("10.0.0.12"), resp->getLocalAddr());
  186. // Response must not be relayed.
  187. EXPECT_FALSE(resp->isRelayed());
  188. // Make sure that the server id is present.
  189. EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
  190. // Make sure that the Routers option has been received.
  191. ASSERT_EQ(2, client.config_.routers_.size());
  192. EXPECT_EQ("10.0.0.200", client.config_.routers_[0].toText());
  193. EXPECT_EQ("10.0.0.201", client.config_.routers_[1].toText());
  194. // Make sure that the DNS Servers option has been received.
  195. ASSERT_EQ(2, client.config_.dns_servers_.size());
  196. EXPECT_EQ("10.0.0.202", client.config_.dns_servers_[0].toText());
  197. EXPECT_EQ("10.0.0.203", client.config_.dns_servers_[1].toText());
  198. // Make sure that the Quotes Servers option hasn't been received.
  199. ASSERT_TRUE(client.config_.quotes_servers_.empty());
  200. }
  201. // This test checks that the server drops DHCPINFORM message when the
  202. // source address and ciaddr is 0.
  203. TEST_F(InformTest, directClientBroadcastNoAddress) {
  204. Dhcp4Client client;
  205. // Configure DHCP server.
  206. configure(INFORM_CONFIGS[0], *client.getServer());
  207. // Request some configuration when DHCPINFORM is sent.
  208. client.requestOptions(DHO_LOG_SERVERS, DHO_COOKIE_SERVERS);
  209. // Send DHCPINFORM message to the server.
  210. ASSERT_NO_THROW(client.doInform());
  211. // Make sure that the server dropped the message.
  212. ASSERT_FALSE(client.getContext().response_);
  213. }
  214. // Test that client's DHCPINFORM message sent to a unicast address
  215. // is received and processed by the server and that the DHCPACK is
  216. // is sent.
  217. TEST_F(InformTest, directClientUnicast) {
  218. Dhcp4Client client;
  219. // Configure DHCP server.
  220. configure(INFORM_CONFIGS[0], *client.getServer());
  221. // Preconfigure the client with the IP address.
  222. client.createLease(IOAddress("10.0.0.56"), 600);
  223. // Set remote address to unicast.
  224. client.setDestAddress(IOAddress("10.0.0.1"));
  225. // Send DHCPINFORM message to the server.
  226. ASSERT_NO_THROW(client.doInform());
  227. // Make sure that the server responded.
  228. ASSERT_TRUE(client.getContext().response_);
  229. Pkt4Ptr resp = client.getContext().response_;
  230. // Make sure that the server has responded with DHCPACK.
  231. ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
  232. // Response should have been unicast to the ciaddr.
  233. EXPECT_EQ(IOAddress("10.0.0.56"), resp->getLocalAddr());
  234. // Response must not be relayed.
  235. EXPECT_FALSE(resp->isRelayed());
  236. // Make sure that the server id is present.
  237. EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
  238. // Make sure that the Routers option has been received.
  239. ASSERT_EQ(2, client.config_.routers_.size());
  240. EXPECT_EQ("10.0.0.200", client.config_.routers_[0].toText());
  241. EXPECT_EQ("10.0.0.201", client.config_.routers_[1].toText());
  242. // Make sure that the DNS Servers option has been received.
  243. ASSERT_EQ(2, client.config_.dns_servers_.size());
  244. EXPECT_EQ("10.0.0.202", client.config_.dns_servers_[0].toText());
  245. EXPECT_EQ("10.0.0.203", client.config_.dns_servers_[1].toText());
  246. }
  247. // This test checks that the server responds to the source address of the
  248. // packet received from the directly connected client if the client didn't
  249. // set the ciaddr.
  250. TEST_F(InformTest, directClientNoCiaddr) {
  251. Dhcp4Client client;
  252. // Configure DHCP server.
  253. configure(INFORM_CONFIGS[0], *client.getServer());
  254. // Preconfigure the client with the IP address.
  255. client.createLease(IOAddress("10.0.0.56"), 600);
  256. // Send DHCPINFORM message (with ciaddr not set) to the server.
  257. ASSERT_NO_THROW(client.doInform(false));
  258. // Make sure that the server responded.
  259. ASSERT_TRUE(client.getContext().response_);
  260. Pkt4Ptr resp = client.getContext().response_;
  261. // Make sure that the server has responded with DHCPACK.
  262. ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
  263. // Response should have been unicast to the ciaddr.
  264. EXPECT_EQ(IOAddress("10.0.0.56"), resp->getLocalAddr());
  265. // Response must not be relayed.
  266. EXPECT_FALSE(resp->isRelayed());
  267. // Make sure that the server id is present.
  268. EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
  269. // Make sure that the Routers option has been received.
  270. ASSERT_EQ(2, client.config_.routers_.size());
  271. EXPECT_EQ("10.0.0.200", client.config_.routers_[0].toText());
  272. EXPECT_EQ("10.0.0.201", client.config_.routers_[1].toText());
  273. // Make sure that the DNS Servers option has been received.
  274. ASSERT_EQ(2, client.config_.dns_servers_.size());
  275. EXPECT_EQ("10.0.0.202", client.config_.dns_servers_[0].toText());
  276. EXPECT_EQ("10.0.0.203", client.config_.dns_servers_[1].toText());
  277. }
  278. // This test checks that the server receiving DHCPINFORM via relay, unicasts the
  279. // DHCPACK to the client (ciaddr).
  280. TEST_F(InformTest, relayedClient) {
  281. Dhcp4Client client;
  282. // Configure DHCP server.
  283. configure(INFORM_CONFIGS[1], *client.getServer());
  284. // Message is relayed.
  285. client.useRelay();
  286. // Request some configuration when DHCPINFORM is sent.
  287. client.requestOptions(DHO_LOG_SERVERS, DHO_COOKIE_SERVERS);
  288. // Preconfigure the client with the IP address.
  289. client.createLease(IOAddress("192.0.2.56"), 600);
  290. // Send DHCPINFORM message to the server.
  291. ASSERT_NO_THROW(client.doInform());
  292. // Make sure that the server responded.
  293. ASSERT_TRUE(client.getContext().response_);
  294. Pkt4Ptr resp = client.getContext().response_;
  295. // Make sure that the server has responded with DHCPACK.
  296. ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
  297. // Response should have been unicast to the ciaddr.
  298. EXPECT_EQ(IOAddress("192.0.2.56"), resp->getLocalAddr());
  299. // Response is unicast to the client, so it must not be relayed.
  300. EXPECT_FALSE(resp->isRelayed());
  301. // Make sure that the server id is present.
  302. EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
  303. // Make sure that the Routers option has been received.
  304. ASSERT_EQ(2, client.config_.routers_.size());
  305. EXPECT_EQ("192.0.2.200", client.config_.routers_[0].toText());
  306. EXPECT_EQ("192.0.2.201", client.config_.routers_[1].toText());
  307. // Make sure that the DNS Servers option has been received.
  308. ASSERT_EQ(2, client.config_.dns_servers_.size());
  309. EXPECT_EQ("192.0.2.202", client.config_.dns_servers_[0].toText());
  310. EXPECT_EQ("192.0.2.203", client.config_.dns_servers_[1].toText());
  311. // Make sure that the Log Servers option has been received.
  312. ASSERT_EQ(2, client.config_.quotes_servers_.size());
  313. EXPECT_EQ("192.0.2.200", client.config_.routers_[0].toText());
  314. EXPECT_EQ("192.0.2.201", client.config_.routers_[1].toText());
  315. // Make sure that the Quotes Servers option has been received.
  316. ASSERT_EQ(2, client.config_.log_servers_.size());
  317. EXPECT_EQ("192.0.2.202", client.config_.dns_servers_[0].toText());
  318. EXPECT_EQ("192.0.2.203", client.config_.dns_servers_[1].toText());
  319. }
  320. // This test checks that the server can respond to the DHCPINFORM message
  321. // received via relay when the ciaddr is not set.
  322. TEST_F(InformTest, relayedClientNoCiaddr) {
  323. Dhcp4Client client;
  324. // Configure DHCP server.
  325. configure(INFORM_CONFIGS[1], *client.getServer());
  326. // Message is relayed.
  327. client.useRelay();
  328. // Send DHCPINFORM message to the server.
  329. ASSERT_NO_THROW(client.doInform());
  330. // Make sure that the server responded.
  331. ASSERT_TRUE(client.getContext().response_);
  332. Pkt4Ptr resp = client.getContext().response_;
  333. // Make sure that the server has responded with DHCPACK.
  334. ASSERT_EQ(DHCPACK, static_cast<int>(resp->getType()));
  335. // Response should go through a relay as there is no ciaddr.
  336. EXPECT_EQ(IOAddress("192.0.2.2"), resp->getLocalAddr());
  337. EXPECT_EQ(IOAddress("192.0.2.2"), resp->getGiaddr());
  338. EXPECT_EQ(1, resp->getHops());
  339. // In the case when the client didn't set the ciaddr and the message
  340. // was received via relay the server sets the Broadcast flag to help
  341. // the relay forwarding the message (without yiaddr) to the client.
  342. EXPECT_EQ(BOOTP_BROADCAST, resp->getFlags() & BOOTP_BROADCAST);
  343. // Make sure that the server id is present.
  344. EXPECT_EQ("10.0.0.1", client.config_.serverid_.toText());
  345. // Make sure that the Routers option has been received.
  346. ASSERT_EQ(2, client.config_.routers_.size());
  347. EXPECT_EQ("192.0.2.200", client.config_.routers_[0].toText());
  348. EXPECT_EQ("192.0.2.201", client.config_.routers_[1].toText());
  349. // Make sure that the DNS Servers option has been received.
  350. ASSERT_EQ(2, client.config_.dns_servers_.size());
  351. EXPECT_EQ("192.0.2.202", client.config_.dns_servers_[0].toText());
  352. EXPECT_EQ("192.0.2.203", client.config_.dns_servers_[1].toText());
  353. }
  354. } // end of anonymous namespace