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