Hi, Using relayd's redirect/forward on ipv6 addresses I discovered problems relating to setting TTL.
There is no check for address family and setsockopt tries to apply IP_TTL always. Without ip ttl on ipv6 table, check_icmp gives send_icmp: getsockopt: Invalid argument With ip ttl on ipv6 table, check_tcp gives hce_notify_done: fdaa:10:1:9::11 (tcp socket option) is the following diff valid? I've removed the IP_IPDEFTTL check. Was this ok? regards, Giannis Index: check_icmp.c =================================================================== RCS file: /cvs/src/usr.sbin/relayd/check_icmp.c,v retrieving revision 1.45 diff -u -p -r1.45 check_icmp.c --- check_icmp.c 28 May 2017 10:39:15 -0000 1.45 +++ check_icmp.c 23 Jun 2017 10:42:30 -0000 @@ -165,7 +165,7 @@ send_icmp(int s, short event, void *arg) struct icmp6_hdr *icp6; ssize_t r; u_char packet[ICMP_BUF_SIZE]; - socklen_t slen, len; + socklen_t slen; int i = 0, ttl; u_int32_t id; @@ -221,18 +221,18 @@ send_icmp(int s, short event, void *arg) } if ((ttl = host->conf.ttl) > 0) - (void)setsockopt(s, IPPROTO_IP, IP_TTL, - &host->conf.ttl, sizeof(int)); - else { - /* Revert to default TTL */ - len = sizeof(ttl); - if (getsockopt(s, IPPROTO_IP, IP_IPDEFTTL, - &ttl, &len) == 0) - (void)setsockopt(s, IPPROTO_IP, IP_TTL, - &ttl, len); - else - log_warn("%s: getsockopt",__func__); - } + switch(cie->af) { + case AF_INET: + if (setsockopt(s, IPPROTO_IP, IP_TTL, + &host->conf.ttl, sizeof(int)) == -1) + log_warn("%s: setsockopt",__func__); + break; + case AF_INET6: + if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, + &host->conf.ttl, sizeof(int)) == -1) + log_warn("%s: setsockopt",__func__); + break; + } r = sendto(s, packet, sizeof(packet), 0, to, slen); if (r == -1) { Index: check_tcp.c =================================================================== RCS file: /cvs/src/usr.sbin/relayd/check_tcp.c,v retrieving revision 1.54 diff -u -p -r1.54 check_tcp.c --- check_tcp.c 28 May 2017 10:39:15 -0000 1.54 +++ check_tcp.c 23 Jun 2017 10:42:30 -0000 @@ -82,11 +82,19 @@ check_tcp(struct ctl_tcp_event *cte) if (setsockopt(s, SOL_SOCKET, SO_LINGER, &lng, sizeof(lng)) == -1) goto bad; - if (cte->host->conf.ttl > 0) { - if (setsockopt(s, IPPROTO_IP, IP_TTL, - &cte->host->conf.ttl, sizeof(int)) == -1) - goto bad; - } + if (cte->host->conf.ttl > 0) + switch (cte->host->conf.ss.ss_family) { + case AF_INET: + if (setsockopt(s, IPPROTO_IP, IP_TTL, + &cte->host->conf.ttl, sizeof(int)) == -1) + goto bad; + break; + case AF_INET6: + if (setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS, + &cte->host->conf.ttl, sizeof(int)) == -1) + goto bad; + break; + } bcopy(&cte->table->conf.timeout, &tv, sizeof(tv)); if (connect(s, (struct sockaddr *)&cte->host->conf.ss, len) == -1) {