Add GTSM support (RFC 6720).
authorrenato <renato@openbsd.org>
Fri, 1 Jul 2016 23:14:31 +0000 (23:14 +0000)
committerrenato <renato@openbsd.org>
Fri, 1 Jul 2016 23:14:31 +0000 (23:14 +0000)
This also finishes the missing bits from our RFC 7552 implementation
because GTSM is mandatory for LDPv6.

To avoid any kind of interoperability problems, I included a few
knobs to enable/disable GTSM on a per-address-family and per-neighbor
basis. Cisco's LDPv6 implementation, for instance, doesn't support GTSM.

"reads good" claudio@

12 files changed:
usr.sbin/ldpd/hello.c
usr.sbin/ldpd/ldp.h
usr.sbin/ldpd/ldpd.8
usr.sbin/ldpd/ldpd.c
usr.sbin/ldpd/ldpd.conf.5
usr.sbin/ldpd/ldpd.h
usr.sbin/ldpd/ldpe.h
usr.sbin/ldpd/neighbor.c
usr.sbin/ldpd/packet.c
usr.sbin/ldpd/parse.y
usr.sbin/ldpd/printconf.c
usr.sbin/ldpd/socket.c

index 5eb8261..09c3976 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: hello.c,v 1.52 2016/06/27 19:18:54 renato Exp $ */
+/*     $OpenBSD: hello.c,v 1.53 2016/07/01 23:14:31 renato Exp $ */
 
 /*
  * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -53,6 +53,8 @@ send_hello(enum hello_type type, struct iface_af *ia, struct tnbr *tnbr)
                /* multicast destination address */
                switch (af) {
                case AF_INET:
+                       if (!(leconf->ipv4.flags & F_LDPD_AF_NO_GTSM))
+                               flags |= GTSM_HELLO;
                        dst.v4 = global.mcast_addr_v4;
                        break;
                case AF_INET6:
@@ -363,6 +365,14 @@ recv_hello(struct in_addr lsr_id, struct ldp_msg *lm, int af,
            (trans_pref == DUAL_STACK_LDPOV6 && af == AF_INET6))))
                nbr = nbr_new(lsr_id, af, ds_tlv, &trans_addr, scope_id);
 
