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 MAX_PREFIX_LEN 28 40 41 static uint32_t serial = 0; 42 43 struct odhcpd_ref_ip { 44 struct list_head head; 45 int ref_cnt; 46 struct odhcpd_ipaddr addr; 47 }; 48 49 static void inc_ref_cnt_ip(struct odhcpd_ref_ip **ptr, struct odhcpd_ref_ip *ip) 50 { 51 *ptr = ip; 52 ip->ref_cnt++; 53 } 54 55 static void decr_ref_cnt_ip(struct odhcpd_ref_ip **ptr, struct interface *iface) 56 { 57 struct odhcpd_ref_ip *ip = *ptr; 58 59 if (--ip->ref_cnt == 0) { 60 netlink_setup_addr(&ip->addr, iface->ifindex, false, false); 61 62 list_del(&ip->head); 63 free(ip); 64 } 65 66 *ptr = NULL; 67 } 68 69 static bool addr_is_fr_ip(struct interface *iface, struct in_addr *addr) 70 { 71 struct odhcpd_ref_ip *p; 72 73 list_for_each_entry(p, &iface->dhcpv4_fr_ips, head) { 74 if (addr->s_addr == p->addr.addr.in.s_addr) 75 return true; 76 } 77 78 return false; 79 } 80 81 static bool leases_require_fr(struct interface *iface, struct odhcpd_ipaddr *addr, 82 uint32_t mask) 83 { 84 struct dhcpv4_lease *lease = NULL; 85 struct odhcpd_ref_ip *fr_ip = NULL; 86 87 list_for_each_entry(lease, &iface->dhcpv4_leases, head) { 88 if ((lease->accept_fr_nonce || iface->dhcpv4_forcereconf) && 89 !lease->fr_ip && 90 ((lease->addr & mask) == (addr->addr.in.s_addr & mask))) { 91 if (!fr_ip) { 92 fr_ip = calloc(1, sizeof(*fr_ip)); 93 if (!fr_ip) 94 break; 95 96 list_add(&fr_ip->head, &iface->dhcpv4_fr_ips); 97 fr_ip->addr = *addr; 98 } 99 inc_ref_cnt_ip(&lease->fr_ip, fr_ip); 100 } 101 } 102 103 return fr_ip ? true : false; 104 } 105 106 static const char *dhcpv4_msg_to_string(uint8_t req_msg) 107 { 108 static const char *dhcpv4_msg_names[] = { 109 [DHCPV4_MSG_DISCOVER] = "DHCPV4_MSG_DISCOVER", 110 [DHCPV4_MSG_OFFER] = "DHCPV4_MSG_OFFER", 111 [DHCPV4_MSG_REQUEST] = "DHCPV4_MSG_REQUEST", 112 [DHCPV4_MSG_DECLINE] = "DHCPV4_MSG_DECLINE", 113 [DHCPV4_MSG_ACK] = "DHCPV4_MSG_ACK", 114 [DHCPV4_MSG_NAK] = "DHCPV4_MSG_NAK", 115 [DHCPV4_MSG_RELEASE] = "DHCPV4_MSG_RELEASE", 116 [DHCPV4_MSG_INFORM] = "DHCPV4_MSG_INFORM", 117 [DHCPV4_MSG_FORCERENEW] = "DHCPV4_MSG_FORCERENEW", 118 [DHCPV4_MSG_LEASEQUERY] = "DHCPV4_MSG_LEASEQUERY", 119 [DHCPV4_MSG_LEASEUNASSIGNED] = "DHCPV4_MSG_LEASEUNASSIGNED", 120 [DHCPV4_MSG_LEASEUNKNOWN] = "DHCPV4_MSG_LEASEUNKNOWN", 121 [DHCPV4_MSG_LEASEACTIVE] = "DHCPV4_MSG_LEASEACTIVE", 122 [DHCPV4_MSG_BULKLEASEQUERY] = "DHCPV4_MSG_BULKLEASEQUERY", 123 [DHCPV4_MSG_LEASEQUERYDONE] = "DHCPV4_MSG_LEASEQUERYDONE", 124 [DHCPV4_MSG_ACTIVELEASEQUERY] = "DHCPV4_MSG_ACTIVELEASEQUERY", 125 [DHCPV4_MSG_LEASEQUERYSTATUS] = "DHCPV4_MSG_LEASEQUERYSTATUS", 126 [DHCPV4_MSG_TLS] = "DHCPV4_MSG_TLS", 127 }; 128 129 if (req_msg >= ARRAY_SIZE(dhcpv4_msg_names)) 130 return "UNKNOWN"; 131 return dhcpv4_msg_names[req_msg]; 132 } 133 134 static ssize_t dhcpv4_send_reply(struct iovec *iov, size_t iov_len, 135 struct sockaddr *dest, socklen_t dest_len, 136 void *opaque) 137 { 138 int *sock = opaque; 139 struct msghdr msg = { 140 .msg_name = dest, 141 .msg_namelen = dest_len, 142 .msg_iov = iov, 143 .msg_iovlen = iov_len, 144 }; 145 146 return sendmsg(*sock, &msg, MSG_DONTWAIT); 147 } 148 149 static void dhcpv4_add_padding(struct iovec *iov, size_t iovlen) 150 { 151 // Theoretical max padding = vendor-specific area, RFC951, ยง3 152 static uint8_t padding[64] = { 0 }; 153 size_t len = 0; 154 155 if (!iov || !iovlen) 156 return; 157 158 iov[iovlen - 1].iov_base = padding; 159 iov[iovlen - 1].iov_len = 0; 160 161 for (size_t i = 0; i < iovlen; i++) 162 len += iov[i].iov_len; 163 164 if (len < DHCPV4_MIN_PACKET_SIZE) 165 iov[iovlen - 1].iov_len = DHCPV4_MIN_PACKET_SIZE - len; 166 } 167 168 enum { 169 IOV_FR_HEADER = 0, 170 IOV_FR_MESSAGE, 171 IOV_FR_AUTH, 172 IOV_FR_AUTH_BODY, 173 IOV_FR_SERVERID, 174 IOV_FR_END, 175 IOV_FR_PADDING, 176 IOV_FR_TOTAL 177 }; 178 179 static void dhcpv4_fr_send(struct dhcpv4_lease *lease) 180 { 181 struct dhcpv4_message fr = { 182 .op = DHCPV4_OP_BOOTREPLY, 183 .htype = ARPHRD_ETHER, 184 .hlen = ETH_ALEN, 185 .hops = 0, 186 .xid = 0, 187 .secs = 0, 188 .flags = 0, 189 .ciaddr = { INADDR_ANY }, 190 .yiaddr = { INADDR_ANY }, 191 .siaddr = { INADDR_ANY }, 192 .giaddr = { INADDR_ANY }, 193 .chaddr = { 0 }, 194 .sname = { 0 }, 195 .file = { 0 }, 196 .cookie = htonl(DHCPV4_MAGIC_COOKIE), 197 }; 198 struct dhcpv4_option_u8 fr_msg = { 199 .code = DHCPV4_OPT_MESSAGE, 200 .len = sizeof(uint8_t), 201 .data = DHCPV4_MSG_FORCERENEW, 202 }; 203 struct dhcpv4_auth_forcerenew fr_auth_body = { 204 .protocol = DHCPV4_AUTH_PROTO_RKAP, 205 .algorithm = DHCPV4_AUTH_ALG_HMAC_MD5, 206 .rdm = DHCPV4_AUTH_RDM_MONOTONIC, 207 .type = DHCPV4_AUTH_RKAP_AI_TYPE_MD5_DIGEST, 208 .key = { 0 }, 209 }; 210 struct dhcpv4_option fr_auth = { 211 .code = DHCPV4_OPT_AUTHENTICATION, 212 .len = sizeof(fr_auth_body), 213 }; 214 struct dhcpv4_option_u32 fr_serverid = { 215 .code = DHCPV4_OPT_SERVERID, 216 .len = sizeof(struct in_addr), 217 .data = lease->fr_ip->addr.addr.in.s_addr, 218 }; 219 uint8_t fr_end = DHCPV4_OPT_END; 220 221 struct iovec iov[IOV_FR_TOTAL] = { 222 [IOV_FR_HEADER] = { &fr, sizeof(fr) }, 223 [IOV_FR_MESSAGE] = { &fr_msg, sizeof(fr_msg) }, 224 [IOV_FR_AUTH] = { &fr_auth, 0 }, 225 [IOV_FR_AUTH_BODY] = { &fr_auth_body, 0 }, 226 [IOV_FR_SERVERID] = { &fr_serverid, 0 }, 227 [IOV_FR_END] = { &fr_end, sizeof(fr_end) }, 228 [IOV_FR_PADDING] = { NULL, 0 }, 229 }; 230 231 struct sockaddr_in dest = { 232 .sin_family = AF_INET, 233 .sin_port = htons(DHCPV4_CLIENT_PORT), 234 .sin_addr = { lease->addr }, 235 }; 236 237 odhcpd_urandom(&fr.xid, sizeof(fr.xid)); 238 memcpy(fr.chaddr, lease->hwaddr, fr.hlen); 239 240 if (lease->accept_fr_nonce) { 241 uint8_t secretbytes[64] = { 0 }; 242 md5_ctx_t md5; 243 244 fr_auth_body.replay[0] = htonl(time(NULL)); 245 fr_auth_body.replay[1] = htonl(++serial); 246 iov[IOV_FR_AUTH].iov_len = sizeof(fr_auth); 247 iov[IOV_FR_AUTH_BODY].iov_len = sizeof(fr_auth_body); 248 dhcpv4_add_padding(iov, ARRAY_SIZE(iov)); 249 250 memcpy(secretbytes, lease->key, sizeof(lease->key)); 251 for (size_t i = 0; i < sizeof(secretbytes); ++i) 252 secretbytes[i] ^= 0x36; 253 254 md5_begin(&md5); 255 md5_hash(secretbytes, sizeof(secretbytes), &md5); 256 for (size_t i = 0; i < ARRAY_SIZE(iov); i++) 257 md5_hash(iov[i].iov_base, iov[i].iov_len, &md5); 258 md5_end(fr_auth_body.key, &md5); 259 260 for (size_t i = 0; i < sizeof(secretbytes); ++i) { 261 secretbytes[i] ^= 0x36; 262 secretbytes[i] ^= 0x5c; 263 } 264 265 md5_begin(&md5); 266 md5_hash(secretbytes, sizeof(secretbytes), &md5); 267 md5_hash(fr_auth_body.key, sizeof(fr_auth_body.key), &md5); 268 md5_end(fr_auth_body.key, &md5); 269 } else { 270 iov[IOV_FR_SERVERID].iov_len = sizeof(fr_serverid); 271 dhcpv4_add_padding(iov, ARRAY_SIZE(iov)); 272 } 273 274 if (dhcpv4_send_reply(iov, ARRAY_SIZE(iov), (struct sockaddr *)&dest, sizeof(dest), 275 &lease->iface->dhcpv4_event.uloop.fd) < 0) 276 error("Failed to send %s to %s - %s: %m", dhcpv4_msg_to_string(fr_msg.data), 277 odhcpd_print_mac(lease->hwaddr, sizeof(lease->hwaddr)), inet_ntoa(dest.sin_addr)); 278 else 279 debug("Sent %s to %s - %s", dhcpv4_msg_to_string(fr_msg.data), 280 odhcpd_print_mac(lease->hwaddr, sizeof(lease->hwaddr)), inet_ntoa(dest.sin_addr)); 281 } 282 283 static void dhcpv4_fr_stop(struct dhcpv4_lease *lease) 284 { 285 uloop_timeout_cancel(&lease->fr_timer); 286 decr_ref_cnt_ip(&lease->fr_ip, lease->iface); 287 lease->fr_cnt = 0; 288 lease->fr_timer.cb = NULL; 289 } 290 291 static void dhcpv4_fr_timer(struct uloop_timeout *event) 292 { 293 struct dhcpv4_lease *lease = container_of(event, struct dhcpv4_lease, fr_timer); 294 295 if (lease->fr_cnt > 0 && lease->fr_cnt < 8) { 296 dhcpv4_fr_send(lease); 297 uloop_timeout_set(&lease->fr_timer, 1000 << lease->fr_cnt); 298 lease->fr_cnt++; 299 } else 300 dhcpv4_fr_stop(lease); 301 } 302 303 static void dhcpv4_fr_start(struct dhcpv4_lease *lease) 304 { 305 uloop_timeout_set(&lease->fr_timer, 1000 << lease->fr_cnt); 306 lease->fr_timer.cb = dhcpv4_fr_timer; 307 lease->fr_cnt++; 308 309 dhcpv4_fr_send(lease); 310 } 311 312 static void dhcpv4_fr_rand_delay(struct dhcpv4_lease *lease); 313 314 static void dhcpv4_fr_delay_timer(struct uloop_timeout *event) 315 { 316 struct dhcpv4_lease *lease = container_of(event, struct dhcpv4_lease, fr_timer); 317 struct interface *iface = lease->iface; 318 319 (iface->dhcpv4_event.uloop.fd == -1 ? dhcpv4_fr_rand_delay(lease) : dhcpv4_fr_start(lease)); 320 } 321 322 static void dhcpv4_fr_rand_delay(struct dhcpv4_lease *lease) 323 { 324 int msecs; 325 326 odhcpd_urandom(&msecs, sizeof(msecs)); 327 328 msecs = abs(msecs) % DHCPV4_FR_MAX_FUZZ + DHCPV4_FR_MIN_DELAY; 329 330 uloop_timeout_set(&lease->fr_timer, msecs); 331 lease->fr_timer.cb = dhcpv4_fr_delay_timer; 332 } 333 334 void dhcpv4_free_lease(struct dhcpv4_lease *lease) 335 { 336 if (lease->fr_ip) 337 dhcpv4_fr_stop(lease); 338 339 list_del(&lease->head); 340 if (lease->lease_cfg) 341 lease->lease_cfg->dhcpv4_lease = NULL; 342 343 free(lease->hostname); 344 free(lease); 345 } 346 347 static struct dhcpv4_lease * 348 dhcpv4_alloc_lease(struct interface *iface, const uint8_t *hwaddr, size_t hwaddr_len) 349 { 350 struct dhcpv4_lease *lease; 351 352 if (!iface || !hwaddr || hwaddr_len == 0 || hwaddr_len > sizeof(lease->hwaddr)) 353 return NULL; 354 355 lease = calloc(1, sizeof(*lease)); 356 if (!lease) 357 return NULL; 358 359 INIT_LIST_HEAD(&lease->head); 360 361 lease->hwaddr_len = hwaddr_len; 362 memcpy(lease->hwaddr, hwaddr, hwaddr_len); 363 lease->iface = iface; 364 365 return lease; 366 } 367 368 static bool dhcpv4_insert_lease(struct list_head *list, struct dhcpv4_lease *lease, 369 uint32_t addr) 370 { 371 uint32_t h_addr = ntohl(addr); 372 struct dhcpv4_lease *c; 373 374 list_for_each_entry(c, list, head) { 375 uint32_t c_addr = ntohl(c->addr); 376 377 if (c_addr == h_addr) 378 return false; 379 380 if (c_addr > h_addr) 381 break; 382 } 383 384 /* Insert new node before c (might match list head) */ 385 lease->addr = addr; 386 list_add_tail(&lease->head, &c->head); 387 388 return true; 389 } 390 391 static bool dhcpv4_assign(struct interface *iface, struct dhcpv4_lease *lease, 392 uint32_t raddr) 393 { 394 uint32_t start = ntohl(iface->dhcpv4_start_ip.s_addr); 395 uint32_t end = ntohl(iface->dhcpv4_end_ip.s_addr); 396 uint32_t count = end - start + 1; 397 uint32_t seed = 0; 398 char ipv4_str[INET_ADDRSTRLEN]; 399 400 /* Preconfigured IP address by static lease */ 401 if (lease->addr) { 402 if (!dhcpv4_insert_lease(&iface->dhcpv4_leases, lease, lease->addr)) { 403 error("The static IP address is already assigned: %s", 404 inet_ntop(AF_INET, &lease->addr, ipv4_str, sizeof(ipv4_str))); 405 return false; 406 } 407 408 debug("Assigned static IP address: %s", 409 inet_ntop(AF_INET, &lease->addr, ipv4_str, sizeof(ipv4_str))); 410 return true; 411 } 412 413 /* The client asked for a specific address, let's try... */ 414 if (ntohl(raddr) < start || ntohl(raddr) > end) { 415 debug("The requested IP address is outside the pool: %s", 416 inet_ntop(AF_INET, &raddr, ipv4_str, sizeof(ipv4_str))); 417 } else if (config_find_lease_cfg_by_ipaddr(raddr)) { 418 debug("The requested IP address is statically assigned: %s", 419 inet_ntop(AF_INET, &raddr, ipv4_str, sizeof(ipv4_str))); 420 } else if (!dhcpv4_insert_lease(&iface->dhcpv4_leases, lease, raddr)) { 421 debug("The requested IP address is already assigned: %s", 422 inet_ntop(AF_INET, &raddr, ipv4_str, sizeof(ipv4_str))); 423 } else { 424 debug("Assigned the requested IP address: %s", 425 inet_ntop(AF_INET, &lease->addr, ipv4_str, sizeof(ipv4_str))); 426 return true; 427 } 428 429 /* Ok, we'll have to pick an address for the client... */ 430 for (size_t i = 0; i < sizeof(lease->hwaddr); ++i) { 431 /* ...hash the hwaddr (Knuth's multiplicative method)... */ 432 uint8_t o = lease->hwaddr[i]; 433 seed += (o * 2654435761) % UINT32_MAX; 434 } 435 436 /* ...use it to seed the RNG... */ 437 srand(seed); 438 439 /* ...and try a bunch of times to assign a randomly chosen address */ 440 for (uint32_t i = 0, try = (((uint32_t)rand()) % count) + start; i < count; 441 ++i, try = (((try - start) + 1) % count) + start) { 442 uint32_t n_try = htonl(try); 443 444 if (config_find_lease_cfg_by_ipaddr(n_try)) 445 continue; 446 447 if (dhcpv4_insert_lease(&iface->dhcpv4_leases, lease, n_try)) { 448 debug("Assigned IP adress from pool: %s (succeeded on attempt %u of %u)", 449 inet_ntop(AF_INET, &lease->addr, ipv4_str, sizeof(ipv4_str)), 450 i + 1, count); 451 return true; 452 } 453 } 454 455 warn("Can't assign any IP address -> address space is full"); 456 457 return false; 458 } 459 460 static struct dhcpv4_lease *find_lease_by_hwaddr(struct interface *iface, const uint8_t *hwaddr) 461 { 462 struct dhcpv4_lease *lease; 463 464 list_for_each_entry(lease, &iface->dhcpv4_leases, head) 465 if (!memcmp(lease->hwaddr, hwaddr, 6)) 466 return lease; 467 468 return NULL; 469 } 470 471 static struct dhcpv4_lease * 472 dhcpv4_lease(struct interface *iface, enum dhcpv4_msg req_msg, const uint8_t *req_mac, 473 const uint32_t req_addr, uint32_t *req_leasetime, const char *req_hostname, 474 const size_t req_hostname_len, const bool req_accept_fr, bool *reply_incl_fr, 475 uint32_t *fr_serverid) 476 { 477 struct dhcpv4_lease *lease = find_lease_by_hwaddr(iface, req_mac); 478 struct lease_cfg *lease_cfg = config_find_lease_cfg_by_mac(req_mac); 479 time_t now = odhcpd_time(); 480 481 /* 482 * If we found a static lease cfg, but no old assignment for this 483 * hwaddr, we need to clear out any old assignments given to other 484 * hwaddrs in order to take over the IP address. 485 */ 486 if (lease_cfg && !lease && (req_msg == DHCPV4_MSG_DISCOVER || req_msg == DHCPV4_MSG_REQUEST)) { 487 if (lease_cfg->dhcpv4_lease) 488 dhcpv4_free_lease(lease_cfg->dhcpv4_lease); 489 } 490 491 if (lease_cfg && lease && lease->lease_cfg != lease_cfg) { 492 dhcpv4_free_lease(lease); 493 lease = NULL; 494 } 495 496 if (lease && (lease->flags & OAF_BOUND) && lease->fr_ip) { 497 *fr_serverid = lease->fr_ip->addr.addr.in.s_addr; 498 dhcpv4_fr_stop(lease); 499 } 500 501 switch (req_msg) { 502 case DHCPV4_MSG_RELEASE: 503 if (!lease) 504 return NULL; 505 506 ubus_bcast_dhcp_event("dhcp.release", req_mac, 507 (struct in_addr *)&lease->addr, 508 lease->hostname, iface->ifname); 509 dhcpv4_free_lease(lease); 510 lease = NULL; 511 break; 512 513 case DHCPV4_MSG_DECLINE: 514 if (!lease) 515 return NULL; 516 517 lease->flags &= ~OAF_BOUND; 518 519 if (!(lease->flags & OAF_STATIC) || lease->lease_cfg->ipaddr != lease->addr) { 520 memset(lease->hwaddr, 0, sizeof(lease->hwaddr)); 521 lease->valid_until = now + 3600; /* Block address for 1h */ 522 } else 523 lease->valid_until = now - 1; 524 break; 525 526 case DHCPV4_MSG_DISCOVER: 527 _fallthrough; 528 529 case DHCPV4_MSG_REQUEST: 530 if (!lease && iface->no_dynamic_dhcp && !lease_cfg) 531 return NULL; 532 533 /* Old lease, but with an address that is out-of-scope? */ 534 if (lease && ((lease->addr & iface->dhcpv4_mask.s_addr) != 535 (iface->dhcpv4_start_ip.s_addr & iface->dhcpv4_mask.s_addr)) && 536 !(lease->flags & OAF_STATIC)) { 537 /* Try to reassign to an address that is in-scope */ 538 list_del_init(&lease->head); 539 lease->addr = INADDR_ANY; 540 if (!dhcpv4_assign(iface, lease, req_addr)) { 541 dhcpv4_free_lease(lease); 542 lease = NULL; 543 break; 544 } 545 } 546 547 if (!lease) { 548 /* Create new binding */ 549 lease = dhcpv4_alloc_lease(iface, req_mac, ETH_ALEN); 550 if (!lease) { 551 warn("Failed to allocate memory for DHCPv4 lease on interface %s", iface->ifname); 552 return NULL; 553 } 554 555 /* static lease => infinite (0), else a placeholder */ 556 lease->valid_until = lease_cfg ? 0 : now; 557 lease->addr = lease_cfg ? lease_cfg->ipaddr : INADDR_ANY; 558 559 if (!dhcpv4_assign(iface, lease, req_addr)) { 560 dhcpv4_free_lease(lease); 561 return NULL; 562 } 563 564 if (lease_cfg) { 565 lease->flags |= OAF_STATIC; 566 567 if (lease_cfg->hostname) 568 lease->hostname = strdup(lease_cfg->hostname); 569 570 lease_cfg->dhcpv4_lease = lease; 571 lease->lease_cfg = lease_cfg; 572 } 573 } 574 575 /* See if we need to clamp the requested leasetime */ 576 uint32_t max_leasetime; 577 if (lease->lease_cfg && lease->lease_cfg->leasetime) 578 max_leasetime = lease->lease_cfg->leasetime; 579 else 580 max_leasetime = iface->dhcp_leasetime; 581 582 if ((*req_leasetime == 0) || (max_leasetime < *req_leasetime)) 583 *req_leasetime = max_leasetime; 584 585 if (req_msg == DHCPV4_MSG_DISCOVER) { 586 lease->flags &= ~OAF_BOUND; 587 *reply_incl_fr = req_accept_fr; 588 lease->valid_until = now; 589 break; 590 } 591 592 if ((!(lease->flags & OAF_STATIC) || !lease->hostname) && req_hostname_len > 0) { 593 char *new_name = realloc(lease->hostname, req_hostname_len + 1); 594 if (new_name) { 595 lease->hostname = new_name; 596 memcpy(lease->hostname, req_hostname, req_hostname_len); 597 lease->hostname[req_hostname_len] = 0; 598 599 if (odhcpd_valid_hostname(lease->hostname)) 600 lease->flags &= ~OAF_BROKEN_HOSTNAME; 601 else 602 lease->flags |= OAF_BROKEN_HOSTNAME; 603 } 604 } 605 606 *reply_incl_fr = false; 607 if (!(lease->flags & OAF_BOUND)) { 608 /* This is the client's first request for the address */ 609 if (req_accept_fr) { 610 lease->accept_fr_nonce = true; 611 *reply_incl_fr = true; 612 odhcpd_urandom(lease->key, sizeof(lease->key)); 613 } 614 lease->flags |= OAF_BOUND; 615 } 616 617 if (*req_leasetime == UINT32_MAX) 618 lease->valid_until = 0; 619 else 620 lease->valid_until = (time_t)(now + *req_leasetime); 621 break; 622 623 default: 624 return NULL; 625 } 626 627 dhcpv6_ia_write_statefile(); 628 return lease; 629 } 630 631 static void dhcpv4_set_dest_addr(const struct interface *iface, 632 uint8_t reply_msg, 633 const struct dhcpv4_message *req, 634 const struct dhcpv4_message *reply, 635 const struct sockaddr_in *src, 636 struct sockaddr_in *dest) 637 { 638 *dest = *src; 639 640 //struct sockaddr_in dest = *((struct sockaddr_in*)addr); 641 if (req->giaddr.s_addr) { 642 /* 643 * relay agent is configured, send reply to the agent 644 */ 645 dest->sin_addr = req->giaddr; 646 dest->sin_port = htons(DHCPV4_SERVER_PORT); 647 648 } else if (req->ciaddr.s_addr && req->ciaddr.s_addr != dest->sin_addr.s_addr) { 649 /* 650 * client has existing configuration (ciaddr is set) AND this 651 * address is not the address it used for the dhcp message 652 */ 653 dest->sin_addr = req->ciaddr; 654 dest->sin_port = htons(DHCPV4_CLIENT_PORT); 655 656 } else if (ntohs(req->flags) & DHCPV4_FLAG_BROADCAST || 657 req->hlen != reply->hlen || !reply->yiaddr.s_addr) { 658 /* 659 * client requests a broadcast reply OR we can't offer an IP 660 */ 661 dest->sin_addr.s_addr = INADDR_BROADCAST; 662 dest->sin_port = htons(DHCPV4_CLIENT_PORT); 663 664 } else if (!req->ciaddr.s_addr && reply_msg == DHCPV4_MSG_NAK) { 665 /* 666 * client has no previous configuration -> no IP, so we need to 667 * reply with a broadcast packet 668 */ 669 dest->sin_addr.s_addr = INADDR_BROADCAST; 670 dest->sin_port = htons(DHCPV4_CLIENT_PORT); 671 672 } else { 673 /* 674 * send reply to the newly allocated IP 675 */ 676 dest->sin_addr = reply->yiaddr; 677 dest->sin_port = htons(DHCPV4_CLIENT_PORT); 678 679 if (!(iface->ifflags & IFF_NOARP)) { 680 struct arpreq arp = { .arp_flags = ATF_COM }; 681 682 memcpy(arp.arp_ha.sa_data, req->chaddr, 6); 683 memcpy(&arp.arp_pa, dest, sizeof(arp.arp_pa)); 684 memcpy(arp.arp_dev, iface->ifname, sizeof(arp.arp_dev)); 685 686 if (ioctl(iface->dhcpv4_event.uloop.fd, SIOCSARP, &arp) < 0) 687 error("ioctl(SIOCSARP): %m"); 688 } 689 } 690 } 691 692 enum { 693 IOV_HEADER = 0, 694 IOV_MESSAGE, 695 IOV_SERVERID, 696 IOV_NETMASK, 697 IOV_ROUTER, 698 IOV_ROUTER_ADDR, 699 IOV_DNSSERVER, 700 IOV_DNSSERVER_ADDR, 701 IOV_HOSTNAME, 702 IOV_HOSTNAME_NAME, 703 IOV_MTU, 704 IOV_BROADCAST, 705 IOV_NTP, 706 IOV_NTP_ADDR, 707 IOV_LEASETIME, 708 IOV_RENEW, 709 IOV_REBIND, 710 IOV_AUTH, 711 IOV_AUTH_BODY, 712 IOV_SRCH_DOMAIN, 713 IOV_SRCH_DOMAIN_NAME, 714 IOV_FR_NONCE_CAP, 715 IOV_DNR, 716 IOV_DNR_BODY, 717 IOV_END, 718 IOV_PADDING, 719 IOV_TOTAL 720 }; 721 722 void dhcpv4_handle_msg(void *src_addr, void *data, size_t len, 723 struct interface *iface, _unused void *our_dest_addr, 724 send_reply_cb_t send_reply, void *opaque) 725 { 726 /* Request variables */ 727 struct dhcpv4_message *req = data; 728 uint8_t req_msg = DHCPV4_MSG_REQUEST; 729 uint8_t *req_opts = NULL; 730 size_t req_opts_len = 0; 731 uint32_t req_addr = INADDR_ANY; 732 uint32_t req_leasetime = 0; 733 char *req_hostname = NULL; 734 size_t req_hostname_len = 0; 735 bool req_accept_fr = false; 736 737 /* Reply variables */ 738 struct dhcpv4_message reply = { 739 .op = DHCPV4_OP_BOOTREPLY, 740 .htype = ARPHRD_ETHER, 741 .hlen = ETH_ALEN, 742 .hops = 0, 743 .xid = req->xid, 744 .secs = 0, 745 .flags = req->flags, 746 .ciaddr = { INADDR_ANY }, 747 .yiaddr = { INADDR_ANY }, 748 .siaddr = iface->dhcpv4_local, 749 .giaddr = req->giaddr, 750 .chaddr = { 0 }, 751 .sname = { 0 }, 752 .file = { 0 }, 753 .cookie = htonl(DHCPV4_MAGIC_COOKIE), 754 }; 755 struct dhcpv4_option_u8 reply_msg = { 756 .code = DHCPV4_OPT_MESSAGE, 757 .len = sizeof(uint8_t), 758 .data = DHCPV4_MSG_ACK, 759 }; 760 struct dhcpv4_option_u32 reply_serverid = { 761 .code = DHCPV4_OPT_SERVERID, 762 .len = sizeof(struct in_addr), 763 .data = iface->dhcpv4_local.s_addr, 764 }; 765 struct dhcpv4_option_u32 reply_netmask = { 766 .code = DHCPV4_OPT_NETMASK, 767 .len = sizeof(uint32_t), 768 }; 769 struct dhcpv4_option reply_router = { 770 .code = DHCPV4_OPT_ROUTER, 771 }; 772 struct dhcpv4_option reply_dnsserver = { 773 .code = DHCPV4_OPT_DNSSERVER, 774 }; 775 struct dhcpv4_option reply_hostname = { 776 .code = DHCPV4_OPT_HOSTNAME, 777 }; 778 struct dhcpv4_option_u16 reply_mtu = { 779 .code = DHCPV4_OPT_MTU, 780 .len = sizeof(uint16_t), 781 }; 782 struct dhcpv4_option_u32 reply_broadcast = { 783 .code = DHCPV4_OPT_BROADCAST, 784 .len = sizeof(uint32_t), 785 }; 786 struct dhcpv4_option reply_ntp = { 787 .code = DHCPV4_OPT_NTPSERVER, 788 .len = iface->dhcpv4_ntp_cnt * sizeof(*iface->dhcpv4_ntp), 789 }; 790 struct dhcpv4_option_u32 reply_leasetime = { 791 .code = DHCPV4_OPT_LEASETIME, 792 .len = sizeof(uint32_t), 793 }; 794 struct dhcpv4_option_u32 reply_renew = { 795 .code = DHCPV4_OPT_RENEW, 796 .len = sizeof(uint32_t), 797 }; 798 struct dhcpv4_option_u32 reply_rebind = { 799 .code = DHCPV4_OPT_REBIND, 800 .len = sizeof(uint32_t), 801 }; 802 struct dhcpv4_auth_forcerenew reply_auth_body = { 803 .protocol = DHCPV4_AUTH_PROTO_RKAP, 804 .algorithm = DHCPV4_AUTH_ALG_HMAC_MD5, 805 .rdm = DHCPV4_AUTH_RDM_MONOTONIC, 806 .type = DHCPV4_AUTH_RKAP_AI_TYPE_KEY, 807 .key = { 0 }, 808 }; 809 struct dhcpv4_option reply_auth = { 810 .code = DHCPV4_OPT_AUTHENTICATION, 811 .len = sizeof(reply_auth_body), 812 }; 813 struct dhcpv4_option reply_srch_domain = { 814 .code = DHCPV4_OPT_SEARCH_DOMAIN, 815 }; 816 struct dhcpv4_option_u8 reply_fr_nonce_cap = { 817 .code = DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE, 818 .len = sizeof(uint8_t), 819 .data = 1, 820 }; 821 struct dhcpv4_option reply_dnr = { 822 .code = DHCPV4_OPT_DNR, 823 }; 824 uint8_t reply_end = DHCPV4_OPT_END; 825 826 struct iovec iov[IOV_TOTAL] = { 827 [IOV_HEADER] = { &reply, sizeof(reply) }, 828 [IOV_MESSAGE] = { &reply_msg, sizeof(reply_msg) }, 829 [IOV_SERVERID] = { &reply_serverid, sizeof(reply_serverid) }, 830 [IOV_NETMASK] = { &reply_netmask, 0 }, 831 [IOV_ROUTER] = { &reply_router, 0 }, 832 [IOV_ROUTER_ADDR] = { NULL, 0 }, 833 [IOV_DNSSERVER] = { &reply_dnsserver, 0 }, 834 [IOV_DNSSERVER_ADDR] = { NULL, 0 }, 835 [IOV_HOSTNAME] = { &reply_hostname, 0 }, 836 [IOV_HOSTNAME_NAME] = { NULL, 0 }, 837 [IOV_MTU] = { &reply_mtu, 0 }, 838 [IOV_BROADCAST] = { &reply_broadcast, 0 }, 839 [IOV_NTP] = { &reply_ntp, 0 }, 840 [IOV_NTP_ADDR] = { iface->dhcpv4_ntp, 0 }, 841 [IOV_LEASETIME] = { &reply_leasetime, 0 }, 842 [IOV_RENEW] = { &reply_renew, 0 }, 843 [IOV_REBIND] = { &reply_rebind, 0 }, 844 [IOV_AUTH] = { &reply_auth, 0 }, 845 [IOV_AUTH_BODY] = { &reply_auth_body, 0 }, 846 [IOV_SRCH_DOMAIN] = { &reply_srch_domain, 0 }, 847 [IOV_SRCH_DOMAIN_NAME] = { NULL, 0 }, 848 [IOV_FR_NONCE_CAP] = { &reply_fr_nonce_cap, 0 }, 849 [IOV_DNR] = { &reply_dnr, 0 }, 850 [IOV_DNR_BODY] = { NULL, 0 }, 851 [IOV_END] = { &reply_end, sizeof(reply_end) }, 852 [IOV_PADDING] = { NULL, 0 }, 853 }; 854 855 /* Options which *might* be included in the reply unrequested */ 856 uint8_t std_opts[] = { 857 DHCPV4_OPT_NETMASK, 858 DHCPV4_OPT_ROUTER, 859 DHCPV4_OPT_DNSSERVER, 860 DHCPV4_OPT_HOSTNAME, 861 DHCPV4_OPT_MTU, 862 DHCPV4_OPT_BROADCAST, 863 DHCPV4_OPT_LEASETIME, 864 DHCPV4_OPT_RENEW, 865 DHCPV4_OPT_REBIND, 866 DHCPV4_OPT_AUTHENTICATION, 867 DHCPV4_OPT_SEARCH_DOMAIN, 868 DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE, 869 }; 870 871 /* Misc */ 872 struct sockaddr_in dest_addr; 873 bool reply_incl_fr = false; 874 struct dhcpv4_lease *lease = NULL; 875 uint32_t fr_serverid = INADDR_ANY; 876 877 if (iface->dhcpv4 == MODE_DISABLED) 878 return; 879 880 /* FIXME: would checking the magic cookie value here break any clients? */ 881 882 if (len < offsetof(struct dhcpv4_message, options) || 883 req->op != DHCPV4_OP_BOOTREQUEST || 884 req->htype != ARPHRD_ETHER || 885 req->hlen != ETH_ALEN) 886 return; 887 888 debug("Got DHCPv4 request on %s", iface->name); 889 890 if (!iface->dhcpv4_start_ip.s_addr && !iface->dhcpv4_end_ip.s_addr) { 891 warn("No DHCP range available on %s", iface->name); 892 return; 893 } 894 895 struct dhcpv4_option *opt; 896 dhcpv4_for_each_option(req->options, (uint8_t *)data + len, opt) { 897 switch (opt->code) { 898 case DHCPV4_OPT_PAD: 899 break; 900 case DHCPV4_OPT_HOSTNAME: 901 req_hostname = (char *)opt->data; 902 req_hostname_len = opt->len; 903 break; 904 case DHCPV4_OPT_IPADDRESS: 905 if (opt->len == 4) 906 memcpy(&req_addr, opt->data, 4); 907 break; 908 case DHCPV4_OPT_MESSAGE: 909 if (opt->len == 1) 910 req_msg = opt->data[0]; 911 break; 912 case DHCPV4_OPT_SERVERID: 913 if (opt->len == 4 && memcmp(opt->data, &iface->dhcpv4_local, 4)) 914 return; 915 break; 916 case DHCPV4_OPT_REQOPTS: 917 if (opt->len > 0) { 918 req_opts = opt->data; 919 req_opts_len = opt->len; 920 } 921 break; 922 case DHCPV4_OPT_USER_CLASS: 923 if (iface->filter_class) { 924 uint8_t *c = opt->data, *cend = &opt->data[opt->len]; 925 for (; c < cend && &c[*c] < cend; c = &c[1 + *c]) { 926 size_t elen = strlen(iface->filter_class); 927 if (*c == elen && !memcmp(&c[1], iface->filter_class, elen)) 928 return; // Ignore from homenet 929 } 930 } 931 break; 932 case DHCPV4_OPT_LEASETIME: 933 if (opt->len == 4) { 934 memcpy(&req_leasetime, opt->data, 4); 935 req_leasetime = ntohl(req_leasetime); 936 } 937 break; 938 case DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE: 939 for (uint8_t i = 0; i < opt->len; i++) { 940 if (opt->data[i] == 1) { 941 req_accept_fr = true; 942 break; 943 } 944 } 945 break; 946 } 947 } 948 949 info("Received %s from %s on %s", dhcpv4_msg_to_string(req_msg), 950 odhcpd_print_mac(req->chaddr, req->hlen), iface->name); 951 952 switch (req_msg) { 953 case DHCPV4_MSG_INFORM: 954 break; 955 case DHCPV4_MSG_DECLINE: 956 _fallthrough; 957 case DHCPV4_MSG_RELEASE: 958 dhcpv4_lease(iface, req_msg, req->chaddr, req_addr, 959 &req_leasetime, req_hostname, req_hostname_len, 960 req_accept_fr, &reply_incl_fr, &fr_serverid); 961 return; 962 case DHCPV4_MSG_DISCOVER: 963 _fallthrough; 964 case DHCPV4_MSG_REQUEST: 965 lease = dhcpv4_lease(iface, req_msg, req->chaddr, req_addr, 966 &req_leasetime, req_hostname, req_hostname_len, 967 req_accept_fr, &reply_incl_fr, &fr_serverid); 968 break; 969 default: 970 return; 971 } 972 973 /* We are at the point where we know the client expects a reply */ 974 switch (req_msg) { 975 case DHCPV4_MSG_DISCOVER: 976 if (!lease) 977 return; 978 reply_msg.data = DHCPV4_MSG_OFFER; 979 break; 980 981 case DHCPV4_MSG_REQUEST: 982 if (!lease) { 983 reply_msg.data = DHCPV4_MSG_NAK; 984 break; 985 } 986 987 if ((req_addr && req_addr != lease->addr) || 988 (req->ciaddr.s_addr && req->ciaddr.s_addr != lease->addr)) { 989 reply_msg.data = DHCPV4_MSG_NAK; 990 /* 991 * DHCP client requested an IP which we can't offer to him. Probably the 992 * client changed the network or the network has been changed. The reply 993 * type is set to DHCPV4_MSG_NAK, because the client should not use that IP. 994 * 995 * For modern devices we build an answer that includes a valid IP, like 996 * a DHCPV4_MSG_ACK. The client will use that IP and doesn't need to 997 * perform additional DHCP round trips. 998 * 999 * Buggy clients do serverid checking in nack messages; therefore set the 1000 * serverid in nack messages triggered by a previous force renew equal to 1001 * the server id in use at that time by the server 1002 * 1003 */ 1004 if (fr_serverid) 1005 reply_serverid.data = fr_serverid; 1006 1007 if (req->ciaddr.s_addr && 1008 ((iface->dhcpv4_start_ip.s_addr & iface->dhcpv4_mask.s_addr) != 1009 (req->ciaddr.s_addr & iface->dhcpv4_mask.s_addr))) 1010 req->ciaddr.s_addr = INADDR_ANY; 1011 } 1012 break; 1013 } 1014 1015 /* Note: each option might get called more than once */ 1016 for (size_t i = 0; i < sizeof(std_opts) + req_opts_len; i++) { 1017 uint8_t opt = i < sizeof(std_opts) ? std_opts[i] : req_opts[i - sizeof(std_opts)]; 1018 1019 switch (opt) { 1020 case DHCPV4_OPT_NETMASK: 1021 if (!lease) 1022 break; 1023 reply_netmask.data = iface->dhcpv4_mask.s_addr; 1024 iov[IOV_NETMASK].iov_len = sizeof(reply_netmask); 1025 break; 1026 1027 case DHCPV4_OPT_ROUTER: 1028 iov[IOV_ROUTER].iov_len = sizeof(reply_router); 1029 if (iface->dhcpv4_router_cnt) { 1030 reply_router.len = iface->dhcpv4_router_cnt * sizeof(*iface->dhcpv4_router); 1031 iov[IOV_ROUTER_ADDR].iov_base = iface->dhcpv4_router; 1032 } else { 1033 reply_router.len = sizeof(iface->dhcpv4_local); 1034 iov[IOV_ROUTER_ADDR].iov_base = &iface->dhcpv4_local; 1035 } 1036 iov[IOV_ROUTER_ADDR].iov_len = reply_router.len; 1037 break; 1038 1039 case DHCPV4_OPT_DNSSERVER: 1040 iov[IOV_DNSSERVER].iov_len = sizeof(reply_dnsserver); 1041 if (iface->dhcpv4_dns_cnt) { 1042 reply_dnsserver.len = iface->dhcpv4_dns_cnt * sizeof(*iface->dhcpv4_dns); 1043 iov[IOV_DNSSERVER_ADDR].iov_base = iface->dhcpv4_dns; 1044 } else { 1045 reply_dnsserver.len = sizeof(iface->dhcpv4_local); 1046 iov[IOV_DNSSERVER_ADDR].iov_base = &iface->dhcpv4_local; 1047 } 1048 iov[IOV_DNSSERVER_ADDR].iov_len = reply_dnsserver.len; 1049 break; 1050 1051 case DHCPV4_OPT_HOSTNAME: 1052 if (!lease || !lease->hostname) 1053 break; 1054 reply_hostname.len = strlen(lease->hostname); 1055 iov[IOV_HOSTNAME].iov_len = sizeof(reply_hostname); 1056 iov[IOV_HOSTNAME_NAME].iov_base = lease->hostname; 1057 iov[IOV_HOSTNAME_NAME].iov_len = reply_hostname.len; 1058 break; 1059 1060 case DHCPV4_OPT_MTU: 1061 if (iov[IOV_MTU].iov_len) 1062 break; 1063 1064 struct ifreq ifr = { .ifr_name = { 0x0, } }; 1065 1066 strncpy(ifr.ifr_name, iface->ifname, sizeof(ifr.ifr_name) - 1); 1067 if (!ioctl(iface->dhcpv4_event.uloop.fd, SIOCGIFMTU, &ifr)) { 1068 reply_mtu.data = htons(ifr.ifr_mtu); 1069 iov[IOV_MTU].iov_len = sizeof(reply_mtu); 1070 } 1071 break; 1072 1073 case DHCPV4_OPT_BROADCAST: 1074 if (!lease || iface->dhcpv4_bcast.s_addr == INADDR_ANY) 1075 break; 1076 reply_broadcast.data = iface->dhcpv4_bcast.s_addr; 1077 iov[IOV_BROADCAST].iov_len = sizeof(reply_broadcast); 1078 break; 1079 1080 case DHCPV4_OPT_NTPSERVER: 1081 if (!lease) 1082 break; 1083 iov[IOV_NTP].iov_len = sizeof(reply_ntp); 1084 iov[IOV_NTP_ADDR].iov_len = iface->dhcpv4_ntp_cnt * sizeof(*iface->dhcpv4_ntp); 1085 break; 1086 1087 case DHCPV4_OPT_LEASETIME: 1088 if (!lease) 1089 break; 1090 reply_leasetime.data = htonl(req_leasetime); 1091 iov[IOV_LEASETIME].iov_len = sizeof(reply_leasetime); 1092 break; 1093 1094 case DHCPV4_OPT_RENEW: 1095 if (!lease || req_leasetime == UINT32_MAX) 1096 break; 1097 reply_renew.data = htonl(500 * req_leasetime / 1000); 1098 iov[IOV_RENEW].iov_len = sizeof(reply_renew); 1099 break; 1100 1101 case DHCPV4_OPT_REBIND: 1102 if (!lease || req_leasetime == UINT32_MAX) 1103 break; 1104 reply_rebind.data = htonl(875 * req_leasetime / 1000); 1105 iov[IOV_REBIND].iov_len = sizeof(reply_rebind); 1106 break; 1107 1108 case DHCPV4_OPT_AUTHENTICATION: 1109 if (!lease || !reply_incl_fr || req_msg != DHCPV4_MSG_REQUEST) 1110 break; 1111 1112 memcpy(reply_auth_body.key, lease->key, sizeof(reply_auth_body.key)); 1113 reply_auth_body.replay[0] = htonl(time(NULL)); 1114 reply_auth_body.replay[1] = htonl(++serial); 1115 iov[IOV_AUTH].iov_len = sizeof(reply_auth); 1116 iov[IOV_AUTH_BODY].iov_len = sizeof(reply_auth_body); 1117 break; 1118 1119 case DHCPV4_OPT_SEARCH_DOMAIN: 1120 if (iov[IOV_SRCH_DOMAIN].iov_len || iface->search_len > UINT8_MAX) 1121 break; 1122 1123 if (iface->search) { 1124 reply_srch_domain.len = iface->search_len; 1125 iov[IOV_SRCH_DOMAIN].iov_len = sizeof(reply_srch_domain); 1126 iov[IOV_SRCH_DOMAIN_NAME].iov_base = iface->search; 1127 iov[IOV_SRCH_DOMAIN_NAME].iov_len = iface->search_len; 1128 } else if (!res_init() && _res.dnsrch[0] && _res.dnsrch[0][0]) { 1129 int len; 1130 1131 if (!iov[IOV_SRCH_DOMAIN_NAME].iov_base) 1132 iov[IOV_SRCH_DOMAIN_NAME].iov_base = alloca(DNS_MAX_NAME_LEN); 1133 1134 len = dn_comp(_res.dnsrch[0], 1135 iov[IOV_SRCH_DOMAIN_NAME].iov_base, 1136 DNS_MAX_NAME_LEN, NULL, NULL); 1137 if (len < 0) 1138 break; 1139 1140 reply_srch_domain.len = len; 1141 iov[IOV_SRCH_DOMAIN].iov_len = sizeof(reply_srch_domain); 1142 iov[IOV_SRCH_DOMAIN_NAME].iov_len = len; 1143 } 1144 break; 1145 1146 case DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE: 1147 if (!lease || !reply_incl_fr || req_msg == DHCPV4_MSG_REQUEST) 1148 break; 1149 1150 iov[IOV_FR_NONCE_CAP].iov_len = sizeof(reply_fr_nonce_cap); 1151 break; 1152 1153 case DHCPV4_OPT_DNR: 1154 struct dhcpv4_dnr *dnrs; 1155 size_t dnrs_len = 0; 1156 1157 if (!lease || reply_dnr.len > 0) 1158 break; 1159 1160 for (size_t i = 0; i < iface->dnr_cnt; i++) { 1161 struct dnr_options *dnr = &iface->dnr[i]; 1162 1163 if (dnr->addr4_cnt == 0 && dnr->addr6_cnt > 0) 1164 continue; 1165 1166 dnrs_len += sizeof(struct dhcpv4_dnr); 1167 dnrs_len += dnr->adn_len; 1168 1169 if (dnr->addr4_cnt > 0 || dnr->svc_len > 0) { 1170 dnrs_len += sizeof(uint8_t); 1171 dnrs_len += dnr->addr4_cnt * sizeof(*dnr->addr4); 1172 dnrs_len += dnr->svc_len; 1173 } 1174 } 1175 1176 if (dnrs_len > UINT8_MAX) 1177 break; 1178 1179 dnrs = alloca(dnrs_len); 1180 uint8_t *pos = (uint8_t *)dnrs; 1181 1182 for (size_t i = 0; i < iface->dnr_cnt; i++) { 1183 struct dnr_options *dnr = &iface->dnr[i]; 1184 struct dhcpv4_dnr *d4dnr = (struct dhcpv4_dnr *)pos; 1185 uint16_t d4dnr_len = sizeof(uint16_t) + sizeof(uint8_t) + dnr->adn_len; 1186 uint16_t d4dnr_priority_be = htons(dnr->priority); 1187 uint16_t d4dnr_len_be; 1188 1189 if (dnr->addr4_cnt == 0 && dnr->addr6_cnt > 0) 1190 continue; 1191 1192 /* memcpy as the struct is unaligned */ 1193 memcpy(&d4dnr->priority, &d4dnr_priority_be, sizeof(d4dnr_priority_be)); 1194 1195 d4dnr->adn_len = dnr->adn_len; 1196 pos = d4dnr->body; 1197 memcpy(pos, dnr->adn, dnr->adn_len); 1198 pos += dnr->adn_len; 1199 1200 if (dnr->addr4_cnt > 0 || dnr->svc_len > 0) { 1201 uint8_t addr4_len = dnr->addr4_cnt * sizeof(*dnr->addr4); 1202 1203 *(pos++) = addr4_len; 1204 memcpy(pos, dnr->addr4, addr4_len); 1205 pos += addr4_len; 1206 memcpy(pos, dnr->svc, dnr->svc_len); 1207 pos += dnr->svc_len; 1208 1209 d4dnr_len += sizeof(addr4_len) + addr4_len + dnr->svc_len; 1210 } 1211 1212 d4dnr_len_be = htons(d4dnr_len); 1213 memcpy(&d4dnr->len, &d4dnr_len_be, sizeof(d4dnr_len_be)); 1214 } 1215 1216 reply_dnr.len = dnrs_len; 1217 iov[IOV_DNR].iov_len = sizeof(reply_dnr); 1218 iov[IOV_DNR_BODY].iov_base = dnrs; 1219 iov[IOV_DNR_BODY].iov_len = dnrs_len; 1220 break; 1221 } 1222 } 1223 1224 if (lease) 1225 reply.yiaddr.s_addr = lease->addr; 1226 1227 memcpy(reply.chaddr, req->chaddr, sizeof(reply.chaddr)); 1228 dhcpv4_set_dest_addr(iface, reply_msg.data, req, &reply, src_addr, &dest_addr); 1229 dhcpv4_add_padding(iov, ARRAY_SIZE(iov)); 1230 1231 if (send_reply(iov, ARRAY_SIZE(iov), (struct sockaddr *)&dest_addr, sizeof(dest_addr), opaque) < 0) 1232 error("Failed to send %s to %s - %s: %m", 1233 dhcpv4_msg_to_string(reply_msg.data), 1234 dest_addr.sin_addr.s_addr == INADDR_BROADCAST ? 1235 "ff:ff:ff:ff:ff:ff": odhcpd_print_mac(req->chaddr, req->hlen), 1236 inet_ntoa(dest_addr.sin_addr)); 1237 else 1238 error("Sent %s to %s - %s", 1239 dhcpv4_msg_to_string(reply_msg.data), 1240 dest_addr.sin_addr.s_addr == INADDR_BROADCAST ? 1241 "ff:ff:ff:ff:ff:ff": odhcpd_print_mac(req->chaddr, req->hlen), 1242 inet_ntoa(dest_addr.sin_addr)); 1243 1244 if (reply_msg.data == DHCPV4_MSG_ACK && lease) 1245 ubus_bcast_dhcp_event("dhcp.ack", req->chaddr, 1246 (struct in_addr *)&lease->addr, 1247 lease->hostname, iface->ifname); 1248 } 1249 1250 /* Handler for DHCPv4 messages */ 1251 static void dhcpv4_handle_dgram(void *addr, void *data, size_t len, 1252 struct interface *iface, _unused void *dest_addr) 1253 { 1254 int sock = iface->dhcpv4_event.uloop.fd; 1255 1256 dhcpv4_handle_msg(addr, data, len, iface, dest_addr, dhcpv4_send_reply, &sock); 1257 } 1258 1259 static int dhcpv4_setup_addresses(struct interface *iface) 1260 { 1261 iface->dhcpv4_start_ip.s_addr = INADDR_ANY; 1262 iface->dhcpv4_end_ip.s_addr = INADDR_ANY; 1263 iface->dhcpv4_local.s_addr = INADDR_ANY; 1264 iface->dhcpv4_bcast.s_addr = INADDR_ANY; 1265 iface->dhcpv4_mask.s_addr = INADDR_ANY; 1266 1267 /* Sanity checks */ 1268 if (iface->dhcpv4_start.s_addr & htonl(0xffff0000) || 1269 iface->dhcpv4_end.s_addr & htonl(0xffff0000) || 1270 ntohl(iface->dhcpv4_start.s_addr) > ntohl(iface->dhcpv4_end.s_addr)) { 1271 warn("Invalid DHCP range for %s", iface->name); 1272 return -1; 1273 } 1274 1275 if (!iface->addr4_len) { 1276 warn("No network(s) available on %s", iface->name); 1277 return -1; 1278 } 1279 1280 uint32_t start = ntohl(iface->dhcpv4_start.s_addr); 1281 uint32_t end = ntohl(iface->dhcpv4_end.s_addr); 1282 1283 for (size_t i = 0; i < iface->addr4_len && start && end; i++) { 1284 struct in_addr *addr = &iface->addr4[i].addr.in; 1285 struct in_addr mask; 1286 1287 if (addr_is_fr_ip(iface, addr)) 1288 continue; 1289 1290 odhcpd_bitlen2netmask(false, iface->addr4[i].prefix, &mask); 1291 if ((start & ntohl(~mask.s_addr)) == start && 1292 (end & ntohl(~mask.s_addr)) == end && 1293 end < ntohl(~mask.s_addr)) { /* Exclude broadcast address */ 1294 iface->dhcpv4_start_ip.s_addr = htonl(start) | 1295 (addr->s_addr & mask.s_addr); 1296 iface->dhcpv4_end_ip.s_addr = htonl(end) | 1297 (addr->s_addr & mask.s_addr); 1298 iface->dhcpv4_local = *addr; 1299 iface->dhcpv4_bcast = iface->addr4[i].broadcast; 1300 iface->dhcpv4_mask = mask; 1301 return 0; 1302 } 1303 } 1304 1305 /* Don't allocate IP range for subnets smaller than /28 */ 1306 if (iface->addr4[0].prefix > MAX_PREFIX_LEN) { 1307 warn("Auto allocation of DHCP range fails on %s (prefix length must be < %d).", 1308 iface->name, MAX_PREFIX_LEN + 1); 1309 return -1; 1310 } 1311 1312 iface->dhcpv4_local = iface->addr4[0].addr.in; 1313 iface->dhcpv4_bcast = iface->addr4[0].broadcast; 1314 odhcpd_bitlen2netmask(false, iface->addr4[0].prefix, &iface->dhcpv4_mask); 1315 end = start = iface->dhcpv4_local.s_addr & iface->dhcpv4_mask.s_addr; 1316 1317 /* Auto allocate ranges */ 1318 if (ntohl(iface->dhcpv4_mask.s_addr) <= 0xffffff00) { /* /24, 150 of 256, [100..249] */ 1319 iface->dhcpv4_start_ip.s_addr = start | htonl(100); 1320 iface->dhcpv4_end_ip.s_addr = end | htonl(100 + 150 - 1); 1321 } else if (ntohl(iface->dhcpv4_mask.s_addr) <= 0xffffff80) { /* /25, 100 of 128, [20..119] */ 1322 iface->dhcpv4_start_ip.s_addr = start | htonl(20); 1323 iface->dhcpv4_end_ip.s_addr = end | htonl(20 + 100 - 1); 1324 } else if (ntohl(iface->dhcpv4_mask.s_addr) <= 0xffffffc0) { /* /26, 50 of 64, [10..59] */ 1325 iface->dhcpv4_start_ip.s_addr = start | htonl(10); 1326 iface->dhcpv4_end_ip.s_addr = end | htonl(10 + 50 - 1); 1327 } else if (ntohl(iface->dhcpv4_mask.s_addr) <= 0xffffffe0) { /* /27, 20 of 32, [10..29] */ 1328 iface->dhcpv4_start_ip.s_addr = start | htonl(10); 1329 iface->dhcpv4_end_ip.s_addr = end | htonl(10 + 20 - 1); 1330 } else { /* /28, 10 of 16, [3..12] */ 1331 iface->dhcpv4_start_ip.s_addr = start | htonl(3); 1332 iface->dhcpv4_end_ip.s_addr = end | htonl(3 + 10 - 1); 1333 } 1334 1335 return 0; 1336 } 1337 1338 int dhcpv4_setup_interface(struct interface *iface, bool enable) 1339 { 1340 int ret = 0; 1341 struct sockaddr_in bind_addr = { 1342 .sin_family = AF_INET, 1343 .sin_port = htons(DHCPV4_SERVER_PORT), 1344 .sin_addr = { INADDR_ANY }, 1345 }; 1346 int val = 1; 1347 1348 if (iface->dhcpv4_event.uloop.fd >= 0) { 1349 uloop_fd_delete(&iface->dhcpv4_event.uloop); 1350 close(iface->dhcpv4_event.uloop.fd); 1351 iface->dhcpv4_event.uloop.fd = -1; 1352 } 1353 1354 if (!enable || iface->dhcpv4 == MODE_DISABLED) { 1355 while (!list_empty(&iface->dhcpv4_leases)) 1356 dhcpv4_free_lease(list_first_entry(&iface->dhcpv4_leases, 1357 struct dhcpv4_lease, head)); 1358 return 0; 1359 } 1360 1361 iface->dhcpv4_event.uloop.fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP); 1362 if (iface->dhcpv4_event.uloop.fd < 0) { 1363 error("socket(AF_INET): %m"); 1364 ret = -1; 1365 goto out; 1366 } 1367 1368 /* Basic IPv4 configuration */ 1369 if (setsockopt(iface->dhcpv4_event.uloop.fd, SOL_SOCKET, SO_REUSEADDR, 1370 &val, sizeof(val)) < 0) { 1371 error("setsockopt(SO_REUSEADDR): %m"); 1372 ret = -1; 1373 goto out; 1374 } 1375 1376 if (setsockopt(iface->dhcpv4_event.uloop.fd, SOL_SOCKET, SO_BROADCAST, 1377 &val, sizeof(val)) < 0) { 1378 error("setsockopt(SO_BROADCAST): %m"); 1379 ret = -1; 1380 goto out; 1381 } 1382 1383 if (setsockopt(iface->dhcpv4_event.uloop.fd, IPPROTO_IP, IP_PKTINFO, 1384 &val, sizeof(val)) < 0) { 1385 error("setsockopt(IP_PKTINFO): %m"); 1386 ret = -1; 1387 goto out; 1388 } 1389 1390 val = IPTOS_PREC_INTERNETCONTROL; 1391 if (setsockopt(iface->dhcpv4_event.uloop.fd, IPPROTO_IP, IP_TOS, &val, 1392 sizeof(val)) < 0) { 1393 error("setsockopt(IP_TOS): %m"); 1394 ret = -1; 1395 goto out; 1396 } 1397 1398 val = IP_PMTUDISC_DONT; 1399 if (setsockopt(iface->dhcpv4_event.uloop.fd, IPPROTO_IP, IP_MTU_DISCOVER, 1400 &val, sizeof(val)) < 0) { 1401 error("setsockopt(IP_MTU_DISCOVER): %m"); 1402 ret = -1; 1403 goto out; 1404 } 1405 1406 if (setsockopt(iface->dhcpv4_event.uloop.fd, SOL_SOCKET, SO_BINDTODEVICE, 1407 iface->ifname, strlen(iface->ifname)) < 0) { 1408 error("setsockopt(SO_BINDTODEVICE): %m"); 1409 ret = -1; 1410 goto out; 1411 } 1412 1413 if (bind(iface->dhcpv4_event.uloop.fd, (struct sockaddr *)&bind_addr, 1414 sizeof(bind_addr)) < 0) { 1415 error("bind(): %m"); 1416 ret = -1; 1417 goto out; 1418 } 1419 1420 if (dhcpv4_setup_addresses(iface) < 0) { 1421 ret = -1; 1422 goto out; 1423 } 1424 1425 iface->dhcpv4_event.handle_dgram = dhcpv4_handle_dgram; 1426 odhcpd_register(&iface->dhcpv4_event); 1427 1428 out: 1429 if (ret < 0 && iface->dhcpv4_event.uloop.fd >= 0) { 1430 close(iface->dhcpv4_event.uloop.fd); 1431 iface->dhcpv4_event.uloop.fd = -1; 1432 } 1433 1434 return ret; 1435 } 1436 1437 static void dhcpv4_addrlist_change(struct interface *iface) 1438 { 1439 struct odhcpd_ipaddr ip; 1440 struct odhcpd_ref_ip *a; 1441 struct dhcpv4_lease *lease; 1442 uint32_t mask = iface->dhcpv4_mask.s_addr; 1443 1444 memset(&ip, 0, sizeof(ip)); 1445 ip.addr.in = iface->dhcpv4_local; 1446 ip.prefix = odhcpd_netmask2bitlen(false, &iface->dhcpv4_mask); 1447 ip.broadcast = iface->dhcpv4_bcast; 1448 1449 dhcpv4_setup_addresses(iface); 1450 1451 if ((ip.addr.in.s_addr & mask) == 1452 (iface->dhcpv4_local.s_addr & iface->dhcpv4_mask.s_addr)) 1453 return; 1454 1455 if (ip.addr.in.s_addr && !leases_require_fr(iface, &ip, mask)) 1456 return; 1457 1458 if (iface->dhcpv4_local.s_addr == INADDR_ANY || list_empty(&iface->dhcpv4_fr_ips)) 1459 return; 1460 1461 a = list_first_entry(&iface->dhcpv4_fr_ips, struct odhcpd_ref_ip, head); 1462 1463 if (netlink_setup_addr(&a->addr, iface->ifindex, false, true)) { 1464 warn("Failed to add ip address on %s", iface->name); 1465 return; 1466 } 1467 1468 list_for_each_entry(lease, &iface->dhcpv4_leases, head) { 1469 if ((lease->flags & OAF_BOUND) && lease->fr_ip && !lease->fr_cnt) { 1470 if (lease->accept_fr_nonce || iface->dhcpv4_forcereconf) 1471 dhcpv4_fr_rand_delay(lease); 1472 else 1473 dhcpv4_fr_stop(lease); 1474 } 1475 } 1476 } 1477 1478 static void dhcpv4_netevent_cb(unsigned long event, struct netevent_handler_info *info) 1479 { 1480 struct interface *iface = info->iface; 1481 1482 if (!iface || iface->dhcpv4 == MODE_DISABLED) 1483 return; 1484 1485 switch (event) { 1486 case NETEV_IFINDEX_CHANGE: 1487 dhcpv4_setup_interface(iface, true); 1488 break; 1489 case NETEV_ADDRLIST_CHANGE: 1490 dhcpv4_addrlist_change(iface); 1491 break; 1492 default: 1493 break; 1494 } 1495 } 1496 1497 static void dhcpv4_valid_until_cb(struct uloop_timeout *event) 1498 { 1499 struct interface *iface; 1500 time_t now = odhcpd_time(); 1501 1502 avl_for_each_element(&interfaces, iface, avl) { 1503 struct dhcpv4_lease *lease, *tmp; 1504 1505 if (iface->dhcpv4 != MODE_SERVER) 1506 continue; 1507 1508 list_for_each_entry_safe(lease, tmp, &iface->dhcpv4_leases, head) { 1509 if (!INFINITE_VALID(lease->valid_until) && lease->valid_until < now) { 1510 ubus_bcast_dhcp_event("dhcp.expire", lease->hwaddr, 1511 (struct in_addr *)&lease->addr, 1512 lease->hostname, iface->ifname); 1513 dhcpv4_free_lease(lease); 1514 } 1515 } 1516 } 1517 uloop_timeout_set(event, 1000); 1518 } 1519 1520 /* Create socket and register events */ 1521 int dhcpv4_init(void) 1522 { 1523 static struct netevent_handler dhcpv4_netevent_handler = { .cb = dhcpv4_netevent_cb }; 1524 static struct uloop_timeout valid_until_timeout = { .cb = dhcpv4_valid_until_cb }; 1525 1526 uloop_timeout_set(&valid_until_timeout, 1000); 1527 netlink_add_netevent_handler(&dhcpv4_netevent_handler); 1528 1529 return 0; 1530 } 1531
This page was automatically generated by LXR 0.3.1. • OpenWrt