Still working towards bringing ospf6d and ospfd closer.

area is now part of struct iface.
redist_list is part of struct area.

Some changes, related to reloading, are not in use now but it feels like the
right time to get it in.

Denis

Index: area.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/area.c,v
retrieving revision 1.4
diff -u -p -r1.4 area.c
--- area.c      28 Dec 2008 20:08:31 -0000      1.4
+++ area.c      13 Dec 2019 22:24:09 -0000
@@ -39,6 +39,7 @@ area_new(void)
        LIST_INIT(&area->iface_list);
        LIST_INIT(&area->nbr_list);
        RB_INIT(&area->lsa_tree);
+       SIMPLEQ_INIT(&area->redist_list);
 
        return (area);
 }
@@ -46,9 +47,10 @@ area_new(void)
 int
 area_del(struct area *area)
 {
-       struct iface    *iface = NULL;
-       struct vertex   *v, *nv;
-       struct rde_nbr  *n;
+       struct iface            *iface = NULL;
+       struct vertex           *v, *nv;
+       struct rde_nbr          *n;
+       struct redistribute     *r;
 
        /* area is removed so neutralize the demotion done by the area */
        if (area->active == 0)
@@ -68,6 +70,11 @@ area_del(struct area *area)
                vertex_free(v);
        }
 
+       while ((r = SIMPLEQ_FIRST(&area->redist_list)) != NULL) {
+               SIMPLEQ_REMOVE_HEAD(&area->redist_list, entry);
+               free(r);
+       }
+
        free(area);
 
        return (0);
@@ -88,19 +95,24 @@ area_find(struct ospfd_conf *conf, struc
 }
 
 void
-area_track(struct area *area, int state)
+area_track(struct area *area)
 {
-       int     old = area->active;
+       int              old = area->active;
+       struct iface    *iface;
 
-       if (state & NBR_STA_FULL)
-               area->active++;
-       else if (area->active == 0)
-               fatalx("area_track: area already inactive");
-       else
-               area->active--;
+       area->active = 0;
+       LIST_FOREACH(iface, &area->iface_list, entry) {
+               if (iface->state & IF_STA_DOWN)
+                       continue;
+               area->active = 1;
+               break;
+       }
 
-       if (area->active == 0 || old == 0)
+       if (area->active != old) {
+               ospfe_imsg_compose_rde(IMSG_AREA_CHANGE, area->id.s_addr, 0,
+                   &area->active, sizeof(area->active));
                ospfe_demote_area(area, old == 0);
+       }
 }
 
 int
@@ -110,7 +122,7 @@ area_border_router(struct ospfd_conf *co
        int              active = 0;
 
        LIST_FOREACH(area, &conf->area_list, entry)
-               if (area->active > 0)
+               if (area->active)
                        active++;
 
        return (active > 1);
@@ -124,5 +136,5 @@ area_ospf_options(struct area *area)
        if (area && !area->stub)
                opt |= OSPF_OPTION_E;
 
-       return opt;
+       return (opt);
 }
Index: database.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/database.c,v
retrieving revision 1.17
diff -u -p -r1.17 database.c
--- database.c  11 Dec 2019 21:33:56 -0000      1.17
+++ database.c  13 Dec 2019 22:24:09 -0000
@@ -135,7 +135,7 @@ send_db_description(struct nbr *nbr)
        }
 
        dd_hdr.opts = htonl(area_ospf_options(area_find(oeconf,
-           nbr->iface->area_id)));
+           nbr->iface->area->id)));
        dd_hdr.bits = bits;
        dd_hdr.dd_seq_num = htonl(nbr->dd_seq_num);
 
Index: hello.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/hello.c,v
retrieving revision 1.19
diff -u -p -r1.19 hello.c
--- hello.c     11 Dec 2019 21:33:56 -0000      1.19
+++ hello.c     13 Dec 2019 22:24:09 -0000
@@ -72,7 +72,7 @@ send_hello(struct iface *iface)
        /* hello header */
        hello.iface_id = htonl(iface->ifindex);
        LSA_24_SETHI(hello.opts, iface->priority);
-       opts = area_ospf_options(area_find(oeconf, iface->area_id));
+       opts = area_ospf_options(iface->area);
        LSA_24_SETLO(hello.opts, opts);
        hello.opts = htonl(hello.opts);
 
