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