dhcp4_srv.cc 84 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165
  1. // Copyright (C) 2011-2015 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 <dhcp/dhcp4.h>
  17. #include <dhcp/duid.h>
  18. #include <dhcp/hwaddr.h>
  19. #include <dhcp/iface_mgr.h>
  20. #include <dhcp/option4_addrlst.h>
  21. #include <dhcp/option_int.h>
  22. #include <dhcp/option_int_array.h>
  23. #include <dhcp/option_vendor.h>
  24. #include <dhcp/option_string.h>
  25. #include <dhcp/pkt4.h>
  26. #include <dhcp/docsis3_option_defs.h>
  27. #include <dhcp4/dhcp4_log.h>
  28. #include <dhcp4/dhcp4_srv.h>
  29. #include <dhcpsrv/addr_utilities.h>
  30. #include <dhcpsrv/callout_handle_store.h>
  31. #include <dhcpsrv/cfgmgr.h>
  32. #include <dhcpsrv/cfg_subnets4.h>
  33. #include <dhcpsrv/lease_mgr.h>
  34. #include <dhcpsrv/lease_mgr_factory.h>
  35. #include <dhcpsrv/subnet.h>
  36. #include <dhcpsrv/subnet_selector.h>
  37. #include <dhcpsrv/utils.h>
  38. #include <dhcpsrv/utils.h>
  39. #include <hooks/callout_handle.h>
  40. #include <hooks/hooks_manager.h>
  41. #include <util/strutil.h>
  42. #include <asio.hpp>
  43. #include <boost/bind.hpp>
  44. #include <boost/foreach.hpp>
  45. #include <boost/shared_ptr.hpp>
  46. #include <iomanip>
  47. using namespace isc;
  48. using namespace isc::asiolink;
  49. using namespace isc::dhcp;
  50. using namespace isc::dhcp_ddns;
  51. using namespace isc::hooks;
  52. using namespace isc::log;
  53. using namespace std;
  54. /// Structure that holds registered hook indexes
  55. struct Dhcp4Hooks {
  56. int hook_index_buffer4_receive_;///< index for "buffer4_receive" hook point
  57. int hook_index_pkt4_receive_; ///< index for "pkt4_receive" hook point
  58. int hook_index_subnet4_select_; ///< index for "subnet4_select" hook point
  59. int hook_index_lease4_release_; ///< index for "lease4_release" hook point
  60. int hook_index_pkt4_send_; ///< index for "pkt4_send" hook point
  61. int hook_index_buffer4_send_; ///< index for "buffer4_send" hook point
  62. /// Constructor that registers hook points for DHCPv4 engine
  63. Dhcp4Hooks() {
  64. hook_index_buffer4_receive_= HooksManager::registerHook("buffer4_receive");
  65. hook_index_pkt4_receive_ = HooksManager::registerHook("pkt4_receive");
  66. hook_index_subnet4_select_ = HooksManager::registerHook("subnet4_select");
  67. hook_index_pkt4_send_ = HooksManager::registerHook("pkt4_send");
  68. hook_index_lease4_release_ = HooksManager::registerHook("lease4_release");
  69. hook_index_buffer4_send_ = HooksManager::registerHook("buffer4_send");
  70. }
  71. };
  72. // Declare a Hooks object. As this is outside any function or method, it
  73. // will be instantiated (and the constructor run) when the module is loaded.
  74. // As a result, the hook indexes will be defined before any method in this
  75. // module is called.
  76. Dhcp4Hooks Hooks;
  77. namespace isc {
  78. namespace dhcp {
  79. Dhcpv4Exchange::Dhcpv4Exchange(const AllocEnginePtr& alloc_engine,
  80. const Pkt4Ptr& query,
  81. const Subnet4Ptr& subnet)
  82. : alloc_engine_(alloc_engine), query_(query), resp_(),
  83. context_(new AllocEngine::ClientContext4()) {
  84. if (!alloc_engine_) {
  85. isc_throw(BadValue, "alloc_engine value must not be NULL"
  86. " when creating an instance of the Dhcpv4Exchange");
  87. }
  88. if (!query_) {
  89. isc_throw(BadValue, "query value must not be NULL when"
  90. " creating an instance of the Dhcpv4Exchange");
  91. }
  92. // Create response message.
  93. initResponse();
  94. // Select subnet for the query message.
  95. context_->subnet_ = subnet;
  96. // Hardware address.
  97. context_->hwaddr_ = query->getHWAddr();
  98. // Set client identifier if the record-client-id flag is enabled (default).
  99. // If the subnet wasn't found it doesn't matter because we will not be
  100. // able to allocate a lease anyway so this context will not be used.
  101. if (subnet) {
  102. if (subnet->getRecordClientId()) {
  103. OptionPtr opt_clientid = query->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
  104. if (opt_clientid) {
  105. context_->clientid_.reset(new ClientId(opt_clientid->getData()));
  106. }
  107. } else {
  108. /// @todo When merging with #3806 use different logger.
  109. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, DHCP4_CLIENTID_IGNORED_FOR_LEASES)
  110. .arg(query->getLabel())
  111. .arg(subnet->getID());
  112. }
  113. }
  114. // Check for static reservations.
  115. alloc_engine->findReservation(*context_);
  116. };
  117. void
  118. Dhcpv4Exchange::initResponse() {
  119. uint8_t resp_type = 0;
  120. switch (getQuery()->getType()) {
  121. case DHCPDISCOVER:
  122. resp_type = DHCPOFFER;
  123. break;
  124. case DHCPREQUEST:
  125. case DHCPINFORM:
  126. resp_type = DHCPACK;
  127. break;
  128. default:
  129. ;
  130. }
  131. // Only create a response if one is required.
  132. if (resp_type > 0) {
  133. resp_.reset(new Pkt4(resp_type, getQuery()->getTransid()));
  134. copyDefaultFields();
  135. }
  136. }
  137. void
  138. Dhcpv4Exchange::copyDefaultFields() {
  139. resp_->setIface(query_->getIface());
  140. resp_->setIndex(query_->getIndex());
  141. // explicitly set this to 0
  142. resp_->setSiaddr(IOAddress::IPV4_ZERO_ADDRESS());
  143. // ciaddr is always 0, except for the Renew/Rebind state when it may
  144. // be set to the ciaddr sent by the client.
  145. resp_->setCiaddr(IOAddress::IPV4_ZERO_ADDRESS());
  146. resp_->setHops(query_->getHops());
  147. // copy MAC address
  148. resp_->setHWAddr(query_->getHWAddr());
  149. // relay address
  150. resp_->setGiaddr(query_->getGiaddr());
  151. // Let's copy client-id to response. See RFC6842.
  152. // It is possible to disable RFC6842 to keep backward compatibility
  153. bool echo = CfgMgr::instance().echoClientId();
  154. OptionPtr client_id = query_->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
  155. if (client_id && echo) {
  156. resp_->addOption(client_id);
  157. }
  158. // If src/dest HW addresses are used by the packet filtering class
  159. // we need to copy them as well. There is a need to check that the
  160. // address being set is not-NULL because an attempt to set the NULL
  161. // HW would result in exception. If these values are not set, the
  162. // the default HW addresses (zeroed) should be generated by the
  163. // packet filtering class when creating Ethernet header for
  164. // outgoing packet.
  165. HWAddrPtr src_hw_addr = query_->getLocalHWAddr();
  166. if (src_hw_addr) {
  167. resp_->setLocalHWAddr(src_hw_addr);
  168. }
  169. HWAddrPtr dst_hw_addr = query_->getRemoteHWAddr();
  170. if (dst_hw_addr) {
  171. resp_->setRemoteHWAddr(dst_hw_addr);
  172. }
  173. // If this packet is relayed, we want to copy Relay Agent Info option
  174. OptionPtr rai = query_->getOption(DHO_DHCP_AGENT_OPTIONS);
  175. if (rai) {
  176. resp_->addOption(rai);
  177. }
  178. }
  179. const std::string Dhcpv4Srv::VENDOR_CLASS_PREFIX("VENDOR_CLASS_");
  180. Dhcpv4Srv::Dhcpv4Srv(uint16_t port, const bool use_bcast,
  181. const bool direct_response_desired)
  182. : shutdown_(true), alloc_engine_(), port_(port),
  183. use_bcast_(use_bcast), hook_index_pkt4_receive_(-1),
  184. hook_index_subnet4_select_(-1), hook_index_pkt4_send_(-1) {
  185. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_START, DHCP4_OPEN_SOCKET).arg(port);
  186. try {
  187. // Port 0 is used for testing purposes where we don't open broadcast
  188. // capable sockets. So, set the packet filter handling direct traffic
  189. // only if we are in non-test mode.
  190. if (port) {
  191. // First call to instance() will create IfaceMgr (it's a singleton)
  192. // it may throw something if things go wrong.
  193. // The 'true' value of the call to setMatchingPacketFilter imposes
  194. // that IfaceMgr will try to use the mechanism to respond directly
  195. // to the client which doesn't have address assigned. This capability
  196. // may be lacking on some OSes, so there is no guarantee that server
  197. // will be able to respond directly.
  198. IfaceMgr::instance().setMatchingPacketFilter(direct_response_desired);
  199. }
  200. // Instantiate allocation engine
  201. alloc_engine_.reset(new AllocEngine(AllocEngine::ALLOC_ITERATIVE, 100,
  202. false /* false = IPv4 */));
  203. // Register hook points
  204. hook_index_pkt4_receive_ = Hooks.hook_index_pkt4_receive_;
  205. hook_index_subnet4_select_ = Hooks.hook_index_subnet4_select_;
  206. hook_index_pkt4_send_ = Hooks.hook_index_pkt4_send_;
  207. /// @todo call loadLibraries() when handling configuration changes
  208. } catch (const std::exception &e) {
  209. LOG_ERROR(dhcp4_logger, DHCP4_SRV_CONSTRUCT_ERROR).arg(e.what());
  210. shutdown_ = true;
  211. return;
  212. }
  213. shutdown_ = false;
  214. }
  215. Dhcpv4Srv::~Dhcpv4Srv() {
  216. IfaceMgr::instance().closeSockets();
  217. }
  218. void
  219. Dhcpv4Srv::shutdown() {
  220. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_SHUTDOWN_REQUEST);
  221. shutdown_ = true;
  222. }
  223. isc::dhcp::Subnet4Ptr
  224. Dhcpv4Srv::selectSubnet(const Pkt4Ptr& query) const {
  225. Subnet4Ptr subnet;
  226. SubnetSelector selector;
  227. selector.ciaddr_ = query->getCiaddr();
  228. selector.giaddr_ = query->getGiaddr();
  229. selector.local_address_ = query->getLocalAddr();
  230. selector.remote_address_ = query->getRemoteAddr();
  231. selector.client_classes_ = query->classes_;
  232. selector.iface_name_ = query->getIface();
  233. CfgMgr& cfgmgr = CfgMgr::instance();
  234. subnet = cfgmgr.getCurrentCfg()->getCfgSubnets4()->selectSubnet(selector);
  235. // Let's execute all callouts registered for subnet4_select
  236. if (HooksManager::calloutsPresent(hook_index_subnet4_select_)) {
  237. CalloutHandlePtr callout_handle = getCalloutHandle(query);
  238. // We're reusing callout_handle from previous calls
  239. callout_handle->deleteAllArguments();
  240. // Set new arguments
  241. callout_handle->setArgument("query4", query);
  242. callout_handle->setArgument("subnet4", subnet);
  243. callout_handle->setArgument("subnet4collection",
  244. cfgmgr.getCurrentCfg()->
  245. getCfgSubnets4()->getAll());
  246. // Call user (and server-side) callouts
  247. HooksManager::callCallouts(hook_index_subnet4_select_,
  248. *callout_handle);
  249. // Callouts decided to skip this step. This means that no subnet
  250. // will be selected. Packet processing will continue, but it will
  251. // be severely limited (i.e. only global options will be assigned)
  252. if (callout_handle->getSkip()) {
  253. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_HOOKS,
  254. DHCP4_HOOK_SUBNET4_SELECT_SKIP);
  255. return (Subnet4Ptr());
  256. }
  257. // Use whatever subnet was specified by the callout
  258. callout_handle->getArgument("subnet4", subnet);
  259. }
  260. return (subnet);
  261. }
  262. Pkt4Ptr
  263. Dhcpv4Srv::receivePacket(int timeout) {
  264. return (IfaceMgr::instance().receive4(timeout));
  265. }
  266. void
  267. Dhcpv4Srv::sendPacket(const Pkt4Ptr& packet) {
  268. IfaceMgr::instance().send(packet);
  269. }
  270. bool
  271. Dhcpv4Srv::run() {
  272. while (!shutdown_) {
  273. // client's message and server's response
  274. Pkt4Ptr query;
  275. Pkt4Ptr rsp;
  276. try {
  277. // The lease database backend may install some timers for which
  278. // the handlers need to be executed periodically. Retrieve the
  279. // maximum interval at which the handlers must be executed from
  280. // the lease manager.
  281. uint32_t timeout = LeaseMgrFactory::instance().getIOServiceExecInterval();
  282. // If the returned value is zero it means that there are no
  283. // timers installed, so use a default value.
  284. if (timeout == 0) {
  285. timeout = 1000;
  286. }
  287. query = receivePacket(timeout);
  288. } catch (const SignalInterruptOnSelect) {
  289. // Packet reception interrupted because a signal has been received.
  290. // This is not an error because we might have received a SIGTERM,
  291. // SIGINT or SIGHUP which are handled by the server. For signals
  292. // that are not handled by the server we rely on the default
  293. // behavior of the system, but there is nothing we should log here.
  294. } catch (const std::exception& e) {
  295. // Log all other errors.
  296. LOG_ERROR(dhcp4_logger, DHCP4_PACKET_RECEIVE_FAIL).arg(e.what());
  297. }
  298. // Handle next signal received by the process. It must be called after
  299. // an attempt to receive a packet to properly handle server shut down.
  300. // The SIGTERM or SIGINT will be received prior to, or during execution
  301. // of select() (select is invoked by receivePacket()). When that
  302. // happens, select will be interrupted. The signal handler will be
  303. // invoked immediately after select(). The handler will set the
  304. // shutdown flag and cause the process to terminate before the next
  305. // select() function is called. If the function was called before
  306. // receivePacket the process could wait up to the duration of timeout
  307. // of select() to terminate.
  308. handleSignal();
  309. // Execute ready timers for the lease database, e.g. Lease File Cleanup.
  310. try {
  311. LeaseMgrFactory::instance().getIOService()->poll();
  312. } catch (const std::exception& ex) {
  313. LOG_WARN(dhcp4_logger, DHCP4_LEASE_DATABASE_TIMERS_EXEC_FAIL)
  314. .arg(ex.what());
  315. }
  316. // Timeout may be reached or signal received, which breaks select()
  317. // with no reception occurred
  318. if (!query) {
  319. continue;
  320. }
  321. // In order to parse the DHCP options, the server needs to use some
  322. // configuration information such as: existing option spaces, option
  323. // definitions etc. This is the kind of information which is not
  324. // available in the libdhcp, so we need to supply our own implementation
  325. // of the option parsing function here, which would rely on the
  326. // configuration data.
  327. query->setCallback(boost::bind(&Dhcpv4Srv::unpackOptions, this,
  328. _1, _2, _3));
  329. bool skip_unpack = false;
  330. // The packet has just been received so contains the uninterpreted wire
  331. // data; execute callouts registered for buffer4_receive.
  332. if (HooksManager::calloutsPresent(Hooks.hook_index_buffer4_receive_)) {
  333. CalloutHandlePtr callout_handle = getCalloutHandle(query);
  334. // Delete previously set arguments
  335. callout_handle->deleteAllArguments();
  336. // Pass incoming packet as argument
  337. callout_handle->setArgument("query4", query);
  338. // Call callouts
  339. HooksManager::callCallouts(Hooks.hook_index_buffer4_receive_,
  340. *callout_handle);
  341. // Callouts decided to skip the next processing step. The next
  342. // processing step would to parse the packet, so skip at this
  343. // stage means that callouts did the parsing already, so server
  344. // should skip parsing.
  345. if (callout_handle->getSkip()) {
  346. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_HOOKS, DHCP4_HOOK_BUFFER_RCVD_SKIP);
  347. skip_unpack = true;
  348. }
  349. callout_handle->getArgument("query4", query);
  350. }
  351. // Unpack the packet information unless the buffer4_receive callouts
  352. // indicated they did it
  353. if (!skip_unpack) {
  354. try {
  355. query->unpack();
  356. } catch (const std::exception& e) {
  357. // Failed to parse the packet.
  358. LOG_DEBUG(bad_packet_logger, DBG_DHCP4_DETAIL,
  359. DHCP4_PACKET_DROP_0001)
  360. .arg(query->getLabel())
  361. .arg(e.what());
  362. continue;
  363. }
  364. }
  365. // Assign this packet to one or more classes if needed. We need to do
  366. // this before calling accept(), because getSubnet4() may need client
  367. // class information.
  368. classifyPacket(query);
  369. // Check whether the message should be further processed or discarded.
  370. // There is no need to log anything here. This function logs by itself.
  371. if (!accept(query)) {
  372. continue;
  373. }
  374. // We have sanity checked (in accept() that the Message Type option
  375. // exists, so we can safely get it here.
  376. int type = query->getType();
  377. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, DHCP4_PACKET_RECEIVED)
  378. .arg(serverReceivedPacketName(type))
  379. .arg(type)
  380. .arg(query->getIface());
  381. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_QUERY_DATA)
  382. .arg(type)
  383. .arg(query->toText());
  384. // Let's execute all callouts registered for pkt4_receive
  385. if (HooksManager::calloutsPresent(hook_index_pkt4_receive_)) {
  386. CalloutHandlePtr callout_handle = getCalloutHandle(query);
  387. // Delete previously set arguments
  388. callout_handle->deleteAllArguments();
  389. // Pass incoming packet as argument
  390. callout_handle->setArgument("query4", query);
  391. // Call callouts
  392. HooksManager::callCallouts(hook_index_pkt4_receive_,
  393. *callout_handle);
  394. // Callouts decided to skip the next processing step. The next
  395. // processing step would to process the packet, so skip at this
  396. // stage means drop.
  397. if (callout_handle->getSkip()) {
  398. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_HOOKS, DHCP4_HOOK_PACKET_RCVD_SKIP);
  399. continue;
  400. }
  401. callout_handle->getArgument("query4", query);
  402. }
  403. try {
  404. switch (query->getType()) {
  405. case DHCPDISCOVER:
  406. rsp = processDiscover(query);
  407. break;
  408. case DHCPREQUEST:
  409. // Note that REQUEST is used for many things in DHCPv4: for
  410. // requesting new leases, renewing existing ones and even
  411. // for rebinding.
  412. rsp = processRequest(query);
  413. break;
  414. case DHCPRELEASE:
  415. processRelease(query);
  416. break;
  417. case DHCPDECLINE:
  418. processDecline(query);
  419. break;
  420. case DHCPINFORM:
  421. rsp = processInform(query);
  422. break;
  423. default:
  424. // Only action is to output a message if debug is enabled,
  425. // and that is covered by the debug statement before the
  426. // "switch" statement.
  427. ;
  428. }
  429. } catch (const isc::Exception& e) {
  430. // Catch-all exception (at least for ones based on the isc Exception
  431. // class, which covers more or less all that are explicitly raised
  432. // in the Kea code). Just log the problem and ignore the packet.
  433. // (The problem is logged as a debug message because debug is
  434. // disabled by default - it prevents a DDOS attack based on the
  435. // sending of problem packets.)
  436. if (dhcp4_logger.isDebugEnabled(DBG_DHCP4_BASIC)) {
  437. std::string source = "unknown";
  438. HWAddrPtr hwptr = query->getHWAddr();
  439. if (hwptr) {
  440. source = hwptr->toText();
  441. }
  442. LOG_DEBUG(bad_packet_logger, DBG_DHCP4_BASIC,
  443. DHCP4_PACKET_DROP_0007)
  444. .arg(query->getLabel())
  445. .arg(e.what());
  446. }
  447. }
  448. if (!rsp) {
  449. continue;
  450. }
  451. // Specifies if server should do the packing
  452. bool skip_pack = false;
  453. // Execute all callouts registered for pkt4_send
  454. if (HooksManager::calloutsPresent(hook_index_pkt4_send_)) {
  455. CalloutHandlePtr callout_handle = getCalloutHandle(query);
  456. // Delete all previous arguments
  457. callout_handle->deleteAllArguments();
  458. // Clear skip flag if it was set in previous callouts
  459. callout_handle->setSkip(false);
  460. // Set our response
  461. callout_handle->setArgument("response4", rsp);
  462. // Call all installed callouts
  463. HooksManager::callCallouts(hook_index_pkt4_send_,
  464. *callout_handle);
  465. // Callouts decided to skip the next processing step. The next
  466. // processing step would to send the packet, so skip at this
  467. // stage means "drop response".
  468. if (callout_handle->getSkip()) {
  469. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_HOOKS, DHCP4_HOOK_PACKET_SEND_SKIP);
  470. skip_pack = true;
  471. }
  472. }
  473. if (!skip_pack) {
  474. try {
  475. rsp->pack();
  476. } catch (const std::exception& e) {
  477. LOG_ERROR(dhcp4_logger, DHCP4_PACKET_SEND_FAIL)
  478. .arg(e.what());
  479. }
  480. }
  481. try {
  482. // Now all fields and options are constructed into output wire buffer.
  483. // Option objects modification does not make sense anymore. Hooks
  484. // can only manipulate wire buffer at this stage.
  485. // Let's execute all callouts registered for buffer4_send
  486. if (HooksManager::calloutsPresent(Hooks.hook_index_buffer4_send_)) {
  487. CalloutHandlePtr callout_handle = getCalloutHandle(query);
  488. // Delete previously set arguments
  489. callout_handle->deleteAllArguments();
  490. // Pass incoming packet as argument
  491. callout_handle->setArgument("response4", rsp);
  492. // Call callouts
  493. HooksManager::callCallouts(Hooks.hook_index_buffer4_send_,
  494. *callout_handle);
  495. // Callouts decided to skip the next processing step. The next
  496. // processing step would to parse the packet, so skip at this
  497. // stage means drop.
  498. if (callout_handle->getSkip()) {
  499. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_HOOKS,
  500. DHCP4_HOOK_BUFFER_SEND_SKIP);
  501. continue;
  502. }
  503. callout_handle->getArgument("response4", rsp);
  504. }
  505. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL_DATA,
  506. DHCP4_RESPONSE_DATA)
  507. .arg(static_cast<int>(rsp->getType())).arg(rsp->toText());
  508. sendPacket(rsp);
  509. } catch (const std::exception& e) {
  510. LOG_ERROR(dhcp4_logger, DHCP4_PACKET_SEND_FAIL)
  511. .arg(e.what());
  512. }
  513. }
  514. return (true);
  515. }
  516. string
  517. Dhcpv4Srv::srvidToString(const OptionPtr& srvid) {
  518. if (!srvid) {
  519. isc_throw(BadValue, "NULL pointer passed to srvidToString()");
  520. }
  521. boost::shared_ptr<Option4AddrLst> generated =
  522. boost::dynamic_pointer_cast<Option4AddrLst>(srvid);
  523. if (!srvid) {
  524. isc_throw(BadValue, "Pointer to invalid option passed to srvidToString()");
  525. }
  526. Option4AddrLst::AddressContainer addrs = generated->getAddresses();
  527. if (addrs.size() != 1) {
  528. isc_throw(BadValue, "Malformed option passed to srvidToString(). "
  529. << "Expected to contain a single IPv4 address.");
  530. }
  531. return (addrs[0].toText());
  532. }
  533. isc::dhcp_ddns::D2Dhcid
  534. Dhcpv4Srv::computeDhcid(const Lease4Ptr& lease) {
  535. if (!lease) {
  536. isc_throw(DhcidComputeError, "a pointer to the lease must be not"
  537. " NULL to compute DHCID");
  538. } else if (lease->hostname_.empty()) {
  539. isc_throw(DhcidComputeError, "unable to compute the DHCID for the"
  540. " lease which has empty hostname set");
  541. }
  542. // In order to compute DHCID the client's hostname must be encoded in
  543. // canonical wire format. It is unlikely that the FQDN is malformed
  544. // because it is validated by the classes which encapsulate options
  545. // carrying client FQDN. However, if the client name was carried in the
  546. // Hostname option it is more likely as it carries the hostname as a
  547. // regular string.
  548. std::vector<uint8_t> fqdn_wire;
  549. try {
  550. OptionDataTypeUtil::writeFqdn(lease->hostname_, fqdn_wire, true);
  551. } catch (const Exception& ex) {
  552. isc_throw(DhcidComputeError, "unable to compute DHCID because the"
  553. " hostname: " << lease->hostname_ << " is invalid");
  554. }
  555. // Prefer client id to HW address to compute DHCID. If Client Id is
  556. // NULL, use HW address.
  557. try {
  558. if (lease->client_id_) {
  559. return (D2Dhcid(lease->client_id_->getClientId(), fqdn_wire));
  560. } else {
  561. return (D2Dhcid(lease->hwaddr_, fqdn_wire));
  562. }
  563. } catch (const Exception& ex) {
  564. isc_throw(DhcidComputeError, "unable to compute DHCID: "
  565. << ex.what());
  566. }
  567. }
  568. void
  569. Dhcpv4Srv::appendServerID(Dhcpv4Exchange& ex) {
  570. // The source address for the outbound message should have been set already.
  571. // This is the address that to the best of the server's knowledge will be
  572. // available from the client.
  573. /// @todo: perhaps we should consider some more sophisticated server id
  574. /// generation, but for the current use cases, it should be ok.
  575. OptionPtr opt_srvid(new Option4AddrLst(DHO_DHCP_SERVER_IDENTIFIER,
  576. ex.getResponse()->getLocalAddr()));
  577. ex.getResponse()->addOption(opt_srvid);
  578. }
  579. void
  580. Dhcpv4Srv::appendRequestedOptions(Dhcpv4Exchange& ex) {
  581. // Get the subnet relevant for the client. We will need it
  582. // to get the options associated with it.
  583. Subnet4Ptr subnet = ex.getContext()->subnet_;
  584. // If we can't find the subnet for the client there is no way
  585. // to get the options to be sent to a client. We don't log an
  586. // error because it will be logged by the assignLease method
  587. // anyway.
  588. if (!subnet) {
  589. return;
  590. }
  591. Pkt4Ptr query = ex.getQuery();
  592. // try to get the 'Parameter Request List' option which holds the
  593. // codes of requested options.
  594. OptionUint8ArrayPtr option_prl = boost::dynamic_pointer_cast<
  595. OptionUint8Array>(query->getOption(DHO_DHCP_PARAMETER_REQUEST_LIST));
  596. // If there is no PRL option in the message from the client then
  597. // there is nothing to do.
  598. if (!option_prl) {
  599. return;
  600. }
  601. Pkt4Ptr resp = ex.getResponse();
  602. // Get the codes of requested options.
  603. const std::vector<uint8_t>& requested_opts = option_prl->getValues();
  604. // For each requested option code get the instance of the option
  605. // to be returned to the client.
  606. for (std::vector<uint8_t>::const_iterator opt = requested_opts.begin();
  607. opt != requested_opts.end(); ++opt) {
  608. if (!resp->getOption(*opt)) {
  609. OptionDescriptor desc = subnet->getCfgOption()->get("dhcp4", *opt);
  610. if (desc.option_) {
  611. resp->addOption(desc.option_);
  612. }
  613. }
  614. }
  615. }
  616. void
  617. Dhcpv4Srv::appendRequestedVendorOptions(Dhcpv4Exchange& ex) {
  618. // Get the configured subnet suitable for the incoming packet.
  619. Subnet4Ptr subnet = ex.getContext()->subnet_;
  620. // Leave if there is no subnet matching the incoming packet.
  621. // There is no need to log the error message here because
  622. // it will be logged in the assignLease() when it fails to
  623. // pick the suitable subnet. We don't want to duplicate
  624. // error messages in such case.
  625. if (!subnet) {
  626. return;
  627. }
  628. // Try to get the vendor option
  629. boost::shared_ptr<OptionVendor> vendor_req = boost::dynamic_pointer_cast<
  630. OptionVendor>(ex.getQuery()->getOption(DHO_VIVSO_SUBOPTIONS));
  631. if (!vendor_req) {
  632. return;
  633. }
  634. uint32_t vendor_id = vendor_req->getVendorId();
  635. // Let's try to get ORO within that vendor-option
  636. /// @todo This is very specific to vendor-id=4491 (Cable Labs). Other
  637. /// vendors may have different policies.
  638. OptionUint8ArrayPtr oro =
  639. boost::dynamic_pointer_cast<OptionUint8Array>(vendor_req->getOption(DOCSIS3_V4_ORO));
  640. // Option ORO not found. Don't do anything then.
  641. if (!oro) {
  642. return;
  643. }
  644. boost::shared_ptr<OptionVendor> vendor_rsp(new OptionVendor(Option::V4, vendor_id));
  645. // Get the list of options that client requested.
  646. bool added = false;
  647. const std::vector<uint8_t>& requested_opts = oro->getValues();
  648. for (std::vector<uint8_t>::const_iterator code = requested_opts.begin();
  649. code != requested_opts.end(); ++code) {
  650. if (!vendor_rsp->getOption(*code)) {
  651. OptionDescriptor desc = subnet->getCfgOption()->get(vendor_id,
  652. *code);
  653. if (desc.option_) {
  654. vendor_rsp->addOption(desc.option_);
  655. added = true;
  656. }
  657. }
  658. if (added) {
  659. ex.getResponse()->addOption(vendor_rsp);
  660. }
  661. }
  662. }
  663. void
  664. Dhcpv4Srv::appendBasicOptions(Dhcpv4Exchange& ex) {
  665. // Identify options that we always want to send to the
  666. // client (if they are configured).
  667. static const uint16_t required_options[] = {
  668. DHO_ROUTERS,
  669. DHO_DOMAIN_NAME_SERVERS,
  670. DHO_DOMAIN_NAME };
  671. static size_t required_options_size =
  672. sizeof(required_options) / sizeof(required_options[0]);
  673. // Get the subnet.
  674. Subnet4Ptr subnet = ex.getContext()->subnet_;
  675. if (!subnet) {
  676. return;
  677. }
  678. Pkt4Ptr resp = ex.getResponse();
  679. // Try to find all 'required' options in the outgoing
  680. // message. Those that are not present will be added.
  681. for (int i = 0; i < required_options_size; ++i) {
  682. OptionPtr opt = resp->getOption(required_options[i]);
  683. if (!opt) {
  684. // Check whether option has been configured.
  685. OptionDescriptor desc = subnet->getCfgOption()->
  686. get("dhcp4", required_options[i]);
  687. if (desc.option_) {
  688. resp->addOption(desc.option_);
  689. }
  690. }
  691. }
  692. }
  693. void
  694. Dhcpv4Srv::processClientName(Dhcpv4Exchange& ex) {
  695. // It is possible that client has sent both Client FQDN and Hostname
  696. // option. In such case, server should prefer Client FQDN option and
  697. // ignore the Hostname option.
  698. try {
  699. Pkt4Ptr resp = ex.getResponse();
  700. Option4ClientFqdnPtr fqdn = boost::dynamic_pointer_cast<Option4ClientFqdn>
  701. (ex.getQuery()->getOption(DHO_FQDN));
  702. if (fqdn) {
  703. processClientFqdnOption(ex);
  704. } else {
  705. OptionStringPtr hostname = boost::dynamic_pointer_cast<OptionString>
  706. (ex.getQuery()->getOption(DHO_HOST_NAME));
  707. if (hostname) {
  708. processHostnameOption(ex);
  709. }
  710. }
  711. } catch (const Exception& ex) {
  712. // In some rare cases it is possible that the client's name processing
  713. // fails. For example, the Hostname option may be malformed, or there
  714. // may be an error in the server's logic which would cause multiple
  715. // attempts to add the same option to the response message. This
  716. // error message aggregates all these errors so they can be diagnosed
  717. // from the log. We don't want to throw an exception here because,
  718. // it will impact the processing of the whole packet. We rather want
  719. // the processing to continue, even if the client's name is wrong.
  720. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_CLIENT_NAME_PROC_FAIL)
  721. .arg(ex.what());
  722. }
  723. }
  724. void
  725. Dhcpv4Srv::processClientFqdnOption(Dhcpv4Exchange& ex) {
  726. // Obtain the FQDN option from the client's message.
  727. Option4ClientFqdnPtr fqdn = boost::dynamic_pointer_cast<
  728. Option4ClientFqdn>(ex.getQuery()->getOption(DHO_FQDN));
  729. // Create the DHCPv4 Client FQDN Option to be included in the server's
  730. // response to a client.
  731. Option4ClientFqdnPtr fqdn_resp(new Option4ClientFqdn(*fqdn));
  732. // Set the server S, N, and O flags based on client's flags and
  733. // current configuration.
  734. D2ClientMgr& d2_mgr = CfgMgr::instance().getD2ClientMgr();
  735. d2_mgr.adjustFqdnFlags<Option4ClientFqdn>(*fqdn, *fqdn_resp);
  736. // Carry over the client's E flag.
  737. fqdn_resp->setFlag(Option4ClientFqdn::FLAG_E,
  738. fqdn->getFlag(Option4ClientFqdn::FLAG_E));
  739. if (ex.getContext()->host_ && !ex.getContext()->host_->getHostname().empty()) {
  740. D2ClientMgr& d2_mgr = CfgMgr::instance().getD2ClientMgr();
  741. fqdn_resp->setDomainName(d2_mgr.qualifyName(ex.getContext()->host_->getHostname(),
  742. true), Option4ClientFqdn::FULL);
  743. } else {
  744. // Adjust the domain name based on domain name value and type sent by the
  745. // client and current configuration.
  746. d2_mgr.adjustDomainName<Option4ClientFqdn>(*fqdn, *fqdn_resp);
  747. }
  748. // Add FQDN option to the response message. Note that, there may be some
  749. // cases when server may choose not to include the FQDN option in a
  750. // response to a client. In such cases, the FQDN should be removed from the
  751. // outgoing message. In theory we could cease to include the FQDN option
  752. // in this function until it is confirmed that it should be included.
  753. // However, we include it here for simplicity. Functions used to acquire
  754. // lease for a client will scan the response message for FQDN and if it
  755. // is found they will take necessary actions to store the FQDN information
  756. // in the lease database as well as to generate NameChangeRequests to DNS.
  757. // If we don't store the option in the response message, we will have to
  758. // propagate it in the different way to the functions which acquire the
  759. // lease. This would require modifications to the API of this class.
  760. ex.getResponse()->addOption(fqdn_resp);
  761. }
  762. void
  763. Dhcpv4Srv::processHostnameOption(Dhcpv4Exchange& ex) {
  764. // Obtain the Hostname option from the client's message.
  765. OptionStringPtr opt_hostname = boost::dynamic_pointer_cast<OptionString>
  766. (ex.getQuery()->getOption(DHO_HOST_NAME));
  767. // Fetch D2 configuration.
  768. D2ClientMgr& d2_mgr = CfgMgr::instance().getD2ClientMgr();
  769. // Do nothing if the DNS updates are disabled.
  770. if (!d2_mgr.ddnsEnabled()) {
  771. return;
  772. }
  773. std::string hostname = isc::util::str::trim(opt_hostname->getValue());
  774. unsigned int label_count = OptionDataTypeUtil::getLabelCount(hostname);
  775. // The hostname option sent by the client should be at least 1 octet long.
  776. // If it isn't we ignore this option. (Per RFC 2131, section 3.14)
  777. /// @todo It would be more liberal to accept this and let it fall into
  778. /// the case of replace or less than two below.
  779. if (label_count == 0) {
  780. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_EMPTY_HOSTNAME);
  781. return;
  782. }
  783. // Copy construct the hostname provided by the client. It is entirely
  784. // possible that we will use the hostname option provided by the client
  785. // to perform the DNS update and we will send the same option to him to
  786. // indicate that we accepted this hostname.
  787. OptionStringPtr opt_hostname_resp(new OptionString(*opt_hostname));
  788. // The hostname option may be unqualified or fully qualified. The lab_count
  789. // holds the number of labels for the name. The number of 1 means that
  790. // there is only root label "." (even for unqualified names, as the
  791. // getLabelCount function treats each name as a fully qualified one).
  792. // By checking the number of labels present in the hostname we may infer
  793. // whether client has sent the fully qualified or unqualified hostname.
  794. // If there is a hostname reservation for this client, use it.
  795. if (ex.getContext()->host_ && !ex.getContext()->host_->getHostname().empty()) {
  796. opt_hostname_resp->setValue(d2_mgr.qualifyName(ex.getContext()->host_->getHostname(),
  797. false));
  798. } else if ((d2_mgr.getD2ClientConfig()->getReplaceClientName()) ||
  799. (label_count < 2)) {
  800. // Set to root domain to signal later on that we should replace it.
  801. // DHO_HOST_NAME is a string option which cannot be empty.
  802. /// @todo We may want to reconsider whether it is appropriate for the
  803. /// client to send a root domain name as a Hostname. There are
  804. /// also extensions to the auto generation of the client's name,
  805. /// e.g. conversion to the puny code which may be considered at some point.
  806. /// For now, we just remain liberal and expect that the DNS will handle
  807. /// conversion if needed and possible.
  808. opt_hostname_resp->setValue(".");
  809. } else if (label_count == 2) {
  810. // If there are two labels, it means that the client has specified
  811. // the unqualified name. We have to concatenate the unqualified name
  812. // with the domain name. The false value passed as a second argument
  813. // indicates that the trailing dot should not be appended to the
  814. // hostname. We don't want to append the trailing dot because
  815. // we don't know whether the hostname is partial or not and some
  816. // clients do not handle the hostnames with the trailing dot.
  817. opt_hostname_resp->setValue(d2_mgr.qualifyName(hostname, false));
  818. }
  819. ex.getResponse()->addOption(opt_hostname_resp);
  820. }
  821. void
  822. Dhcpv4Srv::createNameChangeRequests(const Lease4Ptr& lease,
  823. const Lease4Ptr& old_lease) {
  824. if (!lease) {
  825. isc_throw(isc::Unexpected,
  826. "NULL lease specified when creating NameChangeRequest");
  827. }
  828. // If old lease is not NULL, it is an indication that the lease has
  829. // just been renewed. In such case we may need to generate the
  830. // additional NameChangeRequest to remove an existing entry before
  831. // we create a NameChangeRequest to add the entry for an updated lease.
  832. // We may also decide not to generate any requests at all. This is when
  833. // we discover that nothing has changed in the client's FQDN data.
  834. if (old_lease) {
  835. // There will be a NameChangeRequest generated to remove existing
  836. // DNS entries if the following conditions are met:
  837. // - The hostname is set for the existing lease, we can't generate
  838. // removal request for non-existent hostname.
  839. // - A server has performed reverse, forward or both updates.
  840. // - FQDN data between the new and old lease do not match.
  841. if (!lease->hasIdenticalFqdn(*old_lease)) {
  842. queueNameChangeRequest(isc::dhcp_ddns::CHG_REMOVE, old_lease);
  843. // If FQDN data from both leases match, there is no need to update.
  844. } else if (lease->hasIdenticalFqdn(*old_lease)) {
  845. return;
  846. }
  847. }
  848. // We may need to generate the NameChangeRequest for the new lease. It
  849. // will be generated only if hostname is set and if forward or reverse
  850. // update has been requested.
  851. queueNameChangeRequest(isc::dhcp_ddns::CHG_ADD, lease);
  852. }
  853. void
  854. Dhcpv4Srv::
  855. queueNameChangeRequest(const isc::dhcp_ddns::NameChangeType chg_type,
  856. const Lease4Ptr& lease) {
  857. // The hostname must not be empty, and at least one type of update
  858. // should be requested.
  859. if (!lease || lease->hostname_.empty() ||
  860. (!lease->fqdn_rev_ && !lease->fqdn_fwd_)) {
  861. return;
  862. }
  863. // Create the DHCID for the NameChangeRequest.
  864. D2Dhcid dhcid;
  865. try {
  866. dhcid = computeDhcid(lease);
  867. } catch (const DhcidComputeError& ex) {
  868. LOG_ERROR(dhcp4_logger, DHCP4_DHCID_COMPUTE_ERROR)
  869. .arg(lease->toText())
  870. .arg(ex.what());
  871. return;
  872. }
  873. // Create NameChangeRequest
  874. NameChangeRequestPtr ncr(new NameChangeRequest(chg_type, lease->fqdn_fwd_,
  875. lease->fqdn_rev_,
  876. lease->hostname_,
  877. lease->addr_.toText(),
  878. dhcid,
  879. (lease->cltt_ +
  880. lease->valid_lft_),
  881. lease->valid_lft_));
  882. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_QUEUE_NCR)
  883. .arg(chg_type == CHG_ADD ? "add" : "remove")
  884. .arg(ncr->toText());
  885. // And pass it to the the manager.
  886. CfgMgr::instance().getD2ClientMgr().sendRequest(ncr);
  887. }
  888. void
  889. Dhcpv4Srv::assignLease(Dhcpv4Exchange& ex) {
  890. // Get the pointers to the query and the response messages.
  891. Pkt4Ptr query = ex.getQuery();
  892. Pkt4Ptr resp = ex.getResponse();
  893. // Get the context.
  894. AllocEngine::ClientContext4Ptr ctx = ex.getContext();
  895. // Subnet should have been already selected when the context was created.
  896. Subnet4Ptr subnet = ctx->subnet_;
  897. if (!subnet) {
  898. // This particular client is out of luck today. We do not have
  899. // information about the subnet he is connected to. This likely means
  900. // misconfiguration of the server (or some relays). We will continue to
  901. // process this message, but our response will be almost useless: no
  902. // addresses or prefixes, no subnet specific configuration etc. The only
  903. // thing this client can get is some global information (like DNS
  904. // servers).
  905. // perhaps this should be logged on some higher level? This is most
  906. // likely configuration bug.
  907. LOG_ERROR(bad_packet_logger, DHCP4_PACKET_NAK_0001)
  908. .arg(query->getLabel())
  909. .arg(query->getRemoteAddr().toText())
  910. .arg(serverReceivedPacketName(query->getType()));
  911. resp->setType(DHCPNAK);
  912. resp->setYiaddr(IOAddress::IPV4_ZERO_ADDRESS());
  913. return;
  914. }
  915. // Set up siaddr. Perhaps assignLease is not the best place to call this
  916. // as siaddr has nothing to do with a lease, but otherwise we would have
  917. // to select subnet twice (performance hit) or update too many functions
  918. // at once.
  919. /// @todo: move subnet selection to a common code
  920. resp->setSiaddr(subnet->getSiaddr());
  921. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL_DATA, DHCP4_SUBNET_SELECTED)
  922. .arg(subnet->toText());
  923. // Get the server identifier. It will be used to determine the state
  924. // of the client.
  925. OptionCustomPtr opt_serverid = boost::dynamic_pointer_cast<
  926. OptionCustom>(query->getOption(DHO_DHCP_SERVER_IDENTIFIER));
  927. // Check if the client has sent a requested IP address option or
  928. // ciaddr.
  929. OptionCustomPtr opt_requested_address = boost::dynamic_pointer_cast<
  930. OptionCustom>(query->getOption(DHO_DHCP_REQUESTED_ADDRESS));
  931. IOAddress hint(0);
  932. if (opt_requested_address) {
  933. hint = opt_requested_address->readAddress();
  934. } else if (!query->getCiaddr().isV4Zero()) {
  935. hint = query->getCiaddr();
  936. }
  937. HWAddrPtr hwaddr = query->getHWAddr();
  938. // "Fake" allocation is processing of DISCOVER message. We pretend to do an
  939. // allocation, but we do not put the lease in the database. That is ok,
  940. // because we do not guarantee that the user will get that exact lease. If
  941. // the user selects this server to do actual allocation (i.e. sends REQUEST)
  942. // it should include this hint. That will help us during the actual lease
  943. // allocation.
  944. bool fake_allocation = (query->getType() == DHCPDISCOVER);
  945. // Get client-id. It is not mandatory in DHCPv4.
  946. ClientIdPtr client_id = ex.getContext()->clientid_;
  947. // If there is no server id and there is a Requested IP Address option
  948. // the client is in the INIT-REBOOT state in which the server has to
  949. // determine whether the client's notion of the address is correct
  950. // and whether the client is known, i.e., has a lease.
  951. if (!fake_allocation && !opt_serverid && opt_requested_address) {
  952. Lease4Ptr lease;
  953. if (client_id) {
  954. lease = LeaseMgrFactory::instance().getLease4(*client_id, subnet->getID());
  955. }
  956. if (!lease && hwaddr) {
  957. lease = LeaseMgrFactory::instance().getLease4(*hwaddr, subnet->getID());
  958. }
  959. // Check the first error case: unknown client. We check this before
  960. // validating the address sent because we don't want to respond if
  961. // we don't know this client.
  962. /// @todo The client_id logged here should be the client_id from the message
  963. /// rather than effective client id which is null when the
  964. /// record-client-id is set to false. This is addressed by the #3806
  965. /// which is under review.
  966. if (!lease || !lease->belongsToClient(hwaddr, client_id)) {
  967. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL,
  968. DHCP4_NO_LEASE_INIT_REBOOT)
  969. .arg(hint.toText())
  970. .arg(client_id ? client_id->toText():"(no client-id)")
  971. .arg(hwaddr ? hwaddr->toText():"(no hwaddr info)");
  972. ex.deleteResponse();
  973. return;
  974. }
  975. // We know this client so we can now check if his notion of the
  976. // IP address is correct.
  977. if (lease && (lease->addr_ != hint)) {
  978. LOG_DEBUG(bad_packet_logger, DBG_DHCP4_DETAIL,
  979. DHCP4_PACKET_NAK_0002)
  980. .arg(query->getLabel())
  981. .arg(hint.toText());
  982. resp->setType(DHCPNAK);
  983. resp->setYiaddr(IOAddress::IPV4_ZERO_ADDRESS());
  984. return;
  985. }
  986. }
  987. CalloutHandlePtr callout_handle = getCalloutHandle(query);
  988. std::string hostname;
  989. bool fqdn_fwd = false;
  990. bool fqdn_rev = false;
  991. OptionStringPtr opt_hostname;
  992. Option4ClientFqdnPtr fqdn = boost::dynamic_pointer_cast<
  993. Option4ClientFqdn>(resp->getOption(DHO_FQDN));
  994. if (fqdn) {
  995. hostname = fqdn->getDomainName();
  996. CfgMgr::instance().getD2ClientMgr().getUpdateDirections(*fqdn,
  997. fqdn_fwd,
  998. fqdn_rev);
  999. } else {
  1000. opt_hostname = boost::dynamic_pointer_cast<OptionString>
  1001. (resp->getOption(DHO_HOST_NAME));
  1002. if (opt_hostname) {
  1003. hostname = opt_hostname->getValue();
  1004. // DHO_HOST_NAME is string option which cannot be blank,
  1005. // we use "." to know we should replace it with a fully
  1006. // generated name. The local string variable needs to be
  1007. // blank in logic below.
  1008. if (hostname == ".") {
  1009. hostname = "";
  1010. }
  1011. /// @todo It could be configurable what sort of updates the
  1012. /// server is doing when Hostname option was sent.
  1013. fqdn_fwd = true;
  1014. fqdn_rev = true;
  1015. }
  1016. }
  1017. // We need to set these values in the context as they haven't been set yet.
  1018. ctx->requested_address_ = hint;
  1019. ctx->fwd_dns_update_ = fqdn_fwd;
  1020. ctx->rev_dns_update_ = fqdn_rev;
  1021. ctx->hostname_ = hostname;
  1022. ctx->fake_allocation_ = fake_allocation;
  1023. ctx->callout_handle_ = callout_handle;
  1024. Lease4Ptr lease = alloc_engine_->allocateLease4(*ctx);
  1025. if (lease) {
  1026. // We have a lease! Let's set it in the packet and send it back to
  1027. // the client.
  1028. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, fake_allocation?
  1029. DHCP4_LEASE_ADVERT:DHCP4_LEASE_ALLOC)
  1030. .arg(lease->addr_.toText())
  1031. .arg(client_id?client_id->toText():"(no client-id)")
  1032. .arg(hwaddr?hwaddr->toText():"(no hwaddr info)");
  1033. resp->setYiaddr(lease->addr_);
  1034. /// @todo The server should check what ciaddr the client has supplied
  1035. /// in ciaddr. Currently the ciaddr is ignored except for the subnet
  1036. /// selection. If the client supplied an invalid address, the server
  1037. /// will also return an invalid address here.
  1038. if (!fake_allocation) {
  1039. // If this is a renewing client it will set a ciaddr which the
  1040. // server may include in the response. If this is a new allocation
  1041. // the client will set ciaddr to 0 and this will also be propagated
  1042. // to the server's resp.
  1043. resp->setCiaddr(query->getCiaddr());
  1044. }
  1045. // If there has been Client FQDN or Hostname option sent, but the
  1046. // hostname is empty, it means that server is responsible for
  1047. // generating the entire hostname for the client. The example of the
  1048. // client's name, generated from the IP address is: host-192-0-2-3.
  1049. if ((fqdn || opt_hostname) && lease->hostname_.empty()) {
  1050. // Note that if we have received the hostname option, rather than
  1051. // Client FQDN the trailing dot is not appended to the generated
  1052. // hostname because some clients don't handle the trailing dot in
  1053. // the hostname. Whether the trailing dot is appended or not is
  1054. // controlled by the second argument to the generateFqdn().
  1055. lease->hostname_ = CfgMgr::instance().getD2ClientMgr()
  1056. .generateFqdn(lease->addr_, static_cast<bool>(fqdn));
  1057. // The operations below are rather safe, but we want to catch
  1058. // any potential exceptions (e.g. invalid lease database backend
  1059. // implementation) and log an error.
  1060. try {
  1061. // The lease update should be safe, because the lease should
  1062. // be already in the database. In most cases the exception
  1063. // would be thrown if the lease was missing.
  1064. LeaseMgrFactory::instance().updateLease4(lease);
  1065. // The name update in the option should be also safe,
  1066. // because the generated name is well formed.
  1067. if (fqdn) {
  1068. fqdn->setDomainName(lease->hostname_,
  1069. Option4ClientFqdn::FULL);
  1070. } else if (opt_hostname) {
  1071. opt_hostname->setValue(lease->hostname_);
  1072. }
  1073. } catch (const Exception& ex) {
  1074. LOG_ERROR(dhcp4_logger, DHCP4_NAME_GEN_UPDATE_FAIL)
  1075. .arg(ex.what());
  1076. }
  1077. }
  1078. // IP Address Lease time (type 51)
  1079. OptionPtr opt(new OptionUint32(Option::V4, DHO_DHCP_LEASE_TIME,
  1080. lease->valid_lft_));
  1081. resp->addOption(opt);
  1082. // Subnet mask (type 1)
  1083. resp->addOption(getNetmaskOption(subnet));
  1084. // renewal-timer (type 58)
  1085. if (!subnet->getT1().unspecified()) {
  1086. OptionUint32Ptr t1(new OptionUint32(Option::V4,
  1087. DHO_DHCP_RENEWAL_TIME,
  1088. subnet->getT1()));
  1089. resp->addOption(t1);
  1090. }
  1091. // rebind timer (type 59)
  1092. if (!subnet->getT2().unspecified()) {
  1093. OptionUint32Ptr t2(new OptionUint32(Option::V4,
  1094. DHO_DHCP_REBINDING_TIME,
  1095. subnet->getT2()));
  1096. resp->addOption(t2);
  1097. }
  1098. // Create NameChangeRequests if DDNS is enabled and this is a
  1099. // real allocation.
  1100. if (!fake_allocation && CfgMgr::instance().ddnsEnabled()) {
  1101. try {
  1102. createNameChangeRequests(lease, ctx->old_lease_);
  1103. } catch (const Exception& ex) {
  1104. LOG_ERROR(dhcp4_logger, DHCP4_NCR_CREATION_FAILED)
  1105. .arg(ex.what());
  1106. }
  1107. }
  1108. } else {
  1109. // Allocation engine did not allocate a lease. The engine logged
  1110. // cause of that failure. The only thing left is to insert
  1111. // status code to pass the sad news to the client.
  1112. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, fake_allocation ?
  1113. DHCP4_PACKET_NAK_0003 : DHCP4_PACKET_NAK_0004)
  1114. .arg(query->getLabel())
  1115. .arg(query->getCiaddr().toText())
  1116. .arg(opt_requested_address ?
  1117. opt_requested_address->readAddress().toText() : "(no address)");
  1118. resp->setType(DHCPNAK);
  1119. resp->setYiaddr(IOAddress::IPV4_ZERO_ADDRESS());
  1120. resp->delOption(DHO_FQDN);
  1121. resp->delOption(DHO_HOST_NAME);
  1122. }
  1123. }
  1124. void
  1125. Dhcpv4Srv::adjustIfaceData(Dhcpv4Exchange& ex) {
  1126. adjustRemoteAddr(ex);
  1127. // Initialize the pointers to the client's message and the server's
  1128. // response.
  1129. Pkt4Ptr query = ex.getQuery();
  1130. Pkt4Ptr response = ex.getResponse();
  1131. // For the non-relayed message, the destination port is the client's port.
  1132. // For the relayed message, the server/relay port is a destination.
  1133. // Note that the call to this function may throw if invalid combination
  1134. // of hops and giaddr is found (hops = 0 if giaddr = 0 and hops != 0 if
  1135. // giaddr != 0). The exception will propagate down and eventually cause the
  1136. // packet to be discarded.
  1137. response->setRemotePort(query->isRelayed() ? DHCP4_SERVER_PORT :
  1138. DHCP4_CLIENT_PORT);
  1139. IOAddress local_addr = query->getLocalAddr();
  1140. // In many cases the query is sent to a broadcast address. This address
  1141. // apears as a local address in the query message. We can't simply copy
  1142. // this address to a response message and use it as a source address.
  1143. // Instead we will need to use the address assigned to the interface
  1144. // on which the query has been received. In other cases, we will just
  1145. // use this address as a source address for the response.
  1146. if (local_addr == IOAddress::IPV4_BCAST_ADDRESS()) {
  1147. SocketInfo sock_info = IfaceMgr::instance().getSocket(*query);
  1148. local_addr = sock_info.addr_;
  1149. }
  1150. // We assume that there is an appropriate socket bound to this address
  1151. // and that the address is correct. This is safe assumption because
  1152. // the local address of the query is set when the query is received.
  1153. // The query sent to an incorrect address wouldn't have been received.
  1154. // However, if socket is closed for this address between the reception
  1155. // of the query and sending a response, the IfaceMgr should detect it
  1156. // and return an error.
  1157. response->setLocalAddr(local_addr);
  1158. // In many cases the query is sent to a broadcast address. This address
  1159. // appears as a local address in the query message. Therefore we can't
  1160. // simply copy local address from the query and use it as a source
  1161. // address for the response. Instead, we have to check what address our
  1162. // socket is bound to and use it as a source address. This operation
  1163. // may throw if for some reason the socket is closed.
  1164. /// @todo Consider an optimization that we use local address from
  1165. /// the query if this address is not broadcast.
  1166. response->setLocalPort(DHCP4_SERVER_PORT);
  1167. response->setIface(query->getIface());
  1168. response->setIndex(query->getIndex());
  1169. }
  1170. void
  1171. Dhcpv4Srv::adjustRemoteAddr(Dhcpv4Exchange& ex) {
  1172. // Initialize the pointers to the client's message and the server's
  1173. // response.
  1174. Pkt4Ptr query = ex.getQuery();
  1175. Pkt4Ptr response = ex.getResponse();
  1176. // The DHCPINFORM is slightly different than other messages in a sense
  1177. // that the server should always unicast the response to the ciaddr.
  1178. // It appears however that some clients don't set the ciaddr. We still
  1179. // want to provision these clients and we do what we can't to send the
  1180. // packet to the address where client can receive it.
  1181. if (query->getType() == DHCPINFORM) {
  1182. // If client adheres to RFC2131 it will set the ciaddr and in this
  1183. // case we always unicast our response to this address.
  1184. if (query->getCiaddr() != IOAddress::IPV4_ZERO_ADDRESS()) {
  1185. response->setRemoteAddr(query->getCiaddr());
  1186. // If we received DHCPINFORM via relay and the ciaddr is not set we
  1187. // will try to send the response via relay. The caveat is that the
  1188. // relay will not have any idea where to forward the packet because
  1189. // the yiaddr is likely not set. So, the broadcast flag is set so
  1190. // as the response may be broadcast.
  1191. } else if (query->isRelayed()) {
  1192. response->setRemoteAddr(query->getGiaddr());
  1193. response->setFlags(response->getFlags() | BOOTP_BROADCAST);
  1194. // If there is no ciaddr and no giaddr the only thing we can do is
  1195. // to use the source address of the packet.
  1196. } else {
  1197. response->setRemoteAddr(query->getRemoteAddr());
  1198. }
  1199. // Remote address is now set so return.
  1200. return;
  1201. }
  1202. // If received relayed message, server responds to the relay address.
  1203. if (query->isRelayed()) {
  1204. // The client should set the ciaddr when sending the DHCPINFORM
  1205. // but in case he didn't, the relay may not be able to determine the
  1206. // address of the client, because yiaddr is not set when responding
  1207. // to Confirm and the only address available was the source address
  1208. // of the client. The source address is however not used here because
  1209. // the message is relayed. Therefore, we set the BROADCAST flag so
  1210. // as the relay can broadcast the packet.
  1211. if ((query->getType() == DHCPINFORM) &&
  1212. (query->getCiaddr() == IOAddress::IPV4_ZERO_ADDRESS())) {
  1213. response->setFlags(BOOTP_BROADCAST);
  1214. }
  1215. response->setRemoteAddr(query->getGiaddr());
  1216. // If giaddr is 0 but client set ciaddr, server should unicast the
  1217. // response to ciaddr.
  1218. } else if (query->getCiaddr() != IOAddress::IPV4_ZERO_ADDRESS()) {
  1219. response->setRemoteAddr(query->getCiaddr());
  1220. // We can't unicast the response to the client when sending NAK,
  1221. // because we haven't allocated address for him. Therefore,
  1222. // NAK is broadcast.
  1223. } else if (response->getType() == DHCPNAK) {
  1224. response->setRemoteAddr(IOAddress::IPV4_BCAST_ADDRESS());
  1225. // If yiaddr is set it means that we have created a lease for a client.
  1226. } else if (response->getYiaddr() != IOAddress::IPV4_ZERO_ADDRESS()) {
  1227. // If the broadcast bit is set in the flags field, we have to
  1228. // send the response to broadcast address. Client may have requested it
  1229. // because it doesn't support reception of messages on the interface
  1230. // which doesn't have an address assigned. The other case when response
  1231. // must be broadcasted is when our server does not support responding
  1232. // directly to a client without address assigned.
  1233. const bool bcast_flag = ((query->getFlags() & Pkt4::FLAG_BROADCAST_MASK) != 0);
  1234. if (!IfaceMgr::instance().isDirectResponseSupported() || bcast_flag) {
  1235. response->setRemoteAddr(IOAddress::IPV4_BCAST_ADDRESS());
  1236. // Client cleared the broadcast bit and we support direct responses
  1237. // so we should unicast the response to a newly allocated address -
  1238. // yiaddr.
  1239. } else {
  1240. response->setRemoteAddr(response ->getYiaddr());
  1241. }
  1242. // In most cases, we should have the remote address found already. If we
  1243. // found ourselves at this point, the rational thing to do is to respond
  1244. // to the address we got the query from.
  1245. } else {
  1246. response->setRemoteAddr(query->getRemoteAddr());
  1247. }
  1248. }
  1249. OptionPtr
  1250. Dhcpv4Srv::getNetmaskOption(const Subnet4Ptr& subnet) {
  1251. uint32_t netmask = getNetmask4(subnet->get().second);
  1252. OptionPtr opt(new OptionInt<uint32_t>(Option::V4,
  1253. DHO_SUBNET_MASK, netmask));
  1254. return (opt);
  1255. }
  1256. Pkt4Ptr
  1257. Dhcpv4Srv::processDiscover(Pkt4Ptr& discover) {
  1258. sanityCheck(discover, FORBIDDEN);
  1259. Dhcpv4Exchange ex(alloc_engine_, discover, selectSubnet(discover));
  1260. // If DHCPDISCOVER message contains the FQDN or Hostname option, server
  1261. // may respond to the client with the appropriate FQDN or Hostname
  1262. // option to indicate that whether it will take responsibility for
  1263. // updating DNS when the client sends DHCPREQUEST message.
  1264. processClientName(ex);
  1265. assignLease(ex);
  1266. if (!ex.getResponse()) {
  1267. // The offer is empty so return it *now*!
  1268. return (Pkt4Ptr());
  1269. }
  1270. // Adding any other options makes sense only when we got the lease.
  1271. if (!ex.getResponse()->getYiaddr().isV4Zero()) {
  1272. appendRequestedOptions(ex);
  1273. appendRequestedVendorOptions(ex);
  1274. // There are a few basic options that we always want to
  1275. // include in the response. If client did not request
  1276. // them we append them for him.
  1277. appendBasicOptions(ex);
  1278. } else {
  1279. // If the server can't offer an address, it drops the packet.
  1280. return (Pkt4Ptr());
  1281. }
  1282. // Set the src/dest IP address, port and interface for the outgoing
  1283. // packet.
  1284. adjustIfaceData(ex);
  1285. appendServerID(ex);
  1286. /// @todo: decide whether we want to add a new hook point for
  1287. /// doing class specific processing.
  1288. if (!classSpecificProcessing(ex)) {
  1289. /// @todo add more verbosity here
  1290. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_DISCOVER_CLASS_PROCESSING_FAILED);
  1291. }
  1292. return (ex.getResponse());
  1293. }
  1294. Pkt4Ptr
  1295. Dhcpv4Srv::processRequest(Pkt4Ptr& request) {
  1296. /// @todo Uncomment this (see ticket #3116)
  1297. /// sanityCheck(request, MANDATORY);
  1298. Dhcpv4Exchange ex(alloc_engine_, request, selectSubnet(request));
  1299. // If DHCPREQUEST message contains the FQDN or Hostname option, server
  1300. // should respond to the client with the appropriate FQDN or Hostname
  1301. // option to indicate if it takes responsibility for the DNS updates.
  1302. // This is performed by the function below.
  1303. processClientName(ex);
  1304. // Note that we treat REQUEST message uniformly, regardless if this is a
  1305. // first request (requesting for new address), renewing existing address
  1306. // or even rebinding.
  1307. assignLease(ex);
  1308. if (!ex.getResponse()) {
  1309. // The ack is empty so return it *now*!
  1310. return (Pkt4Ptr());
  1311. }
  1312. // Adding any other options makes sense only when we got the lease.
  1313. if (!ex.getResponse()->getYiaddr().isV4Zero()) {
  1314. appendRequestedOptions(ex);
  1315. appendRequestedVendorOptions(ex);
  1316. // There are a few basic options that we always want to
  1317. // include in the response. If client did not request
  1318. // them we append them for him.
  1319. appendBasicOptions(ex);
  1320. }
  1321. // Set the src/dest IP address, port and interface for the outgoing
  1322. // packet.
  1323. adjustIfaceData(ex);
  1324. appendServerID(ex);
  1325. /// @todo: decide whether we want to add a new hook point for
  1326. /// doing class specific processing.
  1327. if (!classSpecificProcessing(ex)) {
  1328. /// @todo add more verbosity here
  1329. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_REQUEST_CLASS_PROCESSING_FAILED);
  1330. }
  1331. return (ex.getResponse());
  1332. }
  1333. void
  1334. Dhcpv4Srv::processRelease(Pkt4Ptr& release) {
  1335. /// @todo Uncomment this (see ticket #3116)
  1336. /// sanityCheck(release, MANDATORY);
  1337. // Try to find client-id. Note that for the DHCPRELEASE we don't check if the
  1338. // record-client-id configuration parameter is disabled because this parameter
  1339. // is configured for subnets and we don't select subnet for the DHCPRELEASE.
  1340. // Bogus clients usually generate new client identifiers when they first
  1341. // connect to the network, so whatever client identifier has been used to
  1342. // acquire the lease, the client identifier carried in the DHCPRELEASE is
  1343. // likely to be the same and the lease will be correctly identified in the
  1344. // lease database. If supplied client identifier differs from the one used
  1345. // to acquire the lease then the lease will remain in the database and
  1346. // simply expire.
  1347. ClientIdPtr client_id;
  1348. OptionPtr opt = release->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
  1349. if (opt) {
  1350. client_id = ClientIdPtr(new ClientId(opt->getData()));
  1351. }
  1352. try {
  1353. // Do we have a lease for that particular address?
  1354. Lease4Ptr lease = LeaseMgrFactory::instance().getLease4(release->getCiaddr());
  1355. if (!lease) {
  1356. // No such lease - bogus release
  1357. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL,
  1358. DHCP4_RELEASE_FAIL_NO_LEASE)
  1359. .arg(client_id ? client_id->toText() : "(no client-id)")
  1360. .arg(release->getHWAddr() ?
  1361. release->getHWAddr()->toText() : "(no hwaddr info)")
  1362. .arg(release->getCiaddr().toText());
  1363. return;
  1364. }
  1365. if (!lease->belongsToClient(release->getHWAddr(), client_id)) {
  1366. /// @todo add debug message here when we merge the code with the
  1367. /// changes from #3806.
  1368. return;
  1369. }
  1370. bool skip = false;
  1371. // Execute all callouts registered for lease4_release
  1372. if (HooksManager::calloutsPresent(Hooks.hook_index_lease4_release_)) {
  1373. CalloutHandlePtr callout_handle = getCalloutHandle(release);
  1374. // Delete all previous arguments
  1375. callout_handle->deleteAllArguments();
  1376. // Pass the original packet
  1377. callout_handle->setArgument("query4", release);
  1378. // Pass the lease to be updated
  1379. callout_handle->setArgument("lease4", lease);
  1380. // Call all installed callouts
  1381. HooksManager::callCallouts(Hooks.hook_index_lease4_release_,
  1382. *callout_handle);
  1383. // Callouts decided to skip the next processing step. The next
  1384. // processing step would to send the packet, so skip at this
  1385. // stage means "drop response".
  1386. if (callout_handle->getSkip()) {
  1387. skip = true;
  1388. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_HOOKS,
  1389. DHCP4_HOOK_LEASE4_RELEASE_SKIP);
  1390. }
  1391. }
  1392. // Ok, hw and client-id match - let's release the lease.
  1393. if (!skip) {
  1394. bool success = LeaseMgrFactory::instance().deleteLease(lease->addr_);
  1395. if (success) {
  1396. // Release successful
  1397. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_DETAIL, DHCP4_RELEASE)
  1398. .arg(lease->addr_.toText())
  1399. .arg(client_id ? client_id->toText() : "(no client-id)")
  1400. .arg(release->getHWAddr()->toText());
  1401. if (CfgMgr::instance().ddnsEnabled()) {
  1402. // Remove existing DNS entries for the lease, if any.
  1403. queueNameChangeRequest(isc::dhcp_ddns::CHG_REMOVE, lease);
  1404. }
  1405. } else {
  1406. // Release failed -
  1407. LOG_ERROR(dhcp4_logger, DHCP4_RELEASE_FAIL)
  1408. .arg(lease->addr_.toText())
  1409. .arg(client_id ? client_id->toText() : "(no client-id)")
  1410. .arg(release->getHWAddr()->toText());
  1411. }
  1412. }
  1413. } catch (const isc::Exception& ex) {
  1414. // Rethrow the exception with a bit more data.
  1415. LOG_ERROR(dhcp4_logger, DHCP4_RELEASE_EXCEPTION)
  1416. .arg(ex.what())
  1417. .arg(release->getYiaddr());
  1418. }
  1419. }
  1420. void
  1421. Dhcpv4Srv::processDecline(Pkt4Ptr&) {
  1422. /// @todo Implement this (also see ticket #3116)
  1423. }
  1424. Pkt4Ptr
  1425. Dhcpv4Srv::processInform(Pkt4Ptr& inform) {
  1426. // DHCPINFORM MUST not include server identifier.
  1427. sanityCheck(inform, FORBIDDEN);
  1428. Dhcpv4Exchange ex(alloc_engine_, inform, selectSubnet(inform));
  1429. Pkt4Ptr ack = ex.getResponse();
  1430. appendRequestedOptions(ex);
  1431. appendRequestedVendorOptions(ex);
  1432. appendBasicOptions(ex);
  1433. adjustIfaceData(ex);
  1434. // There are cases for the DHCPINFORM that the server receives it via
  1435. // relay but will send the response to the client's unicast address
  1436. // carried in the ciaddr. In this case, the giaddr and hops field should
  1437. // be cleared (these fields were copied by the copyDefaultFields function).
  1438. // Also Relay Agent Options should be removed if present.
  1439. if (ack->getRemoteAddr() != inform->getGiaddr()) {
  1440. ack->setHops(0);
  1441. ack->setGiaddr(IOAddress::IPV4_ZERO_ADDRESS());
  1442. ack->delOption(DHO_DHCP_AGENT_OPTIONS);
  1443. }
  1444. // The DHCPACK must contain server id.
  1445. appendServerID(ex);
  1446. /// @todo: decide whether we want to add a new hook point for
  1447. /// doing class specific processing.
  1448. if (!classSpecificProcessing(ex)) {
  1449. /// @todo add more verbosity here
  1450. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_INFORM_CLASS_PROCESSING_FAILED);
  1451. }
  1452. return (ex.getResponse());
  1453. }
  1454. const char*
  1455. Dhcpv4Srv::serverReceivedPacketName(uint8_t type) {
  1456. static const char* DISCOVER = "DISCOVER";
  1457. static const char* REQUEST = "REQUEST";
  1458. static const char* RELEASE = "RELEASE";
  1459. static const char* DECLINE = "DECLINE";
  1460. static const char* INFORM = "INFORM";
  1461. static const char* UNKNOWN = "UNKNOWN";
  1462. switch (type) {
  1463. case DHCPDISCOVER:
  1464. return (DISCOVER);
  1465. case DHCPREQUEST:
  1466. return (REQUEST);
  1467. case DHCPRELEASE:
  1468. return (RELEASE);
  1469. case DHCPDECLINE:
  1470. return (DECLINE);
  1471. case DHCPINFORM:
  1472. return (INFORM);
  1473. default:
  1474. ;
  1475. }
  1476. return (UNKNOWN);
  1477. }
  1478. bool
  1479. Dhcpv4Srv::accept(const Pkt4Ptr& query) const {
  1480. // Check that the message type is accepted by the server. We rely on the
  1481. // function called to log a message if needed.
  1482. if (!acceptMessageType(query)) {
  1483. return (false);
  1484. }
  1485. // Check if the message from directly connected client (if directly
  1486. // connected) should be dropped or processed.
  1487. if (!acceptDirectRequest(query)) {
  1488. LOG_DEBUG(bad_packet_logger, DBG_DHCP4_DETAIL, DHCP4_PACKET_DROP_0002)
  1489. .arg(query->getLabel())
  1490. .arg(query->getIface());
  1491. return (false);
  1492. }
  1493. // Check if the DHCPv4 packet has been sent to us or to someone else.
  1494. // If it hasn't been sent to us, drop it!
  1495. if (!acceptServerId(query)) {
  1496. LOG_DEBUG(bad_packet_logger, DBG_DHCP4_DETAIL, DHCP4_PACKET_DROP_0003)
  1497. .arg(query->getLabel())
  1498. .arg(query->getIface());
  1499. return (false);
  1500. }
  1501. return (true);
  1502. }
  1503. bool
  1504. Dhcpv4Srv::acceptDirectRequest(const Pkt4Ptr& pkt) const {
  1505. // Accept all relayed messages.
  1506. if (pkt->isRelayed()) {
  1507. return (true);
  1508. }
  1509. // The source address must not be zero for the DHCPINFORM message from
  1510. // the directly connected client because the server will not know where
  1511. // to respond if the ciaddr was not present.
  1512. try {
  1513. if (pkt->getType() == DHCPINFORM) {
  1514. if ((pkt->getRemoteAddr() == IOAddress::IPV4_ZERO_ADDRESS()) &&
  1515. (pkt->getCiaddr() == IOAddress::IPV4_ZERO_ADDRESS())) {
  1516. return (false);
  1517. }
  1518. }
  1519. } catch (...) {
  1520. // If we got here, it is probably because the message type hasn't
  1521. // been set. But, this should not really happen assuming that
  1522. // we validate the message type prior to calling this function.
  1523. return (false);
  1524. }
  1525. return ((pkt->getLocalAddr() != IOAddress::IPV4_BCAST_ADDRESS()
  1526. || selectSubnet(pkt)));
  1527. }
  1528. bool
  1529. Dhcpv4Srv::acceptMessageType(const Pkt4Ptr& query) const {
  1530. // When receiving a packet without message type option, getType() will
  1531. // throw.
  1532. int type;
  1533. try {
  1534. type = query->getType();
  1535. } catch (...) {
  1536. LOG_DEBUG(bad_packet_logger, DBG_DHCP4_DETAIL, DHCP4_PACKET_DROP_0004)
  1537. .arg(query->getLabel())
  1538. .arg(query->getIface());
  1539. return (false);
  1540. }
  1541. // If we receive a message with a non-existing type, we are logging it.
  1542. if (type > DHCPLEASEQUERYDONE) {
  1543. LOG_DEBUG(bad_packet_logger, DBG_DHCP4_DETAIL, DHCP4_PACKET_DROP_0005)
  1544. .arg(query->getLabel())
  1545. .arg(type);
  1546. return (false);
  1547. }
  1548. // Once we know that the message type is within a range of defined DHCPv4
  1549. // messages, we do a detailed check to make sure that the received message
  1550. // is targeted at server. Note that we could have received some Offer
  1551. // message broadcasted by the other server to a relay. Even though, the
  1552. // server would rather unicast its response to a relay, let's be on the
  1553. // safe side. Also, we want to drop other messages which we don't support.
  1554. // All these valid messages that we are not going to process are dropped
  1555. // silently.
  1556. if ((type != DHCPDISCOVER) && (type != DHCPREQUEST) &&
  1557. (type != DHCPRELEASE) && (type != DHCPDECLINE) &&
  1558. (type != DHCPINFORM)) {
  1559. LOG_DEBUG(bad_packet_logger, DBG_DHCP4_DETAIL, DHCP4_PACKET_DROP_0006)
  1560. .arg(query->getLabel())
  1561. .arg(type);
  1562. return (false);
  1563. }
  1564. return (true);
  1565. }
  1566. bool
  1567. Dhcpv4Srv::acceptServerId(const Pkt4Ptr& query) const {
  1568. // This function is meant to be called internally by the server class, so
  1569. // we rely on the caller to sanity check the pointer and we don't check
  1570. // it here.
  1571. // Check if server identifier option is present. If it is not present
  1572. // we accept the message because it is targeted to all servers.
  1573. // Note that we don't check cases that server identifier is mandatory
  1574. // but not present. This is meant to be sanity checked in other
  1575. // functions.
  1576. OptionPtr option = query->getOption(DHO_DHCP_SERVER_IDENTIFIER);
  1577. if (!option) {
  1578. return (true);
  1579. }
  1580. // Server identifier is present. Let's convert it to 4-byte address
  1581. // and try to match with server identifiers used by the server.
  1582. OptionCustomPtr option_custom =
  1583. boost::dynamic_pointer_cast<OptionCustom>(option);
  1584. // Unable to convert the option to the option type which encapsulates it.
  1585. // We treat this as non-matching server id.
  1586. if (!option_custom) {
  1587. return (false);
  1588. }
  1589. // The server identifier option should carry exactly one IPv4 address.
  1590. // If the option definition for the server identifier doesn't change,
  1591. // the OptionCustom object should have exactly one IPv4 address and
  1592. // this check is somewhat redundant. On the other hand, if someone
  1593. // breaks option it may be better to check that here.
  1594. if (option_custom->getDataFieldsNum() != 1) {
  1595. return (false);
  1596. }
  1597. // The server identifier MUST be an IPv4 address. If given address is
  1598. // v6, it is wrong.
  1599. IOAddress server_id = option_custom->readAddress();
  1600. if (!server_id.isV4()) {
  1601. return (false);
  1602. }
  1603. // This function iterates over all interfaces on which the
  1604. // server is listening to find the one which has a socket bound
  1605. // to the address carried in the server identifier option.
  1606. // This has some performance implications. However, given that
  1607. // typically there will be just a few active interfaces the
  1608. // performance hit should be acceptable. If it turns out to
  1609. // be significant, we will have to cache server identifiers
  1610. // when sockets are opened.
  1611. return (IfaceMgr::instance().hasOpenSocket(server_id));
  1612. }
  1613. void
  1614. Dhcpv4Srv::sanityCheck(const Pkt4Ptr& query, RequirementLevel serverid) {
  1615. OptionPtr server_id = query->getOption(DHO_DHCP_SERVER_IDENTIFIER);
  1616. switch (serverid) {
  1617. case FORBIDDEN:
  1618. if (server_id) {
  1619. isc_throw(RFCViolation, "Server-id option was not expected, but "
  1620. << "received in "
  1621. << serverReceivedPacketName(query->getType()));
  1622. }
  1623. break;
  1624. case MANDATORY:
  1625. if (!server_id) {
  1626. isc_throw(RFCViolation, "Server-id option was expected, but not "
  1627. " received in message "
  1628. << serverReceivedPacketName(query->getType()));
  1629. }
  1630. break;
  1631. case OPTIONAL:
  1632. // do nothing here
  1633. ;
  1634. }
  1635. // If there is HWAddress set and it is non-empty, then we're good
  1636. if (query->getHWAddr() && !query->getHWAddr()->hwaddr_.empty()) {
  1637. return;
  1638. }
  1639. // There has to be something to uniquely identify the client:
  1640. // either non-zero MAC address or client-id option present (or both)
  1641. OptionPtr client_id = query->getOption(DHO_DHCP_CLIENT_IDENTIFIER);
  1642. // If there's no client-id (or a useless one is provided, i.e. 0 length)
  1643. if (!client_id || client_id->len() == client_id->getHeaderLen()) {
  1644. isc_throw(RFCViolation, "Missing or useless client-id and no HW address "
  1645. " provided in message "
  1646. << serverReceivedPacketName(query->getType()));
  1647. }
  1648. }
  1649. size_t
  1650. Dhcpv4Srv::unpackOptions(const OptionBuffer& buf,
  1651. const std::string& option_space,
  1652. isc::dhcp::OptionCollection& options) {
  1653. size_t offset = 0;
  1654. OptionDefContainer option_defs;
  1655. if (option_space == "dhcp4") {
  1656. // Get the list of standard option definitions.
  1657. option_defs = LibDHCP::getOptionDefs(Option::V4);
  1658. } else if (!option_space.empty()) {
  1659. OptionDefContainerPtr option_defs_ptr = CfgMgr::instance()
  1660. .getCurrentCfg()->getCfgOptionDef()->getAll(option_space);
  1661. if (option_defs_ptr != NULL) {
  1662. option_defs = *option_defs_ptr;
  1663. }
  1664. }
  1665. // Get the search index #1. It allows to search for option definitions
  1666. // using option code.
  1667. const OptionDefContainerTypeIndex& idx = option_defs.get<1>();
  1668. // The buffer being read comprises a set of options, each starting with
  1669. // a one-byte type code and a one-byte length field.
  1670. while (offset + 1 <= buf.size()) {
  1671. uint8_t opt_type = buf[offset++];
  1672. // DHO_END is a special, one octet long option
  1673. if (opt_type == DHO_END)
  1674. return (offset); // just return. Don't need to add DHO_END option
  1675. // DHO_PAD is just a padding after DHO_END. Let's continue parsing
  1676. // in case we receive a message without DHO_END.
  1677. if (opt_type == DHO_PAD)
  1678. continue;
  1679. if (offset + 1 > buf.size()) {
  1680. // opt_type must be cast to integer so as it is not treated as
  1681. // unsigned char value (a number is presented in error message).
  1682. isc_throw(OutOfRange, "Attempt to parse truncated option "
  1683. << static_cast<int>(opt_type));
  1684. }
  1685. uint8_t opt_len = buf[offset++];
  1686. if (offset + opt_len > buf.size()) {
  1687. // We peeked at the option header of the next option, but discovered
  1688. // that it would end up beyond buffer end, so the option is
  1689. // truncated. Hence we can't parse it. Therefore we revert
  1690. // back by two bytes (as if we never parsed them).
  1691. return (offset - 2);
  1692. // isc_throw(OutOfRange, "Option parse failed. Tried to parse "
  1693. // << offset + opt_len << " bytes from " << buf.size()
  1694. // << "-byte long buffer.");
  1695. }
  1696. // Get all definitions with the particular option code. Note that option code
  1697. // is non-unique within this container however at this point we expect
  1698. // to get one option definition with the particular code. If more are
  1699. // returned we report an error.
  1700. const OptionDefContainerTypeRange& range = idx.equal_range(opt_type);
  1701. // Get the number of returned option definitions for the option code.
  1702. size_t num_defs = distance(range.first, range.second);
  1703. OptionPtr opt;
  1704. if (num_defs > 1) {
  1705. // Multiple options of the same code are not supported right now!
  1706. isc_throw(isc::Unexpected, "Internal error: multiple option definitions"
  1707. " for option type " << static_cast<int>(opt_type)
  1708. << " returned. Currently it is not supported to initialize"
  1709. << " multiple option definitions for the same option code."
  1710. << " This will be supported once support for option spaces"
  1711. << " is implemented");
  1712. } else if (num_defs == 0) {
  1713. opt = OptionPtr(new Option(Option::V4, opt_type,
  1714. buf.begin() + offset,
  1715. buf.begin() + offset + opt_len));
  1716. opt->setEncapsulatedSpace("dhcp4");
  1717. } else {
  1718. // The option definition has been found. Use it to create
  1719. // the option instance from the provided buffer chunk.
  1720. const OptionDefinitionPtr& def = *(range.first);
  1721. assert(def);
  1722. opt = def->optionFactory(Option::V4, opt_type,
  1723. buf.begin() + offset,
  1724. buf.begin() + offset + opt_len,
  1725. boost::bind(&Dhcpv4Srv::unpackOptions,
  1726. this, _1, _2, _3));
  1727. }
  1728. options.insert(std::make_pair(opt_type, opt));
  1729. offset += opt_len;
  1730. }
  1731. return (offset);
  1732. }
  1733. void Dhcpv4Srv::classifyPacket(const Pkt4Ptr& pkt) {
  1734. boost::shared_ptr<OptionString> vendor_class =
  1735. boost::dynamic_pointer_cast<OptionString>(pkt->getOption(DHO_VENDOR_CLASS_IDENTIFIER));
  1736. string classes = "";
  1737. if (!vendor_class) {
  1738. return;
  1739. }
  1740. // DOCSIS specific section
  1741. // Let's keep this as a series of checks. So far we're supporting only
  1742. // docsis3.0, but there are also docsis2.0, docsis1.1 and docsis1.0. We
  1743. // may come up with adding several classes, e.g. for docsis2.0 we would
  1744. // add classes docsis2.0, docsis1.1 and docsis1.0.
  1745. // Also we are using find, because we have at least one traffic capture
  1746. // where the user class was followed by a space ("docsis3.0 ").
  1747. // For now, the code is very simple, but it is expected to get much more
  1748. // complex soon. One specific case is that the vendor class is an option
  1749. // sent by the client, so we should not trust it. To confirm that the device
  1750. // is indeed a modem, John B. suggested to check whether chaddr field
  1751. // quals subscriber-id option that was inserted by the relay (CMTS).
  1752. // This kind of logic will appear here soon.
  1753. if (vendor_class->getValue().find(DOCSIS3_CLASS_MODEM) != std::string::npos) {
  1754. pkt->addClass(VENDOR_CLASS_PREFIX + DOCSIS3_CLASS_MODEM);
  1755. classes += string(VENDOR_CLASS_PREFIX + DOCSIS3_CLASS_MODEM) + " ";
  1756. } else
  1757. if (vendor_class->getValue().find(DOCSIS3_CLASS_EROUTER) != std::string::npos) {
  1758. pkt->addClass(VENDOR_CLASS_PREFIX + DOCSIS3_CLASS_EROUTER);
  1759. classes += string(VENDOR_CLASS_PREFIX + DOCSIS3_CLASS_EROUTER) + " ";
  1760. } else {
  1761. classes += VENDOR_CLASS_PREFIX + vendor_class->getValue();
  1762. pkt->addClass(VENDOR_CLASS_PREFIX + vendor_class->getValue());
  1763. }
  1764. if (!classes.empty()) {
  1765. LOG_DEBUG(dhcp4_logger, DBG_DHCP4_BASIC, DHCP4_CLASS_ASSIGNED)
  1766. .arg(classes);
  1767. }
  1768. }
  1769. bool
  1770. Dhcpv4Srv::classSpecificProcessing(const Dhcpv4Exchange& ex) {
  1771. Subnet4Ptr subnet = ex.getContext()->subnet_;
  1772. Pkt4Ptr query = ex.getQuery();
  1773. Pkt4Ptr rsp = ex.getResponse();
  1774. // If any of those is missing, there is nothing to do.
  1775. if (!subnet || !query || !rsp) {
  1776. return (true);
  1777. }
  1778. if (query->inClass(VENDOR_CLASS_PREFIX + DOCSIS3_CLASS_MODEM)) {
  1779. // Set next-server. This is TFTP server address. Cable modems will
  1780. // download their configuration from that server.
  1781. rsp->setSiaddr(subnet->getSiaddr());
  1782. // Now try to set up file field in DHCPv4 packet. We will just copy
  1783. // content of the boot-file option, which contains the same information.
  1784. OptionDescriptor desc = subnet->getCfgOption()->
  1785. get("dhcp4", DHO_BOOT_FILE_NAME);
  1786. if (desc.option_) {
  1787. boost::shared_ptr<OptionString> boot =
  1788. boost::dynamic_pointer_cast<OptionString>(desc.option_);
  1789. if (boot) {
  1790. std::string filename = boot->getValue();
  1791. rsp->setFile((const uint8_t*)filename.c_str(), filename.size());
  1792. }
  1793. }
  1794. }
  1795. if (query->inClass(VENDOR_CLASS_PREFIX + DOCSIS3_CLASS_EROUTER)) {
  1796. // Do not set TFTP server address for eRouter devices.
  1797. rsp->setSiaddr(IOAddress::IPV4_ZERO_ADDRESS());
  1798. }
  1799. return (true);
  1800. }
  1801. void
  1802. Dhcpv4Srv::startD2() {
  1803. D2ClientMgr& d2_mgr = CfgMgr::instance().getD2ClientMgr();
  1804. if (d2_mgr.ddnsEnabled()) {
  1805. // Updates are enabled, so lets start the sender, passing in
  1806. // our error handler.
  1807. // This may throw so wherever this is called needs to ready.
  1808. d2_mgr.startSender(boost::bind(&Dhcpv4Srv::d2ClientErrorHandler,
  1809. this, _1, _2));
  1810. }
  1811. }
  1812. void
  1813. Dhcpv4Srv::d2ClientErrorHandler(const
  1814. dhcp_ddns::NameChangeSender::Result result,
  1815. dhcp_ddns::NameChangeRequestPtr& ncr) {
  1816. LOG_ERROR(dhcp4_logger, DHCP4_DDNS_REQUEST_SEND_FAILED).
  1817. arg(result).arg((ncr ? ncr->toText() : " NULL "));
  1818. // We cannot communicate with kea-dhcp-ddns, suspend further updates.
  1819. /// @todo We may wish to revisit this, but for now we will simply turn
  1820. /// them off.
  1821. CfgMgr::instance().getD2ClientMgr().suspendUpdates();
  1822. }
  1823. std::string
  1824. Daemon::getVersion(bool extended) {
  1825. std::stringstream tmp;
  1826. tmp << VERSION;
  1827. if (extended) {
  1828. tmp << endl << EXTENDED_VERSION;
  1829. // @todo print more details (is it Botan or OpenSSL build,
  1830. // with or without MySQL/Postgres? What compilation options were
  1831. // used? etc)
  1832. }
  1833. return (tmp.str());
  1834. }
  1835. } // namespace dhcp
  1836. } // namespace isc