dispatch.c revision 1.10
1/* $OpenBSD: dispatch.c,v 1.10 2004/05/25 17:41:54 canacar Exp $ */ 2 3/* 4 * Copyright (c) 1995, 1996, 1997, 1998, 1999 5 * The Internet Software Consortium. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of The Internet Software Consortium nor the names 17 * of its contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND 21 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 22 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR 25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 28 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * This software has been written for the Internet Software Consortium 35 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie 36 * Enterprises. To learn more about the Internet Software Consortium, 37 * see ``http://www.vix.com/isc''. To learn more about Vixie 38 * Enterprises, see ``http://www.vix.com''. 39 */ 40 41#include "dhcpd.h" 42#include <ifaddrs.h> 43#include <sys/ioctl.h> 44#include <poll.h> 45#include <net/if_media.h> 46 47 48/* Most boxes has less than 16 interfaces, so this might be a good guess. */ 49#define INITIAL_IFREQ_COUNT 16 50 51struct interface_info *interfaces, *dummy_interfaces, *fallback_interface; 52struct protocol *protocols; 53struct timeout *timeouts; 54static struct timeout *free_timeouts; 55static int interfaces_invalidated; 56void (*bootp_packet_handler)(struct interface_info *, 57 struct dhcp_packet *, int, unsigned int, struct iaddr, struct hardware *); 58 59static int interface_status(struct interface_info *ifinfo); 60 61int quiet_interface_discovery; 62 63/* Use getifaddrs() to get a list of all the attached interfaces. 64 For each interface that's of type INET and not the loopback interface, 65 register that interface with the network I/O software, figure out what 66 subnet it's on, and add it to the list of interfaces. */ 67 68void 69discover_interfaces(int state) 70{ 71 struct interface_info *tmp; 72 struct interface_info *last, *next; 73 struct subnet *subnet; 74 struct shared_network *share; 75 struct sockaddr_in foo; 76 int ir; 77 struct ifreq *tif; 78 struct ifaddrs *ifap, *ifa; 79#ifdef ALIAS_NAMES_PERMUTED 80 char *s; 81#endif 82 83 if (getifaddrs(&ifap) != 0) 84 error("getifaddrs failed"); 85 86 /* If we already have a list of interfaces, and we're running as 87 a DHCP server, the interfaces were requested. */ 88 if (interfaces && (state == DISCOVER_SERVER || 89 state == DISCOVER_RELAY || state == DISCOVER_REQUESTED)) 90 ir = 0; 91 else if (state == DISCOVER_UNCONFIGURED) 92 ir = INTERFACE_REQUESTED | INTERFACE_AUTOMATIC; 93 else 94 ir = INTERFACE_REQUESTED; 95 96 /* Cycle through the list of interfaces looking for IP addresses. */ 97 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 98 /* 99 * See if this is the sort of interface we want to 100 * deal with. Skip loopback, point-to-point and down 101 * interfaces, except don't skip down interfaces if we're 102 * trying to get a list of configurable interfaces. 103 */ 104 if ((ifa->ifa_flags & IFF_LOOPBACK) || 105 (ifa->ifa_flags & IFF_POINTOPOINT) || 106 (!(ifa->ifa_flags & IFF_UP) && 107 state != DISCOVER_UNCONFIGURED)) 108 continue; 109 110 /* See if we've seen an interface that matches this one. */ 111 for (tmp = interfaces; tmp; tmp = tmp->next) 112 if (!strcmp(tmp->name, ifa->ifa_name)) 113 break; 114 115 /* If there isn't already an interface by this name, 116 allocate one. */ 117 if (!tmp) { 118 tmp = ((struct interface_info *)dmalloc(sizeof *tmp, 119 "discover_interfaces")); 120 if (!tmp) 121 error("Insufficient memory to %s %s", 122 "record interface", ifa->ifa_name); 123 strlcpy(tmp->name, ifa->ifa_name, sizeof(tmp->name)); 124 tmp->next = interfaces; 125 tmp->flags = ir; 126 tmp->noifmedia = tmp->dead = tmp->errors = 0; 127 interfaces = tmp; 128 } 129 130 /* If we have the capability, extract link information 131 and record it in a linked list. */ 132 if (ifa->ifa_addr->sa_family == AF_LINK) { 133 struct sockaddr_dl *foo = 134 ((struct sockaddr_dl *)(ifa->ifa_addr)); 135 tmp->index = foo->sdl_index; 136 tmp->hw_address.hlen = foo->sdl_alen; 137 tmp->hw_address.htype = HTYPE_ETHER; /* XXX */ 138 memcpy(tmp->hw_address.haddr, 139 LLADDR(foo), foo->sdl_alen); 140 } else if (ifa->ifa_addr->sa_family == AF_INET) { 141 struct iaddr addr; 142 143 /* Get a pointer to the address... */ 144 bcopy(ifa->ifa_addr, &foo, sizeof(foo)); 145 146 /* We don't want the loopback interface. */ 147 if (foo.sin_addr.s_addr == htonl (INADDR_LOOPBACK)) 148 continue; 149 150 /* If this is the first real IP address we've 151 found, keep a pointer to ifreq structure in 152 which we found it. */ 153 if (!tmp->ifp) { 154 int len = (IFNAMSIZ + ifa->ifa_addr->sa_len); 155 tif = (struct ifreq *)malloc(len); 156 if (!tif) 157 error("no space to remember ifp."); 158 strlcpy(tif->ifr_name, ifa->ifa_name, IFNAMSIZ); 159 memcpy(&tif->ifr_addr, ifa->ifa_addr, 160 ifa->ifa_addr->sa_len); 161 tmp->ifp = tif; 162 tmp->primary_address = foo.sin_addr; 163 } 164 165 /* Grab the address... */ 166 addr.len = 4; 167 memcpy(addr.iabuf, &foo.sin_addr.s_addr, addr.len); 168 169 /* If there's a registered subnet for this address, 170 connect it together... */ 171 if ((subnet = find_subnet(addr))) { 172 /* If this interface has multiple aliases 173 on the same subnet, ignore all but the 174 first we encounter. */ 175 if (!subnet->interface) { 176 subnet->interface = tmp; 177 subnet->interface_address = addr; 178 } else if (subnet->interface != tmp) { 179 warn("Multiple %s %s: %s %s", 180 "interfaces match the", 181 "same subnet", 182 subnet->interface->name, 183 tmp->name); 184 } 185 share = subnet->shared_network; 186 if (tmp->shared_network && 187 tmp->shared_network != share) { 188 warn("Interface %s matches %s", 189 tmp->name, 190 "multiple shared networks"); 191 } else { 192 tmp->shared_network = share; 193 } 194 195 if (!share->interface) { 196 share->interface = tmp; 197 } else if (share->interface != tmp) { 198 warn("Multiple %s %s: %s %s", 199 "interfaces match the", 200 "same shared network", 201 share->interface->name, 202 tmp->name); 203 } 204 } 205 } 206 } 207 208 /* Now cycle through all the interfaces we found, looking for 209 hardware addresses. */ 210 211 /* If we're just trying to get a list of interfaces that we might 212 be able to configure, we can quit now. */ 213 if (state == DISCOVER_UNCONFIGURED) 214 return; 215 216 /* Weed out the interfaces that did not have IP addresses. */ 217 last = NULL; 218 for (tmp = interfaces; tmp; tmp = next) { 219 next = tmp->next; 220 if ((tmp->flags & INTERFACE_AUTOMATIC) && 221 state == DISCOVER_REQUESTED) 222 tmp->flags &= 223 ~(INTERFACE_AUTOMATIC | INTERFACE_REQUESTED); 224 if (!tmp->ifp || !(tmp->flags & INTERFACE_REQUESTED)) { 225 if ((tmp->flags & INTERFACE_REQUESTED) != ir) 226 error("%s: not found", tmp->name); 227 if (!last) 228 interfaces = interfaces->next; 229 else 230 last->next = tmp->next; 231 232 /* Remember the interface in case we need to know 233 about it later. */ 234 tmp->next = dummy_interfaces; 235 dummy_interfaces = tmp; 236 continue; 237 } 238 last = tmp; 239 240 memcpy(&foo, &tmp->ifp->ifr_addr, sizeof tmp->ifp->ifr_addr); 241 242 /* We must have a subnet declaration for each interface. */ 243 if (!tmp->shared_network && (state == DISCOVER_SERVER)) { 244 warn("No subnet declaration for %s (%s).", 245 tmp->name, inet_ntoa(foo.sin_addr)); 246 warn("Please write a subnet declaration in your %s", 247 "dhcpd.conf file for the"); 248 error("network segment to which interface %s %s", 249 tmp->name, "is attached."); 250 } 251 252 /* Find subnets that don't have valid interface 253 addresses... */ 254 for (subnet = (tmp->shared_network ? tmp->shared_network->subnets : 255 NULL); subnet; subnet = subnet->next_sibling) { 256 if (!subnet->interface_address.len) { 257 /* 258 * Set the interface address for this subnet 259 * to the first address we found. 260 */ 261 subnet->interface_address.len = 4; 262 memcpy(subnet->interface_address.iabuf, 263 &foo.sin_addr.s_addr, 4); 264 } 265 } 266 267 /* Register the interface... */ 268 if_register_receive(tmp); 269 if_register_send(tmp); 270 } 271 272 /* Now register all the remaining interfaces as protocols. */ 273 for (tmp = interfaces; tmp; tmp = tmp->next) 274 add_protocol(tmp->name, tmp->rfdesc, got_one, tmp); 275 276 freeifaddrs(ifap); 277} 278 279/* 280 * Wait for packets to come in using poll(). When a packet comes in, 281 * call receive_packet to receive the packet and possibly strip hardware 282 * addressing information from it, and then call through the 283 * bootp_packet_handler hook to try to do something with it. 284 */ 285void 286dispatch(void) 287{ 288 int count, i, nfds = 0, to_msec; 289 struct protocol *l; 290 struct pollfd *fds; 291 time_t howlong; 292 293 for (l = protocols; l; l = l->next) 294 ++nfds; 295 fds = (struct pollfd *)malloc((nfds) * sizeof (struct pollfd)); 296 if (fds == NULL) 297 error("Can't allocate poll structures."); 298 299 do { 300 /* 301 * Call any expired timeouts, and then if there's 302 * still a timeout registered, time out the select 303 * call then. 304 */ 305another: 306 if (timeouts) { 307 struct timeout *t; 308 309 if (timeouts->when <= cur_time) { 310 t = timeouts; 311 timeouts = timeouts->next; 312 (*(t->func))(t->what); 313 t->next = free_timeouts; 314 free_timeouts = t; 315 goto another; 316 } 317 318 /* 319 * Figure timeout in milliseconds, and check for 320 * potential overflow, so we can cram into an int 321 * for poll, while not polling with a negative 322 * timeout and blocking indefinetely. 323 */ 324 howlong = timeouts->when - cur_time; 325 if (howlong > INT_MAX / 1000) 326 howlong = INT_MAX / 1000; 327 to_msec = howlong * 1000; 328 } else 329 to_msec = -1; 330 331 /* Set up the descriptors to be polled. */ 332 i = 0; 333 334 for (l = protocols; l; l = l->next) { 335 struct interface_info *ip = l->local; 336 337 if (ip && (l->handler != got_one || !ip->dead)) { 338 fds[i].fd = l->fd; 339 fds[i].events = POLLIN; 340 fds[i].revents = 0; 341 ++i; 342 } 343 } 344 345 if (i == 0) 346 error("No live interfaces to poll on - exiting."); 347 348 /* Wait for a packet or a timeout... XXX */ 349 count = poll(fds, nfds, to_msec); 350 351 /* Not likely to be transitory... */ 352 if (count == -1) { 353 if (errno == EAGAIN || errno == EINTR) { 354 time(&cur_time); 355 continue; 356 } else 357 error("poll: %m"); 358 } 359 360 /* Get the current time... */ 361 time(&cur_time); 362 363 i = 0; 364 for (l = protocols; l; l = l->next) { 365 struct interface_info *ip = l->local; 366 367 if ((fds[i].revents & (POLLIN | POLLHUP))) { 368 fds[i].revents = 0; 369 if (ip && (l->handler != got_one || 370 !ip->dead)) 371 (*(l->handler))(l); 372 if (interfaces_invalidated) 373 break; 374 } 375 ++i; 376 } 377 interfaces_invalidated = 0; 378 } while (1); 379} 380 381 382void 383got_one(struct protocol *l) 384{ 385 struct sockaddr_in from; 386 struct hardware hfrom; 387 struct iaddr ifrom; 388 size_t result; 389 union { 390 unsigned char packbuf[4095]; 391 struct dhcp_packet packet; 392 } u; 393 struct interface_info *ip = l->local; 394 395 if ((result = receive_packet (ip, u.packbuf, sizeof u, 396 &from, &hfrom)) == -1) { 397 warn("receive_packet failed on %s: %s", ip->name, 398 strerror(errno)); 399 ip->errors++; 400 if ((!interface_status(ip)) || 401 (ip->noifmedia && ip->errors > 20)) { 402 /* our interface has gone away. */ 403 warn("Interface %s no longer appears valid.", 404 ip->name); 405 ip->dead = 1; 406 interfaces_invalidated = 1; 407 close(l->fd); 408 remove_protocol(l); 409 free(ip); 410 } 411 return; 412 } 413 if (result == 0) 414 return; 415 416 if (bootp_packet_handler) { 417 ifrom.len = 4; 418 memcpy(ifrom.iabuf, &from.sin_addr, ifrom.len); 419 420 (*bootp_packet_handler)(ip, &u.packet, result, 421 from.sin_port, ifrom, &hfrom); 422 } 423} 424 425int 426interface_status(struct interface_info *ifinfo) 427{ 428 char * ifname = ifinfo->name; 429 int ifsock = ifinfo->rfdesc; 430 struct ifreq ifr; 431 struct ifmediareq ifmr; 432 433 /* get interface flags */ 434 memset(&ifr, 0, sizeof(ifr)); 435 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 436 if (ioctl(ifsock, SIOCGIFFLAGS, &ifr) < 0) { 437 syslog(LOG_ERR, "ioctl(SIOCGIFFLAGS) on %s: %m", ifname); 438 goto inactive; 439 } 440 /* 441 * if one of UP and RUNNING flags is dropped, 442 * the interface is not active. 443 */ 444 if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 445 goto inactive; 446 447 /* Next, check carrier on the interface, if possible */ 448 if (ifinfo->noifmedia) 449 goto active; 450 memset(&ifmr, 0, sizeof(ifmr)); 451 strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); 452 if (ioctl(ifsock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 453 if (errno != EINVAL) { 454 syslog(LOG_DEBUG, "ioctl(SIOCGIFMEDIA) on %s: %m", 455 ifname); 456 ifinfo->noifmedia = 1; 457 goto active; 458 } 459 /* 460 * EINVAL (or ENOTTY) simply means that the interface 461 * does not support the SIOCGIFMEDIA ioctl. We regard it alive. 462 */ 463 ifinfo->noifmedia = 1; 464 goto active; 465 } 466 if (ifmr.ifm_status & IFM_AVALID) { 467 switch (ifmr.ifm_active & IFM_NMASK) { 468 case IFM_ETHER: 469 if (ifmr.ifm_status & IFM_ACTIVE) 470 goto active; 471 else 472 goto inactive; 473 break; 474 default: 475 goto inactive; 476 } 477 } 478 inactive: 479 return (0); 480 active: 481 return (1); 482} 483 484int 485locate_network(struct packet *packet) 486{ 487 struct iaddr ia; 488 489 /* If this came through a gateway, find the corresponding subnet... */ 490 if (packet->raw->giaddr.s_addr) { 491 struct subnet *subnet; 492 493 ia.len = 4; 494 memcpy(ia.iabuf, &packet->raw->giaddr, 4); 495 subnet = find_subnet(ia); 496 if (subnet) 497 packet->shared_network = subnet->shared_network; 498 else 499 packet->shared_network = NULL; 500 } else { 501 packet->shared_network = packet->interface->shared_network; 502 } 503 if (packet->shared_network) 504 return 1; 505 return 0; 506} 507 508void 509add_timeout(time_t when, void (*where)(void *), void *what) 510{ 511 struct timeout *t, *q; 512 513 /* See if this timeout supersedes an existing timeout. */ 514 t = NULL; 515 for (q = timeouts; q; q = q->next) { 516 if (q->func == where && q->what == what) { 517 if (t) 518 t->next = q->next; 519 else 520 timeouts = q->next; 521 break; 522 } 523 t = q; 524 } 525 526 /* If we didn't supersede a timeout, allocate a timeout 527 structure now. */ 528 if (!q) { 529 if (free_timeouts) { 530 q = free_timeouts; 531 free_timeouts = q->next; 532 q->func = where; 533 q->what = what; 534 } else { 535 q = (struct timeout *)malloc(sizeof (struct timeout)); 536 if (!q) 537 error("Can't allocate timeout structure!"); 538 q->func = where; 539 q->what = what; 540 } 541 } 542 543 q->when = when; 544 545 /* Now sort this timeout into the timeout list. */ 546 547 /* Beginning of list? */ 548 if (!timeouts || timeouts->when > q->when) { 549 q->next = timeouts; 550 timeouts = q; 551 return; 552 } 553 554 /* Middle of list? */ 555 for (t = timeouts; t->next; t = t->next) { 556 if (t->next->when > q->when) { 557 q->next = t->next; 558 t->next = q; 559 return; 560 } 561 } 562 563 /* End of list. */ 564 t->next = q; 565 q->next = NULL; 566} 567 568void 569cancel_timeout(void (*where)(void *), void *what) 570{ 571 struct timeout *t, *q; 572 573 /* Look for this timeout on the list, and unlink it if we find it. */ 574 t = NULL; 575 for (q = timeouts; q; q = q->next) { 576 if (q->func == where && q->what == what) { 577 if (t) 578 t->next = q->next; 579 else 580 timeouts = q->next; 581 break; 582 } 583 t = q; 584 } 585 586 /* If we found the timeout, put it on the free list. */ 587 if (q) { 588 q->next = free_timeouts; 589 free_timeouts = q; 590 } 591} 592 593/* Add a protocol to the list of protocols... */ 594void 595add_protocol(char *name, int fd, void (*handler)(struct protocol *), 596 void *local) 597{ 598 struct protocol *p; 599 600 p = (struct protocol *)malloc(sizeof *p); 601 if (!p) 602 error("can't allocate protocol struct for %s", name); 603 p->fd = fd; 604 p->handler = handler; 605 p->local = local; 606 p->next = protocols; 607 protocols = p; 608} 609 610void 611remove_protocol(struct protocol *proto) 612{ 613 struct protocol *p, *next, *prev = NULL; 614 615 for (p = protocols; p; p = next) { 616 next = p->next; 617 if (p == proto) { 618 if (prev) 619 prev->next = p->next; 620 else 621 protocols = p->next; 622 free(p); 623 } 624 } 625} 626