OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
dhcpv6_handler.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #ifndef vnsw_agent_dhcpv6_handler_hpp
6 #define vnsw_agent_dhcpv6_handler_hpp
7 
8 #include "dhcp_handler_base.h"
9 
10 #define ALL_DHCPV6_SERVERS_ADDRESS "FF05::1:3"
11 #define ALL_DHCPV6_RELAYAGENTS_SERVERS_ADDRESS "FF05::1:3"
12 
13 // Supported DHCPv6 options
14 #define DHCPV6_OPTION_UNKNOWN 0
15 #define DHCPV6_OPTION_CLIENTID 1
16 #define DHCPV6_OPTION_SERVERID 2
17 #define DHCPV6_OPTION_IA_NA 3
18 #define DHCPV6_OPTION_IA_TA 4
19 #define DHCPV6_OPTION_IAADDR 5
20 #define DHCPV6_OPTION_ORO 6
21 #define DHCPV6_OPTION_PREFERENCE 7
22 #define DHCPV6_OPTION_ELAPSED_TIME 8
23 #define DHCPV6_OPTION_RELAY_MSG 9
24 // Option 10 Unassigned
25 #define DHCPV6_OPTION_AUTH 11
26 #define DHCPV6_OPTION_UNICAST 12
27 #define DHCPV6_OPTION_STATUS_CODE 13
28 #define DHCPV6_OPTION_RAPID_COMMIT 14
29 #define DHCPV6_OPTION_USER_CLASS 15
30 #define DHCPV6_OPTION_VENDOR_CLASS 16
31 #define DHCPV6_OPTION_VENDOR_OPTS 17
32 #define DHCPV6_OPTION_INTERFACE_ID 18
33 #define DHCPV6_OPTION_RECONF_MSG 19
34 #define DHCPV6_OPTION_RECONF_ACCEPT 20
35 #define DHCPV6_OPTION_SIP_SERVER_D 21
36 #define DHCPV6_OPTION_SIP_SERVER_A 22
37 #define DHCPV6_OPTION_DNS_SERVERS 23
38 #define DHCPV6_OPTION_DOMAIN_LIST 24
39 #define DHCPV6_OPTION_IA_PD 25
40 #define DHCPV6_OPTION_IAPREFIX 26
41 #define DHCPV6_OPTION_NIS_SERVERS 27
42 #define DHCPV6_OPTION_NISP_SERVERS 28
43 #define DHCPV6_OPTION_NIS_DOMAIN_NAME 29
44 #define DHCPV6_OPTION_NISP_DOMAIN_NAME 30
45 #define DHCPV6_OPTION_SNTP_SERVERS 31
46 #define DHCPV6_OPTION_INFORMATION_REFRESH_TIME 32
47 #define DHCPV6_OPTION_BCMCS_SERVER_D 33
48 #define DHCPV6_OPTION_BCMCS_SERVER_A 34
49 // Option 35 Unassigned
50 #define DHCPV6_OPTION_GEOCONF_CIVIC 36
51 #define DHCPV6_OPTION_REMOTE_ID 37
52 #define DHCPV6_OPTION_SUBSCRIBER_ID 38
53 #define DHCPV6_OPTION_CLIENT_FQDN 39
54 #define DHCPV6_OPTION_PANA_AGENT 40
55 #define DHCPV6_OPTION_NEW_POSIX_TIMEZONE 41
56 #define DHCPV6_OPTION_NEW_TZDB_TIMEZONE 42
57 #define DHCPV6_OPTION_ERO 43
58 #define DHCPV6_OPTION_LQ_QUERY 44
59 #define DHCPV6_OPTION_CLIENT_DATA 45
60 #define DHCPV6_OPTION_CLT_TIME 46
61 #define DHCPV6_OPTION_LQ_RELAY_DATA 47
62 #define DHCPV6_OPTION_LQ_CLIENT_LINK 48
63 #define DHCPV6_OPTION_MIP6_HNIDF 49
64 #define DHCPV6_OPTION_MIP6_VDINF 50
65 #define DHCPV6_OPTION_V6_LOST 51
66 #define DHCPV6_OPTION_CAPWAP_AC_V6 52
67 #define DHCPV6_OPTION_RELAY_ID 53
68 #define DHCPV6_OPTION_IPv6_Address_MoS 54
69 #define DHCPV6_OPTION_IPv6_FQDN_MoS 55
70 #define DHCPV6_OPTION_NTP_SERVER 56
71 #define DHCPV6_OPTION_V6_ACCESS_DOMAIN 57
72 #define DHCPV6_OPTION_SIP_UA_CS_LIST 58
73 #define DHCPV6_OPT_BOOTFILE_URL 59
74 #define DHCPV6_OPT_BOOTFILE_PARAM 60
75 #define DHCPV6_OPTION_CLIENT_ARCH_TYPE 61
76 #define DHCPV6_OPTION_NII 62
77 #define DHCPV6_OPTION_GEOLOCATION 63
78 #define DHCPV6_OPTION_AFTR_NAME 64
79 #define DHCPV6_OPTION_ERP_LOCAL_DOMAIN_NAME 65
80 #define DHCPV6_OPTION_RSOO 66
81 #define DHCPV6_OPTION_PD_EXCLUDE 67
82 #define DHCPV6_OPTION_VSS 68
83 #define DHCPV6_OPTION_MIP6_IDINF 69
84 #define DHCPV6_OPTION_MIP6_UDINF 70
85 #define DHCPV6_OPTION_MIP6_HNP 71
86 #define DHCPV6_OPTION_MIP6_HAA 72
87 #define DHCPV6_OPTION_MIP6_HAF 73
88 #define DHCPV6_OPTION_RDNSS_SELECTION 74
89 #define DHCPV6_OPTION_KRB_PRINCIPAL_NAME 75
90 #define DHCPV6_OPTION_KRB_REALM_NAME 76
91 #define DHCPV6_OPTION_KRB_DEFAULT_REALM_NAME 77
92 #define DHCPV6_OPTION_KRB_KDC 78
93 #define DHCPV6_OPTION_CLIENT_LINKLAYER_ADDR 79
94 #define DHCPV6_OPTION_LINK_ADDRESS 80
95 #define DHCPV6_OPTION_RADIUS 81
96 #define DHCPV6_OPTION_SOL_MAX_RT 82
97 #define DHCPV6_OPTION_INF_MAX_RT 83
98 #define DHCPV6_OPTION_ADDRSEL 84
99 #define DHCPV6_OPTION_ADDRSEL_TABLE 85
100 #define DHCPV6_OPTION_V6_PCP_SERVER 86
101 #define DHCPV6_OPTION_DHCPV4_MSG 87
102 #define DHCPV6_OPTION_DHCP4_O_DHCP6_SERVER 88
103 #define DHCPV6_OPTION_S46_RULE 89
104 #define DHCPV6_OPTION_S46_BR 90
105 #define DHCPV6_OPTION_S46_DMR 91
106 #define DHCPV6_OPTION_S46_V4V6BIND 92
107 #define DHCPV6_OPTION_S46_PORTPARAMS 93
108 #define DHCPV6_OPTION_S46_CONT_MAPE 94
109 #define DHCPV6_OPTION_S46_CONT_MAPT 95
110 #define DHCPV6_OPTION_S46_CONT_LW 96
111 // options 97-142 Unassigned
112 #define DHCPV6_OPTION_IPv6_ADDRESS_ANDSF 143
113 
114 // DHCPv6 message types
115 #define DHCPV6_UNKNOWN 0
116 #define DHCPV6_SOLICIT 1
117 #define DHCPV6_ADVERTISE 2
118 #define DHCPV6_REQUEST 3
119 #define DHCPV6_CONFIRM 4
120 #define DHCPV6_RENEW 5
121 #define DHCPV6_REBIND 6
122 #define DHCPV6_REPLY 7
123 #define DHCPV6_RELEASE 8
124 #define DHCPV6_DECLINE 9
125 #define DHCPV6_RECONFIGURE 10
126 #define DHCPV6_INFORMATION_REQUEST 11
127 
128 // DHCPv6 status codes
129 #define DHCPV6_SUCCESS 0
130 #define DHCPV6_UNSPEC_FAIL 1
131 #define DHCPV6_NO_ADDRS_AVAIL 2
132 #define DHCPV6_NO_BINDING 3
133 #define DHCPV6_NOT_ON_LINK 4
134 #define DHCPV6_USE_MULTICAST 5
135 
136 #define DHCPV6_SHORTLEASE_TIME 4
137 #define DHCP_PKT_SIZE 1024
138 #define MAX_DOMAIN_NAME_LENGTH 256
139 
140 // fixed length = sizeof(type) + sizeof(xid)
141 #define DHCPV6_FIXED_LEN 4
142 
144  void WriteData(uint16_t c, uint16_t l, const void *d, uint16_t *optlen) {
145  code = htons(c);
146  len = htons(l);
147  memcpy(data, (uint8_t *)d, l);
148  *optlen += 4 + l;
149  }
150  void AppendData(uint16_t l, const void *d, uint16_t *optlen) {
151  uint16_t curr_len = ntohs(len);
152  memcpy(data + curr_len, (uint8_t *)d, l);
153  len = htons(curr_len + l);
154  *optlen += l;
155  }
156  void AddLen(uint16_t l) {
157  len = htons(ntohs(len) + l);
158  }
159  uint16_t GetLen() const { return ntohs(len); }
161  uint8_t *next = reinterpret_cast<uint8_t *>(this);
162  return reinterpret_cast<Dhcpv6Options *>(next + ntohs(len) + 4);
163  }
164 
165  uint16_t code;
166  uint16_t len;
167  uint8_t data[0];
168 };
169 
170 struct Dhcpv6Hdr {
171  uint8_t type;
172  uint8_t xid[3];
173  // followed by options
174 };
175 
176 struct Dhcpv6Ia {
177  void Assign(Dhcpv6Ia *ptr) {
178  iaid = ptr->iaid;
179  t1 = ptr->t1;
180  t2 = ptr->t2;
181  }
182 
183  uint32_t iaid;
184  uint32_t t1;
185  uint32_t t2;
186  // followed by options
187 };
188 
189 struct Dhcpv6IaAddr {
191  if (ptr) {
192  memcpy(address, ptr->address, 16);
195  } else {
196  memset(address, 0, 16);
197  preferred_lifetime = 0;
198  valid_lifetime = 0;
199  }
200  }
201  Dhcpv6IaAddr(uint8_t *addr, uint32_t pl, uint32_t vl) {
202  memcpy(address, addr, 16);
203  preferred_lifetime = htonl(pl);
204  valid_lifetime = htonl(vl);
205  }
206 
207  uint8_t address[16];
209  uint32_t valid_lifetime;
210  // followed by options
211 };
212 
213 // DHCP protocol handler
215 public:
216  typedef boost::scoped_array<uint8_t> Duid;
217 
218  struct Dhcpv6IaData {
219  void AddIa(Dhcpv6Ia *ia_ptr) {
220  ia.Assign(ia_ptr);
221  }
222  void AddIaAddr(Dhcpv6IaAddr *ia_addr_ptr) {
223  ia_addr.push_back(Dhcpv6IaAddr(ia_addr_ptr));
224  }
225  bool DelIaAddr(const Dhcpv6IaAddr &addr) {
226  for (std::vector<Dhcpv6IaAddr>::iterator it = ia_addr.begin();
227  it != ia_addr.end(); ++it) {
228  if (memcmp(it->address, addr.address, 16) == 0) {
229  ia_addr.erase(it);
230  return true;
231  }
232  }
233  return false;
234  }
235 
237  std::vector<Dhcpv6IaAddr> ia_addr;
238  };
239 
241  static const uint16_t kDhcpOptionFixedLen = 4;
242 
243  explicit Dhcpv6OptionHandler(uint8_t *ptr) { dhcp_option_ptr = ptr; }
244  void WriteData(uint8_t c, uint8_t l, const void *d, uint16_t *optlen) {
245  option->WriteData(c, l, d, optlen);
246  }
247  void AppendData(uint16_t l, const void *d, uint16_t *optlen) {
248  option->AppendData(l, d, optlen);
249  }
250  uint16_t GetCode() const { return ntohs(option->code); }
251  uint16_t GetLen() const { return ntohs(option->len); }
252  uint16_t GetFixedLen() const { return kDhcpOptionFixedLen; }
253  uint8_t *GetData() { return option->data; }
254  void SetCode(uint16_t c) { option->code = htons(c); }
255  void SetLen(uint16_t l) { option->len = htons(l); }
256  void AddLen(uint16_t l) { option->AddLen(l); }
257  void SetNextOptionPtr(uint16_t optlen) {
258  option = (Dhcpv6Options *)(dhcp_option_ptr + optlen);
259  }
260  void SetDhcpOptionPtr(uint8_t *ptr) { dhcp_option_ptr = ptr; }
261 
262  uint8_t *dhcp_option_ptr; // pointer to DHCP options in the packet
263  Dhcpv6Options *option; // pointer to current option being processed
264  };
265 
266  Dhcpv6Handler(Agent *agent, boost::shared_ptr<PktInfo> info,
267  boost::asio::io_context &io);
268  virtual ~Dhcpv6Handler();
269 
270  bool Run();
271 
272 private:
273  void ReadOptions(int16_t opt_rem_len);
274  bool ReadIA(uint8_t *ptr, uint16_t len, uint16_t code);
275  void FillDhcpInfo(Ip6Address &addr, int plen,
276  Ip6Address &gw, Ip6Address &dns);
277  bool FindLeaseData();
278  uint16_t AddIP(uint16_t opt_len, const std::string &input);
279  uint16_t AddDomainNameOption(uint16_t opt_len);
280  uint16_t FillDhcpv6Hdr();
281  Ip6Address GetNextV6Address(uint8_t addr[]);
282  void IncrementByteInAddress(Ip6Address::bytes_type &bytes, uint8_t index);
283  void WriteIaOption(uint16_t &optlen);
284  uint16_t FillDhcpResponse(const MacAddress &dest_mac,
285  Ip6Address src_ip, Ip6Address dest_ip);
286  void SendDhcpResponse();
287  void UpdateStats();
288  DhcpOptionCategory OptionCategory(uint32_t option) const;
289  uint32_t OptionCode(const std::string &option) const;
290  void DhcpTrace(const std::string &msg) const;
291  Dhcpv6Options *GetNextOptionPtr(uint16_t optlen) {
292  return reinterpret_cast<Dhcpv6Options *>(
293  (uint8_t *)dhcp_ + DHCPV6_FIXED_LEN + optlen);
294  }
295 
297 
298  uint8_t msg_type_;
299  uint8_t out_msg_type_;
300  uint8_t xid_[3];
301 
302  // data from the incoming dhcp message
307  Duid client_duid_; // client duid
308  Duid server_duid_; // server duid received in the request
309  bool is_ia_na_; // true if ia_na, false if ia_ta
310  boost::scoped_ptr<Dhcpv6IaData> ia_na_;
311 
313 };
314 
315 typedef std::map<std::string, uint32_t> Dhcpv6NameCodeMap;
316 typedef std::map<std::string, uint32_t>::const_iterator Dhcpv6NameCodeIter;
317 typedef std::map<uint32_t, Dhcpv6Handler::DhcpOptionCategory> Dhcpv6CategoryMap;
318 typedef std::map<uint32_t, Dhcpv6Handler::DhcpOptionCategory>::const_iterator Dhcpv6CategoryIter;
319 
320 #endif // vnsw_agent_dhcpv6_handler_hpp
std::map< std::string, uint32_t >::const_iterator Dhcpv6NameCodeIter
void AddIa(Dhcpv6Ia *ia_ptr)
void AppendData(uint16_t l, const void *d, uint16_t *optlen)
uint8_t xid[3]
uint32_t t1
void IncrementByteInAddress(Ip6Address::bytes_type &bytes, uint8_t index)
uint32_t OptionCode(const std::string &option) const
bool ReadIA(uint8_t *ptr, uint16_t len, uint16_t code)
void WriteData(uint16_t c, uint16_t l, const void *d, uint16_t *optlen)
Ip6Address GetNextV6Address(uint8_t addr[])
boost::scoped_array< uint8_t > Duid
uint8_t address[16]
void AddLen(uint16_t l)
uint16_t server_duid_len_
boost::scoped_ptr< Dhcpv6IaData > ia_na_
uint16_t AddIP(uint16_t opt_len, const std::string &input)
uint8_t out_msg_type_
Agent * agent() const
Definition: proto_handler.h:80
uint32_t iaid
std::map< std::string, uint32_t > Dhcpv6NameCodeMap
Definition: agent.h:358
uint16_t FillDhcpResponse(const MacAddress &dest_mac, Ip6Address src_ip, Ip6Address dest_ip)
uint8_t data[0]
uint32_t preferred_lifetime
boost::asio::ip::address_v6 Ip6Address
Definition: address.h:15
void SetNextOptionPtr(uint16_t optlen)
uint8_t type
uint16_t client_duid_len_
Dhcpv6Hdr * dhcp_
std::map< uint32_t, Dhcpv6Handler::DhcpOptionCategory > Dhcpv6CategoryMap
uint16_t AddDomainNameOption(uint16_t opt_len)
void SendDhcpResponse()
void WriteIaOption(uint16_t &optlen)
uint32_t t2
static const uint16_t kDhcpOptionFixedLen
DhcpOptionCategory OptionCategory(uint32_t option) const
std::vector< Dhcpv6IaAddr > ia_addr
void WriteData(uint8_t c, uint8_t l, const void *d, uint16_t *optlen)
uint32_t valid_lifetime
void AppendData(uint16_t l, const void *d, uint16_t *optlen)
void AddIaAddr(Dhcpv6IaAddr *ia_addr_ptr)
Dhcpv6IaAddr(uint8_t *addr, uint32_t pl, uint32_t vl)
std::map< uint32_t, Dhcpv6Handler::DhcpOptionCategory >::const_iterator Dhcpv6CategoryIter
Dhcpv6Options * GetNextOptionPtr()
bool DelIaAddr(const Dhcpv6IaAddr &addr)
uint16_t GetLen() const
Dhcpv6IaAddr(Dhcpv6IaAddr *ptr)
Dhcpv6Handler(Agent *agent, boost::shared_ptr< PktInfo > info, boost::asio::io_context &io)
#define DHCPV6_FIXED_LEN
Dhcpv6Options * GetNextOptionPtr(uint16_t optlen)
void Assign(Dhcpv6Ia *ptr)
virtual ~Dhcpv6Handler()
void DhcpTrace(const std::string &msg) const
DISALLOW_COPY_AND_ASSIGN(Dhcpv6Handler)
void FillDhcpInfo(Ip6Address &addr, int plen, Ip6Address &gw, Ip6Address &dns)
uint16_t FillDhcpv6Hdr()
void ReadOptions(int16_t opt_rem_len)
uint8_t xid_[3]