Line data Source code
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 : 143 : struct Dhcpv6Options { 144 0 : void WriteData(uint16_t c, uint16_t l, const void *d, uint16_t *optlen) { 145 0 : code = htons(c); 146 0 : len = htons(l); 147 0 : memcpy(data, (uint8_t *)d, l); 148 0 : *optlen += 4 + l; 149 0 : } 150 0 : void AppendData(uint16_t l, const void *d, uint16_t *optlen) { 151 0 : uint16_t curr_len = ntohs(len); 152 0 : memcpy(data + curr_len, (uint8_t *)d, l); 153 0 : len = htons(curr_len + l); 154 0 : *optlen += l; 155 0 : } 156 0 : void AddLen(uint16_t l) { 157 0 : len = htons(ntohs(len) + l); 158 0 : } 159 : uint16_t GetLen() const { return ntohs(len); } 160 : Dhcpv6Options *GetNextOptionPtr() { 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 0 : void Assign(Dhcpv6Ia *ptr) { 178 0 : iaid = ptr->iaid; 179 0 : t1 = ptr->t1; 180 0 : t2 = ptr->t2; 181 0 : } 182 : 183 : uint32_t iaid; 184 : uint32_t t1; 185 : uint32_t t2; 186 : // followed by options 187 : }; 188 : 189 : struct Dhcpv6IaAddr { 190 0 : Dhcpv6IaAddr(Dhcpv6IaAddr *ptr) { 191 0 : if (ptr) { 192 0 : memcpy(address, ptr->address, 16); 193 0 : preferred_lifetime = ptr->preferred_lifetime; 194 0 : valid_lifetime = ptr->valid_lifetime; 195 : } else { 196 0 : memset(address, 0, 16); 197 0 : preferred_lifetime = 0; 198 0 : valid_lifetime = 0; 199 : } 200 0 : } 201 0 : Dhcpv6IaAddr(uint8_t *addr, uint32_t pl, uint32_t vl) { 202 0 : memcpy(address, addr, 16); 203 0 : preferred_lifetime = htonl(pl); 204 0 : valid_lifetime = htonl(vl); 205 0 : } 206 : 207 : uint8_t address[16]; 208 : uint32_t preferred_lifetime; 209 : uint32_t valid_lifetime; 210 : // followed by options 211 : }; 212 : 213 : // DHCP protocol handler 214 : class Dhcpv6Handler : public DhcpHandlerBase { 215 : public: 216 : typedef boost::scoped_array<uint8_t> Duid; 217 : 218 : struct Dhcpv6IaData { 219 0 : void AddIa(Dhcpv6Ia *ia_ptr) { 220 0 : ia.Assign(ia_ptr); 221 0 : } 222 0 : void AddIaAddr(Dhcpv6IaAddr *ia_addr_ptr) { 223 0 : ia_addr.push_back(Dhcpv6IaAddr(ia_addr_ptr)); 224 0 : } 225 0 : bool DelIaAddr(const Dhcpv6IaAddr &addr) { 226 0 : for (std::vector<Dhcpv6IaAddr>::iterator it = ia_addr.begin(); 227 0 : it != ia_addr.end(); ++it) { 228 0 : if (memcmp(it->address, addr.address, 16) == 0) { 229 0 : ia_addr.erase(it); 230 0 : return true; 231 : } 232 : } 233 0 : return false; 234 : } 235 : 236 : Dhcpv6Ia ia; 237 : std::vector<Dhcpv6IaAddr> ia_addr; 238 : }; 239 : 240 : struct Dhcpv6OptionHandler : DhcpOptionHandler { 241 : static const uint16_t kDhcpOptionFixedLen = 4; 242 : 243 0 : explicit Dhcpv6OptionHandler(uint8_t *ptr) { dhcp_option_ptr = ptr; } 244 0 : void WriteData(uint8_t c, uint8_t l, const void *d, uint16_t *optlen) { 245 0 : option->WriteData(c, l, d, optlen); 246 0 : } 247 0 : void AppendData(uint16_t l, const void *d, uint16_t *optlen) { 248 0 : option->AppendData(l, d, optlen); 249 0 : } 250 0 : uint16_t GetCode() const { return ntohs(option->code); } 251 0 : uint16_t GetLen() const { return ntohs(option->len); } 252 0 : uint16_t GetFixedLen() const { return kDhcpOptionFixedLen; } 253 0 : uint8_t *GetData() { return option->data; } 254 0 : void SetCode(uint16_t c) { option->code = htons(c); } 255 0 : void SetLen(uint16_t l) { option->len = htons(l); } 256 0 : void AddLen(uint16_t l) { option->AddLen(l); } 257 0 : void SetNextOptionPtr(uint16_t optlen) { 258 0 : option = (Dhcpv6Options *)(dhcp_option_ptr + optlen); 259 0 : } 260 0 : 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 0 : Dhcpv6Options *GetNextOptionPtr(uint16_t optlen) { 292 : return reinterpret_cast<Dhcpv6Options *>( 293 0 : (uint8_t *)dhcp_ + DHCPV6_FIXED_LEN + optlen); 294 : } 295 : 296 : Dhcpv6Hdr *dhcp_; 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 303 : bool rapid_commit_; 304 : bool reconfig_accept_; 305 : uint16_t client_duid_len_; 306 : uint16_t server_duid_len_; 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 : 312 : DISALLOW_COPY_AND_ASSIGN(Dhcpv6Handler); 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