diff options
Diffstat (limited to 'usr.sbin/ldpd/neighbor.c')
-rw-r--r-- | usr.sbin/ldpd/neighbor.c | 90 |
1 files changed, 89 insertions, 1 deletions
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 <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) { |