1 /* dnsmasq is Copyright (c) 2000-2009 Simon Kelley 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License as published by 5 the Free Software Foundation; version 2 dated June, 1991, or 6 (at your option) version 3 dated 29 June, 2007. 7 8 This program is distributed in the hope that it will be useful, 9 but WITHOUT ANY WARRANTY; without even the implied warranty of 10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 GNU General Public License for more details. 12 13 You should have received a copy of the GNU General Public License 14 along with this program. If not, see <http://www.gnu.org/licenses/>. 15 */ 16 17 #include "dnsmasq.h" 18 19 #ifdef HAVE_DHCP 20 21 struct iface_param { 22 struct in_addr relay, primary; 23 struct dhcp_context *current; 24 int ind; 25 }; 26 27 static int complete_context(struct in_addr local, int if_index, 28 struct in_addr netmask, struct in_addr broadcast, void *vparam); 29 30 void dhcp_init(void) 31 { 32 int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 33 struct sockaddr_in saddr; 34 int oneopt = 1; 35 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) 36 int mtu = IP_PMTUDISC_DONT; 37 #endif 38 39 if (fd == -1) 40 die (_("cannot create DHCP socket: %s"), NULL, EC_BADNET); 41 42 if (!fix_fd(fd) || 43 #if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT) 44 setsockopt(fd, SOL_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu)) == -1 || 45 #endif 46 #if defined(HAVE_LINUX_NETWORK) 47 setsockopt(fd, SOL_IP, IP_PKTINFO, &oneopt, sizeof(oneopt)) == -1 || 48 #else 49 setsockopt(fd, IPPROTO_IP, IP_RECVIF, &oneopt, sizeof(oneopt)) == -1 || 50 #endif 51 setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &oneopt, sizeof(oneopt)) == -1) 52 die(_("failed to set options on DHCP socket: %s"), NULL, EC_BADNET); 53 54 /* When bind-interfaces is set, there might be more than one dnmsasq 55 instance binding port 67. That's OK if they serve different networks. 56 Need to set REUSEADDR to make this posible, or REUSEPORT on *BSD. */ 57 if (daemon->options & OPT_NOWILD) 58 { 59 #ifdef SO_REUSEPORT 60 int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt)); 61 #else 62 int rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt)); 63 #endif 64 if (rc == -1) 65 die(_("failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"), NULL, EC_BADNET); 66 } 67 68 memset(&saddr, 0, sizeof(saddr)); 69 saddr.sin_family = AF_INET; 70 saddr.sin_port = htons(daemon->dhcp_server_port); 71 saddr.sin_addr.s_addr = INADDR_ANY; 72 #ifdef HAVE_SOCKADDR_SA_LEN 73 saddr.sin_len = sizeof(struct sockaddr_in); 74 #endif 75 76 if (bind(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in))) 77 die(_("failed to bind DHCP server socket: %s"), NULL, EC_BADNET); 78 79 #ifdef __ANDROID__ 80 if (setsockopt(fd, SOL_SOCKET, SO_MARK, &daemon->listen_mark, sizeof(daemon->listen_mark)) == -1) 81 die(_("failed to set DHCP socket mark: %s"), NULL, EC_BADNET); 82 #endif /* __ANDROID__ */ 83 84 daemon->dhcpfd = fd; 85 86 check_dhcp_hosts(1); 87 88 daemon->dhcp_packet.iov_len = sizeof(struct dhcp_packet); 89 daemon->dhcp_packet.iov_base = safe_malloc(daemon->dhcp_packet.iov_len); 90 } 91 92 void dhcp_packet(time_t now) 93 { 94 struct dhcp_packet *mess; 95 struct dhcp_context *context; 96 struct iname *tmp; 97 struct ifreq ifr; 98 struct msghdr msg; 99 struct sockaddr_in dest; 100 struct cmsghdr *cmptr; 101 struct iovec iov; 102 ssize_t sz; 103 int iface_index = 0, unicast_dest = 0, is_inform = 0; 104 struct in_addr iface_addr, *addrp = NULL; 105 struct iface_param parm; 106 107 union { 108 struct cmsghdr align; /* this ensures alignment */ 109 #if defined(HAVE_LINUX_NETWORK) 110 char control[CMSG_SPACE(sizeof(struct in_pktinfo))]; 111 #endif 112 } control_u; 113 114 msg.msg_control = NULL; 115 msg.msg_controllen = 0; 116 msg.msg_name = NULL; 117 msg.msg_namelen = 0; 118 msg.msg_iov = &daemon->dhcp_packet; 119 msg.msg_iovlen = 1; 120 121 while (1) 122 { 123 msg.msg_flags = 0; 124 while ((sz = recvmsg(daemon->dhcpfd, &msg, MSG_PEEK | MSG_TRUNC)) == -1 && errno == EINTR); 125 126 if (sz == -1) 127 return; 128 129 if (!(msg.msg_flags & MSG_TRUNC)) 130 break; 131 132 /* Very new Linux kernels return the actual size needed, 133 older ones always return truncated size */ 134 if ((size_t)sz == daemon->dhcp_packet.iov_len) 135 { 136 if (!expand_buf(&daemon->dhcp_packet, sz + 100)) 137 return; 138 } 139 else 140 { 141 expand_buf(&daemon->dhcp_packet, sz); 142 break; 143 } 144 } 145 146 /* expand_buf may have moved buffer */ 147 mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base; 148 msg.msg_controllen = sizeof(control_u); 149 msg.msg_control = control_u.control; 150 msg.msg_flags = 0; 151 msg.msg_name = &dest; 152 msg.msg_namelen = sizeof(dest); 153 154 while ((sz = recvmsg(daemon->dhcpfd, &msg, 0)) == -1 && errno == EINTR); 155 156 if ((msg.msg_flags & MSG_TRUNC) || sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options))) 157 return; 158 159 #if defined (HAVE_LINUX_NETWORK) 160 if (msg.msg_controllen >= sizeof(struct cmsghdr)) 161 for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr)) 162 if (cmptr->cmsg_level == SOL_IP && cmptr->cmsg_type == IP_PKTINFO) 163 { 164 iface_index = ((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_ifindex; 165 if (((struct in_pktinfo *)CMSG_DATA(cmptr))->ipi_addr.s_addr != INADDR_BROADCAST) 166 unicast_dest = 1; 167 } 168 #endif 169 170 if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name)) 171 return; 172 173 #ifdef MSG_BCAST 174 /* OpenBSD tells us when a packet was broadcast */ 175 if (!(msg.msg_flags & MSG_BCAST)) 176 unicast_dest = 1; 177 #endif 178 179 ifr.ifr_addr.sa_family = AF_INET; 180 if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1 ) 181 { 182 addrp = &iface_addr; 183 iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; 184 } 185 186 if (!iface_check(AF_INET, (struct all_addr *)addrp, ifr.ifr_name, &iface_index)) 187 return; 188 189 for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next) 190 if (tmp->name && (strcmp(tmp->name, ifr.ifr_name) == 0)) 191 return; 192 193 /* interface may have been changed by alias in iface_check */ 194 if (!addrp) 195 { 196 if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) == -1) 197 { 198 my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name); 199 return; 200 } 201 else 202 iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr; 203 } 204 205 /* unlinked contexts are marked by context->current == context */ 206 for (context = daemon->dhcp; context; context = context->next) 207 context->current = context; 208 209 parm.relay = mess->giaddr; 210 parm.primary = iface_addr; 211 parm.current = NULL; 212 parm.ind = iface_index; 213 214 if (!iface_enumerate(&parm, complete_context, NULL)) 215 return; 216 lease_prune(NULL, now); /* lose any expired leases */ 217 iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz, 218 now, unicast_dest, &is_inform); 219 lease_update_file(now); 220 lease_update_dns(); 221 222 if (iov.iov_len == 0) 223 return; 224 225 msg.msg_name = &dest; 226 msg.msg_namelen = sizeof(dest); 227 msg.msg_control = NULL; 228 msg.msg_controllen = 0; 229 msg.msg_iov = &iov; 230 iov.iov_base = daemon->dhcp_packet.iov_base; 231 232 /* packet buffer may have moved */ 233 mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base; 234 235 #ifdef HAVE_SOCKADDR_SA_LEN 236 dest.sin_len = sizeof(struct sockaddr_in); 237 #endif 238 239 if (mess->giaddr.s_addr) 240 { 241 /* Send to BOOTP relay */ 242 dest.sin_port = htons(daemon->dhcp_server_port); 243 dest.sin_addr = mess->giaddr; 244 } 245 else if (mess->ciaddr.s_addr) 246 { 247 /* If the client's idea of its own address tallys with 248 the source address in the request packet, we believe the 249 source port too, and send back to that. If we're replying 250 to a DHCPINFORM, trust the source address always. */ 251 if ((!is_inform && dest.sin_addr.s_addr != mess->ciaddr.s_addr) || 252 dest.sin_port == 0 || dest.sin_addr.s_addr == 0) 253 { 254 dest.sin_port = htons(daemon->dhcp_client_port); 255 dest.sin_addr = mess->ciaddr; 256 } 257 } 258 #if defined(HAVE_LINUX_NETWORK) 259 else if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 || 260 mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0) 261 { 262 /* broadcast to 255.255.255.255 (or mac address invalid) */ 263 struct in_pktinfo *pkt; 264 msg.msg_control = control_u.control; 265 msg.msg_controllen = sizeof(control_u); 266 cmptr = CMSG_FIRSTHDR(&msg); 267 pkt = (struct in_pktinfo *)CMSG_DATA(cmptr); 268 pkt->ipi_ifindex = iface_index; 269 pkt->ipi_spec_dst.s_addr = 0; 270 msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo)); 271 cmptr->cmsg_level = SOL_IP; 272 cmptr->cmsg_type = IP_PKTINFO; 273 dest.sin_addr.s_addr = INADDR_BROADCAST; 274 dest.sin_port = htons(daemon->dhcp_client_port); 275 } 276 else 277 { 278 /* unicast to unconfigured client. Inject mac address direct into ARP cache. 279 struct sockaddr limits size to 14 bytes. */ 280 struct arpreq req; 281 dest.sin_addr = mess->yiaddr; 282 dest.sin_port = htons(daemon->dhcp_client_port); 283 *((struct sockaddr_in *)&req.arp_pa) = dest; 284 req.arp_ha.sa_family = mess->htype; 285 memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen); 286 strncpy(req.arp_dev, ifr.ifr_name, 16); 287 req.arp_flags = ATF_COM; 288 ioctl(daemon->dhcpfd, SIOCSARP, &req); 289 } 290 #endif 291 292 while(sendmsg(daemon->dhcpfd, &msg, 0) == -1 && retry_send()); 293 } 294 295 /* This is a complex routine: it gets called with each (address,netmask,broadcast) triple 296 of each interface (and any relay address) and does the following things: 297 298 1) Discards stuff for interfaces other than the one on which a DHCP packet just arrived. 299 2) Fills in any netmask and broadcast addresses which have not been explicitly configured. 300 3) Fills in local (this host) and router (this host or relay) addresses. 301 4) Links contexts which are valid for hosts directly connected to the arrival interface on ->current. 302 303 Note that the current chain may be superceded later for configured hosts or those coming via gateways. */ 304 305 static int complete_context(struct in_addr local, int if_index, 306 struct in_addr netmask, struct in_addr broadcast, void *vparam) 307 { 308 struct dhcp_context *context; 309 struct iface_param *param = vparam; 310 311 for (context = daemon->dhcp; context; context = context->next) 312 { 313 if (!(context->flags & CONTEXT_NETMASK) && 314 (is_same_net(local, context->start, netmask) || 315 is_same_net(local, context->end, netmask))) 316 { 317 if (context->netmask.s_addr != netmask.s_addr && 318 !(is_same_net(local, context->start, netmask) && 319 is_same_net(local, context->end, netmask))) 320 { 321 strcpy(daemon->dhcp_buff, inet_ntoa(context->start)); 322 strcpy(daemon->dhcp_buff2, inet_ntoa(context->end)); 323 my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"), 324 daemon->dhcp_buff, daemon->dhcp_buff2, inet_ntoa(netmask)); 325 } 326 context->netmask = netmask; 327 } 328 329 if (context->netmask.s_addr) 330 { 331 if (is_same_net(local, context->start, context->netmask) && 332 is_same_net(local, context->end, context->netmask)) 333 { 334 /* link it onto the current chain if we've not seen it before */ 335 if (if_index == param->ind && context->current == context) 336 { 337 context->router = local; 338 context->local = local; 339 context->current = param->current; 340 param->current = context; 341 } 342 343 if (!(context->flags & CONTEXT_BRDCAST)) 344 { 345 if (is_same_net(broadcast, context->start, context->netmask)) 346 context->broadcast = broadcast; 347 else 348 context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr; 349 } 350 } 351 else if (param->relay.s_addr && is_same_net(param->relay, context->start, context->netmask)) 352 { 353 context->router = param->relay; 354 context->local = param->primary; 355 /* fill in missing broadcast addresses for relayed ranges */ 356 if (!(context->flags & CONTEXT_BRDCAST)) 357 context->broadcast.s_addr = context->start.s_addr | ~context->netmask.s_addr; 358 } 359 360 } 361 } 362 363 return 1; 364 } 365 366 struct dhcp_context *address_available(struct dhcp_context *context, 367 struct in_addr taddr, 368 struct dhcp_netid *netids) 369 { 370 /* Check is an address is OK for this network, check all 371 possible ranges. Make sure that the address isn't in use 372 by the server itself. */ 373 374 unsigned int start, end, addr = ntohl(taddr.s_addr); 375 struct dhcp_context *tmp; 376 377 for (tmp = context; tmp; tmp = tmp->current) 378 if (taddr.s_addr == context->router.s_addr) 379 return NULL; 380 381 for (tmp = context; tmp; tmp = tmp->current) 382 { 383 start = ntohl(tmp->start.s_addr); 384 end = ntohl(tmp->end.s_addr); 385 386 if (!(tmp->flags & CONTEXT_STATIC) && 387 addr >= start && 388 addr <= end && 389 match_netid(tmp->filter, netids, 1)) 390 return tmp; 391 } 392 393 return NULL; 394 } 395 396 struct dhcp_context *narrow_context(struct dhcp_context *context, 397 struct in_addr taddr, 398 struct dhcp_netid *netids) 399 { 400 /* We start of with a set of possible contexts, all on the current physical interface. 401 These are chained on ->current. 402 Here we have an address, and return the actual context correponding to that 403 address. Note that none may fit, if the address came a dhcp-host and is outside 404 any dhcp-range. In that case we return a static range if possible, or failing that, 405 any context on the correct subnet. (If there's more than one, this is a dodgy 406 configuration: maybe there should be a warning.) */ 407 408 struct dhcp_context *tmp; 409 410 if (!(tmp = address_available(context, taddr, netids))) 411 { 412 for (tmp = context; tmp; tmp = tmp->current) 413 if (is_same_net(taddr, tmp->start, tmp->netmask) && 414 (tmp->flags & CONTEXT_STATIC)) 415 break; 416 417 if (!tmp) 418 for (tmp = context; tmp; tmp = tmp->current) 419 if (is_same_net(taddr, tmp->start, tmp->netmask)) 420 break; 421 } 422 423 /* Only one context allowed now */ 424 if (tmp) 425 tmp->current = NULL; 426 427 return tmp; 428 } 429 430 struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr) 431 { 432 struct dhcp_config *config; 433 434 for (config = configs; config; config = config->next) 435 if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr) 436 return config; 437 438 return NULL; 439 } 440 441 /* Is every member of check matched by a member of pool? 442 If tagnotneeded, untagged is OK */ 443 int match_netid(struct dhcp_netid *check, struct dhcp_netid *pool, int tagnotneeded) 444 { 445 struct dhcp_netid *tmp1; 446 447 if (!check && !tagnotneeded) 448 return 0; 449 450 for (; check; check = check->next) 451 { 452 if (check->net[0] != '#') 453 { 454 for (tmp1 = pool; tmp1; tmp1 = tmp1->next) 455 if (strcmp(check->net, tmp1->net) == 0) 456 break; 457 if (!tmp1) 458 return 0; 459 } 460 else 461 for (tmp1 = pool; tmp1; tmp1 = tmp1->next) 462 if (strcmp((check->net)+1, tmp1->net) == 0) 463 return 0; 464 } 465 return 1; 466 } 467 468 int address_allocate(struct dhcp_context *context, 469 struct in_addr *addrp, unsigned char *hwaddr, int hw_len, 470 struct dhcp_netid *netids, time_t now) 471 { 472 /* Find a free address: exclude anything in use and anything allocated to 473 a particular hwaddr/clientid/hostname in our configuration. 474 Try to return from contexts which match netids first. */ 475 476 struct in_addr start, addr; 477 struct dhcp_context *c, *d; 478 int i, pass; 479 unsigned int j; 480 481 /* hash hwaddr */ 482 for (j = 0, i = 0; i < hw_len; i++) 483 j += hwaddr[i] + (hwaddr[i] << 8) + (hwaddr[i] << 16); 484 485 for (pass = 0; pass <= 1; pass++) 486 for (c = context; c; c = c->current) 487 if (c->flags & CONTEXT_STATIC) 488 continue; 489 else if (!match_netid(c->filter, netids, pass)) 490 continue; 491 else 492 { 493 /* pick a seed based on hwaddr then iterate until we find a free address. */ 494 start.s_addr = addr.s_addr = 495 htonl(ntohl(c->start.s_addr) + 496 ((j + c->addr_epoch) % (1 + ntohl(c->end.s_addr) - ntohl(c->start.s_addr)))); 497 498 do { 499 /* eliminate addresses in use by the server. */ 500 for (d = context; d; d = d->current) 501 if (addr.s_addr == d->router.s_addr) 502 break; 503 504 /* Addresses which end in .255 and .0 are broken in Windows even when using 505 supernetting. ie dhcp-range=192.168.0.1,192.168.1.254,255,255,254.0 506 then 192.168.0.255 is a valid IP address, but not for Windows as it's 507 in the class C range. See KB281579. We therefore don't allocate these 508 addresses to avoid hard-to-diagnose problems. Thanks Bill. */ 509 if (!d && 510 !lease_find_by_addr(addr) && 511 !config_find_by_address(daemon->dhcp_conf, addr) && 512 (!IN_CLASSC(ntohl(addr.s_addr)) || 513 ((ntohl(addr.s_addr) & 0xff) != 0xff && ((ntohl(addr.s_addr) & 0xff) != 0x0)))) 514 { 515 struct ping_result *r, *victim = NULL; 516 int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/ 517 ((float)PING_WAIT))); 518 519 *addrp = addr; 520 521 if (daemon->options & OPT_NO_PING) 522 return 1; 523 524 /* check if we failed to ping addr sometime in the last 525 PING_CACHE_TIME seconds. If so, assume the same situation still exists. 526 This avoids problems when a stupid client bangs 527 on us repeatedly. As a final check, if we did more 528 than 60% of the possible ping checks in the last 529 PING_CACHE_TIME, we are in high-load mode, so don't do any more. */ 530 for (count = 0, r = daemon->ping_results; r; r = r->next) 531 if (difftime(now, r->time) > (float)PING_CACHE_TIME) 532 victim = r; /* old record */ 533 else if (++count == max || r->addr.s_addr == addr.s_addr) 534 return 1; 535 536 if (icmp_ping(addr)) 537 /* address in use: perturb address selection so that we are 538 less likely to try this address again. */ 539 c->addr_epoch++; 540 else 541 { 542 /* at this point victim may hold an expired record */ 543 if (!victim) 544 { 545 if ((victim = whine_malloc(sizeof(struct ping_result)))) 546 { 547 victim->next = daemon->ping_results; 548 daemon->ping_results = victim; 549 } 550 } 551 552 /* record that this address is OK for 30s 553 without more ping checks */ 554 if (victim) 555 { 556 victim->addr = addr; 557 victim->time = now; 558 } 559 return 1; 560 } 561 } 562 563 addr.s_addr = htonl(ntohl(addr.s_addr) + 1); 564 565 if (addr.s_addr == htonl(ntohl(c->end.s_addr) + 1)) 566 addr = c->start; 567 568 } while (addr.s_addr != start.s_addr); 569 } 570 return 0; 571 } 572 573 static int is_addr_in_context(struct dhcp_context *context, struct dhcp_config *config) 574 { 575 if (!context) /* called via find_config() from lease_update_from_configs() */ 576 return 1; 577 if (!(config->flags & CONFIG_ADDR)) 578 return 1; 579 for (; context; context = context->current) 580 if (is_same_net(config->addr, context->start, context->netmask)) 581 return 1; 582 583 return 0; 584 } 585 586 int config_has_mac(struct dhcp_config *config, unsigned char *hwaddr, int len, int type) 587 { 588 struct hwaddr_config *conf_addr; 589 590 for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next) 591 if (conf_addr->wildcard_mask == 0 && 592 conf_addr->hwaddr_len == len && 593 (conf_addr->hwaddr_type == type || conf_addr->hwaddr_type == 0) && 594 memcmp(conf_addr->hwaddr, hwaddr, len) == 0) 595 return 1; 596 597 return 0; 598 } 599 600 struct dhcp_config *find_config(struct dhcp_config *configs, 601 struct dhcp_context *context, 602 unsigned char *clid, int clid_len, 603 unsigned char *hwaddr, int hw_len, 604 int hw_type, char *hostname) 605 { 606 int count, new; 607 struct dhcp_config *config, *candidate; 608 struct hwaddr_config *conf_addr; 609 610 if (clid) 611 for (config = configs; config; config = config->next) 612 if (config->flags & CONFIG_CLID) 613 { 614 if (config->clid_len == clid_len && 615 memcmp(config->clid, clid, clid_len) == 0 && 616 is_addr_in_context(context, config)) 617 return config; 618 619 /* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and 620 cope with that here */ 621 if (*clid == 0 && config->clid_len == clid_len-1 && 622 memcmp(config->clid, clid+1, clid_len-1) == 0 && 623 is_addr_in_context(context, config)) 624 return config; 625 } 626 627 628 for (config = configs; config; config = config->next) 629 if (config_has_mac(config, hwaddr, hw_len, hw_type) && 630 is_addr_in_context(context, config)) 631 return config; 632 633 if (hostname && context) 634 for (config = configs; config; config = config->next) 635 if ((config->flags & CONFIG_NAME) && 636 hostname_isequal(config->hostname, hostname) && 637 is_addr_in_context(context, config)) 638 return config; 639 640 /* use match with fewest wildcast octets */ 641 for (candidate = NULL, count = 0, config = configs; config; config = config->next) 642 if (is_addr_in_context(context, config)) 643 for (conf_addr = config->hwaddr; conf_addr; conf_addr = conf_addr->next) 644 if (conf_addr->wildcard_mask != 0 && 645 conf_addr->hwaddr_len == hw_len && 646 (conf_addr->hwaddr_type == hw_type || conf_addr->hwaddr_type == 0) && 647 (new = memcmp_masked(conf_addr->hwaddr, hwaddr, hw_len, conf_addr->wildcard_mask)) > count) 648 { 649 count = new; 650 candidate = config; 651 } 652 653 return candidate; 654 } 655 656 void check_dhcp_hosts(int fatal) 657 { 658 /* If the same IP appears in more than one host config, then DISCOVER 659 for one of the hosts will get the address, but REQUEST will be NAKed, 660 since the address is reserved by the other one -> protocol loop. 661 Also check that FQDNs match the domain we are using. */ 662 663 struct dhcp_config *configs, *cp; 664 665 for (configs = daemon->dhcp_conf; configs; configs = configs->next) 666 { 667 char *domain; 668 669 if ((configs->flags & DHOPT_BANK) || fatal) 670 { 671 for (cp = configs->next; cp; cp = cp->next) 672 if ((configs->flags & cp->flags & CONFIG_ADDR) && configs->addr.s_addr == cp->addr.s_addr) 673 { 674 if (fatal) 675 die(_("duplicate IP address %s in dhcp-config directive."), 676 inet_ntoa(cp->addr), EC_BADCONF); 677 else 678 my_syslog(MS_DHCP | LOG_ERR, _("duplicate IP address %s in %s."), 679 inet_ntoa(cp->addr), daemon->dhcp_hosts_file); 680 configs->flags &= ~CONFIG_ADDR; 681 } 682 683 /* split off domain part */ 684 if ((configs->flags & CONFIG_NAME) && (domain = strip_hostname(configs->hostname))) 685 configs->domain = domain; 686 } 687 } 688 } 689 690 void dhcp_update_configs(struct dhcp_config *configs) 691 { 692 /* Some people like to keep all static IP addresses in /etc/hosts. 693 This goes through /etc/hosts and sets static addresses for any DHCP config 694 records which don't have an address and whose name matches. 695 We take care to maintain the invariant that any IP address can appear 696 in at most one dhcp-host. Since /etc/hosts can be re-read by SIGHUP, 697 restore the status-quo ante first. */ 698 699 struct dhcp_config *config; 700 struct crec *crec; 701 702 for (config = configs; config; config = config->next) 703 if (config->flags & CONFIG_ADDR_HOSTS) 704 config->flags &= ~(CONFIG_ADDR | CONFIG_ADDR_HOSTS); 705 706 707 if (daemon->port != 0) 708 for (config = configs; config; config = config->next) 709 if (!(config->flags & CONFIG_ADDR) && 710 (config->flags & CONFIG_NAME) && 711 (crec = cache_find_by_name(NULL, config->hostname, 0, F_IPV4)) && 712 (crec->flags & F_HOSTS)) 713 { 714 if (cache_find_by_name(crec, config->hostname, 0, F_IPV4)) 715 { 716 /* use primary (first) address */ 717 while (crec && !(crec->flags & F_REVERSE)) 718 crec = cache_find_by_name(crec, config->hostname, 0, F_IPV4); 719 if (!crec) 720 continue; /* should be never */ 721 my_syslog(MS_DHCP | LOG_WARNING, _("%s has more than one address in hostsfile, using %s for DHCP"), 722 config->hostname, inet_ntoa(crec->addr.addr.addr.addr4)); 723 } 724 725 if (config_find_by_address(configs, crec->addr.addr.addr.addr4)) 726 my_syslog(MS_DHCP | LOG_WARNING, _("duplicate IP address %s (%s) in dhcp-config directive"), 727 inet_ntoa(crec->addr.addr.addr.addr4), config->hostname); 728 else 729 { 730 config->addr = crec->addr.addr.addr.addr4; 731 config->flags |= CONFIG_ADDR | CONFIG_ADDR_HOSTS; 732 } 733 } 734 } 735 736 /* If we've not found a hostname any other way, try and see if there's one in /etc/hosts 737 for this address. If it has a domain part, that must match the set domain and 738 it gets stripped. The set of legal domain names is bigger than the set of legal hostnames 739 so check here that the domain name is legal as a hostname. */ 740 char *host_from_dns(struct in_addr addr) 741 { 742 struct crec *lookup; 743 char *hostname = NULL; 744 char *d1, *d2; 745 746 if (daemon->port == 0) 747 return NULL; /* DNS disabled. */ 748 749 lookup = cache_find_by_addr(NULL, (struct all_addr *)&addr, 0, F_IPV4); 750 if (lookup && (lookup->flags & F_HOSTS)) 751 { 752 hostname = daemon->dhcp_buff; 753 strncpy(hostname, cache_get_name(lookup), 256); 754 hostname[255] = 0; 755 d1 = strip_hostname(hostname); 756 d2 = get_domain(addr); 757 if (!legal_hostname(hostname) || (d1 && (!d2 || !hostname_isequal(d1, d2)))) 758 hostname = NULL; 759 } 760 761 return hostname; 762 } 763 764 /* return domain or NULL if none. */ 765 char *strip_hostname(char *hostname) 766 { 767 char *dot = strchr(hostname, '.'); 768 769 if (!dot) 770 return NULL; 771 772 *dot = 0; /* truncate */ 773 if (strlen(dot+1) != 0) 774 return dot+1; 775 776 return NULL; 777 } 778 779 #endif 780 781