1 /** 2 * Copyright (C) 2012-2013 Steven Barth <steven@midlink.org> 3 * Copyright (C) 2016 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 17 #include <time.h> 18 #include <errno.h> 19 #include <fcntl.h> 20 #include <unistd.h> 21 #include <stddef.h> 22 #include <stdlib.h> 23 #include <resolv.h> 24 #include <limits.h> 25 #include <net/if.h> 26 #include <net/if_arp.h> 27 #include <netinet/ip.h> 28 #include <sys/ioctl.h> 29 #include <sys/timerfd.h> 30 #include <arpa/inet.h> 31 32 #include <libubox/md5.h> 33 34 #include "odhcpd.h" 35 #include "dhcpv4.h" 36 #include "dhcpv6.h" 37 38 #define PACKET_SIZE(start, end) (((uint8_t *)end - (uint8_t *)start) < DHCPV4_MIN_PACKET_SIZE ? \ 39 DHCPV4_MIN_PACKET_SIZE : (uint8_t *)end - (uint8_t *)start) 40 #define MAX_PREFIX_LEN 28 41 42 static void dhcpv4_netevent_cb(unsigned long event, struct netevent_handler_info *info); 43 static int setup_dhcpv4_addresses(struct interface *iface); 44 static bool addr_is_fr_ip(struct interface *iface, struct in_addr *addr); 45 static void valid_until_cb(struct uloop_timeout *event); 46 static void handle_addrlist_change(struct interface *iface); 47 static void dhcpv4_fr_start(struct dhcp_assignment *a); 48 static void dhcpv4_fr_rand_delay(struct dhcp_assignment *a); 49 static void dhcpv4_fr_stop(struct dhcp_assignment *a); 50 static void handle_dhcpv4(void *addr, void *data, size_t len, 51 struct interface *iface, void *dest_addr); 52 static struct dhcp_assignment* dhcpv4_lease(struct interface *iface, 53 enum dhcpv4_msg msg, const uint8_t *mac, const uint32_t reqaddr, 54 uint32_t *leasetime, const char *hostname, const size_t hostname_len, 55 const bool accept_fr_nonce, bool *incl_fr_opt, uint32_t *fr_serverid, 56 const char *reqopts, const size_t reqopts_len); 57 58 static struct netevent_handler dhcpv4_netevent_handler = { .cb = dhcpv4_netevent_cb, }; 59 static struct uloop_timeout valid_until_timeout = {.cb = valid_until_cb}; 60 static uint32_t serial = 0; 61 62 struct odhcpd_ref_ip { 63 struct list_head head; 64 int ref_cnt; 65 struct odhcpd_ipaddr addr; 66 }; 67 68 /* Create socket and register events */ 69 int dhcpv4_init(void) 70 { 71 uloop_timeout_set(&valid_until_timeout, 1000); 72 netlink_add_netevent_handler(&dhcpv4_netevent_handler); 73 74 return 0; 75 } 76 77 int dhcpv4_setup_interface(struct interface *iface, bool enable) 78 { 79 int ret = 0; 80 81 enable = enable && (iface->dhcpv4 != MODE_DISABLED); 82 83 if (iface->dhcpv4_event.uloop.fd >= 0) { 84 uloop_fd_delete(&iface->dhcpv4_event.uloop); 85 close(iface->dhcpv4_event.uloop.fd); 86 iface->dhcpv4_event.uloop.fd = -1; 87 } 88 89 if (enable) { 90 struct sockaddr_in bind_addr = {AF_INET, htons(DHCPV4_SERVER_PORT), 91 {INADDR_ANY}, {0}}; 92 int val = 1; 93 94 iface->dhcpv4_event.uloop.fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP); 95 if (iface->dhcpv4_event.uloop.fd < 0) { 96 syslog(LOG_ERR, "socket(AF_INET): %m"); 97 ret = -1; 98 goto out; 99 } 100 101 /* Basic IPv4 configuration */ 102 if (setsockopt(iface->dhcpv4_event.uloop.fd, SOL_SOCKET, SO_REUSEADDR, 103 &val, sizeof(val)) < 0) { 104 syslog(LOG_ERR, "setsockopt(SO_REUSEADDR): %m"); 105 ret = -1; 106 goto out; 107 } 108 109 if (setsockopt(iface->dhcpv4_event.uloop.fd, SOL_SOCKET, SO_BROADCAST, 110 &val, sizeof(val)) < 0) { 111 syslog(LOG_ERR, "setsockopt(SO_BROADCAST): %m"); 112 ret = -1; 113 goto out; 114 } 115 116 if (setsockopt(iface->dhcpv4_event.uloop.fd, IPPROTO_IP, IP_PKTINFO, 117 &val, sizeof(val)) < 0) { 118 syslog(LOG_ERR, "setsockopt(IP_PKTINFO): %m"); 119 ret = -1; 120 goto out; 121 } 122 123 val = IPTOS_PREC_INTERNETCONTROL; 124 if (setsockopt(iface->dhcpv4_event.uloop.fd, IPPROTO_IP, IP_TOS, 125 &val, sizeof(val)) < 0) { 126 syslog(LOG_ERR, "setsockopt(IP_TOS): %m"); 127 ret = -1; 128 goto out; 129 } 130 131 val = IP_PMTUDISC_DONT; 132 if (setsockopt(iface->dhcpv4_event.uloop.fd, IPPROTO_IP, IP_MTU_DISCOVER, 133 &val, sizeof(val)) < 0) { 134 syslog(LOG_ERR, "setsockopt(IP_MTU_DISCOVER): %m"); 135 ret = -1; 136 goto out; 137 } 138 139 if (setsockopt(iface->dhcpv4_event.uloop.fd, SOL_SOCKET, SO_BINDTODEVICE, 140 iface->ifname, strlen(iface->ifname)) < 0) { 141 syslog(LOG_ERR, "setsockopt(SO_BINDTODEVICE): %m"); 142 ret = -1; 143 goto out; 144 } 145 146 if (bind(iface->dhcpv4_event.uloop.fd, (struct sockaddr*)&bind_addr, 147 sizeof(bind_addr)) < 0) { 148 syslog(LOG_ERR, "bind(): %m"); 149 ret = -1; 150 goto out; 151 } 152 153 if (setup_dhcpv4_addresses(iface) < 0) { 154 ret = -1; 155 goto out; 156 } 157 158 iface->dhcpv4_event.handle_dgram = handle_dhcpv4; 159 odhcpd_register(&iface->dhcpv4_event); 160 } else { 161 while (!list_empty(&iface->dhcpv4_assignments)) 162 free_assignment(list_first_entry(&iface->dhcpv4_assignments, 163 struct dhcp_assignment, head)); 164 } 165 166 out: 167 if (ret < 0 && iface->dhcpv4_event.uloop.fd >= 0) { 168 close(iface->dhcpv4_event.uloop.fd); 169 iface->dhcpv4_event.uloop.fd = -1; 170 } 171 172 return ret; 173 } 174 175 176 static void dhcpv4_netevent_cb(unsigned long event, struct netevent_handler_info *info) 177 { 178 struct interface *iface = info->iface; 179 180 if (!iface || iface->dhcpv4 == MODE_DISABLED) 181 return; 182 183 switch (event) { 184 case NETEV_IFINDEX_CHANGE: 185 dhcpv4_setup_interface(iface, true); 186 break; 187 case NETEV_ADDRLIST_CHANGE: 188 handle_addrlist_change(iface); 189 break; 190 default: 191 break; 192 } 193 } 194 195 static struct dhcp_assignment *find_assignment_by_hwaddr(struct interface *iface, const uint8_t *hwaddr) 196 { 197 struct dhcp_assignment *a; 198 199 list_for_each_entry(a, &iface->dhcpv4_assignments, head) 200 if (!memcmp(a->hwaddr, hwaddr, 6)) 201 return a; 202 203 return NULL; 204 } 205 206 static int setup_dhcpv4_addresses(struct interface *iface) 207 { 208 iface->dhcpv4_start_ip.s_addr = INADDR_ANY; 209 iface->dhcpv4_end_ip.s_addr = INADDR_ANY; 210 iface->dhcpv4_local.s_addr = INADDR_ANY; 211 iface->dhcpv4_bcast.s_addr = INADDR_ANY; 212 iface->dhcpv4_mask.s_addr = INADDR_ANY; 213 214 /* Sanity checks */ 215 if (iface->dhcpv4_start.s_addr & htonl(0xffff0000) || 216 iface->dhcpv4_end.s_addr & htonl(0xffff0000) || 217 ntohl(iface->dhcpv4_start.s_addr) > ntohl(iface->dhcpv4_end.s_addr)) { 218 syslog(LOG_WARNING, "Invalid DHCP range for %s", iface->name); 219 return -1; 220 } 221 222 if (!iface->addr4_len) { 223 syslog(LOG_WARNING, "No network(s) available on %s", iface->name); 224 return -1; 225 } 226 227 uint32_t start = ntohl(iface->dhcpv4_start.s_addr); 228 uint32_t end = ntohl(iface->dhcpv4_end.s_addr); 229 230 for (size_t i = 0; i < iface->addr4_len && start && end; i++) { 231 struct in_addr *addr = &iface->addr4[i].addr.in; 232 struct in_addr mask; 233 234 if (addr_is_fr_ip(iface, addr)) 235 continue; 236 237 odhcpd_bitlen2netmask(false, iface->addr4[i].prefix, &mask); 238 if ((start & ntohl(~mask.s_addr)) == start && 239 (end & ntohl(~mask.s_addr)) == end && 240 end < ntohl(~mask.s_addr)) { /* Exclude broadcast address */ 241 iface->dhcpv4_start_ip.s_addr = htonl(start) | 242 (addr->s_addr & mask.s_addr); 243 iface->dhcpv4_end_ip.s_addr = htonl(end) | 244 (addr->s_addr & mask.s_addr); 245 iface->dhcpv4_local = *addr; 246 iface->dhcpv4_bcast = iface->addr4[i].broadcast; 247 iface->dhcpv4_mask = mask; 248 return 0; 249 } 250 } 251 252 /* Don't allocate IP range for subnets smaller than /28 */ 253 if (iface->addr4[0].prefix > MAX_PREFIX_LEN) { 254 syslog(LOG_WARNING, "Auto allocation of DHCP range fails on %s (prefix length must be < %d).", iface->name, MAX_PREFIX_LEN + 1); 255 return -1; 256 } 257 258 iface->dhcpv4_local = iface->addr4[0].addr.in; 259 iface->dhcpv4_bcast = iface->addr4[0].broadcast; 260 odhcpd_bitlen2netmask(false, iface->addr4[0].prefix, &iface->dhcpv4_mask); 261 end = start = iface->dhcpv4_local.s_addr & iface->dhcpv4_mask.s_addr; 262 263 /* Auto allocate ranges */ 264 if (ntohl(iface->dhcpv4_mask.s_addr) <= 0xffffff00) { /* /24, 150 of 256, [100..249] */ 265 iface->dhcpv4_start_ip.s_addr = start | htonl(100); 266 iface->dhcpv4_end_ip.s_addr = end | htonl(100 + 150 - 1); 267 } else if (ntohl(iface->dhcpv4_mask.s_addr) <= 0xffffff80) { /* /25, 100 of 128, [20..119] */ 268 iface->dhcpv4_start_ip.s_addr = start | htonl(20); 269 iface->dhcpv4_end_ip.s_addr = end | htonl(20 + 100 - 1); 270 } else if (ntohl(iface->dhcpv4_mask.s_addr) <= 0xffffffc0) { /* /26, 50 of 64, [10..59] */ 271 iface->dhcpv4_start_ip.s_addr = start | htonl(10); 272 iface->dhcpv4_end_ip.s_addr = end | htonl(10 + 50 - 1); 273 } else if (ntohl(iface->dhcpv4_mask.s_addr) <= 0xffffffe0) { /* /27, 20 of 32, [10..29] */ 274 iface->dhcpv4_start_ip.s_addr = start | htonl(10); 275 iface->dhcpv4_end_ip.s_addr = end | htonl(10 + 20 - 1); 276 } else { /* /28, 10 of 16, [3..12] */ 277 iface->dhcpv4_start_ip.s_addr = start | htonl(3); 278 iface->dhcpv4_end_ip.s_addr = end | htonl(3 + 10 - 1); 279 } 280 281 return 0; 282 } 283 284 static void inc_ref_cnt_ip(struct odhcpd_ref_ip **ptr, struct odhcpd_ref_ip *ip) 285 { 286 *ptr = ip; 287 ip->ref_cnt++; 288 } 289 290 static void decr_ref_cnt_ip(struct odhcpd_ref_ip **ptr, struct interface *iface) 291 { 292 struct odhcpd_ref_ip *ip = *ptr; 293 294 if (--ip->ref_cnt == 0) { 295 netlink_setup_addr(&ip->addr, iface->ifindex, false, false); 296 297 list_del(&ip->head); 298 free(ip); 299 } 300 301 *ptr = NULL; 302 } 303 304 static bool addr_is_fr_ip(struct interface *iface, struct in_addr *addr) 305 { 306 struct odhcpd_ref_ip *p; 307 308 list_for_each_entry(p, &iface->dhcpv4_fr_ips, head) { 309 if (addr->s_addr == p->addr.addr.in.s_addr) 310 return true; 311 } 312 313 return false; 314 } 315 316 static bool leases_require_fr(struct interface *iface, struct odhcpd_ipaddr *addr, 317 uint32_t mask) 318 { 319 struct dhcp_assignment *a = NULL; 320 struct odhcpd_ref_ip *fr_ip = NULL; 321 322 list_for_each_entry(a, &iface->dhcpv4_assignments, head) { 323 if ((a->accept_fr_nonce || iface->dhcpv4_forcereconf) && 324 !a->fr_ip && 325 ((a->addr & mask) == (addr->addr.in.s_addr & mask))) { 326 if (!fr_ip) { 327 fr_ip = calloc(1, sizeof(*fr_ip)); 328 if (!fr_ip) 329 break; 330 331 list_add(&fr_ip->head, &iface->dhcpv4_fr_ips); 332 fr_ip->addr = *addr; 333 } 334 inc_ref_cnt_ip(&a->fr_ip, fr_ip); 335 } 336 } 337 338 return fr_ip ? true : false; 339 } 340 341 static void valid_until_cb(struct uloop_timeout *event) 342 { 343 struct interface *iface; 344 time_t now = odhcpd_time(); 345 346 avl_for_each_element(&interfaces, iface, avl) { 347 struct dhcp_assignment *a, *n; 348 349 if (iface->dhcpv4 != MODE_SERVER) 350 continue; 351 352 list_for_each_entry_safe(a, n, &iface->dhcpv4_assignments, head) { 353 if (!INFINITE_VALID(a->valid_until) && a->valid_until < now) 354 free_assignment(a); 355 } 356 } 357 uloop_timeout_set(event, 1000); 358 } 359 360 static void handle_addrlist_change(struct interface *iface) 361 { 362 struct odhcpd_ipaddr ip; 363 struct odhcpd_ref_ip *a; 364 struct dhcp_assignment *c; 365 uint32_t mask = iface->dhcpv4_mask.s_addr; 366 367 memset(&ip, 0, sizeof(ip)); 368 ip.addr.in = iface->dhcpv4_local; 369 ip.prefix = odhcpd_netmask2bitlen(false, &iface->dhcpv4_mask); 370 ip.broadcast = iface->dhcpv4_bcast; 371 372 setup_dhcpv4_addresses(iface); 373 374 if ((ip.addr.in.s_addr & mask) == 375 (iface->dhcpv4_local.s_addr & iface->dhcpv4_mask.s_addr)) 376 return; 377 378 if (ip.addr.in.s_addr && !leases_require_fr(iface, &ip, mask)) 379 return; 380 381 if (iface->dhcpv4_local.s_addr == INADDR_ANY || list_empty(&iface->dhcpv4_fr_ips)) 382 return; 383 384 a = list_first_entry(&iface->dhcpv4_fr_ips, struct odhcpd_ref_ip, head); 385 386 if (netlink_setup_addr(&a->addr, iface->ifindex, false, true)) { 387 syslog(LOG_WARNING, "Failed to add ip address on %s", iface->name); 388 return; 389 } 390 391 list_for_each_entry(c, &iface->dhcpv4_assignments, head) { 392 if ((c->flags & OAF_BOUND) && c->fr_ip && !c->fr_cnt) { 393 if (c->accept_fr_nonce || iface->dhcpv4_forcereconf) 394 dhcpv4_fr_rand_delay(c); 395 else 396 dhcpv4_fr_stop(c); 397 } 398 } 399 } 400 401 static char *dhcpv4_msg_to_string(uint8_t reqmsg) 402 { 403 switch (reqmsg) { 404 case (DHCPV4_MSG_DISCOVER): 405 return "DHCPV4_MSG_DISCOVER"; 406 case (DHCPV4_MSG_OFFER): 407 return "DHCPV4_MSG_OFFER"; 408 case (DHCPV4_MSG_REQUEST): 409 return "DHCPV4_MSG_REQUEST"; 410 case (DHCPV4_MSG_DECLINE): 411 return "DHCPV4_MSG_DECLINE"; 412 case (DHCPV4_MSG_ACK): 413 return "DHCPV4_MSG_ACK"; 414 case (DHCPV4_MSG_NAK): 415 return "DHCPV4_MSG_NAK"; 416 case (DHCPV4_MSG_RELEASE): 417 return "DHCPV4_MSG_RELEASE"; 418 case (DHCPV4_MSG_INFORM): 419 return "DHCPV4_MSG_INFORM"; 420 case (DHCPV4_MSG_FORCERENEW): 421 return "DHCPV4_MSG_FORCERENEW"; 422 default: 423 return "UNKNOWN"; 424 } 425 } 426 427 static void dhcpv4_free_assignment(struct dhcp_assignment *a) 428 { 429 if (a->fr_ip) 430 dhcpv4_fr_stop(a); 431 } 432 433 static void dhcpv4_put(struct dhcpv4_message *msg, uint8_t **cookie, 434 uint8_t type, uint8_t len, const void *data) 435 { 436 uint8_t *c = *cookie; 437 uint8_t *end = (uint8_t *)msg + sizeof(*msg); 438 bool tag_only = type == DHCPV4_OPT_PAD || type == DHCPV4_OPT_END; 439 int total_len = tag_only ? 1 : 2 + len; 440 441 if (*cookie + total_len > end) 442 return; 443 444 *cookie += total_len; 445 *c++ = type; 446 447 if (tag_only) 448 return; 449 450 *c++ = len; 451 memcpy(c, data, len); 452 } 453 454 static void dhcpv4_fr_send(struct dhcp_assignment *a) 455 { 456 struct dhcpv4_message fr_msg = { 457 .op = DHCPV4_BOOTREPLY, 458 .htype = 1, 459 .hlen = 6, 460 .hops = 0, 461 .secs = 0, 462 .flags = 0, 463 .ciaddr = {INADDR_ANY}, 464 .yiaddr = {INADDR_ANY}, 465 .siaddr = {INADDR_ANY}, 466 .giaddr = {INADDR_ANY}, 467 .chaddr = {0}, 468 .sname = {0}, 469 .file = {0}, 470 }; 471 struct dhcpv4_auth_forcerenew *auth_o, auth = { 472 .protocol = 3, 473 .algorithm = 1, 474 .rdm = 0, 475 .replay = {htonl(time(NULL)), htonl(++serial)}, 476 .type = 2, 477 .key = {0}, 478 }; 479 struct interface *iface = a->iface; 480 481 odhcpd_urandom(&fr_msg.xid, sizeof(fr_msg.xid)); 482 memcpy(fr_msg.chaddr, a->hwaddr, fr_msg.hlen); 483 484 fr_msg.options[0] = 0x63; 485 fr_msg.options[1] = 0x82; 486 fr_msg.options[2] = 0x53; 487 fr_msg.options[3] = 0x63; 488 489 uint8_t *cookie = &fr_msg.options[4]; 490 uint8_t msg = DHCPV4_MSG_FORCERENEW; 491 492 dhcpv4_put(&fr_msg, &cookie, DHCPV4_OPT_MESSAGE, 1, &msg); 493 if (a->accept_fr_nonce) { 494 dhcpv4_put(&fr_msg, &cookie, DHCPV4_OPT_AUTHENTICATION, sizeof(auth), &auth); 495 auth_o = (struct dhcpv4_auth_forcerenew *)(cookie - sizeof(auth)); 496 dhcpv4_put(&fr_msg, &cookie, DHCPV4_OPT_END, 0, NULL); 497 498 md5_ctx_t md5; 499 uint8_t secretbytes[64]; 500 memset(secretbytes, 0, sizeof(secretbytes)); 501 memcpy(secretbytes, a->key, sizeof(a->key)); 502 503 for (size_t i = 0; i < sizeof(secretbytes); ++i) 504 secretbytes[i] ^= 0x36; 505 506 md5_begin(&md5); 507 md5_hash(secretbytes, sizeof(secretbytes), &md5); 508 md5_hash(&fr_msg, sizeof(fr_msg), &md5); 509 md5_end(auth_o->key, &md5); 510 511 for (size_t i = 0; i < sizeof(secretbytes); ++i) { 512 secretbytes[i] ^= 0x36; 513 secretbytes[i] ^= 0x5c; 514 } 515 516 md5_begin(&md5); 517 md5_hash(secretbytes, sizeof(secretbytes), &md5); 518 md5_hash(auth_o->key, sizeof(auth_o->key), &md5); 519 md5_end(auth_o->key, &md5); 520 } else { 521 dhcpv4_put(&fr_msg, &cookie, DHCPV4_OPT_SERVERID, 4, 522 &a->fr_ip->addr.addr.in.s_addr); 523 dhcpv4_put(&fr_msg, &cookie, DHCPV4_OPT_END, 0, NULL); 524 } 525 526 struct sockaddr_in dest; 527 memset(&dest, 0, sizeof(dest)); 528 dest.sin_family = AF_INET; 529 dest.sin_port = htons(DHCPV4_CLIENT_PORT); 530 dest.sin_addr.s_addr = a->addr; 531 532 if (sendto(iface->dhcpv4_event.uloop.fd, &fr_msg, PACKET_SIZE(&fr_msg, cookie), 533 MSG_DONTWAIT, (struct sockaddr*)&dest, sizeof(dest)) < 0) 534 syslog(LOG_ERR, "Failed to send %s to %s - %s: %m", dhcpv4_msg_to_string(msg), 535 odhcpd_print_mac(a->hwaddr, sizeof(a->hwaddr)), inet_ntoa(dest.sin_addr)); 536 else 537 syslog(LOG_DEBUG, "Sent %s to %s - %s", dhcpv4_msg_to_string(msg), 538 odhcpd_print_mac(a->hwaddr, sizeof(a->hwaddr)), inet_ntoa(dest.sin_addr)); 539 } 540 541 static void dhcpv4_fr_timer(struct uloop_timeout *event) 542 { 543 struct dhcp_assignment *a = container_of(event, struct dhcp_assignment, fr_timer); 544 545 if (a->fr_cnt > 0 && a->fr_cnt < 8) { 546 dhcpv4_fr_send(a); 547 uloop_timeout_set(&a->fr_timer, 1000 << a->fr_cnt); 548 a->fr_cnt++; 549 } else 550 dhcpv4_fr_stop(a); 551 } 552 553 static void dhcpv4_fr_start(struct dhcp_assignment *a) 554 { 555 uloop_timeout_set(&a->fr_timer, 1000 << a->fr_cnt); 556 a->fr_timer.cb = dhcpv4_fr_timer; 557 a->fr_cnt++; 558 559 dhcpv4_fr_send(a); 560 } 561 562 static void dhcpv4_fr_delay_timer(struct uloop_timeout *event) 563 { 564 struct dhcp_assignment *a = container_of(event, struct dhcp_assignment, fr_timer); 565 struct interface *iface = a->iface; 566 567 (iface->dhcpv4_event.uloop.fd == -1 ? dhcpv4_fr_rand_delay(a) : dhcpv4_fr_start(a)); 568 } 569 570 static void dhcpv4_fr_rand_delay(struct dhcp_assignment *a) 571 { 572 #define MIN_DELAY 500 573 #define MAX_FUZZ 500 574 int msecs; 575 576 odhcpd_urandom(&msecs, sizeof(msecs)); 577 578 msecs = labs(msecs)%MAX_FUZZ + MIN_DELAY; 579 580 uloop_timeout_set(&a->fr_timer, msecs); 581 a->fr_timer.cb = dhcpv4_fr_delay_timer; 582 } 583 584 static void dhcpv4_fr_stop(struct dhcp_assignment *a) 585 { 586 uloop_timeout_cancel(&a->fr_timer); 587 decr_ref_cnt_ip(&a->fr_ip, a->iface); 588 a->fr_cnt = 0; 589 a->fr_timer.cb = NULL; 590 } 591 592 static int dhcpv4_send_reply(const void *buf, size_t len, 593 const struct sockaddr *dest, socklen_t dest_len, 594 void *opaque) 595 { 596 int *sock = opaque; 597 598 return sendto(*sock, buf, len, MSG_DONTWAIT, dest, dest_len); 599 } 600 601 /* Handler for DHCPv4 messages */ 602 static void handle_dhcpv4(void *addr, void *data, size_t len, 603 struct interface *iface, _unused void *dest_addr) 604 { 605 int sock = iface->dhcpv4_event.uloop.fd; 606 607 dhcpv4_handle_msg(addr, data, len, iface, dest_addr, dhcpv4_send_reply, &sock); 608 } 609 610 void dhcpv4_handle_msg(void *addr, void *data, size_t len, 611 struct interface *iface, _unused void *dest_addr, 612 send_reply_cb_t send_reply, void *opaque) 613 { 614 struct dhcpv4_message *req = data; 615 616 if (iface->dhcpv4 == MODE_DISABLED) 617 return; 618 619 if (len < offsetof(struct dhcpv4_message, options) + 4 || 620 req->op != DHCPV4_BOOTREQUEST || req->hlen != 6) 621 return; 622 623 syslog(LOG_DEBUG, "Got DHCPv4 request on %s", iface->name); 624 625 if (!iface->dhcpv4_start_ip.s_addr && !iface->dhcpv4_end_ip.s_addr) { 626 syslog(LOG_WARNING, "No DHCP range available on %s", iface->name); 627 return; 628 } 629 630 int sock = iface->dhcpv4_event.uloop.fd; 631 632 struct dhcpv4_message reply = { 633 .op = DHCPV4_BOOTREPLY, 634 .htype = req->htype, 635 .hlen = req->hlen, 636 .hops = 0, 637 .xid = req->xid, 638 .secs = 0, 639 .flags = req->flags, 640 .ciaddr = {INADDR_ANY}, 641 .giaddr = req->giaddr, 642 .siaddr = iface->dhcpv4_local, 643 }; 644 memcpy(reply.chaddr, req->chaddr, sizeof(reply.chaddr)); 645 646 reply.options[0] = 0x63; 647 reply.options[1] = 0x82; 648 reply.options[2] = 0x53; 649 reply.options[3] = 0x63; 650 651 uint8_t *cookie = &reply.options[4]; 652 uint8_t reqmsg = DHCPV4_MSG_REQUEST; 653 uint8_t msg = DHCPV4_MSG_ACK; 654 655 uint32_t reqaddr = INADDR_ANY; 656 uint32_t leasetime = 0; 657 size_t hostname_len = 0; 658 size_t reqopts_len = 0; 659 char hostname[256]; 660 char reqopts[256]; 661 bool accept_fr_nonce = false; 662 bool incl_fr_opt = false; 663 664 uint8_t *start = &req->options[4]; 665 uint8_t *end = ((uint8_t*)data) + len; 666 struct dhcpv4_option *opt; 667 dhcpv4_for_each_option(start, end, opt) { 668 if (opt->type == DHCPV4_OPT_MESSAGE && opt->len == 1) 669 reqmsg = opt->data[0]; 670 else if (opt->type == DHCPV4_OPT_REQOPTS && opt->len > 0) { 671 reqopts_len = opt->len; 672 memcpy(reqopts, opt->data, reqopts_len); 673 reqopts[reqopts_len] = 0; 674 } else if (opt->type == DHCPV4_OPT_HOSTNAME && opt->len > 0) { 675 hostname_len = opt->len; 676 memcpy(hostname, opt->data, hostname_len); 677 hostname[hostname_len] = 0; 678 } else if (opt->type == DHCPV4_OPT_IPADDRESS && opt->len == 4) 679 memcpy(&reqaddr, opt->data, 4); 680 else if (opt->type == DHCPV4_OPT_SERVERID && opt->len == 4) { 681 if (memcmp(opt->data, &iface->dhcpv4_local, 4)) 682 return; 683 } else if (iface->filter_class && opt->type == DHCPV4_OPT_USER_CLASS) { 684 uint8_t *c = opt->data, *cend = &opt->data[opt->len]; 685 for (; c < cend && &c[*c] < cend; c = &c[1 + *c]) { 686 size_t elen = strlen(iface->filter_class); 687 if (*c == elen && !memcmp(&c[1], iface->filter_class, elen)) 688 return; // Ignore from homenet 689 } 690 } else if (opt->type == DHCPV4_OPT_LEASETIME && opt->len == 4) 691 memcpy(&leasetime, opt->data, 4); 692 else if (opt->type == DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE && opt->len > 0) { 693 for (uint8_t i = 0; i < opt->len; i++) { 694 if (opt->data[i] == 1) { 695 accept_fr_nonce = true; 696 break; 697 } 698 } 699 700 } 701 } 702 703 if (reqmsg != DHCPV4_MSG_DISCOVER && reqmsg != DHCPV4_MSG_REQUEST && 704 reqmsg != DHCPV4_MSG_INFORM && reqmsg != DHCPV4_MSG_DECLINE && 705 reqmsg != DHCPV4_MSG_RELEASE) 706 return; 707 708 struct dhcp_assignment *a = NULL; 709 uint32_t serverid = iface->dhcpv4_local.s_addr; 710 uint32_t fr_serverid = INADDR_ANY; 711 712 if (reqmsg != DHCPV4_MSG_INFORM) 713 a = dhcpv4_lease(iface, reqmsg, req->chaddr, reqaddr, 714 &leasetime, hostname, hostname_len, 715 accept_fr_nonce, &incl_fr_opt, &fr_serverid, 716 reqopts, reqopts_len); 717 718 if (!a) { 719 if (reqmsg == DHCPV4_MSG_REQUEST) 720 msg = DHCPV4_MSG_NAK; 721 else if (reqmsg == DHCPV4_MSG_DISCOVER) 722 return; 723 } else if (reqmsg == DHCPV4_MSG_DISCOVER) 724 msg = DHCPV4_MSG_OFFER; 725 else if (reqmsg == DHCPV4_MSG_REQUEST && 726 ((reqaddr && reqaddr != a->addr) || 727 (req->ciaddr.s_addr && req->ciaddr.s_addr != a->addr))) { 728 msg = DHCPV4_MSG_NAK; 729 /* 730 * DHCP client requested an IP which we can't offer to him. Probably the 731 * client changed the network or the network has been changed. The reply 732 * type is set to DHCPV4_MSG_NAK, because the client should not use that IP. 733 * 734 * For modern devices we build an answer that includes a valid IP, like 735 * a DHCPV4_MSG_ACK. The client will use that IP and doesn't need to 736 * perform additional DHCP round trips. 737 * 738 */ 739 740 /* 741 * 742 * Buggy clients do serverid checking in nack messages; therefore set the 743 * serverid in nack messages triggered by a previous force renew equal to 744 * the server id in use at that time by the server 745 * 746 */ 747 if (fr_serverid) 748 serverid = fr_serverid; 749 750 if (req->ciaddr.s_addr && 751 ((iface->dhcpv4_start_ip.s_addr & iface->dhcpv4_mask.s_addr) != 752 (req->ciaddr.s_addr & iface->dhcpv4_mask.s_addr))) 753 req->ciaddr.s_addr = INADDR_ANY; 754 } 755 756 syslog(LOG_INFO, "Received %s from %s on %s", dhcpv4_msg_to_string(reqmsg), 757 odhcpd_print_mac(req->chaddr, req->hlen), iface->name); 758 759 #ifdef WITH_UBUS 760 if (reqmsg == DHCPV4_MSG_RELEASE) 761 ubus_bcast_dhcp_event("dhcp.release", req->chaddr, req->hlen, 762 &req->ciaddr, a ? a->hostname : NULL, iface->ifname); 763 #endif 764 if (reqmsg == DHCPV4_MSG_DECLINE || reqmsg == DHCPV4_MSG_RELEASE) 765 return; 766 767 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_MESSAGE, 1, &msg); 768 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_SERVERID, 4, &serverid); 769 770 if (a) { 771 uint32_t val; 772 773 reply.yiaddr.s_addr = a->addr; 774 775 val = htonl(leasetime); 776 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_LEASETIME, 4, &val); 777 778 if (leasetime != UINT32_MAX) { 779 val = htonl(500 * leasetime / 1000); 780 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_RENEW, 4, &val); 781 782 val = htonl(875 * leasetime / 1000); 783 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_REBIND, 4, &val); 784 } 785 786 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_NETMASK, 4, 787 &iface->dhcpv4_mask.s_addr); 788 789 if (a->hostname) 790 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_HOSTNAME, 791 strlen(a->hostname), a->hostname); 792 793 if (iface->dhcpv4_bcast.s_addr != INADDR_ANY) 794 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_BROADCAST, 4, &iface->dhcpv4_bcast); 795 796 if (incl_fr_opt) { 797 if (reqmsg == DHCPV4_MSG_REQUEST) { 798 struct dhcpv4_auth_forcerenew auth = { 799 .protocol = 3, 800 .algorithm = 1, 801 .rdm = 0, 802 .replay = {htonl(time(NULL)), htonl(++serial)}, 803 .type = 1, 804 .key = {0}, 805 }; 806 807 memcpy(auth.key, a->key, sizeof(auth.key)); 808 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_AUTHENTICATION, sizeof(auth), &auth); 809 } else { 810 uint8_t one = 1; 811 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE, 812 sizeof(one), &one); 813 } 814 } 815 } 816 817 struct ifreq ifr; 818 819 memset(&ifr, 0, sizeof(ifr)); 820 strncpy(ifr.ifr_name, iface->ifname, sizeof(ifr.ifr_name) - 1); 821 822 if (!ioctl(sock, SIOCGIFMTU, &ifr)) { 823 uint16_t mtu = htons(ifr.ifr_mtu); 824 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_MTU, 2, &mtu); 825 } 826 827 if (iface->search && iface->search_len <= 255) 828 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_SEARCH_DOMAIN, 829 iface->search_len, iface->search); 830 else if (!res_init() && _res.dnsrch[0] && _res.dnsrch[0][0]) { 831 uint8_t search_buf[256]; 832 int len = dn_comp(_res.dnsrch[0], search_buf, 833 sizeof(search_buf), NULL, NULL); 834 if (len > 0) 835 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_SEARCH_DOMAIN, 836 len, search_buf); 837 } 838 839 if (iface->dhcpv4_router_cnt == 0) 840 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_ROUTER, 4, &iface->dhcpv4_local); 841 else 842 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_ROUTER, 843 4 * iface->dhcpv4_router_cnt, iface->dhcpv4_router); 844 845 846 if (iface->dhcpv4_dns_cnt == 0) { 847 if (iface->dns_service) 848 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_DNSSERVER, 4, &iface->dhcpv4_local); 849 } else 850 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_DNSSERVER, 851 4 * iface->dhcpv4_dns_cnt, iface->dhcpv4_dns); 852 853 if (a && a->reqopts && iface->dhcpv4_ntp_cnt != 0) { 854 for(size_t opts = 0; a->reqopts[opts]; opts++) { 855 if (a->reqopts[opts] == DHCPV4_OPT_NTPSERVER) { 856 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_NTPSERVER, 857 4 * iface->dhcpv4_ntp_cnt, iface->dhcpv4_ntp); 858 } 859 } 860 } 861 862 dhcpv4_put(&reply, &cookie, DHCPV4_OPT_END, 0, NULL); 863 864 struct sockaddr_in dest = *((struct sockaddr_in*)addr); 865 if (req->giaddr.s_addr) { 866 /* 867 * relay agent is configured, send reply to the agent 868 */ 869 dest.sin_addr = req->giaddr; 870 dest.sin_port = htons(DHCPV4_SERVER_PORT); 871 } else if (req->ciaddr.s_addr && req->ciaddr.s_addr != dest.sin_addr.s_addr) { 872 /* 873 * client has existing configuration (ciaddr is set) AND this address is 874 * not the address it used for the dhcp message 875 */ 876 dest.sin_addr = req->ciaddr; 877 dest.sin_port = htons(DHCPV4_CLIENT_PORT); 878 } else if ((ntohs(req->flags) & DHCPV4_FLAG_BROADCAST) || 879 req->hlen != reply.hlen || !reply.yiaddr.s_addr) { 880 /* 881 * client requests a broadcast reply OR we can't offer an IP 882 */ 883 dest.sin_addr.s_addr = INADDR_BROADCAST; 884 dest.sin_port = htons(DHCPV4_CLIENT_PORT); 885 } else if (!req->ciaddr.s_addr && msg == DHCPV4_MSG_NAK) { 886 /* 887 * client has no previous configuration -> no IP, so we need to reply 888 * with a broadcast packet 889 */ 890 dest.sin_addr.s_addr = INADDR_BROADCAST; 891 dest.sin_port = htons(DHCPV4_CLIENT_PORT); 892 } else { 893 struct arpreq arp = {.arp_flags = ATF_COM}; 894 895 /* 896 * send reply to the newly (in this proccess) allocated IP 897 */ 898 dest.sin_addr = reply.yiaddr; 899 dest.sin_port = htons(DHCPV4_CLIENT_PORT); 900 901 if (!(iface->ifflags & IFF_NOARP)) { 902 memcpy(arp.arp_ha.sa_data, req->chaddr, 6); 903 memcpy(&arp.arp_pa, &dest, sizeof(arp.arp_pa)); 904 memcpy(arp.arp_dev, iface->ifname, sizeof(arp.arp_dev)); 905 906 if (ioctl(sock, SIOCSARP, &arp) < 0) 907 syslog(LOG_ERR, "ioctl(SIOCSARP): %m"); 908 } 909 } 910 911 if (send_reply(&reply, PACKET_SIZE(&reply, cookie), 912 (struct sockaddr*)&dest, sizeof(dest), opaque) < 0) 913 syslog(LOG_ERR, "Failed to send %s to %s - %s: %m", 914 dhcpv4_msg_to_string(msg), 915 dest.sin_addr.s_addr == INADDR_BROADCAST ? 916 "ff:ff:ff:ff:ff:ff": odhcpd_print_mac(req->chaddr, req->hlen), 917 inet_ntoa(dest.sin_addr)); 918 else 919 syslog(LOG_DEBUG, "Sent %s to %s - %s", 920 dhcpv4_msg_to_string(msg), 921 dest.sin_addr.s_addr == INADDR_BROADCAST ? 922 "ff:ff:ff:ff:ff:ff": odhcpd_print_mac(req->chaddr, req->hlen), 923 inet_ntoa(dest.sin_addr)); 924 925 926 #ifdef WITH_UBUS 927 if (msg == DHCPV4_MSG_ACK) 928 ubus_bcast_dhcp_event("dhcp.ack", req->chaddr, req->hlen, &reply.yiaddr, 929 a ? a->hostname : NULL, iface->ifname); 930 #endif 931 } 932 933 static bool dhcpv4_insert_assignment(struct list_head *list, struct dhcp_assignment *a, 934 uint32_t addr) 935 { 936 uint32_t h_addr = ntohl(addr); 937 struct dhcp_assignment *c; 938 939 list_for_each_entry(c, list, head) { 940 uint32_t c_addr = ntohl(c->addr); 941 942 if (c_addr == h_addr) 943 return false; 944 945 if (c_addr > h_addr) 946 break; 947 } 948 949 /* Insert new node before c (might match list head) */ 950 a->addr = addr; 951 list_add_tail(&a->head, &c->head); 952 953 return true; 954 } 955 956 static char* ip4toa(uint32_t addr) 957 { 958 static char buf[16]; 959 960 snprintf(buf, sizeof(buf), "%u.%u.%u.%u", 961 ((uint8_t *)&addr)[0], ((uint8_t *)&addr)[1], 962 ((uint8_t *)&addr)[2], ((uint8_t *)&addr)[3]); 963 964 return buf; 965 } 966 967 static bool dhcpv4_assign(struct interface *iface, struct dhcp_assignment *a, 968 uint32_t raddr) 969 { 970 uint32_t start = ntohl(iface->dhcpv4_start_ip.s_addr); 971 uint32_t end = ntohl(iface->dhcpv4_end_ip.s_addr); 972 uint32_t count = end - start + 1; 973 uint32_t seed = 0; 974 bool assigned; 975 976 /* Preconfigured IP address by static lease */ 977 if (a->addr) { 978 assigned = dhcpv4_insert_assignment(&iface->dhcpv4_assignments, 979 a, a->addr); 980 981 if (assigned) 982 syslog(LOG_DEBUG, "Assigning static IP: %s", ip4toa(a->addr)); 983 984 return assigned; 985 } 986 987 /* try to assign the IP the client asked for */ 988 if (start <= ntohl(raddr) && ntohl(raddr) <= end && 989 !config_find_lease_by_ipaddr(raddr)) { 990 assigned = dhcpv4_insert_assignment(&iface->dhcpv4_assignments, 991 a, raddr); 992 993 if (assigned) { 994 syslog(LOG_DEBUG, "Assigning the IP the client asked for: %s", 995 ip4toa(a->addr)); 996 997 return true; 998 } 999 } 1000 1001 /* Seed RNG with checksum of hwaddress */ 1002 for (size_t i = 0; i < sizeof(a->hwaddr); ++i) { 1003 /* Knuth's multiplicative method */ 1004 uint8_t o = a->hwaddr[i]; 1005 seed += (o*2654435761) % UINT32_MAX; 1006 } 1007 1008 srand(seed); 1009 1010 for (uint32_t i = 0, try = (((uint32_t)rand()) % count) + start; i < count; 1011 ++i, try = (((try - start) + 1) % count) + start) { 1012 uint32_t n_try = htonl(try); 1013 1014 if (config_find_lease_by_ipaddr(n_try)) 1015 continue; 1016 1017 assigned = dhcpv4_insert_assignment(&iface->dhcpv4_assignments, 1018 a, n_try); 1019 1020 if (assigned) { 1021 syslog(LOG_DEBUG, "Assigning mapped IP: %s (try %u of %u)", 1022 ip4toa(a->addr), i + 1, count); 1023 1024 return true; 1025 } 1026 } 1027 1028 syslog(LOG_NOTICE, "Can't assign any IP address -> address space is full"); 1029 1030 return false; 1031 } 1032 1033 1034 static struct dhcp_assignment* 1035 dhcpv4_lease(struct interface *iface, enum dhcpv4_msg msg, const uint8_t *mac, 1036 const uint32_t reqaddr, uint32_t *leasetime, const char *hostname, 1037 const size_t hostname_len, const bool accept_fr_nonce, bool *incl_fr_opt, 1038 uint32_t *fr_serverid, const char* reqopts, const size_t reqopts_len) 1039 { 1040 struct dhcp_assignment *a = find_assignment_by_hwaddr(iface, mac); 1041 struct lease *l = config_find_lease_by_mac(mac); 1042 time_t now = odhcpd_time(); 1043 1044 if (l && a && a->lease != l) { 1045 free_assignment(a); 1046 a = NULL; 1047 } 1048 1049 if (a && (a->flags & OAF_BOUND) && a->fr_ip) { 1050 *fr_serverid = a->fr_ip->addr.addr.in.s_addr; 1051 dhcpv4_fr_stop(a); 1052 } 1053 1054 if (msg == DHCPV4_MSG_DISCOVER || msg == DHCPV4_MSG_REQUEST) { 1055 bool assigned = !!a; 1056 1057 if (!a) { 1058 if (!iface->no_dynamic_dhcp || l) { 1059 /* Create new binding */ 1060 a = alloc_assignment(0); 1061 if (!a) { 1062 syslog(LOG_WARNING, "Failed to alloc assignment on interface %s", 1063 iface->ifname); 1064 return NULL; 1065 } 1066 memcpy(a->hwaddr, mac, sizeof(a->hwaddr)); 1067 /* Set valid time to 0 for static lease indicating */ 1068 /* infinite lifetime otherwise current time */ 1069 a->valid_until = l ? 0 : now; 1070 a->dhcp_free_cb = dhcpv4_free_assignment; 1071 a->iface = iface; 1072 a->flags = OAF_DHCPV4; 1073 a->addr = l ? l->ipaddr : INADDR_ANY; 1074 1075 assigned = dhcpv4_assign(iface, a, reqaddr); 1076 1077 if (l) { 1078 a->flags |= OAF_STATIC; 1079 1080 if (l->hostname) 1081 a->hostname = strdup(l->hostname); 1082 1083 if (l->leasetime) 1084 a->leasetime = l->leasetime; 1085 1086 list_add(&a->lease_list, &l->assignments); 1087 a->lease = l; 1088 } 1089 } 1090 } else if (((a->addr & iface->dhcpv4_mask.s_addr) != 1091 (iface->dhcpv4_start_ip.s_addr & iface->dhcpv4_mask.s_addr)) && 1092 !(a->flags & OAF_STATIC)) { 1093 list_del_init(&a->head); 1094 a->addr = INADDR_ANY; 1095 1096 assigned = dhcpv4_assign(iface, a, reqaddr); 1097 } 1098 1099 if (assigned) { 1100 uint32_t my_leasetime; 1101 1102 if (a->leasetime) 1103 my_leasetime = a->leasetime; 1104 else 1105 my_leasetime = iface->dhcp_leasetime; 1106 1107 if ((*leasetime == 0) || (my_leasetime < *leasetime)) 1108 *leasetime = my_leasetime; 1109 1110 if (msg == DHCPV4_MSG_DISCOVER) { 1111 a->flags &= ~OAF_BOUND; 1112 1113 *incl_fr_opt = accept_fr_nonce; 1114 a->valid_until = now; 1115 } else { 1116 if ((!(a->flags & OAF_STATIC) || !a->hostname) && hostname_len > 0) { 1117 a->hostname = realloc(a->hostname, hostname_len + 1); 1118 if (a->hostname) { 1119 memcpy(a->hostname, hostname, hostname_len); 1120 a->hostname[hostname_len] = 0; 1121 1122 if (odhcpd_valid_hostname(a->hostname)) 1123 a->flags &= ~OAF_BROKEN_HOSTNAME; 1124 else 1125 a->flags |= OAF_BROKEN_HOSTNAME; 1126 } 1127 } 1128 1129 if (reqopts_len > 0) { 1130 a->reqopts = realloc(a->reqopts, reqopts_len + 1); 1131 if (a->reqopts) { 1132 memcpy(a->reqopts, reqopts, reqopts_len); 1133 a->reqopts[reqopts_len] = 0; 1134 } 1135 } 1136 1137 if (!(a->flags & OAF_BOUND)) { 1138 a->accept_fr_nonce = accept_fr_nonce; 1139 *incl_fr_opt = accept_fr_nonce; 1140 odhcpd_urandom(a->key, sizeof(a->key)); 1141 a->flags |= OAF_BOUND; 1142 } else 1143 *incl_fr_opt = false; 1144 1145 a->valid_until = ((*leasetime == UINT32_MAX) ? 0 : (time_t)(now + *leasetime)); 1146 } 1147 } else if (!assigned && a) { 1148 /* Cleanup failed assignment */ 1149 free_assignment(a); 1150 a = NULL; 1151 } 1152 1153 } else if (msg == DHCPV4_MSG_RELEASE && a) { 1154 a->flags &= ~OAF_BOUND; 1155 a->valid_until = now - 1; 1156 1157 } else if (msg == DHCPV4_MSG_DECLINE && a) { 1158 a->flags &= ~OAF_BOUND; 1159 1160 if (!(a->flags & OAF_STATIC) || a->lease->ipaddr != a->addr) { 1161 memset(a->hwaddr, 0, sizeof(a->hwaddr)); 1162 a->valid_until = now + 3600; /* Block address for 1h */ 1163 } else 1164 a->valid_until = now - 1; 1165 } 1166 1167 dhcpv6_ia_write_statefile(); 1168 1169 return a; 1170 } 1171
This page was automatically generated by LXR 0.3.1. • OpenWrt