1*f1b790a5Sclaudio /* $OpenBSD: ospfd.c,v 1.124 2024/11/21 13:38:14 claudio Exp $ */ 2204df0f8Sclaudio 3204df0f8Sclaudio /* 4204df0f8Sclaudio * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org> 5367f601bSnorby * Copyright (c) 2004 Esben Norby <norby@openbsd.org> 6204df0f8Sclaudio * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org> 7204df0f8Sclaudio * 8204df0f8Sclaudio * Permission to use, copy, modify, and distribute this software for any 9204df0f8Sclaudio * purpose with or without fee is hereby granted, provided that the above 10204df0f8Sclaudio * copyright notice and this permission notice appear in all copies. 11204df0f8Sclaudio * 12204df0f8Sclaudio * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 13204df0f8Sclaudio * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 14204df0f8Sclaudio * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 15204df0f8Sclaudio * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 16204df0f8Sclaudio * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 17204df0f8Sclaudio * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 18204df0f8Sclaudio * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 19204df0f8Sclaudio */ 20204df0f8Sclaudio 21204df0f8Sclaudio #include <sys/types.h> 22204df0f8Sclaudio #include <sys/socket.h> 23204df0f8Sclaudio #include <sys/queue.h> 24204df0f8Sclaudio #include <sys/time.h> 25204df0f8Sclaudio #include <sys/stat.h> 26204df0f8Sclaudio #include <sys/wait.h> 279e6b6024Snorby #include <sys/sysctl.h> 28f2e37bc3Sbenno #include <syslog.h> 29204df0f8Sclaudio 30204df0f8Sclaudio #include <netinet/in.h> 31204df0f8Sclaudio #include <arpa/inet.h> 32ac149fe2Sremi #include <net/if_types.h> 33204df0f8Sclaudio 34204df0f8Sclaudio #include <event.h> 35204df0f8Sclaudio #include <err.h> 36204df0f8Sclaudio #include <errno.h> 37204df0f8Sclaudio #include <pwd.h> 38204df0f8Sclaudio #include <stdio.h> 39204df0f8Sclaudio #include <stdlib.h> 4044cb7d8eSclaudio #include <string.h> 41204df0f8Sclaudio #include <signal.h> 42204df0f8Sclaudio #include <unistd.h> 43204df0f8Sclaudio 44204df0f8Sclaudio #include "ospfd.h" 45204df0f8Sclaudio #include "ospf.h" 46204df0f8Sclaudio #include "ospfe.h" 47204df0f8Sclaudio #include "control.h" 48204df0f8Sclaudio #include "log.h" 49204df0f8Sclaudio #include "rde.h" 50204df0f8Sclaudio 51204df0f8Sclaudio void main_sig_handler(int, short, void *); 52cbb557dbShenning __dead void usage(void); 53a27c0559Srenato __dead void ospfd_shutdown(void); 54204df0f8Sclaudio 55204df0f8Sclaudio void main_dispatch_ospfe(int, short, void *); 56204df0f8Sclaudio void main_dispatch_rde(int, short, void *); 57204df0f8Sclaudio 58f28af201Sclaudio int ospf_reload(void); 59f28af201Sclaudio int ospf_sendboth(enum imsg_type, void *, u_int16_t); 603a0d6b5fSclaudio int merge_interfaces(struct area *, struct area *); 61f28af201Sclaudio struct iface *iface_lookup(struct area *, struct iface *); 62f28af201Sclaudio 63204df0f8Sclaudio int pipe_parent2ospfe[2]; 64204df0f8Sclaudio int pipe_parent2rde[2]; 65204df0f8Sclaudio int pipe_ospfe2rde[2]; 66204df0f8Sclaudio 67d8606ed9Sclaudio enum ospfd_process ospfd_process; 68f28af201Sclaudio struct ospfd_conf *ospfd_conf = NULL; 69d8606ed9Sclaudio static struct imsgev *iev_ospfe; 70d8606ed9Sclaudio static struct imsgev *iev_rde; 71f28af201Sclaudio char *conffile; 72204df0f8Sclaudio 734ce4cce4Shenning pid_t ospfe_pid = 0; 744ce4cce4Shenning pid_t rde_pid = 0; 75204df0f8Sclaudio 76204df0f8Sclaudio void 77204df0f8Sclaudio main_sig_handler(int sig, short event, void *arg) 78204df0f8Sclaudio { 79a27c0559Srenato /* signal handler rules don't apply, libevent decouples for us */ 80204df0f8Sclaudio switch (sig) { 81204df0f8Sclaudio case SIGTERM: 82204df0f8Sclaudio case SIGINT: 83d67317b7Shenning ospfd_shutdown(); 84a27c0559Srenato /* NOTREACHED */ 85204df0f8Sclaudio case SIGHUP: 861035f31cSpyr if (ospf_reload() == -1) 871035f31cSpyr log_warnx("configuration reload failed"); 881035f31cSpyr else 891035f31cSpyr log_debug("configuration reloaded"); 90204df0f8Sclaudio break; 91204df0f8Sclaudio default: 92204df0f8Sclaudio fatalx("unexpected signal"); 93204df0f8Sclaudio /* NOTREACHED */ 94204df0f8Sclaudio } 95204df0f8Sclaudio } 96204df0f8Sclaudio 97cbb557dbShenning __dead void 98204df0f8Sclaudio usage(void) 99204df0f8Sclaudio { 100204df0f8Sclaudio extern char *__progname; 101204df0f8Sclaudio 102d1b94773Sreyk fprintf(stderr, "usage: %s [-cdnv] [-D macro=value]" 103d1b94773Sreyk " [-f file] [-s socket]\n", 10400a91a7aSclaudio __progname); 105204df0f8Sclaudio exit(1); 106204df0f8Sclaudio } 107204df0f8Sclaudio 108204df0f8Sclaudio int 109204df0f8Sclaudio main(int argc, char *argv[]) 110204df0f8Sclaudio { 111a27c0559Srenato struct event ev_sigint, ev_sigterm, ev_sighup; 112f28af201Sclaudio struct area *a; 11304fa3fdbSnorby int ch, opts = 0; 114204df0f8Sclaudio int debug = 0; 1159e6b6024Snorby int ipforwarding; 1169e6b6024Snorby int mib[4]; 1179e6b6024Snorby size_t len; 118ec107b41Sremi char *sockname = NULL; 119617bb465Sremi int control_fd; 120204df0f8Sclaudio 121204df0f8Sclaudio conffile = CONF_FILE; 122204df0f8Sclaudio ospfd_process = PROC_MAIN; 123204df0f8Sclaudio 124f2e37bc3Sbenno log_init(1, LOG_DAEMON); /* log to stderr until daemonized */ 125f2e37bc3Sbenno log_procinit(log_procnames[ospfd_process]); 126e23c639fSpyr 127d1b94773Sreyk while ((ch = getopt(argc, argv, "cdD:f:ns:v")) != -1) { 128204df0f8Sclaudio switch (ch) { 129fba2d3d0Sclaudio case 'c': 130fba2d3d0Sclaudio opts |= OSPFD_OPT_FORCE_DEMOTE; 131fba2d3d0Sclaudio break; 132204df0f8Sclaudio case 'd': 133204df0f8Sclaudio debug = 1; 134204df0f8Sclaudio break; 13500a91a7aSclaudio case 'D': 13600a91a7aSclaudio if (cmdline_symset(optarg) < 0) 13700a91a7aSclaudio log_warnx("could not parse macro definition %s", 13800a91a7aSclaudio optarg); 13900a91a7aSclaudio break; 140204df0f8Sclaudio case 'f': 141204df0f8Sclaudio conffile = optarg; 142204df0f8Sclaudio break; 14304fa3fdbSnorby case 'n': 14404fa3fdbSnorby opts |= OSPFD_OPT_NOACTION; 14504fa3fdbSnorby break; 146d1b94773Sreyk case 's': 147d1b94773Sreyk sockname = optarg; 148d1b94773Sreyk break; 14904fa3fdbSnorby case 'v': 15004fa3fdbSnorby if (opts & OSPFD_OPT_VERBOSE) 15104fa3fdbSnorby opts |= OSPFD_OPT_VERBOSE2; 15204fa3fdbSnorby opts |= OSPFD_OPT_VERBOSE; 1533d3f412bSremi log_setverbose(1); 15404fa3fdbSnorby break; 155204df0f8Sclaudio default: 156204df0f8Sclaudio usage(); 157204df0f8Sclaudio /* NOTREACHED */ 158204df0f8Sclaudio } 159204df0f8Sclaudio } 160204df0f8Sclaudio 161fde55bc4Spyr argc -= optind; 162fde55bc4Spyr argv += optind; 163fde55bc4Spyr if (argc > 0) 164fde55bc4Spyr usage(); 165fde55bc4Spyr 1669e6b6024Snorby mib[0] = CTL_NET; 1679e6b6024Snorby mib[1] = PF_INET; 1689e6b6024Snorby mib[2] = IPPROTO_IP; 1699e6b6024Snorby mib[3] = IPCTL_FORWARDING; 1709e6b6024Snorby len = sizeof(ipforwarding); 1719e6b6024Snorby if (sysctl(mib, 4, &ipforwarding, &len, NULL, 0) == -1) 1729e6b6024Snorby err(1, "sysctl"); 1739e6b6024Snorby 1741891964aSclaudio if (ipforwarding != 1) { 1751891964aSclaudio log_warnx("WARNING: IP forwarding NOT enabled, " 1761891964aSclaudio "running as stub router"); 1771891964aSclaudio opts |= OSPFD_OPT_STUB_ROUTER; 1781891964aSclaudio } 1791891964aSclaudio 180e9fa2173Sclaudio /* fetch interfaces early */ 181e9fa2173Sclaudio kif_init(); 182e9fa2173Sclaudio 183204df0f8Sclaudio /* parse config file */ 184fff8a082Sclaudio if ((ospfd_conf = parse_config(conffile, opts)) == NULL) { 185358269bbSclaudio kif_clear(); 186204df0f8Sclaudio exit(1); 187fff8a082Sclaudio } 188f65e64a0Sdenis if (ospfd_conf->rtr_id.s_addr == 0) 189f65e64a0Sdenis ospfd_conf->rtr_id.s_addr = get_rtr_id(); 190ec107b41Sremi 191ec107b41Sremi if (sockname == NULL) { 192ec107b41Sremi if (asprintf(&sockname, "%s.%d", OSPFD_SOCKET, 193ec107b41Sremi ospfd_conf->rdomain) == -1) 194ec107b41Sremi err(1, "asprintf"); 195ec107b41Sremi } 196ec107b41Sremi 197d1b94773Sreyk ospfd_conf->csock = sockname; 198204df0f8Sclaudio 199f28af201Sclaudio if (ospfd_conf->opts & OSPFD_OPT_NOACTION) { 200f28af201Sclaudio if (ospfd_conf->opts & OSPFD_OPT_VERBOSE) 201f28af201Sclaudio print_config(ospfd_conf); 20204fa3fdbSnorby else 20304fa3fdbSnorby fprintf(stderr, "configuration OK\n"); 204358269bbSclaudio kif_clear(); 20504fa3fdbSnorby exit(0); 20604fa3fdbSnorby } 20704fa3fdbSnorby 208a139c072Sdavid /* check for root privileges */ 209204df0f8Sclaudio if (geteuid()) 210204df0f8Sclaudio errx(1, "need root privileges"); 211204df0f8Sclaudio 212204df0f8Sclaudio /* check for ospfd user */ 213204df0f8Sclaudio if (getpwnam(OSPFD_USER) == NULL) 214204df0f8Sclaudio errx(1, "unknown user %s", OSPFD_USER); 215204df0f8Sclaudio 216f2e37bc3Sbenno log_init(debug, LOG_DAEMON); 217f2e37bc3Sbenno log_setverbose(ospfd_conf->opts & OSPFD_OPT_VERBOSE); 218e23c639fSpyr 219617bb465Sremi if ((control_check(ospfd_conf->csock)) == -1) 2200347b698Sflorian fatalx("ospfd already running"); 221617bb465Sremi 222204df0f8Sclaudio if (!debug) 223204df0f8Sclaudio daemon(1, 0); 224204df0f8Sclaudio 225204df0f8Sclaudio log_info("startup"); 226204df0f8Sclaudio 22758ef7452Sclaudio if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 22858ef7452Sclaudio PF_UNSPEC, pipe_parent2ospfe) == -1) 229204df0f8Sclaudio fatal("socketpair"); 23058ef7452Sclaudio if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 23158ef7452Sclaudio PF_UNSPEC, pipe_parent2rde) == -1) 232204df0f8Sclaudio fatal("socketpair"); 23358ef7452Sclaudio if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 23458ef7452Sclaudio PF_UNSPEC, pipe_ospfe2rde) == -1) 235204df0f8Sclaudio fatal("socketpair"); 236204df0f8Sclaudio 237204df0f8Sclaudio /* start children */ 238f28af201Sclaudio rde_pid = rde(ospfd_conf, pipe_parent2rde, pipe_ospfe2rde, 239f28af201Sclaudio pipe_parent2ospfe); 240f28af201Sclaudio ospfe_pid = ospfe(ospfd_conf, pipe_parent2ospfe, pipe_ospfe2rde, 241204df0f8Sclaudio pipe_parent2rde); 242204df0f8Sclaudio 243d713ab80Sclaudio event_init(); 244d713ab80Sclaudio 245204df0f8Sclaudio /* setup signal handler */ 246204df0f8Sclaudio signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL); 247204df0f8Sclaudio signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL); 248608e9eabSclaudio signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL); 249204df0f8Sclaudio signal_add(&ev_sigint, NULL); 250204df0f8Sclaudio signal_add(&ev_sigterm, NULL); 251204df0f8Sclaudio signal_add(&ev_sighup, NULL); 252da456578Sclaudio signal(SIGPIPE, SIG_IGN); 253204df0f8Sclaudio 254204df0f8Sclaudio /* setup pipes to children */ 255204df0f8Sclaudio close(pipe_parent2ospfe[1]); 256204df0f8Sclaudio close(pipe_parent2rde[1]); 257204df0f8Sclaudio close(pipe_ospfe2rde[0]); 258204df0f8Sclaudio close(pipe_ospfe2rde[1]); 259204df0f8Sclaudio 2607b4c0c10Seric if ((iev_ospfe = malloc(sizeof(struct imsgev))) == NULL || 2617b4c0c10Seric (iev_rde = malloc(sizeof(struct imsgev))) == NULL) 262204df0f8Sclaudio fatal(NULL); 263*f1b790a5Sclaudio if (imsgbuf_init(&iev_ospfe->ibuf, pipe_parent2ospfe[0]) == -1) 264*f1b790a5Sclaudio fatal(NULL); 265*f1b790a5Sclaudio imsgbuf_allow_fdpass(&iev_ospfe->ibuf); 2667b4c0c10Seric iev_ospfe->handler = main_dispatch_ospfe; 267*f1b790a5Sclaudio if (imsgbuf_init(&iev_rde->ibuf, pipe_parent2rde[0]) == -1) 268*f1b790a5Sclaudio fatal(NULL); 2697b4c0c10Seric iev_rde->handler = main_dispatch_rde; 270204df0f8Sclaudio 271204df0f8Sclaudio /* setup event handler */ 2727b4c0c10Seric iev_ospfe->events = EV_READ; 2737b4c0c10Seric event_set(&iev_ospfe->ev, iev_ospfe->ibuf.fd, iev_ospfe->events, 2747b4c0c10Seric iev_ospfe->handler, iev_ospfe); 2757b4c0c10Seric event_add(&iev_ospfe->ev, NULL); 276204df0f8Sclaudio 2777b4c0c10Seric iev_rde->events = EV_READ; 2787b4c0c10Seric event_set(&iev_rde->ev, iev_rde->ibuf.fd, iev_rde->events, 2797b4c0c10Seric iev_rde->handler, iev_rde); 2807b4c0c10Seric event_add(&iev_rde->ev, NULL); 281204df0f8Sclaudio 282617bb465Sremi if ((control_fd = control_init(ospfd_conf->csock)) == -1) 283617bb465Sremi fatalx("control socket setup failed"); 284617bb465Sremi main_imsg_compose_ospfe_fd(IMSG_CONTROLFD, 0, control_fd); 285617bb465Sremi 286bb8a822fSremi if (unveil("/", "r") == -1) 287025f8c0aSderaadt fatal("unveil /"); 288bb8a822fSremi if (unveil(NULL, NULL) == -1) 289bb8a822fSremi fatal("unveil"); 290bb8a822fSremi 291e4caa3d9Sclaudio if (kr_init(!(ospfd_conf->flags & OSPFD_FLAG_NO_FIB_UPDATE), 2924c260f66Sremi ospfd_conf->rdomain, ospfd_conf->redist_label_or_prefix, 2934c260f66Sremi ospfd_conf->fib_priority) == -1) 2949c2db8ffSclaudio fatalx("kr_init failed"); 295204df0f8Sclaudio 2964bbf72b3Skrw /* remove unneeded stuff from config */ 297f28af201Sclaudio while ((a = LIST_FIRST(&ospfd_conf->area_list)) != NULL) { 298f28af201Sclaudio LIST_REMOVE(a, entry); 299f28af201Sclaudio area_del(a); 300f28af201Sclaudio } 301f28af201Sclaudio 302204df0f8Sclaudio event_dispatch(); 303204df0f8Sclaudio 304204df0f8Sclaudio ospfd_shutdown(); 305204df0f8Sclaudio /* NOTREACHED */ 306204df0f8Sclaudio return (0); 307204df0f8Sclaudio } 308204df0f8Sclaudio 309a27c0559Srenato __dead void 310204df0f8Sclaudio ospfd_shutdown(void) 311204df0f8Sclaudio { 312204df0f8Sclaudio pid_t pid; 313a27c0559Srenato int status; 31472f25908Sclaudio struct redistribute *r; 315204df0f8Sclaudio 316a27c0559Srenato /* close pipes */ 3179cbf9e90Sclaudio imsgbuf_clear(&iev_ospfe->ibuf); 318a27c0559Srenato close(iev_ospfe->ibuf.fd); 3199cbf9e90Sclaudio imsgbuf_clear(&iev_rde->ibuf); 320a27c0559Srenato close(iev_rde->ibuf.fd); 321204df0f8Sclaudio 322faef135eSremi control_cleanup(); 32372f25908Sclaudio while ((r = SIMPLEQ_FIRST(&ospfd_conf->redist_list)) != NULL) { 32472f25908Sclaudio SIMPLEQ_REMOVE_HEAD(&ospfd_conf->redist_list, entry); 32572f25908Sclaudio free(r); 32672f25908Sclaudio } 327204df0f8Sclaudio kr_shutdown(); 328fba2d3d0Sclaudio carp_demote_shutdown(); 329204df0f8Sclaudio 330a27c0559Srenato log_debug("waiting for children to terminate"); 331204df0f8Sclaudio do { 332a27c0559Srenato pid = wait(&status); 333a27c0559Srenato if (pid == -1) { 334a27c0559Srenato if (errno != EINTR && errno != ECHILD) 335204df0f8Sclaudio fatal("wait"); 336a27c0559Srenato } else if (WIFSIGNALED(status)) 337a27c0559Srenato log_warnx("%s terminated; signal %d", 338a27c0559Srenato (pid == rde_pid) ? "route decision engine" : 339a27c0559Srenato "ospf engine", WTERMSIG(status)); 340204df0f8Sclaudio } while (pid != -1 || (pid == -1 && errno == EINTR)); 341204df0f8Sclaudio 3427b4c0c10Seric free(iev_ospfe); 3437b4c0c10Seric free(iev_rde); 344f28af201Sclaudio free(ospfd_conf); 345204df0f8Sclaudio 346204df0f8Sclaudio log_info("terminating"); 347204df0f8Sclaudio exit(0); 348204df0f8Sclaudio } 349204df0f8Sclaudio 350204df0f8Sclaudio /* imsg handling */ 351204df0f8Sclaudio void 352204df0f8Sclaudio main_dispatch_ospfe(int fd, short event, void *bula) 353204df0f8Sclaudio { 3547b4c0c10Seric struct imsgev *iev = bula; 3557b4c0c10Seric struct imsgbuf *ibuf; 356204df0f8Sclaudio struct imsg imsg; 357fba2d3d0Sclaudio struct demote_msg dmsg; 35826e8c965Sclaudio ssize_t n; 359636d06c3Sclaudio int shut = 0, verbose; 360204df0f8Sclaudio 3617b4c0c10Seric ibuf = &iev->ibuf; 3627b4c0c10Seric 363b202c6d3Sclaudio if (event & EV_READ) { 364668e5ba9Sclaudio if ((n = imsgbuf_read(ibuf)) == -1) 365dd7efffeSclaudio fatal("imsgbuf_read error"); 366204df0f8Sclaudio if (n == 0) /* connection closed */ 367410c7411Sclaudio shut = 1; 368b202c6d3Sclaudio } 369b202c6d3Sclaudio if (event & EV_WRITE) { 370dd7efffeSclaudio if (imsgbuf_write(ibuf) == -1) { 371c1aa9554Sclaudio if (errno == EPIPE) /* connection closed */ 3721203692fSkrw shut = 1; 373c1aa9554Sclaudio else 374dd7efffeSclaudio fatal("imsgbuf_write"); 375c1aa9554Sclaudio } 376204df0f8Sclaudio } 377204df0f8Sclaudio 378204df0f8Sclaudio for (;;) { 379204df0f8Sclaudio if ((n = imsg_get(ibuf, &imsg)) == -1) 380204df0f8Sclaudio fatal("imsg_get"); 381204df0f8Sclaudio 382204df0f8Sclaudio if (n == 0) 383204df0f8Sclaudio break; 384204df0f8Sclaudio 385204df0f8Sclaudio switch (imsg.hdr.type) { 386204df0f8Sclaudio case IMSG_CTL_RELOAD: 387f28af201Sclaudio if (ospf_reload() == -1) 388f28af201Sclaudio log_warnx("configuration reload failed"); 389f28af201Sclaudio else 390f28af201Sclaudio log_debug("configuration reloaded"); 391204df0f8Sclaudio break; 392204df0f8Sclaudio case IMSG_CTL_FIB_COUPLE: 393204df0f8Sclaudio kr_fib_couple(); 394204df0f8Sclaudio break; 395204df0f8Sclaudio case IMSG_CTL_FIB_DECOUPLE: 396204df0f8Sclaudio kr_fib_decouple(); 397204df0f8Sclaudio break; 398119f0f1dSdlg case IMSG_CTL_FIB_RELOAD: 399119f0f1dSdlg kr_fib_reload(); 400119f0f1dSdlg break; 401b6b3a59aSclaudio case IMSG_CTL_KROUTE: 402b6b3a59aSclaudio case IMSG_CTL_KROUTE_ADDR: 403b6b3a59aSclaudio kr_show_route(&imsg); 404b6b3a59aSclaudio break; 405b6b3a59aSclaudio case IMSG_CTL_IFINFO: 40670955e50Sclaudio if (imsg.hdr.len == IMSG_HEADER_SIZE) 40770955e50Sclaudio kr_ifinfo(NULL, imsg.hdr.pid); 40870955e50Sclaudio else if (imsg.hdr.len == IMSG_HEADER_SIZE + IFNAMSIZ) 40970955e50Sclaudio kr_ifinfo(imsg.data, imsg.hdr.pid); 410b6b3a59aSclaudio else 41170955e50Sclaudio log_warnx("IFINFO request with wrong len"); 412b6b3a59aSclaudio break; 413fba2d3d0Sclaudio case IMSG_DEMOTE: 414fba2d3d0Sclaudio if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(dmsg)) 415fba2d3d0Sclaudio fatalx("invalid size of OE request"); 416fba2d3d0Sclaudio memcpy(&dmsg, imsg.data, sizeof(dmsg)); 417fba2d3d0Sclaudio carp_demote_set(dmsg.demote_group, dmsg.level); 418fba2d3d0Sclaudio break; 419636d06c3Sclaudio case IMSG_CTL_LOG_VERBOSE: 420636d06c3Sclaudio /* already checked by ospfe */ 421636d06c3Sclaudio memcpy(&verbose, imsg.data, sizeof(verbose)); 422f2e37bc3Sbenno log_setverbose(verbose); 423636d06c3Sclaudio break; 424204df0f8Sclaudio default: 425204df0f8Sclaudio log_debug("main_dispatch_ospfe: error handling imsg %d", 426204df0f8Sclaudio imsg.hdr.type); 427204df0f8Sclaudio break; 428204df0f8Sclaudio } 429204df0f8Sclaudio imsg_free(&imsg); 430204df0f8Sclaudio } 431410c7411Sclaudio if (!shut) 4327b4c0c10Seric imsg_event_add(iev); 433410c7411Sclaudio else { 434410c7411Sclaudio /* this pipe is dead, so remove the event handler */ 4357b4c0c10Seric event_del(&iev->ev); 436410c7411Sclaudio event_loopexit(NULL); 437410c7411Sclaudio } 438204df0f8Sclaudio } 439204df0f8Sclaudio 440204df0f8Sclaudio void 441204df0f8Sclaudio main_dispatch_rde(int fd, short event, void *bula) 442204df0f8Sclaudio { 4437b4c0c10Seric struct imsgev *iev = bula; 4447b4c0c10Seric struct imsgbuf *ibuf; 445204df0f8Sclaudio struct imsg imsg; 44626e8c965Sclaudio ssize_t n; 447d5218eb1Sclaudio int count, shut = 0; 448204df0f8Sclaudio 4497b4c0c10Seric ibuf = &iev->ibuf; 4507b4c0c10Seric 451b202c6d3Sclaudio if (event & EV_READ) { 452668e5ba9Sclaudio if ((n = imsgbuf_read(ibuf)) == -1) 453dd7efffeSclaudio fatal("imsgbuf_read error"); 454204df0f8Sclaudio if (n == 0) /* connection closed */ 455410c7411Sclaudio shut = 1; 456b202c6d3Sclaudio } 457b202c6d3Sclaudio if (event & EV_WRITE) { 458dd7efffeSclaudio if (imsgbuf_write(ibuf) == -1) { 459c1aa9554Sclaudio if (errno == EPIPE) /* connection closed */ 4601203692fSkrw shut = 1; 461c1aa9554Sclaudio else 462dd7efffeSclaudio fatal("imsgbuf_write"); 463c1aa9554Sclaudio } 464204df0f8Sclaudio } 465204df0f8Sclaudio 466204df0f8Sclaudio for (;;) { 467204df0f8Sclaudio if ((n = imsg_get(ibuf, &imsg)) == -1) 468204df0f8Sclaudio fatal("imsg_get"); 469204df0f8Sclaudio 470204df0f8Sclaudio if (n == 0) 471204df0f8Sclaudio break; 472204df0f8Sclaudio 473204df0f8Sclaudio switch (imsg.hdr.type) { 4743ada9d8fSnorby case IMSG_KROUTE_CHANGE: 475d5218eb1Sclaudio count = (imsg.hdr.len - IMSG_HEADER_SIZE) / 476d5218eb1Sclaudio sizeof(struct kroute); 477d5218eb1Sclaudio if (kr_change(imsg.data, count)) 478eb1522a1Snorby log_warn("main_dispatch_rde: error changing " 479eb1522a1Snorby "route"); 480eb1522a1Snorby break; 481eb1522a1Snorby case IMSG_KROUTE_DELETE: 482eb1522a1Snorby if (kr_delete(imsg.data)) 483eb1522a1Snorby log_warn("main_dispatch_rde: error deleting " 484eb1522a1Snorby "route"); 4853ada9d8fSnorby break; 486204df0f8Sclaudio default: 487204df0f8Sclaudio log_debug("main_dispatch_rde: error handling imsg %d", 488204df0f8Sclaudio imsg.hdr.type); 489204df0f8Sclaudio break; 490204df0f8Sclaudio } 491204df0f8Sclaudio imsg_free(&imsg); 492204df0f8Sclaudio } 493410c7411Sclaudio if (!shut) 4947b4c0c10Seric imsg_event_add(iev); 495410c7411Sclaudio else { 496410c7411Sclaudio /* this pipe is dead, so remove the event handler */ 4977b4c0c10Seric event_del(&iev->ev); 498410c7411Sclaudio event_loopexit(NULL); 499410c7411Sclaudio } 500204df0f8Sclaudio } 501204df0f8Sclaudio 502204df0f8Sclaudio void 503204df0f8Sclaudio main_imsg_compose_ospfe(int type, pid_t pid, void *data, u_int16_t datalen) 504204df0f8Sclaudio { 5053a9b53d2Sbenno if (iev_ospfe) 5067b4c0c10Seric imsg_compose_event(iev_ospfe, type, 0, pid, -1, data, datalen); 507204df0f8Sclaudio } 508204df0f8Sclaudio 509204df0f8Sclaudio void 510617bb465Sremi main_imsg_compose_ospfe_fd(int type, pid_t pid, int fd) 511617bb465Sremi { 512617bb465Sremi if (iev_ospfe) 513617bb465Sremi imsg_compose_event(iev_ospfe, type, 0, pid, fd, NULL, 0); 514617bb465Sremi } 515617bb465Sremi 516617bb465Sremi void 517204df0f8Sclaudio main_imsg_compose_rde(int type, pid_t pid, void *data, u_int16_t datalen) 518204df0f8Sclaudio { 5193a9b53d2Sbenno if (iev_rde) 5207b4c0c10Seric imsg_compose_event(iev_rde, type, 0, pid, -1, data, datalen); 521204df0f8Sclaudio } 522204df0f8Sclaudio 523204df0f8Sclaudio void 5247b4c0c10Seric imsg_event_add(struct imsgev *iev) 525204df0f8Sclaudio { 5267b4c0c10Seric iev->events = EV_READ; 52731be28caSclaudio if (imsgbuf_queuelen(&iev->ibuf) > 0) 5287b4c0c10Seric iev->events |= EV_WRITE; 529204df0f8Sclaudio 5307b4c0c10Seric event_del(&iev->ev); 5317b4c0c10Seric event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler, iev); 5327b4c0c10Seric event_add(&iev->ev, NULL); 533204df0f8Sclaudio } 53444cb7d8eSclaudio 53544cb7d8eSclaudio int 5367b4c0c10Seric imsg_compose_event(struct imsgev *iev, u_int16_t type, u_int32_t peerid, 537d13e54e1Spyr pid_t pid, int fd, void *data, u_int16_t datalen) 538d13e54e1Spyr { 539d13e54e1Spyr int ret; 540d13e54e1Spyr 5417b4c0c10Seric if ((ret = imsg_compose(&iev->ibuf, type, peerid, 542d13e54e1Spyr pid, fd, data, datalen)) != -1) 5437b4c0c10Seric imsg_event_add(iev); 544d13e54e1Spyr return (ret); 545d13e54e1Spyr } 546d13e54e1Spyr 547d13e54e1Spyr int 548f373ed5aSclaudio ospf_redistribute(struct kroute *kr, u_int32_t *metric) 54944cb7d8eSclaudio { 550ac149fe2Sremi struct in_addr addr; 551ac149fe2Sremi struct kif *kif; 552bbb232d2Sclaudio struct redistribute *r; 55302ba2abaSjca int is_default, depend_ok; 554ac149fe2Sremi 555ac149fe2Sremi bzero(&addr, sizeof(addr)); 556bbb232d2Sclaudio 55739c227bcSmichele /* only allow 0.0.0.0/0 via REDIST_DEFAULT */ 55802ba2abaSjca is_default = (kr->prefix.s_addr == INADDR_ANY && kr->prefixlen == 0); 55944cb7d8eSclaudio 560f28af201Sclaudio SIMPLEQ_FOREACH(r, &ospfd_conf->redist_list, entry) { 561ac149fe2Sremi if (r->dependon[0] != '\0') { 562ac149fe2Sremi if ((kif = kif_findname(r->dependon, addr, NULL))) 563ac149fe2Sremi depend_ok = ifstate_is_up(kif); 564ac149fe2Sremi else 565ac149fe2Sremi depend_ok = 0; 566ac149fe2Sremi } else 567ac149fe2Sremi depend_ok = 1; 568ac149fe2Sremi 569619421e7Sclaudio switch (r->type & ~REDIST_NO) { 570bbb232d2Sclaudio case REDIST_LABEL: 571921688e4Sclaudio if (kr->rtlabel == r->label) { 57217e34b32Sremi *metric = depend_ok ? r->metric : 57317e34b32Sremi r->metric | MAX_METRIC; 574619421e7Sclaudio return (r->type & REDIST_NO ? 0 : 1); 575921688e4Sclaudio } 576bbb232d2Sclaudio break; 577bbb232d2Sclaudio case REDIST_STATIC: 578bbb232d2Sclaudio /* 579bbb232d2Sclaudio * Dynamic routes are not redistributable. Placed here 580bbb232d2Sclaudio * so that link local addresses can be redistributed 581bbb232d2Sclaudio * via a rtlabel. 582bbb232d2Sclaudio */ 58339c227bcSmichele if (is_default) 58439c227bcSmichele continue; 585bbb232d2Sclaudio if (kr->flags & F_DYNAMIC) 586bbb232d2Sclaudio continue; 587f373ed5aSclaudio if (kr->flags & F_STATIC) { 58817e34b32Sremi *metric = depend_ok ? r->metric : 58917e34b32Sremi r->metric | MAX_METRIC; 590619421e7Sclaudio return (r->type & REDIST_NO ? 0 : 1); 591f373ed5aSclaudio } 592275b428fSclaudio break; 593bbb232d2Sclaudio case REDIST_CONNECTED: 59439c227bcSmichele if (is_default) 59539c227bcSmichele continue; 596bbb232d2Sclaudio if (kr->flags & F_DYNAMIC) 597bbb232d2Sclaudio continue; 598f373ed5aSclaudio if (kr->flags & F_CONNECTED) { 59917e34b32Sremi *metric = depend_ok ? r->metric : 60017e34b32Sremi r->metric | MAX_METRIC; 601619421e7Sclaudio return (r->type & REDIST_NO ? 0 : 1); 602f373ed5aSclaudio } 603275b428fSclaudio break; 604bbb232d2Sclaudio case REDIST_ADDR: 605619421e7Sclaudio if (kr->flags & F_DYNAMIC) 606619421e7Sclaudio continue; 6077644670cSmichele 6087644670cSmichele if (r->addr.s_addr == INADDR_ANY && 6097644670cSmichele r->mask.s_addr == INADDR_ANY) { 610f1191fa4Smpf if (is_default) { 611ac149fe2Sremi *metric = depend_ok ? r->metric : 61217e34b32Sremi r->metric | MAX_METRIC; 6137644670cSmichele return (r->type & REDIST_NO ? 0 : 1); 614f1191fa4Smpf } else 6157644670cSmichele return (0); 6167644670cSmichele } 6177644670cSmichele 618619421e7Sclaudio if ((kr->prefix.s_addr & r->mask.s_addr) == 619619421e7Sclaudio (r->addr.s_addr & r->mask.s_addr) && 620f373ed5aSclaudio kr->prefixlen >= mask2prefixlen(r->mask.s_addr)) { 62117e34b32Sremi *metric = depend_ok ? r->metric : 62217e34b32Sremi r->metric | MAX_METRIC; 623619421e7Sclaudio return (r->type & REDIST_NO ? 0 : 1); 624f373ed5aSclaudio } 625bbb232d2Sclaudio break; 6266fa28760Sclaudio case REDIST_DEFAULT: 627f1191fa4Smpf if (is_default) { 62817e34b32Sremi *metric = depend_ok ? r->metric : 62917e34b32Sremi r->metric | MAX_METRIC; 6307644670cSmichele return (r->type & REDIST_NO ? 0 : 1); 631f1191fa4Smpf } 6326fa28760Sclaudio break; 633bbb232d2Sclaudio } 634bbb232d2Sclaudio } 63544cb7d8eSclaudio 63644cb7d8eSclaudio return (0); 63744cb7d8eSclaudio } 63844cb7d8eSclaudio 639f28af201Sclaudio int 640f28af201Sclaudio ospf_reload(void) 641f28af201Sclaudio { 642f28af201Sclaudio struct area *area; 643f28af201Sclaudio struct iface *iface; 644f28af201Sclaudio struct ospfd_conf *xconf; 6456fa28760Sclaudio struct redistribute *r; 646f28af201Sclaudio 647f28af201Sclaudio if ((xconf = parse_config(conffile, ospfd_conf->opts)) == NULL) 648f28af201Sclaudio return (-1); 649f28af201Sclaudio 650f65e64a0Sdenis /* No router-id was specified, keep existing value */ 651f65e64a0Sdenis if (xconf->rtr_id.s_addr == 0) 652f65e64a0Sdenis xconf->rtr_id.s_addr = ospfd_conf->rtr_id.s_addr; 653f65e64a0Sdenis 654f2e20b5eSjca /* Abort the reload if rtr_id changed */ 655f2e20b5eSjca if (ospfd_conf->rtr_id.s_addr != xconf->rtr_id.s_addr) { 656ab2e5253Sremi log_warnx("router-id changed: restart required"); 657f2e20b5eSjca return (-1); 658f2e20b5eSjca } 659f2e20b5eSjca 660f28af201Sclaudio /* send config to childs */ 661f28af201Sclaudio if (ospf_sendboth(IMSG_RECONF_CONF, xconf, sizeof(*xconf)) == -1) 662f28af201Sclaudio return (-1); 663f28af201Sclaudio 664f28af201Sclaudio /* send interfaces */ 665f28af201Sclaudio LIST_FOREACH(area, &xconf->area_list, entry) { 666f28af201Sclaudio if (ospf_sendboth(IMSG_RECONF_AREA, area, sizeof(*area)) == -1) 667f28af201Sclaudio return (-1); 668f28af201Sclaudio 6696fa28760Sclaudio SIMPLEQ_FOREACH(r, &area->redist_list, entry) { 6706fa28760Sclaudio main_imsg_compose_rde(IMSG_RECONF_REDIST, 0, r, 6716fa28760Sclaudio sizeof(*r)); 6726fa28760Sclaudio } 673f28af201Sclaudio LIST_FOREACH(iface, &area->iface_list, entry) { 674f28af201Sclaudio if (ospf_sendboth(IMSG_RECONF_IFACE, iface, 675f28af201Sclaudio sizeof(*iface)) == -1) 676f28af201Sclaudio return (-1); 677f28af201Sclaudio if (iface->auth_type == AUTH_CRYPT) 678f28af201Sclaudio if (md_list_send(&iface->auth_md_list, 6797b4c0c10Seric iev_ospfe) == -1) 680f28af201Sclaudio return (-1); 681f28af201Sclaudio } 682f28af201Sclaudio } 683f28af201Sclaudio 684f28af201Sclaudio if (ospf_sendboth(IMSG_RECONF_END, NULL, 0) == -1) 685f28af201Sclaudio return (-1); 686f28af201Sclaudio 687f28af201Sclaudio merge_config(ospfd_conf, xconf); 688f28af201Sclaudio /* update redistribute lists */ 689ad4152efSbenno kr_reload(ospfd_conf->redist_label_or_prefix); 690f28af201Sclaudio return (0); 691f28af201Sclaudio } 692f28af201Sclaudio 693f28af201Sclaudio int 694f28af201Sclaudio ospf_sendboth(enum imsg_type type, void *buf, u_int16_t len) 695f28af201Sclaudio { 6967b4c0c10Seric if (imsg_compose_event(iev_ospfe, type, 0, 0, -1, buf, len) == -1) 697f28af201Sclaudio return (-1); 6987b4c0c10Seric if (imsg_compose_event(iev_rde, type, 0, 0, -1, buf, len) == -1) 699f28af201Sclaudio return (-1); 700f28af201Sclaudio return (0); 701f28af201Sclaudio } 702f28af201Sclaudio 703f28af201Sclaudio void 704f28af201Sclaudio merge_config(struct ospfd_conf *conf, struct ospfd_conf *xconf) 705f28af201Sclaudio { 706f28af201Sclaudio struct area *a, *xa, *na; 707f28af201Sclaudio struct iface *iface; 708f28af201Sclaudio struct redistribute *r; 7098456656cSclaudio int rchange = 0; 710f28af201Sclaudio 7111891964aSclaudio conf->flags = xconf->flags; 712f28af201Sclaudio conf->spf_delay = xconf->spf_delay; 713f28af201Sclaudio conf->spf_hold_time = xconf->spf_hold_time; 7146fa28760Sclaudio if (SIMPLEQ_EMPTY(&conf->redist_list) != 7156fa28760Sclaudio SIMPLEQ_EMPTY(&xconf->redist_list)) 7168456656cSclaudio rchange = 1; 717f28af201Sclaudio conf->rfc1583compat = xconf->rfc1583compat; 718ad4152efSbenno conf->redist_label_or_prefix = xconf->redist_label_or_prefix; 719f28af201Sclaudio 720f28af201Sclaudio if (ospfd_process == PROC_MAIN) { 721f28af201Sclaudio /* main process does neither use areas nor interfaces */ 722f28af201Sclaudio while ((r = SIMPLEQ_FIRST(&conf->redist_list)) != NULL) { 723f28af201Sclaudio SIMPLEQ_REMOVE_HEAD(&conf->redist_list, entry); 724f28af201Sclaudio free(r); 725f28af201Sclaudio } 726a12804d6Sbket SIMPLEQ_CONCAT(&conf->redist_list, &xconf->redist_list); 7274c260f66Sremi 7284c260f66Sremi /* adjust FIB priority if changed */ 7294c260f66Sremi if (conf->fib_priority != xconf->fib_priority) { 7304c260f66Sremi kr_fib_decouple(); 7314c260f66Sremi kr_fib_update_prio(xconf->fib_priority); 7324c260f66Sremi conf->fib_priority = xconf->fib_priority; 7334c260f66Sremi kr_fib_couple(); 7344c260f66Sremi } 7354c260f66Sremi 736f28af201Sclaudio goto done; 737f28af201Sclaudio } 738f28af201Sclaudio 739f28af201Sclaudio /* merge areas and interfaces */ 740f28af201Sclaudio for (a = LIST_FIRST(&conf->area_list); a != NULL; a = na) { 741f28af201Sclaudio na = LIST_NEXT(a, entry); 742f28af201Sclaudio /* find deleted areas */ 743f28af201Sclaudio if ((xa = area_find(xconf, a->id)) == NULL) { 744f28af201Sclaudio if (ospfd_process == PROC_OSPF_ENGINE) { 745f28af201Sclaudio LIST_FOREACH(iface, &a->iface_list, entry) 746f28af201Sclaudio if_fsm(iface, IF_EVT_DOWN); 747f28af201Sclaudio } 748f28af201Sclaudio LIST_REMOVE(a, entry); 749f28af201Sclaudio area_del(a); 750f28af201Sclaudio } 751f28af201Sclaudio } 752f28af201Sclaudio 753f28af201Sclaudio for (xa = LIST_FIRST(&xconf->area_list); xa != NULL; xa = na) { 754f28af201Sclaudio na = LIST_NEXT(xa, entry); 755f28af201Sclaudio if ((a = area_find(conf, xa->id)) == NULL) { 756f28af201Sclaudio LIST_REMOVE(xa, entry); 757f28af201Sclaudio LIST_INSERT_HEAD(&conf->area_list, xa, entry); 758f28af201Sclaudio if (ospfd_process == PROC_OSPF_ENGINE) { 759f28af201Sclaudio /* start interfaces */ 760fba2d3d0Sclaudio ospfe_demote_area(xa, 0); 761f28af201Sclaudio LIST_FOREACH(iface, &xa->iface_list, entry) { 762f28af201Sclaudio if_init(conf, iface); 763f28af201Sclaudio if (if_fsm(iface, IF_EVT_UP)) { 764f28af201Sclaudio log_debug("error starting " 765f28af201Sclaudio "interface %s", 766f28af201Sclaudio iface->name); 767f28af201Sclaudio } 768f28af201Sclaudio } 769f28af201Sclaudio } 770f28af201Sclaudio /* no need to merge interfaces */ 771f28af201Sclaudio continue; 772f28af201Sclaudio } 773f28af201Sclaudio /* 774f28af201Sclaudio * stub is not yet used but switching between stub and normal 775f28af201Sclaudio * will be another painful job. 776f28af201Sclaudio */ 7776fa28760Sclaudio if (a->stub != xa->stub && ospfd_process == PROC_OSPF_ENGINE) 77898b447a7Sclaudio a->dirty = 1; /* force rtr LSA update */ 7796fa28760Sclaudio if (xa->stub && ospfd_process == PROC_RDE_ENGINE) { 7806fa28760Sclaudio while ((r = SIMPLEQ_FIRST(&a->redist_list)) != NULL) { 7816fa28760Sclaudio SIMPLEQ_REMOVE_HEAD(&a->redist_list, entry); 7826fa28760Sclaudio free(r); 7836fa28760Sclaudio } 7846fa28760Sclaudio 785a12804d6Sbket SIMPLEQ_CONCAT(&a->redist_list, &xa->redist_list); 7866fa28760Sclaudio } 78798b447a7Sclaudio 788f28af201Sclaudio a->stub = xa->stub; 789f28af201Sclaudio a->stub_default_cost = xa->stub_default_cost; 7903a0d6b5fSclaudio if (ospfd_process == PROC_RDE_ENGINE) 791f28af201Sclaudio a->dirty = 1; /* force SPF tree recalculation */ 792f28af201Sclaudio 793f28af201Sclaudio /* merge interfaces */ 7943a0d6b5fSclaudio if (merge_interfaces(a, xa) && 7953a0d6b5fSclaudio ospfd_process == PROC_OSPF_ENGINE) 7963a0d6b5fSclaudio a->dirty = 1; /* force rtr LSA update */ 797f28af201Sclaudio } 798f28af201Sclaudio 799f28af201Sclaudio if (ospfd_process == PROC_OSPF_ENGINE) { 800f28af201Sclaudio LIST_FOREACH(a, &conf->area_list, entry) { 801f28af201Sclaudio LIST_FOREACH(iface, &a->iface_list, entry) { 802f28af201Sclaudio if (iface->state == IF_STA_NEW) { 803f28af201Sclaudio iface->state = IF_STA_DOWN; 804f28af201Sclaudio if_init(conf, iface); 805f28af201Sclaudio if (if_fsm(iface, IF_EVT_UP)) { 806f28af201Sclaudio log_debug("error starting " 807f28af201Sclaudio "interface %s", 808f28af201Sclaudio iface->name); 809f28af201Sclaudio } 810f28af201Sclaudio } 811f28af201Sclaudio } 8128456656cSclaudio if (a->dirty || rchange) { 8133a0d6b5fSclaudio a->dirty = 0; 8143a0d6b5fSclaudio orig_rtr_lsa(a); 8153a0d6b5fSclaudio } 816f28af201Sclaudio } 817f28af201Sclaudio } 8186fa28760Sclaudio if (ospfd_process == PROC_RDE_ENGINE) { 8196fa28760Sclaudio LIST_FOREACH(a, &conf->area_list, entry) { 8206fa28760Sclaudio if (a->dirty) { 8216fa28760Sclaudio start_spf_timer(); 8226fa28760Sclaudio break; 8236fa28760Sclaudio } 8246fa28760Sclaudio } 8256fa28760Sclaudio } 826f28af201Sclaudio 827f28af201Sclaudio done: 828f28af201Sclaudio while ((a = LIST_FIRST(&xconf->area_list)) != NULL) { 829f28af201Sclaudio LIST_REMOVE(a, entry); 830f28af201Sclaudio area_del(a); 831f28af201Sclaudio } 832f28af201Sclaudio free(xconf); 833f28af201Sclaudio } 834f28af201Sclaudio 8353a0d6b5fSclaudio int 836f28af201Sclaudio merge_interfaces(struct area *a, struct area *xa) 837f28af201Sclaudio { 838f28af201Sclaudio struct iface *i, *xi, *ni; 8393a0d6b5fSclaudio int dirty = 0; 840f28af201Sclaudio 841f28af201Sclaudio /* problems: 842f28af201Sclaudio * - new interfaces (easy) 8431eaf9454Sremi * - deleted interfaces 844f28af201Sclaudio * - changing passive (painful?) 845f28af201Sclaudio */ 846f28af201Sclaudio for (i = LIST_FIRST(&a->iface_list); i != NULL; i = ni) { 847f28af201Sclaudio ni = LIST_NEXT(i, entry); 848f28af201Sclaudio if (iface_lookup(xa, i) == NULL) { 849644f0a52Smichele log_debug("merge_interfaces: proc %d area %s removing " 85072c35befSnorby "interface %s", ospfd_process, inet_ntoa(a->id), 85172c35befSnorby i->name); 852f28af201Sclaudio if (ospfd_process == PROC_OSPF_ENGINE) 853f28af201Sclaudio if_fsm(i, IF_EVT_DOWN); 854d9d28784Sclaudio else if (ospfd_process == PROC_RDE_ENGINE) 855d9d28784Sclaudio rde_nbr_iface_del(i); 856f28af201Sclaudio LIST_REMOVE(i, entry); 857f28af201Sclaudio if_del(i); 8581eaf9454Sremi dirty = 1; /* force rtr LSA update */ 859f28af201Sclaudio } 860f28af201Sclaudio } 861f28af201Sclaudio 862f28af201Sclaudio for (xi = LIST_FIRST(&xa->iface_list); xi != NULL; xi = ni) { 863f28af201Sclaudio ni = LIST_NEXT(xi, entry); 864f28af201Sclaudio if ((i = iface_lookup(a, xi)) == NULL) { 865f28af201Sclaudio /* new interface but delay initialisation */ 866644f0a52Smichele log_debug("merge_interfaces: proc %d area %s adding " 86772c35befSnorby "interface %s", ospfd_process, inet_ntoa(a->id), 86872c35befSnorby xi->name); 869f28af201Sclaudio LIST_REMOVE(xi, entry); 870f28af201Sclaudio LIST_INSERT_HEAD(&a->iface_list, xi, entry); 871f28af201Sclaudio xi->area = a; 872aa018143Sclaudio if (ospfd_process == PROC_OSPF_ENGINE) 873f28af201Sclaudio xi->state = IF_STA_NEW; 874f28af201Sclaudio continue; 875f28af201Sclaudio } 876644f0a52Smichele log_debug("merge_interfaces: proc %d area %s merging " 877644f0a52Smichele "interface %s", ospfd_process, inet_ntoa(a->id), i->name); 878f28af201Sclaudio i->dst = xi->dst; 879f28af201Sclaudio i->abr_id = xi->abr_id; 880f28af201Sclaudio i->baudrate = xi->baudrate; 881f28af201Sclaudio i->dead_interval = xi->dead_interval; 882f28af201Sclaudio i->mtu = xi->mtu; 883f28af201Sclaudio i->transmit_delay = xi->transmit_delay; 884f28af201Sclaudio i->hello_interval = xi->hello_interval; 885f28af201Sclaudio i->rxmt_interval = xi->rxmt_interval; 8863a0d6b5fSclaudio if (i->metric != xi->metric) 8873a0d6b5fSclaudio dirty = 1; 888f28af201Sclaudio i->metric = xi->metric; 889f28af201Sclaudio i->priority = xi->priority; 890783ec83fSclaudio if (i->self) 891783ec83fSclaudio i->self->priority = i->priority; 892f28af201Sclaudio i->flags = xi->flags; /* needed? */ 89318ffdd94Sstsp i->if_type = xi->if_type; /* needed? */ 894f28af201Sclaudio i->linkstate = xi->linkstate; /* needed? */ 895f28af201Sclaudio 896f28af201Sclaudio i->auth_type = xi->auth_type; 897a36fe386Sclaudio strncpy(i->auth_key, xi->auth_key, MAX_SIMPLE_AUTH_LEN); 898f28af201Sclaudio md_list_clr(&i->auth_md_list); 899f28af201Sclaudio md_list_copy(&i->auth_md_list, &xi->auth_md_list); 900f28af201Sclaudio 901a431dab5Sremi strlcpy(i->dependon, xi->dependon, 902a431dab5Sremi sizeof(i->dependon)); 903a431dab5Sremi i->depend_ok = xi->depend_ok; 904a431dab5Sremi 905f28af201Sclaudio if (i->passive != xi->passive) { 906f28af201Sclaudio /* need to restart interface to cope with this change */ 907f28af201Sclaudio if (ospfd_process == PROC_OSPF_ENGINE) 908f28af201Sclaudio if_fsm(i, IF_EVT_DOWN); 909f28af201Sclaudio i->passive = xi->passive; 910f28af201Sclaudio if (ospfd_process == PROC_OSPF_ENGINE) 911f28af201Sclaudio if_fsm(i, IF_EVT_UP); 912f28af201Sclaudio } 913ac149fe2Sremi 91409e8f780Sremi if (i->type != xi->type) { 915ef209401Sremi /* restart interface to enable or disable DR election */ 916ef209401Sremi if (ospfd_process == PROC_OSPF_ENGINE) 917ef209401Sremi if_fsm(i, IF_EVT_DOWN); 91809e8f780Sremi i->type = xi->type; 919ef209401Sremi if (ospfd_process == PROC_OSPF_ENGINE) 920ef209401Sremi if_fsm(i, IF_EVT_UP); 921ef209401Sremi } 922f28af201Sclaudio } 9233a0d6b5fSclaudio return (dirty); 924f28af201Sclaudio } 925f28af201Sclaudio 926f28af201Sclaudio struct iface * 927f28af201Sclaudio iface_lookup(struct area *area, struct iface *iface) 928f28af201Sclaudio { 929f28af201Sclaudio struct iface *i; 930f28af201Sclaudio 931f28af201Sclaudio LIST_FOREACH(i, &area->iface_list, entry) 932783ec83fSclaudio if (i->ifindex == iface->ifindex && 933783ec83fSclaudio i->addr.s_addr == iface->addr.s_addr && 934783ec83fSclaudio i->mask.s_addr == iface->mask.s_addr) 935f28af201Sclaudio return (i); 936f28af201Sclaudio return (NULL); 937f28af201Sclaudio } 938ac149fe2Sremi 939ac149fe2Sremi int 940ac149fe2Sremi ifstate_is_up(struct kif *kif) 941ac149fe2Sremi { 942ac149fe2Sremi if (!(kif->flags & IFF_UP)) 943ac149fe2Sremi return (0); 944ac149fe2Sremi if (kif->if_type == IFT_CARP && 945ac149fe2Sremi kif->link_state == LINK_STATE_UNKNOWN) 946ac149fe2Sremi return (0); 947ac149fe2Sremi return LINK_STATE_IS_UP(kif->link_state); 948ac149fe2Sremi } 949