1 /** 2 * Copyright (C) 2012-2014 Steven Barth <steven@midlink.org> 3 * Copyright (C) 2018 Hans Dedecker <dedeckeh@gmail.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License v2 as published by 7 * the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 */ 15 16 #ifndef _ODHCP6C_H_ 17 #define _ODHCP6C_H_ 18 19 #include <netinet/in.h> 20 #include <stdbool.h> 21 #include <stdint.h> 22 23 #define _unused __attribute__((unused)) 24 #define _packed __attribute__((packed)) 25 #define _aligned(n) __attribute__((aligned(n))) 26 27 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) 28 29 #define ND_OPT_RECURSIVE_DNS 25 30 #define ND_OPT_DNSSL 31 31 32 #define DHCPV6_MAX_DELAY 1 33 #define DHCPV6_IRT_DEFAULT 86400 34 #define DHCPV6_IRT_MIN 600 35 #define DHCPV6_RAND_FACTOR 100 36 37 #define DHCPV6_SOL_INIT_RT 1 38 #define DHCPV6_SOL_MAX_RT 120 39 40 #define DHCPV6_REQ_INIT_RT 1 41 #define DHCPV6_REQ_MAX_RT 30 42 #define DHCPV6_REQ_MAX_RC 10 43 44 #define DHCPV6_REN_INIT_RT 10 45 #define DHCPV6_REN_MAX_RT 600 46 47 #define DHCPV6_REB_INIT_RT 10 48 #define DHCPV6_REB_MAX_RT 600 49 50 #define DHCPV6_INF_INIT_RT 1 51 #define DHCPV6_INF_MAX_RT 3600 52 53 #define DHCPV6_REL_INIT_RT 1 54 #define DHCPV6_REL_MAX_RC 4 55 56 #define DHCPV6_DEC_INIT_RT 1 57 #define DHCPV6_DEC_MAX_RC 4 58 59 #define RA_MIN_ADV_INTERVAL 3 /* RFC 4861 paragraph 6.2.1 */ 60 61 enum dhcvp6_opt { 62 DHCPV6_OPT_CLIENTID = 1, 63 DHCPV6_OPT_SERVERID = 2, 64 DHCPV6_OPT_IA_NA = 3, 65 DHCPV6_OPT_IA_TA = 4, 66 DHCPV6_OPT_IA_ADDR = 5, 67 DHCPV6_OPT_ORO = 6, 68 DHCPV6_OPT_PREF = 7, 69 DHCPV6_OPT_ELAPSED = 8, 70 DHCPV6_OPT_RELAY_MSG = 9, 71 DHCPV6_OPT_AUTH = 11, 72 DHCPV6_OPT_UNICAST = 12, 73 DHCPV6_OPT_STATUS = 13, 74 DHCPV6_OPT_RAPID_COMMIT = 14, 75 DHCPV6_OPT_USER_CLASS = 15, 76 DHCPV6_OPT_VENDOR_CLASS = 16, 77 DHCPV6_OPT_INTERFACE_ID = 18, 78 DHCPV6_OPT_RECONF_MESSAGE = 19, 79 DHCPV6_OPT_RECONF_ACCEPT = 20, 80 DHCPV6_OPT_SIP_SERVER_D = 21, 81 DHCPV6_OPT_SIP_SERVER_A = 22, 82 DHCPV6_OPT_DNS_SERVERS = 23, 83 DHCPV6_OPT_DNS_DOMAIN = 24, 84 DHCPV6_OPT_IA_PD = 25, 85 DHCPV6_OPT_IA_PREFIX = 26, 86 DHCPV6_OPT_SNTP_SERVERS = 31, 87 DHCPV6_OPT_INFO_REFRESH = 32, 88 DHCPV6_OPT_REMOTE_ID = 37, 89 DHCPV6_OPT_SUBSCRIBER_ID = 38, 90 DHCPV6_OPT_FQDN = 39, 91 DHCPV6_OPT_ERO = 43, 92 DHCPV6_OPT_LQ_QUERY = 44, 93 DHCPV6_OPT_CLIENT_DATA = 45, 94 DHCPV6_OPT_CLT_TIME = 46, 95 DHCPV6_OPT_LQ_RELAY_DATA = 47, 96 DHCPV6_OPT_LQ_CLIENT_LINK = 48, 97 DHCPV6_OPT_RELAY_ID = 53, 98 DHCPV6_OPT_NTP_SERVER = 56, 99 DHCPV6_OPT_CLIENT_ARCH_TYPE = 61, 100 DHCPV6_OPT_AFTR_NAME = 64, 101 DHCPV6_OPT_RSOO = 66, 102 DHCPV6_OPT_PD_EXCLUDE = 67, 103 DHCPV6_OPT_VSS = 68, 104 DHCPV6_OPT_LINK_LAYER_ADDRESS = 79, 105 DHCPV6_OPT_LINK_ADDRESS = 80, 106 DHCPV6_OPT_RADIUS = 81, 107 DHCPV6_OPT_SOL_MAX_RT = 82, 108 DHCPV6_OPT_INF_MAX_RT = 83, 109 #ifdef EXT_CER_ID 110 /* draft-donley-dhc-cer-id-option-03 */ 111 DHCPV6_OPT_CER_ID = EXT_CER_ID, 112 #endif 113 DHCPV6_OPT_DHCPV4_MSG = 87, 114 /* RFC 7598 */ 115 DHCPV6_OPT_S46_RULE = 89, 116 DHCPV6_OPT_S46_BR = 90, 117 DHCPV6_OPT_S46_DMR = 91, 118 DHCPV6_OPT_S46_V4V6BIND = 92, 119 DHCPV6_OPT_S46_PORTPARAMS = 93, 120 DHCPV6_OPT_S46_CONT_MAPE = 94, 121 DHCPV6_OPT_S46_CONT_MAPT = 95, 122 DHCPV6_OPT_S46_CONT_LW = 96, 123 DHCPV6_OPT_LQ_BASE_TIME = 100, 124 DHCPV6_OPT_LQ_START_TIME = 101, 125 DHCPV6_OPT_LQ_END_TIME = 102, 126 DHCPV6_OPT_ANI_ATT = 105, 127 DHCPV6_OPT_ANI_NETWORK_NAME = 106, 128 DHCPV6_OPT_ANI_AP_NAME = 107, 129 DHCPV6_OPT_ANI_AP_BSSID = 108, 130 DHCPV6_OPT_ANI_OPERATOR_ID = 109, 131 DHCPV6_OPT_ANI_OPERATOR_REALM = 110, 132 DHCPV6_OPT_MUD_URL_V6 = 112, 133 DHCPV6_OPT_F_BINDING_STATUS = 114, 134 DHCPV6_OPT_F_CONNECT_FLAGS = 115, 135 DHCPV6_OPT_F_DNS_REMOVAL_INFO = 116, 136 DHCPV6_OPT_F_DNS_HOST_NAME = 117, 137 DHCPV6_OPT_F_DNS_ZONE_NAME = 118, 138 DHCPV6_OPT_F_DNS_FLAGS = 119, 139 DHCPV6_OPT_F_EXPIRATION_TIME = 120, 140 DHCPV6_OPT_F_MAX_UNACKED_BNDUPD = 121, 141 DHCPV6_OPT_F_MCLT = 122, 142 DHCPV6_OPT_F_PARTNER_LIFETIME = 123, 143 DHCPV6_OPT_F_PARTNER_LIFETIME_SENT = 124, 144 DHCPV6_OPT_F_PARTNER_DOWN_TIME = 125, 145 DHCPV6_OPT_F_PARTNER_RAW_CLT_TIME = 126, 146 DHCPV6_OPT_F_PROTOCOL_VERSION = 127, 147 DHCPV6_OPT_F_KEEPALIVE_TIME = 128, 148 DHCPV6_OPT_F_RECONFIGURE_DATA = 129, 149 DHCPV6_OPT_F_RELATIONSHIP_NAME = 130, 150 DHCPV6_OPT_F_SERVER_FLAGS = 131, 151 DHCPV6_OPT_F_SERVER_STATE = 132, 152 DHCPV6_OPT_F_START_TIME_OF_STATE = 133, 153 DHCPV6_OPT_F_STATE_EXPIRATION_TIME = 134, 154 DHCPV6_OPT_RELAY_PORT = 135, 155 }; 156 157 enum dhcpv6_opt_npt { 158 NTP_SRV_ADDR = 1, 159 NTP_MC_ADDR = 2, 160 NTP_SRV_FQDN = 3 161 }; 162 163 enum dhcpv6_msg { 164 DHCPV6_MSG_UNKNOWN = 0, 165 DHCPV6_MSG_SOLICIT = 1, 166 DHCPV6_MSG_ADVERT = 2, 167 DHCPV6_MSG_REQUEST = 3, 168 DHCPV6_MSG_RENEW = 5, 169 DHCPV6_MSG_REBIND = 6, 170 DHCPV6_MSG_REPLY = 7, 171 DHCPV6_MSG_RELEASE = 8, 172 DHCPV6_MSG_DECLINE = 9, 173 DHCPV6_MSG_RECONF = 10, 174 DHCPV6_MSG_INFO_REQ = 11, 175 _DHCPV6_MSG_MAX 176 }; 177 178 enum dhcpv6_state { 179 DHCPV6_INIT, 180 DHCPV6_SOLICIT, 181 DHCPV6_SOLICIT_PROCESSING, 182 DHCPV6_ADVERT, 183 DHCPV6_REQUEST, 184 DHCPV6_REQUEST_PROCESSING, 185 DHCPV6_REPLY, 186 DHCPV6_BOUND, 187 DHCPV6_BOUND_PROCESSING, 188 DHCPV6_BOUND_REPLY, 189 DHCPV6_RECONF, 190 DHCPV6_RECONF_PROCESSING, 191 DHCPV6_RECONF_REPLY, 192 DHCPV6_RENEW, 193 DHCPV6_RENEW_PROCESSING, 194 DHCPV6_RENEW_REPLY, 195 DHCPV6_REBIND, 196 DHCPV6_REBIND_PROCESSING, 197 DHCPV6_REBIND_REPLY, 198 DHCPV6_INFO, 199 DHCPV6_INFO_PROCESSING, 200 DHCPV6_INFO_REPLY, 201 DHCPV6_EXIT, 202 DHCPV6_RESET 203 }; 204 205 enum dhcpv6_status { 206 DHCPV6_Success = 0, 207 DHCPV6_UnspecFail = 1, 208 DHCPV6_NoAddrsAvail = 2, 209 DHCPV6_NoBinding = 3, 210 DHCPV6_NotOnLink = 4, 211 DHCPV6_UseMulticast = 5, 212 DHCPV6_NoPrefixAvail = 6, 213 _DHCPV6_Status_Max 214 }; 215 216 enum dhcpv6_config { 217 DHCPV6_STRICT_OPTIONS = 1, 218 DHCPV6_CLIENT_FQDN = 2, 219 DHCPV6_ACCEPT_RECONFIGURE = 4, 220 DHCPV6_IGNORE_OPT_UNICAST = 8, 221 }; 222 223 typedef int(reply_handler)(enum dhcpv6_msg orig, const int rc, 224 const void *opt, const void *end, const struct sockaddr_in6 *from); 225 226 // retransmission strategy 227 struct dhcpv6_retx { 228 uint8_t max_delay; 229 uint8_t init_timeo; 230 uint16_t max_timeo; 231 uint8_t max_rc; 232 char name[8]; 233 reply_handler *handler_reply; 234 int(*handler_finish)(void); 235 bool is_retransmit; 236 uint64_t timeout; 237 uint8_t rc; 238 uint64_t start; 239 uint8_t tr_id[3]; 240 int64_t rto; 241 uint64_t round_start; 242 uint64_t round_end; 243 int reply_ret; 244 uint64_t delay_msec; 245 }; 246 247 // DHCPv6 Protocol Headers 248 struct dhcpv6_header { 249 uint8_t msg_type; 250 uint8_t tr_id[3]; 251 } __attribute__((packed)); 252 253 struct dhcpv6_ia_hdr { 254 uint16_t type; 255 uint16_t len; 256 uint32_t iaid; 257 uint32_t t1; 258 uint32_t t2; 259 } _packed; 260 261 struct dhcpv6_ia_addr { 262 uint16_t type; 263 uint16_t len; 264 struct in6_addr addr; 265 uint32_t preferred; 266 uint32_t valid; 267 } _packed; 268 269 struct dhcpv6_ia_prefix { 270 uint16_t type; 271 uint16_t len; 272 uint32_t preferred; 273 uint32_t valid; 274 uint8_t prefix; 275 struct in6_addr addr; 276 } _packed; 277 278 struct dhcpv6_duid { 279 uint16_t type; 280 uint16_t len; 281 uint16_t duid_type; 282 uint8_t data[128]; 283 } _packed; 284 285 struct dhcpv6_auth { 286 uint16_t type; 287 uint16_t len; 288 uint8_t protocol; 289 uint8_t algorithm; 290 uint8_t rdm; 291 uint64_t replay; 292 uint8_t data[]; 293 } _packed; 294 295 struct dhcpv6_auth_reconfigure { 296 uint8_t reconf_type; 297 uint8_t key[16]; 298 } _packed; 299 300 struct dhcpv6_cer_id { 301 uint16_t type; 302 uint16_t len; 303 struct in6_addr addr; 304 } _packed; 305 306 struct dhcpv6_s46_portparams { 307 uint8_t offset; 308 uint8_t psid_len; 309 uint16_t psid; 310 } _packed; 311 312 struct dhcpv6_s46_v4v6bind { 313 struct in_addr ipv4_address; 314 uint8_t bindprefix6_len; 315 uint8_t bind_ipv6_prefix[]; 316 } _packed; 317 318 struct dhcpv6_s46_dmr { 319 uint8_t dmr_prefix6_len; 320 uint8_t dmr_ipv6_prefix[]; 321 } _packed; 322 323 struct dhcpv6_s46_rule { 324 uint8_t flags; 325 uint8_t ea_len; 326 uint8_t prefix4_len; 327 struct in_addr ipv4_prefix; 328 uint8_t prefix6_len; 329 uint8_t ipv6_prefix[]; 330 } _packed; 331 332 #define dhcpv6_for_each_option(start, end, otype, olen, odata)\ 333 for (uint8_t *_o = (uint8_t*)(start); _o + 4 <= (uint8_t*)(end) &&\ 334 ((otype) = _o[0] << 8 | _o[1]) && ((odata) = (void*)&_o[4]) &&\ 335 ((olen) = _o[2] << 8 | _o[3]) + (odata) <= (uint8_t*)(end); \ 336 _o += 4 + (_o[2] << 8 | _o[3])) 337 338 339 struct dhcpv6_server_cand { 340 bool has_noaddravail; 341 bool wants_reconfigure; 342 int16_t preference; 343 uint8_t duid_len; 344 uint8_t duid[130]; 345 struct in6_addr server_addr; 346 uint32_t sol_max_rt; 347 uint32_t inf_max_rt; 348 void *ia_na; 349 void *ia_pd; 350 size_t ia_na_len; 351 size_t ia_pd_len; 352 }; 353 354 struct dhcpv6_stats { 355 uint64_t solicit; 356 uint64_t advertise; 357 uint64_t request; 358 uint64_t confirm; 359 uint64_t renew; 360 uint64_t rebind; 361 uint64_t reply; 362 uint64_t release; 363 uint64_t decline; 364 uint64_t reconfigure; 365 uint64_t information_request; 366 uint64_t discarded_packets; 367 uint64_t transmit_failures; 368 }; 369 370 enum odhcp6c_state { 371 STATE_CLIENT_ID, 372 STATE_SERVER_ID, 373 STATE_SERVER_CAND, 374 STATE_SERVER_ADDR, 375 STATE_ORO, 376 STATE_DNS, 377 STATE_SEARCH, 378 STATE_IA_NA, 379 STATE_IA_PD, 380 STATE_IA_PD_INIT, 381 STATE_CUSTOM_OPTS, 382 STATE_SNTP_IP, 383 STATE_NTP_IP, 384 STATE_NTP_FQDN, 385 STATE_SIP_IP, 386 STATE_SIP_FQDN, 387 STATE_RA_ROUTE, 388 STATE_RA_PREFIX, 389 STATE_RA_DNS, 390 STATE_RA_SEARCH, 391 STATE_AFTR_NAME, 392 STATE_OPTS, 393 STATE_CER, 394 STATE_S46_MAPT, 395 STATE_S46_MAPE, 396 STATE_S46_LW, 397 STATE_PASSTHRU, 398 _STATE_MAX 399 }; 400 401 struct icmp6_opt { 402 uint8_t type; 403 uint8_t len; 404 uint8_t data[6]; 405 }; 406 407 408 enum dhcpv6_mode { 409 DHCPV6_UNKNOWN = -1, 410 DHCPV6_STATELESS, 411 DHCPV6_STATEFUL 412 }; 413 414 enum ra_config { 415 RA_RDNSS_DEFAULT_LIFETIME = 1, 416 }; 417 418 enum odhcp6c_ia_mode { 419 IA_MODE_NONE, 420 IA_MODE_TRY, 421 IA_MODE_FORCE, 422 }; 423 424 enum odhcp6c_auth_protocol { 425 AUTH_PROT_NONE = -1, 426 /* RFC3118 */ 427 AUTH_PROT_TOKEN = 0, 428 /* draft-ietf-dhc-rfc8415bis-12 */ 429 AUTH_PROT_RKAP = 3, 430 }; 431 432 enum odhcp6c_auth_algorithm { 433 /* RFC3118 */ 434 AUTH_ALG_TOKEN = 0, 435 /* draft-ietf-dhc-rfc8415bis-12 */ 436 AUTH_ALG_HMACMD5 = 1 437 }; 438 439 enum odhcp6c_rkap_type { 440 /* draft-ietf-dhc-rfc8415bis-12 */ 441 RKAP_TYPE_KEY = 1, 442 RKAP_TYPE_HMACMD5 = 2, 443 }; 444 445 struct odhcp6c_entry { 446 struct in6_addr router; 447 uint8_t auxlen; 448 uint8_t length; 449 struct in6_addr target; 450 int16_t priority; 451 uint32_t valid; 452 uint32_t preferred; 453 uint32_t t1; 454 uint32_t t2; 455 uint32_t iaid; 456 uint8_t auxtarget[]; 457 }; 458 459 // Include padding after auxtarget to align the next entry 460 #define odhcp6c_entry_size(entry) \ 461 (sizeof(struct odhcp6c_entry) + (((entry)->auxlen + 3) & ~3)) 462 463 #define odhcp6c_next_entry(entry) \ 464 ((struct odhcp6c_entry *)((uint8_t *)(entry) + odhcp6c_entry_size(entry))) 465 466 467 struct odhcp6c_request_prefix { 468 uint32_t iaid; 469 uint8_t length; 470 struct in6_addr addr; 471 }; 472 473 enum odhcp6c_opt_flags { 474 OPT_U8 = 0, 475 OPT_IP6, 476 OPT_STR, 477 OPT_DNS_STR, 478 OPT_USER_CLASS, 479 OPT_MASK_SIZE = 0x0F, 480 OPT_ARRAY = 0x10, 481 OPT_INTERNAL = 0x20, 482 OPT_NO_PASSTHRU = 0x40, 483 OPT_ORO = 0x80, 484 OPT_ORO_STATEFUL = 0x100, 485 OPT_ORO_STATELESS = 0x200, 486 OPT_ORO_SOLICIT = 0x400 487 }; 488 489 struct odhcp6c_opt { 490 uint16_t code; 491 uint16_t flags; 492 const char *str; 493 }; 494 495 int init_dhcpv6(const char *ifname); 496 int dhcpv6_get_ia_mode(void); 497 int dhcpv6_promote_server_cand(void); 498 int dhcpv6_send_request(enum dhcpv6_msg type); 499 int dhcpv6_receive_response(enum dhcpv6_msg type); 500 enum dhcpv6_state dhcpv6_get_state(void); 501 void dhcpv6_set_state(enum dhcpv6_state state); 502 int dhcpv6_get_socket(void); 503 struct dhcpv6_stats dhcpv6_get_stats(void); 504 void dhcpv6_reset_stats(void); 505 int dhcpv6_state_processing(enum dhcpv6_msg type); 506 int dhcpv6_get_state_timeout(void); 507 void dhcpv6_set_state_timeout(int timeout); 508 void dhcpv6_reset_state_timeout(void); 509 const char *dhcpv6_state_to_str(enum dhcpv6_state state); 510 511 int init_rtnetlink(void); 512 int set_rtnetlink_addr(int ifindex, const struct in6_addr *addr, 513 uint32_t pref, uint32_t valid); 514 515 int ra_get_hoplimit(void); 516 int ra_get_mtu(void); 517 int ra_get_reachable(void); 518 int ra_get_retransmit(void); 519 520 void notify_state_change(const char *status, int delay, bool resume); 521 522 int script_init(const char *path, const char *ifname); 523 ssize_t script_unhexlify(uint8_t *dst, size_t len, const char *src); 524 void script_hexlify(char *dst, const uint8_t *src, size_t len); 525 void script_call(const char *status, int delay, bool resume); 526 527 bool odhcp6c_signal_process(void); 528 uint64_t odhcp6c_get_milli_time(void); 529 int odhcp6c_random(void *buf, size_t len); 530 bool odhcp6c_is_bound(void); 531 bool odhcp6c_addr_in_scope(const struct in6_addr *addr); 532 533 // State manipulation 534 void odhcp6c_clear_state(enum odhcp6c_state state); 535 int odhcp6c_add_state(enum odhcp6c_state state, const void *data, size_t len); 536 void odhcp6c_append_state(enum odhcp6c_state state, const void *data, size_t len); 537 int odhcp6c_insert_state(enum odhcp6c_state state, size_t offset, const void *data, size_t len); 538 size_t odhcp6c_remove_state(enum odhcp6c_state state, size_t offset, size_t len); 539 void* odhcp6c_move_state(enum odhcp6c_state state, size_t *len); 540 void* odhcp6c_get_state(enum odhcp6c_state state, size_t *len); 541 542 // Entry manipulation 543 bool odhcp6c_update_entry(enum odhcp6c_state state, struct odhcp6c_entry *new, 544 uint32_t safe, unsigned int holdoff_interval); 545 546 void odhcp6c_expire(bool expire_ia_pd); 547 uint32_t odhcp6c_elapsed(void); 548 struct odhcp6c_opt *odhcp6c_find_opt(const uint16_t code); 549 struct odhcp6c_opt *odhcp6c_find_opt_by_name(const char *name); 550 551 #endif /* _ODHCP6C_H_ */ 552
This page was automatically generated by LXR 0.3.1. • OpenWrt