summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRenato Westphal <renato@cvs.openbsd.org>2017-03-04 00:06:11 +0000
committerRenato Westphal <renato@cvs.openbsd.org>2017-03-04 00:06:11 +0000
commit512924baf176079550a3e543d949bc8ab73cf778 (patch)
tree99ae0fe570c15063f701ef6a06b3d4c5ac7c4f3b
parentf0cbdab642f0c88a7edb19fb0e8cf2a44ee3acee (diff)
Implement RFC 5561 (LDP Capabilities).
This patch per-se doesn't introduce any useful functionality, but prepares the ground for new enhancements to ldpd (i.e. implementation of new RFCs that make use of LDP capabilities).
-rw-r--r--usr.sbin/ldpd/init.c154
-rw-r--r--usr.sbin/ldpd/labelmapping.c10
-rw-r--r--usr.sbin/ldpd/ldp.h20
-rw-r--r--usr.sbin/ldpd/ldpd.815
-rw-r--r--usr.sbin/ldpd/ldpd.h8
-rw-r--r--usr.sbin/ldpd/ldpe.h7
-rw-r--r--usr.sbin/ldpd/logmsg.c6
-rw-r--r--usr.sbin/ldpd/notification.c57
-rw-r--r--usr.sbin/ldpd/packet.c15
9 files changed, 262 insertions, 30 deletions
diff --git a/usr.sbin/ldpd/init.c b/usr.sbin/ldpd/init.c
index 721a6dfe298..ae1513720f1 100644
--- a/usr.sbin/ldpd/init.c
+++ b/usr.sbin/ldpd/init.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: init.c,v 1.34 2017/03/03 23:44:35 renato Exp $ */
+/* $OpenBSD: init.c,v 1.35 2017/03/04 00:06:10 renato Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -25,6 +25,7 @@
#include "log.h"
static int gen_init_prms_tlv(struct ibuf *, struct nbr *);
+static int gen_cap_dynamic_tlv(struct ibuf *);
void
send_init(struct nbr *nbr)
@@ -35,15 +36,16 @@ send_init(struct nbr *nbr)
log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
- size = LDP_HDR_SIZE + LDP_MSG_SIZE + SESS_PRMS_SIZE;
+ size = LDP_HDR_SIZE + LDP_MSG_SIZE + SESS_PRMS_SIZE +
+ CAP_TLV_DYNAMIC_SIZE;
if ((buf = ibuf_open(size)) == NULL)
fatal(__func__);
err |= gen_ldp_hdr(buf, size);
size -= LDP_HDR_SIZE;
err |= gen_msg_hdr(buf, MSG_TYPE_INIT, size);
- size -= LDP_MSG_SIZE;
err |= gen_init_prms_tlv(buf, nbr);
+ err |= gen_cap_dynamic_tlv(buf);
if (err) {
ibuf_free(buf);
return;
@@ -58,6 +60,7 @@ recv_init(struct nbr *nbr, char *buf, uint16_t len)
struct ldp_msg msg;
struct sess_prms_tlv sess;
uint16_t max_pdu_len;
+ int caps_rcvd = 0;
log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
@@ -94,6 +97,7 @@ recv_init(struct nbr *nbr, char *buf, uint16_t len)
/* Optional Parameters */
while (len > 0) {
struct tlv tlv;
+ uint16_t tlv_type;
uint16_t tlv_len;
if (len < sizeof(tlv)) {
@@ -102,6 +106,7 @@ recv_init(struct nbr *nbr, char *buf, uint16_t len)
}
memcpy(&tlv, buf, TLV_HDR_SIZE);
+ tlv_type = ntohs(tlv.type);
tlv_len = ntohs(tlv.length);
if (tlv_len + TLV_HDR_SIZE > len) {
session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
@@ -110,17 +115,42 @@ recv_init(struct nbr *nbr, char *buf, uint16_t len)
buf += TLV_HDR_SIZE;
len -= TLV_HDR_SIZE;
- switch (ntohs(tlv.type)) {
+ /*
+ * RFC 5561 - Section 6:
+ * "The S-bit of a Capability Parameter in an Initialization
+ * message MUST be 1 and SHOULD be ignored on receipt".
+ */
+ switch (tlv_type) {
case TLV_TYPE_ATMSESSIONPAR:
session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type);
return (-1);
case TLV_TYPE_FRSESSION:
session_shutdown(nbr, S_BAD_TLV_VAL, msg.id, msg.type);
return (-1);
+ case TLV_TYPE_DYNAMIC_CAP:
+ if (tlv_len != CAP_TLV_DYNAMIC_LEN) {
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg.id,
+ msg.type);
+ return (-1);
+ }
+
+ if (caps_rcvd & F_CAP_TLV_RCVD_DYNAMIC) {
+ session_shutdown(nbr, S_BAD_TLV_VAL, msg.id,
+ msg.type);
+ return (-1);
+ }
+ caps_rcvd |= F_CAP_TLV_RCVD_DYNAMIC;
+
+ nbr->flags |= F_NBR_CAP_DYNAMIC;
+
+ log_debug("%s: lsr-id %s announced the Dynamic "
+ "Capability Announcement capability", __func__,
+ inet_ntoa(nbr->id));
+ break;
default:
if (!(ntohs(tlv.type) & UNKNOWN_FLAG))
- send_notification(nbr->tcp, S_UNKNOWN_TLV,
- msg.id, msg.type);
+ send_notification_rtlvs(nbr, S_UNSSUPORTDCAP,
+ msg.id, msg.type, tlv_type, tlv_len, buf);
/* ignore unknown tlv */
break;
}
@@ -146,6 +176,104 @@ recv_init(struct nbr *nbr, char *buf, uint16_t len)
return (0);
}
+void
+send_capability(struct nbr *nbr, uint16_t capability, int enable)
+{
+ struct ibuf *buf;
+ uint16_t size;
+ int err = 0;
+
+ log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
+
+ size = LDP_HDR_SIZE + LDP_MSG_SIZE + CAP_TLV_DYNAMIC_SIZE;
+ if ((buf = ibuf_open(size)) == NULL)
+ fatal(__func__);
+
+ err |= gen_ldp_hdr(buf, size);
+ size -= LDP_HDR_SIZE;
+ err |= gen_msg_hdr(buf, MSG_TYPE_CAPABILITY, size);
+
+ switch (capability) {
+ case TLV_TYPE_DYNAMIC_CAP:
+ /*
+ * RFC 5561 - Section 9:
+ * "An LDP speaker MUST NOT include the Dynamic Capability
+ * Announcement Parameter in Capability messages sent to
+ * its peers".
+ */
+ /* FALLTHROUGH */
+ default:
+ fatalx("send_capability: unsupported capability");
+ }
+
+ if (err) {
+ ibuf_free(buf);
+ return;
+ }
+
+ evbuf_enqueue(&nbr->tcp->wbuf, buf);
+ nbr_fsm(nbr, NBR_EVT_PDU_SENT);
+}
+
+int
+recv_capability(struct nbr *nbr, char *buf, uint16_t len)
+{
+ struct ldp_msg msg;
+
+ log_debug("%s: lsr-id %s", __func__, inet_ntoa(nbr->id));
+
+ memcpy(&msg, buf, sizeof(msg));
+ buf += LDP_MSG_SIZE;
+ len -= LDP_MSG_SIZE;
+
+ /* Optional Parameters */
+ while (len > 0) {
+ struct tlv tlv;
+ uint16_t tlv_type;
+ uint16_t tlv_len;
+
+ if (len < sizeof(tlv)) {
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
+ return (-1);
+ }
+
+ memcpy(&tlv, buf, TLV_HDR_SIZE);
+ tlv_type = ntohs(tlv.type);
+ tlv_len = ntohs(tlv.length);
+ if (tlv_len + TLV_HDR_SIZE > len) {
+ session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
+ return (-1);
+ }
+ buf += TLV_HDR_SIZE;
+ len -= TLV_HDR_SIZE;
+
+ switch (tlv_type) {
+ case TLV_TYPE_DYNAMIC_CAP:
+ /*
+ * RFC 5561 - Section 9:
+ * "An LDP speaker that receives a Capability message
+ * from a peer that includes the Dynamic Capability
+ * Announcement Parameter SHOULD silently ignore the
+ * parameter and process any other Capability Parameters
+ * in the message".
+ */
+ /* FALLTHROUGH */
+ default:
+ if (!(ntohs(tlv.type) & UNKNOWN_FLAG))
+ send_notification_rtlvs(nbr, S_UNSSUPORTDCAP,
+ msg.id, msg.type, tlv_type, tlv_len, buf);
+ /* ignore unknown tlv */
+ break;
+ }
+ buf += tlv_len;
+ len -= tlv_len;
+ }
+
+ nbr_fsm(nbr, NBR_EVT_PDU_RCVD);
+
+ return (0);
+}
+
static int
gen_init_prms_tlv(struct ibuf *buf, struct nbr *nbr)
{
@@ -164,3 +292,17 @@ gen_init_prms_tlv(struct ibuf *buf, struct nbr *nbr)
return (ibuf_add(buf, &parms, SESS_PRMS_SIZE));
}
+
+static int
+gen_cap_dynamic_tlv(struct ibuf *buf)
+{
+ struct capability_tlv cap;
+
+ memset(&cap, 0, sizeof(cap));
+ cap.type = htons(TLV_TYPE_DYNAMIC_CAP);
+ cap.length = htons(CAP_TLV_DYNAMIC_LEN);
+ /* the S-bit is always 1 for the Dynamic Capability Announcement */
+ cap.reserved = STATE_BIT;
+
+ return (ibuf_add(buf, &cap, CAP_TLV_DYNAMIC_SIZE));
+}
diff --git a/usr.sbin/ldpd/labelmapping.c b/usr.sbin/ldpd/labelmapping.c
index 964cc44286e..580d3072452 100644
--- a/usr.sbin/ldpd/labelmapping.c
+++ b/usr.sbin/ldpd/labelmapping.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: labelmapping.c,v 1.64 2017/03/03 23:50:45 renato Exp $ */
+/* $OpenBSD: labelmapping.c,v 1.65 2017/03/04 00:06:10 renato Exp $ */
/*
* Copyright (c) 2014, 2015 Renato Westphal <renato@openbsd.org>
@@ -241,6 +241,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
/* Optional Parameters */
while (len > 0) {
struct tlv tlv;
+ uint16_t tlv_type;
uint16_t tlv_len;
uint32_t reqbuf, labelbuf, statusbuf;
@@ -250,6 +251,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
}
memcpy(&tlv, buf, TLV_HDR_SIZE);
+ tlv_type = ntohs(tlv.type);
tlv_len = ntohs(tlv.length);
if (tlv_len + TLV_HDR_SIZE > len) {
session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
@@ -258,7 +260,7 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
buf += TLV_HDR_SIZE;
len -= TLV_HDR_SIZE;
- switch (ntohs(tlv.type)) {
+ switch (tlv_type) {
case TLV_TYPE_LABELREQUEST:
switch (type) {
case MSG_TYPE_LABELMAPPING:
@@ -343,8 +345,8 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
break;
default:
if (!(ntohs(tlv.type) & UNKNOWN_FLAG))
- send_notification(nbr->tcp, S_UNKNOWN_TLV,
- msg.id, msg.type);
+ send_notification_rtlvs(nbr, S_UNKNOWN_TLV,
+ msg.id, msg.type, tlv_type, tlv_len, buf);
/* ignore unknown tlv */
break;
}
diff --git a/usr.sbin/ldpd/ldp.h b/usr.sbin/ldpd/ldp.h
index e8c007a9c08..dd00af9eb76 100644
--- a/usr.sbin/ldpd/ldp.h
+++ b/usr.sbin/ldpd/ldp.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldp.h,v 1.37 2017/03/03 23:56:54 renato Exp $ */
+/* $OpenBSD: ldp.h,v 1.38 2017/03/04 00:06:10 renato Exp $ */
/*
* Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -65,6 +65,7 @@
#define MSG_TYPE_HELLO 0x0100
#define MSG_TYPE_INIT 0x0200
#define MSG_TYPE_KEEPALIVE 0x0201
+#define MSG_TYPE_CAPABILITY 0x0202 /* RFC 5561 */
#define MSG_TYPE_ADDR 0x0300
#define MSG_TYPE_ADDRWITHDRAW 0x0301
#define MSG_TYPE_LABELMAPPING 0x0400
@@ -97,6 +98,9 @@
#define TLV_TYPE_PW_STATUS 0x896A
#define TLV_TYPE_PW_IF_PARAM 0x096B
#define TLV_TYPE_PW_GROUP_ID 0x096C
+/* RFC 5561 */
+#define TLV_TYPE_RETURNED_TLVS 0x8304
+#define TLV_TYPE_DYNAMIC_CAP 0x8506
/* RFC 7552 */
#define TLV_TYPE_DUALSTACK 0x8701
@@ -198,6 +202,8 @@ struct hello_prms_opt16_tlv {
#define S_UNASSIGN_TAI 0x00000029
#define S_MISCONF_ERR 0x0000002A
#define S_WITHDRAW_MTHD 0x0000002B
+/* RFC 5561 */
+#define S_UNSSUPORTDCAP 0x0000002E
/* RFC 7552 */
#define S_TRANS_MISMTCH 0x80000032
#define S_DS_NONCMPLNCE 0x80000033
@@ -229,6 +235,18 @@ struct status_tlv {
#define STATUS_TLV_LEN 10
#define STATUS_FATAL 0x80000000
+struct capability_tlv {
+ uint16_t type;
+ uint16_t length;
+ uint8_t reserved;
+};
+#define STATE_BIT 0x80
+
+#define F_CAP_TLV_RCVD_DYNAMIC 0x01
+
+#define CAP_TLV_DYNAMIC_SIZE 5
+#define CAP_TLV_DYNAMIC_LEN 1
+
#define AF_IPV4 0x1
#define AF_IPV6 0x2
diff --git a/usr.sbin/ldpd/ldpd.8 b/usr.sbin/ldpd/ldpd.8
index 9382991a2de..c270cba5fbe 100644
--- a/usr.sbin/ldpd/ldpd.8
+++ b/usr.sbin/ldpd/ldpd.8
@@ -1,4 +1,4 @@
-.\" $OpenBSD: ldpd.8,v 1.17 2017/03/03 23:30:57 renato Exp $
+.\" $OpenBSD: ldpd.8,v 1.18 2017/03/04 00:06:10 renato Exp $
.\"
.\" Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
.\" Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -16,7 +16,7 @@
.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.\"
-.Dd $Mdocdate: March 3 2017 $
+.Dd $Mdocdate: March 4 2017 $
.Dt LDPD 8
.Os
.Sh NAME
@@ -132,6 +132,17 @@ socket used for communication with
.Re
.Pp
.Rs
+.%A B. Thomas
+.%A K. Raza
+.%A S. Aggarwal
+.%A R. Aggarwal
+.%A JL. Le Roux
+.%D July 2009
+.%R RFC 5561
+.%T LDP Capabilities
+.Re
+.Pp
+.Rs
.%A C. Pignataro
.%A R. Asati
.%D August 2012
diff --git a/usr.sbin/ldpd/ldpd.h b/usr.sbin/ldpd/ldpd.h
index f5b2a96cac1..88353d8ddaa 100644
--- a/usr.sbin/ldpd/ldpd.h
+++ b/usr.sbin/ldpd/ldpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpd.h,v 1.83 2017/03/03 23:36:06 renato Exp $ */
+/* $OpenBSD: ldpd.h,v 1.84 2017/03/04 00:06:10 renato Exp $ */
/*
* Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -228,10 +228,16 @@ struct notify_msg {
uint16_t msg_type; /* network byte order */
uint32_t pw_status;
struct map fec;
+ struct {
+ uint16_t type;
+ uint16_t length;
+ char *data;
+ } rtlvs;
uint8_t flags;
};
#define F_NOTIF_PW_STATUS 0x01 /* pseudowire status tlv present */
#define F_NOTIF_FEC 0x02 /* fec tlv present */
+#define F_NOTIF_RETURNED_TLVS 0x04 /* returned tlvs present */
struct if_addr {
LIST_ENTRY(if_addr) entry;
diff --git a/usr.sbin/ldpd/ldpe.h b/usr.sbin/ldpd/ldpe.h
index 25295375119..a298f6e3967 100644
--- a/usr.sbin/ldpd/ldpe.h
+++ b/usr.sbin/ldpd/ldpe.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpe.h,v 1.71 2017/03/03 23:44:35 renato Exp $ */
+/* $OpenBSD: ldpe.h,v 1.72 2017/03/04 00:06:10 renato Exp $ */
/*
* Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -104,6 +104,7 @@ struct nbr {
int flags;
};
#define F_NBR_GTSM_NEGOTIATED 0x01
+#define F_NBR_CAP_DYNAMIC 0x02
RB_HEAD(nbr_id_head, nbr);
RB_PROTOTYPE(nbr_id_head, nbr, id_tree, nbr_id_compare)
@@ -152,6 +153,8 @@ void recv_hello(struct in_addr, struct ldp_msg *, int, union ldpd_addr *,
/* init.c */
void send_init(struct nbr *);
int recv_init(struct nbr *, char *, uint16_t);
+void send_capability(struct nbr *, uint16_t, int);
+int recv_capability(struct nbr *, char *, uint16_t);
/* keepalive.c */
void send_keepalive(struct nbr *);
@@ -160,6 +163,8 @@ int recv_keepalive(struct nbr *, char *, uint16_t);
/* notification.c */
void send_notification_full(struct tcp_conn *, struct notify_msg *);
void send_notification(struct tcp_conn *, uint32_t, uint32_t, uint16_t);
+void send_notification_rtlvs(struct nbr *, uint32_t, uint32_t, uint16_t,
+ uint16_t, uint16_t, char *);
int recv_notification(struct nbr *, char *, uint16_t);
int gen_status_tlv(struct ibuf *, uint32_t, uint32_t, uint16_t);
diff --git a/usr.sbin/ldpd/logmsg.c b/usr.sbin/ldpd/logmsg.c
index 568533f2dee..e71b6f79c81 100644
--- a/usr.sbin/ldpd/logmsg.c
+++ b/usr.sbin/ldpd/logmsg.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: logmsg.c,v 1.2 2017/03/04 00:03:04 renato Exp $ */
+/* $OpenBSD: logmsg.c,v 1.3 2017/03/04 00:06:10 renato Exp $ */
/*
* Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
@@ -303,6 +303,8 @@ msg_name(uint16_t msg)
return ("initialization");
case MSG_TYPE_KEEPALIVE:
return ("keepalive");
+ case MSG_TYPE_CAPABILITY:
+ return ("capability");
case MSG_TYPE_ADDR:
return ("address");
case MSG_TYPE_ADDRWITHDRAW:
@@ -396,6 +398,8 @@ status_code_name(uint32_t status)
return ("Generic Misconfiguration Error");
case S_WITHDRAW_MTHD:
return ("Label Withdraw PW Status Method");
+ case S_UNSSUPORTDCAP:
+ return ("Unsupported Capability");
case S_TRANS_MISMTCH:
return ("Transport Connection Mismatch");
case S_DS_NONCMPLNCE:
diff --git a/usr.sbin/ldpd/notification.c b/usr.sbin/ldpd/notification.c
index b8fab3476b5..962a1fea78c 100644
--- a/usr.sbin/ldpd/notification.c
+++ b/usr.sbin/ldpd/notification.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: notification.c,v 1.44 2017/03/03 23:50:45 renato Exp $ */
+/* $OpenBSD: notification.c,v 1.45 2017/03/04 00:06:10 renato Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -25,6 +25,7 @@
#include "log.h"
#include "ldpe.h"
+static int gen_returned_tlvs(struct ibuf *, uint16_t, uint16_t, char *);
static void log_msg_notification(int, struct nbr *, struct notify_msg *);
void
@@ -48,6 +49,8 @@ send_notification_full(struct tcp_conn *tcp, struct notify_msg *nm)
break;
}
}
+ if (nm->flags & F_NOTIF_RETURNED_TLVS)
+ size += TLV_HDR_SIZE * 2 + nm->rtlvs.length;
if ((buf = ibuf_open(size)) == NULL)
fatal(__func__);
@@ -61,6 +64,9 @@ send_notification_full(struct tcp_conn *tcp, struct notify_msg *nm)
err |= gen_pw_status_tlv(buf, nm->pw_status);
if (nm->flags & F_NOTIF_FEC)
err |= gen_fec_tlv(buf, &nm->fec);
+ if (nm->flags & F_NOTIF_RETURNED_TLVS)
+ err |= gen_returned_tlvs(buf, nm->rtlvs.type, nm->rtlvs.length,
+ nm->rtlvs.data);
if (err) {
ibuf_free(buf);
return;
@@ -89,6 +95,27 @@ send_notification(struct tcp_conn *tcp, uint32_t status_code, uint32_t msg_id,
send_notification_full(tcp, &nm);
}
+void
+send_notification_rtlvs(struct nbr *nbr, uint32_t status_code, uint32_t msg_id,
+ uint16_t msg_type, uint16_t tlv_type, uint16_t tlv_len, char *tlv_data)
+{
+ struct notify_msg nm;
+
+ memset(&nm, 0, sizeof(nm));
+ nm.status_code = status_code;
+ nm.msg_id = msg_id;
+ nm.msg_type = msg_type;
+ /* do not append the given TLV if it's too big (shouldn't happen) */
+ if (tlv_len < 1024) {
+ nm.rtlvs.type = tlv_type;
+ nm.rtlvs.length = tlv_len;
+ nm.rtlvs.data = tlv_data;
+ nm.flags |= F_NOTIF_RETURNED_TLVS;
+ }
+
+ send_notification_full(nbr->tcp, &nm);
+}
+
int
recv_notification(struct nbr *nbr, char *buf, uint16_t len)
{
@@ -121,6 +148,7 @@ recv_notification(struct nbr *nbr, char *buf, uint16_t len)
/* Optional Parameters */
while (len > 0) {
struct tlv tlv;
+ uint16_t tlv_type;
uint16_t tlv_len;
if (len < sizeof(tlv)) {
@@ -129,6 +157,7 @@ recv_notification(struct nbr *nbr, char *buf, uint16_t len)
}
memcpy(&tlv, buf, TLV_HDR_SIZE);
+ tlv_type = ntohs(tlv.type);
tlv_len = ntohs(tlv.length);
if (tlv_len + TLV_HDR_SIZE > len) {
session_shutdown(nbr, S_BAD_TLV_LEN, msg.id, msg.type);
@@ -137,7 +166,7 @@ recv_notification(struct nbr *nbr, char *buf, uint16_t len)
buf += TLV_HDR_SIZE;
len -= TLV_HDR_SIZE;
- switch (ntohs(tlv.type)) {
+ switch (tlv_type) {
case TLV_TYPE_EXTSTATUS:
case TLV_TYPE_RETURNEDPDU:
case TLV_TYPE_RETURNEDMSG:
@@ -167,8 +196,8 @@ recv_notification(struct nbr *nbr, char *buf, uint16_t len)
break;
default:
if (!(ntohs(tlv.type) & UNKNOWN_FLAG))
- send_notification(nbr->tcp, S_UNKNOWN_TLV,
- msg.id, msg.type);
+ send_notification_rtlvs(nbr, S_UNKNOWN_TLV,
+ msg.id, msg.type, tlv_type, tlv_len, buf);
/* ignore unknown tlv */
break;
}
@@ -230,6 +259,26 @@ gen_status_tlv(struct ibuf *buf, uint32_t status_code, uint32_t msg_id,
return (ibuf_add(buf, &st, STATUS_SIZE));
}
+static int
+gen_returned_tlvs(struct ibuf *buf, uint16_t type, uint16_t length,
+ char *tlv_data)
+{
+ struct tlv rtlvs;
+ struct tlv tlv;
+ int err;
+
+ rtlvs.type = htons(TLV_TYPE_RETURNED_TLVS);
+ rtlvs.length = htons(length + TLV_HDR_SIZE);
+ tlv.type = htons(type);
+ tlv.length = htons(length);
+
+ err = ibuf_add(buf, &rtlvs, sizeof(rtlvs));
+ err |= ibuf_add(buf, &tlv, sizeof(tlv));
+ err |= ibuf_add(buf, tlv_data, length);
+
+ return (err);
+}
+
void
log_msg_notification(int out, struct nbr *nbr, struct notify_msg *nm)
{
diff --git a/usr.sbin/ldpd/packet.c b/usr.sbin/ldpd/packet.c
index cfb9d2265d1..1e03a09bcee 100644
--- a/usr.sbin/ldpd/packet.c
+++ b/usr.sbin/ldpd/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.69 2017/03/03 23:44:35 renato Exp $ */
+/* $OpenBSD: packet.c,v 1.70 2017/03/04 00:06:10 renato Exp $ */
/*
* Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -518,13 +518,7 @@ session_read(int fd, short event, void *arg)
return;
}
break;
- case MSG_TYPE_ADDR:
- case MSG_TYPE_ADDRWITHDRAW:
- case MSG_TYPE_LABELMAPPING:
- case MSG_TYPE_LABELREQUEST:
- case MSG_TYPE_LABELWITHDRAW:
- case MSG_TYPE_LABELRELEASE:
- case MSG_TYPE_LABELABORTREQ:
+ default:
if (nbr->state != NBR_STA_OPER) {
session_shutdown(nbr, S_SHUTDOWN,
msg->id, msg->type);
@@ -532,8 +526,6 @@ session_read(int fd, short event, void *arg)
return;
}
break;
- default:
- break;
}
/* switch LDP packet type */
@@ -547,6 +539,9 @@ session_read(int fd, short event, void *arg)
case MSG_TYPE_KEEPALIVE:
ret = recv_keepalive(nbr, pdu, msg_size);
break;
+ case MSG_TYPE_CAPABILITY:
+ ret = recv_capability(nbr, pdu, msg_size);
+ break;
case MSG_TYPE_ADDR:
case MSG_TYPE_ADDRWITHDRAW:
ret = recv_address(nbr, pdu, msg_size);