diff options
author | Claudio Jeker <claudio@cvs.openbsd.org> | 2011-01-10 12:02:49 +0000 |
---|---|---|
committer | Claudio Jeker <claudio@cvs.openbsd.org> | 2011-01-10 12:02:49 +0000 |
commit | 37754a29a234575c97dd4982fbf84e553ff379cd (patch) | |
tree | 3510cd9926b9bd5e155bf533cd4741f6ca1ca088 /usr.sbin/ldpd | |
parent | 7fc4cc53bdd6bcaf945aa67a133f4f01e184a890 (diff) |
Implement optional parameter handling for initialization messages.
This will now correctly ignore TLV with U flag set -- like the FT
extension used by JunOS. The function is built after
tlv_decode_opt_hello_prms().
Problem reported and fix tested by Marcel Wiget.
Diffstat (limited to 'usr.sbin/ldpd')
-rw-r--r-- | usr.sbin/ldpd/init.c | 45 |
1 files changed, 42 insertions, 3 deletions
diff --git a/usr.sbin/ldpd/init.c b/usr.sbin/ldpd/init.c index 2004bc71bcf..121ac201073 100644 --- a/usr.sbin/ldpd/init.c +++ b/usr.sbin/ldpd/init.c @@ -1,4 +1,4 @@ -/* $OpenBSD: init.c,v 1.6 2010/11/04 09:52:16 claudio Exp $ */ +/* $OpenBSD: init.c,v 1.7 2011/01/10 12:02:48 claudio Exp $ */ /* * Copyright (c) 2009 Michele Marchetto <michele@openbsd.org> @@ -38,6 +38,7 @@ #include "ldpe.h" int gen_init_prms_tlv(struct ibuf *, struct nbr *, u_int16_t); +int tlv_decode_opt_init_prms(char *, u_int16_t); void send_init(struct nbr *nbr) @@ -88,12 +89,19 @@ recv_init(struct nbr *nbr, char *buf, u_int16_t len) bcopy(buf, &sess, sizeof(sess)); if (ntohs(sess.length) != SESS_PRMS_SIZE - TLV_HDR_LEN || - ntohs(sess.length) != len - TLV_HDR_LEN) { + ntohs(sess.length) > len - TLV_HDR_LEN) { session_shutdown(nbr, S_BAD_TLV_LEN, init.msgid, init.type); return (-1); } - /* ATM and Frame Relay optional attributes not supported */ + buf += SESS_PRMS_SIZE; + len -= SESS_PRMS_SIZE; + + /* just ignore all optional TLVs for now */ + if (tlv_decode_opt_init_prms(buf, len) == -1) { + session_shutdown(nbr, S_BAD_TLV_VAL, init.msgid, init.type); + return (-1); + } if (nbr->iface->keepalive < ntohs(sess.keepalive_time)) nbr->keepalive = nbr->iface->keepalive; @@ -127,3 +135,34 @@ gen_init_prms_tlv(struct ibuf *buf, struct nbr *nbr, u_int16_t size) return (ibuf_add(buf, &parms, SESS_PRMS_SIZE)); } + +int +tlv_decode_opt_init_prms(char *buf, u_int16_t len) +{ + struct tlv tlv; + int cons = 0; + u_int16_t tlv_len; + + while (len >= sizeof(tlv)) { + bcopy(buf, &tlv, sizeof(tlv)); + tlv_len = ntohs(tlv.length); + switch (ntohs(tlv.type)) { + case TLV_TYPE_ATMSESSIONPAR: + log_warnx("ATM session parameter present"); + return (-1); + case TLV_TYPE_FRSESSION: + log_warnx("FR session parameter present"); + return (-1); + default: + /* if unknown flag set, ignore TLV */ + if (!(ntohs(tlv.type) & UNKNOWN_FLAG)) + return (-1); + break; + } + buf += TLV_HDR_LEN + tlv_len; + len -= TLV_HDR_LEN + tlv_len; + cons += TLV_HDR_LEN + tlv_len; + } + + return (cons); +} |