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