+       /* dynamic LDPv4 GTSM negotiation as per RFC 6720 */
+       if (nbr) {
+               if (flags & GTSM_HELLO)
+                       nbr->flags |= F_NBR_GTSM_NEGOTIATED;
+               else
+                       nbr->flags &= ~F_NBR_GTSM_NEGOTIATED;
+       }
+
        /* update neighbor's configuration sequence number */
        if (nbr && (tlvs_rcvd & F_HELLO_TLV_RCVD_CONF)) {
                if (conf_seqnum > nbr->conf_seqnum &&
index 964a0be..281decc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ldp.h,v 1.29 2016/05/23 19:14:03 renato Exp $ */
+/*     $OpenBSD: ldp.h,v 1.30 2016/07/01 23:14:31 renato Exp $ */
 
 /*
  * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -142,6 +142,7 @@ struct hello_prms_tlv {
 
 #define TARGETED_HELLO         0x8000
 #define REQUEST_TARG_HELLO     0x4000
+#define GTSM_HELLO             0x2000
 
 struct hello_prms_opt4_tlv {
        uint16_t        type;
index b4de0ad..6c2fd9b 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: ldpd.8,v 1.15 2016/05/23 19:14:03 renato Exp $
+.\"    $OpenBSD: ldpd.8,v 1.16 2016/07/01 23:14:31 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: May 23 2016 $
+.Dd $Mdocdate: July 1 2016 $
 .Dt LDPD 8
 .Os
 .Sh NAME
@@ -129,6 +129,14 @@ socket used for communication with
 .Re
 .Pp
 .Rs
+.%A C. Pignataro
+.%A R. Asati
+.%D August 2012
+.%R RFC 6720
+.%T The Generalized TTL Security Mechanism (GTSM) for the Label Distribution Protocol (LDP)
+.Re
+.Pp
+.Rs
 .%A R. Asati
 .%A C. Pignataro
 .%A K. Raza
index 9ef1e63..e2bc9d9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ldpd.c,v 1.54 2016/06/18 17:13:05 renato Exp $ */
+/*     $OpenBSD: ldpd.c,v 1.55 2016/07/01 23:14:31 renato Exp $ */
 
 /*
  * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -813,6 +813,7 @@ static void
 merge_af(int af, struct ldpd_af_conf *af_conf, struct ldpd_af_conf *xa)
 {
        int                      egress_label_changed = 0;
+       int                      update_sockets = 0;
 
        if (af_conf->keepalive != xa->keepalive) {
                af_conf->keepalive = xa->keepalive;
@@ -828,6 +829,16 @@ merge_af(int af, struct ldpd_af_conf *af_conf, struct ldpd_af_conf *xa)
            !(xa->flags & F_LDPD_AF_THELLO_ACCEPT))
                ldpe_remove_dynamic_tnbrs(af);
 
+       if ((af_conf->flags & F_LDPD_AF_NO_GTSM) !=
+           (xa->flags & F_LDPD_AF_NO_GTSM)) {
+               if (af == AF_INET6)
+                       /* need to set/unset IPV6_MINHOPCOUNT */
+                       update_sockets = 1;
+               else if (ldpd_process == PROC_LDP_ENGINE)
+                       /* for LDPv4 just resetting the neighbors is enough */
+                       ldpe_reset_nbrs(af);
+       }
+
        if ((af_conf->flags & F_LDPD_AF_EXPNULL) !=
            (xa->flags & F_LDPD_AF_EXPNULL))
                egress_label_changed = 1;
@@ -851,10 +862,12 @@ merge_af(int af, struct ldpd_af_conf *af_conf, struct ldpd_af_conf *xa)
 
        if (ldp_addrcmp(af, &af_conf->trans_addr, &xa->trans_addr)) {
                af_conf->trans_addr = xa->trans_addr;
-               if (ldpd_process == PROC_MAIN)
-                       imsg_compose_event(iev_ldpe, IMSG_CLOSE_SOCKETS, af,
-                           0, -1, NULL, 0);
+               update_sockets = 1;
        }
+
+       if (ldpd_process == PROC_MAIN && update_sockets)
+               imsg_compose_event(iev_ldpe, IMSG_CLOSE_SOCKETS, af, 0, -1,
+                   NULL, 0);
 }
 
 static void
@@ -988,7 +1001,10 @@ merge_nbrps(struct ldpd_conf *conf, struct ldpd_conf *xconf)
                }
 
                /* update existing nbrps */
