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