summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/ospfd/interface.c14
-rw-r--r--usr.sbin/ospfd/neighbor.c17
-rw-r--r--usr.sbin/ospfd/ospfe.c311
-rw-r--r--usr.sbin/ospfd/ospfe.h4
-rw-r--r--usr.sbin/ospfd/rde.c7
-rw-r--r--usr.sbin/ospfd/rde.h5
-rw-r--r--usr.sbin/ospfd/rde_lsdb.c39
7 files changed, 272 insertions, 125 deletions
diff --git a/usr.sbin/ospfd/interface.c b/usr.sbin/ospfd/interface.c
index 04489dabe2d..b57d6bf49f9 100644
--- a/usr.sbin/ospfd/interface.c
+++ b/usr.sbin/ospfd/interface.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: interface.c,v 1.7 2005/02/09 17:41:16 claudio Exp $ */
+/* $OpenBSD: interface.c,v 1.8 2005/02/09 20:40:23 claudio Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -138,6 +138,9 @@ if_fsm(struct iface *iface, enum iface_event event)
if (new_state != 0)
iface->state = new_state;
+ if (iface->state != old_state)
+ orig_rtr_lsa(iface->area);
+
log_debug("fsm_if: event %s resulted in action %s and changing "
"state for interface %s from %s to %s",
if_event_name(event), if_action_name(iface_fsm[i].action),
@@ -241,6 +244,7 @@ if_init(struct ospfd_conf *xconf)
struct area *area = NULL;
struct iface *iface = NULL;
+ /* XXX wrong as hell */
if ((xconf->ospf_socket = socket(AF_INET, SOCK_RAW,
IPPROTO_OSPF)) == -1) {
log_warn("if_init: error creating socket");
@@ -419,6 +423,7 @@ if_act_elect(struct iface *iface)
struct nbr *nbr, *bdr = NULL, *dr = NULL;
int round = 0;
int changed = 0;
+ int old_state;
char b1[16], b2[16], b3[16], b4[16];
log_debug("if_act_elect: interface %s", iface->name);
@@ -488,6 +493,7 @@ start:
* After the second round still DR or BDR change state to DR or BDR,
* etc.
*/
+ old_state = iface->state;
if (dr == iface->self)
iface->state = IF_STA_DR;
else if (bdr == iface->self)
@@ -506,11 +512,15 @@ start:
iface->dr = dr;
iface->bdr = bdr;
- if (changed)
+ if (changed) {
LIST_FOREACH(nbr, &iface->nbr_list, entry) {
if (nbr->state & NBR_STA_BIDIR)
nbr_fsm(nbr, NBR_EVT_ADJ_OK);
}
+ orig_rtr_lsa(iface->area);
+ if (iface->state & IF_STA_DR || old_state & IF_STA_DR)
+ orig_net_lsa(iface);
+ }
if (if_start_hello_timer(iface)) {
log_warnx("if_act_elect: cannot schedule hello_timer");
diff --git a/usr.sbin/ospfd/neighbor.c b/usr.sbin/ospfd/neighbor.c
index 68872cd5142..e4db3637911 100644
--- a/usr.sbin/ospfd/neighbor.c
+++ b/usr.sbin/ospfd/neighbor.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: neighbor.c,v 1.8 2005/02/09 16:14:23 claudio Exp $ */
+/* $OpenBSD: neighbor.c,v 1.9 2005/02/09 20:40:23 claudio Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -197,14 +197,23 @@ nbr_fsm(struct nbr *nbr, enum nbr_event event)
if (new_state != 0)
nbr->state = new_state;
- if (nbr->state != old_state)
+ /* state change inform RDE */
+ if (old_state != nbr->state)
ospfe_imsg_compose_rde(IMSG_NEIGHBOR_CHANGE,
nbr->peerid, 0, &new_state, sizeof(new_state));
- if (old_state & ~NBR_STA_PRELIM && new_state & NBR_STA_PRELIM)
- /* bidirectional communication lost */
+ /* bidirectional communication lost */
+ if (old_state & ~NBR_STA_PRELIM && nbr->state & NBR_STA_PRELIM)
if_fsm(nbr->iface, IF_EVT_NBR_CHNG);
+ /* neighbor changed from/to FULL originate new rtr and net LSA */
+ if (old_state != nbr->state && (old_state & NBR_STA_FULL ||
+ nbr->state & NBR_STA_FULL)) {
+ orig_rtr_lsa(nbr->iface->area);
+ if (nbr->iface->state & IF_STA_DR)
+ orig_net_lsa(nbr->iface);
+ }
+
if (old_state != nbr->state) {
nbr->stats.sta_chng++;
log_debug("nbr_fsm: event %s resulted in action %s and "
diff --git a/usr.sbin/ospfd/ospfe.c b/usr.sbin/ospfd/ospfe.c
index 4a98af08bc7..b6aae0bf494 100644
--- a/usr.sbin/ospfd/ospfe.c
+++ b/usr.sbin/ospfd/ospfe.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospfe.c,v 1.4 2005/02/07 05:51:00 david Exp $ */
+/* $OpenBSD: ospfe.c,v 1.5 2005/02/09 20:40:23 claudio Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -43,9 +43,6 @@
void ospfe_sig_handler(int, short, void *);
void ospfe_shutdown(void);
-void orig_lsa(void);
-void orig_rtr_lsa(struct area *);
-void orig_net_lsa(struct iface *);
volatile sig_atomic_t ospfe_quit = 0;
struct ospfd_conf *oeconf = NULL;
@@ -164,8 +161,6 @@ ospfe(struct ospfd_conf *xconf, int pipe_parent2ospfe[2], int pipe_ospfe2rde[2],
}
}
- orig_lsa();
-
event_dispatch();
ospfe_shutdown();
@@ -528,155 +523,251 @@ ospfe_dispatch_rde(int fd, short event, void *bula)
}
void
-orig_lsa(void)
-{
- struct area *area;
- struct iface *iface;
-
- LIST_FOREACH(area, &oeconf->area_list, entry) {
- orig_rtr_lsa(area);
- LIST_FOREACH(iface, &area->iface_list, entry)
- orig_net_lsa(iface);
- }
-}
-
-void
orig_rtr_lsa(struct area *area)
{
- struct lsa *lsa;
+ struct lsa_hdr lsa_hdr;
+ struct lsa_rtr lsa_rtr;
+ struct lsa_rtr_link rtr_link;
struct iface *iface;
- char *buf;
- struct lsa_rtr_link *rtr_link;
- int num_links = 0;
- u_int16_t len;
+ struct buf *buf;
+ struct nbr *nbr, *self = NULL;
+ u_int16_t num_links = 0;
+ u_int16_t chksum;
log_debug("orig_rtr_lsa: area %s", inet_ntoa(area->id));
- if ((buf = calloc(1, READ_BUF_SIZE)) == NULL)
+ if ((buf = buf_dynamic(sizeof(lsa_hdr), READ_BUF_SIZE /* XXX */)) == NULL)
fatal("orig_rtr_lsa");
- /* LSA header */
- lsa = (struct lsa *)buf;
- lsa->hdr.age = htons(DEFAULT_AGE); /* XXX */
- lsa->hdr.opts = oeconf->options; /* XXX */
- lsa->hdr.type = LSA_TYPE_ROUTER;
- lsa->hdr.ls_id = oeconf->rtr_id.s_addr;
- lsa->hdr.adv_rtr = oeconf->rtr_id.s_addr;
- lsa->hdr.seq_num = htonl(INIT_SEQ_NUM);
- lsa->hdr.ls_chksum = 0; /* updated later */
- lsa->hdr.len = 0; /* updated later */
- len = sizeof(struct lsa_hdr) + sizeof(struct lsa_rtr);
+ /* reserve space for LSA header and LSA Router header */
+ if (buf_reserve(buf, sizeof(lsa_hdr)) == NULL)
+ fatal("orig_rtr_lsa: buf_reserve failed");
+
+ if (buf_reserve(buf, sizeof(lsa_rtr)) == NULL)
+ fatal("orig_rtr_lsa: buf_reserve failed");
/* links */
LIST_FOREACH(iface, &area->iface_list, entry) {
log_debug("orig_rtr_lsa: interface %s", iface->name);
- rtr_link = (struct lsa_rtr_link *)(buf + len);
+ if (self == NULL && iface->self != NULL)
+ self = iface->self;
+
+ if (iface->state & IF_STA_DOWN)
+ continue;
+
+ bzero(&rtr_link, sizeof(rtr_link));
+
+ if (iface->state & IF_STA_LOOPBACK) {
+ rtr_link.id = iface->addr.s_addr;
+ rtr_link.data = 0xffffffff;
+ rtr_link.type = LINK_TYPE_STUB_NET;
+ num_links++;
+ if (buf_add(buf, &rtr_link, sizeof(rtr_link)))
+ fatalx("orig_rtr_lsa: buf_add failed");
+ continue;
+ }
+
switch (iface->type) {
case IF_TYPE_POINTOPOINT:
- case IF_TYPE_VIRTUALLINK:
- log_debug("orig_rtr_lsa: not supported, interface %s",
- iface->name);
- break;
- case IF_TYPE_BROADCAST:
- if (iface->state == IF_STA_DOWN)
- break;
-
- if ((iface->state == IF_STA_WAITING) ||
- iface->dr == NULL) { /* XXX */
- log_debug("orig_rtr_lsa: stub net, "
+ LIST_FOREACH(nbr, &iface->nbr_list, entry)
+ if (nbr != iface->self &&
+ nbr->state & NBR_STA_FULL)
+ break;
+ if (nbr) {
+ log_debug("orig_rtr_lsa: point-to-point, "
"interface %s", iface->name);
-
- rtr_link->id =
- iface->addr.s_addr & iface->mask.s_addr;
- rtr_link->data = iface->mask.s_addr;
- rtr_link->type = LINK_TYPE_STUB_NET;
- } else {
- log_debug("orig_rtr_lsa: transit net, "
+ rtr_link.id = nbr->addr.s_addr;
+ rtr_link.data = iface->addr.s_addr;
+ rtr_link.type = LINK_TYPE_POINTTOPOINT;
+ rtr_link.metric = htons(iface->metric);
+ num_links++;
+ if (buf_add(buf, &rtr_link, sizeof(rtr_link)))
+ fatalx("orig_rtr_lsa: buf_add failed");
+ }
+ if (iface->state & IF_STA_POINTTOPOINT) {
+ log_debug("orig_rtr_lsa: stub net, "
"interface %s", iface->name);
-
- rtr_link->id = iface->dr->addr.s_addr;
- rtr_link->data = iface->addr.s_addr;
- rtr_link->type = LINK_TYPE_TRANSIT_NET;
+ bzero(&rtr_link, sizeof(rtr_link));
+ if (nbr) {
+ rtr_link.id = nbr->addr.s_addr;
+ rtr_link.data = 0xffffffff;
+ } else {
+ rtr_link.id = iface->addr.s_addr;
+ rtr_link.data = iface->mask.s_addr;
+ }
+ rtr_link.metric = htons(iface->metric);
+ rtr_link.type = LINK_TYPE_STUB_NET;
+ num_links++;
+ if (buf_add(buf, &rtr_link, sizeof(rtr_link)))
+ fatalx("orig_rtr_lsa: buf_add failed");
+ }
+ continue;
+ case IF_TYPE_BROADCAST:
+ case IF_TYPE_NBMA:
+ if ((iface->state & IF_STA_MULTI)) {
+ if (iface->dr == iface->self) {
+ LIST_FOREACH(nbr, &iface->nbr_list,
+ entry)
+ if (nbr != iface->self &&
+ nbr->state & NBR_STA_FULL)
+ break;
+ } else
+ nbr = iface->dr;
+
+ if (nbr && nbr->state & NBR_STA_FULL) {
+ log_debug("orig_rtr_lsa: transit net, "
+ "interface %s", iface->name);
+
+ rtr_link.id = iface->dr->addr.s_addr;
+ rtr_link.data = iface->addr.s_addr;
+ rtr_link.type = LINK_TYPE_TRANSIT_NET;
+ break;
+ }
}
+ log_debug("orig_rtr_lsa: stub net, "
+ "interface %s", iface->name);
- rtr_link->num_tos = 0;
- rtr_link->metric = htons(iface->metric);
- num_links++;
- len += sizeof(struct lsa_rtr_link);
+ rtr_link.id =
+ iface->addr.s_addr & iface->mask.s_addr;
+ rtr_link.data = iface->mask.s_addr;
+ rtr_link.type = LINK_TYPE_STUB_NET;
break;
- case IF_TYPE_NBMA:
- case IF_TYPE_POINTOMULTIPOINT:
+ case IF_TYPE_VIRTUALLINK:
log_debug("orig_rtr_lsa: not supported, interface %s",
iface->name);
- break;
+ continue;
+ case IF_TYPE_POINTOMULTIPOINT:
+ log_debug("orig_rtr_lsa: stub net, "
+ "interface %s", iface->name);
+ rtr_link.id = iface->addr.s_addr;
+ rtr_link.data = 0xffffffff;
+ rtr_link.type = LINK_TYPE_STUB_NET;
+ num_links++;
+ if (buf_add(buf, &rtr_link, sizeof(rtr_link)))
+ fatalx("orig_rtr_lsa: buf_add failed");
+
+ LIST_FOREACH(nbr, &iface->nbr_list, entry) {
+ if (nbr != iface->self &&
+ nbr->state & NBR_STA_FULL) {
+ bzero(&rtr_link, sizeof(rtr_link));
+ log_debug("orig_rtr_lsa: "
+ "point-to-point, interface %s",
+ iface->name);
+ rtr_link.id = nbr->addr.s_addr;
+ rtr_link.data = iface->addr.s_addr;
+ rtr_link.type = LINK_TYPE_POINTTOPOINT;
+ rtr_link.metric = htons(iface->metric);
+ num_links++;
+ if (buf_add(buf, &rtr_link,
+ sizeof(rtr_link)))
+ fatalx("orig_rtr_lsa: "
+ "buf_add failed");
+ }
+ }
+ continue;
default:
fatalx("orig_rtr_lsa: unknown interface type");
}
- }
- lsa->data.rtr.flags = 0; /* XXX */
- lsa->data.rtr.dummy = 0;
- lsa->data.rtr.nlinks = htons(num_links);
-
- lsa->hdr.len = htons(len);
+ rtr_link.num_tos = 0;
+ rtr_link.metric = htons(iface->metric);
+ num_links++;
+ if (buf_add(buf, &rtr_link, sizeof(rtr_link)))
+ fatalx("orig_rtr_lsa: buf_add failed");
+ }
- lsa->hdr.ls_chksum = htons(iso_cksum(lsa, len, LS_CKSUM_OFFSET));
+ /* LSA router header */
+ lsa_rtr.flags = 0; /* XXX */
+ lsa_rtr.dummy = 0;
+ lsa_rtr.nlinks = htons(num_links);
+ memcpy(buf_seek(buf, sizeof(lsa_hdr), sizeof(lsa_rtr)),
+ &lsa_rtr, sizeof(lsa_rtr));
- imsg_compose(ibuf_rde, IMSG_LS_UPD,
- LIST_FIRST(&area->iface_list)->self->peerid, 0, -1, buf,
- ntohs(lsa->hdr.len));
+ /* LSA header */
+ lsa_hdr.age = htons(DEFAULT_AGE);
+ lsa_hdr.opts = oeconf->options; /* XXX */
+ lsa_hdr.type = LSA_TYPE_ROUTER;
+ lsa_hdr.ls_id = oeconf->rtr_id.s_addr;
+ lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr;
+ lsa_hdr.seq_num = htonl(INIT_SEQ_NUM);
+ lsa_hdr.len = htons(buf->wpos);
+ lsa_hdr.ls_chksum = 0; /* updated later */
+ memcpy(buf_seek(buf, 0, sizeof(lsa_hdr)), &lsa_hdr, sizeof(lsa_hdr));
+
+ chksum = htons(iso_cksum(buf->buf, buf->wpos, LS_CKSUM_OFFSET));
+ memcpy(buf_seek(buf, LS_CKSUM_OFFSET, sizeof(chksum)),
+ &chksum, sizeof(chksum));
+
+ if (self)
+ imsg_compose(ibuf_rde, IMSG_LS_UPD,
+ self->peerid, 0, -1, buf->buf, buf->wpos);
+ else
+ log_warnx("orig_rtr_lsa: empty area %s",
+ inet_ntoa(area->id));
+
+ buf_free(buf);
}
void
orig_net_lsa(struct iface *iface)
{
- struct lsa *lsa;
+ struct lsa_hdr lsa_hdr;
struct nbr *nbr;
- char *buf;
+ struct buf *buf;
int num_rtr = 0;
- u_int16_t len;
+ u_int16_t chksum;
log_debug("orig_net_lsa: iface %s", iface->name);
- /* XXX if not dr quit */
- /* ... */
-
- if ((buf = calloc(1, READ_BUF_SIZE)) == NULL)
+ if ((buf = buf_dynamic(sizeof(lsa_hdr), READ_BUF_SIZE /* XXX */)) == NULL)
fatal("orig_net_lsa");
- /* LSA header */
- lsa = (struct lsa *)buf;
- lsa->hdr.age = htons(DEFAULT_AGE); /* XXX */
- lsa->hdr.opts = oeconf->options; /* XXX */
- lsa->hdr.type = LSA_TYPE_NETWORK;
- lsa->hdr.ls_id = oeconf->rtr_id.s_addr;
- lsa->hdr.adv_rtr = oeconf->rtr_id.s_addr;
- lsa->hdr.seq_num = htonl(INIT_SEQ_NUM);
- lsa->hdr.ls_chksum = 0; /* updated later */
- lsa->hdr.len = 0; /* updated later */
- len = sizeof(lsa->hdr);
-
- lsa->data.net.mask = iface->mask.s_addr;
- len += sizeof(lsa->data.net.mask);
-
- /* attached routers */
+ /* reserve space for LSA header and LSA Router header */
+ if (buf_reserve(buf, sizeof(lsa_hdr)) == NULL)
+ fatal("orig_net_lsa: buf_reserve failed");
+
+ /* LSA net mask and then all fully adjacent routers */
+ if (buf_add(buf, &iface->mask, sizeof(iface->mask)))
+ fatal("orig_net_lsa: buf_add failed");
+
/* fully adjacent neighbors + self */
- LIST_FOREACH(nbr, &iface->nbr_list, entry) {
- if (nbr->state != NBR_STA_FULL) { /* XXX */
- lsa->data.net.att_rtr[num_rtr] = nbr->id.s_addr;
+ LIST_FOREACH(nbr, &iface->nbr_list, entry)
+ if (nbr->state & NBR_STA_FULL) {
+ if (buf_add(buf, &nbr->id, sizeof(nbr->id)))
+ fatal("orig_net_lsa: buf_add failed");
num_rtr++;
- len += sizeof(nbr->id);
}
- }
- lsa->hdr.len = htons(len);
+ if (num_rtr == 1) {
+ /* non transit net therefor no need to generate a net lsa */
+ buf_free(buf);
+ return;
+ }
- lsa->hdr.ls_chksum = htons(iso_cksum(lsa, len, LS_CKSUM_OFFSET));
-/*
- imsg_compose(ibuf_rde, IMSG_LS_UPD, iface->self->peerid, 0, -1, buf,
- ntohs(lsa->hdr.len));
-*/
+ /* LSA header */
+ if (iface->state & IF_STA_DR)
+ lsa_hdr.age = htons(DEFAULT_AGE);
+ else
+ lsa_hdr.age = htons(MAX_AGE);
+
+ lsa_hdr.opts = oeconf->options; /* XXX */
+ lsa_hdr.type = LSA_TYPE_NETWORK;
+ lsa_hdr.ls_id = iface->addr.s_addr;
+ lsa_hdr.adv_rtr = oeconf->rtr_id.s_addr;
+ lsa_hdr.seq_num = htonl(INIT_SEQ_NUM);
+ lsa_hdr.len = htons(buf->wpos);
+ lsa_hdr.ls_chksum = 0; /* updated later */
+ memcpy(buf_seek(buf, 0, sizeof(lsa_hdr)), &lsa_hdr, sizeof(lsa_hdr));
+
+ chksum = htons(iso_cksum(buf->buf, buf->wpos, LS_CKSUM_OFFSET));
+ memcpy(buf_seek(buf, LS_CKSUM_OFFSET, sizeof(chksum)),
+ &chksum, sizeof(chksum));
+
+ imsg_compose(ibuf_rde, IMSG_LS_UPD, iface->self->peerid, 0, -1,
+ buf->buf, buf->wpos);
+
+ buf_free(buf);
}
u_int32_t
diff --git a/usr.sbin/ospfd/ospfe.h b/usr.sbin/ospfd/ospfe.h
index b4ac850093d..3a5a488a179 100644
--- a/usr.sbin/ospfd/ospfe.h
+++ b/usr.sbin/ospfd/ospfe.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ospfe.h,v 1.3 2005/02/02 19:15:07 henning Exp $ */
+/* $OpenBSD: ospfe.h,v 1.4 2005/02/09 20:40:23 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -171,6 +171,8 @@ int ospfe_imsg_compose_rde(int, u_int32_t, pid_t, void *,
u_int32_t ospfe_router_id(void);
void ospfe_iface_ctl(struct ctl_conn *, unsigned int);
void ospfe_nbr_ctl(struct ctl_conn *);
+void orig_rtr_lsa(struct area *);
+void orig_net_lsa(struct iface *);
/* interface.c */
int if_fsm(struct iface *, enum iface_event);
diff --git a/usr.sbin/ospfd/rde.c b/usr.sbin/ospfd/rde.c
index 2d48a1e4b2a..b835a90515c 100644
--- a/usr.sbin/ospfd/rde.c
+++ b/usr.sbin/ospfd/rde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.c,v 1.3 2005/02/02 19:15:07 henning Exp $ */
+/* $OpenBSD: rde.c,v 1.4 2005/02/09 20:40:23 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -351,6 +351,11 @@ rde_dispatch_imsg(int fd, short event, void *bula)
else
db_hdr = &v->lsa->hdr;
+ if (nbr->self) {
+ lsa_merge(nbr, lsa, v);
+ break;
+ }
+
r = lsa_newer(&lsa->hdr, db_hdr);
if (r > 0) {
/* new LSA newer than DB */
diff --git a/usr.sbin/ospfd/rde.h b/usr.sbin/ospfd/rde.h
index 232ea6dc24d..404c036c70a 100644
--- a/usr.sbin/ospfd/rde.h
+++ b/usr.sbin/ospfd/rde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: rde.h,v 1.2 2005/01/28 17:53:33 norby Exp $ */
+/* $OpenBSD: rde.h,v 1.3 2005/02/09 20:40:23 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Esben Norby <norby@openbsd.org>
@@ -63,7 +63,7 @@ u_int32_t rde_router_id(void);
void rde_nbr_del(struct rde_nbr *);
int rde_nbr_loading(struct area *);
-/* rde_spf.c */
+/* rde_lsdb.c */
void lsa_init(struct lsa_tree *);
int lsa_compare(struct vertex *, struct vertex *);
void vertex_free(struct vertex *);
@@ -75,6 +75,7 @@ void lsa_del(struct rde_nbr *, struct lsa_hdr *);
struct vertex *lsa_find(struct area *, u_int8_t, u_int32_t, u_int32_t);
void lsa_snap(struct area *, u_int32_t);
void lsa_dump(struct lsa_tree *, pid_t);
+void lsa_merge(struct rde_nbr *, struct lsa *, struct vertex *);
RB_PROTOTYPE(lsa_tree, vertex, entry, lsa_compare)
diff --git a/usr.sbin/ospfd/rde_lsdb.c b/usr.sbin/ospfd/rde_lsdb.c
index eafb5ed0502..2b5fef75c6a 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.6 2005/02/08 12:56:48 claudio Exp $ */
+/* $OpenBSD: rde_lsdb.c,v 1.7 2005/02/09 20:40:23 claudio Exp $ */
/*
* Copyright (c) 2004, 2005 Claudio Jeker <claudio@openbsd.org>
@@ -224,7 +224,7 @@ lsa_check(struct rde_nbr *nbr, struct lsa *lsa, u_int16_t len)
}
/* MaxAge handling */
- if (ntohs(lsa->hdr.age) == MAX_AGE && lsa_find(area,
+ if (lsa->hdr.age == htons(MAX_AGE) && !nbr->self && lsa_find(area,
lsa->hdr.type, lsa->hdr.ls_id, lsa->hdr.adv_rtr) == NULL &&
!rde_nbr_loading(area)) {
/*
@@ -466,7 +466,7 @@ lsa_timeout(int fd, short event, void *bula)
log_debug("lsa_timeout: REFLOOD");
- if (v->nbr->self)
+ if (v->nbr->self && v->lsa->hdr.age != htons(MAX_AGE))
lsa_refresh(v);
rde_imsg_compose_ospfe(IMSG_LS_FLOOD, v->nbr->peerid, 0,
@@ -481,7 +481,7 @@ lsa_refresh(struct vertex *v)
u_int16_t len;
/* refresh LSA by increasing sequence number by one */
- v->lsa->hdr.age = ntohs(DEFAULT_AGE);
+ v->lsa->hdr.age = htons(DEFAULT_AGE);
seqnum = ntohl(v->lsa->hdr.seq_num);
if (seqnum++ == MAX_SEQ_NUM)
/* XXX fix me */
@@ -493,8 +493,37 @@ lsa_refresh(struct vertex *v)
v->lsa->hdr.ls_chksum = 0;
v->lsa->hdr.ls_chksum = htons(iso_cksum(v->lsa, len, LS_CKSUM_OFFSET));
- v->changed = time(NULL);
+ v->changed = v->stamp = time(NULL);
timerclear(&tv);
tv.tv_sec = LS_REFRESH_TIME;
evtimer_add(&v->ev, &tv);
}
+
+void
+lsa_merge(struct rde_nbr *nbr, struct lsa *lsa, struct vertex *v)
+{
+ struct timeval tv;
+ time_t now;
+
+ if (v == NULL) {
+ lsa_add(nbr, lsa);
+ rde_imsg_compose_ospfe(IMSG_LS_FLOOD, nbr->peerid, 0,
+ lsa, ntohs(lsa->hdr.len));
+ return;
+ }
+
+ /* TODO check for changes */
+
+ /* set the seq_num to the current on. lsa_refresh() will do the ++ */
+ lsa->hdr.seq_num = v->lsa->hdr.seq_num;
+ /* overwrite the lsa all other fields are unaffected */
+ free(v->lsa);
+ v->lsa = lsa;
+
+ /* set correct timeout for reflooding the LSA */
+ now = time(NULL);
+ timerclear(&tv);
+ if (v->changed + MIN_LS_ARRIVAL >= now)
+ tv.tv_sec = MIN_LS_ARRIVAL;
+ evtimer_add(&v->ev, &tv);
+}