1 /* $OpenBSD: ldpd.c,v 1.20 2014/07/12 20:16:38 krw Exp $ */ 2 3 /* 4 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 5 * Copyright (c) 2004, 2008 Esben Norby <norby@openbsd.org> 6 * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 7 * 8 * Permission to use, copy, modify, and distribute this software for any 9 * purpose with or without fee is hereby granted, provided that the above 10 * copyright notice and this permission notice appear in all copies. 11 * 12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19 */ 20 21 #include <sys/types.h> 22 #include <sys/socket.h> 23 #include <sys/queue.h> 24 #include <sys/time.h> 25 #include <sys/stat.h> 26 #include <sys/wait.h> 27 #include <sys/param.h> 28 29 #include <netinet/in.h> 30 #include <arpa/inet.h> 31 #include <netmpls/mpls.h> 32 33 #include <event.h> 34 #include <err.h> 35 #include <errno.h> 36 #include <pwd.h> 37 #include <stdio.h> 38 #include <stdlib.h> 39 #include <string.h> 40 #include <signal.h> 41 #include <unistd.h> 42 43 #include "ldpd.h" 44 #include "ldp.h" 45 #include "ldpe.h" 46 #include "control.h" 47 #include "log.h" 48 #include "lde.h" 49 50 void main_sig_handler(int, short, void *); 51 __dead void usage(void); 52 void ldpd_shutdown(void); 53 int check_child(pid_t, const char *); 54 55 void main_dispatch_ldpe(int, short, void *); 56 void main_dispatch_lde(int, short, void *); 57 58 /*int ldp_reload(void); */ 59 int ldp_sendboth(enum imsg_type, void *, u_int16_t); 60 /*int merge_interfaces(struct lspace *, struct lspace *); */ 61 /*struct iface *iface_lookup(struct lspace *, struct iface *); */ 62 63 int pipe_parent2ldpe[2]; 64 int pipe_parent2lde[2]; 65 int pipe_ldpe2lde[2]; 66 67 struct ldpd_conf *ldpd_conf = NULL; 68 struct imsgev *iev_ldpe; 69 struct imsgev *iev_lde; 70 char *conffile; 71 72 pid_t ldpe_pid = 0; 73 pid_t lde_pid = 0; 74 75 /* ARGSUSED */ 76 void 77 main_sig_handler(int sig, short event, void *arg) 78 { 79 /* 80 * signal handler rules don't apply, libevent decouples for us 81 */ 82 83 int die = 0; 84 85 switch (sig) { 86 case SIGTERM: 87 case SIGINT: 88 die = 1; 89 /* FALLTHROUGH */ 90 case SIGCHLD: 91 if (check_child(ldpe_pid, "ldp engine")) { 92 ldpe_pid = 0; 93 die = 1; 94 } 95 if (check_child(lde_pid, "label decision engine")) { 96 lde_pid = 0; 97 die = 1; 98 } 99 if (die) 100 ldpd_shutdown(); 101 break; 102 case SIGHUP: 103 /* 104 if (ldp_reload() == -1) 105 log_warnx("configuration reload failed"); 106 else 107 log_debug("configuration reloaded"); 108 */ 109 break; 110 default: 111 fatalx("unexpected signal"); 112 /* NOTREACHED */ 113 } 114 } 115 116 __dead void 117 usage(void) 118 { 119 extern char *__progname; 120 121 fprintf(stderr, "usage: %s [-dnv] [-D macro=value] [-f file]\n", 122 __progname); 123 exit(1); 124 } 125 126 int 127 main(int argc, char *argv[]) 128 { 129 struct event ev_sigint, ev_sigterm, ev_sigchld, ev_sighup; 130 int ch, opts = 0; 131 int debug = 0; 132 133 conffile = CONF_FILE; 134 ldpd_process = PROC_MAIN; 135 136 log_init(1); /* log to stderr until daemonized */ 137 log_verbose(1); 138 139 while ((ch = getopt(argc, argv, "dD:f:nv")) != -1) { 140 switch (ch) { 141 case 'd': 142 debug = 1; 143 break; 144 case 'D': 145 if (cmdline_symset(optarg) < 0) 146 log_warnx("could not parse macro definition %s", 147 optarg); 148 break; 149 case 'f': 150 conffile = optarg; 151 break; 152 case 'n': 153 opts |= LDPD_OPT_NOACTION; 154 break; 155 case 'v': 156 if (opts & LDPD_OPT_VERBOSE) 157 opts |= LDPD_OPT_VERBOSE2; 158 opts |= LDPD_OPT_VERBOSE; 159 break; 160 default: 161 usage(); 162 /* NOTREACHED */ 163 } 164 } 165 166 /* fetch interfaces early */ 167 kif_init(); 168 169 /* parse config file */ 170 if ((ldpd_conf = parse_config(conffile, opts)) == NULL ) 171 exit(1); 172 173 if (ldpd_conf->opts & LDPD_OPT_NOACTION) { 174 if (ldpd_conf->opts & LDPD_OPT_VERBOSE) 175 print_config(ldpd_conf); 176 else 177 fprintf(stderr, "configuration OK\n"); 178 exit(0); 179 } 180 181 /* check for root privileges */ 182 if (geteuid()) 183 errx(1, "need root privileges"); 184 185 /* check for ldpd user */ 186 if (getpwnam(LDPD_USER) == NULL) 187 errx(1, "unknown user %s", LDPD_USER); 188 189 log_init(debug); 190 log_verbose(opts & (LDPD_OPT_VERBOSE | LDPD_OPT_VERBOSE2)); 191 192 if (!debug) 193 daemon(1, 0); 194 195 log_info("startup"); 196 197 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, 198 pipe_parent2ldpe) == -1) 199 fatal("socketpair"); 200 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2lde) == -1) 201 fatal("socketpair"); 202 if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_ldpe2lde) == -1) 203 fatal("socketpair"); 204 session_socket_blockmode(pipe_parent2ldpe[0], BM_NONBLOCK); 205 session_socket_blockmode(pipe_parent2ldpe[1], BM_NONBLOCK); 206 session_socket_blockmode(pipe_parent2lde[0], BM_NONBLOCK); 207 session_socket_blockmode(pipe_parent2lde[1], BM_NONBLOCK); 208 session_socket_blockmode(pipe_ldpe2lde[0], BM_NONBLOCK); 209 session_socket_blockmode(pipe_ldpe2lde[1], BM_NONBLOCK); 210 211 /* start children */ 212 lde_pid = lde(ldpd_conf, pipe_parent2lde, pipe_ldpe2lde, 213 pipe_parent2ldpe); 214 ldpe_pid = ldpe(ldpd_conf, pipe_parent2ldpe, pipe_ldpe2lde, 215 pipe_parent2lde); 216 217 /* show who we are */ 218 setproctitle("parent"); 219 220 event_init(); 221 222 /* setup signal handler */ 223 signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL); 224 signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL); 225 signal_set(&ev_sigchld, SIGCHLD, main_sig_handler, NULL); 226 signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL); 227 signal_add(&ev_sigint, NULL); 228 signal_add(&ev_sigterm, NULL); 229 signal_add(&ev_sigchld, NULL); 230 signal_add(&ev_sighup, NULL); 231 signal(SIGPIPE, SIG_IGN); 232 233 /* setup pipes to children */ 234 close(pipe_parent2ldpe[1]); 235 close(pipe_parent2lde[1]); 236 close(pipe_ldpe2lde[0]); 237 close(pipe_ldpe2lde[1]); 238 239 if ((iev_ldpe = malloc(sizeof(struct imsgev))) == NULL || 240 (iev_lde = malloc(sizeof(struct imsgev))) == NULL) 241 fatal(NULL); 242 imsg_init(&iev_ldpe->ibuf, pipe_parent2ldpe[0]); 243 iev_ldpe->handler = main_dispatch_ldpe; 244 imsg_init(&iev_lde->ibuf, pipe_parent2lde[0]); 245 iev_lde->handler = main_dispatch_lde; 246 247 /* setup event handler */ 248 iev_ldpe->events = EV_READ; 249 event_set(&iev_ldpe->ev, iev_ldpe->ibuf.fd, iev_ldpe->events, 250 iev_ldpe->handler, iev_ldpe); 251 event_add(&iev_ldpe->ev, NULL); 252 253 iev_lde->events = EV_READ; 254 event_set(&iev_lde->ev, iev_lde->ibuf.fd, iev_lde->events, 255 iev_lde->handler, iev_lde); 256 event_add(&iev_lde->ev, NULL); 257 258 /* notify ldpe about existing interfaces and addresses */ 259 kif_redistribute(); 260 261 if (kr_init(!(ldpd_conf->flags & LDPD_FLAG_NO_FIB_UPDATE)) == -1) 262 fatalx("kr_init failed"); 263 264 /* remove unneded stuff from config */ 265 /* ... */ 266 267 event_dispatch(); 268 269 ldpd_shutdown(); 270 /* NOTREACHED */ 271 return (0); 272 } 273 274 void 275 ldpd_shutdown(void) 276 { 277 pid_t pid; 278 279 if (ldpe_pid) 280 kill(ldpe_pid, SIGTERM); 281 282 if (lde_pid) 283 kill(lde_pid, SIGTERM); 284 285 control_cleanup(); 286 kr_shutdown(); 287 288 do { 289 if ((pid = wait(NULL)) == -1 && 290 errno != EINTR && errno != ECHILD) 291 fatal("wait"); 292 } while (pid != -1 || (pid == -1 && errno == EINTR)); 293 294 msgbuf_clear(&iev_ldpe->ibuf.w); 295 free(iev_ldpe); 296 msgbuf_clear(&iev_lde->ibuf.w); 297 free(iev_lde); 298 free(ldpd_conf); 299 300 log_info("terminating"); 301 exit(0); 302 } 303 304 int 305 check_child(pid_t pid, const char *pname) 306 { 307 int status; 308 309 if (waitpid(pid, &status, WNOHANG) > 0) { 310 if (WIFEXITED(status)) { 311 log_warnx("lost child: %s exited", pname); 312 return (1); 313 } 314 if (WIFSIGNALED(status)) { 315 log_warnx("lost child: %s terminated; signal %d", 316 pname, WTERMSIG(status)); 317 return (1); 318 } 319 } 320 321 return (0); 322 } 323 324 /* imsg handling */ 325 /* ARGSUSED */ 326 void 327 main_dispatch_ldpe(int fd, short event, void *bula) 328 { 329 struct imsgev *iev = bula; 330 struct imsgbuf *ibuf = &iev->ibuf; 331 struct imsg imsg; 332 ssize_t n; 333 int shut = 0, verbose; 334 335 if (event & EV_READ) { 336 if ((n = imsg_read(ibuf)) == -1) 337 fatal("imsg_read error"); 338 if (n == 0) /* connection closed */ 339 shut = 1; 340 } 341 if (event & EV_WRITE) { 342 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 343 fatal("msgbuf_write"); 344 if (n == 0) 345 shut = 1; 346 } 347 348 for (;;) { 349 if ((n = imsg_get(ibuf, &imsg)) == -1) 350 fatal("imsg_get"); 351 352 if (n == 0) 353 break; 354 355 switch (imsg.hdr.type) { 356 case IMSG_CTL_RELOAD: 357 /* 358 if (ldp_reload() == -1) 359 log_warnx("configuration reload failed"); 360 else 361 log_debug("configuration reloaded"); 362 break; 363 */ 364 case IMSG_CTL_FIB_COUPLE: 365 kr_fib_couple(); 366 break; 367 case IMSG_CTL_FIB_DECOUPLE: 368 kr_fib_decouple(); 369 break; 370 case IMSG_CTL_KROUTE: 371 case IMSG_CTL_KROUTE_ADDR: 372 kr_show_route(&imsg); 373 break; 374 case IMSG_CTL_IFINFO: 375 if (imsg.hdr.len == IMSG_HEADER_SIZE) 376 kr_ifinfo(NULL, imsg.hdr.pid); 377 else if (imsg.hdr.len == IMSG_HEADER_SIZE + IFNAMSIZ) 378 kr_ifinfo(imsg.data, imsg.hdr.pid); 379 else 380 log_warnx("IFINFO request with wrong len"); 381 break; 382 case IMSG_CTL_LOG_VERBOSE: 383 /* already checked by ldpe */ 384 memcpy(&verbose, imsg.data, sizeof(verbose)); 385 log_verbose(verbose); 386 break; 387 default: 388 log_debug("main_dispatch_ldpe: error handling imsg %d", 389 imsg.hdr.type); 390 break; 391 } 392 imsg_free(&imsg); 393 } 394 if (!shut) 395 imsg_event_add(iev); 396 else { 397 /* this pipe is dead, so remove the event handler */ 398 event_del(&iev->ev); 399 event_loopexit(NULL); 400 } 401 } 402 403 /* ARGSUSED */ 404 void 405 main_dispatch_lde(int fd, short event, void *bula) 406 { 407 struct imsgev *iev = bula; 408 struct imsgbuf *ibuf = &iev->ibuf; 409 struct imsg imsg; 410 ssize_t n; 411 int shut = 0; 412 413 if (event & EV_READ) { 414 if ((n = imsg_read(ibuf)) == -1) 415 fatal("imsg_read error"); 416 if (n == 0) /* connection closed */ 417 shut = 1; 418 } 419 if (event & EV_WRITE) { 420 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN) 421 fatal("msgbuf_write"); 422 if (n == 0) 423 shut = 1; 424 } 425 426 for (;;) { 427 if ((n = imsg_get(ibuf, &imsg)) == -1) 428 fatal("imsg_get"); 429 430 if (n == 0) 431 break; 432 433 switch (imsg.hdr.type) { 434 case IMSG_KLABEL_CHANGE: 435 if (imsg.hdr.len - IMSG_HEADER_SIZE != 436 sizeof(struct kroute)) 437 fatalx("invalid size of IMSG_KLABEL_CHANGE"); 438 if (kr_change(imsg.data)) 439 log_warn("main_dispatch_lde: error changing " 440 "route"); 441 break; 442 case IMSG_KLABEL_DELETE: 443 if (imsg.hdr.len - IMSG_HEADER_SIZE != 444 sizeof(struct kroute)) 445 fatalx("invalid size of IMSG_KLABEL_DELETE"); 446 if (kr_delete(imsg.data)) 447 log_warn("main_dispatch_lde: error deleting " 448 "route"); 449 break; 450 default: 451 log_debug("main_dispatch_lde: error handling imsg %d", 452 imsg.hdr.type); 453 break; 454 } 455 imsg_free(&imsg); 456 } 457 if (!shut) 458 imsg_event_add(iev); 459 else { 460 /* this pipe is dead, so remove the event handler */ 461 event_del(&iev->ev); 462 event_loopexit(NULL); 463 } 464 } 465 466 void 467 main_imsg_compose_ldpe(int type, pid_t pid, void *data, u_int16_t datalen) 468 { 469 if (iev_ldpe == NULL) 470 return; 471 imsg_compose_event(iev_ldpe, type, 0, pid, -1, data, datalen); 472 } 473 474 void 475 main_imsg_compose_lde(int type, pid_t pid, void *data, u_int16_t datalen) 476 { 477 imsg_compose_event(iev_lde, type, 0, pid, -1, data, datalen); 478 } 479 480 void 481 imsg_event_add(struct imsgev *iev) 482 { 483 iev->events = EV_READ; 484 if (iev->ibuf.w.queued) 485 iev->events |= EV_WRITE; 486 487 event_del(&iev->ev); 488 event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev); 489 event_add(&iev->ev, NULL); 490 } 491 492 int 493 imsg_compose_event(struct imsgev *iev, u_int16_t type, 494 u_int32_t peerid, pid_t pid, int fd, void *data, u_int16_t datalen) 495 { 496 int ret; 497 498 if ((ret = imsg_compose(&iev->ibuf, type, peerid, 499 pid, fd, data, datalen)) != -1) 500 imsg_event_add(iev); 501 return (ret); 502 } 503 504 void 505 evbuf_enqueue(struct evbuf *eb, struct ibuf *buf) 506 { 507 ibuf_close(&eb->wbuf, buf); 508 evbuf_event_add(eb); 509 } 510 511 void 512 evbuf_event_add(struct evbuf *eb) 513 { 514 if (eb->wbuf.queued) 515 event_add(&eb->ev, NULL); 516 } 517 518 void 519 evbuf_init(struct evbuf *eb, int fd, void (*handler)(int, short, void *), 520 void *arg) 521 { 522 msgbuf_init(&eb->wbuf); 523 eb->wbuf.fd = fd; 524 event_set(&eb->ev, eb->wbuf.fd, EV_WRITE, handler, arg); 525 } 526 527 void 528 evbuf_clear(struct evbuf *eb) 529 { 530 event_del(&eb->ev); 531 msgbuf_clear(&eb->wbuf); 532 eb->wbuf.fd = -1; 533 } 534 535 /* 536 int 537 ldp_reload(void) 538 { 539 struct lspace *lspace; 540 struct iface *iface; 541 struct ldpd_conf *xconf; 542 543 if ((xconf = parse_config(conffile, ldpd_conf->opts)) == NULL) 544 return (-1); 545 546 if (ldp_sendboth(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1) 547 return (-1); 548 549 LIST_FOREACH(lspace, &xconf->lspace_list, entry) { 550 if (ldp_sendboth(IMSG_RECONF_AREA, lspace, sizeof(*lspace)) == -1) 551 return (-1); 552 553 LIST_FOREACH(iface, &lspace->iface_list, entry) { 554 if (ldp_sendboth(IMSG_RECONF_IFACE, iface, 555 sizeof(*iface)) == -1) 556 return (-1); 557 } 558 } 559 560 if (ldp_sendboth(IMSG_RECONF_END, NULL, 0) == -1) 561 return (-1); 562 563 merge_config(ldpd_conf, xconf); 564 565 kr_reload(); 566 return (0); 567 } 568 569 int 570 ldp_sendboth(enum imsg_type type, void *buf, u_int16_t len) 571 { 572 if (imsg_compose_event(iev_ldpe, type, 0, 0, -1, buf, len) == -1) 573 return (-1); 574 if (imsg_compose_event(iev_lde, type, 0, 0, -1, buf, len) == -1) 575 return (-1); 576 return (0); 577 } 578 579 void 580 merge_config(struct ldpd_conf *conf, struct ldpd_conf *xconf) 581 { 582 struct lspace *a, *xa, *na; 583 struct iface *iface; 584 struct redistribute *r; 585 int rchange = 0; 586 587 conf->flags = xconf->flags; 588 conf->spf_delay = xconf->spf_delay; 589 conf->spf_hold_time = xconf->spf_hold_time; 590 if ((conf->redistribute & REDISTRIBUTE_ON) != 591 (xconf->redistribute & REDISTRIBUTE_ON)) 592 rchange = 1; 593 conf->redistribute = xconf->redistribute; 594 conf->rfc1583compat = xconf->rfc1583compat; 595 596 if (ldpd_process == PROC_MAIN) { 597 while ((r = SIMPLEQ_FIRST(&conf->redist_list)) != NULL) { 598 SIMPLEQ_REMOVE_HEAD(&conf->redist_list, entry); 599 free(r); 600 } 601 while ((r = SIMPLEQ_FIRST(&xconf->redist_list)) != NULL) { 602 SIMPLEQ_REMOVE_HEAD(&xconf->redist_list, entry); 603 SIMPLEQ_INSERT_TAIL(&conf->redist_list, r, entry); 604 } 605 goto done; 606 } 607 608 for (a = LIST_FIRST(&conf->lspace_list); a != NULL; a = na) { 609 na = LIST_NEXT(a, entry); 610 if ((xa = lspace_find(xconf, a->id)) == NULL) { 611 if (ldpd_process == PROC_LDP_ENGINE) { 612 LIST_FOREACH(iface, &a->iface_list, entry) 613 if_fsm(iface, IF_EVT_DOWN); 614 } 615 LIST_REMOVE(a, entry); 616 lspace_del(a); 617 } 618 } 619 620 for (xa = LIST_FIRST(&xconf->lspace_list); xa != NULL; xa = na) { 621 na = LIST_NEXT(xa, entry); 622 if ((a = lspace_find(conf, xa->id)) == NULL) { 623 LIST_REMOVE(xa, entry); 624 LIST_INSERT_HEAD(&conf->lspace_list, xa, entry); 625 if (ldpd_process == PROC_LDP_ENGINE) { 626 LIST_FOREACH(iface, &xa->iface_list, entry) { 627 if_init(conf, iface); 628 if (if_fsm(iface, IF_EVT_UP)) { 629 log_debug("error starting " 630 "interface %s", 631 iface->name); 632 } 633 } 634 } 635 continue; 636 } 637 a->stub = xa->stub; 638 a->stub_default_cost = xa->stub_default_cost; 639 if (ldpd_process == PROC_LDE_ENGINE) 640 a->dirty = 1; 641 642 if (merge_interfaces(a, xa) && 643 ldpd_process == PROC_LDP_ENGINE) 644 a->dirty = 1; 645 } 646 647 if (ldpd_process == PROC_LDP_ENGINE) { 648 LIST_FOREACH(a, &conf->lspace_list, entry) { 649 LIST_FOREACH(iface, &a->iface_list, entry) { 650 if (iface->state == IF_STA_NEW) { 651 iface->state = IF_STA_DOWN; 652 if_init(conf, iface); 653 if (if_fsm(iface, IF_EVT_UP)) { 654 log_debug("error starting " 655 "interface %s", 656 iface->name); 657 } 658 } 659 } 660 } 661 } 662 663 done: 664 while ((a = LIST_FIRST(&xconf->lspace_list)) != NULL) { 665 LIST_REMOVE(a, entry); 666 lspace_del(a); 667 } 668 free(xconf); 669 } 670 671 int 672 merge_interfaces(struct lspace *a, struct lspace *xa) 673 { 674 struct iface *i, *xi, *ni; 675 int dirty = 0; 676 677 for (i = LIST_FIRST(&a->iface_list); i != NULL; i = ni) { 678 ni = LIST_NEXT(i, entry); 679 if (iface_lookup(xa, i) == NULL) { 680 log_debug("merge_config: proc %d label space %s removing " 681 "interface %s", ldpd_process, inet_ntoa(a->id), 682 i->name); 683 if (ldpd_process == PROC_LDP_ENGINE) 684 if_fsm(i, IF_EVT_DOWN); 685 LIST_REMOVE(i, entry); 686 if_del(i); 687 } 688 } 689 690 for (xi = LIST_FIRST(&xa->iface_list); xi != NULL; xi = ni) { 691 ni = LIST_NEXT(xi, entry); 692 if ((i = iface_lookup(a, xi)) == NULL) { 693 log_debug("merge_config: proc %d label space %s adding " 694 "interface %s", ldpd_process, inet_ntoa(a->id), 695 xi->name); 696 LIST_REMOVE(xi, entry); 697 LIST_INSERT_HEAD(&a->iface_list, xi, entry); 698 xi->lspace = a; 699 if (ldpd_process == PROC_LDP_ENGINE) 700 xi->state = IF_STA_NEW; 701 continue; 702 } 703 log_debug("merge_config: proc %d label space %s merging interface %s", 704 ldpd_process, inet_ntoa(a->id), i->name); 705 i->addr = xi->addr; 706 i->dst = xi->dst; 707 i->mask = xi->mask; 708 i->abr_id = xi->abr_id; 709 i->baudrate = xi->baudrate; 710 i->dead_interval = xi->dead_interval; 711 i->mtu = xi->mtu; 712 i->transmit_delay = xi->transmit_delay; 713 i->hello_interval = xi->hello_interval; 714 i->rxmt_interval = xi->rxmt_interval; 715 if (i->metric != xi->metric) 716 dirty = 1; 717 i->metric = xi->metric; 718 i->priority = xi->priority; 719 i->flags = xi->flags; 720 i->type = xi->type; 721 i->media_type = xi->media_type; 722 i->linkstate = xi->linkstate; 723 724 if (i->passive != xi->passive) { 725 if (ldpd_process == PROC_LDP_ENGINE) 726 if_fsm(i, IF_EVT_DOWN); 727 i->passive = xi->passive; 728 if (ldpd_process == PROC_LDP_ENGINE) 729 if_fsm(i, IF_EVT_UP); 730 } 731 } 732 return (dirty); 733 } 734 735 struct iface * 736 iface_lookup(struct lspace *lspace, struct iface *iface) 737 { 738 struct iface *i; 739 740 LIST_FOREACH(i, &lspace->iface_list, entry) 741 if (i->ifindex == iface->ifindex) 742 return (i); 743 return (NULL); 744 } 745 */ 746