@@ -120,7 +120,6 @@ recv_hello(struct iface *iface, struct i
 {
        struct hello_hdr         hello;
        struct nbr              *nbr = NULL, *dr;
-       struct area             *area;
        u_int32_t                nbr_id, opts;
        int                      nbr_change = 0;
 
@@ -148,12 +147,12 @@ recv_hello(struct iface *iface, struct i
                return;
        }
 
-       if ((area = area_find(oeconf, iface->area_id)) == NULL)
+       if (iface->area == NULL)
                fatalx("interface lost area");
 
        opts = LSA_24_GETLO(ntohl(hello.opts));
-       if ((opts & OSPF_OPTION_E && area->stub) ||
-           ((opts & OSPF_OPTION_E) == 0 && !area->stub)) {
+       if ((opts & OSPF_OPTION_E && iface->area->stub) ||
+           ((opts & OSPF_OPTION_E) == 0 && !iface->area->stub)) {
                log_warnx("recv_hello: ExternalRoutingCapability mismatch, "
                    "interface %s", iface->name);
                return;
Index: interface.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/interface.c,v
retrieving revision 1.25
diff -u -p -r1.25 interface.c
--- interface.c 28 Jun 2019 13:32:49 -0000      1.25
+++ interface.c 13 Dec 2019 22:24:10 -0000
@@ -649,7 +649,7 @@ if_to_ctl(struct iface *iface)
        memcpy(ictl.name, iface->name, sizeof(ictl.name));
        memcpy(&ictl.addr, &iface->addr, sizeof(ictl.addr));
        ictl.rtr_id.s_addr = ospfe_router_id();
-       memcpy(&ictl.area, &iface->area_id, sizeof(ictl.area));
+       memcpy(&ictl.area, &iface->area->id, sizeof(ictl.area));
        if (iface->dr) {
                memcpy(&ictl.dr_id, &iface->dr->id, sizeof(ictl.dr_id));
                memcpy(&ictl.dr_addr, &iface->dr->addr, sizeof(ictl.dr_addr));
Index: kroute.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/kroute.c,v
retrieving revision 1.61
diff -u -p -r1.61 kroute.c
--- kroute.c    12 Dec 2019 08:21:34 -0000      1.61
+++ kroute.c    13 Dec 2019 22:24:10 -0000
@@ -97,10 +97,11 @@ RB_PROTOTYPE(kroute_tree, kroute_node, e
 RB_GENERATE(kroute_tree, kroute_node, entry, kroute_compare)
 
 int
-kr_init(int fs, u_int rdomain, u_int8_t fib_prio)
+kr_init(int fs, u_int rdomain, int redis_label_or_prefix, u_int8_t fib_prio)
 {
        int             opt = 0, rcvbuf, default_rcvbuf;
        socklen_t       optlen;
+       int             filter_prio = fib_prio;
 
        kr_state.fib_sync = fs;
        kr_state.rdomain = rdomain;
@@ -117,6 +118,18 @@ kr_init(int fs, u_int rdomain, u_int8_t 
            &opt, sizeof(opt)) == -1)
                log_warn("kr_init: setsockopt");        /* not fatal */
 
+       if (redis_label_or_prefix) {
+               filter_prio = 0;
+               log_info("%s: priority filter disabled", __func__);
+       } else
+               log_debug("%s: priority filter enabled", __func__);
+
+       if (setsockopt(kr_state.fd, AF_ROUTE, ROUTE_PRIOFILTER, &filter_prio,
+           sizeof(filter_prio)) == -1) {
+               log_warn("%s: setsockopt AF_ROUTE ROUTE_PRIOFILTER", __func__);
+               /* not fatal */
+       }
+
        /* grow receive buffer, don't wanna miss messages */
        optlen = sizeof(default_rcvbuf);
        if (getsockopt(kr_state.fd, SOL_SOCKET, SO_RCVBUF,
@@ -522,11 +535,25 @@ kr_redistribute(struct kroute_node *kh)
 }
 
 void
-kr_reload(void)
+kr_reload(int redis_label_or_prefix)
 {
        struct kroute_node      *kr, *kn;
        u_int32_t                dummy;
        int                      r;
+       int                      filter_prio = kr_state.fib_prio;
+
+       /* update the priority filter */
+       if (redis_label_or_prefix) {
+               filter_prio = 0;
+               log_info("%s: priority filter disabled", __func__);
+       } else
+               log_debug("%s: priority filter enabled", __func__);
+
+       if (setsockopt(kr_state.fd, AF_ROUTE, ROUTE_PRIOFILTER, &filter_prio,
+           sizeof(filter_prio)) == -1) {
+               log_warn("%s: setsockopt AF_ROUTE ROUTE_PRIOFILTER", __func__);
+               /* not fatal */
+       }
 
        RB_FOREACH(kr, kroute_tree, &krt) {
                for (kn = kr; kn; kn = kn->next) {
Index: neighbor.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/neighbor.c,v
retrieving revision 1.14
diff -u -p -r1.14 neighbor.c
--- neighbor.c  9 Feb 2018 03:53:37 -0000       1.14
+++ neighbor.c  13 Dec 2019 22:24:10 -0000
@@ -202,8 +202,7 @@ nbr_fsm(struct nbr *nbr, enum nbr_event 
                         * neighbor changed from/to FULL
                         * originate new rtr and net LSA
                         */
-                       area_track(area_find(oeconf, nbr->iface->area_id),
-                           nbr->state);
+                       area_track(nbr->iface->area);
                        orig_rtr_lsa(nbr->iface);
                        if (nbr->iface->state & IF_STA_DR)
                                orig_net_lsa(nbr->iface);
@@ -319,7 +318,7 @@ nbr_new(u_int32_t nbr_id, struct iface *
        if (addr)
                rn.addr = *addr;
        rn.id.s_addr = nbr->id.s_addr;
-       rn.area_id.s_addr = nbr->iface->area_id.s_addr;
+       rn.area_id.s_addr = nbr->iface->area->id.s_addr;
        rn.ifindex = nbr->iface->ifindex;
        rn.iface_id = nbr->iface_id;
        rn.state = nbr->state;
@@ -660,7 +659,7 @@ nbr_to_ctl(struct nbr *nbr)
        memcpy(&nctl.addr, &nbr->addr, sizeof(nctl.addr));
        memcpy(&nctl.dr, &nbr->dr, sizeof(nctl.dr));
        memcpy(&nctl.bdr, &nbr->bdr, sizeof(nctl.bdr));
-       memcpy(&nctl.area, &nbr->iface->area_id, sizeof(nctl.area));
+       memcpy(&nctl.area, &nbr->iface->area->id, sizeof(nctl.area));
 
        /* this list is 99% of the time empty so that's OK for now */
        nctl.db_sum_lst_cnt = 0;
Index: ospf6d.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/ospf6d.c,v
retrieving revision 1.44
diff -u -p -r1.44 ospf6d.c
--- ospf6d.c    25 Mar 2019 20:53:33 -0000      1.44
+++ ospf6d.c    13 Dec 2019 22:24:10 -0000
@@ -280,7 +280,8 @@ main(int argc, char *argv[])
                fatal("unveil");
 
        if (kr_init(!(ospfd_conf->flags & OSPFD_FLAG_NO_FIB_UPDATE),
-           ospfd_conf->rdomain, ospfd_conf->fib_priority) == -1)
+           ospfd_conf->rdomain, ospfd_conf->redist_label_or_prefix,
+           ospfd_conf->fib_priority) == -1)
                fatalx("kr_init failed");
 
        event_dispatch();
@@ -293,8 +294,9 @@ main(int argc, char *argv[])
 __dead void
 ospfd_shutdown(void)
 {
-       pid_t   pid;
-       int     status;
+       pid_t                    pid;
+       int                      status;
+       struct redistribute     *r;
 
        /* close pipes */
        msgbuf_clear(&iev_ospfe->ibuf.w);
@@ -303,6 +305,10 @@ ospfd_shutdown(void)
        close(iev_rde->ibuf.fd);
 
        control_cleanup(ospfd_conf->csock);
+       while ((r = SIMPLEQ_FIRST(&ospfd_conf->redist_list)) != NULL) {
+               SIMPLEQ_REMOVE_HEAD(&ospfd_conf->redist_list, entry);
+               free(r);
+       }
        kr_shutdown();
        carp_demote_shutdown();
 
@@ -622,6 +628,11 @@ ospf_reload(void)
        LIST_FOREACH(area, &xconf->area_list, entry) {
                if (ospf_sendboth(IMSG_RECONF_AREA, area, sizeof(*area)) == -1)
                        return (-1);
+
+               SIMPLEQ_FOREACH(r, &area->redist_list, entry) {
+                       main_imsg_compose_rde(IMSG_RECONF_REDIST, 0, r,
+                           sizeof(*r));
+               }
        }
 
        if (ospf_sendboth(IMSG_RECONF_END, NULL, 0) == -1)
@@ -631,7 +642,7 @@ ospf_reload(void)
 
        merge_config(ospfd_conf, xconf);
        /* update redistribute lists */
-       kr_reload();
+       kr_reload(ospfd_conf->redist_label_or_prefix);
        return (0);
 #else
        return (-1);
@@ -654,12 +665,16 @@ merge_config(struct ospfd_conf *conf, st
        struct area             *a, *xa, *na;
        struct iface            *iface;
        struct redistribute     *r;
+       int                      rchange = 0;
 
        /* change of rtr_id needs a restart */
        conf->flags = xconf->flags;
        conf->spf_delay = xconf->spf_delay;
        conf->spf_hold_time = xconf->spf_hold_time;
-       conf->redistribute = xconf->redistribute;
+       if (SIMPLEQ_EMPTY(&conf->redist_list) !=
+           SIMPLEQ_EMPTY(&xconf->redist_list))
+               rchange = 1;
+       conf->redist_label_or_prefix = xconf->redist_label_or_prefix;
 
        if (ospfd_process == PROC_MAIN) {
                /* main process does neither use areas nor interfaces */
@@ -706,6 +721,20 @@ merge_config(struct ospfd_conf *conf, st
                 * stub is not yet used but switching between stub and normal
                 * will be another painful job.
                 */
+               if (a->stub != xa->stub && ospfd_process == PROC_OSPF_ENGINE)
+                       a->dirty = 1; /* force rtr LSA update */
+               if (xa->stub && ospfd_process == PROC_RDE_ENGINE) {
+                       while ((r = SIMPLEQ_FIRST(&a->redist_list)) != NULL) {
+                               SIMPLEQ_REMOVE_HEAD(&a->redist_list, entry);
+                               free(r);
+                       }
+
+                       while ((r = SIMPLEQ_FIRST(&xa->redist_list)) != NULL) {
+                               SIMPLEQ_REMOVE_HEAD(&xa->redist_list, entry);
+                               SIMPLEQ_INSERT_TAIL(&a->redist_list, r, entry);
+                       }
+                }
+
                a->stub = xa->stub;
                a->stub_default_cost = xa->stub_default_cost;
                if (ospfd_process == PROC_RDE_ENGINE)
Index: ospf6d.h
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/ospf6d.h,v
retrieving revision 1.40
diff -u -p -r1.40 ospf6d.h
--- ospf6d.h    11 Jun 2019 05:00:09 -0000      1.40
+++ ospf6d.h    13 Dec 2019 22:24:10 -0000
@@ -125,12 +125,32 @@ enum imsg_type {
        IMSG_LS_MAXAGE,
        IMSG_ABR_UP,
        IMSG_ABR_DOWN,
+       IMSG_AREA_CHANGE,
        IMSG_RECONF_CONF,
        IMSG_RECONF_AREA,
+       IMSG_RECONF_REDIST,
        IMSG_RECONF_END,
        IMSG_DEMOTE
 };
 
+#define        REDIST_CONNECTED        0x01
+#define        REDIST_STATIC           0x02
+#define        REDIST_LABEL            0x04
+#define        REDIST_ADDR             0x08
+#define        REDIST_NO               0x10
+#define        REDIST_DEFAULT          0x20
+
+struct redistribute {
+       SIMPLEQ_ENTRY(redistribute)     entry;
+       struct in6_addr                 addr;
+       u_int32_t                       metric;
+       u_int16_t                       label;
+       u_int16_t                       type;
+       u_int8_t                        prefixlen;
+       char                            dependon[IFNAMSIZ];
+};
+SIMPLEQ_HEAD(redist_list, redistribute);
+
 /* area */
 struct vertex;
 struct rde_nbr;
@@ -143,7 +163,7 @@ struct area {
 
        LIST_HEAD(, iface)       iface_list;
        LIST_HEAD(, rde_nbr)     nbr_list;
-/*     list                     addr_range_list; */
+       struct redist_list       redist_list;
        char                     demote_group[IFNAMSIZ];
        u_int32_t                stub_default_cost;
        u_int32_t                num_spf_calc;
@@ -304,10 +324,10 @@ struct iface {
        struct in6_addr          addr;
        struct in6_addr          dst;
        struct in_addr           abr_id;
-       struct in_addr           area_id;
        struct nbr              *dr;    /* designated router */
        struct nbr              *bdr;   /* backup designated router */
        struct nbr              *self;
+       struct area             *area;
 
        u_int64_t                baudrate;
        u_int32_t                ls_ack_cnt;
@@ -348,24 +368,6 @@ enum {
        PROC_RDE_ENGINE
 } ospfd_process;
 
-#define        REDIST_CONNECTED        0x01
-#define        REDIST_STATIC           0x02
-#define        REDIST_LABEL            0x04
-#define        REDIST_ADDR             0x08
-#define        REDIST_NO               0x10
-#define        REDIST_DEFAULT          0x20
-
-struct redistribute {
-       SIMPLEQ_ENTRY(redistribute)     entry;
-       struct in6_addr                 addr;
-       u_int32_t                       metric;
-       u_int16_t                       label;
-       u_int16_t                       type;
-       u_int8_t                        prefixlen;
-       char                            dependon[IFNAMSIZ];
-};
-SIMPLEQ_HEAD(redist_list, redistribute);
-
 struct ospfd_conf {
        struct event            ev;
        struct in_addr          rtr_id;
@@ -385,6 +387,7 @@ struct ospfd_conf {
        int                     spf_state;
        int                     ospf_socket;
        int                     flags;
+       int                     redist_label_or_prefix;
        u_int8_t                border;
        u_int8_t                redistribute;
        u_int8_t                fib_priority;
@@ -510,7 +513,7 @@ struct demote_msg {
 struct area    *area_new(void);
 int             area_del(struct area *);
 struct area    *area_find(struct ospfd_conf *, struct in_addr);
-void            area_track(struct area *, int);
+void            area_track(struct area *);
 int             area_border_router(struct ospfd_conf *);
 u_int32_t       area_ospf_options(struct area *);
 
@@ -540,7 +543,7 @@ u_int16_t    in_cksum(void *, size_t);
 u_int16_t       iso_cksum(void *, u_int16_t, u_int16_t);
 
 /* kroute.c */
-int             kr_init(int, u_int, u_int8_t);
+int             kr_init(int, u_int, int, u_int8_t);
 int             kr_change(struct kroute *, int);
 int             kr_delete(struct kroute *);
 void            kr_shutdown(void);
@@ -548,7 +551,7 @@ void                 kr_fib_couple(void);
 void            kr_fib_decouple(void);
 void            kr_dispatch_msg(int, short, void *);
 void            kr_show_route(struct imsg *);
-void            kr_reload(void);
+void            kr_reload(int);
 
 void            embedscope(struct sockaddr_in6 *);
 void            recoverscope(struct sockaddr_in6 *);
Index: ospfe.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/ospfe.c,v
retrieving revision 1.56
diff -u -p -r1.56 ospfe.c
--- ospfe.c     11 Jun 2019 05:00:09 -0000      1.56
+++ ospfe.c     13 Dec 2019 22:24:10 -0000
@@ -72,11 +72,12 @@ pid_t
 ospfe(struct ospfd_conf *xconf, int pipe_parent2ospfe[2], int 
pipe_ospfe2rde[2],
     int pipe_parent2rde[2])
 {
-       struct area     *area;
-       struct iface    *iface;
-       struct passwd   *pw;
-       struct event     ev_sigint, ev_sigterm;
-       pid_t            pid;
+       struct area             *area;
+       struct iface            *iface;
+       struct redistribute     *r;
+       struct passwd           *pw;
+       struct event             ev_sigint, ev_sigterm;
+       pid_t                    pid;
 
        switch (pid = fork()) {
        case -1:
@@ -174,6 +175,12 @@ ospfe(struct ospfd_conf *xconf, int pipe
 
        /* remove unneeded config stuff */
        conf_clear_redist_list(&oeconf->redist_list);
+       LIST_FOREACH(area, &oeconf->area_list, entry) {
+               while ((r = SIMPLEQ_FIRST(&area->redist_list)) != NULL) {
+                       SIMPLEQ_REMOVE_HEAD(&area->redist_list, entry);
+                       free(r);
+               }
+       }
 
        /* listen on ospfd control socket */
        TAILQ_INIT(&ctl_conns);
@@ -341,8 +348,8 @@ ospfe_dispatch_main(int fd, short event,
                        TAILQ_INIT(&iface->ls_ack_list);
                        RB_INIT(&iface->lsa_tree);
 
-                       area = area_find(oeconf, iface->area_id);
-                       LIST_INSERT_HEAD(&area->iface_list, iface, entry);
+                       LIST_INSERT_HEAD(&iface->area->iface_list, iface,
+                           entry);
                        break;
                case IMSG_IFDELETE:
                        if (imsg.hdr.len != IMSG_HEADER_SIZE +
@@ -418,6 +425,7 @@ ospfe_dispatch_main(int fd, short event,
                        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;
@@ -600,10 +608,10 @@ ospfe_dispatch_rde(int fd, short event, 
                                 * flood on all area interfaces on
                                 * area 0.0.0.0 include also virtual links.
                                 */
-                               if ((area = area_find(oeconf,
-                                   nbr->iface->area_id)) == NULL)
+                               if (nbr->iface->area == NULL)
                                        fatalx("interface lost area");
-                               LIST_FOREACH(iface, &area->iface_list, entry) {
+                               LIST_FOREACH(iface,
+                                   &nbr->iface->area->iface_list, entry) {
                                        noack += lsa_flood(iface, nbr,
                                            &lsa_hdr, imsg.data);
                                }
@@ -778,7 +786,7 @@ find_vlink(struct abr_rtr *ar)
                        if (iface->abr_id.s_addr == ar->abr_id.s_addr &&
                            iface->type == IF_TYPE_VIRTUALLINK &&
 //XXX                      iface->area->id.s_addr == ar->area.s_addr) {
-                           iface->area_id.s_addr == ar->area.s_addr) {
+                           iface->area->id.s_addr == ar->area.s_addr) {
 //XXX                          iface->dst.s_addr = ar->dst_ip.s_addr;
                                iface->dst = ar->dst_ip;
 //XXX                          iface->addr.s_addr = ar->addr.s_addr;
@@ -808,11 +816,9 @@ orig_rtr_lsa_all(struct area *area)
 void
 orig_rtr_lsa(struct iface *iface)
 {
-       struct area     *area;
-
-       if ((area = area_find(oeconf, iface->area_id)) == NULL)
+       if (iface->area == NULL)
                fatalx("interface lost area");
-       orig_rtr_lsa_area(area);
+       orig_rtr_lsa_area(iface->area);
 }
 
 void
@@ -1155,7 +1161,7 @@ orig_link_lsa(struct iface *iface)
 
        /* LSA link header (lladdr has already been filled in above) */
        LSA_24_SETHI(lsa_link.opts, iface->priority);
-       options = area_ospf_options(area_find(oeconf, iface->area_id));
+       options = area_ospf_options(iface->area);
        LSA_24_SETLO(lsa_link.opts, options);
        lsa_link.opts = htonl(lsa_link.opts);
        lsa_link.numprefix = htonl(num_prefix);
Index: packet.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/packet.c,v
retrieving revision 1.16
diff -u -p -r1.16 packet.c
--- packet.c    11 Dec 2019 21:33:56 -0000      1.16
+++ packet.c    13 Dec 2019 22:24:10 -0000
@@ -52,7 +52,7 @@ gen_ospf_hdr(struct ibuf *buf, struct if
        ospf_hdr.type = type;
        ospf_hdr.rtr_id = ospfe_router_id();
        if (iface->type != IF_TYPE_VIRTUALLINK)
-               ospf_hdr.area_id = iface->area_id.s_addr;
+               ospf_hdr.area_id = iface->area->id.s_addr;
        ospf_hdr.instance = DEFAULT_INSTANCE_ID;
        ospf_hdr.zero = 0;              /* must be zero */
 
@@ -270,7 +270,7 @@ ospf_hdr_sanity_check(struct ospf_hdr *o
        }
 
        if (iface->type != IF_TYPE_VIRTUALLINK) {
-               if (ospf_hdr->area_id != iface->area_id.s_addr) {
+               if (ospf_hdr->area_id != iface->area->id.s_addr) {
                        id.s_addr = ospf_hdr->area_id;
                        log_debug("recv_packet: invalid area ID %s, "
                            "interface %s", inet_ntoa(id), iface->name);
Index: parse.y
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/parse.y,v
retrieving revision 1.45
diff -u -p -r1.45 parse.y
--- parse.y     11 Jun 2019 05:00:09 -0000      1.45
+++ parse.y     13 Dec 2019 22:24:10 -0000
@@ -289,8 +289,10 @@ redistribute       : no REDISTRIBUTE STRING op
                                r->type = REDIST_STATIC;
                        else if (!strcmp($3, "connected"))
                                r->type = REDIST_CONNECTED;
-                       else if (prefix($3, &r->addr, &r->prefixlen))
+                       else if (prefix($3, &r->addr, &r->prefixlen)) {
                                r->type = REDIST_ADDR;
+                               conf->redist_label_or_prefix = !$1;
+                       }
                        else {
                                yyerror("unknown redistribute type");
                                free($3);
@@ -318,6 +320,8 @@ redistribute        : no REDISTRIBUTE STRING op
                        r->label = rtlabel_name2id($4);
                        if ($1)
                                r->type |= REDIST_NO;
+                       else
+                               conf->redist_label_or_prefix = 1;
                        r->metric = $5;
                        if ($6)
                                strlcpy(r->dependon, $6, sizeof(r->dependon));
@@ -519,6 +523,20 @@ areaoptsl  : interface
                        }
                }
                | defaults
+               | STUB                  { area->stub = 1; }
+               | STUB redistribute {
+                       area->stub = 1;
+                       if ($2->type != REDIST_DEFAULT) {
+                               yyerror("bad redistribute option");
+                               YYERROR;
+                       }
+                       if (!SIMPLEQ_EMPTY(&area->redist_list)) {
+                               yyerror("area redistribute option only "
+                                   "allowed once");
+                               YYERROR;
+                       }
+                       SIMPLEQ_INSERT_TAIL(&area->redist_list, $2, entry);
+               }
                ;
 
 interface      : INTERFACE STRING      {
@@ -533,7 +551,7 @@ interface   : INTERFACE STRING      {
                                YYERROR;
                        }
                        free($2);
-                       iface->area_id.s_addr = area->id.s_addr;
+                       iface->area = area;
                        LIST_INSERT_HEAD(&area->iface_list, iface, entry);
 
                        memcpy(&ifacedefs, defs, sizeof(ifacedefs));
Index: printconf.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/printconf.c,v
retrieving revision 1.8
diff -u -p -r1.8 printconf.c
--- printconf.c 29 Dec 2018 16:04:31 -0000      1.8
+++ printconf.c 13 Dec 2019 22:24:10 -0000
@@ -31,7 +31,7 @@
 
 void   print_mainconf(struct ospfd_conf *);
 const char *print_no(u_int16_t);
-void   print_redistribute(struct ospfd_conf *);
+void   print_redistribute(struct redist_list *);
 void   print_rtlabel(struct ospfd_conf *);
 void   print_iface(struct iface *);
 
@@ -53,7 +53,7 @@ print_mainconf(struct ospfd_conf *conf)
        if (conf->flags & OSPFD_FLAG_STUB_ROUTER)
                printf("stub router yes\n");
 
-       print_redistribute(conf);
+       print_redistribute(&conf->redist_list);
        print_rtlabel(conf);
 
        printf("spf-delay %u\n", conf->spf_delay);
@@ -70,11 +70,11 @@ print_no(u_int16_t type)
 }
 
 void
-print_redistribute(struct ospfd_conf *conf)
+print_redistribute(struct redist_list *rlh)
 {
        struct redistribute     *r;
 
-       SIMPLEQ_FOREACH(r, &conf->redist_list, entry) {
+       SIMPLEQ_FOREACH(r, rlh, entry) {
                switch (r->type & ~REDIST_NO) {
                case REDIST_STATIC:
                        printf("%sredistribute static ", print_no(r->type));
@@ -150,6 +150,15 @@ print_config(struct ospfd_conf *conf)
 
        LIST_FOREACH(area, &conf->area_list, entry) {
                printf("area %s {\n", inet_ntoa(area->id));
+               if (area->stub) {
+                       printf("\tstub");
+                       if (SIMPLEQ_EMPTY(&area->redist_list))
+                               printf("\n");
+                       else {
+                               printf(" ");
+                               print_redistribute(&area->redist_list);
+                       }
+               }
                if (*area->demote_group)
                        printf("\tdemote %s %d\n", area->demote_group,
                        area->demote_level);
Index: rde.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/rde.c,v
retrieving revision 1.80
diff -u -p -r1.80 rde.c
--- rde.c       11 Jun 2019 05:00:09 -0000      1.80
+++ rde.c       13 Dec 2019 22:24:10 -0000
@@ -319,7 +319,7 @@ rde_dispatch_imsg(int fd, short event, v
                            (nbr->state & NBR_STA_FULL ||
                            state & NBR_STA_FULL)) {
                                nbr->state = state;
-                               area_track(nbr->area, state);
+                               area_track(nbr->area);
                                orig_intra_area_prefix_lsas(nbr->area);
                        }
 
@@ -327,6 +327,19 @@ rde_dispatch_imsg(int fd, short event, v
                        if (nbr->state & NBR_STA_FULL)
                                rde_req_list_free(nbr);
                        break;
+               case IMSG_AREA_CHANGE:
+                       if (imsg.hdr.len - IMSG_HEADER_SIZE != sizeof(state))
+                               fatalx("invalid size of OE request");
+
+                       LIST_FOREACH(area, &rdeconf->area_list, entry) {
+                               if (area->id.s_addr == imsg.hdr.peerid)
+                                       break;
+                       }
+                       if (area == NULL)
+                               break;
+                       memcpy(&state, imsg.data, sizeof(state));
+                       area->active = state;
+                       break;
                case IMSG_DB_SNAPSHOT:
                        nbr = rde_nbr_find(imsg.hdr.peerid);
                        if (nbr == NULL)
@@ -637,6 +650,7 @@ rde_dispatch_parent(int fd, short event,
        struct kroute            kr;
        struct imsgev           *iev = bula;
        struct imsgbuf          *ibuf = &iev->ibuf;
+       struct redistribute     *nred;
        struct lsa              *lsa;
        struct vertex           *v;
        ssize_t                  n;
@@ -740,10 +754,9 @@ rde_dispatch_parent(int fd, short event,
                        if (prev_link_ok == link_ok)
                                break;
 
-                       area = area_find(rdeconf, iface->area_id);
-                       if (!area)
+                       if (iface->area == NULL)
                                fatalx("interface lost area");
-                       orig_intra_area_prefix_lsas(area);
+                       orig_intra_area_prefix_lsas(iface->area);
 
                        break;
                case IMSG_IFADD:
@@ -755,8 +768,7 @@ rde_dispatch_parent(int fd, short event,
                        TAILQ_INIT(&iface->ls_ack_list);
                        RB_INIT(&iface->lsa_tree);
 
-                       area = area_find(rdeconf, iface->area_id);
-                       LIST_INSERT_HEAD(&area->iface_list, iface, entry);
+                       LIST_INSERT_HEAD(&iface->area->iface_list, iface, 
entry);
                        break;
                case IMSG_IFDELETE:
                        if (imsg.hdr.len != IMSG_HEADER_SIZE +
@@ -789,9 +801,8 @@ rde_dispatch_parent(int fd, short event,
                        ia->prefixlen = ifc->prefixlen;
 
                        TAILQ_INSERT_TAIL(&iface->ifa_list, ia, entry);
-                       area = area_find(rdeconf, iface->area_id);
-                       if (area)
-                               orig_intra_area_prefix_lsas(area);
+                       if (iface->area)
+                               orig_intra_area_prefix_lsas(iface->area);
                        break;
                case IMSG_IFADDRDEL:
                        if (imsg.hdr.len != IMSG_HEADER_SIZE +
@@ -815,9 +826,8 @@ rde_dispatch_parent(int fd, short event,
                                        break;
                                }
                        }
-                       area = area_find(rdeconf, iface->area_id);
-                       if (area)
-                               orig_intra_area_prefix_lsas(area);
+                       if (iface->area)
+                               orig_intra_area_prefix_lsas(iface->area);
                        break;
                case IMSG_RECONF_CONF:
                        if ((nconf = malloc(sizeof(struct ospfd_conf))) ==
@@ -836,8 +846,16 @@ rde_dispatch_parent(int fd, short event,
                        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));
+
+                       SIMPLEQ_INSERT_TAIL(&narea->redist_list, nred, entry);
                        break;
                case IMSG_RECONF_END:
                        merge_config(rdeconf, nconf);
Index: rde_lsdb.c
===================================================================
RCS file: /cvs/src/usr.sbin/ospf6d/rde_lsdb.c,v
retrieving revision 1.38
diff -u -p -r1.38 rde_lsdb.c
--- rde_lsdb.c  18 Oct 2013 11:16:52 -0000      1.38
+++ rde_lsdb.c  13 Dec 2019 22:24:10 -0000
@@ -544,11 +544,9 @@ lsa_find(struct iface *iface, u_int16_t 
        if (LSA_IS_SCOPE_AS(ntohs(type)))
                tree = &asext_tree;
        else if (LSA_IS_SCOPE_AREA(ntohs(type))) {
-               struct area     *area;
-
-               if ((area = area_find(rdeconf, iface->area_id)) == NULL)
+               if (iface->area == NULL)
                        fatalx("interface lost area");
-               tree = &area->lsa_tree;
+               tree = &iface->area->lsa_tree;
        } else if (LSA_IS_SCOPE_LLOCAL(ntohs(type)))
                tree = &iface->lsa_tree;
        else

Reply via email to