diff options
| -rw-r--r-- | usr.sbin/ospfd/control.c | 3 | ||||
| -rw-r--r-- | usr.sbin/ospfd/database.c | 12 | ||||
| -rw-r--r-- | usr.sbin/ospfd/interface.c | 3 | ||||
| -rw-r--r-- | usr.sbin/ospfd/neighbor.c | 7 | ||||
| -rw-r--r-- | usr.sbin/ospfd/ospf.h | 20 | ||||
| -rw-r--r-- | usr.sbin/ospfd/ospfd.h | 6 | ||||
| -rw-r--r-- | usr.sbin/ospfd/ospfe.c | 11 | ||||
| -rw-r--r-- | usr.sbin/ospfd/ospfe.h | 3 | ||||
| -rw-r--r-- | usr.sbin/ospfd/rde.c | 68 | ||||
| -rw-r--r-- | usr.sbin/ospfd/rde.h | 13 | ||||
| -rw-r--r-- | usr.sbin/ospfd/rde_lsdb.c | 131 | ||||
| -rw-r--r-- | usr.sbin/ospfd/rde_spf.c | 12 |
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; |
