1 /* 2 * dhcpcd - DHCP client daemon 3 * Copyright (c) 2006-2010 Roy Marples <roy (at) marples.name> 4 * All rights reserved 5 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/stat.h> 29 #include <sys/uio.h> 30 #include <sys/wait.h> 31 32 #include <netinet/in.h> 33 #include <arpa/inet.h> 34 35 #include <ctype.h> 36 #include <errno.h> 37 #include <signal.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <syslog.h> 41 #include <unistd.h> 42 43 #include "config.h" 44 #include "common.h" 45 #include "configure.h" 46 #include "dhcp.h" 47 #include "if-options.h" 48 #include "if-pref.h" 49 #include "net.h" 50 #include "signals.h" 51 52 #define DEFAULT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin" 53 54 /* Some systems have route metrics */ 55 #ifndef HAVE_ROUTE_METRIC 56 # ifdef __linux__ 57 # define HAVE_ROUTE_METRIC 1 58 # endif 59 # ifndef HAVE_ROUTE_METRIC 60 # define HAVE_ROUTE_METRIC 0 61 # endif 62 #endif 63 64 static struct rt *routes; 65 66 67 static int 68 exec_script(char *const *argv, char *const *env) 69 { 70 pid_t pid; 71 sigset_t full; 72 sigset_t old; 73 74 /* OK, we need to block signals */ 75 sigfillset(&full); 76 sigprocmask(SIG_SETMASK, &full, &old); 77 signal_reset(); 78 79 switch (pid = vfork()) { 80 case -1: 81 syslog(LOG_ERR, "vfork: %m"); 82 break; 83 case 0: 84 sigprocmask(SIG_SETMASK, &old, NULL); 85 execve(argv[0], argv, env); 86 syslog(LOG_ERR, "%s: %m", argv[0]); 87 _exit(127); 88 /* NOTREACHED */ 89 } 90 91 /* Restore our signals */ 92 signal_setup(); 93 sigprocmask(SIG_SETMASK, &old, NULL); 94 return pid; 95 } 96 97 static char * 98 make_var(const char *prefix, const char *var) 99 { 100 size_t len; 101 char *v; 102 103 len = strlen(prefix) + strlen(var) + 2; 104 v = xmalloc(len); 105 snprintf(v, len, "%s_%s", prefix, var); 106 return v; 107 } 108 109 110 static void 111 append_config(char ***env, ssize_t *len, 112 const char *prefix, const char *const *config) 113 { 114 ssize_t i, j, e1; 115 char **ne, *eq; 116 117 if (config == NULL) 118 return; 119 120 ne = *env; 121 for (i = 0; config[i] != NULL; i++) { 122 eq = strchr(config[i], '='); 123 e1 = eq - config[i] + 1; 124 for (j = 0; j < *len; j++) { 125 if (strncmp(ne[j] + strlen(prefix) + 1, 126 config[i], e1) == 0) 127 { 128 free(ne[j]); 129 ne[j] = make_var(prefix, config[i]); 130 break; 131 } 132 } 133 if (j == *len) { 134 j++; 135 ne = xrealloc(ne, sizeof(char *) * (j + 1)); 136 ne[j - 1] = make_var(prefix, config[i]); 137 *len = j; 138 } 139 } 140 *env = ne; 141 } 142 143 static size_t 144 arraytostr(const char *const *argv, char **s) 145 { 146 const char *const *ap; 147 char *p; 148 size_t len, l; 149 150 len = 0; 151 ap = argv; 152 while (*ap) 153 len += strlen(*ap++) + 1; 154 *s = p = xmalloc(len); 155 ap = argv; 156 while (*ap) { 157 l = strlen(*ap) + 1; 158 memcpy(p, *ap, l); 159 p += l; 160 ap++; 161 } 162 return len; 163 } 164 165 static ssize_t 166 make_env(const struct interface *iface, char ***argv) 167 { 168 char **env, *p; 169 ssize_t e, elen, l; 170 const struct if_options *ifo = iface->state->options; 171 const struct interface *ifp; 172 173 /* Make our env */ 174 elen = 8; 175 env = xmalloc(sizeof(char *) * (elen + 1)); 176 e = strlen("interface") + strlen(iface->name) + 2; 177 env[0] = xmalloc(e); 178 snprintf(env[0], e, "interface=%s", iface->name); 179 e = strlen("reason") + strlen(iface->state->reason) + 2; 180 env[1] = xmalloc(e); 181 snprintf(env[1], e, "reason=%s", iface->state->reason); 182 e = 20; 183 env[2] = xmalloc(e); 184 snprintf(env[2], e, "pid=%d", getpid()); 185 env[3] = xmalloc(e); 186 snprintf(env[3], e, "ifmetric=%d", iface->metric); 187 env[4] = xmalloc(e); 188 snprintf(env[4], e, "ifwireless=%d", iface->wireless); 189 env[5] = xmalloc(e); 190 snprintf(env[5], e, "ifflags=%u", iface->flags); 191 env[6] = xmalloc(e); 192 snprintf(env[6], e, "ifmtu=%d", get_mtu(iface->name)); 193 l = e = strlen("interface_order="); 194 for (ifp = ifaces; ifp; ifp = ifp->next) 195 e += strlen(ifp->name) + 1; 196 p = env[7] = xmalloc(e); 197 strlcpy(p, "interface_order=", e); 198 e -= l; 199 p += l; 200 for (ifp = ifaces; ifp; ifp = ifp->next) { 201 l = strlcpy(p, ifp->name, e); 202 p += l; 203 e -= l; 204 *p++ = ' '; 205 e--; 206 } 207 *--p = '\0'; 208 if (*iface->state->profile) { 209 e = strlen("profile=") + strlen(iface->state->profile) + 2; 210 env[elen] = xmalloc(e); 211 snprintf(env[elen++], e, "profile=%s", iface->state->profile); 212 } 213 if (iface->wireless) { 214 e = strlen("new_ssid=") + strlen(iface->ssid) + 2; 215 if (iface->state->new != NULL || 216 strcmp(iface->state->reason, "CARRIER") == 0) 217 { 218 env = xrealloc(env, sizeof(char *) * (elen + 2)); 219 env[elen] = xmalloc(e); 220 snprintf(env[elen++], e, "new_ssid=%s", iface->ssid); 221 } 222 if (iface->state->old != NULL || 223 strcmp(iface->state->reason, "NOCARRIER") == 0) 224 { 225 env = xrealloc(env, sizeof(char *) * (elen + 2)); 226 env[elen] = xmalloc(e); 227 snprintf(env[elen++], e, "old_ssid=%s", iface->ssid); 228 } 229 } 230 if (iface->state->old) { 231 e = configure_env(NULL, NULL, iface->state->old, ifo); 232 if (e > 0) { 233 env = xrealloc(env, sizeof(char *) * (elen + e + 1)); 234 elen += configure_env(env + elen, "old", 235 iface->state->old, ifo); 236 } 237 append_config(&env, &elen, "old", 238 (const char *const *)ifo->config); 239 } 240 if (iface->state->new) { 241 e = configure_env(NULL, NULL, iface->state->new, ifo); 242 if (e > 0) { 243 env = xrealloc(env, sizeof(char *) * (elen + e + 1)); 244 elen += configure_env(env + elen, "new", 245 iface->state->new, ifo); 246 } 247 append_config(&env, &elen, "new", 248 (const char *const *)ifo->config); 249 } 250 251 /* Add our base environment */ 252 if (ifo->environ) { 253 e = 0; 254 while (ifo->environ[e++]) 255 ; 256 env = xrealloc(env, sizeof(char *) * (elen + e + 1)); 257 e = 0; 258 while (ifo->environ[e]) { 259 env[elen + e] = xstrdup(ifo->environ[e]); 260 e++; 261 } 262 elen += e; 263 } 264 env[elen] = '\0'; 265 266 *argv = env; 267 return elen; 268 } 269 270 int 271 send_interface(int fd, const struct interface *iface) 272 { 273 char **env, **ep, *s; 274 ssize_t elen; 275 struct iovec iov[2]; 276 int retval; 277 278 retval = 0; 279 make_env(iface, &env); 280 elen = arraytostr((const char *const *)env, &s); 281 iov[0].iov_base = &elen; 282 iov[0].iov_len = sizeof(ssize_t); 283 iov[1].iov_base = s; 284 iov[1].iov_len = elen; 285 retval = writev(fd, iov, 2); 286 ep = env; 287 while (*ep) 288 free(*ep++); 289 free(env); 290 free(s); 291 return retval; 292 } 293 294 int 295 run_script(const struct interface *iface) 296 { 297 char *const argv[2] = { UNCONST(iface->state->options->script), NULL }; 298 char **env = NULL, **ep; 299 char *path, *bigenv; 300 ssize_t e, elen = 0; 301 pid_t pid; 302 int status = 0; 303 const struct fd_list *fd; 304 struct iovec iov[2]; 305 306 syslog(LOG_DEBUG, "%s: executing `%s', reason %s", 307 iface->name, argv[0], iface->state->reason); 308 309 /* Make our env */ 310 elen = make_env(iface, &env); 311 env = xrealloc(env, sizeof(char *) * (elen + 2)); 312 /* Add path to it */ 313 path = getenv("PATH"); 314 if (path) { 315 e = strlen("PATH") + strlen(path) + 2; 316 env[elen] = xmalloc(e); 317 snprintf(env[elen], e, "PATH=%s", path); 318 } else 319 env[elen] = xstrdup(DEFAULT_PATH); 320 env[++elen] = '\0'; 321 322 pid = exec_script(argv, env); 323 if (pid == -1) 324 status = -1; 325 else if (pid != 0) { 326 /* Wait for the script to finish */ 327 while (waitpid(pid, &status, 0) == -1) { 328 if (errno != EINTR) { 329 syslog(LOG_ERR, "waitpid: %m"); 330 status = -1; 331 break; 332 } 333 } 334 } 335 336 /* Send to our listeners */ 337 bigenv = NULL; 338 for (fd = fds; fd != NULL; fd = fd->next) { 339 if (fd->listener) { 340 if (bigenv == NULL) { 341 elen = arraytostr((const char *const *)env, 342 &bigenv); 343 iov[0].iov_base = &elen; 344 iov[0].iov_len = sizeof(ssize_t); 345 iov[1].iov_base = bigenv; 346 iov[1].iov_len = elen; 347 } 348 if (writev(fd->fd, iov, 2) == -1) 349 syslog(LOG_ERR, "writev: %m"); 350 } 351 } 352 free(bigenv); 353 354 /* Cleanup */ 355 ep = env; 356 while (*ep) 357 free(*ep++); 358 free(env); 359 return status; 360 } 361 362 static struct rt * 363 find_route(struct rt *rts, const struct rt *r, struct rt **lrt, 364 const struct rt *srt) 365 { 366 struct rt *rt; 367 368 if (lrt) 369 *lrt = NULL; 370 for (rt = rts; rt; rt = rt->next) { 371 if (rt->dest.s_addr == r->dest.s_addr && 372 #if HAVE_ROUTE_METRIC 373 (srt || (!rt->iface || 374 rt->iface->metric == r->iface->metric)) && 375 #endif 376 (!srt || srt != rt) && 377 rt->net.s_addr == r->net.s_addr) 378 return rt; 379 if (lrt) 380 *lrt = rt; 381 } 382 return NULL; 383 } 384 385 static void 386 desc_route(const char *cmd, const struct rt *rt, const char *ifname) 387 { 388 char addr[sizeof("000.000.000.000") + 1]; 389 390 strlcpy(addr, inet_ntoa(rt->dest), sizeof(addr)); 391 if (rt->gate.s_addr == INADDR_ANY) 392 syslog(LOG_DEBUG, "%s: %s route to %s/%d", ifname, cmd, 393 addr, inet_ntocidr(rt->net)); 394 else if (rt->gate.s_addr == rt->dest.s_addr && 395 rt->net.s_addr == INADDR_BROADCAST) 396 syslog(LOG_DEBUG, "%s: %s host route to %s", ifname, cmd, 397 addr); 398 else if (rt->dest.s_addr == INADDR_ANY && rt->net.s_addr == INADDR_ANY) 399 syslog(LOG_DEBUG, "%s: %s default route via %s", ifname, cmd, 400 inet_ntoa(rt->gate)); 401 else 402 syslog(LOG_DEBUG, "%s: %s route to %s/%d via %s", ifname, cmd, 403 addr, inet_ntocidr(rt->net), inet_ntoa(rt->gate)); 404 } 405 406 /* If something other than dhcpcd removes a route, 407 * we need to remove it from our internal table. */ 408 int 409 route_deleted(const struct rt *rt) 410 { 411 struct rt *f, *l; 412 413 f = find_route(routes, rt, &l, NULL); 414 if (f == NULL) 415 return 0; 416 desc_route("removing", f, f->iface->name); 417 if (l) 418 l->next = f->next; 419 else 420 routes = f->next; 421 free(f); 422 return 1; 423 } 424 425 static int 426 n_route(struct rt *rt, const struct interface *iface) 427 { 428 /* Don't set default routes if not asked to */ 429 if (rt->dest.s_addr == 0 && 430 rt->net.s_addr == 0 && 431 !(iface->state->options->options & DHCPCD_GATEWAY)) 432 return -1; 433 434 desc_route("adding", rt, iface->name); 435 if (!add_route(iface, &rt->dest, &rt->net, &rt->gate, iface->metric)) 436 return 0; 437 if (errno == EEXIST) { 438 /* Pretend we added the subnet route */ 439 if (rt->dest.s_addr == (iface->addr.s_addr & iface->net.s_addr) && 440 rt->net.s_addr == iface->net.s_addr && 441 rt->gate.s_addr == 0) 442 return 0; 443 else 444 return -1; 445 } 446 syslog(LOG_ERR, "%s: add_route: %m", iface->name); 447 return -1; 448 } 449 450 static int 451 c_route(struct rt *ort, struct rt *nrt, const struct interface *iface) 452 { 453 /* Don't set default routes if not asked to */ 454 if (nrt->dest.s_addr == 0 && 455 nrt->net.s_addr == 0 && 456 !(iface->state->options->options & DHCPCD_GATEWAY)) 457 return -1; 458 459 desc_route("changing", nrt, iface->name); 460 /* We delete and add the route so that we can change metric. 461 * This also has the nice side effect of flushing ARP entries so 462 * we don't have to do that manually. */ 463 del_route(ort->iface, &ort->dest, &ort->net, &ort->gate, 464 ort->iface->metric); 465 if (!add_route(iface, &nrt->dest, &nrt->net, &nrt->gate, 466 iface->metric)) 467 return 0; 468 syslog(LOG_ERR, "%s: add_route: %m", iface->name); 469 return -1; 470 } 471 472 static int 473 d_route(struct rt *rt, const struct interface *iface, int metric) 474 { 475 int retval; 476 477 desc_route("deleting", rt, iface->name); 478 retval = del_route(iface, &rt->dest, &rt->net, &rt->gate, metric); 479 if (retval != 0 && errno != ENOENT && errno != ESRCH) 480 syslog(LOG_ERR,"%s: del_route: %m", iface->name); 481 return retval; 482 } 483 484 static struct rt * 485 get_subnet_route(struct dhcp_message *dhcp) 486 { 487 in_addr_t addr; 488 struct in_addr net; 489 struct rt *rt; 490 491 addr = dhcp->yiaddr; 492 if (addr == 0) 493 addr = dhcp->ciaddr; 494 /* Ensure we have all the needed values */ 495 if (get_option_addr(&net, dhcp, DHO_SUBNETMASK) == -1) 496 net.s_addr = get_netmask(addr); 497 if (net.s_addr == INADDR_BROADCAST || net.s_addr == INADDR_ANY) 498 return NULL; 499 rt = malloc(sizeof(*rt)); 500 rt->dest.s_addr = addr & net.s_addr; 501 rt->net.s_addr = net.s_addr; 502 rt->gate.s_addr = 0; 503 return rt; 504 } 505 506 static struct rt * 507 add_subnet_route(struct rt *rt, const struct interface *iface) 508 { 509 struct rt *r; 510 511 if (iface->net.s_addr == INADDR_BROADCAST || 512 iface->net.s_addr == INADDR_ANY || 513 (iface->state->options->options & 514 (DHCPCD_INFORM | DHCPCD_STATIC) && 515 iface->state->options->req_addr.s_addr == INADDR_ANY)) 516 return rt; 517 518 r = xmalloc(sizeof(*r)); 519 r->dest.s_addr = iface->addr.s_addr & iface->net.s_addr; 520 r->net.s_addr = iface->net.s_addr; 521 r->gate.s_addr = 0; 522 r->next = rt; 523 return r; 524 } 525 526 static struct rt * 527 get_routes(const struct interface *iface) 528 { 529 struct rt *rt, *nrt = NULL, *r = NULL; 530 531 if (iface->state->options->routes != NULL) { 532 for (rt = iface->state->options->routes; 533 rt != NULL; 534 rt = rt->next) 535 { 536 if (rt->gate.s_addr == 0) 537 break; 538 if (r == NULL) 539 r = nrt = xmalloc(sizeof(*r)); 540 else { 541 r->next = xmalloc(sizeof(*r)); 542 r = r->next; 543 } 544 memcpy(r, rt, sizeof(*r)); 545 r->next = NULL; 546 } 547 return nrt; 548 } 549 550 return get_option_routes(iface->state->new, 551 iface->name, &iface->state->options->options); 552 } 553 554 /* Some DHCP servers add set host routes by setting the gateway 555 * to the assinged IP address. This differs from our notion of a host route 556 * where the gateway is the destination address, so we fix it. */ 557 static struct rt * 558 massage_host_routes(struct rt *rt, const struct interface *iface) 559 { 560 struct rt *r; 561 562 for (r = rt; r; r = r->next) 563 if (r->gate.s_addr == iface->addr.s_addr && 564 r->net.s_addr == INADDR_BROADCAST) 565 r->gate.s_addr = r->dest.s_addr; 566 return rt; 567 } 568 569 static struct rt * 570 add_destination_route(struct rt *rt, const struct interface *iface) 571 { 572 struct rt *r; 573 574 if (!(iface->flags & IFF_POINTOPOINT) || 575 !has_option_mask(iface->state->options->dstmask, DHO_ROUTER)) 576 return rt; 577 r = xmalloc(sizeof(*r)); 578 r->dest.s_addr = INADDR_ANY; 579 r->net.s_addr = INADDR_ANY; 580 r->gate.s_addr = iface->dst.s_addr; 581 r->next = rt; 582 return r; 583 } 584 585 /* We should check to ensure the routers are on the same subnet 586 * OR supply a host route. If not, warn and add a host route. */ 587 static struct rt * 588 add_router_host_route(struct rt *rt, const struct interface *ifp) 589 { 590 struct rt *rtp, *rtl, *rtn; 591 const char *cp, *cp2, *cp3, *cplim; 592 593 for (rtp = rt, rtl = NULL; rtp; rtl = rtp, rtp = rtp->next) { 594 if (rtp->dest.s_addr != INADDR_ANY) 595 continue; 596 /* Scan for a route to match */ 597 for (rtn = rt; rtn != rtp; rtn = rtn->next) { 598 /* match host */ 599 if (rtn->dest.s_addr == rtp->gate.s_addr) 600 break; 601 /* match subnet */ 602 cp = (const char *)&rtp->gate.s_addr; 603 cp2 = (const char *)&rtn->dest.s_addr; 604 cp3 = (const char *)&rtn->net.s_addr; 605 cplim = cp3 + sizeof(rtn->net.s_addr); 606 while (cp3 < cplim) { 607 if ((*cp++ ^ *cp2++) & *cp3++) 608 break; 609 } 610 if (cp3 == cplim) 611 break; 612 } 613 if (rtn != rtp) 614 continue; 615 if (ifp->flags & IFF_NOARP) { 616 syslog(LOG_WARNING, 617 "%s: forcing router %s through interface", 618 ifp->name, inet_ntoa(rtp->gate)); 619 rtp->gate.s_addr = 0; 620 continue; 621 } 622 syslog(LOG_WARNING, "%s: router %s requires a host route", 623 ifp->name, inet_ntoa(rtp->gate)); 624 rtn = xmalloc(sizeof(*rtn)); 625 rtn->dest.s_addr = rtp->gate.s_addr; 626 rtn->net.s_addr = INADDR_BROADCAST; 627 rtn->gate.s_addr = rtp->gate.s_addr; 628 rtn->next = rtp; 629 if (rtl == NULL) 630 rt = rtn; 631 else 632 rtl->next = rtn; 633 } 634 return rt; 635 } 636 637 void 638 build_routes(void) 639 { 640 struct rt *nrs = NULL, *dnr, *or, *rt, *rtn, *rtl, *lrt = NULL; 641 const struct interface *ifp; 642 643 if (avoid_routes) return; 644 645 for (ifp = ifaces; ifp; ifp = ifp->next) { 646 if (ifp->state->new == NULL) 647 continue; 648 dnr = get_routes(ifp); 649 dnr = massage_host_routes(dnr, ifp); 650 dnr = add_subnet_route(dnr, ifp); 651 dnr = add_router_host_route(dnr, ifp); 652 dnr = add_destination_route(dnr, ifp); 653 for (rt = dnr; rt && (rtn = rt->next, 1); lrt = rt, rt = rtn) { 654 rt->iface = ifp; 655 /* Is this route already in our table? */ 656 if ((find_route(nrs, rt, NULL, NULL)) != NULL) 657 continue; 658 /* Do we already manage it? */ 659 if ((or = find_route(routes, rt, &rtl, NULL))) { 660 if (or->iface != ifp || 661 rt->gate.s_addr != or->gate.s_addr) 662 { 663 if (c_route(or, rt, ifp) != 0) 664 continue; 665 } 666 if (rtl != NULL) 667 rtl->next = or->next; 668 else 669 routes = or->next; 670 free(or); 671 } else { 672 if (n_route(rt, ifp) != 0) 673 continue; 674 } 675 if (dnr == rt) 676 dnr = rtn; 677 else if (lrt) 678 lrt->next = rtn; 679 rt->next = nrs; 680 nrs = rt; 681 } 682 free_routes(dnr); 683 } 684 685 /* Remove old routes we used to manage */ 686 for (rt = routes; rt; rt = rt->next) { 687 if (find_route(nrs, rt, NULL, NULL) == NULL) 688 d_route(rt, rt->iface, rt->iface->metric); 689 } 690 691 free_routes(routes); 692 routes = nrs; 693 } 694 695 static int 696 delete_address(struct interface *iface) 697 { 698 int retval; 699 struct if_options *ifo; 700 701 ifo = iface->state->options; 702 if (ifo->options & DHCPCD_INFORM || 703 (ifo->options & DHCPCD_STATIC && ifo->req_addr.s_addr == 0)) 704 return 0; 705 syslog(LOG_DEBUG, "%s: deleting IP address %s/%d", 706 iface->name, 707 inet_ntoa(iface->addr), 708 inet_ntocidr(iface->net)); 709 retval = del_address(iface, &iface->addr, &iface->net); 710 if (retval == -1 && errno != EADDRNOTAVAIL) 711 syslog(LOG_ERR, "del_address: %m"); 712 iface->addr.s_addr = 0; 713 iface->net.s_addr = 0; 714 return retval; 715 } 716 717 int 718 configure(struct interface *iface) 719 { 720 struct dhcp_message *dhcp = iface->state->new; 721 struct dhcp_lease *lease = &iface->state->lease; 722 struct if_options *ifo = iface->state->options; 723 struct rt *rt; 724 725 /* As we are now adjusting an interface, we need to ensure 726 * we have them in the right order for routing and configuration. */ 727 sort_interfaces(); 728 729 if (dhcp == NULL) { 730 if (!(ifo->options & DHCPCD_PERSISTENT)) { 731 build_routes(); 732 if (iface->addr.s_addr != 0) 733 delete_address(iface); 734 run_script(iface); 735 } 736 return 0; 737 } 738 739 /* This also changes netmask */ 740 if (!(ifo->options & DHCPCD_INFORM) || 741 !has_address(iface->name, &lease->addr, &lease->net)) 742 { 743 syslog(LOG_DEBUG, "%s: adding IP address %s/%d", 744 iface->name, inet_ntoa(lease->addr), 745 inet_ntocidr(lease->net)); 746 if (add_address(iface, 747 &lease->addr, &lease->net, &lease->brd) == -1 && 748 errno != EEXIST) 749 { 750 syslog(LOG_ERR, "add_address: %m"); 751 return -1; 752 } 753 } 754 755 /* Now delete the old address if different */ 756 if (iface->addr.s_addr != lease->addr.s_addr && 757 iface->addr.s_addr != 0) 758 delete_address(iface); 759 760 iface->addr.s_addr = lease->addr.s_addr; 761 iface->net.s_addr = lease->net.s_addr; 762 763 if (!avoid_routes) { 764 /* We need to delete the subnet route to have our metric or 765 * prefer the interface. */ 766 rt = get_subnet_route(dhcp); 767 if (rt != NULL) { 768 rt->iface = iface; 769 if (!find_route(routes, rt, NULL, NULL)) 770 del_route(iface, &rt->dest, &rt->net, &rt->gate, 0); 771 free(rt); 772 } 773 774 build_routes(); 775 } 776 777 if (!iface->state->lease.frominfo && 778 !(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC))) 779 if (write_lease(iface, dhcp) == -1) 780 syslog(LOG_ERR, "write_lease: %m"); 781 run_script(iface); 782 return 0; 783 } 784