1 /* $OpenBSD: ospfe.c,v 1.71 2023/12/13 15:34:43 claudio Exp $ */
2
3 /*
4 * Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
5 * Copyright (c) 2004 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 <netinet/in.h>
25 #include <arpa/inet.h>
26 #include <net/if_types.h>
27 #include <stdlib.h>
28 #include <signal.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <pwd.h>
32 #include <unistd.h>
33 #include <event.h>
34 #include <err.h>
35 #include <errno.h>
36 #include <stdio.h>
37
38 #include "ospf6.h"
39 #include "ospf6d.h"
40 #include "ospfe.h"
41 #include "rde.h"
42 #include "control.h"
43 #include "log.h"
44
45 void ospfe_sig_handler(int, short, void *);
46 __dead void ospfe_shutdown(void);
47 void orig_rtr_lsa_all(struct area *);
48 struct iface *find_vlink(struct abr_rtr *);
49
50 struct ospfd_conf *oeconf = NULL, *noeconf;
51 static struct imsgev *iev_main;
52 static struct imsgev *iev_rde;
53 int oe_nofib;
54
55 void
ospfe_sig_handler(int sig,short event,void * bula)56 ospfe_sig_handler(int sig, short event, void *bula)
57 {
58 switch (sig) {
59 case SIGINT:
60 case SIGTERM:
61 ospfe_shutdown();
62 /* NOTREACHED */
63 default:
64 fatalx("unexpected signal");
65 }
66 }
67
68 /* ospf engine */
69 pid_t
ospfe(struct ospfd_conf * xconf,int pipe_parent2ospfe[2],int pipe_ospfe2rde[2],int pipe_parent2rde[2])70 ospfe(struct ospfd_conf *xconf, int pipe_parent2ospfe[2], int pipe_ospfe2rde[2],
71 int pipe_parent2rde[2])
72 {
73 struct area *area;
74 struct iface *iface;
75 struct passwd *pw;
76 struct event ev_sigint, ev_sigterm;
77 pid_t pid;
78
79 switch (pid = fork()) {
80 case -1:
81 fatal("cannot fork");
82 case 0:
83 break;
84 default:
85 return (pid);
86 }
87
88 /* create the raw ip socket */
89 if ((xconf->ospf_socket = socket(AF_INET6,
90 SOCK_RAW | SOCK_CLOEXEC | SOCK_NONBLOCK, IPPROTO_OSPF)) == -1)
91 fatal("error creating raw socket");
92
93 /* set some defaults */
94 if (if_set_mcast_loop(xconf->ospf_socket) == -1)
95 fatal("if_set_mcast_loop");
96 if (if_set_ipv6_checksum(xconf->ospf_socket) == -1)
97 fatal("if_set_ipv6_checksum");
98 if (if_set_ipv6_pktinfo(xconf->ospf_socket, 1) == -1)
99 fatal("if_set_ipv6_pktinfo");
100 if_set_sockbuf(xconf->ospf_socket);
101
102 oeconf = xconf;
103 if (oeconf->flags & OSPFD_FLAG_NO_FIB_UPDATE)
104 oe_nofib = 1;
105
106 if ((pw = getpwnam(OSPF6D_USER)) == NULL)
107 fatal("getpwnam");
108
109 if (chroot(pw->pw_dir) == -1)
110 fatal("chroot");
111 if (chdir("/") == -1)
112 fatal("chdir(\"/\")");
113
114 setproctitle("ospf engine");
115 /*
116 * XXX needed with fork+exec
117 * log_init(debug, LOG_DAEMON);
118 * log_setverbose(verbose);
119 */
120
121 ospfd_process = PROC_OSPF_ENGINE;
122 log_procinit(log_procnames[ospfd_process]);
123
124 if (setgroups(1, &pw->pw_gid) ||
125 setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) ||
126 setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid))
127 fatal("can't drop privileges");
128
129 if (pledge("stdio inet mcast recvfd", NULL) == -1)
130 fatal("pledge");
131
132 event_init();
133 nbr_init(NBR_HASHSIZE);
134 lsa_cache_init(LSA_HASHSIZE);
135
136 /* setup signal handler */
137 signal_set(&ev_sigint, SIGINT, ospfe_sig_handler, NULL);
138 signal_set(&ev_sigterm, SIGTERM, ospfe_sig_handler, NULL);
139 signal_add(&ev_sigint, NULL);
140 signal_add(&ev_sigterm, NULL);
141 signal(SIGPIPE, SIG_IGN);
142 signal(SIGHUP, SIG_IGN);
143
144 /* setup pipes */
145 close(pipe_parent2ospfe[0]);
146 close(pipe_ospfe2rde[1]);
147 close(pipe_parent2rde[0]);
148 close(pipe_parent2rde[1]);
149
150 if ((iev_rde = malloc(sizeof(struct imsgev))) == NULL ||
151 (iev_main = malloc(sizeof(struct imsgev))) == NULL)
152 fatal(NULL);
153 imsg_init(&iev_rde->ibuf, pipe_ospfe2rde[0]);
154 iev_rde->handler = ospfe_dispatch_rde;
155 imsg_init(&iev_main->ibuf, pipe_parent2ospfe[1]);
156 iev_main->handler = ospfe_dispatch_main;
157
158 /* setup event handler */
159 iev_rde->events = EV_READ;
160 event_set(&iev_rde->ev, iev_rde->ibuf.fd, iev_rde->events,
161 iev_rde->handler, iev_rde);
162 event_add(&iev_rde->ev, NULL);
163
164 iev_main->events = EV_READ;
165 event_set(&iev_main->ev, iev_main->ibuf.fd, iev_main->events,
166 iev_main->handler, iev_main);
167 event_add(&iev_main->ev, NULL);
168
169 event_set(&oeconf->ev, oeconf->ospf_socket, EV_READ|EV_PERSIST,
170 recv_packet, oeconf);
171 event_add(&oeconf->ev, NULL);
172
173 /* remove unneeded config stuff */
174 conf_clear_redist_list(&oeconf->redist_list);
175
176 /* start interfaces */
177 LIST_FOREACH(area, &oeconf->area_list, entry) {
178 ospfe_demote_area(area, 0);
179 LIST_FOREACH(iface, &area->iface_list, entry)
180 if_start(xconf, iface);
181 }
182
183 event_dispatch();
184
185 ospfe_shutdown();
186 /* NOTREACHED */
187 return (0);
188 }
189
190 __dead void
ospfe_shutdown(void)191 ospfe_shutdown(void)
192 {
193 struct area *area;
194 struct iface *iface;
195
196 /* close pipes */
197 msgbuf_write(&iev_rde->ibuf.w);
198 msgbuf_clear(&iev_rde->ibuf.w);
199 close(iev_rde->ibuf.fd);
200 msgbuf_write(&iev_main->ibuf.w);
201 msgbuf_clear(&iev_main->ibuf.w);
202 close(iev_main->ibuf.fd);
203
204 /* stop all interfaces and remove all areas */
205 while ((area = LIST_FIRST(&oeconf->area_list)) != NULL) {
206 LIST_FOREACH(iface, &area->iface_list, entry) {
207 if (if_fsm(iface, IF_EVT_DOWN)) {
208 log_debug("error stopping interface %s",
209 iface->name);
210 }
211 }
212 LIST_REMOVE(area, entry);
213 area_del(area);
214 }
215
216 close(oeconf->ospf_socket);
217
218 /* clean up */
219 free(iev_rde);
220 free(iev_main);
221 free(oeconf);
222
223 log_info("ospf engine exiting");
224 _exit(0);
225 }
226
227 /* imesg */
228 int
ospfe_imsg_compose_parent(int type,pid_t pid,void * data,u_int16_t datalen)229 ospfe_imsg_compose_parent(int type, pid_t pid, void *data, u_int16_t datalen)
230 {
231 return (imsg_compose_event(iev_main, type, 0, pid, -1, data, datalen));
232 }
233
234 int
ospfe_imsg_compose_rde(int type,u_int32_t peerid,pid_t pid,void * data,u_int16_t datalen)235 ospfe_imsg_compose_rde(int type, u_int32_t peerid, pid_t pid,
236 void *data, u_int16_t datalen)
237 {
238 return (imsg_compose_event(iev_rde, type, peerid, pid, -1,
239 data, datalen));
240 }
241
242 void
ospfe_dispatch_main(int fd,short event,void * bula)243 ospfe_dispatch_main(int fd, short event, void *bula)
244 {
245 static struct area *narea;
246 struct area *area;
247 struct iface *iface, *ifp, *i;
248 struct ifaddrchange *ifc;
249 struct iface_addr *ia, *nia;
250 struct imsg imsg;
251 struct imsgev *iev = bula;
252 struct imsgbuf *ibuf = &iev->ibuf;
253 int n, stub_changed, shut = 0, isvalid, wasvalid;
254
255 if (event & EV_READ) {
256 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
257 fatal("imsg_read error");
258 if (n == 0) /* connection closed */
259 shut = 1;
260 }
261 if (event & EV_WRITE) {
262 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
263 fatal("msgbuf_write");
264 if (n == 0) /* connection closed */
265 shut = 1;
266 }
267
268 for (;;) {
269 if ((n = imsg_get(ibuf, &imsg)) == -1)
270 fatal("ospfe_dispatch_main: imsg_get error");
271 if (n == 0)
272 break;
273
274 switch (imsg.hdr.type) {
275 case IMSG_IFINFO:
276 if (imsg.hdr.len != IMSG_HEADER_SIZE +
277 sizeof(struct iface))
278 fatalx("IFINFO imsg with wrong len");
279 ifp = imsg.data;
280
281 LIST_FOREACH(area, &oeconf->area_list, entry) {
282 LIST_FOREACH(i, &area->iface_list, entry) {
283 if (strcmp(i->dependon,
284 ifp->name) == 0) {
285 log_warnx("interface %s"
286 " changed state, %s"
287 " depends on it",
288 ifp->name, i->name);
289 i->depend_ok =
290 ifstate_is_up(ifp);
291 if (ifstate_is_up(i))
292 orig_rtr_lsa(i->area);
293 }
294 }
295 }
296
297 if (!(ifp->cflags & F_IFACE_CONFIGURED))
298 break;
299 iface = if_find(ifp->ifindex);
300 if (iface == NULL)
301 fatalx("interface lost in ospfe");
302
303 wasvalid = (iface->flags & IFF_UP) &&
304 LINK_STATE_IS_UP(iface->linkstate);
305
306 if_update(iface, ifp->mtu, ifp->flags, ifp->if_type,
307 ifp->linkstate, ifp->baudrate, ifp->rdomain);
308
309 isvalid = (iface->flags & IFF_UP) &&
310 LINK_STATE_IS_UP(iface->linkstate);
311
312 if (wasvalid == isvalid)
313 break;
314
315 if (isvalid) {
316 if_fsm(iface, IF_EVT_UP);
317 log_warnx("interface %s up", iface->name);
318 } else {
319 if_fsm(iface, IF_EVT_DOWN);
320 log_warnx("interface %s down", iface->name);
321 }
322 break;
323 case IMSG_IFADDRNEW:
324 if (imsg.hdr.len != IMSG_HEADER_SIZE +
325 sizeof(struct ifaddrchange))
326 fatalx("IFADDRNEW imsg with wrong len");
327 ifc = imsg.data;
328
329 iface = if_find(ifc->ifindex);
330 if (iface == NULL)
331 fatalx("IFADDRNEW interface lost in ospfe");
332
333 if ((ia = calloc(1, sizeof(struct iface_addr))) ==
334 NULL)
335 fatal("ospfe_dispatch_main IFADDRNEW");
336 ia->addr = ifc->addr;
337 ia->dstbrd = ifc->dstbrd;
338 ia->prefixlen = ifc->prefixlen;
339
340 TAILQ_INSERT_TAIL(&iface->ifa_list, ia, entry);
341 orig_link_lsa(iface);
342 break;
343 case IMSG_IFADDRDEL:
344 if (imsg.hdr.len != IMSG_HEADER_SIZE +
345 sizeof(struct ifaddrchange))
346 fatalx("IFADDRDEL imsg with wrong len");
347 ifc = imsg.data;
348
349 iface = if_find(ifc->ifindex);
350 if (iface == NULL)
351 fatalx("IFADDRDEL interface lost in ospfe");
352
353 for (ia = TAILQ_FIRST(&iface->ifa_list); ia != NULL;
354 ia = nia) {
355 nia = TAILQ_NEXT(ia, entry);
356
357 if (IN6_ARE_ADDR_EQUAL(&ia->addr,
358 &ifc->addr)) {
359 TAILQ_REMOVE(&iface->ifa_list, ia,
360 entry);
361 free(ia);
362 break;
363 }
364 }
365 orig_link_lsa(iface);
366 break;
367 case IMSG_RECONF_CONF:
368 if ((noeconf = malloc(sizeof(struct ospfd_conf))) ==
369 NULL)
370 fatal(NULL);
371 memcpy(noeconf, imsg.data, sizeof(struct ospfd_conf));
372
373 LIST_INIT(&noeconf->area_list);
374 LIST_INIT(&noeconf->cand_list);
375 break;
376 case IMSG_RECONF_AREA:
377 if ((narea = area_new()) == NULL)
378 fatal(NULL);
379 memcpy(narea, imsg.data, sizeof(struct area));
380
381 LIST_INIT(&narea->iface_list);
382 LIST_INIT(&narea->nbr_list);
383 RB_INIT(&narea->lsa_tree);
384
385 LIST_INSERT_HEAD(&noeconf->area_list, narea, entry);
386 break;
387 case IMSG_RECONF_END:
388 if ((oeconf->flags & OSPFD_FLAG_STUB_ROUTER) !=
389 (noeconf->flags & OSPFD_FLAG_STUB_ROUTER))
390 stub_changed = 1;
391 else
392 stub_changed = 0;
393 merge_config(oeconf, noeconf);
394 noeconf = NULL;
395 if (stub_changed)
396 orig_rtr_lsa_all(NULL);
397 break;
398 case IMSG_CTL_KROUTE:
399 case IMSG_CTL_KROUTE_ADDR:
400 case IMSG_CTL_END:
401 control_imsg_relay(&imsg);
402 break;
403 case IMSG_CONTROLFD:
404 if ((fd = imsg_get_fd(&imsg)) == -1)
405 fatalx("%s: expected to receive imsg control"
406 "fd but didn't receive any", __func__);
407 /* Listen on control socket. */
408 control_listen(fd);
409 if (pledge("stdio inet mcast", NULL) == -1)
410 fatal("pledge");
411 break;
412 default:
413 log_debug("ospfe_dispatch_main: error handling imsg %d",
414 imsg.hdr.type);
415 break;
416 }
417 imsg_free(&imsg);
418 }
419 if (!shut)
420 imsg_event_add(iev);
421 else {
422 /* this pipe is dead, so remove the event handler */
423 event_del(&iev->ev);
424 event_loopexit(NULL);
425 }
426 }
427
428 void
ospfe_dispatch_rde(int fd,short event,void * bula)429 ospfe_dispatch_rde(int fd, short event, void *bula)
430 {
431 struct lsa_hdr lsa_hdr;
432 struct lsa_link lsa_link;
433 struct imsgev *iev = bula;
434 struct imsgbuf *ibuf = &iev->ibuf;
435 struct nbr *nbr;
436 struct lsa_hdr *lhp;
437 struct lsa_ref *ref;
438 struct area *area;
439 struct iface *iface;
440 struct lsa_entry *le;
441 struct imsg imsg;
442 struct abr_rtr ar;
443 int n, noack = 0, shut = 0;
444 u_int16_t l, age;
445
446 if (event & EV_READ) {
447 if ((n = imsg_read(ibuf)) == -1 && errno != EAGAIN)
448 fatal("imsg_read error");
449 if (n == 0) /* connection closed */
450 shut = 1;
451 }
452 if (event & EV_WRITE) {
453 if ((n = msgbuf_write(&ibuf->w)) == -1 && errno != EAGAIN)
454 fatal("msgbuf_write");
455 if (n == 0) /* connection closed */
456 shut = 1;
457 }
458
459 for (;;) {
460 if ((n = imsg_get(ibuf, &imsg)) == -1)
461 fatal("ospfe_dispatch_rde: imsg_get error");
462 if (n == 0)
463 break;
464
465 switch (imsg.hdr.type) {
466 case IMSG_DD:
467 nbr = nbr_find_peerid(imsg.hdr.peerid);
468 if (nbr == NULL)
469 break;
470
471 /* put these on my ls_req_list for retrieval */
472 lhp = lsa_hdr_new();
473 memcpy(lhp, imsg.data, sizeof(*lhp));
474 ls_req_list_add(nbr, lhp);
475 break;
476 case IMSG_DD_END:
477 nbr = nbr_find_peerid(imsg.hdr.peerid);
478 if (nbr == NULL)
479 break;
480
481 nbr->dd_pending--;
482 if (nbr->dd_pending == 0 && nbr->state & NBR_STA_LOAD) {
483 if (ls_req_list_empty(nbr))
484 nbr_fsm(nbr, NBR_EVT_LOAD_DONE);
485 else
486 start_ls_req_tx_timer(nbr);
487 }
488 break;
489 case IMSG_DB_SNAPSHOT:
490 nbr = nbr_find_peerid(imsg.hdr.peerid);
491 if (nbr == NULL)
492 break;
493 if (nbr->state != NBR_STA_SNAP) /* discard */
494 break;
495
496 /* add LSA header to the neighbor db_sum_list */
497 lhp = lsa_hdr_new();
498 memcpy(lhp, imsg.data, sizeof(*lhp));
499 db_sum_list_add(nbr, lhp);
500 break;
501 case IMSG_DB_END:
502 nbr = nbr_find_peerid(imsg.hdr.peerid);
503 if (nbr == NULL)
504 break;
505
506 nbr->dd_snapshot = 0;
507 if (nbr->state != NBR_STA_SNAP)
508 break;
509
510 /* snapshot done, start tx of dd packets */
511 nbr_fsm(nbr, NBR_EVT_SNAP_DONE);
512 break;
513 case IMSG_LS_FLOOD:
514 nbr = nbr_find_peerid(imsg.hdr.peerid);
515 if (nbr == NULL)
516 break;
517
518 l = imsg.hdr.len - IMSG_HEADER_SIZE;
519 if (l < sizeof(lsa_hdr))
520 fatalx("ospfe_dispatch_rde: "
521 "bad imsg size");
522 memcpy(&lsa_hdr, imsg.data, sizeof(lsa_hdr));
523
524 ref = lsa_cache_add(imsg.data, l);
525
526 if (lsa_hdr.type == htons(LSA_TYPE_EXTERNAL)) {
527 /*
528 * flood on all areas but stub areas and
529 * virtual links
530 */
531 LIST_FOREACH(area, &oeconf->area_list, entry) {
532 if (area->stub)
533 continue;
534 LIST_FOREACH(iface, &area->iface_list,
535 entry) {
536 noack += lsa_flood(iface, nbr,
537 &lsa_hdr, imsg.data);
538 }
539 }
540 } else if (lsa_hdr.type == htons(LSA_TYPE_LINK)) {
541 /*
542 * Save link-LSA options of neighbor.
543 * This is needed to originate network-LSA.
544 */
545 if (l - sizeof(lsa_hdr) < sizeof(lsa_link))
546 fatalx("ospfe_dispatch_rde: "
547 "bad imsg link size");
548 memcpy(&lsa_link, (char *)imsg.data +
549 sizeof(lsa_hdr), sizeof(lsa_link));
550 nbr->link_options = lsa_link.opts &
551 htonl(LSA_24_MASK);
552
553 /*
554 * flood on interface only
555 */
556 noack += lsa_flood(nbr->iface, nbr,
557 &lsa_hdr, imsg.data);
558 } else {
559 /*
560 * flood on all area interfaces on
561 * area 0.0.0.0 include also virtual links.
562 */
563 LIST_FOREACH(iface,
564 &nbr->iface->area->iface_list, entry) {
565 noack += lsa_flood(iface, nbr,
566 &lsa_hdr, imsg.data);
567 }
568 /* XXX virtual links */
569 }
570
571 /* remove from ls_req_list */
572 le = ls_req_list_get(nbr, &lsa_hdr);
573 if (!(nbr->state & NBR_STA_FULL) && le != NULL) {
574 ls_req_list_free(nbr, le);
575 /*
576 * XXX no need to ack requested lsa
577 * the problem is that the RFC is very
578 * unclear about this.
579 */
580 noack = 1;
581 }
582
583 if (!noack && nbr->iface != NULL &&
584 nbr->iface->self != nbr) {
585 if (!(nbr->iface->state & IF_STA_BACKUP) ||
586 nbr->iface->dr == nbr) {
587 /* delayed ack */
588 lhp = lsa_hdr_new();
589 memcpy(lhp, &lsa_hdr, sizeof(*lhp));
590 ls_ack_list_add(nbr->iface, lhp);
591 }
592 }
593
594 lsa_cache_put(ref, nbr);
595 break;
596 case IMSG_LS_UPD:
597 case IMSG_LS_SNAP:
598 /*
599 * IMSG_LS_UPD is used in two cases:
600 * 1. as response to ls requests
601 * 2. as response to ls updates where the DB
602 * is newer then the sent LSA
603 * IMSG_LS_SNAP is used in one case:
604 * in EXSTART when the LSA has age MaxAge
605 */
606 l = imsg.hdr.len - IMSG_HEADER_SIZE;
607 if (l < sizeof(lsa_hdr))
608 fatalx("ospfe_dispatch_rde: "
609 "bad imsg size");
610
611 nbr = nbr_find_peerid(imsg.hdr.peerid);
612 if (nbr == NULL)
613 break;
614
615 if (nbr->iface->self == nbr)
616 break;
617
618 if (imsg.hdr.type == IMSG_LS_SNAP &&
619 nbr->state != NBR_STA_SNAP)
620 break;
621
622 memcpy(&age, imsg.data, sizeof(age));
623 ref = lsa_cache_add(imsg.data, l);
624 if (ntohs(age) >= MAX_AGE)
625 /* add to retransmit list */
626 ls_retrans_list_add(nbr, imsg.data, 0, 0);
627 else
628 ls_retrans_list_add(nbr, imsg.data, 0, 1);
629
630 lsa_cache_put(ref, nbr);
631 break;
632 case IMSG_LS_ACK:
633 /*
634 * IMSG_LS_ACK is used in two cases:
635 * 1. LSA was a duplicate
636 * 2. LS age is MaxAge and there is no current
637 * instance in the DB plus no neighbor in state
638 * Exchange or Loading
639 */
640 nbr = nbr_find_peerid(imsg.hdr.peerid);
641 if (nbr == NULL)
642 break;
643
644 if (nbr->iface->self == nbr)
645 break;
646
647 if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(lsa_hdr))
648 fatalx("ospfe_dispatch_rde: bad imsg size");
649 memcpy(&lsa_hdr, imsg.data, sizeof(lsa_hdr));
650
651 /* for case one check for implied acks */
652 if (nbr->iface->state & IF_STA_DROTHER)
653 if (ls_retrans_list_del(nbr->iface->self,
654 &lsa_hdr) == 0)
655 break;
656 if (ls_retrans_list_del(nbr, &lsa_hdr) == 0)
657 break;
658
659 /* send a direct acknowledgement */
660 send_direct_ack(nbr->iface, nbr->addr, imsg.data,
661 imsg.hdr.len - IMSG_HEADER_SIZE);
662
663 break;
664 case IMSG_LS_BADREQ:
665 nbr = nbr_find_peerid(imsg.hdr.peerid);
666 if (nbr == NULL)
667 break;
668
669 if (nbr->iface->self == nbr)
670 fatalx("ospfe_dispatch_rde: "
671 "dummy neighbor got BADREQ");
672
673 nbr_fsm(nbr, NBR_EVT_BAD_LS_REQ);
674 break;
675 case IMSG_ABR_UP:
676 memcpy(&ar, imsg.data, sizeof(ar));
677
678 if ((iface = find_vlink(&ar)) != NULL &&
679 iface->state == IF_STA_DOWN)
680 if (if_fsm(iface, IF_EVT_UP)) {
681 log_debug("error starting interface %s",
682 iface->name);
683 }
684 break;
685 case IMSG_ABR_DOWN:
686 memcpy(&ar, imsg.data, sizeof(ar));
687
688 if ((iface = find_vlink(&ar)) != NULL &&
689 iface->state == IF_STA_POINTTOPOINT)
690 if (if_fsm(iface, IF_EVT_DOWN)) {
691 log_debug("error stopping interface %s",
692 iface->name);
693 }
694 break;
695 case IMSG_CTL_AREA:
696 case IMSG_CTL_IFACE:
697 case IMSG_CTL_END:
698 case IMSG_CTL_SHOW_DATABASE:
699 case IMSG_CTL_SHOW_DB_EXT:
700 case IMSG_CTL_SHOW_DB_LINK:
701 case IMSG_CTL_SHOW_DB_NET:
702 case IMSG_CTL_SHOW_DB_RTR:
703 case IMSG_CTL_SHOW_DB_INTRA:
704 case IMSG_CTL_SHOW_DB_SELF:
705 case IMSG_CTL_SHOW_DB_SUM:
706 case IMSG_CTL_SHOW_DB_ASBR:
707 case IMSG_CTL_SHOW_RIB:
708 case IMSG_CTL_SHOW_SUM:
709 case IMSG_CTL_SHOW_SUM_AREA:
710 control_imsg_relay(&imsg);
711 break;
712 default:
713 log_debug("ospfe_dispatch_rde: error handling imsg %d",
714 imsg.hdr.type);
715 break;
716 }
717 imsg_free(&imsg);
718 }
719 if (!shut)
720 imsg_event_add(iev);
721 else {
722 /* this pipe is dead, so remove the event handler */
723 event_del(&iev->ev);
724 event_loopexit(NULL);
725 }
726 }
727
728 struct iface *
find_vlink(struct abr_rtr * ar)729 find_vlink(struct abr_rtr *ar)
730 {
731 struct area *area;
732 struct iface *iface = NULL;
733
734 LIST_FOREACH(area, &oeconf->area_list, entry)
735 LIST_FOREACH(iface, &area->iface_list, entry)
736 if (iface->abr_id.s_addr == ar->abr_id.s_addr &&
737 iface->type == IF_TYPE_VIRTUALLINK &&
738 iface->area->id.s_addr == ar->area.s_addr) {
739 iface->dst = ar->dst_ip;
740 iface->addr = ar->addr;
741 iface->metric = ar->metric;
742
743 return (iface);
744 }
745
746 return (iface);
747 }
748
749 void
orig_rtr_lsa_all(struct area * area)750 orig_rtr_lsa_all(struct area *area)
751 {
752 struct area *a;
753
754 /*
755 * update all router LSA in all areas except area itself,
756 * as this update is already running.
757 */
758 LIST_FOREACH(a, &oeconf->area_list, entry)
759 if (a != area)
760 orig_rtr_lsa(a);
761 }
762
763 void
orig_rtr_lsa(struct area * area)764 orig_rtr_lsa(struct area *area)
765 {
766 struct lsa_hdr lsa_hdr;
767 struct lsa_rtr lsa_rtr;
768 struct lsa_rtr_link rtr_link;
769 struct iface *iface;
770 struct ibuf *buf;
771 struct nbr *nbr, *self = NULL;
772 u_int32_t flags;
773 u_int16_t chksum;
774 u_int8_t border, virtual = 0;
775
776 log_debug("orig_rtr_lsa: area %s", inet_ntoa(area->id));
777
778 /* XXX IBUF_READ_SIZE */
779 if ((buf = ibuf_dynamic(sizeof(lsa_hdr), IBUF_READ_SIZE)) == NULL)
780 fatal("orig_rtr_lsa");
781
782 /* reserve space for LSA header and LSA Router header */
783 if (ibuf_add_zero(buf, sizeof(lsa_hdr)) == -1)
784 fatal("orig_rtr_lsa: ibuf_add_zero failed");
785
786 if (ibuf_add_zero(buf, sizeof(lsa_rtr)) == -1)
787 fatal("orig_rtr_lsa: ibuf_add_zero failed");
788
789 /* links */
790 LIST_FOREACH(iface, &area->iface_list, entry) {
791 if (self == NULL && iface->self != NULL)
792 self = iface->self;
793
794 bzero(&rtr_link, sizeof(rtr_link));
795
796 switch (iface->type) {
797 case IF_TYPE_POINTOPOINT:
798 LIST_FOREACH(nbr, &iface->nbr_list, entry)
799 if (nbr != iface->self &&
800 nbr->state & NBR_STA_FULL)
801 break;
802 if (nbr && iface->state & IF_STA_POINTTOPOINT) {
803 log_debug("orig_rtr_lsa: point-to-point, "
804 "interface %s", iface->name);
805 rtr_link.type = LINK_TYPE_POINTTOPOINT;
806 if (iface->dependon[0] != '\0' &&
807 iface->depend_ok == 0)
808 rtr_link.metric = MAX_METRIC;
809 else
810 rtr_link.metric = htons(iface->metric);
811 rtr_link.iface_id = htonl(iface->ifindex);
812 rtr_link.nbr_iface_id = htonl(nbr->iface_id);
813 rtr_link.nbr_rtr_id = nbr->id.s_addr;
814 if (ibuf_add(buf, &rtr_link, sizeof(rtr_link)))
815 fatalx("orig_rtr_lsa: ibuf_add failed");
816 }
817 continue;
818 case IF_TYPE_BROADCAST:
819 case IF_TYPE_NBMA:
820 if ((iface->state & IF_STA_MULTI)) {
821 if (iface->dr == iface->self) {
822 LIST_FOREACH(nbr, &iface->nbr_list,
823 entry)
824 if (nbr != iface->self &&
825 nbr->state & NBR_STA_FULL)
826 break;
827 } else
828 nbr = iface->dr;
829
830 if (nbr && nbr->state & NBR_STA_FULL) {
831 log_debug("orig_rtr_lsa: transit net, "
832 "interface %s", iface->name);
833
834 rtr_link.type = LINK_TYPE_TRANSIT_NET;
835 if (iface->dependon[0] != '\0' &&
836 iface->depend_ok == 0)
837 rtr_link.metric = MAX_METRIC;
838 else
839 rtr_link.metric =
840 htons(iface->metric);
841 rtr_link.iface_id = htonl(iface->ifindex);
842 rtr_link.nbr_iface_id = htonl(iface->dr->iface_id);
843 rtr_link.nbr_rtr_id = iface->dr->id.s_addr;
844 if (ibuf_add(buf, &rtr_link,
845 sizeof(rtr_link)))
846 fatalx("orig_rtr_lsa: "
847 "ibuf_add failed");
848 break;
849 }
850 }
851 break;
852 #if 0 /* TODO virtualllink/pointtomulti */
853 case IF_TYPE_VIRTUALLINK:
854 LIST_FOREACH(nbr, &iface->nbr_list, entry) {
855 if (nbr != iface->self &&
856 nbr->state & NBR_STA_FULL)
857 break;
858 }
859 if (nbr) {
860 rtr_link.id = nbr->id.s_addr;
861 //XXX rtr_link.data = iface->addr.s_addr;
862 rtr_link.type = LINK_TYPE_VIRTUAL;
863 /* RFC 3137: stub router support */
864 if (oeconf->flags & OSPFD_FLAG_STUB_ROUTER ||
865 oe_nofib)
866 rtr_link.metric = 0xffff;
867 else
868 rtr_link.metric = htons(iface->metric);
869 virtual = 1;
870 if (ibuf_add(buf, &rtr_link, sizeof(rtr_link)))
871 fatalx("orig_rtr_lsa: ibuf_add failed");
872
873 log_debug("orig_rtr_lsa: virtual link, "
874 "interface %s", iface->name);
875 }
876 continue;
877 case IF_TYPE_POINTOMULTIPOINT:
878 log_debug("orig_rtr_lsa: stub net, "
879 "interface %s", iface->name);
880 //XXX rtr_link.id = iface->addr.s_addr;
881 rtr_link.data = 0xffffffff;
882 rtr_link.type = LINK_TYPE_STUB_NET;
883 rtr_link.metric = htons(iface->metric);
884 if (ibuf_add(buf, &rtr_link, sizeof(rtr_link)))
885 fatalx("orig_rtr_lsa: ibuf_add failed");
886
887 LIST_FOREACH(nbr, &iface->nbr_list, entry) {
888 if (nbr != iface->self &&
889 nbr->state & NBR_STA_FULL) {
890 bzero(&rtr_link, sizeof(rtr_link));
891 log_debug("orig_rtr_lsa: "
892 "point-to-multipoint, interface %s",
893 iface->name);
894 //XXX rtr_link.id = nbr->addr.s_addr;
895 //XXX rtr_link.data = iface->addr.s_addr;
896 rtr_link.type = LINK_TYPE_POINTTOPOINT;
897 /* RFC 3137: stub router support */
898 if (oe_nofib || oeconf->flags &
899 OSPFD_FLAG_STUB_ROUTER)
900 rtr_link.metric = MAX_METRIC;
901 else if (iface->dependon[0] != '\0' &&
902 iface->dependon_ok == 0)
903 rtr_link.metric = MAX_METRIC;
904 else
905 rtr_link.metric =
906 htons(iface->metric);
907 if (ibuf_add(buf, &rtr_link,
908 sizeof(rtr_link)))
909 fatalx("orig_rtr_lsa: "
910 "ibuf_add failed");
911 }
912 }
913 continue;
914 #endif /* TODO virtualllink/pointtomulti */
915 default:
916 fatalx("orig_rtr_lsa: unknown interface type");
917 }
918 }
919
920 /* LSA router header */
921 lsa_rtr.opts = 0;
922 flags = 0;
923
924 /*
925 * Set the E bit as soon as an as-ext lsa may be redistributed, only
926 * setting it in case we redistribute something is not worth the fuss.
927 */
928 if (oeconf->redistribute && !area->stub)
929 flags |= OSPF_RTR_E;
930
931 border = (area_border_router(oeconf) != 0);
932 if (border != oeconf->border) {
933 oeconf->border = border;
934 orig_rtr_lsa_all(area);
935 }
936
937 if (oeconf->border)
938 flags |= OSPF_RTR_B;
939 /* TODO set V flag if a active virtual link ends here and the
940 * area is the transit area for this link. */
941 if (virtual)
942 flags |= OSPF_RTR_V;
943
944 LSA_24_SETLO(lsa_rtr.opts, area_ospf_options(area));
945 LSA_24_SETHI(lsa_rtr.opts, flags);
946 lsa_rtr.opts = htonl(lsa_rtr.opts);
947 if (ibuf_set(buf, sizeof(lsa_hdr), &lsa_rtr, sizeof(lsa_rtr)) == -1)
948 fatal("orig_rtr_lsa: ibuf_set failed");
949
950 /* LSA header */
951 lsa_hdr.age = htons(DEFAULT_AGE);
952 lsa_hdr.type = htons(LSA_TYPE_ROUTER);
953 /* XXX needs to be fixed if multiple router-lsa need to be announced */
954 lsa_hdr.ls_id = 0;
955 lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr;
956 lsa_hdr.seq_num = htonl(INIT_SEQ_NUM);
957 lsa_hdr.len = htons(ibuf_size(buf));
958 lsa_hdr.ls_chksum = 0; /* updated later */
959 if (ibuf_set(buf, 0, &lsa_hdr, sizeof(lsa_hdr)) == -1)
960 fatal("orig_rtr_lsa: ibuf_set failed");
961
962 chksum = iso_cksum(ibuf_data(buf), ibuf_size(buf), LS_CKSUM_OFFSET);
963 if (ibuf_set_n16(buf, LS_CKSUM_OFFSET, chksum) == -1)
964 fatal("orig_rtr_lsa: ibuf_set_n16 failed");
965
966 if (self)
967 imsg_compose_event(iev_rde, IMSG_LS_UPD, self->peerid, 0,
968 -1, ibuf_data(buf), ibuf_size(buf));
969 else
970 log_warnx("orig_rtr_lsa: empty area %s",
971 inet_ntoa(area->id));
972
973 ibuf_free(buf);
974 }
975
976 void
orig_net_lsa(struct iface * iface)977 orig_net_lsa(struct iface *iface)
978 {
979 struct lsa_hdr lsa_hdr;
980 struct nbr *nbr;
981 struct ibuf *buf;
982 struct lsa_net lsa_net;
983 int num_rtr = 0;
984 u_int16_t chksum;
985
986 /* XXX IBUF_READ_SIZE */
987 if ((buf = ibuf_dynamic(sizeof(lsa_hdr), IBUF_READ_SIZE)) == NULL)
988 fatal("orig_net_lsa");
989
990 /* reserve space for LSA header and options field */
991 if (ibuf_add_zero(buf, sizeof(lsa_hdr) + sizeof(lsa_net)) == -1)
992 fatal("orig_net_lsa: ibuf_add_zero failed");
993
994 lsa_net.opts = 0;
995 /* fully adjacent neighbors + self */
996 LIST_FOREACH(nbr, &iface->nbr_list, entry)
997 if (nbr->state & NBR_STA_FULL) {
998 if (ibuf_add(buf, &nbr->id, sizeof(nbr->id)))
999 fatal("orig_net_lsa: ibuf_add failed");
1000 lsa_net.opts |= nbr->link_options;
1001 num_rtr++;
1002 }
1003
1004 if (num_rtr == 1) {
1005 /* non transit net therefore no need to generate a net lsa */
1006 ibuf_free(buf);
1007 return;
1008 }
1009
1010 /* LSA header */
1011 if (iface->state & IF_STA_DR)
1012 lsa_hdr.age = htons(DEFAULT_AGE);
1013 else
1014 lsa_hdr.age = htons(MAX_AGE);
1015
1016 lsa_hdr.type = htons(LSA_TYPE_NETWORK);
1017 /* for network LSAs, the link state ID equals the interface ID */
1018 lsa_hdr.ls_id = htonl(iface->ifindex);
1019 lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr;
1020 lsa_hdr.seq_num = htonl(INIT_SEQ_NUM);
1021 lsa_hdr.len = htons(ibuf_size(buf));
1022 lsa_hdr.ls_chksum = 0; /* updated later */
1023 if (ibuf_set(buf, 0, &lsa_hdr, sizeof(lsa_hdr)) == -1)
1024 fatal("orig_net_lsa: ibuf_set failed");
1025
1026 lsa_net.opts &= lsa_net.opts & htonl(LSA_24_MASK);
1027 if (ibuf_set(buf, sizeof(lsa_hdr), &lsa_net, sizeof(lsa_net)) == -1)
1028 fatal("orig_net_lsa: ibuf_set failed");
1029
1030 chksum = iso_cksum(ibuf_data(buf), ibuf_size(buf), LS_CKSUM_OFFSET);
1031 if (ibuf_set_n16(buf, LS_CKSUM_OFFSET, chksum) == -1)
1032 fatal("orig_net_lsa: ibuf_set_n16 failed");
1033
1034 imsg_compose_event(iev_rde, IMSG_LS_UPD, iface->self->peerid, 0,
1035 -1, ibuf_data(buf), ibuf_size(buf));
1036
1037 ibuf_free(buf);
1038 }
1039
1040 void
orig_link_lsa(struct iface * iface)1041 orig_link_lsa(struct iface *iface)
1042 {
1043 struct lsa_hdr lsa_hdr;
1044 struct lsa_link lsa_link;
1045 struct lsa_prefix lsa_prefix;
1046 struct ibuf *buf;
1047 struct iface_addr *ia;
1048 struct in6_addr prefix;
1049 unsigned int num_prefix = 0;
1050 u_int16_t chksum;
1051 u_int32_t options;
1052
1053 log_debug("orig_link_lsa: interface %s", iface->name);
1054
1055 switch (iface->type) {
1056 case IF_TYPE_VIRTUALLINK: /* forbidden by rfc5340 */
1057 return;
1058 case IF_TYPE_BROADCAST:
1059 case IF_TYPE_NBMA:
1060 if ((iface->state & IF_STA_MULTI) == 0)
1061 return;
1062 break;
1063 case IF_TYPE_POINTOPOINT:
1064 case IF_TYPE_POINTOMULTIPOINT:
1065 if ((iface->state & IF_STA_POINTTOPOINT) == 0)
1066 return;
1067 break;
1068 default:
1069 fatalx("orig_link_lsa: unknown interface type");
1070 }
1071
1072 /* XXX IBUF_READ_SIZE */
1073 if ((buf = ibuf_dynamic(sizeof(lsa_hdr) + sizeof(lsa_link),
1074 IBUF_READ_SIZE)) == NULL)
1075 fatal("orig_link_lsa");
1076
1077 /* reserve space for LSA header and LSA link header */
1078 if (ibuf_add_zero(buf, sizeof(lsa_hdr) + sizeof(lsa_link)) == -1)
1079 fatal("orig_link_lsa: ibuf_add_zero failed");
1080
1081 /* link-local address, and all prefixes configured on interface */
1082 TAILQ_FOREACH(ia, &iface->ifa_list, entry) {
1083 if (IN6_IS_ADDR_LINKLOCAL(&ia->addr)) {
1084 log_debug("orig_link_lsa: link local address %s",
1085 log_in6addr(&ia->addr));
1086 lsa_link.lladdr = ia->addr;
1087 continue;
1088 }
1089
1090 lsa_prefix.prefixlen = ia->prefixlen;
1091 lsa_prefix.options = 0;
1092 lsa_prefix.metric = 0;
1093 inet6applymask(&prefix, &ia->addr, ia->prefixlen);
1094 log_debug("orig_link_lsa: prefix %s", log_in6addr(&prefix));
1095 if (ibuf_add(buf, &lsa_prefix, sizeof(lsa_prefix)))
1096 fatal("orig_link_lsa: ibuf_add failed");
1097 if (ibuf_add(buf, &prefix.s6_addr[0],
1098 LSA_PREFIXSIZE(ia->prefixlen)))
1099 fatal("orig_link_lsa: ibuf_add failed");
1100 num_prefix++;
1101 }
1102
1103 /* LSA link header (lladdr has already been filled in above) */
1104 LSA_24_SETHI(lsa_link.opts, iface->priority);
1105 options = area_ospf_options(iface->area);
1106 LSA_24_SETLO(lsa_link.opts, options);
1107 lsa_link.opts = htonl(lsa_link.opts);
1108 lsa_link.numprefix = htonl(num_prefix);
1109 if (ibuf_set(buf, sizeof(lsa_hdr), &lsa_link, sizeof(lsa_link)) == -1)
1110 fatal("orig_link_lsa: ibuf_set failed");
1111
1112 /* LSA header */
1113 lsa_hdr.age = htons(DEFAULT_AGE);
1114 lsa_hdr.type = htons(LSA_TYPE_LINK);
1115 /* for link LSAs, the link state ID equals the interface ID */
1116 lsa_hdr.ls_id = htonl(iface->ifindex);
1117 lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr;
1118 lsa_hdr.seq_num = htonl(INIT_SEQ_NUM);
1119 lsa_hdr.len = htons(ibuf_size(buf));
1120 lsa_hdr.ls_chksum = 0; /* updated later */
1121 if (ibuf_set(buf, 0, &lsa_hdr, sizeof(lsa_hdr)) == -1)
1122 fatal("orig_link_lsa: ibuf_set failed");
1123
1124 chksum = iso_cksum(ibuf_data(buf), ibuf_size(buf), LS_CKSUM_OFFSET);
1125 if (ibuf_set_n16(buf, LS_CKSUM_OFFSET, chksum) == -1)
1126 fatal("orig_link_lsa: ibuf_set_n16 failed");
1127
1128 imsg_compose_event(iev_rde, IMSG_LS_UPD, iface->self->peerid, 0,
1129 -1, ibuf_data(buf), ibuf_size(buf));
1130
1131 ibuf_free(buf);
1132 }
1133
1134 u_int32_t
ospfe_router_id(void)1135 ospfe_router_id(void)
1136 {
1137 return (oeconf->rtr_id.s_addr);
1138 }
1139
1140 void
ospfe_fib_update(int type)1141 ospfe_fib_update(int type)
1142 {
1143 int old = oe_nofib;
1144
1145 if (type == IMSG_CTL_FIB_COUPLE)
1146 oe_nofib = 0;
1147 if (type == IMSG_CTL_FIB_DECOUPLE)
1148 oe_nofib = 1;
1149 if (old != oe_nofib)
1150 orig_rtr_lsa_all(NULL);
1151 }
1152
1153 void
ospfe_iface_ctl(struct ctl_conn * c,unsigned int idx)1154 ospfe_iface_ctl(struct ctl_conn *c, unsigned int idx)
1155 {
1156 struct area *area;
1157 struct iface *iface;
1158 struct ctl_iface *ictl;
1159
1160 LIST_FOREACH(area, &oeconf->area_list, entry)
1161 LIST_FOREACH(iface, &area->iface_list, entry)
1162 if (idx == 0 || idx == iface->ifindex) {
1163 ictl = if_to_ctl(iface);
1164 imsg_compose_event(&c->iev,
1165 IMSG_CTL_SHOW_INTERFACE, 0, 0, -1,
1166 ictl, sizeof(struct ctl_iface));
1167 }
1168 }
1169
1170 void
ospfe_nbr_ctl(struct ctl_conn * c)1171 ospfe_nbr_ctl(struct ctl_conn *c)
1172 {
1173 struct area *area;
1174 struct iface *iface;
1175 struct nbr *nbr;
1176 struct ctl_nbr *nctl;
1177
1178 LIST_FOREACH(area, &oeconf->area_list, entry)
1179 LIST_FOREACH(iface, &area->iface_list, entry)
1180 LIST_FOREACH(nbr, &iface->nbr_list, entry) {
1181 if (iface->self != nbr) {
1182 nctl = nbr_to_ctl(nbr);
1183 imsg_compose_event(&c->iev,
1184 IMSG_CTL_SHOW_NBR, 0, 0, -1, nctl,
1185 sizeof(struct ctl_nbr));
1186 }
1187 }
1188
1189 imsg_compose_event(&c->iev, IMSG_CTL_END, 0, 0, -1, NULL, 0);
1190 }
1191
1192 void
ospfe_demote_area(struct area * area,int active)1193 ospfe_demote_area(struct area *area, int active)
1194 {
1195 struct demote_msg dmsg;
1196
1197 if (ospfd_process != PROC_OSPF_ENGINE ||
1198 area->demote_group[0] == '\0')
1199 return;
1200
1201 bzero(&dmsg, sizeof(dmsg));
1202 strlcpy(dmsg.demote_group, area->demote_group,
1203 sizeof(dmsg.demote_group));
1204 dmsg.level = area->demote_level;
1205 if (active)
1206 dmsg.level = -dmsg.level;
1207
1208 ospfe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg));
1209 }
1210
1211 void
ospfe_demote_iface(struct iface * iface,int active)1212 ospfe_demote_iface(struct iface *iface, int active)
1213 {
1214 struct demote_msg dmsg;
1215
1216 if (ospfd_process != PROC_OSPF_ENGINE ||
1217 iface->demote_group[0] == '\0')
1218 return;
1219
1220 bzero(&dmsg, sizeof(dmsg));
1221 strlcpy(dmsg.demote_group, iface->demote_group,
1222 sizeof(dmsg.demote_group));
1223 if (active)
1224 dmsg.level = -1;
1225 else
1226 dmsg.level = 1;
1227
1228 log_warnx("ospfe_demote_iface: group %s level %d", dmsg.demote_group,
1229 dmsg.level);
1230
1231 ospfe_imsg_compose_parent(IMSG_DEMOTE, 0, &dmsg, sizeof(dmsg));
1232 }
1233