-               if (nbrp->keepalive != xn->keepalive ||
+               if (nbrp->flags != xn->flags ||
+                   nbrp->keepalive != xn->keepalive ||
+                   nbrp->gtsm_enabled != xn->gtsm_enabled ||
+                   nbrp->gtsm_hops != xn->gtsm_hops ||
                    nbrp->auth.method != xn->auth.method ||
                    strcmp(nbrp->auth.md5key, xn->auth.md5key) != 0)
                        nbrp_changed = 1;
index c9dbb9d..686e3cc 100644 (file)
@@ -1,4 +1,4 @@
-.\"    $OpenBSD: ldpd.conf.5,v 1.29 2016/05/23 21:05:07 jmc Exp $
+.\"    $OpenBSD: ldpd.conf.5,v 1.30 2016/07/01 23:14:31 renato Exp $
 .\"
 .\" Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
 .\" Copyright (c) 2009 Michele Marchetto <michele@openbsd.org>
@@ -19,7 +19,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: May 23 2016 $
+.Dd $Mdocdate: July 1 2016 $
 .Dt LDPD.CONF 5
 .Os
 .Sh NAME
@@ -145,6 +145,28 @@ connected prefixes.
 The default is
 .Ic no .
 .Pp
+.It Xo
+.Ic gtsm-enable
+.Pq Ic yes Ns | Ns Ic no
+.Xc
+If set to
+.Ic yes ,
+.Xr ldpd 8
+will use the GTSM procedures described in RFC 6720 (for the IPv4 address-family)
+and RFC 7552 (for the IPv6 address-family).
+.Pp
+Since GTSM is mandatory for LDPv6, the only effect of disabling GTSM for the
+IPv6 address-family is that
+.Xr ldpd 8
+will not check the incoming packets' Hop Limit.
+Outgoing packets will still be sent using a Hop Limit of 255 to guarantee
+interoperability.
+.Pp
+If GTSM is enabled, multi-hop neighbors should have either GTSM disabled
+individually or configured with an appropriate gtsm-hops distance.
+The default is
+.Ic yes .
+.Pp
 .It Ic keepalive Ar seconds
 Set the keepalive timeout in seconds.
 The default value is 180; valid range is 3\-65535.
@@ -239,6 +261,17 @@ Neighbor-specific parameters are listed below.
 Set the keepalive timeout in seconds.
 Inherited from the global configuration if not given.
 The default value is 180; valid range is 3\-65535.
+.It Xo
+.Ic gtsm-enable
+.Pq Ic yes Ns | Ns Ic no
+.Xc
+Override the inherited configuration and enable/disable GTSM for this neighbor.
+.It Ic gtsm-hops Ar hops
+Set the maximum number of hops the neighbor may be away.
+When GTSM is enabled for this neighbor, incoming packets are required to have
+a TTL/Hop Limit of 256 minus this value, ensuring they have not passed
+through more than the expected number of hops.
+The default value is 1; valid range is 1\-255.
 .It Ic password Ar secret
 Enable TCP MD5 signatures per RFC 5036.
 .El
index 3c59cc1..03a90a4 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ldpd.h,v 1.77 2016/06/13 23:01:37 renato Exp $ */
+/*     $OpenBSD: ldpd.h,v 1.78 2016/07/01 23:14:31 renato Exp $ */
 
 /*
  * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -288,6 +288,8 @@ struct nbr_params {
        LIST_ENTRY(nbr_params)   entry;
        struct in_addr           lsr_id;
        uint16_t                 keepalive;
+       int                      gtsm_enabled;
+       uint8_t                  gtsm_hops;
        struct {
                enum auth_method         method;
                char                     md5key[TCP_MD5_KEY_LEN];
@@ -296,6 +298,8 @@ struct nbr_params {
        uint8_t                  flags;
 };
 #define F_NBRP_KEEPALIVE        0x01
+#define F_NBRP_GTSM             0x02
+#define F_NBRP_GTSM_HOPS        0x04
 
 struct l2vpn_if {
        LIST_ENTRY(l2vpn_if)     entry;
@@ -368,6 +372,7 @@ struct ldpd_af_conf {
 #define        F_LDPD_AF_ENABLED       0x0001
 #define        F_LDPD_AF_THELLO_ACCEPT 0x0002
 #define        F_LDPD_AF_EXPNULL       0x0004
+#define        F_LDPD_AF_NO_GTSM       0x0008
 
 struct ldpd_conf {
        struct in_addr           rtr_id;
@@ -574,13 +579,18 @@ int                ldp_create_socket(int, enum socket_type);
 void            sock_set_recvbuf(int);
 int             sock_set_reuse(int, int);
 int             sock_set_bindany(int, int);
-int             sock_set_ipv4_mcast_ttl(int, uint8_t);
 int             sock_set_ipv4_tos(int, int);
 int             sock_set_ipv4_recvif(int, int);
+int             sock_set_ipv4_minttl(int, int);
+int             sock_set_ipv4_ucast_ttl(int fd, int);
+int             sock_set_ipv4_mcast_ttl(int, uint8_t);
 int             sock_set_ipv4_mcast(struct iface *);
 int             sock_set_ipv4_mcast_loop(int);
 int             sock_set_ipv6_dscp(int, int);
 int             sock_set_ipv6_pktinfo(int, int);
+int             sock_set_ipv6_minhopcount(int, int);
+int             sock_set_ipv6_ucast_hops(int, int);
+int             sock_set_ipv6_mcast_hops(int, int);
 int             sock_set_ipv6_mcast(struct iface *);
 int             sock_set_ipv6_mcast_loop(int);
 
index dade57b..ac0a285 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: ldpe.h,v 1.63 2016/06/27 19:06:33 renato Exp $ */
+/*     $OpenBSD: ldpe.h,v 1.64 2016/07/01 23:14:31 renato Exp $ */
 
 /*
  * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -101,7 +101,10 @@ struct nbr {
                enum auth_method        method;
                char                    md5key[TCP_MD5_KEY_LEN];
        } auth;
+       int                      flags;
 };
+#define F_NBR_GTSM_NEGOTIATED   0x01
+
 RB_HEAD(nbr_id_head, nbr);
 RB_PROTOTYPE(nbr_id_head, nbr, id_tree, nbr_id_compare)
 RB_HEAD(nbr_addr_head, nbr);
@@ -236,6 +239,9 @@ void                         nbr_stop_idtimer(struct nbr *);
 int                     nbr_pending_idtimer(struct nbr *);
 int                     nbr_pending_connect(struct nbr *);
 int                     nbr_establish_connection(struct nbr *);
+int                     nbr_gtsm_enabled(struct nbr *, struct nbr_params *);
+int                     nbr_gtsm_setup(int, int, struct nbr_params *);
+int                     nbr_gtsm_check(int, struct nbr *, struct nbr_params *);
 struct nbr_params      *nbr_params_new(struct in_addr);
 struct nbr_params      *nbr_params_find(struct ldpd_conf *, struct in_addr);
 uint16_t                nbr_get_keepalive(int, struct in_addr);
index 8f8cf4f..bf62c0d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: neighbor.c,v 1.74 2016/06/13 23:01:37 renato Exp $ */
+/*     $OpenBSD: neighbor.c,v 1.75 2016/07/01 23:14:31 renato Exp $ */
 
 /*
  * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -608,6 +608,11 @@ nbr_establish_connection(struct nbr *nbr)
                return (-1);
        }
 
+       if (nbr_gtsm_check(nbr->fd, nbr, nbrp)) {
+               close(nbr->fd);
+               return (-1);
+       }
+
        /*
         * Send an extra hello to guarantee that the remote peer has formed
         * an adjacency as well.
@@ -636,6 +641,89 @@ nbr_establish_connection(struct nbr *nbr)
        return (0);
 }
 
+int
+nbr_gtsm_enabled(struct nbr *nbr, struct nbr_params *nbrp)
+{
+       /*
+        * RFC 6720 - Section 3:
+        * "This document allows for the implementation to provide an option to
+        * statically (e.g., via configuration) and/or dynamically override the
+        * default behavior and enable/disable GTSM on a per-peer basis".
+        */
+       if (nbrp && (nbrp->flags & F_NBRP_GTSM))
+               return (nbrp->gtsm_enabled);
+
+       if ((ldp_af_conf_get(leconf, nbr->af))->flags & F_LDPD_AF_NO_GTSM)
+               return (0);
+
+       /* By default, GTSM support has to be negotiated for LDPv4 */
+       if (nbr->af == AF_INET && !(nbr->flags & F_NBR_GTSM_NEGOTIATED))
+               return (0);
+
+       return (1);
+}
+
+int
+nbr_gtsm_setup(int fd, int af, struct nbr_params *nbrp)
+{
+       int      ttl = 255;
+
+       if (nbrp && (nbrp->flags & F_NBRP_GTSM_HOPS))
+               ttl = 256 - nbrp->gtsm_hops;
+
+       switch (af) {
+       case AF_INET:
+               if (sock_set_ipv4_minttl(fd, ttl) == -1)
+                       return (-1);
+               ttl = 255;
+               if (sock_set_ipv4_ucast_ttl(fd, ttl) == -1)
+                       return (-1);
+               break;
+       case AF_INET6:
+               if (sock_set_ipv6_minhopcount(fd, ttl) == -1)
+                       return (-1);
+               ttl = 255;
+               if (sock_set_ipv6_ucast_hops(fd, ttl) == -1)
+                       return (-1);
+               break;
+       default:
+               fatalx("nbr_gtsm_setup: unknown af");
+       }
+
+       return (0);
+}
+
+int
+nbr_gtsm_check(int fd, struct nbr *nbr, struct nbr_params *nbrp)
+{
+       if (!nbr_gtsm_enabled(nbr, nbrp)) {
+               switch (nbr->af) {
+               case AF_INET:
+                       sock_set_ipv4_ucast_ttl(fd, -1);
+                       break;
+               case AF_INET6:
+                       /*
+                        * Send packets with a Hop Limit of 255 even when GSTM
+                        * is disabled to guarantee interoperability.
+                        */
+                       sock_set_ipv6_ucast_hops(fd, 255);
+                       break;
+               default:
+                       fatalx("nbr_gtsm_check: unknown af");
+                       break;
+               }
+               return (0);
+       }
+
+       if (nbr_gtsm_setup(fd, nbr->af, nbrp) == -1) {
+               log_warnx("%s: error enabling GTSM for lsr-id %s", __func__,
+                   inet_ntoa(nbr->id));
+               return (-1);
+       }
+
+       return (0);
+}
+
 static int
 nbr_act_session_operational(struct nbr *nbr)
 {
index a211994..ababd18 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: packet.c,v 1.64 2016/06/18 17:31:32 renato Exp $ */
+/*     $OpenBSD: packet.c,v 1.65 2016/07/01 23:14:31 renato Exp $ */
 
 /*
  * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -387,6 +387,11 @@ session_accept_nbr(struct nbr *nbr, int fd)
        socklen_t                len;
 
        nbrp = nbr_params_find(leconf, nbr->id);
+       if (nbr_gtsm_check(fd, nbr, nbrp)) {
+               close(fd);
+               return;
+       }
+
        if (nbrp && nbrp->auth.method == AUTH_MD5SIG) {
                if (sysdep.no_pfkey || sysdep.no_md5sig) {
                        log_warnx("md5sig configured but not available");
index 4ba0249..98f0e1e 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: parse.y,v 1.56 2016/06/21 21:35:24 benno Exp $ */
+/*     $OpenBSD: parse.y,v 1.57 2016/07/01 23:14:31 renato Exp $ */
 
 /*
  * Copyright (c) 2013, 2015, 2016 Renato Westphal <renato@openbsd.org>
@@ -136,7 +136,7 @@ static int                   pushback_index;
 %token INTERFACE TNEIGHBOR ROUTERID FIBUPDATE EXPNULL
 %token LHELLOHOLDTIME LHELLOINTERVAL
 %token THELLOHOLDTIME THELLOINTERVAL
-%token THELLOACCEPT AF IPV4 IPV6
+%token THELLOACCEPT AF IPV4 IPV6 GTSMENABLE GTSMHOPS
 %token KEEPALIVE TRANSADDRESS TRANSPREFERENCE DSCISCOINTEROP
 %token NEIGHBOR PASSWORD
 %token L2VPN TYPE VPLS PWTYPE MTU BRIDGE
@@ -324,6 +324,10 @@ afoptsl            :  TRANSADDRESS STRING {
                                YYERROR;
                        }
                }
+               | GTSMENABLE yesno {
+                       if ($2 == 0)
+                               defs->afflags |= F_LDPD_AF_NO_GTSM;
+               }
                | af_defaults
                | iface_defaults
                | tnbr_defaults
@@ -413,6 +417,18 @@ nbr_opts   : KEEPALIVE NUMBER {
                        nbrp->auth.method = AUTH_MD5SIG;
                        free($2);
                }
+               | GTSMENABLE yesno {
+                       nbrp->flags |= F_NBRP_GTSM;
+                       nbrp->gtsm_enabled = $2;
+               }
+               | GTSMHOPS NUMBER {
+                       if ($2 < 1 || $2 > 255) {
+                               yyerror("invalid number of hops %lld", $2);
+                               YYERROR;
+                       }
+                       nbrp->gtsm_hops = $2;
+                       nbrp->flags |= F_NBRP_GTSM_HOPS;
+               }
                ;
 
 pw_defaults    : STATUSTLV yesno {
@@ -807,6 +823,8 @@ lookup(char *s)
                {"ethernet-tagged",             ETHERNETTAGGED},
                {"explicit-null",               EXPNULL},
                {"fib-update",                  FIBUPDATE},
+               {"gtsm-enable",                 GTSMENABLE},
+               {"gtsm-hops",                   GTSMHOPS},
                {"include",                     INCLUDE},
                {"interface",                   INTERFACE},
                {"ipv4",                        IPV4},
index e26b57e..32db881 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: printconf.c,v 1.25 2016/05/23 19:14:03 renato Exp $ */
+/*     $OpenBSD: printconf.c,v 1.26 2016/07/01 23:14:31 renato Exp $ */
 
 /*
  * Copyright (c) 2013, 2016 Renato Westphal <renato@openbsd.org>
@@ -74,6 +74,11 @@ print_af(int af, struct ldpd_conf *conf, struct ldpd_af_conf *af_conf)
        else
                printf("\texplicit-null no\n");
 
+       if (af_conf->flags & F_LDPD_AF_NO_GTSM)
+               printf("\tgtsm-enable no\n");
+       else
+               printf("\tgtsm-enable yes\n");
+
        printf("\tkeepalive %u\n", af_conf->keepalive);
        printf("\ttransport-address %s\n", log_addr(af, &af_conf->trans_addr));
 
@@ -116,6 +121,16 @@ print_nbrp(struct nbr_params *nbrp)
        if (nbrp->flags & F_NBRP_KEEPALIVE)
                printf("\tkeepalive %u\n", nbrp->keepalive);
 
+       if (nbrp->flags & F_NBRP_GTSM) {
+               if (nbrp->gtsm_enabled)
+                       printf("\tgtsm-enable yes\n");
+               else
+                       printf("\tgtsm-enable no\n");
+       }
+
+       if (nbrp->flags & F_NBRP_GTSM_HOPS)
+               printf("\tgtsm-hops %u\n", nbrp->gtsm_hops);
+
        if (nbrp->auth.method == AUTH_MD5SIG)
                printf("\tpassword XXXXXX\n");
 
index 231bee0..039241a 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: socket.c,v 1.7 2016/05/23 19:09:25 renato Exp $ */
+/*     $OpenBSD: socket.c,v 1.8 2016/07/01 23:14:31 renato Exp $ */
 
 /*
  * Copyright (c) 2016 Renato Westphal <renato@openbsd.org>
@@ -112,6 +112,12 @@ ldp_create_socket(int af, enum socket_type type)
                                return (-1);
                        }
                }
+               if (type == LDP_SOCKET_SESSION) {
+                       if (sock_set_ipv4_ucast_ttl(fd, 255) == -1) {
+                               close(fd);
+                               return (-1);
+                       }
+               }
                break;
        case AF_INET6:
                if (sock_set_ipv6_dscp(fd, IPTOS_PREC_INTERNETCONTROL) == -1) {
@@ -123,6 +129,16 @@ ldp_create_socket(int af, enum socket_type type)
                                close(fd);
                                return (-1);
                        }
+                       if (sock_set_ipv6_mcast_hops(fd, 255) == -1) {
+                               close(fd);
+                               return (-1);
+                       }
+                       if (!(ldpd_conf->ipv6.flags & F_LDPD_AF_NO_GTSM)) {
+                               if (sock_set_ipv6_minhopcount(fd, 255) == -1) {
+                                       close(fd);
+                                       return (-1);
+                               }
+                       }
                }
                if (type == LDP_SOCKET_DISC || type == LDP_SOCKET_EDISC) {
                        if (sock_set_ipv6_pktinfo(fd, 1) == -1) {
@@ -130,6 +146,12 @@ ldp_create_socket(int af, enum socket_type type)
                                return (-1);
                        }
                }
+               if (type == LDP_SOCKET_SESSION) {
+                       if (sock_set_ipv6_ucast_hops(fd, 255) == -1) {
+                               close(fd);
+                               return (-1);
+                       }
+               }
                break;
        }
        switch (type) {
@@ -194,12 +216,10 @@ sock_set_bindany(int fd, int enable)
 }
 
 int
-sock_set_ipv4_mcast_ttl(int fd, uint8_t ttl)
+sock_set_ipv4_tos(int fd, int tos)
 {
-       if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL,
-           (char *)&ttl, sizeof(ttl)) < 0) {
-               log_warn("%s: error setting IP_MULTICAST_TTL to %d",
-                   __func__, ttl);
+       if (setsockopt(fd, IPPROTO_IP, IP_TOS, (int *)&tos, sizeof(tos)) < 0) {
+               log_warn("%s: error setting IP_TOS to 0x%x", __func__, tos);
                return (-1);
        }
 
@@ -207,10 +227,21 @@ sock_set_ipv4_mcast_ttl(int fd, uint8_t ttl)
 }
 
 int
-sock_set_ipv4_tos(int fd, int tos)
+sock_set_ipv4_recvif(int fd, int enable)
 {
-       if (setsockopt(fd, IPPROTO_IP, IP_TOS, (int *)&tos, sizeof(tos)) < 0) {
-               log_warn("%s: error setting IP_TOS to 0x%x", __func__, tos);
+       if (setsockopt(fd, IPPROTO_IP, IP_RECVIF, &enable,
+           sizeof(enable)) < 0) {
+               log_warn("%s: error setting IP_RECVIF", __func__);
+               return (-1);
+       }
+       return (0);
+}
+
+int
+sock_set_ipv4_minttl(int fd, int ttl)
+{
+       if (setsockopt(fd, IPPROTO_IP, IP_MINTTL, &ttl, sizeof(ttl)) < 0) {
+               log_warn("%s: error setting IP_MINTTL", __func__);
                return (-1);
        }
 
@@ -218,13 +249,26 @@ sock_set_ipv4_tos(int fd, int tos)
 }
 
 int
-sock_set_ipv4_recvif(int fd, int enable)
+sock_set_ipv4_ucast_ttl(int fd, int ttl)
 {
-       if (setsockopt(fd, IPPROTO_IP, IP_RECVIF, &enable,
-           sizeof(enable)) < 0) {
-               log_warn("%s: error setting IP_RECVIF", __func__);
+       if (setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) < 0) {
+               log_warn("%s: error setting IP_TTL", __func__);
                return (-1);
        }
+
+       return (0);
+}
+
+int
+sock_set_ipv4_mcast_ttl(int fd, uint8_t ttl)
+{
+       if (setsockopt(fd, IPPROTO_IP, IP_MULTICAST_TTL,
+           (char *)&ttl, sizeof(ttl)) < 0) {
+               log_warn("%s: error setting IP_MULTICAST_TTL to %d",
+                   __func__, ttl);
+               return (-1);
+       }
+
        return (0);
 }
 
@@ -283,6 +327,42 @@ sock_set_ipv6_pktinfo(int fd, int enable)
        return (0);
 }
 
+int
+sock_set_ipv6_minhopcount(int fd, int hoplimit)
+{
+       if (setsockopt(fd, IPPROTO_IPV6, IPV6_MINHOPCOUNT,
+           &hoplimit, sizeof(hoplimit)) < 0) {
+               log_warn("%s: error setting IPV6_MINHOPCOUNT", __func__);
+               return (-1);
+       }
+
+       return (0);
+}
+
+int
+sock_set_ipv6_ucast_hops(int fd, int hoplimit)
+{
+       if (setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
+           &hoplimit, sizeof(hoplimit)) < 0) {
+               log_warn("%s: error setting IPV6_UNICAST_HOPS", __func__);
+               return (-1);
+       }
+
+       return (0);
+}
+
+int
+sock_set_ipv6_mcast_hops(int fd, int hoplimit)
+{
+       if (setsockopt(fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+           &hoplimit, sizeof(hoplimit)) < 0) {
+               log_warn("%s: error setting IPV6_MULTICAST_HOPS", __func__);
+               return (-1);
+       }
+
+       return (0);
+}
+
 int
 sock_set_ipv6_mcast(struct iface *iface)
 {