diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2011-03-08 11:00:45 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2011-03-08 11:00:45 +0000 |
commit | d4d283b86e6155185d8d2e021615d7ac458b98c3 (patch) | |
tree | f78c5a5d2de89e46d0c4e23f0d129621ec730522 /usr.sbin | |
parent | 76139d01bb79d8e9b0e933d2c4ab423536bf13b6 (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.c | 32 |
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) { |