On Sat, Jan 08, 2011 at 08:04:33PM +0100, Marcel Wiget wrote:
> On Jan 8, 2011, at 4:20 PM, Claudio Jeker wrote:
>
> > Commited the diff. I guess there is a bit more needed so that we handle
> > various unknown TLVs correctly in hello and initializaion. I hope I can
> > provide a diff for this soon. Btw. I would be interested in the ldpd -dv
> > output of the failures you get when the JUNOS has RFC 3479 enabled or when
> > a different transport addr is used.
>
> Thanks! Without 'set protocols ldp graceful-restart helper-disable' on junos,
> I get the following output from ldpd -dv. Packet dump of the LDP
> initialization message and openbsd's response further down:
>
Thanks for all the info. Can you try the following diff?
This should allow unkown TLVs in hello and initialization messages.
This should signal the JUNOS neighbor that it needs to disable FT.
--
:wq Claudio
Index: hello.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/hello.c,v
retrieving revision 1.8
diff -u -p -r1.8 hello.c
--- hello.c 8 Jan 2011 14:50:29 -0000 1.8
+++ hello.c 9 Jan 2011 14:55:12 -0000
@@ -202,32 +202,37 @@ int
tlv_decode_opt_hello_prms(char *buf, u_int16_t len, struct in_addr *addr,
u_int32_t *conf_number)
{
- struct hello_opt_parms_tlv tlv;
- int cons = 0;
+ struct tlv tlv;
+ int cons = 0;
+ u_int16_t tlv_len;
bzero(addr, sizeof(*addr));
*conf_number = 0;
while (len >= sizeof(tlv)) {
bcopy(buf, &tlv, sizeof(tlv));
-
- if (ntohs(tlv.length) < sizeof(u_int32_t))
- return (-1);
-
+ tlv_len = ntohs(tlv.length);
switch (ntohs(tlv.type)) {
case TLV_TYPE_IPV4TRANSADDR:
- addr->s_addr = tlv.value;
+ if (tlv_len < sizeof(u_int32_t))
+ return (-1);
+ bcopy(buf + TLV_HDR_LEN, addr, sizeof(u_int32_t));
break;
case TLV_TYPE_CONFIG:
- *conf_number = ntohl(tlv.value);
+ if (tlv_len < sizeof(u_int32_t))
+ return (-1);
+ bcopy(buf + TLV_HDR_LEN, conf_number,
+ sizeof(u_int32_t));
break;
default:
- return (-1);
+ /* if unknown flag set, ignore TLV */
+ if (!(ntohs(tlv.type) & UNKNOWN_FLAG))
+ return (-1);
+ break;
}
-
- len -= sizeof(tlv);
- buf += sizeof(tlv);
- cons += sizeof(tlv);
+ buf += TLV_HDR_LEN + tlv_len;
+ len -= TLV_HDR_LEN + tlv_len;
+ cons += TLV_HDR_LEN + tlv_len;
}
return (cons);
Index: init.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/init.c,v
retrieving revision 1.6
diff -u -p -r1.6 init.c
--- init.c 4 Nov 2010 09:52:16 -0000 1.6
+++ init.c 9 Jan 2011 14:55:35 -0000
@@ -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_
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;
@@ -126,4 +134,35 @@ gen_init_prms_tlv(struct ibuf *buf, stru
parms.lspace_id = 0;
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);
}
Index: labelmapping.c
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/labelmapping.c,v
retrieving revision 1.18
diff -u -p -r1.18 labelmapping.c
--- labelmapping.c 31 Dec 2010 21:22:42 -0000 1.18
+++ labelmapping.c 9 Jan 2011 14:33:51 -0000
@@ -93,7 +93,7 @@ int
recv_labelmapping(struct nbr *nbr, char *buf, u_int16_t len)
{
struct ldp_msg lm;
- struct fec_tlv ft;
+ struct tlv ft;
struct map map;
u_int32_t label;
int feclen, lbllen, tlen;
@@ -202,7 +202,7 @@ int
recv_labelrequest(struct nbr *nbr, char *buf, u_int16_t len)
{
struct ldp_msg lr;
- struct fec_tlv ft;
+ struct tlv ft;
struct map map;
int feclen, tlen;
u_int8_t addr_type;
@@ -308,7 +308,7 @@ recv_labelwithdraw(struct nbr *nbr, char
{
struct map map;
struct ldp_msg lw;
- struct fec_tlv ft;
+ struct tlv ft;
u_int32_t label = NO_LABEL;
int feclen, tlen, numfec = 0;
u_int8_t addr_type;
@@ -449,7 +449,7 @@ recv_labelrelease(struct nbr *nbr, char
{
struct map map;
struct ldp_msg lr;
- struct fec_tlv ft;
+ struct tlv ft;
u_int32_t label = NO_LABEL;
int feclen, tlen, numfec = 0;
u_int8_t addr_type;
@@ -568,7 +568,7 @@ recv_labelabortreq(struct nbr *nbr, char
{
struct map map;
struct ldp_msg la;
- struct fec_tlv ft;
+ struct tlv ft;
int feclen, tlen;
u_int8_t addr_type;
@@ -707,7 +707,7 @@ tlv_decode_reqid(char *buf, u_int16_t le
void
gen_fec_tlv(struct ibuf *buf, struct in_addr prefix, u_int8_t prefixlen)
{
- struct fec_tlv ft;
+ struct tlv ft;
u_int8_t type;
u_int16_t family;
u_int8_t len;
Index: ldp.h
===================================================================
RCS file: /cvs/src/usr.sbin/ldpd/ldp.h,v
retrieving revision 1.7
diff -u -p -r1.7 ldp.h
--- ldp.h 4 Nov 2010 09:52:16 -0000 1.7
+++ ldp.h 9 Jan 2011 14:34:20 -0000
@@ -97,6 +97,12 @@ struct ldp_hdr {
#define INFINITE_HOLDTIME 0xffff
/* TLV record */
+struct tlv {
+ u_int16_t type;
+ u_int16_t length;
+};
+#define TLV_HDR_LEN 4
+
struct ldp_msg {
u_int16_t type;
u_int16_t length;
@@ -106,7 +112,6 @@ struct ldp_msg {
} __packed;
#define LDP_MSG_LEN 8
-#define TLV_HDR_LEN 4
#define UNKNOWN_FLAGS_MASK 0xc000
#define UNKNOWN_FLAG 0x8000
@@ -189,12 +194,6 @@ struct address_list_tlv {
#define ADDR_IPV4 0x1
#define ADDR_IPV6 0x2
-struct fec_tlv {
- u_int16_t type;
- u_int16_t length;
- /* fec elm entries */
-};
-
/* This struct is badly aligned so use two 32 bit fields */
struct fec_elm {
u_int32_t hdr;
@@ -202,10 +201,8 @@ struct fec_elm {
};
#define FEC_ELM_MIN_LEN 4
-
#define FEC_WILDCARD 0x01
#define FEC_PREFIX 0x02
-
#define FEC_IPV4 0x0001
struct label_tlv {
@@ -223,12 +220,6 @@ struct reqid_tlv {
};
#define REQID_TLV_LEN 8
-
-struct hello_opt_parms_tlv {
- u_int16_t type;
- u_int16_t length;
- u_int32_t value;
-};
#define NO_LABEL UINT_MAX