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