Be more compliant with RFC 4447.
authorrenato <renato@openbsd.org>
Fri, 1 Jul 2016 23:33:46 +0000 (23:33 +0000)
committerrenato <renato@openbsd.org>
Fri, 1 Jul 2016 23:33:46 +0000 (23:33 +0000)
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.

usr.sbin/ldpd/l2vpn.c
usr.sbin/ldpd/labelmapping.c
usr.sbin/ldpd/lde.c
usr.sbin/ldpd/lde.h
usr.sbin/ldpd/ldpd.h
usr.sbin/ldpd/ldpe.h
usr.sbin/ldpd/notification.c

index 0c97388..cdd0985 100644 (file)
@@ -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);
index 43dc7a0..501cec9 100644 (file)
@@ -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:
index cb0553d..81fe48e 100644 (file)
@@ -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 */
index d882d77..3d2a06c 100644 (file)
@@ -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);
index 03a90a4..de7902f 100644 (file)
@@ -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;
index 4d9d77d..84f4c2a 100644 (file)
@@ -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);
index 6c290ce..b482c09 100644 (file)
@@ -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;