summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRenato Westphal <renato@cvs.openbsd.org>2016-07-01 23:33:47 +0000
committerRenato Westphal <renato@cvs.openbsd.org>2016-07-01 23:33:47 +0000
commitb0e895600dbc97157dbeb3c284253888aafacecf (patch)
treed7cb3a4dbb7693c1cb67b543f01281c36decb08b
parent2d65c4f7cd8db7125bb35dfe33fffd414d78888d (diff)
Be more compliant with RFC 4447.
When sending a label withdraw during the pseudowire Control Word negotiation, append a "Wrong C-bit" status TLV after the FEC TLV (in conformance to RFC 4447 section 6.2). Apparently this has no use other than aiding in troubleshooting. Also, extend the recv_labelmessage() function to accept Status TLVs and ignore them instead of shutting down the session.
-rw-r--r--usr.sbin/ldpd/l2vpn.c10
-rw-r--r--usr.sbin/ldpd/labelmapping.c17
-rw-r--r--usr.sbin/ldpd/lde.c21
-rw-r--r--usr.sbin/ldpd/lde.h4
-rw-r--r--usr.sbin/ldpd/ldpd.h16
-rw-r--r--usr.sbin/ldpd/ldpe.h3
-rw-r--r--usr.sbin/ldpd/notification.c6
7 files changed, 53 insertions, 24 deletions
diff --git a/usr.sbin/ldpd/l2vpn.c b/usr.sbin/ldpd/l2vpn.c
index 0c973887a74..cdd0985ef5c 100644
--- a/usr.sbin/ldpd/l2vpn.c
+++ b/usr.sbin/ldpd/l2vpn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: l2vpn.c,v 1.19 2016/06/27 19:08:39 renato Exp $ */
+/* $OpenBSD: l2vpn.c,v 1.20 2016/07/01 23:33:46 renato Exp $ */
/*
* Copyright (c) 2015 Renato Westphal <renato@openbsd.org>
@@ -258,6 +258,7 @@ int
l2vpn_pw_negotiate(struct lde_nbr *ln, struct fec_node *fn, struct map *map)
{
struct l2vpn_pw *pw;
+ struct status_tlv status;
/* NOTE: thanks martini & friends for all this mess */
@@ -277,8 +278,11 @@ l2vpn_pw_negotiate(struct lde_nbr *ln, struct fec_node *fn, struct map *map)
return (1);
} else if (!(map->flags & F_MAP_PW_CWORD) &&
(pw->flags & F_PW_CWORD_CONF)) {
- /* TODO append a "Wrong C-bit" status code */
- lde_send_labelwithdraw(ln, fn, NO_LABEL);
+ /* append a "Wrong C-bit" status code */
+ status.status_code = S_WRONG_CBIT;
+ status.msg_id = map->messageid;
+ status.msg_type = htons(MSG_TYPE_LABELMAPPING);
+ lde_send_labelwithdraw(ln, fn, NO_LABEL, &status);
pw->flags &= ~F_PW_CWORD;
lde_send_labelmapping(ln, fn, 1);
diff --git a/usr.sbin/ldpd/labelmapping.c b/usr.sbin/ldpd/labelmapping.c
index 43dc7a0c32b..501cec93075 100644
--- a/usr.sbin/ldpd/labelmapping.c
+++ b/usr.sbin/ldpd/labelmapping.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: labelmapping.c,v 1.53 2016/07/01 23:29:55 renato Exp $ */
+/* $OpenBSD: labelmapping.c,v 1.54 2016/07/01 23:33:46 renato Exp $ */
/*
* Copyright (c) 2014, 2015 Renato Westphal <renato@openbsd.org>
@@ -75,7 +75,6 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh)
/* calculate size */
msg_size = LDP_MSG_SIZE + TLV_HDR_LEN;
-
switch (me->map.type) {
case MAP_TYPE_WILDCARD:
msg_size += FEC_ELM_WCARD_LEN;
@@ -95,11 +94,12 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh)
msg_size += PW_STATUS_TLV_LEN;
break;
}
-
if (me->map.label != NO_LABEL)
msg_size += LABEL_TLV_LEN;
if (me->map.flags & F_MAP_REQ_ID)
msg_size += REQID_TLV_LEN;
+ if (me->map.flags & F_MAP_STATUS)
+ msg_size += STATUS_SIZE;
/* maximum pdu length exceeded, we need a new ldp pdu */
if (size + msg_size > nbr->max_pdu_len) {
@@ -119,6 +119,9 @@ send_labelmessage(struct nbr *nbr, uint16_t type, struct mapping_head *mh)
err |= gen_reqid_tlv(buf, me->map.requestid);
if (me->map.flags & F_MAP_PW_STATUS)
err |= gen_pw_status_tlv(buf, me->map.pw_status);
+ if (me->map.flags & F_MAP_STATUS)
+ err |= gen_status_tlv(buf, me->map.status.code,
+ me->map.status.msg_id, me->map.status.msg_type);
if (err) {
ibuf_free(buf);
return;
@@ -304,6 +307,14 @@ recv_labelmessage(struct nbr *nbr, char *buf, uint16_t len, uint16_t type)
break;
}
break;
+ case TLV_TYPE_STATUS:
+ if (tlv_len != STATUS_TLV_LEN) {
+ session_shutdown(nbr, S_BAD_TLV_LEN,
+ lm.msgid, lm.type);
+ goto err;
+ }
+ /* ignore */
+ break;
case TLV_TYPE_PW_STATUS:
switch (type) {
case MSG_TYPE_LABELMAPPING:
diff --git a/usr.sbin/ldpd/lde.c b/usr.sbin/ldpd/lde.c
index cb0553d1eed..81fe48e256b 100644
--- a/usr.sbin/ldpd/lde.c
+++ b/usr.sbin/ldpd/lde.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: lde.c,v 1.59 2016/06/18 01:25:53 renato Exp $ */
+/* $OpenBSD: lde.c,v 1.60 2016/07/01 23:33:46 renato Exp $ */
/*
* Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -816,7 +816,8 @@ lde_send_labelmapping(struct lde_nbr *ln, struct fec_node *fn, int single)
}
void
-lde_send_labelwithdraw(struct lde_nbr *ln, struct fec_node *fn, uint32_t label)
+lde_send_labelwithdraw(struct lde_nbr *ln, struct fec_node *fn, uint32_t label,
+ struct status_tlv *status)
{
struct lde_wdraw *lw;
struct map map;
@@ -851,6 +852,13 @@ lde_send_labelwithdraw(struct lde_nbr *ln, struct fec_node *fn, uint32_t label)
map.label = label;
}
+ if (status) {
+ map.status.code = status->status_code;
+ map.status.msg_id = status->msg_id;
+ map.status.msg_type = status->msg_type;
+ map.flags |= F_MAP_STATUS;
+ }
+
/* SWd.1: send label withdraw. */
lde_imsg_compose_ldpe(IMSG_WITHDRAW_ADD, ln->peerid, 0,
&map, sizeof(map));
@@ -881,7 +889,7 @@ lde_send_labelwithdraw_all(struct fec_node *fn, uint32_t label)
struct lde_nbr *ln;
RB_FOREACH(ln, nbr_tree, &lde_nbrs)
- lde_send_labelwithdraw(ln, fn, label);
+ lde_send_labelwithdraw(ln, fn, label, NULL);
}
void
@@ -1182,14 +1190,15 @@ lde_change_egress_label(int af, int was_implicit)
RB_FOREACH(ln, nbr_tree, &lde_nbrs) {
/* explicit withdraw */
if (was_implicit)
- lde_send_labelwithdraw(ln, NULL, MPLS_LABEL_IMPLNULL);
+ lde_send_labelwithdraw(ln, NULL, MPLS_LABEL_IMPLNULL,
+ NULL);
else {
if (ln->v4_enabled)
lde_send_labelwithdraw(ln, NULL,
- MPLS_LABEL_IPV4NULL);
+ MPLS_LABEL_IPV4NULL, NULL);
if (ln->v6_enabled)
lde_send_labelwithdraw(ln, NULL,
- MPLS_LABEL_IPV6NULL);
+ MPLS_LABEL_IPV6NULL, NULL);
}
/* advertise new label of connected prefixes */
diff --git a/usr.sbin/ldpd/lde.h b/usr.sbin/ldpd/lde.h
index d882d77c0e8..3d2a06c48cb 100644
--- a/usr.sbin/ldpd/lde.h
+++ b/usr.sbin/ldpd/lde.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: lde.h,v 1.41 2016/06/18 17:13:05 renato Exp $ */
+/* $OpenBSD: lde.h,v 1.42 2016/07/01 23:33:46 renato Exp $ */
/*
* Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -134,7 +134,7 @@ void lde_map2fec(struct map *, struct in_addr, struct fec *);
void lde_send_labelmapping(struct lde_nbr *, struct fec_node *,
int);
void lde_send_labelwithdraw(struct lde_nbr *, struct fec_node *,
- uint32_t);
+ uint32_t, struct status_tlv *);
void lde_send_labelwithdraw_all(struct fec_node *, uint32_t);
void lde_send_labelrelease(struct lde_nbr *, struct fec_node *,
uint32_t);
diff --git a/usr.sbin/ldpd/ldpd.h b/usr.sbin/ldpd/ldpd.h
index 03a90a46a12..de7902f381b 100644
--- a/usr.sbin/ldpd/ldpd.h
+++ b/usr.sbin/ldpd/ldpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpd.h,v 1.78 2016/07/01 23:14:31 renato Exp $ */
+/* $OpenBSD: ldpd.h,v 1.79 2016/07/01 23:33:46 renato Exp $ */
/*
* Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -205,16 +205,22 @@ struct map {
uint16_t ifmtu;
} pwid;
} fec;
+ struct {
+ uint32_t code;
+ uint32_t msg_id;
+ uint16_t msg_type;
+ } status;
uint32_t label;
uint32_t requestid;
uint32_t pw_status;
uint8_t flags;
};
#define F_MAP_REQ_ID 0x01 /* optional request message id present */
-#define F_MAP_PW_CWORD 0x02 /* pseudowire control word */
-#define F_MAP_PW_ID 0x04 /* pseudowire connection id */
-#define F_MAP_PW_IFMTU 0x08 /* pseudowire interface parameter */
-#define F_MAP_PW_STATUS 0x10 /* pseudowire status */
+#define F_MAP_STATUS 0x02 /* status */
+#define F_MAP_PW_CWORD 0x04 /* pseudowire control word */
+#define F_MAP_PW_ID 0x08 /* pseudowire connection id */
+#define F_MAP_PW_IFMTU 0x10 /* pseudowire interface parameter */
+#define F_MAP_PW_STATUS 0x20 /* pseudowire status */
struct notify_msg {
uint32_t status;
diff --git a/usr.sbin/ldpd/ldpe.h b/usr.sbin/ldpd/ldpe.h
index 4d9d77dfc57..84f4c2a74ef 100644
--- a/usr.sbin/ldpd/ldpe.h
+++ b/usr.sbin/ldpd/ldpe.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ldpe.h,v 1.65 2016/07/01 23:29:55 renato Exp $ */
+/* $OpenBSD: ldpe.h,v 1.66 2016/07/01 23:33:46 renato Exp $ */
/*
* Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -163,6 +163,7 @@ void send_notification(uint32_t, struct tcp_conn *, uint32_t,
uint16_t);
void send_notification_nbr(struct nbr *, uint32_t, uint32_t, uint16_t);
int recv_notification(struct nbr *, char *, uint16_t);
+int gen_status_tlv(struct ibuf *, uint32_t, uint32_t, uint16_t);
/* address.c */
void send_address(struct nbr *, int, struct if_addr *, int);
diff --git a/usr.sbin/ldpd/notification.c b/usr.sbin/ldpd/notification.c
index 6c290ceaa82..b482c099068 100644
--- a/usr.sbin/ldpd/notification.c
+++ b/usr.sbin/ldpd/notification.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: notification.c,v 1.37 2016/07/01 23:29:55 renato Exp $ */
+/* $OpenBSD: notification.c,v 1.38 2016/07/01 23:33:46 renato Exp $ */
/*
* Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -25,8 +25,6 @@
#include "log.h"
#include "ldpe.h"
-static int gen_status_tlv(struct ibuf *, uint32_t, uint32_t, uint16_t);
-
void
send_notification_full(struct tcp_conn *tcp, struct notify_msg *nm)
{
@@ -221,7 +219,7 @@ recv_notification(struct nbr *nbr, char *buf, uint16_t len)
return (0);
}
-static int
+int
gen_status_tlv(struct ibuf *buf, uint32_t status, uint32_t msgid, uint16_t type)
{
struct status_tlv st;