OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
dhcp_handler_base.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include <stdint.h>
6 #include "vr_defs.h"
7 #include "cmn/agent_cmn.h"
8 #include "pkt/pkt_init.h"
9 #include "oper/vn.h"
10 #include "services/dhcp_proto.h"
11 #include "services/dhcpv6_proto.h"
12 #include "services/services_types.h"
13 #include "services/services_init.h"
14 #include "services/dns_proto.h"
16 #include "bind/bind_util.h"
17 
18 #include <boost/assign/list_of.hpp>
19 #include <boost/scoped_array.hpp>
20 #include <bind/bind_util.h>
21 
22 using namespace boost::assign;
23 
24 DhcpHandlerBase::DhcpHandlerBase(Agent *agent, boost::shared_ptr<PktInfo> info,
25  boost::asio::io_context &io)
26  : ProtoHandler(agent, info, io), vm_itf_(NULL), vm_itf_index_(-1),
27  option_(NULL), flags_(), dns_enable_(true),
28  host_routes_level_(Invalid) {
29  ipam_type_.ipam_dns_method = "none";
30 }
31 
33 }
34 
35 // Add option taking no data (length = 0)
36 uint16_t DhcpHandlerBase::AddNoDataOption(uint32_t option, uint16_t opt_len) {
37  option_->WriteData(option, 0, NULL, &opt_len);
38  return opt_len;
39 }
40 
41 // Add option taking a byte from input
42 uint16_t DhcpHandlerBase::AddByteOption(uint32_t option, uint16_t opt_len,
43  const std::string &input) {
44  std::stringstream value(input);
45  uint32_t data = 0;
46  value >> data;
47  if (value.bad() || value.fail() || data > 0xFF) {
48  DHCP_BASE_TRACE("Invalid DHCP option " << option << " data : " <<
49  input << "is invalid");
50  } else {
51  uint8_t byte = (uint8_t)data;
52  option_->WriteData(option, 1, &byte, &opt_len);
53  }
54  return opt_len;
55 }
56 
57 // Add option taking array of bytes from input
58 uint16_t DhcpHandlerBase::AddByteArrayOption(uint32_t option, uint16_t opt_len,
59  const std::string &input) {
60  option_->WriteData(option, 0, NULL, &opt_len);
61  std::stringstream value(input);
62  bool done = false;
63  uint32_t byte = 0;
64  value >> byte;
65  while (!value.bad() && !value.fail() && byte <= 0xFF) {
66  option_->AppendData(1, &byte, &opt_len);
67  if (value.eof()) {
68  done = true;
69  break;
70  }
71  value >> byte;
72  }
73 
74  // if atleast one byte is not added or in case of error, ignore this option
75  if (!option_->GetLen() || !done) {
76  DHCP_BASE_TRACE("Invalid DHCP option " << option << " data : " <<
77  input << "is invalid");
78  return opt_len - option_->GetLen() - option_->GetFixedLen();
79  }
80 
81  return opt_len;
82 }
83 
84 // Add option taking a byte followed by a string, from input
85 uint16_t DhcpHandlerBase::AddByteStringOption(uint32_t option, uint16_t opt_len,
86  const std::string &input) {
87  std::stringstream value(input);
88  uint32_t data = 0;
89  value >> data;
90  if (value.fail() || value.bad() || data > 0xFF) {
91  DHCP_BASE_TRACE("Invalid DHCP option " << option << " data : " <<
92  input << "is invalid");
93  return opt_len;
94  }
95 
96  uint8_t byte = (uint8_t)data;
97  std::string str;
98  value >> str;
99  option_->WriteData(option, 1, &byte, &opt_len);
100  option_->AppendData(str.length(), str.c_str(), &opt_len);
101 
102  return opt_len;
103 }
104 
105 // Add option taking a byte followed by one or more IPs, from input
106 uint16_t DhcpHandlerBase::AddByteIPOption(uint32_t option, uint16_t opt_len,
107  const std::string &input) {
108  std::stringstream value(input);
109  uint32_t data = 0;
110  value >> data;
111  uint8_t byte = (uint8_t)data;
112 
113  if (value.fail() || value.bad() || data > 0xFF) {
114  DHCP_BASE_TRACE("Invalid DHCP option " << option << " data : " <<
115  input << "is invalid");
116  return opt_len;
117  }
118 
119  option_->WriteData(option, 1, &byte, &opt_len);
120  while (value.good()) {
121  std::string ipstr;
122  value >> ipstr;
123  opt_len = AddIP(opt_len, ipstr);
124  }
125 
126  // if atleast one IP is not added, ignore this option
127  if (option_->GetLen() == 1) {
128  DHCP_BASE_TRACE("Invalid DHCP option " << option << " data : " <<
129  input << "is invalid");
130  return opt_len - option_->GetLen() - option_->GetFixedLen();
131  }
132 
133  return opt_len;
134 }
135 
136 // Add option taking string from input
137 uint16_t DhcpHandlerBase::AddStringOption(uint32_t option, uint16_t opt_len,
138  const std::string &input) {
139  option_->WriteData(option, input.length(), input.c_str(), &opt_len);
140  return opt_len;
141 }
142 
143 // Add option taking integer from input
144 uint16_t DhcpHandlerBase::AddIntegerOption(uint32_t option, uint16_t opt_len,
145  const std::string &input) {
146  std::stringstream value(input);
147  uint32_t data = 0;
148  value >> data;
149  if (value.bad() || value.fail()) {
150  DHCP_BASE_TRACE("Invalid DHCP option " << option << " data : " <<
151  input << "is invalid");
152  } else {
153  data = htonl(data);
154  option_->WriteData(option, 4, &data, &opt_len);
155  }
156  return opt_len;
157 }
158 
159 // Add option taking array of short from input
160 uint16_t DhcpHandlerBase::AddShortArrayOption(uint32_t option, uint16_t opt_len,
161  const std::string &input,
162  bool array) {
163  option_->WriteData(option, 0, NULL, &opt_len);
164  std::stringstream value(input);
165  uint16_t data = 0;
166  value >> data;
167  while (!value.bad() && !value.fail()) {
168  data = htons(data);
169  option_->AppendData(2, &data, &opt_len);
170  if (!array || value.eof()) break;
171  value >> data;
172  }
173 
174  // if atleast one short is not added, ignore this option
175  if (!option_->GetLen() || !value.eof()) {
176  DHCP_BASE_TRACE("Invalid DHCP option " << option << " data : " <<
177  input << "is invalid");
178  return opt_len - option_->GetLen() - option_->GetFixedLen();
179  }
180 
181  return opt_len;
182 }
183 
184 // Check for exceptions in handling IP options
185 bool DhcpHandlerBase::IsValidIpOption(uint32_t option, const std::string &ipstr,
186  bool is_v4) {
187  boost::system::error_code ec;
188  if (is_v4) {
189  if (option == DHCP_OPTION_DNS) {
190  return IsValidDnsOption(option, ipstr);
191  } else {
192  uint32_t ip = Ip4Address::from_string(ipstr, ec).to_ulong();
193  if(!ec.value() && !ip) {
194  return false;
195  }
196  }
197 
198  } else {
199  if (option == DHCPV6_OPTION_DNS_SERVERS) {
200  return IsValidDnsOption(option, ipstr);
201  } else {
202  IpAddress ip = IpAddress::from_string(ipstr, ec);
203  if (!ec.value() && ip.is_unspecified()) {
204  return false;
205  }
206  }
207  }
208 
209  return true;
210 }
211 
213  const std::string &ipstr) {
214  boost::system::error_code ec;
215  IpAddress ip = IpAddress::from_string(ipstr, ec);
216  if (!ec.value()) {
217  // when DNS server is present in DHCP option, disable vrouter
218  // proxying for DNS requests from VMs.
219  dns_enable_ = false;
220  if (ip.is_unspecified()) {
221  // Do not send the option when DNS servers have 0.0.0.0 or ::
222  // Set option flag so that they are not added later
223  set_flag(option);
224  return false;
225  }
226  }
227 
228  return true;
229 }
230 
231 // Add option taking number of Ipv4 addresses
232 uint16_t DhcpHandlerBase::AddIpv4Option(uint32_t option, uint16_t opt_len,
233  const std::string &input,
234  uint8_t min_count,
235  uint8_t max_count,
236  uint8_t multiples) {
237  option_->WriteData(option, 0, NULL, &opt_len);
238  std::stringstream value(input);
239  while (value.good()) {
240  std::string ipstr;
241  value >> ipstr;
242  if (!IsValidIpOption(option, ipstr, true)) {
243  return opt_len - option_->GetLen() - option_->GetFixedLen();
244  }
245  opt_len = AddIP(opt_len, ipstr);
246  }
247 
248  if (option == DHCP_OPTION_ROUTER) {
249  // Add our gw as well
250  if (!config_.gw_addr.is_unspecified()) {
251  opt_len = AddIP(opt_len, config_.gw_addr.to_string());
252  }
253  }
254 
255  // check that atleast min_count IP addresses are added
256  if (min_count && option_->GetLen() < min_count * 4) {
257  DHCP_BASE_TRACE("Invalid DHCP option " << option << " data : " <<
258  input << "is invalid");
259  return opt_len - option_->GetLen() - option_->GetFixedLen();
260  }
261 
262  // if specified, check that we dont add more than max_count IP addresses
263  if (max_count && option_->GetLen() > max_count * 4) {
264  DHCP_BASE_TRACE("Invalid DHCP option " << option << " data : " <<
265  input << "is invalid");
266  return opt_len - option_->GetLen() - option_->GetFixedLen();
267  }
268 
269  // if specified, check that we add in multiples of IP addresses
270  if (multiples && option_->GetLen() % (multiples * 4)) {
271  DHCP_BASE_TRACE("Invalid DHCP option " << option << " data : " <<
272  input << "is invalid");
273  return opt_len - option_->GetLen() - option_->GetFixedLen();
274  }
275 
276  return opt_len;
277 }
278 
279 // Add option taking number of Ipv6 addresses
280 uint16_t DhcpHandlerBase::AddIpv6Option(uint32_t option, uint16_t opt_len,
281  const std::string &input, bool list) {
282  option_->WriteData(option, 0, NULL, &opt_len);
283  std::stringstream value(input);
284  while (value.good()) {
285  std::string ipstr;
286  value >> ipstr;
287  if (!IsValidIpOption(option, ipstr, false)) {
288  return opt_len - option_->GetLen() - option_->GetFixedLen();
289  }
290  opt_len = AddIP(opt_len, ipstr);
291  if (!list) break;
292  }
293 
294  // check that atleast one IP address is added
295  if (option_->GetLen() < 16) {
296  DHCPV6_TRACE(Error, "Invalid DHCP option " << option << " for VM " <<
297  config_.ip_addr.to_string() << "; data missing");
298  return opt_len - option_->GetLen() - option_->GetFixedLen();
299  }
300 
301  return opt_len;
302 }
303 
304 // Add option taking compressed name
306  uint16_t opt_len,
307  const std::string &input,
308  bool list) {
309  option_->WriteData(option, 0, NULL, &opt_len);
310  std::stringstream value(input);
311  while (value.good()) {
312  std::string str;
313  value >> str;
314  if (str.size()) {
315  opt_len = AddCompressedName(opt_len, str);
316  if (!list) break;
317  }
318  }
319 
320  if (!option_->GetLen()) {
321  DHCP_BASE_TRACE("Invalid DHCP option " << option << " data : " <<
322  input << "is invalid");
323  return opt_len - option_->GetLen() - option_->GetFixedLen();
324  }
325 
326  return opt_len;
327 }
328 
329 // Add option taking a byte followed by a compressed name
331  uint16_t opt_len,
332  const std::string &input) {
333  option_->WriteData(option, 0, NULL, &opt_len);
334 
335  std::stringstream value(input);
336  uint32_t data = 0;
337  value >> data;
338  if (value.bad() || value.fail() || data > 0xFF) {
339  DHCP_BASE_TRACE("Invalid DHCP option " << option << " data : " <<
340  input << "is invalid");
341  return opt_len - option_->GetLen() - option_->GetFixedLen();
342  } else {
343  uint8_t byte = (uint8_t)data;
344  option_->WriteData(option, 1, &byte, &opt_len);
345  }
346 
347  std::string str;
348  value >> str;
349  if (value.bad() || value.fail() || !str.size()) {
350  DHCP_BASE_TRACE("Invalid DHCP option " << option << " data : " <<
351  input << "is invalid");
352  return opt_len - option_->GetLen() - option_->GetFixedLen();
353  }
354  return AddCompressedName(opt_len, str);
355 }
356 
357 uint16_t DhcpHandlerBase::AddCompressedName(uint16_t opt_len,
358  const std::string &input) {
359  boost::scoped_array<uint8_t> name(new uint8_t[input.size() * 2 + 2]);
360  uint16_t len = 0;
361  BindUtil::AddName(name.get(), input, 0, 0, len);
362  option_->AppendData(len, name.get(), &opt_len);
363  return opt_len;
364 }
365 
366 // Add an DNS server addresses from IPAM to the option
367 // Option code and len are added already; add only the addresses
368 uint16_t DhcpHandlerBase::AddDnsServers(uint16_t opt_len) {
369  if (ipam_type_.ipam_dns_method == "default-dns-server" ||
370  ipam_type_.ipam_dns_method == "virtual-dns-server" ||
371  ipam_type_.ipam_dns_method == "none" ||
372  ipam_type_.ipam_dns_method == "") {
373  if (!config_.dns_addr.is_unspecified()) {
374  opt_len = AddIP(opt_len, config_.dns_addr.to_string());
375  }
376  } else if (ipam_type_.ipam_dns_method == "tenant-dns-server") {
377  for (unsigned int i = 0; i < ipam_type_.ipam_dns_server.
378  tenant_dns_server_address.ip_address.size(); ++i) {
379  opt_len = AddIP(opt_len, ipam_type_.ipam_dns_server.
380  tenant_dns_server_address.ip_address[i]);
381  }
382  }
383  return opt_len;
384 }
385 
386 // Read the list of <subnet/plen, gw> from input and store them
387 // for later processing in AddClasslessRouteOption
388 void DhcpHandlerBase::ReadClasslessRoute(uint32_t option, uint16_t opt_len,
389  const std::string &input) {
390  std::stringstream value(input);
391  while (value.good()) {
392  std::string snetstr;
393  value >> snetstr;
394  OperDhcpOptions::HostRoute host_route;
395  boost::system::error_code ec = Ip4PrefixParse(snetstr, &host_route.prefix_,
396  (int *)&host_route.plen_);
397  if (ec || host_route.plen_ > 32 || !value.good()) {
398  DHCP_BASE_TRACE("Invalid Classless route DHCP option -"
399  "has to be list of <subnet/plen gw>");
400  break;
401  }
402 
403  value >> snetstr;
404  host_route.gw_ = Ip4Address::from_string(snetstr, ec);
405  if (ec) {
406  host_route.gw_ = Ip4Address();
407  }
408 
409  host_routes_.push_back(host_route);
410  }
411 }
412 
413 // Add host route options coming via config. Config priority is
414 // 1) options at VM interface level (host routes specifically set)
415 // 2) options at VM interface level (classless routes from --extra-dhcp-opts)
416 // 3) options at subnet level (host routes at subnet level - neutron config)
417 // 4) options at subnet level (classless routes from dhcp options)
418 // 5) options at IPAM level (host routes from IPAM)
419 // 6) options at IPAM level (classless routes from IPAM dhcp options)
420 // Add the options defined at the highest level in priority
421 uint16_t DhcpHandlerBase::AddClasslessRouteOption(uint16_t opt_len) {
422  std::vector<OperDhcpOptions::HostRoute> host_routes;
423  do {
424  // Port specific host route options
425  // TODO: should we remove host routes at port level from schema ?
427  host_routes = vm_itf_->oper_dhcp_options().host_routes();
428  break;
429  }
430  // Host routes from port specific DHCP options (neutron configuration)
432  host_routes.swap(host_routes_);
433  break;
434  }
435 
436  if (vm_itf_->vn()) {
437  Ip4Address ip = config_.ip_addr.to_v4();
438  const std::vector<VnIpam> &vn_ipam = vm_itf_->vn()->GetVnIpam();
439  uint32_t index;
440  for (index = 0; index < vn_ipam.size(); ++index) {
441  if (vn_ipam[index].IsSubnetMember(ip)) {
442  break;
443  }
444  }
445  if (index < vn_ipam.size()) {
446  // Subnet level host route options
447  // Preference to host routes at subnet (neutron configuration)
448  if (vn_ipam[index].oper_dhcp_options.are_host_routes_set()) {
449  host_routes = vn_ipam[index].oper_dhcp_options.host_routes();
450  break;
451  }
452  // Host route options from subnet level DHCP options
453  if (host_routes_level_ == SubnetLevel && host_routes_.size()) {
454  host_routes.swap(host_routes_);
455  break;
456  }
457  }
458 
459  // TODO: should remove host routes at VN level from schema ?
460  vm_itf_->vn()->GetVnHostRoutes(ipam_name_, &host_routes);
461  if (host_routes.size() > 0)
462  break;
463  }
464 
465  // IPAM level host route options
466  OperDhcpOptions oper_dhcp_options;
467  oper_dhcp_options.update_host_routes(ipam_type_.host_routes.route);
468  host_routes = oper_dhcp_options.host_routes();
469 
470  // Host route options from IPAM level DHCP options
471  if (!host_routes.size() && host_routes_.size()) {
472  host_routes.swap(host_routes_);
473  break;
474  }
475  } while (false);
476 
477  if (host_routes.size()) {
479  uint8_t *ptr = option_->GetData();
480  uint8_t len = 0;
481  for (uint32_t i = 0; i < host_routes.size(); ++i) {
482  uint32_t prefix = host_routes[i].prefix_.to_ulong();
483  uint32_t plen = host_routes[i].plen_;
484  uint32_t gw = host_routes[i].gw_.to_ulong();
485  *ptr++ = plen;
486  len++;
487  for (unsigned int j = 0; plen && j <= (plen - 1) / 8; ++j) {
488  *ptr++ = (prefix >> 8 * (3 - j)) & 0xFF;
489  len++;
490  }
491  // if GW is not specified, set it to subnet's GW
492  if (gw)
493  *(uint32_t *)ptr = htonl(gw);
494  else
495  *(uint32_t *)ptr = htonl(config_.gw_addr.to_v4().to_ulong());
496  ptr += sizeof(uint32_t);
497  len += sizeof(uint32_t);
498  }
499  option_->SetLen(len);
500  opt_len += 2 + len;
502  }
503  return opt_len;
504 }
505 
507  uint16_t opt_len,
508  std::vector<autogen::DhcpOptionType> &options,
509  DhcpOptionLevel level) {
510  for (unsigned int i = 0; i < options.size(); ++i) {
511  // get the option code
512  uint32_t option = OptionCode(options[i].dhcp_option_name);
513  if (!option) {
514  DHCP_BASE_TRACE("Invalid DHCP option " <<
515  options[i].dhcp_option_name);
516  continue;
517  }
518 
519  // if option is already set in the response (from higher level), ignore
520  if (is_flag_set(option))
521  continue;
522 
523  uint16_t old_opt_len = opt_len;
524  DhcpOptionCategory category = OptionCategory(option);
525  option_->SetNextOptionPtr(opt_len);
526 
527  // if dhcp_option_value_bytes is set, use that for supported categories
528  std::string &opt_value = options[i].dhcp_option_value;
529  if (!options[i].dhcp_option_value_bytes.empty() &&
530  CanOverrideWithBytes(category)) {
531  category = ByteArray;
532  opt_value = options[i].dhcp_option_value_bytes;
533  }
534 
535  switch(category) {
536  case None:
537  break;
538 
539  case NoData:
540  opt_len = AddNoDataOption(option, opt_len);
541  break;
542 
543  case Bool:
544  case Byte:
545  opt_len = AddByteOption(option, opt_len,
546  options[i].dhcp_option_value);
547  break;
548 
549  case ByteArray:
550  opt_len = AddByteArrayOption(option, opt_len, opt_value);
551  break;
552 
553  case ByteString:
554  opt_len = AddByteStringOption(option, opt_len,
555  options[i].dhcp_option_value);
556  break;
557 
558  case ByteOneIPPlus:
559  opt_len = AddByteIPOption(option, opt_len,
560  options[i].dhcp_option_value);
561  break;
562 
563  case String:
564  opt_len = AddStringOption(option, opt_len,
565  options[i].dhcp_option_value);
566  break;
567 
568  case Int32bit:
569  case Uint32bit:
570  if (option == DHCP_OPTION_IP_LEASE_TIME) {
572  }
573  opt_len = AddIntegerOption(option, opt_len,
574  options[i].dhcp_option_value);
575  break;
576 
577  case Uint16bit:
578  opt_len = AddShortArrayOption(option, opt_len,
579  options[i].dhcp_option_value,
580  false);
581  break;
582 
583  case Uint16bitArray:
584  opt_len = AddShortArrayOption(option, opt_len,
585  options[i].dhcp_option_value,
586  true);
587  break;
588 
589  case OneIPv4:
590  opt_len = AddIpv4Option(option, opt_len,
591  options[i].dhcp_option_value, 1, 1, 0);
592  break;
593 
594  case ZeroIPv4Plus:
595  opt_len = AddIpv4Option(option, opt_len,
596  options[i].dhcp_option_value, 0, 0, 0);
597  break;
598 
599  case OneIPv4Plus:
600  if (option == DHCP_OPTION_ROUTER) {
601  // Router option is added later
602  routers_ = options[i].dhcp_option_value;
604  } else {
605  opt_len = AddIpv4Option(option, opt_len,
606  options[i].dhcp_option_value,
607  1, 0, 0);
608  }
609  break;
610 
611  case TwoIPv4Plus:
612  opt_len = AddIpv4Option(option, opt_len,
613  options[i].dhcp_option_value, 2, 0, 2);
614  break;
615 
616  case OneIPv6:
617  opt_len = AddIpv6Option(option, opt_len,
618  options[i].dhcp_option_value,
619  false);
620  break;
621 
622  case OneIPv6Plus:
623  opt_len = AddIpv6Option(option, opt_len,
624  options[i].dhcp_option_value,
625  true);
626  break;
627 
628  case ClasslessRoute:
629  ReadClasslessRoute(option, opt_len,
630  options[i].dhcp_option_value);
631  if (host_routes_.size()) {
632  // set flag & level for classless route so that we dont
633  // update these at other level (subnet or ipam)
635  host_routes_level_ = level;
636  }
637  break;
638 
639  case NameCompression:
640  opt_len = AddCompressedNameOption(option, opt_len,
641  options[i].dhcp_option_value,
642  false);
643  break;
644 
646  opt_len = AddCompressedNameOption(option, opt_len,
647  options[i].dhcp_option_value,
648  true);
649  break;
650 
651  case ByteNameCompression:
652  opt_len = AddByteCompressedNameOption(option, opt_len,
653  options[i].dhcp_option_value);
654  break;
655 
656  default:
657  DHCP_BASE_TRACE("Invalid DHCP option " <<
658  options[i].dhcp_option_name);
659  break;
660  }
661 
662  // store siaddr for tftp server name to apply it later
663  if (option == DHCP_OPTION_TFTP_SERVER_NAME) {
664  boost::system::error_code ec;
665  Ip4Address siaddr =
666  Ip4Address::from_string(options[i].dhcp_option_value, ec);
667  if (ec.value() == 0)
668  siaddr_tftp_ = htonl(siaddr.to_ulong());
669  }
670 
671  if (opt_len != old_opt_len)
672  set_flag(option);
673  }
674 
675  return opt_len;
676 }
677 
678 // Add the option defined at the highest level in priority
679 // Take all options defined at VM interface level, take those from subnet which
680 // are not configured at interface, then take those from ipam which are not
681 // configured at interface or subnet.
682 uint16_t DhcpHandlerBase::AddConfigDhcpOptions(uint16_t opt_len, bool is_v6) {
683  std::vector<autogen::DhcpOptionType> options;
684  if (vm_itf_->GetInterfaceDhcpOptions(&options))
685  opt_len = AddDhcpOptions(opt_len, options, InterfaceLevel);
686 
687  if (vm_itf_->GetSubnetDhcpOptions(&options, is_v6))
688  opt_len = AddDhcpOptions(opt_len, options, SubnetLevel);
689 
690  if (vm_itf_->GetIpamDhcpOptions(&options, is_v6))
691  opt_len = AddDhcpOptions(opt_len, options, IpamLevel);
692 
693  return opt_len;
694 }
695 
697  if (config_.lease_time != (uint32_t) -1 ||
698  config_.valid_time != (uint32_t) -1)
699  return;
700 
701  if (!vm_itf_->vn() ||
702  !vm_itf_->vn()->GetIpamData(vm_addr, &ipam_name_, &ipam_type_)) {
703  DHCP_BASE_TRACE("Ipam data not found");
704  return;
705  }
706 
707  if (ipam_type_.ipam_dns_method != "virtual-dns-server" ||
708  !agent()->domain_config_table()->GetVDns(ipam_type_.ipam_dns_server.
709  virtual_dns_server_name,
710  &vdns_type_))
711  return;
712 
713  if (config_.domain_name_.size() &&
714  config_.domain_name_ != vdns_type_.domain_name) {
715  DHCP_BASE_TRACE("Client domain " << config_.domain_name_ <<
716  " doesnt match with configured domain " <<
717  vdns_type_.domain_name);
718  }
719  std::size_t pos;
720  if (config_.client_name_.size() &&
721  ((pos = config_.client_name_.find('.', 0)) != std::string::npos) &&
722  (config_.client_name_.substr(pos + 1) != vdns_type_.domain_name)) {
723  DHCP_BASE_TRACE("Client domain doesnt match with configured domain "
724  << vdns_type_.domain_name << "; Client name = "
725  << config_.client_name_);
726  config_.client_name_.replace(config_.client_name_.begin() + pos + 1,
727  config_.client_name_.end(),
728  vdns_type_.domain_name);
729  }
730 
731  config_.domain_name_ = vdns_type_.domain_name;
732 }
733 
735  if (category == ByteArray ||
736  category == ByteString ||
737  category == String ||
738  category == NameCompression ||
739  category == NameCompressionArray ||
740  category == ByteNameCompression)
741  return true;
742 
743  return false;
744 }
bool GetIpamDhcpOptions(std::vector< autogen::DhcpOptionType > *options, bool ipv6) const
void ReadClasslessRoute(uint32_t option, uint16_t opt_len, const std::string &input)
bool are_host_routes_set() const
const std::vector< HostRoute > & host_routes() const
uint16_t AddNoDataOption(uint32_t option, uint16_t opt_len)
uint16_t AddByteOption(uint32_t option, uint16_t opt_len, const std::string &input)
bool IsValidIpOption(uint32_t option, const std::string &ipstr, bool is_v4)
virtual uint16_t AddIP(uint16_t opt_len, const std::string &input)=0
void FindDomainName(const IpAddress &vm_addr)
std::string routers_
boost::system::error_code Ip4PrefixParse(const string &str, Ip4Address *addr, int *plen)
Definition: address.cc:107
uint16_t AddConfigDhcpOptions(uint16_t opt_len, bool is_v6)
#define DHCP_OPTION_TFTP_SERVER_NAME
Definition: dhcp_handler.h:82
boost::scoped_ptr< DhcpOptionHandler > option_
bool GetSubnetDhcpOptions(std::vector< autogen::DhcpOptionType > *options, bool ipv6) const
#define DHCP_OPTION_IP_LEASE_TIME
Definition: dhcp_handler.h:67
boost::asio::ip::address IpAddress
Definition: address.h:13
bool GetInterfaceDhcpOptions(std::vector< autogen::DhcpOptionType > *options) const
ConfigRecord config_
uint16_t AddIntegerOption(uint32_t option, uint16_t opt_len, const std::string &input)
#define DHCPV6_OPTION_DNS_SERVERS
std::vector< OperDhcpOptions::HostRoute > host_routes_
Agent * agent() const
Definition: proto_handler.h:80
uint16_t AddCompressedName(uint16_t opt_len, const std::string &input)
#define DHCP_BASE_TRACE(arg)
uint16_t AddByteCompressedNameOption(uint32_t option, uint16_t opt_len, const std::string &input)
#define DHCP_OPTION_DNS
Definition: dhcp_handler.h:22
uint16_t AddDnsServers(uint16_t opt_len)
uint16_t AddClasslessRouteOption(uint16_t opt_len)
bool IsValidDnsOption(uint32_t option, const std::string &ipstr)
Definition: agent.h:358
static Options options
virtual DhcpOptionCategory OptionCategory(uint32_t option) const =0
static uint8_t * AddName(uint8_t *ptr, const std::string &addr, uint16_t plen, uint16_t offset, uint16_t &length)
Definition: bind_util.cc:146
bool GetVnHostRoutes(const std::string &ipam, std::vector< OperDhcpOptions::HostRoute > *routes) const
Definition: vn.cc:620
DhcpOptionLevel host_routes_level_
uint16_t AddCompressedNameOption(uint32_t option, uint16_t opt_len, const std::string &input, bool list)
const OperDhcpOptions & oper_dhcp_options() const
bool CanOverrideWithBytes(DhcpOptionCategory category)
uint16_t AddByteArrayOption(uint32_t option, uint16_t opt_len, const std::string &input)
const std::vector< VnIpam > & GetVnIpam() const
Definition: vn.h:171
const VnEntry * vn() const
uint16_t AddByteIPOption(uint32_t option, uint16_t opt_len, const std::string &input)
uint16_t AddIpv4Option(uint32_t option, uint16_t opt_len, const std::string &input, uint8_t min_count, uint8_t max_count, uint8_t multiples)
boost::asio::ip::address_v4 Ip4Address
Definition: address.h:14
uint16_t AddIpv6Option(uint32_t option, uint16_t opt_len, const std::string &input, bool list)
void update_host_routes(const HostOptionsList &host_routes)
#define DHCPV6_TRACE(obj, arg)
Definition: dhcpv6_proto.h:11
uint16_t AddByteStringOption(uint32_t option, uint16_t opt_len, const std::string &input)
std::string ipam_name_
virtual uint32_t OptionCode(const std::string &option) const =0
DhcpHandlerBase(Agent *agent, boost::shared_ptr< PktInfo > info, boost::asio::io_context &io)
autogen::VirtualDnsType vdns_type_
virtual ~DhcpHandlerBase()
uint16_t AddShortArrayOption(uint32_t option, uint16_t opt_len, const std::string &input, bool array)
uint16_t AddStringOption(uint32_t option, uint16_t opt_len, const std::string &input)
VmInterface * vm_itf_
void set_flag(uint8_t flag)
autogen::IpamType ipam_type_
#define DHCP_OPTION_CLASSLESS_ROUTE
Definition: dhcp_handler.h:127
uint16_t AddDhcpOptions(uint16_t opt_len, std::vector< autogen::DhcpOptionType > &options, DhcpOptionLevel level)
bool is_flag_set(uint8_t flag) const
#define DHCP_OPTION_ROUTER
Definition: dhcp_handler.h:19
bool GetIpamData(const IpAddress &vm_addr, std::string *ipam_name, autogen::IpamType *ipam_type) const
Definition: vn.cc:641