dispatch.c revision 1.17
1/* $OpenBSD: dispatch.c,v 1.17 2006/03/16 15:44:40 claudio 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; 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 61/* Use getifaddrs() to get a list of all the attached interfaces. 62 For each interface that's of type INET and not the loopback interface, 63 register that interface with the network I/O software, figure out what 64 subnet it's on, and add it to the list of interfaces. */ 65 66void 67discover_interfaces(int state) 68{ 69 struct interface_info *tmp; 70 struct interface_info *last, *next; 71 struct subnet *subnet; 72 struct shared_network *share; 73 struct sockaddr_in foo; 74 int ir; 75 struct ifreq *tif; 76 struct ifaddrs *ifap, *ifa; 77#ifdef ALIAS_NAMES_PERMUTED 78 char *s; 79#endif 80 81 if (getifaddrs(&ifap) != 0) 82 error("getifaddrs failed"); 83 84 /* If we already have a list of interfaces, and we're running as 85 a DHCP server, the interfaces were requested. */ 86 if (interfaces && (state == DISCOVER_SERVER || 87 state == DISCOVER_RELAY || state == DISCOVER_REQUESTED)) 88 ir = 0; 89 else if (state == DISCOVER_UNCONFIGURED) 90 ir = INTERFACE_REQUESTED | INTERFACE_AUTOMATIC; 91 else 92 ir = INTERFACE_REQUESTED; 93 94 /* Cycle through the list of interfaces looking for IP addresses. */ 95 for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) { 96 /* 97 * See if this is the sort of interface we want to 98 * deal with. Skip loopback, point-to-point and down 99 * interfaces, except don't skip down interfaces if we're 100 * trying to get a list of configurable interfaces. 101 */ 102 if ((ifa->ifa_flags & IFF_LOOPBACK) || 103 (ifa->ifa_flags & IFF_POINTOPOINT) || 104 (!(ifa->ifa_flags & IFF_UP) && 105 state != DISCOVER_UNCONFIGURED)) 106 continue; 107 108 /* See if we've seen an interface that matches this one. */ 109 for (tmp = interfaces; tmp; tmp = tmp->next) 110 if (!strcmp(tmp->name, ifa->ifa_name)) 111 break; 112 113 /* If there isn't already an interface by this name, 114 allocate one. */ 115 if (!tmp) { 116 tmp = ((struct interface_info *)dmalloc(sizeof *tmp, 117 "discover_interfaces")); 118 if (!tmp) 119 error("Insufficient memory to %s %s", 120 "record interface", ifa->ifa_name); 121 strlcpy(tmp->name, ifa->ifa_name, sizeof(tmp->name)); 122 tmp->next = interfaces; 123 tmp->flags = ir; 124 tmp->noifmedia = tmp->dead = tmp->errors = 0; 125 interfaces = tmp; 126 } 127 128 /* If we have the capability, extract link information 129 and record it in a linked list. */ 130 if (ifa->ifa_addr->sa_family == AF_LINK) { 131 struct sockaddr_dl *foo = 132 ((struct sockaddr_dl *)(ifa->ifa_addr)); 133 tmp->index = foo->sdl_index; 134 tmp->hw_address.hlen = foo->sdl_alen; 135 tmp->hw_address.htype = HTYPE_ETHER; /* XXX */ 136 memcpy(tmp->hw_address.haddr, 137 LLADDR(foo), foo->sdl_alen); 138 } else if (ifa->ifa_addr->sa_family == AF_INET) { 139 struct iaddr addr; 140 141 /* Get a pointer to the address... */ 142 bcopy(ifa->ifa_addr, &foo, sizeof(foo)); 143 144 /* We don't want the loopback interface. */ 145 if (foo.sin_addr.s_addr == htonl (INADDR_LOOPBACK)) 146 continue; 147 148 /* If this is the first real IP address we've 149 found, keep a pointer to ifreq structure in 150 which we found it. */ 151 if (!tmp->ifp) { 152 int len = (IFNAMSIZ + ifa->ifa_addr->sa_len); 153 tif = (struct ifreq *)malloc(len); 154 if (!tif) 155 error("no space to remember ifp."); 156 strlcpy(tif->ifr_name, ifa->ifa_name, IFNAMSIZ); 157 memcpy(&tif->ifr_addr, ifa->ifa_addr, 158 ifa->ifa_addr->sa_len); 159 tmp->ifp = tif; 160 tmp->primary_address = foo.sin_addr; 161 } 162 163 /* Grab the address... */ 164 addr.len = 4; 165 memcpy(addr.iabuf, &foo.sin_addr.s_addr, addr.len); 166 167 /* If there's a registered subnet for this address, 168 connect it together... */ 169 if ((subnet = find_subnet(addr))) { 170 /* If this interface has multiple aliases 171 on the same subnet, ignore all but the 172 first we encounter. */ 173 if (!subnet->interface) { 174 subnet->interface = tmp; 175 subnet->interface_address = addr; 176 } else if (subnet->interface != tmp) { 177 warning("Multiple %s %s: %s %s", 178 "interfaces match the", 179 "same subnet", 180 subnet->interface->name, 181 tmp->name); 182 } 183 share = subnet->shared_network; 184 if (tmp->shared_network && 185 tmp->shared_network != share) { 186 warning("Interface %s matches %s", 187 tmp->name, 188 "multiple shared networks"); 189 } else { 190 tmp->shared_network = share; 191 } 192 193 if (!share->interface) { 194 share->interface = tmp; 195 } else if (share->interface != tmp) { 196 warning("Multiple %s %s: %s %s", 197 "interfaces match the", 198 "same shared network", 199 share->interface->name, 200 tmp->name); 201 } 202 } 203 } 204 } 205 206 /* Now cycle through all the interfaces we found, looking for 207 hardware addresses. */ 208 209 /* If we're just trying to get a list of interfaces that we might 210 be able to configure, we can quit now. */ 211 if (state == DISCOVER_UNCONFIGURED) 212 return; 213 214 /* Weed out the interfaces that did not have IP addresses. */ 215 last = NULL; 216 for (tmp = interfaces; tmp; tmp = next) { 217 next = tmp->next; 218 if ((tmp->flags & INTERFACE_AUTOMATIC) && 219 state == DISCOVER_REQUESTED) 220 tmp->flags &= 221 ~(INTERFACE_AUTOMATIC | INTERFACE_REQUESTED); 222 if (!tmp->ifp || !(tmp->flags & INTERFACE_REQUESTED)) { 223 if ((tmp->flags & INTERFACE_REQUESTED) != ir) 224 error("%s: not found", tmp->name); 225 if (!last) 226 interfaces = interfaces->next; 227 else 228 last->next = tmp->next; 229 230 continue; 231 } 232 last = tmp; 233 234 memcpy(&foo, &tmp->ifp->ifr_addr, sizeof tmp->ifp->ifr_addr); 235 236 /* We must have a subnet declaration for each interface. */ 237 if (!tmp->shared_network && (state == DISCOVER_SERVER)) { 238 warning("No subnet declaration for %s (%s).", 239 tmp->name, inet_ntoa(foo.sin_addr)); 240 warning("Please write a subnet declaration in your %s", 241 "dhcpd.conf file for the"); 242 error("network segment to which interface %s %s", 243 tmp->name, "is attached."); 244 } 245 246 /* Find subnets that don't have valid interface 247 addresses... */ 248 for (subnet = (tmp->shared_network ? tmp->shared_network->subnets : 249 NULL); subnet; subnet = subnet->next_sibling) { 250 if (!subnet->interface_address.len) { 251 /* 252 * Set the interface address for this subnet 253 * to the first address we found. 254 */ 255 subnet->interface_address.len = 4; 256 memcpy(subnet->interface_address.iabuf, 257 &foo.sin_addr.s_addr, 4); 258 } 259 } 260 261 /* Register the interface... */ 262 if_register_receive(tmp); 263 if_register_send(tmp); 264 } 265 266 /* Now register all the remaining interfaces as protocols. */ 267 for (tmp = interfaces; tmp; tmp = tmp->next) 268 add_protocol(tmp->name, tmp->rfdesc, got_one, tmp); 269 270 freeifaddrs(ifap); 271} 272 273/* 274 * Wait for packets to come in using poll(). When a packet comes in, 275 * call receive_packet to receive the packet and possibly strip hardware 276 * addressing information from it, and then call through the 277 * bootp_packet_handler hook to try to do something with it. 278 */ 279void 280dispatch(void) 281{ 282 int nfds, i, to_msec; 283 struct protocol *l; 284 static struct pollfd *fds; 285 static int nfds_max; 286 time_t howlong; 287 288 for (nfds = 0, l = protocols; l; l = l->next) 289 nfds++; 290 if (nfds > nfds_max) { 291 fds = realloc(fds, nfds * sizeof(struct pollfd)); 292 if (fds == NULL) 293 error("Can't allocate poll structures."); 294 nfds_max = nfds; 295 } 296 297 for (;;) { 298 /* 299 * Call any expired timeouts, and then if there's 300 * still a timeout registered, time out the poll 301 * call then. 302 */ 303 time(&cur_time); 304another: 305 if (timeouts) { 306 if (timeouts->when <= cur_time) { 307 struct timeout *t = timeouts; 308 timeouts = timeouts->next; 309 (*(t->func))(t->what); 310 t->next = free_timeouts; 311 free_timeouts = t; 312 goto another; 313 } 314 315 /* 316 * Figure timeout in milliseconds, and check for 317 * potential overflow, so we can cram into an int 318 * for poll, while not polling with a negative 319 * timeout and blocking indefinitely. 320 */ 321 howlong = timeouts->when - cur_time; 322 if (howlong > INT_MAX / 1000) 323 howlong = INT_MAX / 1000; 324 to_msec = howlong * 1000; 325 } else 326 to_msec = -1; 327 328 /* Set up the descriptors to be polled. */ 329 for (i = 0, l = protocols; l; l = l->next) { 330 struct interface_info *ip = l->local; 331 332 if (ip && (l->handler != got_one || !ip->dead)) { 333 fds[i].fd = l->fd; 334 fds[i].events = POLLIN; 335 ++i; 336 } 337 } 338 if (i == 0) 339 error("No live interfaces to poll on - exiting."); 340 341 /* Wait for a packet or a timeout... */ 342 switch (poll(fds, nfds, to_msec)) { 343 case -1: 344 if (errno != EAGAIN && errno != EINTR) 345 error("poll: %m"); 346 /* FALLTHROUGH */ 347 case 0: 348 continue; /* no packets */ 349 } 350 351 for (i = 0, l = protocols; l; l = l->next) { 352 struct interface_info *ip = l->local; 353 354 if ((fds[i].revents & (POLLIN | POLLHUP))) { 355 if (ip && (l->handler != got_one || 356 !ip->dead)) 357 (*(l->handler))(l); 358 if (interfaces_invalidated) 359 break; 360 } 361 ++i; 362 } 363 interfaces_invalidated = 0; 364 } 365} 366 367 368void 369got_one(struct protocol *l) 370{ 371 struct sockaddr_in from; 372 struct hardware hfrom; 373 struct iaddr ifrom; 374 ssize_t result; 375 union { 376 unsigned char packbuf[4095]; 377 struct dhcp_packet packet; 378 } u; 379 struct interface_info *ip = l->local; 380 381 if ((result = receive_packet(ip, u.packbuf, sizeof u, 382 &from, &hfrom)) == -1) { 383 warning("receive_packet failed on %s: %s", ip->name, 384 strerror(errno)); 385 ip->errors++; 386 if ((!interface_status(ip)) || 387 (ip->noifmedia && ip->errors > 20)) { 388 /* our interface has gone away. */ 389 warning("Interface %s no longer appears valid.", 390 ip->name); 391 ip->dead = 1; 392 interfaces_invalidated = 1; 393 close(l->fd); 394 remove_protocol(l); 395 free(ip); 396 } 397 return; 398 } 399 if (result == 0) 400 return; 401 402 if (bootp_packet_handler) { 403 ifrom.len = 4; 404 memcpy(ifrom.iabuf, &from.sin_addr, ifrom.len); 405 406 (*bootp_packet_handler)(ip, &u.packet, result, 407 from.sin_port, ifrom, &hfrom); 408 } 409} 410 411int 412interface_status(struct interface_info *ifinfo) 413{ 414 char * ifname = ifinfo->name; 415 int ifsock = ifinfo->rfdesc; 416 struct ifreq ifr; 417 struct ifmediareq ifmr; 418 419 /* get interface flags */ 420 memset(&ifr, 0, sizeof(ifr)); 421 strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name)); 422 if (ioctl(ifsock, SIOCGIFFLAGS, &ifr) < 0) { 423 syslog(LOG_ERR, "ioctl(SIOCGIFFLAGS) on %s: %m", ifname); 424 goto inactive; 425 } 426 /* 427 * if one of UP and RUNNING flags is dropped, 428 * the interface is not active. 429 */ 430 if ((ifr.ifr_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 431 goto inactive; 432 433 /* Next, check carrier on the interface, if possible */ 434 if (ifinfo->noifmedia) 435 goto active; 436 memset(&ifmr, 0, sizeof(ifmr)); 437 strlcpy(ifmr.ifm_name, ifname, sizeof(ifmr.ifm_name)); 438 if (ioctl(ifsock, SIOCGIFMEDIA, (caddr_t)&ifmr) < 0) { 439 if (errno != EINVAL) { 440 syslog(LOG_DEBUG, "ioctl(SIOCGIFMEDIA) on %s: %m", 441 ifname); 442 ifinfo->noifmedia = 1; 443 goto active; 444 } 445 /* 446 * EINVAL (or ENOTTY) simply means that the interface 447 * does not support the SIOCGIFMEDIA ioctl. We regard it alive. 448 */ 449 ifinfo->noifmedia = 1; 450 goto active; 451 } 452 if (ifmr.ifm_status & IFM_AVALID) { 453 switch (ifmr.ifm_active & IFM_NMASK) { 454 case IFM_ETHER: 455 if (ifmr.ifm_status & IFM_ACTIVE) 456 goto active; 457 else 458 goto inactive; 459 break; 460 default: 461 goto inactive; 462 } 463 } 464 inactive: 465 return (0); 466 active: 467 return (1); 468} 469 470int 471locate_network(struct packet *packet) 472{ 473 struct iaddr ia; 474 475 /* If this came through a gateway, find the corresponding subnet... */ 476 if (packet->raw->giaddr.s_addr) { 477 struct subnet *subnet; 478 479 ia.len = 4; 480 memcpy(ia.iabuf, &packet->raw->giaddr, 4); 481 subnet = find_subnet(ia); 482 if (subnet) 483 packet->shared_network = subnet->shared_network; 484 else 485 packet->shared_network = NULL; 486 } else { 487 packet->shared_network = packet->interface->shared_network; 488 } 489 if (packet->shared_network) 490 return 1; 491 return 0; 492} 493 494void 495add_timeout(time_t when, void (*where)(void *), void *what) 496{ 497 struct timeout *t, *q; 498 499 /* See if this timeout supersedes an existing timeout. */ 500 t = NULL; 501 for (q = timeouts; q; q = q->next) { 502 if (q->func == where && q->what == what) { 503 if (t) 504 t->next = q->next; 505 else 506 timeouts = q->next; 507 break; 508 } 509 t = q; 510 } 511 512 /* If we didn't supersede a timeout, allocate a timeout 513 structure now. */ 514 if (!q) { 515 if (free_timeouts) { 516 q = free_timeouts; 517 free_timeouts = q->next; 518 q->func = where; 519 q->what = what; 520 } else { 521 q = (struct timeout *)malloc(sizeof (struct timeout)); 522 if (!q) 523 error("Can't allocate timeout structure!"); 524 q->func = where; 525 q->what = what; 526 } 527 } 528 529 q->when = when; 530 531 /* Now sort this timeout into the timeout list. */ 532 533 /* Beginning of list? */ 534 if (!timeouts || timeouts->when > q->when) { 535 q->next = timeouts; 536 timeouts = q; 537 return; 538 } 539 540 /* Middle of list? */ 541 for (t = timeouts; t->next; t = t->next) { 542 if (t->next->when > q->when) { 543 q->next = t->next; 544 t->next = q; 545 return; 546 } 547 } 548 549 /* End of list. */ 550 t->next = q; 551 q->next = NULL; 552} 553 554void 555cancel_timeout(void (*where)(void *), void *what) 556{ 557 struct timeout *t, *q; 558 559 /* Look for this timeout on the list, and unlink it if we find it. */ 560 t = NULL; 561 for (q = timeouts; q; q = q->next) { 562 if (q->func == where && q->what == what) { 563 if (t) 564 t->next = q->next; 565 else 566 timeouts = q->next; 567 break; 568 } 569 t = q; 570 } 571 572 /* If we found the timeout, put it on the free list. */ 573 if (q) { 574 q->next = free_timeouts; 575 free_timeouts = q; 576 } 577} 578 579/* Add a protocol to the list of protocols... */ 580void 581add_protocol(char *name, int fd, void (*handler)(struct protocol *), 582 void *local) 583{ 584 struct protocol *p; 585 586 p = (struct protocol *)malloc(sizeof *p); 587 if (!p) 588 error("can't allocate protocol struct for %s", name); 589 p->fd = fd; 590 p->handler = handler; 591 p->local = local; 592 p->next = protocols; 593 protocols = p; 594} 595 596void 597remove_protocol(struct protocol *proto) 598{ 599 struct protocol *p, *next, *prev = NULL; 600 601 for (p = protocols; p; p = next) { 602 next = p->next; 603 if (p == proto) { 604 if (prev) 605 prev->next = p->next; 606 else 607 protocols = p->next; 608 free(p); 609 } 610 } 611} 612