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