From 5ff72af881a07ca50aa6c6a3def2c19ef3b2c9e6 Mon Sep 17 00:00:00 2001 From: renato Date: Fri, 1 Jul 2016 23:14:31 +0000 Subject: [PATCH] Add GTSM support (RFC 6720). 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@ --- usr.sbin/ldpd/hello.c | 12 ++++- usr.sbin/ldpd/ldp.h | 3 +- usr.sbin/ldpd/ldpd.8 | 12 ++++- usr.sbin/ldpd/ldpd.c | 26 ++++++++-- usr.sbin/ldpd/ldpd.conf.5 | 37 ++++++++++++- usr.sbin/ldpd/ldpd.h | 14 ++++- usr.sbin/ldpd/ldpe.h | 8 ++- usr.sbin/ldpd/neighbor.c | 90 +++++++++++++++++++++++++++++++- usr.sbin/ldpd/packet.c | 7 ++- usr.sbin/ldpd/parse.y | 22 +++++++- usr.sbin/ldpd/printconf.c | 17 +++++- usr.sbin/ldpd/socket.c | 106 +++++++++++++++++++++++++++++++++----- 12 files changed, 322 insertions(+), 32 deletions(-) diff --git a/usr.sbin/ldpd/hello.c b/usr.sbin/ldpd/hello.c index 5eb82617733..09c3976ed1e 100644 --- a/usr.sbin/ldpd/hello.c +++ b/usr.sbin/ldpd/hello.c @@ -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 @@ -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 && diff --git a/usr.sbin/ldpd/ldp.h b/usr.sbin/ldpd/ldp.h index 964a0be8dec..281decc7729 100644 --- a/usr.sbin/ldpd/ldp.h +++ b/usr.sbin/ldpd/ldp.h @@ -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 @@ -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; diff --git a/usr.sbin/ldpd/ldpd.8 b/usr.sbin/ldpd/ldpd.8 index b4de0adc9e0..6c2fd9b4801 100644 --- a/usr.sbin/ldpd/ldpd.8 +++ b/usr.sbin/ldpd/ldpd.8 @@ -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 .\" Copyright (c) 2009 Michele Marchetto @@ -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 diff --git a/usr.sbin/ldpd/ldpd.c b/usr.sbin/ldpd/ldpd.c index 9ef1e63d2a6..e2bc9d9a14b 100644 --- a/usr.sbin/ldpd/ldpd.c +++ b/usr.sbin/ldpd/ldpd.c @@ -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 @@ -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; diff --git a/usr.sbin/ldpd/ldpd.conf.5 b/usr.sbin/ldpd/ldpd.conf.5 index c9dbb9de895..686e3ccfc6d 100644 --- a/usr.sbin/ldpd/ldpd.conf.5 +++ b/usr.sbin/ldpd/ldpd.conf.5 @@ -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 .\" Copyright (c) 2009 Michele Marchetto @@ -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 diff --git a/usr.sbin/ldpd/ldpd.h b/usr.sbin/ldpd/ldpd.h index 3c59cc19783..03a90a46a12 100644 --- a/usr.sbin/ldpd/ldpd.h +++ b/usr.sbin/ldpd/ldpd.h @@ -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 @@ -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); diff --git a/usr.sbin/ldpd/ldpe.h b/usr.sbin/ldpd/ldpe.h index dade57be7d3..ac0a285f8b7 100644 --- a/usr.sbin/ldpd/ldpe.h +++ b/usr.sbin/ldpd/ldpe.h @@ -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 @@ -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); diff --git a/usr.sbin/ldpd/neighbor.c b/usr.sbin/ldpd/neighbor.c index 8f8cf4fe003..bf62c0dc5ad 100644 --- a/usr.sbin/ldpd/neighbor.c +++ b/usr.sbin/ldpd/neighbor.c @@ -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 @@ -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) { diff --git a/usr.sbin/ldpd/packet.c b/usr.sbin/ldpd/packet.c index a211994a9a2..ababd18b7ba 100644 --- a/usr.sbin/ldpd/packet.c +++ b/usr.sbin/ldpd/packet.c @@ -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 @@ -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"); diff --git a/usr.sbin/ldpd/parse.y b/usr.sbin/ldpd/parse.y index 4ba0249eaa0..98f0e1e3b7f 100644 --- a/usr.sbin/ldpd/parse.y +++ b/usr.sbin/ldpd/parse.y @@ -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 @@ -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}, diff --git a/usr.sbin/ldpd/printconf.c b/usr.sbin/ldpd/printconf.c index e26b57ebe73..32db88109df 100644 --- a/usr.sbin/ldpd/printconf.c +++ b/usr.sbin/ldpd/printconf.c @@ -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 @@ -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"); diff --git a/usr.sbin/ldpd/socket.c b/usr.sbin/ldpd/socket.c index 231bee08856..039241a6fb2 100644 --- a/usr.sbin/ldpd/socket.c +++ b/usr.sbin/ldpd/socket.c @@ -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 @@ -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) { -- 2.20.1