summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/ospfd/control.c3
-rw-r--r--usr.sbin/ospfd/database.c12
-rw-r--r--usr.sbin/ospfd/interface.c3
-rw-r--r--usr.sbin/ospfd/neighbor.c7
-rw-r--r--usr.sbin/ospfd/ospf.h20
-rw-r--r--usr.sbin/ospfd/ospfd.h6
-rw-r--r--usr.sbin/ospfd/ospfe.c11
-rw-r--r--usr.sbin/ospfd/ospfe.h3
-rw-r--r--usr.sbin/ospfd/rde.c68
-rw-r--r--usr.sbin/ospfd/rde.h13
-rw-r--r--usr.sbin/ospfd/rde_lsdb.c131
-rw-r--r--usr.sbin/ospfd/rde_spf.c12
12 files changed, 213 insertions, 76 deletions
diff --git a/usr.sbin/ospfd/control.c b/usr.sbin/ospfd/control.c
index 0012c9ebd40..44157b5f659 100644
--- a/usr.sbin/ospfd/control.c
+++ b/usr.sbin/ospfd/control.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: control.c,v 1.34 2010/09/02 14:03:22 sobrado Exp $ */
+/* $OpenBSD: control.c,v 1.35 2011/05/09 12:24:41 claudio Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -253,6 +253,7 @@ control_dispatch_imsg(int fd, short event, void *bula)
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:
c->iev.ibuf.pid = imsg.hdr.pid;
diff --git a/usr.sbin/ospfd/database.c b/usr.sbin/ospfd/database.c
index f3641c31f6d..80f5e0cede0 100644
--- a/usr.sbin/ospfd/database.c
+++ b/usr.sbin/ospfd/database.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: database.c,v 1.28 2011/03/04 09:24:46 claudio Exp $ */
+/* $OpenBSD: database.c,v 1.29 2011/05/09 12:24:41 claudio Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -138,7 +138,8 @@ send_db_description(struct nbr *nbr)
fatalx("send_db_description: unknown interface type");
}
- dd_hdr.opts = area_ospf_options(nbr->iface->area);
+ /* XXX button or not for opaque LSA? */
+ dd_hdr.opts = area_ospf_options(nbr->iface->area) | OSPF_OPTION_O;
dd_hdr.bits = bits;
dd_hdr.dd_seq_num = htonl(nbr->dd_seq_num);
@@ -211,6 +212,13 @@ recv_db_description(struct nbr *nbr, char *buf, u_int16_t len)
case NBR_STA_XSTRT:
if (dupe)
return;
+ nbr->capa_options = dd_hdr.opts;
+ if ((nbr->capa_options & nbr->options) != nbr->options) {
+ log_warnx("recv_db_description: neighbor ID %s "
+ "sent inconsistent options %x vs. %x",
+ inet_ntoa(nbr->id), nbr->capa_options,
+ nbr->options);
+ }
/*
* check bits: either I,M,MS or only M
*/
diff --git a/usr.sbin/ospfd/interface.c b/usr.sbin/ospfd/interface.c
index 6ab3c94be36..a7e30359751 100644
--- a/usr.sbin/ospfd/interface.c
+++ b/usr.sbin/ospfd/interface.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: interface.c,v 1.71 2011/05/06 13:50:37 claudio Exp $ */
+/* $OpenBSD: interface.c,v 1.72 2011/05/09 12:24:41 claudio Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -167,6 +167,7 @@ if_new(struct kif *kif, struct kif_addr *ka)
LIST_INIT(&iface->nbr_list);
TAILQ_INIT(&iface->ls_ack_list);
TAILQ_INIT(&iface->auth_md_list);
+ RB_INIT(&iface->lsa_tree);
iface->crypt_seq_num = arc4random() & 0x0fffffff;
diff --git a/usr.sbin/ospfd/neighbor.c b/usr.sbin/ospfd/neighbor.c
index 6ff76c2b1f6..2a6d7b9a558 100644
--- a/usr.sbin/ospfd/neighbor.c
+++ b/usr.sbin/ospfd/neighbor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: neighbor.c,v 1.42 2011/03/24 08:35:59 claudio Exp $ */
+/* $OpenBSD: neighbor.c,v 1.43 2011/05/09 12:24:41 claudio Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -313,6 +313,7 @@ nbr_new(u_int32_t nbr_id, struct iface *iface, int self)
bzero(&rn, sizeof(rn));
rn.id.s_addr = nbr->id.s_addr;
rn.area_id.s_addr = nbr->iface->area->id.s_addr;
+ rn.ifindex = nbr->iface->ifindex;
rn.state = nbr->state;
rn.self = self;
ospfe_imsg_compose_rde(IMSG_NEIGHBOR_UP, nbr->peerid, 0, &rn,
@@ -519,6 +520,8 @@ nbr_act_snapshot(struct nbr *nbr)
{
stop_db_tx_timer(nbr);
+ ospfe_imsg_compose_rde(IMSG_NEIGHBOR_CAPA, nbr->peerid, 0,
+ &nbr->capa_options, sizeof(nbr->capa_options));
ospfe_imsg_compose_rde(IMSG_DB_SNAPSHOT, nbr->peerid, 0, NULL, 0);
return (0);
@@ -677,7 +680,7 @@ nbr_to_ctl(struct nbr *nbr)
nctl.state_chng_cnt = nbr->stats.sta_chng;
nctl.priority = nbr->priority;
- nctl.options = nbr->options;
+ nctl.options = nbr->options | nbr->capa_options;
gettimeofday(&now, NULL);
if (evtimer_pending(&nbr->inactivity_timer, &tv)) {
diff --git a/usr.sbin/ospfd/ospf.h b/usr.sbin/ospfd/ospf.h
index 7d2d6b1be61..fe0a8998ffc 100644
--- a/usr.sbin/ospfd/ospf.h
+++ b/usr.sbin/ospfd/ospf.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospf.h,v 1.20 2011/03/25 08:52:21 claudio Exp $ */
+/* $OpenBSD: ospf.h,v 1.21 2011/05/09 12:24:41 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -81,11 +81,14 @@
#define MAX_SIMPLE_AUTH_LEN 8
/* OSPF compatibility flags */
+#define OSPF_OPTION_MT 0x01
#define OSPF_OPTION_E 0x02
#define OSPF_OPTION_MC 0x04
#define OSPF_OPTION_NP 0x08
#define OSPF_OPTION_EA 0x10
#define OSPF_OPTION_DC 0x20
+#define OSPF_OPTION_O 0x40 /* only on DD options */
+#define OSPF_OPTION_DN 0x80 /* only on LSA options */
/* OSPF packet types */
#define PACKET_TYPE_HELLO 1
@@ -177,6 +180,9 @@ struct ls_upd_hdr {
#define LSA_TYPE_SUM_NETWORK 3
#define LSA_TYPE_SUM_ROUTER 4
#define LSA_TYPE_EXTERNAL 5
+#define LSA_TYPE_LINK_OPAQ 9
+#define LSA_TYPE_AREA_OPAQ 10
+#define LSA_TYPE_AS_OPAQ 11
#define LINK_TYPE_POINTTOPOINT 1
#define LINK_TYPE_TRANSIT_NET 2
@@ -187,6 +193,18 @@ struct ls_upd_hdr {
#define LSA_METRIC_MASK 0x00ffffff /* only for sum & as-ext */
#define LSA_ASEXT_E_FLAG 0x80000000
+/* for some reason they thought 24bit types are fun, make them less a hazard */
+#define LSA_24_MASK 0xffffff
+#define LSA_24_GETHI(x) \
+ ((x) >> 24)
+#define LSA_24_GETLO(x) \
+ ((x) & LSA_24_MASK)
+#define LSA_24_SETHI(x, y) \
+ ((x) = ((x) & LSA_24_MASK) | (((y) & 0xff) << 24))
+#define LSA_24_SETLO(x, y) \
+ ((x) = ((y) & LSA_24_MASK) | ((x) & ~LSA_24_MASK))
+
+
#define OSPF_RTR_B 0x01
#define OSPF_RTR_E 0x02
#define OSPF_RTR_V 0x04
diff --git a/usr.sbin/ospfd/ospfd.h b/usr.sbin/ospfd/ospfd.h
index 6660f2962c5..1cc0145fbdb 100644
--- a/usr.sbin/ospfd/ospfd.h
+++ b/usr.sbin/ospfd/ospfd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospfd.h,v 1.89 2011/01/12 15:07:46 claudio Exp $ */
+/* $OpenBSD: ospfd.h,v 1.90 2011/05/09 12:24:41 claudio Exp $ */
/*
* Copyright (c) 2004 Esben Norby <norby@openbsd.org>
@@ -80,6 +80,7 @@ enum imsg_type {
IMSG_CTL_SHOW_DB_SELF,
IMSG_CTL_SHOW_DB_SUM,
IMSG_CTL_SHOW_DB_ASBR,
+ IMSG_CTL_SHOW_DB_OPAQ,
IMSG_CTL_SHOW_NBR,
IMSG_CTL_SHOW_RIB,
IMSG_CTL_SHOW_SUM,
@@ -88,6 +89,7 @@ enum imsg_type {
IMSG_CTL_FIB_DECOUPLE,
IMSG_CTL_FIB_RELOAD,
IMSG_CTL_AREA,
+ IMSG_CTL_IFACE,
IMSG_CTL_KROUTE,
IMSG_CTL_KROUTE_ADDR,
IMSG_CTL_IFINFO,
@@ -99,6 +101,7 @@ enum imsg_type {
IMSG_NEIGHBOR_UP,
IMSG_NEIGHBOR_DOWN,
IMSG_NEIGHBOR_CHANGE,
+ IMSG_NEIGHBOR_CAPA,
IMSG_NETWORK_ADD,
IMSG_NETWORK_DEL,
IMSG_DD,
@@ -310,6 +313,7 @@ struct iface {
LIST_HEAD(, nbr) nbr_list;
struct auth_md_head auth_md_list;
struct lsa_head ls_ack_list;
+ struct lsa_tree lsa_tree;
char name[IF_NAMESIZE];
char demote_group[IFNAMSIZ];
diff --git a/usr.sbin/ospfd/ospfe.c b/usr.sbin/ospfd/ospfe.c
index ceef94e855a..969c1b0e967 100644
--- a/usr.sbin/ospfd/ospfe.c
+++ b/usr.sbin/ospfd/ospfe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospfe.c,v 1.81 2011/05/02 09:22:23 claudio Exp $ */
+/* $OpenBSD: ospfe.c,v 1.82 2011/05/09 12:24:41 claudio Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -375,6 +375,7 @@ ospfe_dispatch_main(int fd, short event, void *bula)
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);
@@ -544,6 +545,12 @@ ospfe_dispatch_rde(int fd, short event, void *bula)
&lsa_hdr, imsg.data);
}
}
+ } else if (lsa_hdr.type == LSA_TYPE_LINK_OPAQ) {
+ /*
+ * Flood on interface only
+ */
+ noack += lsa_flood(nbr->iface, nbr,
+ &lsa_hdr, imsg.data);
} else {
/*
* Flood on all area interfaces. For
@@ -676,6 +683,7 @@ ospfe_dispatch_rde(int fd, short event, void *bula)
}
break;
case IMSG_CTL_AREA:
+ case IMSG_CTL_IFACE:
case IMSG_CTL_END:
case IMSG_CTL_SHOW_DATABASE:
case IMSG_CTL_SHOW_DB_EXT:
@@ -684,6 +692,7 @@ ospfe_dispatch_rde(int fd, short event, void *bula)
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:
diff --git a/usr.sbin/ospfd/ospfe.h b/usr.sbin/ospfd/ospfe.h
index fadd896869c..03fdef5e303 100644
--- a/usr.sbin/ospfd/ospfe.h
+++ b/usr.sbin/ospfd/ospfe.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospfe.h,v 1.43 2011/03/25 08:52:21 claudio Exp $ */
+/* $OpenBSD: ospfe.h,v 1.44 2011/05/09 12:24:41 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -88,6 +88,7 @@ struct nbr {
int state;
u_int8_t priority;
u_int8_t options;
+ u_int8_t capa_options;
u_int8_t last_rx_options;
u_int8_t last_rx_bits;
u_int8_t dd_master;
diff --git a/usr.sbin/ospfd/rde.c b/usr.sbin/ospfd/rde.c
index e4e0e06592e..0155e1cd813 100644
--- a/usr.sbin/ospfd/rde.c
+++ b/usr.sbin/ospfd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.93 2011/05/02 11:17:03 claudio Exp $ */
+/* $OpenBSD: rde.c,v 1.94 2011/05/09 12:24:41 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -42,6 +42,7 @@ void rde_sig_handler(int sig, short, void *);
void rde_shutdown(void);
void rde_dispatch_imsg(int, short, void *);
void rde_dispatch_parent(int, short, void *);
+void rde_dump_area(struct area *, int, pid_t);
void rde_send_summary(pid_t);
void rde_send_summary_area(struct area *, pid_t);
@@ -61,7 +62,6 @@ void rde_asext_get(struct kroute *);
void rde_asext_put(struct kroute *);
void rde_asext_free(void);
struct lsa *orig_asext_lsa(struct kroute *, u_int32_t, u_int16_t);
-
struct lsa *orig_sum_lsa(struct rt_node *, struct area *, u_int8_t, int);
struct ospfd_conf *rdeconf = NULL, *nconf = NULL;
@@ -305,12 +305,20 @@ rde_dispatch_imsg(int fd, short event, void *bula)
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;
+ break;
case IMSG_DB_SNAPSHOT:
nbr = rde_nbr_find(imsg.hdr.peerid);
if (nbr == NULL)
break;
- lsa_snap(nbr->area, imsg.hdr.peerid);
+ lsa_snap(nbr);
imsg_compose_event(iev_ospfe, IMSG_DB_END, imsg.hdr.peerid,
0, -1, NULL, 0);
@@ -332,7 +340,7 @@ rde_dispatch_imsg(int fd, short event, void *bula)
error = 1;
break;
}
- v = lsa_find(nbr->area, lsa_hdr.type,
+ v = lsa_find(nbr->iface, lsa_hdr.type,
lsa_hdr.ls_id, lsa_hdr.adv_rtr);
if (v == NULL)
db_hdr = NULL;
@@ -373,7 +381,7 @@ rde_dispatch_imsg(int fd, short event, void *bula)
memcpy(&req_hdr, buf, sizeof(req_hdr));
buf += sizeof(req_hdr);
- if ((v = lsa_find(nbr->area,
+ if ((v = lsa_find(nbr->iface,
ntohl(req_hdr.type), req_hdr.ls_id,
req_hdr.adv_rtr)) == NULL) {
log_debug("rde_dispatch_imsg: "
@@ -408,7 +416,7 @@ rde_dispatch_imsg(int fd, short event, void *bula)
break;
}
- v = lsa_find(nbr->area, lsa->hdr.type, lsa->hdr.ls_id,
+ v = lsa_find(nbr->iface, lsa->hdr.type, lsa->hdr.ls_id,
lsa->hdr.adv_rtr);
if (v == NULL)
db_hdr = NULL;
@@ -504,7 +512,7 @@ rde_dispatch_imsg(int fd, short event, void *bula)
if (rde_nbr_loading(nbr->area))
break;
- v = lsa_find(nbr->area, lsa_hdr.type, lsa_hdr.ls_id,
+ v = lsa_find(nbr->iface, lsa_hdr.type, lsa_hdr.ls_id,
lsa_hdr.adv_rtr);
if (v == NULL)
db_hdr = NULL;
@@ -524,6 +532,7 @@ rde_dispatch_imsg(int fd, short event, void *bula)
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");
@@ -531,10 +540,7 @@ rde_dispatch_imsg(int fd, short event, void *bula)
}
if (imsg.hdr.len == IMSG_HEADER_SIZE) {
LIST_FOREACH(area, &rdeconf->area_list, entry) {
- imsg_compose_event(iev_ospfe,
- IMSG_CTL_AREA, 0, imsg.hdr.pid, -1,
- area, sizeof(*area));
- lsa_dump(&area->lsa_tree, imsg.hdr.type,
+ rde_dump_area(area, imsg.hdr.type,
imsg.hdr.pid);
}
lsa_dump(&asext_tree, imsg.hdr.type,
@@ -542,10 +548,7 @@ rde_dispatch_imsg(int fd, short event, void *bula)
} else {
memcpy(&aid, imsg.data, sizeof(aid));
if ((area = area_find(rdeconf, aid)) != NULL) {
- imsg_compose_event(iev_ospfe,
- IMSG_CTL_AREA, 0, imsg.hdr.pid, -1,
- area, sizeof(*area));
- lsa_dump(&area->lsa_tree, imsg.hdr.type,
+ rde_dump_area(area, imsg.hdr.type,
imsg.hdr.pid);
if (!area->stub)
lsa_dump(&asext_tree,
@@ -686,6 +689,7 @@ rde_dispatch_parent(int fd, short event, void *bula)
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);
@@ -711,6 +715,26 @@ rde_dispatch_parent(int fd, short event, void *bula)
}
}
+void
+rde_dump_area(struct area *area, int imsg_type, pid_t pid)
+{
+ struct iface *iface;
+
+ /* dump header */
+ imsg_compose_event(iev_ospfe, IMSG_CTL_AREA, 0, pid, -1,
+ area, sizeof(*area));
+
+ /* dump link local lsa */
+ LIST_FOREACH(iface, &area->iface_list, entry) {
+ imsg_compose_event(iev_ospfe, IMSG_CTL_IFACE,
+ 0, pid, -1, iface, sizeof(*iface));
+ lsa_dump(&iface->lsa_tree, imsg_type, pid);
+ }
+
+ /* dump area lsa */
+ lsa_dump(&area->lsa_tree, imsg_type, pid);
+}
+
u_int32_t
rde_router_id(void)
{
@@ -903,18 +927,27 @@ rde_nbr_new(u_int32_t peerid, struct rde_nbr *new)
struct rde_nbr_head *head;
struct rde_nbr *nbr;
struct area *area;
+ struct iface *iface;
if (rde_nbr_find(peerid))
return (NULL);
if ((area = area_find(rdeconf, new->area_id)) == NULL)
fatalx("rde_nbr_new: unknown area");
+ LIST_FOREACH(iface, &area->iface_list, entry) {
+ if (iface->ifindex == new->ifindex)
+ break;
+ }
+ if (iface == NULL)
+ fatalx("rde_nbr_new: unknown interface");
+
if ((nbr = calloc(1, sizeof(*nbr))) == NULL)
fatal("rde_nbr_new");
memcpy(nbr, new, sizeof(*nbr));
nbr->peerid = peerid;
nbr->area = area;
+ nbr->iface = iface;
TAILQ_INIT(&nbr->req_list);
@@ -1335,12 +1368,13 @@ rde_summary_update(struct rt_node *rte, struct area *area)
fatalx("rde_summary_update: unknown route type");
/* update lsa but only if it was changed */
- v = lsa_find(area, type, rte->prefix.s_addr, rde_router_id());
+ v = lsa_find_area(area, type, rte->prefix.s_addr, rde_router_id());
lsa = orig_sum_lsa(rte, area, type, rte->invalid);
lsa_merge(rde_nbr_self(area), lsa, v);
if (v == NULL)
- v = lsa_find(area, type, rte->prefix.s_addr, rde_router_id());
+ v = lsa_find_area(area, type, rte->prefix.s_addr,
+ rde_router_id());
/* suppressed/deleted routes are not found in the second lsa_find */
if (v)
diff --git a/usr.sbin/ospfd/rde.h b/usr.sbin/ospfd/rde.h
index 384f60fb3ce..4492f5b40ba 100644
--- a/usr.sbin/ospfd/rde.h
+++ b/usr.sbin/ospfd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.37 2011/05/02 11:45:55 claudio Exp $ */
+/* $OpenBSD: rde.h,v 1.38 2011/05/09 12:24:41 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -41,6 +41,7 @@ struct vertex {
struct event ev;
struct area *area;
struct lsa *lsa;
+ struct lsa_tree *lsa_tree;
time_t changed;
time_t stamp;
u_int32_t cost;
@@ -67,9 +68,12 @@ struct rde_nbr {
struct in_addr area_id;
TAILQ_HEAD(, rde_req_entry) req_list;
struct area *area;
+ struct iface *iface;
u_int32_t peerid; /* unique ID in DB */
int state;
- int self;
+ unsigned int ifindex;
+ u_int8_t self;
+ u_int8_t capa_options;
};
struct rt_nexthop {
@@ -133,10 +137,11 @@ int lsa_self(struct rde_nbr *, struct lsa *, struct vertex *);
int lsa_add(struct rde_nbr *, struct lsa *);
void lsa_del(struct rde_nbr *, struct lsa_hdr *);
void lsa_age(struct vertex *);
-struct vertex *lsa_find(struct area *, u_int8_t, u_int32_t, u_int32_t);
+struct vertex *lsa_find(struct iface *, u_int8_t, u_int32_t, u_int32_t);
+struct vertex *lsa_find_area(struct area *, u_int8_t, u_int32_t, u_int32_t);
struct vertex *lsa_find_net(struct area *area, u_int32_t);
u_int16_t lsa_num_links(struct vertex *);
-void lsa_snap(struct area *, u_int32_t);
+void lsa_snap(struct rde_nbr *);
void lsa_dump(struct lsa_tree *, int, pid_t);
void lsa_merge(struct rde_nbr *, struct lsa *, struct vertex *);
void lsa_remove_invalid_sums(struct area *);
diff --git a/usr.sbin/ospfd/rde_lsdb.c b/usr.sbin/ospfd/rde_lsdb.c
index 4cc79c52fb6..053666cf49e 100644
--- a/usr.sbin/ospfd/rde_lsdb.c
+++ b/usr.sbin/ospfd/rde_lsdb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_lsdb.c,v 1.46 2011/05/02 11:45:55 claudio Exp $ */
+/* $OpenBSD: rde_lsdb.c,v 1.47 2011/05/09 12:24:41 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -27,9 +27,11 @@
#include "rde.h"
#include "log.h"
-struct vertex *vertex_get(struct lsa *, struct rde_nbr *);
+struct vertex *vertex_get(struct lsa *, struct rde_nbr *, struct lsa_tree *);
int lsa_router_check(struct lsa *, u_int16_t);
+struct vertex *lsa_find_tree(struct lsa_tree *, u_int16_t, u_int32_t,
+ u_int32_t);
void lsa_timeout(int, short, void *);
void lsa_refresh(struct vertex *);
int lsa_equal(struct lsa *, struct lsa *);
@@ -49,20 +51,20 @@ lsa_compare(struct vertex *a, struct vertex *b)
return (-1);
if (a->type > b->type)
return (1);
- if (a->ls_id < b->ls_id)
- return (-1);
- if (a->ls_id > b->ls_id)
- return (1);
if (a->adv_rtr < b->adv_rtr)
return (-1);
if (a->adv_rtr > b->adv_rtr)
return (1);
+ if (a->ls_id < b->ls_id)
+ return (-1);
+ if (a->ls_id > b->ls_id)
+ return (1);
return (0);
}
struct vertex *
-vertex_get(struct lsa *lsa, struct rde_nbr *nbr)
+vertex_get(struct lsa *lsa, struct rde_nbr *nbr, struct lsa_tree *tree)
{
struct vertex *v;
struct timespec tp;
@@ -79,6 +81,7 @@ vertex_get(struct lsa *lsa, struct rde_nbr *nbr)
v->ls_id = ntohl(lsa->hdr.ls_id);
v->adv_rtr = ntohl(lsa->hdr.adv_rtr);
v->type = lsa->hdr.type;
+ v->lsa_tree = tree;
if (!nbr->self)
v->flooded = 1; /* XXX fix me */
@@ -92,10 +95,7 @@ vertex_get(struct lsa *lsa, struct rde_nbr *nbr)
void
vertex_free(struct vertex *v)
{
- if (v->type == LSA_TYPE_EXTERNAL)
- RB_REMOVE(lsa_tree, &asext_tree, v);
- else
- RB_REMOVE(lsa_tree, &v->area->lsa_tree, v);
+ RB_REMOVE(lsa_tree, v->lsa_tree, v);
(void)evtimer_del(&v->ev);
vertex_nexthop_clear(v);
@@ -255,13 +255,24 @@ lsa_check(struct rde_nbr *nbr, struct lsa *lsa, u_int16_t len)
if (area->stub)
return (0);
break;
+ case LSA_TYPE_LINK_OPAQ:
+ case LSA_TYPE_AREA_OPAQ:
+ case LSA_TYPE_AS_OPAQ:
+ if (len % sizeof(u_int32_t)) {
+ log_warnx("lsa_check: bad opaque LSA packet");
+ return (0);
+ }
+ /* Type-11 Opaque-LSA are silently discarded in stub areas */
+ if (lsa->hdr.type == LSA_TYPE_AS_OPAQ && area->stub)
+ return (0);
+ break;
default:
log_warnx("lsa_check: unknown type %u", lsa->hdr.type);
return (0);
}
/* MaxAge handling */
- if (lsa->hdr.age == htons(MAX_AGE) && !nbr->self && lsa_find(area,
+ if (lsa->hdr.age == htons(MAX_AGE) && !nbr->self && lsa_find(nbr->iface,
lsa->hdr.type, lsa->hdr.ls_id, lsa->hdr.adv_rtr) == NULL &&
!rde_nbr_loading(area)) {
/*
@@ -372,12 +383,15 @@ lsa_add(struct rde_nbr *nbr, struct lsa *lsa)
struct vertex *new, *old;
struct timeval tv, now, res;
- if (lsa->hdr.type == LSA_TYPE_EXTERNAL)
+ if (lsa->hdr.type == LSA_TYPE_EXTERNAL ||
+ lsa->hdr.type == LSA_TYPE_AS_OPAQ)
tree = &asext_tree;
+ else if (lsa->hdr.type == LSA_TYPE_LINK_OPAQ)
+ tree = &nbr->iface->lsa_tree;
else
tree = &nbr->area->lsa_tree;
- new = vertex_get(lsa, nbr);
+ new = vertex_get(lsa, nbr, tree);
old = RB_INSERT(lsa_tree, tree, new);
if (old != NULL) {
@@ -396,14 +410,16 @@ lsa_add(struct rde_nbr *nbr, struct lsa *lsa)
return (1);
}
if (!lsa_equal(new->lsa, old->lsa)) {
- if (lsa->hdr.type != LSA_TYPE_EXTERNAL)
+ if (lsa->hdr.type != LSA_TYPE_EXTERNAL &&
+ lsa->hdr.type != LSA_TYPE_AS_OPAQ)
nbr->area->dirty = 1;
start_spf_timer();
}
vertex_free(old);
RB_INSERT(lsa_tree, tree, new);
} else {
- if (lsa->hdr.type != LSA_TYPE_EXTERNAL)
+ if (lsa->hdr.type != LSA_TYPE_EXTERNAL &&
+ lsa->hdr.type != LSA_TYPE_AS_OPAQ)
nbr->area->dirty = 1;
start_spf_timer();
}
@@ -427,7 +443,7 @@ lsa_del(struct rde_nbr *nbr, struct lsa_hdr *lsa)
struct vertex *v;
struct timeval tv;
- v = lsa_find(nbr->area, lsa->type, lsa->ls_id, lsa->adv_rtr);
+ v = lsa_find(nbr->iface, lsa->type, lsa->ls_id, lsa->adv_rtr);
if (v == NULL)
return;
@@ -469,21 +485,39 @@ lsa_age(struct vertex *v)
}
struct vertex *
-lsa_find(struct area *area, u_int8_t type, u_int32_t ls_id, u_int32_t adv_rtr)
+lsa_find(struct iface *iface, u_int8_t type, u_int32_t ls_id, u_int32_t adv_rtr)
+{
+ struct lsa_tree *tree;
+
+ if (type == LSA_TYPE_EXTERNAL ||
+ type == LSA_TYPE_AS_OPAQ)
+ tree = &asext_tree;
+ else if (type == LSA_TYPE_LINK_OPAQ)
+ tree = &iface->lsa_tree;
+ else
+ tree = &iface->area->lsa_tree;
+
+ return lsa_find_tree(tree, type, ls_id, adv_rtr);
+}
+
+struct vertex *
+lsa_find_area(struct area *area, u_int8_t type, u_int32_t ls_id,
+ u_int32_t adv_rtr)
+{
+ return lsa_find_tree(&area->lsa_tree, type, ls_id, adv_rtr);
+}
+
+struct vertex *
+lsa_find_tree(struct lsa_tree *tree, u_int16_t type, u_int32_t ls_id,
+ u_int32_t adv_rtr)
{
struct vertex key;
struct vertex *v;
- struct lsa_tree *tree;
key.ls_id = ntohl(ls_id);
key.adv_rtr = ntohl(adv_rtr);
key.type = type;
- if (type == LSA_TYPE_EXTERNAL)
- tree = &asext_tree;
- else
- tree = &area->lsa_tree;
-
v = RB_FIND(lsa_tree, tree, &key);
/* LSA that are deleted are not findable */
@@ -532,26 +566,40 @@ lsa_num_links(struct vertex *v)
}
void
-lsa_snap(struct area *area, u_int32_t peerid)
+lsa_snap(struct rde_nbr *nbr)
{
- struct lsa_tree *tree = &area->lsa_tree;
+ struct lsa_tree *tree = &nbr->area->lsa_tree;
struct vertex *v;
do {
RB_FOREACH(v, lsa_tree, tree) {
if (v->deleted)
continue;
+ switch (v->type) {
+ case LSA_TYPE_LINK_OPAQ:
+ case LSA_TYPE_AREA_OPAQ:
+ case LSA_TYPE_AS_OPAQ:
+ if (nbr->capa_options & OSPF_OPTION_O)
+ break;
+ continue;
+ }
lsa_age(v);
if (ntohs(v->lsa->hdr.age) >= MAX_AGE)
- rde_imsg_compose_ospfe(IMSG_LS_UPD, peerid,
+ rde_imsg_compose_ospfe(IMSG_LS_UPD, nbr->peerid,
0, &v->lsa->hdr, ntohs(v->lsa->hdr.len));
else
- rde_imsg_compose_ospfe(IMSG_DB_SNAPSHOT, peerid,
- 0, &v->lsa->hdr, sizeof(struct lsa_hdr));
+ rde_imsg_compose_ospfe(IMSG_DB_SNAPSHOT,
+ nbr->peerid, 0, &v->lsa->hdr,
+ sizeof(struct lsa_hdr));
}
- if (tree != &area->lsa_tree || area->stub)
+ if (tree == &asext_tree)
break;
- tree = &asext_tree;
+ if (tree == &nbr->area->lsa_tree)
+ tree = &nbr->iface->lsa_tree;
+ else if (nbr->area->stub)
+ break;
+ else
+ tree = &asext_tree;
} while (1);
}
@@ -566,9 +614,7 @@ lsa_dump(struct lsa_tree *tree, int imsg_type, pid_t pid)
lsa_age(v);
switch (imsg_type) {
case IMSG_CTL_SHOW_DATABASE:
- rde_imsg_compose_ospfe(IMSG_CTL_SHOW_DATABASE, 0, pid,
- &v->lsa->hdr, ntohs(v->lsa->hdr.len));
- continue;
+ break;
case IMSG_CTL_SHOW_DB_SELF:
if (v->lsa->hdr.adv_rtr == rde_router_id())
break;
@@ -593,6 +639,12 @@ lsa_dump(struct lsa_tree *tree, int imsg_type, pid_t pid)
if (v->type == LSA_TYPE_SUM_ROUTER)
break;
continue;
+ case IMSG_CTL_SHOW_DB_OPAQ:
+ if (v->type == LSA_TYPE_LINK_OPAQ ||
+ v->type == LSA_TYPE_AREA_OPAQ ||
+ v->type == LSA_TYPE_AS_OPAQ)
+ break;
+ continue;
default:
log_warnx("lsa_dump: unknown imsg type");
return;
@@ -618,7 +670,8 @@ lsa_timeout(int fd, short event, void *bula)
v->deleted = 0;
/* schedule recalculation of the RIB */
- if (v->lsa->hdr.type != LSA_TYPE_EXTERNAL)
+ if (v->type != LSA_TYPE_EXTERNAL &&
+ v->type != LSA_TYPE_AS_OPAQ)
v->area->dirty = 1;
start_spf_timer();
@@ -713,7 +766,8 @@ lsa_merge(struct rde_nbr *nbr, struct lsa *lsa, struct vertex *v)
free(v->lsa);
v->lsa = lsa;
start_spf_timer();
- if (v->type != LSA_TYPE_EXTERNAL)
+ if (v->type != LSA_TYPE_EXTERNAL &&
+ v->type != LSA_TYPE_AS_OPAQ)
nbr->area->dirty = 1;
/* set correct timeout for reflooding the LSA */
@@ -774,13 +828,13 @@ lsa_generate_stub_sums(struct area *area)
rn.cost = r->metric & LSA_METRIC_MASK;
/* update lsa but only if it was changed */
- v = lsa_find(area, LSA_TYPE_SUM_NETWORK,
+ v = lsa_find_area(area, LSA_TYPE_SUM_NETWORK,
rn.prefix.s_addr, rde_router_id());
lsa = orig_sum_lsa(&rn, area, LSA_TYPE_SUM_NETWORK, 0);
lsa_merge(rde_nbr_self(area), lsa, v);
if (v == NULL)
- v = lsa_find(area, LSA_TYPE_SUM_NETWORK,
+ v = lsa_find_area(area, LSA_TYPE_SUM_NETWORK,
rn.prefix.s_addr, rde_router_id());
/*
@@ -817,4 +871,3 @@ lsa_equal(struct lsa *a, struct lsa *b)
return (1);
}
-
diff --git a/usr.sbin/ospfd/rde_spf.c b/usr.sbin/ospfd/rde_spf.c
index c93d6a25b83..996e9fcaf26 100644
--- a/usr.sbin/ospfd/rde_spf.c
+++ b/usr.sbin/ospfd/rde_spf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde_spf.c,v 1.71 2011/05/02 11:45:55 claudio Exp $ */
+/* $OpenBSD: rde_spf.c,v 1.72 2011/05/09 12:24:41 claudio Exp $ */
/*
* Copyright (c) 2005 Esben Norby <norby@openbsd.org>
@@ -63,8 +63,8 @@ spf_calc(struct area *area)
cand_list_clr();
/* initialize SPF tree */
- if ((v = spf_root = lsa_find(area, LSA_TYPE_ROUTER, rde_router_id(),
- rde_router_id())) == NULL)
+ if ((v = spf_root = lsa_find_area(area, LSA_TYPE_ROUTER,
+ rde_router_id(), rde_router_id())) == NULL)
/* empty area because no interface is active */
return;
@@ -86,7 +86,7 @@ spf_calc(struct area *area)
case LINK_TYPE_POINTTOPOINT:
case LINK_TYPE_VIRTUAL:
/* find router LSA */
- w = lsa_find(area, LSA_TYPE_ROUTER,
+ w = lsa_find_area(area, LSA_TYPE_ROUTER,
rtr_link->id, rtr_link->id);
break;
case LINK_TYPE_TRANSIT_NET:
@@ -100,7 +100,7 @@ spf_calc(struct area *area)
case LSA_TYPE_NETWORK:
net_link = get_net_link(v, i);
/* find router LSA */
- w = lsa_find(area, LSA_TYPE_ROUTER,
+ w = lsa_find_area(area, LSA_TYPE_ROUTER,
net_link->att_rtr, net_link->att_rtr);
break;
default:
@@ -231,7 +231,7 @@ rt_calc(struct vertex *v, struct area *area, struct ospfd_conf *conf)
/* TODO type 3 area address range check */
- if ((w = lsa_find(area, LSA_TYPE_ROUTER,
+ if ((w = lsa_find_area(area, LSA_TYPE_ROUTER,
htonl(v->adv_rtr),
htonl(v->adv_rtr))) == NULL)
return;