summaryrefslogtreecommitdiff
path: root/usr.sbin
diff options
context:
space:
mode:
authorClaudio Jeker <claudio@cvs.openbsd.org>2011-03-08 11:00:45 +0000
committerClaudio Jeker <claudio@cvs.openbsd.org>2011-03-08 11:00:45 +0000
commitd4d283b86e6155185d8d2e021615d7ac458b98c3 (patch)
treef78c5a5d2de89e46d0c4e23f0d129621ec730522 /usr.sbin
parent76139d01bb79d8e9b0e933d2c4ab423536bf13b6 (diff)
It was not possible to send out LS updates larger then the MTU.
Change the code in such a way that single huge LSA get fragmented but avoid IP fragmentation when packing multiple ones. Problem found and fix tested by Benjamin Papillon. Tested & OK sthen@
Diffstat (limited to 'usr.sbin')
-rw-r--r--usr.sbin/ospfd/lsupdate.c32
1 files changed, 26 insertions, 6 deletions
diff --git a/usr.sbin/ospfd/lsupdate.c b/usr.sbin/ospfd/lsupdate.c
index 9b00628f98d..4dfc58b5578 100644
--- a/usr.sbin/ospfd/lsupdate.c
+++ b/usr.sbin/ospfd/lsupdate.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lsupdate.c,v 1.39 2010/05/26 13:56:08 nicm Exp $ */
+/* $OpenBSD: lsupdate.c,v 1.40 2011/03/08 11:00:44 claudio Exp $ */
/*
* Copyright (c) 2005 Claudio Jeker <claudio@openbsd.org>
@@ -152,7 +152,8 @@ prepare_ls_update(struct iface *iface)
{
struct ibuf *buf;
- if ((buf = ibuf_open(iface->mtu - sizeof(struct ip))) == NULL)
+ if ((buf = ibuf_dynamic(iface->mtu - sizeof(struct ip),
+ IP_MAXPACKET - sizeof(struct ip))) == NULL)
fatal("prepare_ls_update");
/* OSPF header */
@@ -177,8 +178,13 @@ add_ls_update(struct ibuf *buf, struct iface *iface, void *data, u_int16_t len,
void *lsage;
u_int16_t age;
- if (ibuf_left(buf) < (size_t)len + MD5_DIGEST_LENGTH)
- return (0);
+ if ((size_t)iface->mtu < sizeof(struct ip) + sizeof(struct ospf_hdr) +
+ sizeof(u_int32_t) + ibuf_size(buf) + len + MD5_DIGEST_LENGTH) {
+ /* start new packet unless this is the first LSA to pack */
+ if (ibuf_size(buf) > sizeof(struct ospf_hdr) +
+ sizeof(u_int32_t))
+ return (0);
+ }
lsage = ibuf_reserve(buf, 0);
if (ibuf_add(buf, data, len)) {
@@ -475,8 +481,19 @@ ls_retrans_timer(int fd, short event, void *bula)
d = MAX_AGE;
if (add_ls_update(buf, nbr->iface, le->le_ref->data,
- le->le_ref->len, d) == 0)
+ le->le_ref->len, d) == 0) {
+ if (nlsa == 0) {
+ /* something bad happend retry later */
+ log_warnx("ls_retrans_timer: sending LS update "
+ "to neighbor ID %s failed",
+ inet_ntoa(nbr->id));
+ TAILQ_REMOVE(&nbr->ls_retrans_list, le, entry);
+ nbr->ls_ret_cnt--;
+ le->le_when = nbr->iface->rxmt_interval;
+ ls_retrans_list_insert(nbr, le);
+ }
break;
+ }
nlsa++;
if (le->le_oneshot)
ls_retrans_list_free(nbr, le);
@@ -487,7 +504,10 @@ ls_retrans_timer(int fd, short event, void *bula)
ls_retrans_list_insert(nbr, le);
}
}
- send_ls_update(buf, nbr->iface, addr, nlsa);
+ if (nlsa)
+ send_ls_update(buf, nbr->iface, addr, nlsa);
+ else
+ ibuf_free(buf);
done:
if ((le = TAILQ_FIRST(&nbr->ls_retrans_list)) != NULL) {