Like in nc(1) IPTOS_* (supposedly IPv4) values are used for the IPv6 path. That's not a concern in practice.
Index: ftpd.c =================================================================== RCS file: /cvs/src/libexec/ftpd/ftpd.c,v retrieving revision 1.221 diff -u -p -p -u -r1.221 ftpd.c --- ftpd.c 31 Aug 2016 13:43:36 -0000 1.221 +++ ftpd.c 31 Aug 2016 15:35:27 -0000 @@ -531,11 +531,18 @@ main(int argc, char *argv[]) reply(530, "System not available."); exit(1); } - if (his_addr.su_family == AF_INET) { - tos = IPTOS_LOWDELAY; + tos = IPTOS_LOWDELAY; + switch (his_addr.su_family) { + case AF_INET: if (setsockopt(0, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0) syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); + break; + case AF_INET6: + if (setsockopt(0, IPPROTO_IPV6, IPV6_TCLASS, &tos, + sizeof(int)) < 0) + syslog(LOG_WARNING, "setsockopt (IPV6_TCLASS): %m"); + break; } data_source.su_port = htons(ntohs(ctrl_addr.su_port) - 1); @@ -1269,7 +1276,7 @@ done: static FILE * getdatasock(char *mode) { - int on = 1, s, t, tries; + int on = 1, s, t, tos, tries; if (data >= 0) return (fdopen(data, mode)); @@ -1293,11 +1300,18 @@ getdatasock(char *mode) } sigprocmask (SIG_UNBLOCK, &allsigs, NULL); - if (ctrl_addr.su_family == AF_INET) { - on = IPTOS_THROUGHPUT; - if (setsockopt(s, IPPROTO_IP, IP_TOS, &on, + tos = IPTOS_THROUGHPUT; + switch (ctrl_addr.su_family) { + case AF_INET: + if (setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0) syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); + break; + case AF_INET6: + if (setsockopt(s, IPPROTO_IPV6, IPV6_TCLASS, &tos, + sizeof(int)) < 0) + syslog(LOG_WARNING, "setsockopt (IPV6_TCLASS): %m"); + break; } /* * Turn off push flag to keep sender TCP from sending short packets -- jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF DDCC 0DFA 74AE 1524 E7EE