Download raw body.
ospfd: rewrite the imsg handling part 2
Here is part 2 which extends the imsgev.c code to also handle read / write
internally.
imsgev_new() now takes a imsg_handler and and error_handler as callbacks
and calls them when imsg are available or when an error happened.
The imsg_handler now simply gets a imsg pointer and so functions like
main_dispatch_ospfe become a lot simpler.
The error handler is called with a event of EV_WRITE or EV_READ and passes
errno or 0 (for the connection close case).
ospfd does not care about any of that. Since errors are either ignored
(control socker) or are terminal.
While touching all the dispatch functions I could not help myself and also
use the imsg API properly and stop peaking at the imsg hdr or imsg->data.
As before this seems to work in my limited use case.
--
:wq Claudio
diff --git usr.sbin/ospfd/control.c usr.sbin/ospfd/control.c
index 396af06f422..67a83d5e7e6 100644
--- usr.sbin/ospfd/control.c
+++ usr.sbin/ospfd/control.c
@@ -38,7 +38,9 @@ TAILQ_HEAD(ctl_conns, ctl_conn) ctl_conns = TAILQ_HEAD_INITIALIZER(ctl_conns);
struct ctl_conn *control_connbyfd(int);
struct ctl_conn *control_connbypid(pid_t);
-void control_close(int);
+void control_close(struct ctl_conn *);
+void control_dispatch_imsg(struct imsg *, void *);
+void control_dispatch_error(struct imsgbuf *, void *, short, int);
struct {
struct event ev;
@@ -176,7 +178,8 @@ control_accept(int listenfd, short event, void *bula)
return;
}
- if ((c->imsgbuf = imsgev_new(connfd, control_dispatch_imsg)) == NULL) {
+ if ((c->imsgbuf = imsgev_new(connfd, control_dispatch_imsg,
+ control_dispatch_error, c)) == NULL) {
log_warn("imsgbuf_init");
close(connfd);
free(c);
@@ -213,15 +216,8 @@ control_connbypid(pid_t pid)
}
void
-control_close(int fd)
+control_close(struct ctl_conn *c)
{
- struct ctl_conn *c;
-
- if ((c = control_connbyfd(fd)) == NULL) {
- log_warn("control_close: fd %d: not found", fd);
- return;
- }
-
TAILQ_REMOVE(&ctl_conns, c, entry);
imsgev_free(c->imsgbuf);
@@ -235,104 +231,74 @@ control_close(int fd)
}
void
-control_dispatch_imsg(int fd, short event, void *bula)
+control_dispatch_imsg(struct imsg *imsg, void *arg)
{
- struct ctl_conn *c;
- struct imsg imsg;
- int n, verbose;
+ struct ctl_conn *c = arg;
+ uint32_t type;
+ pid_t pid;
+ int verbose;
unsigned int ifidx;
- if ((c = control_connbyfd(fd)) == NULL) {
- log_warn("control_dispatch_imsg: fd %d: not found", fd);
- return;
- }
-
- if (event & EV_READ) {
- if (imsgbuf_read(c->imsgbuf) != 1) {
- control_close(fd);
- return;
- }
- }
- if (event & EV_WRITE) {
- if (imsgbuf_write(c->imsgbuf) == -1) {
- control_close(fd);
- return;
- }
- }
-
- for (;;) {
- if ((n = imsgbuf_get(c->imsgbuf, &imsg)) == -1) {
- control_close(fd);
- return;
- }
-
- if (n == 0)
+ c->imsgbuf->pid = pid = imsg_get_pid(imsg);
+ type = imsg_get_type(imsg);
+ switch (type) {
+ case IMSG_CTL_FIB_COUPLE:
+ case IMSG_CTL_FIB_DECOUPLE:
+ ospfe_fib_update(type);
+ /* FALLTHROUGH */
+ case IMSG_CTL_FIB_RELOAD:
+ case IMSG_CTL_RELOAD:
+ ospfe_imsg_compose_parent(type, 0, NULL, 0);
+ break;
+ case IMSG_CTL_KROUTE:
+ case IMSG_CTL_KROUTE_ADDR:
+ case IMSG_CTL_IFINFO:
+ ospfe_imsg_forward_parent(imsg);
+ break;
+ case IMSG_CTL_SHOW_INTERFACE:
+ if (imsg_get_data(imsg, &ifidx, sizeof(ifidx)) == -1)
break;
- c->imsgbuf->pid = imsg.hdr.pid;
- switch (imsg.hdr.type) {
- case IMSG_CTL_FIB_COUPLE:
- case IMSG_CTL_FIB_DECOUPLE:
- ospfe_fib_update(imsg.hdr.type);
- /* FALLTHROUGH */
- case IMSG_CTL_FIB_RELOAD:
- case IMSG_CTL_RELOAD:
- ospfe_imsg_compose_parent(imsg.hdr.type, 0, NULL, 0);
- break;
- case IMSG_CTL_KROUTE:
- case IMSG_CTL_KROUTE_ADDR:
- case IMSG_CTL_IFINFO:
- ospfe_imsg_compose_parent(imsg.hdr.type, imsg.hdr.pid,
- imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
- break;
- case IMSG_CTL_SHOW_INTERFACE:
- if (imsg.hdr.len == IMSG_HEADER_SIZE +
- sizeof(ifidx)) {
- memcpy(&ifidx, imsg.data, sizeof(ifidx));
- ospfe_iface_ctl(c, ifidx);
- imsg_compose(c->imsgbuf, IMSG_CTL_END, 0,
- 0, -1, NULL, 0);
- }
- break;
- case IMSG_CTL_SHOW_DATABASE:
- case IMSG_CTL_SHOW_DB_EXT:
- case IMSG_CTL_SHOW_DB_NET:
- case IMSG_CTL_SHOW_DB_RTR:
- case IMSG_CTL_SHOW_DB_SELF:
- case IMSG_CTL_SHOW_DB_SUM:
- case IMSG_CTL_SHOW_DB_ASBR:
- case IMSG_CTL_SHOW_DB_OPAQ:
- case IMSG_CTL_SHOW_RIB:
- case IMSG_CTL_SHOW_SUM:
- ospfe_imsg_compose_rde(imsg.hdr.type, 0, imsg.hdr.pid,
- imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
- break;
- case IMSG_CTL_SHOW_NBR:
- ospfe_nbr_ctl(c);
- break;
- case IMSG_CTL_LOG_VERBOSE:
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(verbose))
- break;
-
- /* forward to other processes */
- ospfe_imsg_compose_parent(imsg.hdr.type, imsg.hdr.pid,
- imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
- ospfe_imsg_compose_rde(imsg.hdr.type, 0, imsg.hdr.pid,
- imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
-
- memcpy(&verbose, imsg.data, sizeof(verbose));
- log_setverbose(verbose);
+ ospfe_iface_ctl(c, ifidx);
+ break;
+ case IMSG_CTL_SHOW_DATABASE:
+ case IMSG_CTL_SHOW_DB_EXT:
+ case IMSG_CTL_SHOW_DB_NET:
+ case IMSG_CTL_SHOW_DB_RTR:
+ case IMSG_CTL_SHOW_DB_SELF:
+ case IMSG_CTL_SHOW_DB_SUM:
+ case IMSG_CTL_SHOW_DB_ASBR:
+ case IMSG_CTL_SHOW_DB_OPAQ:
+ case IMSG_CTL_SHOW_RIB:
+ case IMSG_CTL_SHOW_SUM:
+ ospfe_imsg_forward_rde(imsg);
+ break;
+ case IMSG_CTL_SHOW_NBR:
+ ospfe_nbr_ctl(c);
+ break;
+ case IMSG_CTL_LOG_VERBOSE:
+ if (imsg_get_data(imsg, &verbose, sizeof(verbose)) == -1)
break;
- default:
- log_debug("control_dispatch_imsg: "
- "error handling imsg %d", imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
+
+ /* forward to other processes */
+ ospfe_imsg_forward_parent(imsg);
+ ospfe_imsg_forward_rde(imsg);
+ log_setverbose(verbose);
+ break;
+ default:
+ log_debug("control_dispatch_imsg: "
+ "error handling imsg %d", type);
+ break;
}
+}
+
+void
+control_dispatch_error(struct imsgbuf *ibuf, void *arg, short event, int error)
+{
+ struct ctl_conn *c = arg;
- imsg_event_add(c->imsgbuf, imsgbuf_get_userdata(c->imsgbuf));
+ /* silently discard session, ospfctl will complain to user */
+ control_close(c);
}
int
@@ -340,9 +306,8 @@ control_imsg_relay(struct imsg *imsg)
{
struct ctl_conn *c;
- if ((c = control_connbypid(imsg->hdr.pid)) == NULL)
+ if ((c = control_connbypid(imsg_get_pid(imsg))) == NULL)
return (0);
- return (imsg_compose(c->imsgbuf, imsg->hdr.type, 0, imsg->hdr.pid,
- -1, imsg->data, imsg->hdr.len - IMSG_HEADER_SIZE));
+ return (imsg_forward(c->imsgbuf, imsg));
}
diff --git usr.sbin/ospfd/control.h usr.sbin/ospfd/control.h
index 7608b7805e2..d0ea95f7e6f 100644
--- usr.sbin/ospfd/control.h
+++ usr.sbin/ospfd/control.h
@@ -32,7 +32,6 @@ int control_check(char *);
int control_init(char *);
int control_listen(int);
void control_accept(int, short, void *);
-void control_dispatch_imsg(int, short, void *);
int control_imsg_relay(struct imsg *);
void control_cleanup(void);
diff --git usr.sbin/ospfd/imsgev.c usr.sbin/ospfd/imsgev.c
index 9948006e8cb..6ee40c40800 100644
--- usr.sbin/ospfd/imsgev.c
+++ usr.sbin/ospfd/imsgev.c
@@ -16,6 +16,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
@@ -25,28 +26,76 @@
struct imsgev {
struct imsgbuf ibuf;
- void (*handler)(int, short, void *);
- struct event ev;
- short events;
+ struct event rev;
+ struct event wev;
+ void (*imsg_handler)(struct imsg *, void *);
+ void (*error_handler)(struct imsgbuf *,
+ void *, short, int);
+ void *arg;
};
-void
-imsg_event_add(struct imsgbuf *imsgbuf, void *udata)
+static void
+imsgev_add(struct imsgbuf *imsgbuf, void *udata)
{
struct imsgev *iev = udata;
- iev->events = EV_READ;
- if (imsgbuf_queuelen(&iev->ibuf) > 0)
- iev->events |= EV_WRITE;
+ event_add(&iev->wev, NULL);
+}
+
+static void
+imsgev_write(int fd, short event, void *arg)
+{
+ struct imsgev *iev = arg;
+ struct imsgbuf *imsgbuf = &iev->ibuf;
+
+ if (event & EV_WRITE) {
+ if (imsgbuf_write(imsgbuf) == -1) {
+ iev->error_handler(imsgbuf, iev->arg, EV_WRITE, errno);
+ return;
+ }
+ }
+
+ if (imsgbuf_queuelen(imsgbuf) == 0)
+ event_del(&iev->wev);
+}
- event_del(&iev->ev);
- event_set(&iev->ev, iev->ibuf.fd, iev->events, iev->handler,
- &iev->ibuf);
- event_add(&iev->ev, NULL);
+static void
+imsgev_read(int fd, short event, void *arg)
+{
+ struct imsgev *iev = arg;
+ struct imsgbuf *imsgbuf = &iev->ibuf;
+ struct imsg imsg;
+ int n;
+
+ if (event & EV_READ) {
+ if ((n = imsgbuf_read(imsgbuf)) == -1) {
+ iev->error_handler(imsgbuf, iev->arg, EV_READ, errno);
+ return;
+ }
+ if (n == 0) {
+ iev->error_handler(imsgbuf, iev->arg, EV_READ, 0);
+ return;
+ }
+ }
+
+ for (;;) {
+ if ((n = imsgbuf_get(imsgbuf, &imsg)) == -1) {
+ iev->error_handler(imsgbuf, iev->arg, EV_READ, errno);
+ return;
+ }
+ if (n == 0)
+ break;
+
+ iev->imsg_handler(&imsg, iev->arg);
+
+ imsg_free(&imsg);
+ }
}
struct imsgbuf *
-imsgev_new(int fd, void (*handler)(int, short, void *))
+imsgev_new(int fd, void (*imsg_handler)(struct imsg *, void *),
+ void (*error_handler)(struct imsgbuf *imsgbuf, void *, short, int),
+ void *arg)
{
struct imsgev *iev;
@@ -59,13 +108,15 @@ imsgev_new(int fd, void (*handler)(int, short, void *))
}
imsgbuf_set_userdata(&iev->ibuf, iev);
- imsgbuf_set_close_callback(&iev->ibuf, imsg_event_add);
- iev->handler = handler;
+ imsgbuf_set_close_callback(&iev->ibuf, imsgev_add);
+ iev->imsg_handler = imsg_handler;
+ iev->error_handler = error_handler;
+ iev->arg = arg;
- iev->events = EV_READ;
- event_set(&iev->ev, fd, iev->events, iev->handler, &iev->ibuf);
- event_add(&iev->ev, NULL);
+ event_set(&iev->rev, fd, EV_READ | EV_PERSIST, imsgev_read, iev);
+ event_set(&iev->wev, fd, EV_WRITE | EV_PERSIST, imsgev_write, iev);
+ event_add(&iev->rev, NULL);
return &iev->ibuf;
}
@@ -79,6 +130,7 @@ imsgev_free(struct imsgbuf *imsgbuf)
close(imsgbuf->fd);
imsgbuf_clear(imsgbuf);
- event_del(&iev->ev);
+ event_del(&iev->rev);
+ event_del(&iev->wev);
free(iev);
}
diff --git usr.sbin/ospfd/imsgev.h usr.sbin/ospfd/imsgev.h
index 75c4d1c587a..bb823245e86 100644
--- usr.sbin/ospfd/imsgev.h
+++ usr.sbin/ospfd/imsgev.h
@@ -18,6 +18,6 @@
#include <imsg.h>
-void imsg_event_add(struct imsgbuf *, void *);
-struct imsgbuf *imsgev_new(int, void (*)(int, short, void *));
+struct imsgbuf *imsgev_new(int, void (*)(struct imsg *, void *),
+ void (*)(struct imsgbuf *, void *, short, int), void *);
void imsgev_free(struct imsgbuf *);
diff --git usr.sbin/ospfd/ospfd.c usr.sbin/ospfd/ospfd.c
index 9a172415e82..8d171442527 100644
--- usr.sbin/ospfd/ospfd.c
+++ usr.sbin/ospfd/ospfd.c
@@ -52,8 +52,8 @@ void main_sig_handler(int, short, void *);
__dead void usage(void);
__dead void ospfd_shutdown(void);
-void main_dispatch_ospfe(int, short, void *);
-void main_dispatch_rde(int, short, void *);
+void main_dispatch_ospfe(struct imsg *, void *);
+void main_dispatch_rde(struct imsg *, void *);
int ospf_reload(void);
int ospf_sendboth(enum imsg_type, void *, u_int16_t);
@@ -261,9 +261,9 @@ main(int argc, char *argv[])
close(pipe_ospfe2rde[1]);
if ((imsg_ospfe = imsgev_new(pipe_parent2ospfe[0],
- main_dispatch_ospfe)) == NULL ||
+ main_dispatch_ospfe, ospfd_dispatch_error, NULL)) == NULL ||
(imsg_rde = imsgev_new(pipe_parent2rde[0],
- main_dispatch_rde)) == NULL)
+ main_dispatch_rde, ospfd_dispatch_error, NULL)) == NULL)
fatal(NULL);
imsgbuf_allow_fdpass(imsg_ospfe);
@@ -332,142 +332,101 @@ ospfd_shutdown(void)
/* imsg handling */
void
-main_dispatch_ospfe(int fd, short event, void *arg)
+main_dispatch_ospfe(struct imsg *imsg, void *arg)
{
- struct imsgbuf *ibuf = arg;
- struct imsg imsg;
+ uint32_t type;
struct demote_msg dmsg;
- int n, shut = 0, verbose;
+ char ifname[IFNAMSIZ];
+ int verbose;
- if (event & EV_READ) {
- if ((n = imsgbuf_read(ibuf)) == -1)
- fatal("imsgbuf_read error");
- if (n == 0) /* connection closed */
- shut = 1;
- }
- if (event & EV_WRITE) {
- if (imsgbuf_write(ibuf) == -1) {
- if (errno == EPIPE) /* connection closed */
- shut = 1;
- else
- fatal("imsgbuf_write");
- }
+ type = imsg_get_type(imsg);
+ switch (type) {
+ case IMSG_CTL_RELOAD:
+ if (ospf_reload() == -1)
+ log_warnx("configuration reload failed");
+ else
+ log_debug("configuration reloaded");
+ break;
+ case IMSG_CTL_FIB_COUPLE:
+ kr_fib_couple();
+ break;
+ case IMSG_CTL_FIB_DECOUPLE:
+ kr_fib_decouple();
+ break;
+ case IMSG_CTL_FIB_RELOAD:
+ kr_fib_reload();
+ break;
+ case IMSG_CTL_KROUTE:
+ case IMSG_CTL_KROUTE_ADDR:
+ kr_show_route(imsg);
+ break;
+ case IMSG_CTL_IFINFO:
+ if (imsg_get_len(imsg) == 0)
+ kr_ifinfo(NULL, imsg_get_pid(imsg));
+ else if (imsg_get_len(imsg) != IFNAMSIZ ||
+ imsg_get_strbuf(imsg, ifname, sizeof(ifname)) == -1)
+ log_warnx("bad IFINFO request");
+ else
+ kr_ifinfo(ifname, imsg_get_pid(imsg));
+ break;
+ case IMSG_DEMOTE:
+ if (imsg_get_len(imsg) != sizeof(dmsg) ||
+ imsg_get_strbuf(imsg, dmsg.demote_group,
+ sizeof(dmsg.demote_group)) == -1 ||
+ imsg_get_buf(imsg, &dmsg.level, sizeof(dmsg.level)) == -1)
+ fatalx("bad demote request from OE");
+ carp_demote_set(dmsg.demote_group, dmsg.level);
+ break;
+ case IMSG_CTL_LOG_VERBOSE:
+ if (imsg_get_data(imsg, &verbose, sizeof(verbose)) == -1)
+ log_warn("wrong imsg len");
+ else
+ log_setverbose(verbose);
+ break;
+ default:
+ log_debug("main_dispatch_ospfe: error handling imsg %d",
+ type);
+ break;
}
+}
- for (;;) {
- if ((n = imsgbuf_get(ibuf, &imsg)) == -1)
- fatal("imsgbuf_get");
- if (n == 0)
- break;
+void
+main_dispatch_rde(struct imsg *imsg, void *arg)
+{
+ uint32_t type;
- switch (imsg.hdr.type) {
- case IMSG_CTL_RELOAD:
- if (ospf_reload() == -1)
- log_warnx("configuration reload failed");
- else
- log_debug("configuration reloaded");
- break;
- case IMSG_CTL_FIB_COUPLE:
- kr_fib_couple();
- break;
- case IMSG_CTL_FIB_DECOUPLE:
- kr_fib_decouple();
- break;
- case IMSG_CTL_FIB_RELOAD:
- kr_fib_reload();
- break;
- case IMSG_CTL_KROUTE:
- case IMSG_CTL_KROUTE_ADDR:
- kr_show_route(&imsg);
- break;
- case IMSG_CTL_IFINFO:
- if (imsg.hdr.len == IMSG_HEADER_SIZE)
- kr_ifinfo(NULL, imsg.hdr.pid);
- else if (imsg.hdr.len == IMSG_HEADER_SIZE + IFNAMSIZ)
- kr_ifinfo(imsg.data, imsg.hdr.pid);
- else
- log_warnx("IFINFO request with wrong len");
- break;
- case IMSG_DEMOTE:
- if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(dmsg))
- fatalx("invalid size of OE request");
- memcpy(&dmsg, imsg.data, sizeof(dmsg));
- carp_demote_set(dmsg.demote_group, dmsg.level);
- break;
- case IMSG_CTL_LOG_VERBOSE:
- if (imsg_get_data(&imsg, &verbose, sizeof(verbose)) ==
- -1)
- log_warn("wrong imsg len");
- else
- log_setverbose(verbose);
- break;
- default:
- log_debug("main_dispatch_ospfe: error handling imsg %d",
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- if (!shut)
- imsg_event_add(ibuf, imsgbuf_get_userdata(ibuf));
- else {
- /* this pipe is dead, exit asap */
- event_loopexit(NULL);
+ type = imsg_get_type(imsg);
+ switch (type) {
+ case IMSG_KROUTE_CHANGE:
+ if (kr_change(imsg))
+ log_warn("main_dispatch_rde: error changing route");
+ break;
+ case IMSG_KROUTE_DELETE:
+ if (kr_delete(imsg))
+ log_warn("main_dispatch_rde: error deleting route");
+ break;
+ default:
+ log_debug("main_dispatch_rde: error handling imsg %d", type);
+ break;
}
}
void
-main_dispatch_rde(int fd, short event, void *arg)
+ospfd_dispatch_error(struct imsgbuf *ibuf, void *arg, short event, int error)
{
- struct imsgbuf *ibuf = arg;
- struct imsg imsg;
- int n, shut = 0;
-
- if (event & EV_READ) {
- if ((n = imsgbuf_read(ibuf)) == -1)
- fatal("imsgbuf_read error");
- if (n == 0) /* connection closed */
- shut = 1;
- }
- if (event & EV_WRITE) {
- if (imsgbuf_write(ibuf) == -1) {
- if (errno == EPIPE) /* connection closed */
- shut = 1;
- else
- fatal("imsgbuf_write");
- }
- }
+ const char *dir, *err = "connection closed";
- for (;;) {
- if ((n = imsgbuf_get(ibuf, &imsg)) == -1)
- fatal("imsgbuf_get");
- if (n == 0)
- break;
+ if (event & EV_READ)
+ dir = "imsg read";
+ else
+ dir = "imsg write";
- switch (imsg.hdr.type) {
- case IMSG_KROUTE_CHANGE:
- if (kr_change(&imsg))
- log_warn("main_dispatch_rde: error changing "
- "route");
- break;
- case IMSG_KROUTE_DELETE:
- if (kr_delete(&imsg))
- log_warn("main_dispatch_rde: error deleting "
- "route");
- break;
- default:
- log_debug("main_dispatch_rde: error handling imsg %d",
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- if (!shut)
- imsg_event_add(ibuf, imsgbuf_get_userdata(ibuf));
- else {
- /* this pipe is dead, exit asap */
- event_loopexit(NULL);
- }
+ if (error)
+ err = strerror(error);
+ log_warnx("%s: %s", dir, err);
+
+ /* this pipe is dead, exit asap, cleanup is done there */
+ event_loopexit(NULL);
}
void
@@ -497,7 +456,7 @@ ospf_redistribute(struct kroute *kr, u_int32_t *metric)
struct in_addr addr;
struct kif *kif;
struct redistribute *r;
- int is_default, depend_ok;
+ int is_default, depend_ok;
bzero(&addr, sizeof(addr));
@@ -682,8 +641,8 @@ ospf_reload(void)
return (-1);
/* No router-id was specified, keep existing value */
- if (xconf->rtr_id.s_addr == 0)
- xconf->rtr_id.s_addr = ospfd_conf->rtr_id.s_addr;
+ if (xconf->rtr_id.s_addr == 0)
+ xconf->rtr_id.s_addr = ospfd_conf->rtr_id.s_addr;
/* Abort the reload if rtr_id changed */
if (ospfd_conf->rtr_id.s_addr != xconf->rtr_id.s_addr) {
@@ -934,8 +893,7 @@ merge_interfaces(struct area *a, struct area *xa)
md_list_clr(&i->auth_md_list);
md_list_copy(&i->auth_md_list, &xi->auth_md_list);
- strlcpy(i->dependon, xi->dependon,
- sizeof(i->dependon));
+ strlcpy(i->dependon, xi->dependon, sizeof(i->dependon));
i->depend_ok = xi->depend_ok;
if (i->passive != xi->passive) {
diff --git usr.sbin/ospfd/ospfd.h usr.sbin/ospfd/ospfd.h
index 7e8a9955e5b..54af367ee1b 100644
--- usr.sbin/ospfd/ospfd.h
+++ usr.sbin/ospfd/ospfd.h
@@ -606,6 +606,7 @@ u_int16_t rtlabel_tag2id(u_int32_t);
void rtlabel_tag(u_int16_t, u_int32_t);
/* ospfd.c */
+void ospfd_dispatch_error(struct imsgbuf *, void *, short, int);
void main_imsg_compose_ospfe(int, pid_t, void *, u_int16_t);
void main_imsg_compose_ospfe_fd(int, pid_t, int);
void main_imsg_compose_rde(int, pid_t, void *, u_int16_t);
diff --git usr.sbin/ospfd/ospfe.c usr.sbin/ospfd/ospfe.c
index 47c48cf0318..99e545fab5c 100644
--- usr.sbin/ospfd/ospfe.c
+++ usr.sbin/ospfd/ospfe.c
@@ -46,6 +46,8 @@ void ospfe_sig_handler(int, short, void *);
__dead void ospfe_shutdown(void);
void orig_rtr_lsa_all(struct area *);
struct iface *find_vlink(struct abr_rtr *);
+void ospfe_dispatch_main(struct imsg *, void *);
+void ospfe_dispatch_rde(struct imsg *, void *);
struct ospfd_conf *oeconf = NULL, *noeconf;
static struct imsgbuf *imsg_main;
@@ -153,9 +155,9 @@ ospfe(struct ospfd_conf *xconf, int pipe_parent2ospfe[2], int pipe_ospfe2rde[2],
close(pipe_parent2rde[1]);
if ((imsg_rde = imsgev_new(pipe_ospfe2rde[0],
- ospfe_dispatch_rde)) == NULL ||
+ ospfe_dispatch_rde, ospfd_dispatch_error, NULL)) == NULL ||
(imsg_main = imsgev_new(pipe_parent2ospfe[1],
- ospfe_dispatch_main)) == NULL)
+ ospfe_dispatch_main, ospfd_dispatch_error, NULL)) == NULL)
fatal(NULL);
imsgbuf_allow_fdpass(imsg_main);
@@ -239,532 +241,469 @@ ospfe_imsg_compose_rde(int type, u_int32_t peerid, pid_t pid,
return (imsg_compose(imsg_rde, type, peerid, pid, -1, data, datalen));
}
+int
+ospfe_imsg_forward_parent(struct imsg *imsg)
+{
+ return (imsg_forward(imsg_main, imsg));
+}
+
+int
+ospfe_imsg_forward_rde(struct imsg *imsg)
+{
+ return (imsg_forward(imsg_rde, imsg));
+}
+
void
-ospfe_dispatch_main(int fd, short event, void *arg)
+ospfe_dispatch_main(struct imsg *imsg, void *arg)
{
static struct area *narea;
static struct iface *niface;
- struct ifaddrchange *ifc;
- struct imsg imsg;
- struct imsgbuf *ibuf = arg;
+ struct ifaddrchange ifc;
struct area *area = NULL;
struct iface *iface = NULL;
- struct kif *kif;
+ struct kif kif;
struct auth_md md;
- int n, link_ok, stub_changed, shut = 0;
-
- if (event & EV_READ) {
- if ((n = imsgbuf_read(ibuf)) == -1)
- fatal("imsgbuf_read error");
- if (n == 0) /* connection closed */
- shut = 1;
- }
- if (event & EV_WRITE) {
- if (imsgbuf_write(ibuf) == -1) {
- if (errno == EPIPE) /* connection closed */
- shut = 1;
- else
- fatal("imsgbuf_write");
- }
- }
-
- for (;;) {
- if ((n = imsgbuf_get(ibuf, &imsg)) == -1)
- fatal("ospfe_dispatch_main: imsgbuf_get error");
- if (n == 0)
- break;
-
- switch (imsg.hdr.type) {
- case IMSG_IFINFO:
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct kif))
- fatalx("IFINFO imsg with wrong len");
- kif = imsg.data;
- link_ok = (kif->flags & IFF_UP) &&
- LINK_STATE_IS_UP(kif->link_state);
-
- LIST_FOREACH(area, &oeconf->area_list, entry) {
- LIST_FOREACH(iface, &area->iface_list, entry) {
- if (kif->ifindex == iface->ifindex &&
- iface->type !=
- IF_TYPE_VIRTUALLINK) {
- int prev_link_state =
- (iface->flags & IFF_UP) &&
- LINK_STATE_IS_UP(iface->linkstate);
-
- iface->flags = kif->flags;
- iface->linkstate =
- kif->link_state;
- iface->mtu = kif->mtu;
-
- if (link_ok == prev_link_state)
- break;
+ uint32_t type;
+ int fd, link_ok, stub_changed;
+
+ type = imsg_get_type(imsg);
+ switch (type) {
+ case IMSG_IFINFO:
+ if (imsg_get_data(imsg, &kif, sizeof(kif)) == -1)
+ fatalx("bad IFINFO imsg received");
+ link_ok = (kif.flags & IFF_UP) &&
+ LINK_STATE_IS_UP(kif.link_state);
+
+ LIST_FOREACH(area, &oeconf->area_list, entry) {
+ LIST_FOREACH(iface, &area->iface_list, entry) {
+ if (kif.ifindex == iface->ifindex &&
+ iface->type != IF_TYPE_VIRTUALLINK) {
+ int prev_link_state =
+ (iface->flags & IFF_UP) &&
+ LINK_STATE_IS_UP(iface->linkstate);
+
+ iface->flags = kif.flags;
+ iface->linkstate = kif.link_state;
+ iface->mtu = kif.mtu;
+
+ if (link_ok == prev_link_state)
+ break;
- if (link_ok) {
- if_fsm(iface,
- IF_EVT_UP);
- log_warnx("interface %s"
- " up", iface->name);
- } else {
- if_fsm(iface,
- IF_EVT_DOWN);
- log_warnx("interface %s"
- " down",
- iface->name);
- }
- }
- if (strcmp(kif->ifname,
- iface->dependon) == 0) {
- log_warnx("interface %s"
- " changed state, %s"
- " depends on it",
- kif->ifname,
+ if (link_ok) {
+ if_fsm(iface, IF_EVT_UP);
+ log_warnx("interface %s up",
+ iface->name);
+ } else {
+ if_fsm(iface, IF_EVT_DOWN);
+ log_warnx("interface %s down",
iface->name);
- iface->depend_ok =
- ifstate_is_up(kif);
-
- if ((iface->flags &
- IFF_UP) &&
- LINK_STATE_IS_UP(iface->linkstate))
- orig_rtr_lsa(iface->area);
}
}
- }
- break;
- case IMSG_IFADDRADD:
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct ifaddrchange))
- fatalx("IFADDRADD imsg with wrong len");
- ifc = imsg.data;
+ kif.ifname[sizeof(kif.ifname) - 1] = '\0';
+ if (strcmp(kif.ifname, iface->dependon) == 0) {
+ log_warnx("interface %s changed state, "
+ " %s depends on it", kif.ifname,
+ iface->name);
+ iface->depend_ok = ifstate_is_up(&kif);
- LIST_FOREACH(area, &oeconf->area_list, entry) {
- LIST_FOREACH(iface, &area->iface_list, entry) {
- if (ifc->ifindex == iface->ifindex &&
- ifc->addr.s_addr ==
- iface->addr.s_addr) {
- iface->mask = ifc->mask;
- iface->dst = ifc->dst;
- /*
- * Previous down event might
- * have failed if the address
- * was not present at that
- * time.
- */
- if_fsm(iface, IF_EVT_DOWN);
- if_fsm(iface, IF_EVT_UP);
- log_warnx("interface %s:%s "
- "returned", iface->name,
- inet_ntoa(iface->addr));
- break;
- }
+ if ((iface->flags & IFF_UP) &&
+ LINK_STATE_IS_UP(iface->linkstate))
+ orig_rtr_lsa(iface->area);
}
}
- break;
- case IMSG_IFADDRDEL:
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct ifaddrchange))
- fatalx("IFADDRDEL imsg with wrong len");
- ifc = imsg.data;
-
- LIST_FOREACH(area, &oeconf->area_list, entry) {
- LIST_FOREACH(iface, &area->iface_list, entry) {
- if (ifc->ifindex == iface->ifindex &&
- ifc->addr.s_addr ==
- iface->addr.s_addr) {
- if_fsm(iface, IF_EVT_DOWN);
- log_warnx("interface %s:%s "
- "gone", iface->name,
- inet_ntoa(iface->addr));
- break;
- }
+ }
+ break;
+ case IMSG_IFADDRADD:
+ if (imsg_get_data(imsg, &ifc, sizeof(ifc)) == -1)
+ fatalx("bad IFADDRADD imsg received");
+
+ LIST_FOREACH(area, &oeconf->area_list, entry) {
+ LIST_FOREACH(iface, &area->iface_list, entry) {
+ if (ifc.ifindex == iface->ifindex &&
+ ifc.addr.s_addr == iface->addr.s_addr) {
+ iface->mask = ifc.mask;
+ iface->dst = ifc.dst;
+ /*
+ * Previous down event might
+ * have failed if the address
+ * was not present at that
+ * time.
+ */
+ if_fsm(iface, IF_EVT_DOWN);
+ if_fsm(iface, IF_EVT_UP);
+ log_warnx("interface %s:%s "
+ "returned", iface->name,
+ inet_ntoa(iface->addr));
+ break;
}
}
- break;
- case IMSG_RECONF_CONF:
- if ((noeconf = malloc(sizeof(struct ospfd_conf))) ==
- NULL)
- fatal(NULL);
- memcpy(noeconf, imsg.data, sizeof(struct ospfd_conf));
-
- LIST_INIT(&noeconf->area_list);
- LIST_INIT(&noeconf->cand_list);
- break;
- case IMSG_RECONF_AREA:
- if ((narea = area_new()) == NULL)
- fatal(NULL);
- memcpy(narea, imsg.data, sizeof(struct area));
-
- LIST_INIT(&narea->iface_list);
- LIST_INIT(&narea->nbr_list);
- RB_INIT(&narea->lsa_tree);
- SIMPLEQ_INIT(&narea->redist_list);
-
- LIST_INSERT_HEAD(&noeconf->area_list, narea, entry);
- break;
- case IMSG_RECONF_IFACE:
- if ((niface = malloc(sizeof(struct iface))) == NULL)
- fatal(NULL);
- memcpy(niface, imsg.data, sizeof(struct iface));
-
- LIST_INIT(&niface->nbr_list);
- TAILQ_INIT(&niface->ls_ack_list);
- TAILQ_INIT(&niface->auth_md_list);
- RB_INIT(&niface->lsa_tree);
-
- niface->area = narea;
- LIST_INSERT_HEAD(&narea->iface_list, niface, entry);
- break;
- case IMSG_RECONF_AUTHMD:
- if (imsg_get_data(&imsg, md.key, sizeof(md.key)) == -1)
- fatalx(
- "%s IMSG_RECONF_AUTHMD could not get key",
- __func__);
- md.keyid = imsg_get_id(&imsg);
- md_list_add(&niface->auth_md_list,
- md.keyid, md.key);
- break;
- case IMSG_RECONF_END:
- if ((oeconf->flags & OSPFD_FLAG_STUB_ROUTER) !=
- (noeconf->flags & OSPFD_FLAG_STUB_ROUTER))
- stub_changed = 1;
- else
- stub_changed = 0;
- merge_config(oeconf, noeconf);
- noeconf = NULL;
- if (stub_changed)
- orig_rtr_lsa_all(NULL);
- break;
- case IMSG_CTL_KROUTE:
- case IMSG_CTL_KROUTE_ADDR:
- case IMSG_CTL_IFINFO:
- case IMSG_CTL_END:
- control_imsg_relay(&imsg);
- break;
- case IMSG_CONTROLFD:
- if ((fd = imsg_get_fd(&imsg)) == -1)
- fatalx("%s: expected to receive imsg control"
- "fd but didn't receive any", __func__);
- /* Listen on control socket. */
- control_listen(fd);
- if (pledge("stdio inet mcast", NULL) == -1)
- fatal("pledge");
- break;
- default:
- log_debug("ospfe_dispatch_main: error handling imsg %d",
- imsg.hdr.type);
- break;
}
- imsg_free(&imsg);
- }
- if (!shut)
- imsg_event_add(ibuf, imsgbuf_get_userdata(ibuf));
- else {
- /* this pipe is dead, exit asap */
- event_loopexit(NULL);
+ break;
+ case IMSG_IFADDRDEL:
+ if (imsg_get_data(imsg, &ifc, sizeof(ifc)) == -1)
+ fatalx("bad IFADDRADD imsg received");
+
+ LIST_FOREACH(area, &oeconf->area_list, entry) {
+ LIST_FOREACH(iface, &area->iface_list, entry) {
+ if (ifc.ifindex == iface->ifindex &&
+ ifc.addr.s_addr == iface->addr.s_addr) {
+ if_fsm(iface, IF_EVT_DOWN);
+ log_warnx("interface %s:%s "
+ "gone", iface->name,
+ inet_ntoa(iface->addr));
+ break;
+ }
+ }
+ }
+ break;
+ case IMSG_RECONF_CONF:
+ if ((noeconf = malloc(sizeof(*noeconf))) == NULL)
+ fatal(NULL);
+ if (imsg_get_data(imsg, noeconf, sizeof(*noeconf)) == -1)
+ fatalx("bad RECONF_CONF imsg received");
+
+ LIST_INIT(&noeconf->area_list);
+ LIST_INIT(&noeconf->cand_list);
+ break;
+ case IMSG_RECONF_AREA:
+ if ((narea = area_new()) == NULL)
+ fatal(NULL);
+ if (imsg_get_data(imsg, narea, sizeof(*narea)) == -1)
+ fatalx("bad RECONF_AREA imsg received");
+
+ LIST_INIT(&narea->iface_list);
+ LIST_INIT(&narea->nbr_list);
+ RB_INIT(&narea->lsa_tree);
+ SIMPLEQ_INIT(&narea->redist_list);
+
+ LIST_INSERT_HEAD(&noeconf->area_list, narea, entry);
+ break;
+ case IMSG_RECONF_IFACE:
+ if ((niface = malloc(sizeof(*niface))) == NULL)
+ fatal(NULL);
+ if (imsg_get_data(imsg, niface, sizeof(*niface)) == -1)
+ fatalx("bad RECONF_IFACE imsg received");
+
+ LIST_INIT(&niface->nbr_list);
+ TAILQ_INIT(&niface->ls_ack_list);
+ TAILQ_INIT(&niface->auth_md_list);
+ RB_INIT(&niface->lsa_tree);
+
+ niface->area = narea;
+ LIST_INSERT_HEAD(&narea->iface_list, niface, entry);
+ break;
+ case IMSG_RECONF_AUTHMD:
+ if (imsg_get_data(imsg, md.key, sizeof(md.key)) == -1)
+ fatalx("bad RECONF_AUTHMD imsg received");
+ md.keyid = imsg_get_id(imsg);
+ md_list_add(&niface->auth_md_list,
+ md.keyid, md.key);
+ break;
+ case IMSG_RECONF_END:
+ if ((oeconf->flags & OSPFD_FLAG_STUB_ROUTER) !=
+ (noeconf->flags & OSPFD_FLAG_STUB_ROUTER))
+ stub_changed = 1;
+ else
+ stub_changed = 0;
+ merge_config(oeconf, noeconf);
+ noeconf = NULL;
+ if (stub_changed)
+ orig_rtr_lsa_all(NULL);
+ break;
+ case IMSG_CTL_KROUTE:
+ case IMSG_CTL_KROUTE_ADDR:
+ case IMSG_CTL_IFINFO:
+ case IMSG_CTL_END:
+ control_imsg_relay(imsg);
+ break;
+ case IMSG_CONTROLFD:
+ if ((fd = imsg_get_fd(imsg)) == -1)
+ fatalx("expected to receive imsg control fd "
+ "but didn't receive any");
+ /* Listen on control socket. */
+ control_listen(fd);
+ if (pledge("stdio inet mcast", NULL) == -1)
+ fatal("pledge");
+ break;
+ default:
+ log_debug("ospfe_dispatch_main: error handling imsg %d", type);
+ break;
}
}
void
-ospfe_dispatch_rde(int fd, short event, void *arg)
+ospfe_dispatch_rde(struct imsg *imsg, void *arg)
{
struct ibuf buf;
struct lsa_hdr lsa_hdr;
- struct imsgbuf *ibuf = arg;
struct nbr *nbr;
struct lsa_hdr *lhp;
struct lsa_ref *ref;
struct area *area;
struct iface *iface;
struct lsa_entry *le;
- struct imsg imsg;
struct abr_rtr ar;
- int n, noack = 0, shut = 0;
+ uint32_t type, peerid;
+ int noack = 0;
u_int16_t age;
- if (event & EV_READ) {
- if ((n = imsgbuf_read(ibuf)) == -1)
- fatal("imsgbuf_read error");
- if (n == 0) /* connection closed */
- shut = 1;
- }
- if (event & EV_WRITE) {
- if (imsgbuf_write(ibuf) == -1) {
- if (errno == EPIPE) /* connection closed */
- shut = 1;
- else
- fatal("imsgbuf_write");
- }
- }
-
- for (;;) {
- if ((n = imsgbuf_get(ibuf, &imsg)) == -1)
- fatal("ospfe_dispatch_rde: imsgbuf_get error");
- if (n == 0)
+ type = imsg_get_type(imsg);
+ peerid = imsg_get_id(imsg);
+ switch (type) {
+ case IMSG_DD:
+ nbr = nbr_find_peerid(peerid);
+ if (nbr == NULL)
break;
- switch (imsg.hdr.type) {
- case IMSG_DD:
- nbr = nbr_find_peerid(imsg.hdr.peerid);
- if (nbr == NULL)
- break;
-
- /*
- * Ignore imsg when in the wrong state because a
- * NBR_EVT_SEQ_NUM_MIS may have been issued in between.
- * Luckily regetting the DB snapshot acts as a barrier
- * for both state and process synchronisation.
- */
- if ((nbr->state & NBR_STA_FLOOD) == 0)
- break;
+ /*
+ * Ignore imsg when in the wrong state because a
+ * NBR_EVT_SEQ_NUM_MIS may have been issued in between.
+ * Luckily regetting the DB snapshot acts as a barrier
+ * for both state and process synchronisation.
+ */
+ if ((nbr->state & NBR_STA_FLOOD) == 0)
+ break;
- /* put these on my ls_req_list for retrieval */
- lhp = lsa_hdr_new();
- memcpy(lhp, imsg.data, sizeof(*lhp));
- ls_req_list_add(nbr, lhp);
+ /* put these on my ls_req_list for retrieval */
+ lhp = lsa_hdr_new();
+ if (imsg_get_data(imsg, lhp, sizeof(*lhp)) == -1)
+ fatalx("bad DD imsg received");
+ ls_req_list_add(nbr, lhp);
+ break;
+ case IMSG_DD_END:
+ nbr = nbr_find_peerid(peerid);
+ if (nbr == NULL)
break;
- case IMSG_DD_END:
- nbr = nbr_find_peerid(imsg.hdr.peerid);
- if (nbr == NULL)
- break;
- /* see above */
- if ((nbr->state & NBR_STA_FLOOD) == 0)
- break;
+ /* see above */
+ if ((nbr->state & NBR_STA_FLOOD) == 0)
+ break;
- nbr->dd_pending--;
- if (nbr->dd_pending == 0 && nbr->state & NBR_STA_LOAD) {
- if (ls_req_list_empty(nbr))
- nbr_fsm(nbr, NBR_EVT_LOAD_DONE);
- else
- start_ls_req_tx_timer(nbr);
- }
+ nbr->dd_pending--;
+ if (nbr->dd_pending == 0 && nbr->state & NBR_STA_LOAD) {
+ if (ls_req_list_empty(nbr))
+ nbr_fsm(nbr, NBR_EVT_LOAD_DONE);
+ else
+ start_ls_req_tx_timer(nbr);
+ }
+ break;
+ case IMSG_DD_BADLSA:
+ nbr = nbr_find_peerid(peerid);
+ if (nbr == NULL)
break;
- case IMSG_DD_BADLSA:
- nbr = nbr_find_peerid(imsg.hdr.peerid);
- if (nbr == NULL)
- break;
- if (nbr->iface->self == nbr)
- fatalx("ospfe_dispatch_rde: "
- "dummy neighbor got BADREQ");
+ if (nbr->iface->self == nbr)
+ fatalx("ospfe_dispatch_rde: "
+ "dummy neighbor got BADREQ");
- nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS);
+ nbr_fsm(nbr, NBR_EVT_SEQ_NUM_MIS);
+ break;
+ case IMSG_DB_SNAPSHOT:
+ nbr = nbr_find_peerid(peerid);
+ if (nbr == NULL)
+ break;
+ if (nbr->state != NBR_STA_SNAP) /* discard */
break;
- case IMSG_DB_SNAPSHOT:
- nbr = nbr_find_peerid(imsg.hdr.peerid);
- if (nbr == NULL)
- break;
- if (nbr->state != NBR_STA_SNAP) /* discard */
- break;
- /* add LSA header to the neighbor db_sum_list */
- lhp = lsa_hdr_new();
- memcpy(lhp, imsg.data, sizeof(*lhp));
- db_sum_list_add(nbr, lhp);
+ /* add LSA header to the neighbor db_sum_list */
+ lhp = lsa_hdr_new();
+ if (imsg_get_data(imsg, lhp, sizeof(*lhp)) == -1)
+ fatalx("bad DB_SNAPSHOT imsg received");
+ db_sum_list_add(nbr, lhp);
+ break;
+ case IMSG_DB_END:
+ nbr = nbr_find_peerid(peerid);
+ if (nbr == NULL)
break;
- case IMSG_DB_END:
- nbr = nbr_find_peerid(imsg.hdr.peerid);
- if (nbr == NULL)
- break;
- nbr->dd_snapshot = 0;
- if (nbr->state != NBR_STA_SNAP)
- break;
+ nbr->dd_snapshot = 0;
+ if (nbr->state != NBR_STA_SNAP)
+ break;
- /* snapshot done, start tx of dd packets */
- nbr_fsm(nbr, NBR_EVT_SNAP_DONE);
+ /* snapshot done, start tx of dd packets */
+ nbr_fsm(nbr, NBR_EVT_SNAP_DONE);
+ break;
+ case IMSG_LS_FLOOD:
+ nbr = nbr_find_peerid(peerid);
+ if (nbr == NULL)
break;
- case IMSG_LS_FLOOD:
- nbr = nbr_find_peerid(imsg.hdr.peerid);
- if (nbr == NULL)
- break;
- if (imsg_get_ibuf(&imsg, &buf) == -1)
- fatalx("bad LS_FLOOD imsg received");
-
- ref = lsa_cache_add(&buf);
-
- if (ref->hdr.type == LSA_TYPE_EXTERNAL) {
- /*
- * flood on all areas but stub areas and
- * virtual links
- */
- LIST_FOREACH(area, &oeconf->area_list, entry) {
- if (area->stub)
- continue;
- LIST_FOREACH(iface, &area->iface_list,
- entry) {
- noack += lsa_flood(iface, nbr, ref);
- }
- }
- } else if (ref->hdr.type == LSA_TYPE_LINK_OPAQ) {
- /*
- * Flood on interface only
- */
- noack += lsa_flood(nbr->iface, nbr, ref);
- } else {
- /*
- * Flood on all area interfaces. For
- * area 0.0.0.0 include the virtual links.
- */
- area = nbr->iface->area;
- LIST_FOREACH(iface, &area->iface_list, entry) {
- noack += lsa_flood(iface, nbr, ref);
- }
- /* XXX virtual links */
- }
+ if (imsg_get_ibuf(imsg, &buf) == -1)
+ fatalx("bad LS_FLOOD imsg received");
- /* remove from ls_req_list */
- le = ls_req_list_get(nbr, &ref->hdr);
- if (!(nbr->state & NBR_STA_FULL) && le != NULL) {
- ls_req_list_free(nbr, le);
- /*
- * XXX no need to ack requested lsa
- * the problem is that the RFC is very
- * unclear about this.
- */
- noack = 1;
- }
+ ref = lsa_cache_add(&buf);
- if (!noack && nbr->iface != NULL &&
- nbr->iface->self != nbr) {
- if (!(nbr->iface->state & IF_STA_BACKUP) ||
- nbr->iface->dr == nbr) {
- /* delayed ack */
- lhp = lsa_hdr_new();
- memcpy(lhp, &ref->hdr, sizeof(*lhp));
- ls_ack_list_add(nbr->iface, lhp);
- }
+ if (ref->hdr.type == LSA_TYPE_EXTERNAL) {
+ /*
+ * flood on all areas but stub areas and
+ * virtual links
+ */
+ LIST_FOREACH(area, &oeconf->area_list, entry) {
+ if (area->stub)
+ continue;
+ LIST_FOREACH(iface, &area->iface_list,
+ entry) {
+ noack += lsa_flood(iface, nbr, ref);
+ }
}
+ } else if (ref->hdr.type == LSA_TYPE_LINK_OPAQ) {
+ /*
+ * Flood on interface only
+ */
+ noack += lsa_flood(nbr->iface, nbr, ref);
+ } else {
+ /*
+ * Flood on all area interfaces. For
+ * area 0.0.0.0 include the virtual links.
+ */
+ area = nbr->iface->area;
+ LIST_FOREACH(iface, &area->iface_list, entry) {
+ noack += lsa_flood(iface, nbr, ref);
+ }
+ /* XXX virtual links */
+ }
- lsa_cache_put(ref, nbr);
- break;
- case IMSG_LS_UPD:
- case IMSG_LS_SNAP:
+ /* remove from ls_req_list */
+ le = ls_req_list_get(nbr, &ref->hdr);
+ if (!(nbr->state & NBR_STA_FULL) && le != NULL) {
+ ls_req_list_free(nbr, le);
/*
- * IMSG_LS_UPD is used in two cases:
- * 1. as response to ls requests
- * 2. as response to ls updates where the DB
- * is newer then the sent LSA
- * IMSG_LS_SNAP is used in one case:
- * in EXSTART when the LSA has age MaxAge
+ * XXX no need to ack requested lsa
+ * the problem is that the RFC is very
+ * unclear about this.
*/
- if (imsg_get_ibuf(&imsg, &buf) == -1)
- fatalx("bad LS_UPD/SNAP imsg received");
+ noack = 1;
+ }
- nbr = nbr_find_peerid(imsg.hdr.peerid);
- if (nbr == NULL)
- break;
+ if (!noack && nbr->iface != NULL &&
+ nbr->iface->self != nbr) {
+ if (!(nbr->iface->state & IF_STA_BACKUP) ||
+ nbr->iface->dr == nbr) {
+ /* delayed ack */
+ lhp = lsa_hdr_new();
+ memcpy(lhp, &ref->hdr, sizeof(*lhp));
+ ls_ack_list_add(nbr->iface, lhp);
+ }
+ }
- if (nbr->iface->self == nbr)
- break;
+ lsa_cache_put(ref, nbr);
+ break;
+ case IMSG_LS_UPD:
+ case IMSG_LS_SNAP:
+ /*
+ * IMSG_LS_UPD is used in two cases:
+ * 1. as response to ls requests
+ * 2. as response to ls updates where the DB
+ * is newer then the sent LSA
+ * IMSG_LS_SNAP is used in one case:
+ * in EXSTART when the LSA has age MaxAge
+ */
+ if (imsg_get_ibuf(imsg, &buf) == -1)
+ fatalx("bad LS_UPD/SNAP imsg received");
+
+ nbr = nbr_find_peerid(peerid);
+ if (nbr == NULL)
+ break;
- if (imsg.hdr.type == IMSG_LS_SNAP &&
- nbr->state != NBR_STA_SNAP)
- break;
+ if (nbr->iface->self == nbr)
+ break;
- ref = lsa_cache_add(&buf);
- age = ref->hdr.age;
+ if (type == IMSG_LS_SNAP && nbr->state != NBR_STA_SNAP)
+ break;
- if (ntohs(age) >= MAX_AGE)
- /* add to retransmit list */
- ls_retrans_list_add(nbr, ref, 0, 0);
- else
- ls_retrans_list_add(nbr, ref, 0, 1);
+ ref = lsa_cache_add(&buf);
+ age = ntohs(ref->hdr.age);
+
+ if (age >= MAX_AGE)
+ /* add to retransmit list */
+ ls_retrans_list_add(nbr, ref, 0, 0);
+ else
+ ls_retrans_list_add(nbr, ref, 0, 1);
- lsa_cache_put(ref, nbr);
+ lsa_cache_put(ref, nbr);
+ break;
+ case IMSG_LS_ACK:
+ /*
+ * IMSG_LS_ACK is used in two cases:
+ * 1. LSA was a duplicate
+ * 2. LS age is MaxAge and there is no current
+ * instance in the DB plus no neighbor in state
+ * Exchange or Loading
+ */
+ nbr = nbr_find_peerid(peerid);
+ if (nbr == NULL)
break;
- case IMSG_LS_ACK:
- /*
- * IMSG_LS_ACK is used in two cases:
- * 1. LSA was a duplicate
- * 2. LS age is MaxAge and there is no current
- * instance in the DB plus no neighbor in state
- * Exchange or Loading
- */
- nbr = nbr_find_peerid(imsg.hdr.peerid);
- if (nbr == NULL)
- break;
- if (nbr->iface->self == nbr)
- break;
+ if (nbr->iface->self == nbr)
+ break;
- if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(lsa_hdr))
- fatalx("ospfe_dispatch_rde: bad imsg size");
- memcpy(&lsa_hdr, imsg.data, sizeof(lsa_hdr));
+ if (imsg_get_data(imsg, &lsa_hdr, sizeof(lsa_hdr)) == -1)
+ fatalx("bad LS_ACK imsg received");
- /* for case one check for implied acks */
- if (nbr->iface->state & IF_STA_DROTHER)
- if (ls_retrans_list_del(nbr->iface->self,
- &lsa_hdr) == 0)
- break;
- if (ls_retrans_list_del(nbr, &lsa_hdr) == 0)
+ /* for case one check for implied acks */
+ if (nbr->iface->state & IF_STA_DROTHER)
+ if (ls_retrans_list_del(nbr->iface->self,
+ &lsa_hdr) == 0)
break;
+ if (ls_retrans_list_del(nbr, &lsa_hdr) == 0)
+ break;
- /* send a direct acknowledgement */
- send_direct_ack(nbr->iface, nbr->addr, imsg.data,
- imsg.hdr.len - IMSG_HEADER_SIZE);
-
+ /* send a direct acknowledgement */
+ send_direct_ack(nbr->iface, nbr->addr, &lsa_hdr,
+ sizeof(lsa_hdr));
+ break;
+ case IMSG_LS_BADREQ:
+ nbr = nbr_find_peerid(peerid);
+ if (nbr == NULL)
break;
- case IMSG_LS_BADREQ:
- nbr = nbr_find_peerid(imsg.hdr.peerid);
- if (nbr == NULL)
- break;
- if (nbr->iface->self == nbr)
- fatalx("ospfe_dispatch_rde: "
- "dummy neighbor got BADREQ");
+ if (nbr->iface->self == nbr)
+ fatalx("ospfe_dispatch_rde: "
+ "dummy neighbor got BADREQ");
- nbr_fsm(nbr, NBR_EVT_BAD_LS_REQ);
- break;
- case IMSG_ABR_UP:
- memcpy(&ar, imsg.data, sizeof(ar));
+ nbr_fsm(nbr, NBR_EVT_BAD_LS_REQ);
+ break;
+ case IMSG_ABR_UP:
+ if (imsg_get_data(imsg, &ar, sizeof(ar)) == -1)
+ fatalx("bad ABR_UP imsg received");
- if ((iface = find_vlink(&ar)) != NULL &&
- iface->state == IF_STA_DOWN)
- if (if_fsm(iface, IF_EVT_UP)) {
- log_debug("error starting interface %s",
- iface->name);
- }
- break;
- case IMSG_ABR_DOWN:
- memcpy(&ar, imsg.data, sizeof(ar));
+ if ((iface = find_vlink(&ar)) != NULL &&
+ iface->state == IF_STA_DOWN)
+ if (if_fsm(iface, IF_EVT_UP)) {
+ log_debug("error starting interface %s",
+ iface->name);
+ }
+ break;
+ case IMSG_ABR_DOWN:
+ if (imsg_get_data(imsg, &ar, sizeof(ar)) == -1)
+ fatalx("bad ABR_DOWN imsg received");
- if ((iface = find_vlink(&ar)) != NULL &&
- iface->state == IF_STA_POINTTOPOINT)
- if (if_fsm(iface, IF_EVT_DOWN)) {
- log_debug("error stopping interface %s",
- iface->name);
- }
- break;
- case IMSG_CTL_AREA:
- case IMSG_CTL_IFACE:
- case IMSG_CTL_END:
- case IMSG_CTL_SHOW_DATABASE:
- case IMSG_CTL_SHOW_DB_EXT:
- case IMSG_CTL_SHOW_DB_NET:
- case IMSG_CTL_SHOW_DB_RTR:
- case IMSG_CTL_SHOW_DB_SELF:
- case IMSG_CTL_SHOW_DB_SUM:
- case IMSG_CTL_SHOW_DB_ASBR:
- case IMSG_CTL_SHOW_DB_OPAQ:
- case IMSG_CTL_SHOW_RIB:
- case IMSG_CTL_SHOW_SUM:
- case IMSG_CTL_SHOW_SUM_AREA:
- control_imsg_relay(&imsg);
- break;
- default:
- log_debug("ospfe_dispatch_rde: error handling imsg %d",
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- if (!shut)
- imsg_event_add(ibuf, imsgbuf_get_userdata(ibuf));
- else {
- /* this pipe is dead, exit asap */
- event_loopexit(NULL);
+ if ((iface = find_vlink(&ar)) != NULL &&
+ iface->state == IF_STA_POINTTOPOINT)
+ if (if_fsm(iface, IF_EVT_DOWN)) {
+ log_debug("error stopping interface %s",
+ iface->name);
+ }
+ break;
+ case IMSG_CTL_AREA:
+ case IMSG_CTL_IFACE:
+ case IMSG_CTL_END:
+ case IMSG_CTL_SHOW_DATABASE:
+ case IMSG_CTL_SHOW_DB_EXT:
+ case IMSG_CTL_SHOW_DB_NET:
+ case IMSG_CTL_SHOW_DB_RTR:
+ case IMSG_CTL_SHOW_DB_SELF:
+ case IMSG_CTL_SHOW_DB_SUM:
+ case IMSG_CTL_SHOW_DB_ASBR:
+ case IMSG_CTL_SHOW_DB_OPAQ:
+ case IMSG_CTL_SHOW_RIB:
+ case IMSG_CTL_SHOW_SUM:
+ case IMSG_CTL_SHOW_SUM_AREA:
+ control_imsg_relay(imsg);
+ break;
+ default:
+ log_debug("ospfe_dispatch_rde: error handling imsg %d", type);
+ break;
}
}
@@ -883,7 +822,7 @@ orig_rtr_lsa(struct area *area)
rtr_link.data = 0xffffffff;
} else {
rtr_link.id = iface->addr.s_addr &
- iface->mask.s_addr;
+ iface->mask.s_addr;
rtr_link.data = iface->mask.s_addr;
}
rtr_link.type = LINK_TYPE_STUB_NET;
@@ -950,7 +889,7 @@ orig_rtr_lsa(struct area *area)
iface->linkstate == LINK_STATE_DOWN)
rtr_link.metric = MAX_METRIC;
else if (iface->dependon[0] != '\0' &&
- iface->depend_ok == 0)
+ iface->depend_ok == 0)
rtr_link.metric = MAX_METRIC;
else
rtr_link.metric = htons(iface->metric);
@@ -1191,6 +1130,8 @@ ospfe_iface_ctl(struct ctl_conn *c, unsigned int idx)
IMSG_CTL_SHOW_INTERFACE, 0, 0, -1,
ictl, sizeof(struct ctl_iface));
}
+
+ imsg_compose(c->imsgbuf, IMSG_CTL_END, 0, 0, -1, NULL, 0);
}
void
diff --git usr.sbin/ospfd/ospfe.h usr.sbin/ospfd/ospfe.h
index 8483cbef069..64d346ccf61 100644
--- usr.sbin/ospfd/ospfe.h
+++ usr.sbin/ospfd/ospfe.h
@@ -120,11 +120,11 @@ void recv_hello(struct iface *, struct in_addr, u_int32_t,
/* ospfe.c */
pid_t ospfe(struct ospfd_conf *, int[2], int[2], int[2]);
-void ospfe_dispatch_main(int, short, void *);
-void ospfe_dispatch_rde(int, short, void *);
int ospfe_imsg_compose_parent(int, pid_t, void *, u_int16_t);
int ospfe_imsg_compose_rde(int, u_int32_t, pid_t, void *,
u_int16_t);
+int ospfe_imsg_forward_parent(struct imsg *);
+int ospfe_imsg_forward_rde(struct imsg *);
u_int32_t ospfe_router_id(void);
void ospfe_fib_update(int);
void ospfe_iface_ctl(struct ctl_conn *, unsigned int);
diff --git usr.sbin/ospfd/rde.c usr.sbin/ospfd/rde.c
index 4aad371b473..2ae0106d59b 100644
--- usr.sbin/ospfd/rde.c
+++ usr.sbin/ospfd/rde.c
@@ -40,8 +40,8 @@
void rde_sig_handler(int sig, short, void *);
__dead void rde_shutdown(void);
-void rde_dispatch_imsg(int, short, void *);
-void rde_dispatch_parent(int, short, void *);
+void rde_dispatch_imsg(struct imsg *, void *);
+void rde_dispatch_parent(struct imsg *, void *);
void rde_dump_area(struct area *, int, pid_t);
void rde_send_summary(pid_t);
@@ -159,9 +159,9 @@ rde(struct ospfd_conf *xconf, int pipe_parent2rde[2], int pipe_ospfe2rde[2],
close(pipe_parent2ospfe[1]);
if ((imsg_ospfe = imsgev_new(pipe_ospfe2rde[1],
- rde_dispatch_imsg)) == NULL ||
+ rde_dispatch_imsg, ospfd_dispatch_error, NULL)) == NULL ||
(imsg_main = imsgev_new(pipe_parent2rde[1],
- rde_dispatch_parent)) == NULL)
+ rde_dispatch_parent, ospfd_dispatch_error, NULL)) == NULL)
fatal(NULL);
evtimer_set(&rdeconf->ev, spf_timer, rdeconf);
@@ -224,10 +224,8 @@ rde_imsg_compose_ospfe(int type, u_int32_t peerid, pid_t pid, void *data,
}
void
-rde_dispatch_imsg(int fd, short event, void *arg)
+rde_dispatch_imsg(struct imsg *imsg, void *arg)
{
- struct imsgbuf *ibuf = arg;
- struct imsg imsg;
struct in_addr aid;
struct ls_req_hdr req_hdr;
struct lsa_hdr lsa_hdr, *db_hdr;
@@ -237,492 +235,403 @@ rde_dispatch_imsg(int fd, short event, void *arg)
struct area *area;
struct in_addr addr;
struct vertex *v;
- char *buf;
time_t now;
- int n, r, state, self, error, shut = 0, verbose;
- u_int16_t l;
-
- if (event & EV_READ) {
- if ((n = imsgbuf_read(ibuf)) == -1)
- fatal("imsgbuf_read error");
- if (n == 0) /* connection closed */
- shut = 1;
- }
- if (event & EV_WRITE) {
- if (imsgbuf_write(ibuf) == -1) {
- if (errno == EPIPE) /* connection closed */
- shut = 1;
- else
- fatal("imsgbuf_write");
- }
- }
+ size_t len;
+ uint32_t type, peerid;
+ pid_t pid;
+ int r, state, self, error, verbose;
+ uint8_t capa;
clock_gettime(CLOCK_MONOTONIC, &tp);
now = tp.tv_sec;
- for (;;) {
- if ((n = imsgbuf_get(ibuf, &imsg)) == -1)
- fatal("rde_dispatch_imsg: imsgbuf_get error");
- if (n == 0)
- break;
-
- switch (imsg.hdr.type) {
- case IMSG_NEIGHBOR_UP:
- if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(rn))
- fatalx("invalid size of OE request");
- memcpy(&rn, imsg.data, sizeof(rn));
+ type = imsg_get_type(imsg);
+ peerid = imsg_get_id(imsg);
+ pid = imsg_get_pid(imsg);
+ switch (type) {
+ case IMSG_NEIGHBOR_UP:
+ if (imsg_get_data(imsg, &rn, sizeof(rn)) == -1)
+ fatalx("bad NEIGHBOR_UP imsg received");
+
+ if (rde_nbr_new(peerid, &rn) == NULL)
+ fatalx("rde_dispatch_imsg: "
+ "neighbor already exists");
+ break;
+ case IMSG_NEIGHBOR_DOWN:
+ rde_nbr_del(rde_nbr_find(peerid));
+ break;
+ case IMSG_NEIGHBOR_ADDR:
+ if (imsg_get_data(imsg, &addr, sizeof(addr)) == -1)
+ fatalx("bad NEIGHBOR_ADDR imsg received");
- if (rde_nbr_new(imsg.hdr.peerid, &rn) == NULL)
- fatalx("rde_dispatch_imsg: "
- "neighbor already exists");
- break;
- case IMSG_NEIGHBOR_DOWN:
- rde_nbr_del(rde_nbr_find(imsg.hdr.peerid));
+ nbr = rde_nbr_find(peerid);
+ if (nbr == NULL)
break;
- case IMSG_NEIGHBOR_ADDR:
- if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(addr))
- fatalx("invalid size of OE request");
- memcpy(&addr, imsg.data, sizeof(addr));
- nbr = rde_nbr_find(imsg.hdr.peerid);
- if (nbr == NULL)
- break;
+ nbr->addr.s_addr = addr.s_addr;
+ break;
+ case IMSG_NEIGHBOR_CHANGE:
+ if (imsg_get_data(imsg, &state, sizeof(state)) == -1)
+ fatalx("bad NEIGHBOR_CHANGE imsg received");
- nbr->addr.s_addr = addr.s_addr;
+ nbr = rde_nbr_find(peerid);
+ if (nbr == NULL)
break;
- case IMSG_NEIGHBOR_CHANGE:
- if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(state))
- fatalx("invalid size of OE request");
- memcpy(&state, imsg.data, sizeof(state));
- nbr = rde_nbr_find(imsg.hdr.peerid);
- if (nbr == NULL)
- break;
-
- nbr->state = state;
- if (nbr->state & NBR_STA_FULL)
- rde_req_list_free(nbr);
- break;
- case IMSG_NEIGHBOR_CAPA:
- if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(u_int8_t))
- fatalx("invalid size of OE request");
- nbr = rde_nbr_find(imsg.hdr.peerid);
- if (nbr == NULL)
- break;
- nbr->capa_options = *(u_int8_t *)imsg.data;
+ nbr->state = state;
+ if (nbr->state & NBR_STA_FULL)
+ rde_req_list_free(nbr);
+ break;
+ case IMSG_NEIGHBOR_CAPA:
+ if (imsg_get_data(imsg, &capa, sizeof(capa)) == -1)
+ fatalx("bad NEIGHBOR_CAPA imsg received");
+ nbr = rde_nbr_find(peerid);
+ if (nbr == NULL)
break;
- case IMSG_AREA_CHANGE:
- if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(state))
- fatalx("invalid size of OE request");
+ nbr->capa_options = capa;
+ break;
+ case IMSG_AREA_CHANGE:
+ if (imsg_get_data(imsg, &state, sizeof(state)) == -1)
+ fatalx("bad AREA_CHANGE imsg received");
- LIST_FOREACH(area, &rdeconf->area_list, entry) {
- if (area->id.s_addr == imsg.hdr.peerid)
- break;
- }
- if (area == NULL)
+ LIST_FOREACH(area, &rdeconf->area_list, entry) {
+ if (area->id.s_addr == peerid)
break;
- memcpy(&state, imsg.data, sizeof(state));
- area->active = state;
+ }
+ if (area == NULL)
+ break;
+ area->active = state;
+ break;
+ case IMSG_DB_SNAPSHOT:
+ nbr = rde_nbr_find(peerid);
+ if (nbr == NULL)
break;
- case IMSG_DB_SNAPSHOT:
- nbr = rde_nbr_find(imsg.hdr.peerid);
- if (nbr == NULL)
- break;
- lsa_snap(nbr);
+ lsa_snap(nbr);
- imsg_compose(imsg_ospfe, IMSG_DB_END,
- imsg.hdr.peerid, 0, -1, NULL, 0);
+ imsg_compose(imsg_ospfe, IMSG_DB_END, peerid, 0, -1, NULL, 0);
+ break;
+ case IMSG_DD:
+ nbr = rde_nbr_find(peerid);
+ if (nbr == NULL)
break;
- case IMSG_DD:
- nbr = rde_nbr_find(imsg.hdr.peerid);
- if (nbr == NULL)
- break;
-
- buf = imsg.data;
- error = 0;
- for (l = imsg.hdr.len - IMSG_HEADER_SIZE;
- l >= sizeof(lsa_hdr); l -= sizeof(lsa_hdr)) {
- memcpy(&lsa_hdr, buf, sizeof(lsa_hdr));
- buf += sizeof(lsa_hdr);
- if (lsa_hdr.type == LSA_TYPE_EXTERNAL &&
- nbr->area->stub) {
- error = 1;
- break;
- }
- v = lsa_find(nbr->iface, lsa_hdr.type,
- lsa_hdr.ls_id, lsa_hdr.adv_rtr);
- if (v == NULL)
- db_hdr = NULL;
- else
- db_hdr = &v->lsa->hdr;
-
- if (lsa_newer(&lsa_hdr, db_hdr) > 0) {
- /*
- * only request LSAs that are
- * newer or missing
- */
- rde_req_list_add(nbr, &lsa_hdr);
- imsg_compose(imsg_ospfe, IMSG_DD,
- imsg.hdr.peerid, 0, -1, &lsa_hdr,
- sizeof(lsa_hdr));
- }
- }
- if (l != 0 && !error)
+ error = 0;
+ while (imsg_get_len(imsg) > 0) {
+ if (imsg_get_buf(imsg, &lsa_hdr,
+ sizeof(lsa_hdr)) == -1) {
log_warnx("rde_dispatch_imsg: peerid %u, "
"trailing garbage in Database Description "
- "packet", imsg.hdr.peerid);
-
- if (!error)
- imsg_compose(imsg_ospfe, IMSG_DD_END,
- imsg.hdr.peerid, 0, -1, NULL, 0);
- else
- imsg_compose(imsg_ospfe, IMSG_DD_BADLSA,
- imsg.hdr.peerid, 0, -1, NULL, 0);
- break;
- case IMSG_LS_REQ:
- nbr = rde_nbr_find(imsg.hdr.peerid);
- if (nbr == NULL)
+ "packet", peerid);
+ error = 1;
break;
-
- buf = imsg.data;
- for (l = imsg.hdr.len - IMSG_HEADER_SIZE;
- l >= sizeof(req_hdr); l -= sizeof(req_hdr)) {
- memcpy(&req_hdr, buf, sizeof(req_hdr));
- buf += sizeof(req_hdr);
-
- if ((v = lsa_find(nbr->iface,
- ntohl(req_hdr.type), req_hdr.ls_id,
- req_hdr.adv_rtr)) == NULL) {
- log_debug("rde_dispatch_imsg: "
- "requested LSA not found");
- imsg_compose(imsg_ospfe,
- IMSG_LS_BADREQ, imsg.hdr.peerid,
- 0, -1, NULL, 0);
- continue;
- }
- imsg_compose(imsg_ospfe, IMSG_LS_UPD,
- imsg.hdr.peerid, 0, -1, v->lsa,
- ntohs(v->lsa->hdr.len));
}
- if (l != 0)
- log_warnx("rde_dispatch_imsg: peerid %u, "
- "trailing garbage in LS Request "
- "packet", imsg.hdr.peerid);
- break;
- case IMSG_LS_UPD:
- nbr = rde_nbr_find(imsg.hdr.peerid);
- if (nbr == NULL)
- break;
-
- lsa = malloc(imsg.hdr.len - IMSG_HEADER_SIZE);
- if (lsa == NULL)
- fatal(NULL);
- memcpy(lsa, imsg.data, imsg.hdr.len - IMSG_HEADER_SIZE);
- if (!lsa_check(nbr, lsa,
- imsg.hdr.len - IMSG_HEADER_SIZE)) {
- free(lsa);
+ if (lsa_hdr.type == LSA_TYPE_EXTERNAL &&
+ nbr->area->stub) {
+ error = 1;
break;
}
-
- v = lsa_find(nbr->iface, lsa->hdr.type, lsa->hdr.ls_id,
- lsa->hdr.adv_rtr);
+ v = lsa_find(nbr->iface, lsa_hdr.type,
+ lsa_hdr.ls_id, lsa_hdr.adv_rtr);
if (v == NULL)
db_hdr = NULL;
else
db_hdr = &v->lsa->hdr;
- if (nbr->self) {
- lsa_merge(nbr, lsa, v);
- /* lsa_merge frees the right lsa */
- break;
- }
-
- r = lsa_newer(&lsa->hdr, db_hdr);
- if (r > 0) {
- /* new LSA newer than DB */
- if (v && v->flooded &&
- v->changed + MIN_LS_ARRIVAL >= now) {
- free(lsa);
- break;
- }
-
- rde_req_list_del(nbr, &lsa->hdr);
-
- if (!(self = lsa_self(nbr, lsa, v)))
- if (lsa_add(nbr, lsa))
- /* delayed lsa */
- break;
-
- /* flood and perhaps ack LSA */
- imsg_compose(imsg_ospfe, IMSG_LS_FLOOD,
- imsg.hdr.peerid, 0, -1, lsa,
- ntohs(lsa->hdr.len));
-
- /* reflood self originated LSA */
- if (self && v)
- imsg_compose(imsg_ospfe,
- IMSG_LS_FLOOD, v->peerid, 0, -1,
- v->lsa, ntohs(v->lsa->hdr.len));
- /* new LSA was not added so free it */
- if (self)
- free(lsa);
- } else if (r < 0) {
+ if (lsa_newer(&lsa_hdr, db_hdr) > 0) {
/*
- * point 6 of "The Flooding Procedure"
- * We are violating the RFC here because
- * it does not make sense to reset a session
- * because an equal LSA is already in the table.
- * Only if the LSA sent is older than the one
- * in the table we should reset the session.
+ * only request LSAs that are
+ * newer or missing
*/
- if (rde_req_list_exists(nbr, &lsa->hdr)) {
- imsg_compose(imsg_ospfe,
- IMSG_LS_BADREQ, imsg.hdr.peerid,
- 0, -1, NULL, 0);
- free(lsa);
- break;
- }
+ rde_req_list_add(nbr, &lsa_hdr);
+ imsg_compose(imsg_ospfe, IMSG_DD, peerid,
+ 0, -1, &lsa_hdr, sizeof(lsa_hdr));
+ }
+ }
+ if (!error)
+ imsg_compose(imsg_ospfe, IMSG_DD_END,
+ peerid, 0, -1, NULL, 0);
+ else
+ imsg_compose(imsg_ospfe, IMSG_DD_BADLSA,
+ peerid, 0, -1, NULL, 0);
+ break;
+ case IMSG_LS_REQ:
+ nbr = rde_nbr_find(peerid);
+ if (nbr == NULL)
+ break;
- /* lsa no longer needed */
- free(lsa);
+ while (imsg_get_len(imsg) > 0) {
+ if (imsg_get_buf(imsg, &req_hdr,
+ sizeof(req_hdr)) == -1) {
+ log_warnx("rde_dispatch_imsg: peerid %u, "
+ "trailing garbage in LS Request "
+ "packet", peerid);
+ break;
+ }
- /* new LSA older than DB */
- if (ntohl(db_hdr->seq_num) == MAX_SEQ_NUM &&
- ntohs(db_hdr->age) == MAX_AGE)
- /* seq-num wrap */
- break;
+ if ((v = lsa_find(nbr->iface,
+ ntohl(req_hdr.type), req_hdr.ls_id,
+ req_hdr.adv_rtr)) == NULL) {
+ log_debug("LS_REQ imsg: "
+ "requested LSA not found");
+ imsg_compose(imsg_ospfe,
+ IMSG_LS_BADREQ, peerid, 0, -1, NULL, 0);
+ continue;
+ }
+ imsg_compose(imsg_ospfe, IMSG_LS_UPD, peerid, 0, -1,
+ v->lsa, ntohs(v->lsa->hdr.len));
+ }
+ break;
+ case IMSG_LS_UPD:
+ nbr = rde_nbr_find(peerid);
+ if (nbr == NULL)
+ break;
- if (v->changed + MIN_LS_ARRIVAL >= now)
- break;
+ len = imsg_get_len(imsg);
+ if ((lsa = malloc(len)) == NULL)
+ fatal(NULL);
+ if (imsg_get_data(imsg, lsa, len) == -1)
+ fatalx("bad LS_UPD imsg received");
- /* directly send current LSA, no ack */
- imsg_compose(imsg_ospfe, IMSG_LS_UPD,
- imsg.hdr.peerid, 0, -1, v->lsa,
- ntohs(v->lsa->hdr.len));
- } else {
- /* LSA equal send direct ack */
- imsg_compose(imsg_ospfe, IMSG_LS_ACK,
- imsg.hdr.peerid, 0, -1, &lsa->hdr,
- sizeof(lsa->hdr));
- free(lsa);
- }
+ if (!lsa_check(nbr, lsa, len)) {
+ free(lsa);
break;
- case IMSG_LS_MAXAGE:
- nbr = rde_nbr_find(imsg.hdr.peerid);
- if (nbr == NULL)
- break;
+ }
- if (imsg.hdr.len != IMSG_HEADER_SIZE +
- sizeof(struct lsa_hdr))
- fatalx("invalid size of OE request");
- memcpy(&lsa_hdr, imsg.data, sizeof(lsa_hdr));
+ v = lsa_find(nbr->iface, lsa->hdr.type, lsa->hdr.ls_id,
+ lsa->hdr.adv_rtr);
+ if (v == NULL)
+ db_hdr = NULL;
+ else
+ db_hdr = &v->lsa->hdr;
- if (rde_nbr_loading(nbr->area))
+ if (nbr->self) {
+ lsa_merge(nbr, lsa, v);
+ /* lsa_merge frees the right lsa */
+ break;
+ }
+
+ r = lsa_newer(&lsa->hdr, db_hdr);
+ if (r > 0) {
+ /* new LSA newer than DB */
+ if (v && v->flooded &&
+ v->changed + MIN_LS_ARRIVAL >= now) {
+ free(lsa);
break;
+ }
- v = lsa_find(nbr->iface, lsa_hdr.type, lsa_hdr.ls_id,
- lsa_hdr.adv_rtr);
- if (v == NULL)
- db_hdr = NULL;
- else
- db_hdr = &v->lsa->hdr;
+ rde_req_list_del(nbr, &lsa->hdr);
+
+ if (!(self = lsa_self(nbr, lsa, v)))
+ if (lsa_add(nbr, lsa))
+ /* delayed lsa */
+ break;
+ /* flood and perhaps ack LSA */
+ imsg_compose(imsg_ospfe, IMSG_LS_FLOOD,
+ peerid, 0, -1, lsa, ntohs(lsa->hdr.len));
+
+ /* reflood self originated LSA */
+ if (self && v)
+ imsg_compose(imsg_ospfe,
+ IMSG_LS_FLOOD, v->peerid, 0, -1,
+ v->lsa, ntohs(v->lsa->hdr.len));
+ /* new LSA was not added so free it */
+ if (self)
+ free(lsa);
+ } else if (r < 0) {
/*
- * only delete LSA if the one in the db is not newer
+ * point 6 of "The Flooding Procedure"
+ * We are violating the RFC here because
+ * it does not make sense to reset a session
+ * because an equal LSA is already in the table.
+ * Only if the LSA sent is older than the one
+ * in the table we should reset the session.
*/
- if (lsa_newer(db_hdr, &lsa_hdr) <= 0)
- lsa_del(nbr, &lsa_hdr);
- break;
- case IMSG_CTL_SHOW_DATABASE:
- case IMSG_CTL_SHOW_DB_EXT:
- case IMSG_CTL_SHOW_DB_NET:
- case IMSG_CTL_SHOW_DB_RTR:
- case IMSG_CTL_SHOW_DB_SELF:
- case IMSG_CTL_SHOW_DB_SUM:
- case IMSG_CTL_SHOW_DB_ASBR:
- case IMSG_CTL_SHOW_DB_OPAQ:
- if (imsg.hdr.len != IMSG_HEADER_SIZE &&
- imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(aid)) {
- log_warnx("rde_dispatch_imsg: wrong imsg len");
+ if (rde_req_list_exists(nbr, &lsa->hdr)) {
+ imsg_compose(imsg_ospfe,
+ IMSG_LS_BADREQ, peerid, 0, -1, NULL, 0);
+ free(lsa);
break;
}
- if (imsg.hdr.len == IMSG_HEADER_SIZE) {
- LIST_FOREACH(area, &rdeconf->area_list, entry) {
- rde_dump_area(area, imsg.hdr.type,
- imsg.hdr.pid);
- }
- lsa_dump(&asext_tree, imsg.hdr.type,
- imsg.hdr.pid);
- } else {
- memcpy(&aid, imsg.data, sizeof(aid));
- if ((area = area_find(rdeconf, aid)) != NULL) {
- rde_dump_area(area, imsg.hdr.type,
- imsg.hdr.pid);
- if (!area->stub)
- lsa_dump(&asext_tree,
- imsg.hdr.type,
- imsg.hdr.pid);
- }
- }
- imsg_compose(imsg_ospfe, IMSG_CTL_END, 0,
- imsg.hdr.pid, -1, NULL, 0);
- break;
- case IMSG_CTL_SHOW_RIB:
- LIST_FOREACH(area, &rdeconf->area_list, entry) {
- imsg_compose(imsg_ospfe, IMSG_CTL_AREA,
- 0, imsg.hdr.pid, -1,
- &area->id, sizeof(area->id));
- rt_dump(area->id, imsg.hdr.pid, RIB_RTR);
- rt_dump(area->id, imsg.hdr.pid, RIB_NET);
- }
- aid.s_addr = 0;
- rt_dump(aid, imsg.hdr.pid, RIB_EXT);
+ /* lsa no longer needed */
+ free(lsa);
- imsg_compose(imsg_ospfe, IMSG_CTL_END, 0,
- imsg.hdr.pid, -1, NULL, 0);
- break;
- case IMSG_CTL_SHOW_SUM:
- rde_send_summary(imsg.hdr.pid);
- LIST_FOREACH(area, &rdeconf->area_list, entry)
- rde_send_summary_area(area, imsg.hdr.pid);
- imsg_compose(imsg_ospfe, IMSG_CTL_END, 0,
- imsg.hdr.pid, -1, NULL, 0);
- break;
- case IMSG_CTL_LOG_VERBOSE:
- if (imsg_get_data(&imsg, &verbose, sizeof(verbose)) ==
- -1)
- log_warn("wrong imsg len");
- else
- log_setverbose(verbose);
- break;
- default:
- log_debug("rde_dispatch_imsg: unexpected imsg %d",
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- if (!shut)
- imsg_event_add(ibuf, imsgbuf_get_userdata(ibuf));
- else {
- /* this pipe is dead, exit asap */
- event_loopexit(NULL);
- }
-}
+ /* new LSA older than DB */
+ if (ntohl(db_hdr->seq_num) == MAX_SEQ_NUM &&
+ ntohs(db_hdr->age) == MAX_AGE)
+ /* seq-num wrap */
+ break;
-void
-rde_dispatch_parent(int fd, short event, void *arg)
-{
- static struct area *narea;
- struct iface *niface;
- struct imsg imsg;
- struct kroute rr;
- struct imsgbuf *ibuf = arg;
- struct redistribute *nred;
- int n, shut = 0;
+ if (v->changed + MIN_LS_ARRIVAL >= now)
+ break;
- if (event & EV_READ) {
- if ((n = imsgbuf_read(ibuf)) == -1)
- fatal("imsgbuf_read error");
- if (n == 0) /* connection closed */
- shut = 1;
- }
- if (event & EV_WRITE) {
- if (imsgbuf_write(ibuf) == -1) {
- if (errno == EPIPE) /* connection closed */
- shut = 1;
- else
- fatal("imsgbuf_write");
+ /* directly send current LSA, no ack */
+ imsg_compose(imsg_ospfe, IMSG_LS_UPD,
+ peerid, 0, -1, v->lsa, ntohs(v->lsa->hdr.len));
+ } else {
+ /* LSA equal send direct ack */
+ imsg_compose(imsg_ospfe, IMSG_LS_ACK, peerid, 0, -1,
+ &lsa->hdr, sizeof(lsa->hdr));
+ free(lsa);
}
- }
+ break;
+ case IMSG_LS_MAXAGE:
+ nbr = rde_nbr_find(peerid);
+ if (nbr == NULL)
+ break;
+
+ if (imsg_get_data(imsg, &lsa_hdr, sizeof(lsa_hdr)) == -1)
+ fatalx("bad LS_MAXAGE imsg received");
- for (;;) {
- if ((n = imsgbuf_get(ibuf, &imsg)) == -1)
- fatal("rde_dispatch_parent: imsgbuf_get error");
- if (n == 0)
+ if (rde_nbr_loading(nbr->area))
break;
- switch (imsg.hdr.type) {
- case IMSG_NETWORK_ADD:
- if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(rr)) {
- log_warnx("rde_dispatch_parent: "
- "wrong imsg len");
- break;
+ v = lsa_find(nbr->iface, lsa_hdr.type, lsa_hdr.ls_id,
+ lsa_hdr.adv_rtr);
+ if (v == NULL)
+ db_hdr = NULL;
+ else
+ db_hdr = &v->lsa->hdr;
+
+ /*
+ * only delete LSA if the one in the db is not newer
+ */
+ if (lsa_newer(db_hdr, &lsa_hdr) <= 0)
+ lsa_del(nbr, &lsa_hdr);
+ break;
+ case IMSG_CTL_SHOW_DATABASE:
+ case IMSG_CTL_SHOW_DB_EXT:
+ case IMSG_CTL_SHOW_DB_NET:
+ case IMSG_CTL_SHOW_DB_RTR:
+ case IMSG_CTL_SHOW_DB_SELF:
+ case IMSG_CTL_SHOW_DB_SUM:
+ case IMSG_CTL_SHOW_DB_ASBR:
+ case IMSG_CTL_SHOW_DB_OPAQ:
+ if (imsg_get_len(imsg) == 0) {
+ LIST_FOREACH(area, &rdeconf->area_list, entry) {
+ rde_dump_area(area, type, pid);
}
- memcpy(&rr, imsg.data, sizeof(rr));
- rde_asext_get(&rr);
- break;
- case IMSG_NETWORK_DEL:
- if (imsg.hdr.len != IMSG_HEADER_SIZE + sizeof(rr)) {
- log_warnx("rde_dispatch_parent: "
- "wrong imsg len");
+ lsa_dump(&asext_tree, type, pid);
+ } else {
+ if (imsg_get_data(imsg, &aid, sizeof(aid)) == -1) {
+ log_warnx("bad control imsg received");
break;
}
- memcpy(&rr, imsg.data, sizeof(rr));
- rde_asext_put(&rr);
- break;
- case IMSG_RECONF_CONF:
- if ((nconf = malloc(sizeof(struct ospfd_conf))) ==
- NULL)
- fatal(NULL);
- memcpy(nconf, imsg.data, sizeof(struct ospfd_conf));
-
- LIST_INIT(&nconf->area_list);
- LIST_INIT(&nconf->cand_list);
- break;
- case IMSG_RECONF_AREA:
- if ((narea = area_new()) == NULL)
- fatal(NULL);
- memcpy(narea, imsg.data, sizeof(struct area));
-
- LIST_INIT(&narea->iface_list);
- LIST_INIT(&narea->nbr_list);
- RB_INIT(&narea->lsa_tree);
- SIMPLEQ_INIT(&narea->redist_list);
-
- LIST_INSERT_HEAD(&nconf->area_list, narea, entry);
- break;
- case IMSG_RECONF_REDIST:
- if ((nred= malloc(sizeof(struct redistribute))) == NULL)
- fatal(NULL);
- memcpy(nred, imsg.data, sizeof(struct redistribute));
+ if ((area = area_find(rdeconf, aid)) != NULL) {
+ rde_dump_area(area, type, pid);
+ if (!area->stub)
+ lsa_dump(&asext_tree, type, pid);
+ }
+ }
+ imsg_compose(imsg_ospfe, IMSG_CTL_END, 0, pid, -1, NULL, 0);
+ break;
+ case IMSG_CTL_SHOW_RIB:
+ LIST_FOREACH(area, &rdeconf->area_list, entry) {
+ imsg_compose(imsg_ospfe, IMSG_CTL_AREA,
+ 0, pid, -1, &area->id, sizeof(area->id));
- SIMPLEQ_INSERT_TAIL(&narea->redist_list, nred, entry);
- break;
- case IMSG_RECONF_IFACE:
- if ((niface = malloc(sizeof(struct iface))) == NULL)
- fatal(NULL);
- memcpy(niface, imsg.data, sizeof(struct iface));
+ rt_dump(area->id, pid, RIB_RTR);
+ rt_dump(area->id, pid, RIB_NET);
+ }
+ aid.s_addr = 0;
+ rt_dump(aid, pid, RIB_EXT);
- LIST_INIT(&niface->nbr_list);
- TAILQ_INIT(&niface->ls_ack_list);
- TAILQ_INIT(&niface->auth_md_list);
- RB_INIT(&niface->lsa_tree);
+ imsg_compose(imsg_ospfe, IMSG_CTL_END, 0, pid, -1, NULL, 0);
+ break;
+ case IMSG_CTL_SHOW_SUM:
+ rde_send_summary(pid);
+ LIST_FOREACH(area, &rdeconf->area_list, entry)
+ rde_send_summary_area(area, pid);
+ imsg_compose(imsg_ospfe, IMSG_CTL_END, 0, pid, -1, NULL, 0);
+ break;
+ case IMSG_CTL_LOG_VERBOSE:
+ if (imsg_get_data(imsg, &verbose, sizeof(verbose)) ==
+ -1)
+ log_warn("wrong imsg len");
+ else
+ log_setverbose(verbose);
+ break;
+ default:
+ log_debug("rde_dispatch_imsg: unexpected imsg %d", type);
+ break;
+ }
+}
- niface->area = narea;
- LIST_INSERT_HEAD(&narea->iface_list, niface, entry);
+void
+rde_dispatch_parent(struct imsg *imsg, void *arg)
+{
+ static struct area *narea;
+ struct iface *niface;
+ struct redistribute *nred;
+ struct kroute rr;
+ uint32_t type;
+
+ type = imsg_get_type(imsg);
+ switch (type) {
+ case IMSG_NETWORK_ADD:
+ if (imsg_get_data(imsg, &rr, sizeof(rr)) == -1)
+ fatalx("bad NETWORK_ADD imsg received");
+ rde_asext_get(&rr);
+ break;
+ case IMSG_NETWORK_DEL:
+ if (imsg_get_data(imsg, &rr, sizeof(rr)) == -1)
+ fatalx("bad NETWORK_DEL imsg received");
+ rde_asext_put(&rr);
+ break;
+ case IMSG_RECONF_CONF:
+ if ((nconf = malloc(sizeof(struct ospfd_conf))) == NULL)
+ fatal(NULL);
+ if (imsg_get_data(imsg, nconf, sizeof(*nconf)) == -1)
+ fatalx("bad RECONF_CONF imsg received");
+
+ LIST_INIT(&nconf->area_list);
+ LIST_INIT(&nconf->cand_list);
+ break;
+ case IMSG_RECONF_AREA:
+ if ((narea = area_new()) == NULL)
+ fatal(NULL);
+ if (imsg_get_data(imsg, narea, sizeof(*narea)) == -1)
+ fatalx("bad RECONF_AREA imsg received");
+
+ LIST_INIT(&narea->iface_list);
+ LIST_INIT(&narea->nbr_list);
+ RB_INIT(&narea->lsa_tree);
+ SIMPLEQ_INIT(&narea->redist_list);
+
+ LIST_INSERT_HEAD(&nconf->area_list, narea, entry);
+ break;
+ case IMSG_RECONF_REDIST:
+ if ((nred= malloc(sizeof(struct redistribute))) == NULL)
+ fatal(NULL);
+ if (imsg_get_data(imsg, nred, sizeof(*nred)) == -1)
+ fatalx("bad RECONF_REDIST imsg received");
- break;
- case IMSG_RECONF_END:
- merge_config(rdeconf, nconf);
- nconf = NULL;
- break;
- default:
- log_debug("rde_dispatch_parent: unexpected imsg %d",
- imsg.hdr.type);
- break;
- }
- imsg_free(&imsg);
- }
- if (!shut)
- imsg_event_add(ibuf, imsgbuf_get_userdata(ibuf));
- else {
- /* this pipe is dead, exit asap */
- event_loopexit(NULL);
+ SIMPLEQ_INSERT_TAIL(&narea->redist_list, nred, entry);
+ break;
+ case IMSG_RECONF_IFACE:
+ if ((niface = malloc(sizeof(struct iface))) == NULL)
+ fatal(NULL);
+ if (imsg_get_data(imsg, niface, sizeof(*niface)) == -1)
+ fatalx("bad RECONF_IFACE imsg received");
+
+ LIST_INIT(&niface->nbr_list);
+ TAILQ_INIT(&niface->ls_ack_list);
+ TAILQ_INIT(&niface->auth_md_list);
+ RB_INIT(&niface->lsa_tree);
+
+ niface->area = narea;
+ LIST_INSERT_HEAD(&narea->iface_list, niface, entry);
+ break;
+ case IMSG_RECONF_END:
+ merge_config(rdeconf, nconf);
+ nconf = NULL;
+ break;
+ default:
+ log_debug("rde_dispatch_parent: unexpected imsg %d", type);
+ break;
}
}
@@ -1205,7 +1114,7 @@ rde_asext_get(struct kroute *kr)
/* lsa to insert is more specific, fix other lsa */
mask = v->lsa->data.asext.mask;
oan = asext_find(v->lsa->hdr.ls_id & mask,
- mask2prefixlen(mask));
+ mask2prefixlen(mask));
if (oan == NULL)
fatalx("as-ext LSA DB corrupted");
}
ospfd: rewrite the imsg handling part 2