summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--usr.sbin/ldpd/init.c7
-rw-r--r--usr.sbin/ldpd/labelmapping.c154
-rw-r--r--usr.sbin/ldpd/ldp.h3
-rw-r--r--usr.sbin/ldpd/notification.c5
-rw-r--r--usr.sbin/ldpd/packet.c13
5 files changed, 121 insertions, 61 deletions
diff --git a/usr.sbin/ldpd/init.c b/usr.sbin/ldpd/init.c
index 26680dc9d24..4e726f5dbd3 100644
--- a/usr.sbin/ldpd/init.c
+++ b/usr.sbin/ldpd/init.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: init.c,v 1.12 2013/06/04 02:34:48 claudio Exp $ */
+/* $OpenBSD: init.c,v 1.13 2013/10/15 19:59:52 renato Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -93,6 +93,11 @@ recv_init(struct nbr *nbr, char *buf, u_int16_t len)
return (-1);
}
+ if (ntohs(sess.proto_version) != LDP_VERSION) {
+ session_shutdown(nbr, S_BAD_PROTO_VER, init.msgid, init.type);
+ return (-1);
+ }
+
buf += SESS_PRMS_SIZE;
len -= SESS_PRMS_SIZE;
diff --git a/usr.sbin/ldpd/labelmapping.c b/usr.sbin/ldpd/labelmapping.c
index 2ed93570578..c69e123d658 100644
--- a/usr.sbin/ldpd/labelmapping.c
+++ b/usr.sbin/ldpd/labelmapping.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: labelmapping.c,v 1.24 2013/06/04 02:34:48 claudio Exp $ */
+/* $OpenBSD: labelmapping.c,v 1.25 2013/10/15 19:59:53 renato Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -25,6 +25,7 @@
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <net/if_dl.h>
+#include <netmpls/mpls.h>
#include <unistd.h>
#include <errno.h>
@@ -42,10 +43,11 @@ void gen_label_tlv(struct ibuf *, u_int32_t);
void gen_reqid_tlv(struct ibuf *, u_int32_t);
void gen_fec_tlv(struct ibuf *, struct in_addr, u_int8_t);
-int tlv_decode_label(char *, u_int16_t, u_int32_t *);
+int tlv_decode_label(struct nbr *, struct ldp_msg *, char *, u_int16_t,
+ u_int32_t *);
int tlv_decode_reqid(char *, u_int16_t, u_int32_t *);
-int tlv_decode_fec_elm(char *, u_int16_t, u_int8_t *, u_int32_t *,
- u_int8_t *);
+int tlv_decode_fec_elm(struct nbr *, struct ldp_msg *, char *, u_int16_t,
+ u_int8_t *, u_int32_t *, u_int8_t *);
/* Label Mapping Message */
void
@@ -108,6 +110,10 @@ recv_labelmapping(struct nbr *nbr, char *buf, u_int16_t len)
}
bcopy(buf, &ft, sizeof(ft));
+ if (ntohs(ft.type) != TLV_TYPE_FEC) {
+ send_notification_nbr(nbr, S_MISS_MSG, lm.msgid, lm.type);
+ return (-1);
+ }
feclen = ntohs(ft.length);
if (feclen > len - TLV_HDR_LEN) {
@@ -118,15 +124,10 @@ recv_labelmapping(struct nbr *nbr, char *buf, u_int16_t len)
buf += TLV_HDR_LEN; /* just advance to the end of the fec header */
len -= TLV_HDR_LEN;
- lbllen = tlv_decode_label(buf + feclen, len - feclen, &label);
- if (lbllen == -1) {
- session_shutdown(nbr, S_BAD_TLV_LEN, lm.msgid, lm.type);
+ lbllen = tlv_decode_label(nbr, &lm, buf + feclen, len - feclen,
+ &label);
+ if (lbllen == -1)
return (-1);
- }
- if (label == NO_LABEL) {
- session_shutdown(nbr, S_BAD_TLV_VAL, lm.msgid, lm.type);
- return (-1);
- }
/* TODO opt label request msg id, hop cnt and path vektor TLV */
@@ -134,9 +135,10 @@ recv_labelmapping(struct nbr *nbr, char *buf, u_int16_t len)
map.messageid = lm.msgid;
map.label = label;
do {
- if ((tlen = tlv_decode_fec_elm(buf, feclen, &addr_type,
- &map.prefix.s_addr, &map.prefixlen)) == -1 ||
- addr_type == FEC_WILDCARD) {
+ if ((tlen = tlv_decode_fec_elm(nbr, &lm, buf, feclen,
+ &addr_type, &map.prefix.s_addr, &map.prefixlen)) == -1)
+ return (-1);
+ if (addr_type == FEC_WILDCARD) {
session_shutdown(nbr, S_BAD_TLV_VAL, lm.msgid, lm.type);
return (-1);
}
@@ -208,6 +210,10 @@ recv_labelrequest(struct nbr *nbr, char *buf, u_int16_t len)
}
bcopy(buf, &ft, sizeof(ft));
+ if (ntohs(ft.type) != TLV_TYPE_FEC) {
+ send_notification_nbr(nbr, S_MISS_MSG, lr.msgid, lr.type);
+ return (-1);
+ }
feclen = ntohs(ft.length);
if (feclen > len - TLV_HDR_LEN) {
@@ -223,9 +229,10 @@ recv_labelrequest(struct nbr *nbr, char *buf, u_int16_t len)
bzero(&map, sizeof(map));
map.messageid = lr.msgid;
do {
- if ((tlen = tlv_decode_fec_elm(buf, feclen, &addr_type,
- &map.prefix.s_addr, &map.prefixlen)) == -1 ||
- addr_type == FEC_WILDCARD) {
+ if ((tlen = tlv_decode_fec_elm(nbr, &lr, buf, feclen,
+ &addr_type, &map.prefix.s_addr, &map.prefixlen)) == -1)
+ return (-1);
+ if (addr_type == FEC_WILDCARD) {
session_shutdown(nbr, S_BAD_TLV_VAL, lr.msgid, lr.type);
return (-1);
}
@@ -306,6 +313,10 @@ recv_labelwithdraw(struct nbr *nbr, char *buf, u_int16_t len)
}
bcopy(buf, &ft, sizeof(ft));
+ if (ntohs(ft.type) != TLV_TYPE_FEC) {
+ send_notification_nbr(nbr, S_MISS_MSG, lw.msgid, lw.type);
+ return (-1);
+ }
feclen = ntohs(ft.length);
if (feclen > len - TLV_HDR_LEN) {
@@ -320,7 +331,8 @@ recv_labelwithdraw(struct nbr *nbr, char *buf, u_int16_t len)
if (len > feclen) {
int r;
- r = tlv_decode_label(buf + feclen, len - feclen, &label);
+ r = tlv_decode_label(nbr, &lw, buf + feclen, len - feclen,
+ &label);
if (r == -1 || len != feclen + r) {
session_shutdown(nbr, S_BAD_TLV_VAL, lw.msgid,
lw.type);
@@ -335,11 +347,9 @@ recv_labelwithdraw(struct nbr *nbr, char *buf, u_int16_t len)
map.flags = F_MAP_OPTLABEL;
}
do {
- if ((tlen = tlv_decode_fec_elm(buf, feclen, &addr_type,
- &map.prefix.s_addr, &map.prefixlen)) == -1) {
- session_shutdown(nbr, S_BAD_TLV_VAL, lw.msgid, lw.type);
+ if ((tlen = tlv_decode_fec_elm(nbr, &lw, buf, feclen,
+ &addr_type, &map.prefix.s_addr, &map.prefixlen)) == -1)
return (-1);
- }
if (addr_type == FEC_WILDCARD) {
/* Wildcard FEC must be the only FEC element */
@@ -439,6 +449,10 @@ recv_labelrelease(struct nbr *nbr, char *buf, u_int16_t len)
}
bcopy(buf, &ft, sizeof(ft));
+ if (ntohs(ft.type) != TLV_TYPE_FEC) {
+ send_notification_nbr(nbr, S_MISS_MSG, lr.msgid, lr.type);
+ return (-1);
+ }
feclen = ntohs(ft.length);
if (feclen > len - TLV_HDR_LEN) {
@@ -453,7 +467,8 @@ recv_labelrelease(struct nbr *nbr, char *buf, u_int16_t len)
if (len > feclen) {
int r;
- r = tlv_decode_label(buf + feclen, len - feclen, &label);
+ r = tlv_decode_label(nbr, &lr, buf + feclen, len - feclen,
+ &label);
if (r == -1 || len != feclen + r) {
session_shutdown(nbr, S_BAD_TLV_VAL, lr.msgid,
lr.type);
@@ -468,11 +483,9 @@ recv_labelrelease(struct nbr *nbr, char *buf, u_int16_t len)
map.flags = F_MAP_OPTLABEL;
}
do {
- if ((tlen = tlv_decode_fec_elm(buf, feclen, &addr_type,
- &map.prefix.s_addr, &map.prefixlen)) == -1) {
- session_shutdown(nbr, S_BAD_TLV_VAL, lr.msgid, lr.type);
+ if ((tlen = tlv_decode_fec_elm(nbr, &lr, buf, feclen,
+ &addr_type, &map.prefix.s_addr, &map.prefixlen)) == -1)
return (-1);
- }
if (addr_type == FEC_WILDCARD) {
/* Wildcard FEC must be the only FEC element */
@@ -551,6 +564,10 @@ recv_labelabortreq(struct nbr *nbr, char *buf, u_int16_t len)
}
bcopy(buf, &ft, sizeof(ft));
+ if (ntohs(ft.type) != TLV_TYPE_FEC) {
+ send_notification_nbr(nbr, S_MISS_MSG, la.msgid, la.type);
+ return (-1);
+ }
feclen = ntohs(ft.length);
if (feclen > len - TLV_HDR_LEN) {
@@ -579,9 +596,10 @@ recv_labelabortreq(struct nbr *nbr, char *buf, u_int16_t len)
}
do {
- if ((tlen = tlv_decode_fec_elm(buf, feclen, &addr_type,
- &map.prefix.s_addr, &map.prefixlen)) == -1 ||
- addr_type == FEC_WILDCARD) {
+ if ((tlen = tlv_decode_fec_elm(nbr, &la, buf, feclen,
+ &addr_type, &map.prefix.s_addr, &map.prefixlen)) == -1)
+ return (-1);
+ if (addr_type == FEC_WILDCARD) {
session_shutdown(nbr, S_BAD_TLV_VAL, la.msgid, la.type);
return (-1);
}
@@ -612,21 +630,47 @@ gen_label_tlv(struct ibuf *buf, u_int32_t label)
}
int
-tlv_decode_label(char *buf, u_int16_t len, u_int32_t *label)
+tlv_decode_label(struct nbr *nbr, struct ldp_msg *lm, char *buf,
+ u_int16_t len, u_int32_t *label)
{
struct label_tlv lt;
- if (len < sizeof(lt))
+ if (len < sizeof(lt)) {
+ session_shutdown(nbr, S_BAD_TLV_LEN, lm->msgid, lm->type);
return (-1);
+ }
bcopy(buf, &lt, sizeof(lt));
- if (ntohs(lt.length) != sizeof(lt) - TLV_HDR_LEN)
+ if (!(ntohs(lt.type) & TLV_TYPE_GENERICLABEL)) {
+ send_notification_nbr(nbr, S_MISS_MSG, lm->msgid, lm->type);
return (-1);
+ }
- if (lt.type != htons(TLV_TYPE_GENERICLABEL))
- return (-1);
+ switch (htons(lt.type)) {
+ case TLV_TYPE_GENERICLABEL:
+ if (ntohs(lt.length) != sizeof(lt) - TLV_HDR_LEN) {
+ session_shutdown(nbr, S_BAD_TLV_LEN, lm->msgid,
+ lm->type);
+ return (-1);
+ }
- *label = ntohl(lt.label);
+ *label = ntohl(lt.label);
+ if (*label > MPLS_LABEL_MAX ||
+ (*label <= MPLS_LABEL_RESERVED_MAX &&
+ *label != MPLS_LABEL_IPV4NULL &&
+ *label != MPLS_LABEL_IMPLNULL)) {
+ session_shutdown(nbr, S_BAD_TLV_VAL, lm->msgid,
+ lm->type);
+ return (-1);
+ }
+ break;
+ case TLV_TYPE_ATMLABEL:
+ case TLV_TYPE_FRLABEL:
+ default:
+ /* unsupported */
+ session_shutdown(nbr, S_BAD_TLV_VAL, lm->msgid, lm->type);
+ return (-1);
+ }
return (sizeof(lt));
}
@@ -663,7 +707,6 @@ tlv_decode_reqid(char *buf, u_int16_t len, u_int32_t *reqid)
return (sizeof(rt));
}
-
void
gen_fec_tlv(struct ibuf *buf, struct in_addr prefix, u_int8_t prefixlen)
{
@@ -690,8 +733,8 @@ gen_fec_tlv(struct ibuf *buf, struct in_addr prefix, u_int8_t prefixlen)
}
int
-tlv_decode_fec_elm(char *buf, u_int16_t len, u_int8_t *type, u_int32_t *prefix,
- u_int8_t *prefixlen)
+tlv_decode_fec_elm(struct nbr *nbr, struct ldp_msg *lm, char *buf,
+ u_int16_t len, u_int8_t *type, u_int32_t *prefix, u_int8_t *prefixlen)
{
u_int16_t family, off = 0;
@@ -701,27 +744,38 @@ tlv_decode_fec_elm(char *buf, u_int16_t len, u_int8_t *type, u_int32_t *prefix,
if (*type == FEC_WILDCARD) {
if (len == 0)
return (off);
- else
- return (-1); /* XXX Malformed TLV Value */
+ else {
+ session_shutdown(nbr, S_BAD_TLV_VAL, lm->msgid,
+ lm->type);
+ return (-1);
+ }
}
- if (*type != FEC_PREFIX)
- return (-1); /* XXX "Unknown FEC" Notification */
+ if (*type != FEC_PREFIX) {
+ send_notification_nbr(nbr, S_UNKNOWN_FEC, lm->msgid, lm->type);
+ return (-1);
+ }
- if (len < FEC_ELM_MIN_LEN)
- return (-1); /* XXX Bad TLV Length */
+ if (len < FEC_ELM_MIN_LEN) {
+ session_shutdown(nbr, S_BAD_TLV_LEN, lm->msgid, lm->type);
+ return (-1);
+ }
bcopy(buf + off, &family, sizeof(family));
off += sizeof(family);
- if (family != htons(FEC_IPV4))
- return (-1); /* XXX "Unsupported Address Family" */
+ if (family != htons(FEC_IPV4)) {
+ send_notification_nbr(nbr, S_UNSUP_ADDR, lm->msgid, lm->type);
+ return (-1);
+ }
*prefixlen = buf[off];
off += sizeof(u_int8_t);
- if (len < off + PREFIX_SIZE(*prefixlen))
- return (-1); /* XXX Bad TLV Length */
+ if (len < off + PREFIX_SIZE(*prefixlen)) {
+ session_shutdown(nbr, S_BAD_TLV_LEN, lm->msgid, lm->type);
+ return (-1);
+ }
*prefix = 0;
bcopy(buf + off, prefix, PREFIX_SIZE(*prefixlen));
diff --git a/usr.sbin/ldpd/ldp.h b/usr.sbin/ldpd/ldp.h
index 25d426c3817..d5a571422d2 100644
--- a/usr.sbin/ldpd/ldp.h
+++ b/usr.sbin/ldpd/ldp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldp.h,v 1.14 2013/10/15 16:47:24 renato Exp $ */
+/* $OpenBSD: ldp.h,v 1.15 2013/10/15 19:59:53 renato Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -92,6 +92,7 @@ struct ldp_hdr {
} __packed;
#define LDP_HDR_SIZE 10
+#define LDP_HDR_PDU_LEN 6
/* TLV record */
struct tlv {
diff --git a/usr.sbin/ldpd/notification.c b/usr.sbin/ldpd/notification.c
index f3e62868767..320dd1cc99c 100644
--- a/usr.sbin/ldpd/notification.c
+++ b/usr.sbin/ldpd/notification.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: notification.c,v 1.14 2013/06/04 02:34:48 claudio Exp $ */
+/* $OpenBSD: notification.c,v 1.15 2013/10/15 19:59:53 renato Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -112,7 +112,8 @@ recv_notification(struct nbr *nbr, char *buf, u_int16_t len)
if (st.status_code == htonl(S_NO_HELLO) ||
st.status_code == htonl(S_PARM_ADV_MODE) ||
st.status_code == htonl(S_MAX_PDU_LEN) ||
- st.status_code == htonl(S_PARM_L_RANGE))
+ st.status_code == htonl(S_PARM_L_RANGE) ||
+ st.status_code == htonl(S_KEEPALIVE_BAD))
nbr_start_idtimer(nbr);
nbr_fsm(nbr, NBR_EVT_CLOSE_SESSION);
diff --git a/usr.sbin/ldpd/packet.c b/usr.sbin/ldpd/packet.c
index 237c510f917..b8c6ca824ba 100644
--- a/usr.sbin/ldpd/packet.c
+++ b/usr.sbin/ldpd/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.29 2013/10/15 16:47:24 renato Exp $ */
+/* $OpenBSD: packet.c,v 1.30 2013/10/15 19:59:53 renato Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -345,11 +345,12 @@ session_read(int fd, short event, void *arg)
}
pdu_len = ntohs(ldp_hdr->length);
- if (pdu_len < LDP_HDR_SIZE || pdu_len > LDP_MAX_LEN) {
+ if (pdu_len < (LDP_HDR_PDU_LEN + LDP_MSG_LEN) ||
+ pdu_len > LDP_MAX_LEN) {
if (nbr)
- session_shutdown(nbr, S_BAD_MSG_LEN, 0, 0);
+ session_shutdown(nbr, S_BAD_PDU_LEN, 0, 0);
else {
- send_notification(S_BAD_MSG_LEN, tcp, 0, 0);
+ send_notification(S_BAD_PDU_LEN, tcp, 0, 0);
msgbuf_write(&tcp->wbuf.wbuf);
tcp_close(tcp);
}
@@ -405,9 +406,6 @@ session_read(int fd, short event, void *arg)
/* check for error conditions earlier */
switch (type) {
- case MSG_TYPE_NOTIFICATION:
- /* notifications are always processed */
- break;
case MSG_TYPE_INIT:
if ((nbr->state != NBR_STA_INITIAL) &&
(nbr->state != NBR_STA_OPENSENT)) {
@@ -426,6 +424,7 @@ session_read(int fd, short event, void *arg)
return;
}
break;
+ case MSG_TYPE_NOTIFICATION:
case MSG_TYPE_ADDR:
case MSG_TYPE_ADDRWITHDRAW:
case MSG_TYPE_LABELMAPPING: