diff options
-rw-r--r-- | usr.sbin/traceroute6/traceroute6.8 | 20 | ||||
-rw-r--r-- | usr.sbin/traceroute6/traceroute6.c | 44 |
2 files changed, 56 insertions, 8 deletions
diff --git a/usr.sbin/traceroute6/traceroute6.8 b/usr.sbin/traceroute6/traceroute6.8 index f02b08872ea5..13917eb47c7f 100644 --- a/usr.sbin/traceroute6/traceroute6.8 +++ b/usr.sbin/traceroute6/traceroute6.8 @@ -27,7 +27,7 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.Dd November 25, 2020 +.Dd October 25, 2023 .Dt TRACEROUTE6 8 .Os .\" @@ -38,7 +38,7 @@ .Sh SYNOPSIS .Nm .Bk -words -.Op Fl adIlnNrSTUv +.Op Fl adEIlnNrSTUv .Ek .Bk -words .Op Fl f Ar firsthop @@ -94,6 +94,22 @@ Turn on AS# lookups for each hop encountered. Turn on AS# lookups and use the given server instead of the default. .It Fl d Debug mode. +.It Fl E +Detect ECN bleaching. +Set the +.Em IPTOS_ECN_ECT1 +Explicit Congestion Notification (ECN) bits +.Pq Dv 01 , +and report if the hop has bleached +.Pq Dv 00 +or mangled +.Pq Dv 10 +them, or if it is experiencing congestion +.Pq Dv 11 . +Otherwise, report that it passed the bits appropriately. +If +.Fl t +is also specified, the corresponding ECN bits will be replaced. .It Fl f Ar firsthop Specify how many hops to skip in trace. .It Fl g Ar gateway diff --git a/usr.sbin/traceroute6/traceroute6.c b/usr.sbin/traceroute6/traceroute6.c index 925020546f27..212564415d6c 100644 --- a/usr.sbin/traceroute6/traceroute6.c +++ b/usr.sbin/traceroute6/traceroute6.c @@ -262,6 +262,7 @@ #include <string.h> #include <unistd.h> +#include <netinet/ip.h> #include <netinet/ip6.h> #include <netinet/icmp6.h> #include <netinet/sctp.h> @@ -294,7 +295,7 @@ void capdns_open(void); int get_hoplim(struct msghdr *); double deltaT(struct timeval *, struct timeval *); const char *pr_type(int); -int packet_ok(struct msghdr *, int, int, u_char *, u_char *); +int packet_ok(struct msghdr *, int, int, u_char *, u_char *, u_char *); void print(struct msghdr *, int); const char *inetname(struct sockaddr *); u_int32_t sctp_crc32c(void *, u_int32_t); @@ -340,6 +341,7 @@ static int nflag; /* print addresses numerically */ static int useproto = IPPROTO_UDP; /* protocol to use to send packet */ static int lflag; /* print both numerical address & hostname */ static int as_path; /* print as numbers for each hop */ +static int ecnflag; /* ECN bleaching detection flag */ static char *as_server = NULL; static void *asn; @@ -355,7 +357,7 @@ main(int argc, char *argv[]) struct hostent *hp; size_t size, minlen; uid_t uid; - u_char type, code; + u_char type, code, ecn; #if defined(IPSEC) && defined(IPSEC_POLICY_IPSEC) char ipsec_inpolicy[] = "in bypass"; char ipsec_outpolicy[] = "out bypass"; @@ -401,7 +403,7 @@ main(int argc, char *argv[]) seq = 0; ident = htons(getpid() & 0xffff); /* same as ping6 */ - while ((ch = getopt(argc, argv, "aA:df:g:Ilm:nNp:q:rs:St:TUvw:")) != -1) + while ((ch = getopt(argc, argv, "aA:dEf:g:Ilm:nNp:q:rs:St:TUvw:")) != -1) switch (ch) { case 'a': as_path = 1; @@ -413,6 +415,9 @@ main(int argc, char *argv[]) case 'd': options |= SO_DEBUG; break; + case 'E': + ecnflag = 1; + break; case 'f': ep = NULL; errno = 0; @@ -584,6 +589,15 @@ main(int argc, char *argv[]) exit(1); } + if (ecnflag) { + if (tclass != -1) { + tclass &= ~IPTOS_ECN_MASK; + } else { + tclass = 0; + } + tclass |= IPTOS_ECN_ECT1; + } + /* revoke privs */ uid = getuid(); if (setresuid(uid, uid, uid) == -1) { @@ -948,7 +962,7 @@ main(int argc, char *argv[]) send_probe(++seq, hops); while ((cc = wait_for_reply(rcvsock, &rcvmhdr))) { (void) gettimeofday(&t2, NULL); - if (packet_ok(&rcvmhdr, cc, seq, &type, &code)) { + if (packet_ok(&rcvmhdr, cc, seq, &type, &code, &ecn)) { if (!IN6_ARE_ADDR_EQUAL(&Rcv.sin6_addr, &lastaddr)) { if (probe > 0) @@ -957,6 +971,22 @@ main(int argc, char *argv[]) lastaddr = Rcv.sin6_addr; } printf(" %.3f ms", deltaT(&t1, &t2)); + if (ecnflag) { + switch (ecn) { + case IPTOS_ECN_ECT1: + printf(" (ecn=passed)"); + break; + case IPTOS_ECN_NOTECT: + printf(" (ecn=bleached)"); + break; + case IPTOS_ECN_CE: + printf(" (ecn=congested)"); + break; + default: + printf(" (ecn=mangled)"); + break; + } + } if (type == ICMP6_DST_UNREACH) { switch (code) { case ICMP6_DST_UNREACH_NOROUTE: @@ -1290,7 +1320,8 @@ pr_type(int t0) } int -packet_ok(struct msghdr *mhdr, int cc, int seq, u_char *type, u_char *code) +packet_ok(struct msghdr *mhdr, int cc, int seq, u_char *type, u_char *code, + u_char *ecn) { struct icmp6_hdr *icp; struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name; @@ -1373,6 +1404,7 @@ packet_ok(struct msghdr *mhdr, int cc, int seq, u_char *type, u_char *code) void *up; hip = (struct ip6_hdr *)(icp + 1); + *ecn = ntohl(hip->ip6_flow & IPV6_ECN_MASK) >> 20; if ((up = get_uphdr(hip, (u_char *)(buf + cc))) == NULL) { if (verbose) warnx("failed to get upper layer header"); @@ -1792,7 +1824,7 @@ usage(void) { fprintf(stderr, -"usage: traceroute6 [-adIlnNrSTUv] [-A as_server] [-f firsthop] [-g gateway]\n" +"usage: traceroute6 [-adEIlnNrSTUv] [-A as_server] [-f firsthop] [-g gateway]\n" " [-m hoplimit] [-p port] [-q probes] [-s src] [-w waittime] target\n" " [datalen]\n"); exit(1); |