diff --git a/contrib/traceroute/traceroute.8 b/contrib/traceroute/traceroute.8 index 85a7e9d3a17..21427ef6e97 100644 --- a/contrib/traceroute/traceroute.8 +++ b/contrib/traceroute/traceroute.8 @@ -16,7 +16,7 @@ .\" $Id: traceroute.8,v 1.19 2000/09/21 08:44:19 leres Exp $ .\" $FreeBSD$ .\" -.Dd November 25, 2020 +.Dd October 25, 2023 .Dt TRACEROUTE 8 .Os .Sh NAME @@ -25,7 +25,7 @@ .Sh SYNOPSIS .Nm .Bk -words -.Op Fl adDeFISnrvx +.Op Fl adDeEFISnrvx .Op Fl f Ar first_ttl .Op Fl g Ar gateway .Op Fl M Ar first_ttl @@ -67,6 +67,22 @@ default. Firewall evasion mode. Use fixed destination ports for UDP, UDP-Lite, TCP and SCTP probes. The destination port does NOT increment with each packet sent. +.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 first_ttl Set the initial time-to-live used in the first outgoing probe packet. .It Fl F diff --git a/contrib/traceroute/traceroute.c b/contrib/traceroute/traceroute.c index fc87575ea04..6f2350150bd 100644 --- a/contrib/traceroute/traceroute.c +++ b/contrib/traceroute/traceroute.c @@ -365,6 +365,7 @@ int doipcksum = 1; /* calculate ip checksums by default */ int optlen; /* length of ip options */ int fixedPort = 0; /* Use fixed destination port for TCP and UDP */ int printdiff = 0; /* Print the difference between sent and quoted */ +int ecnflag = 0; /* ECN bleaching detection flag */ extern int optind; extern int opterr; @@ -597,7 +598,7 @@ main(int argc, char **argv) prog = argv[0]; opterr = 0; - while ((op = getopt(argc, argv, "aA:edDFInrSvxf:g:i:M:m:P:p:q:s:t:w:z:")) != EOF) + while ((op = getopt(argc, argv, "aA:eEdDFInrSvxf:g:i:M:m:P:p:q:s:t:w:z:")) != EOF) switch (op) { case 'a': as_path = 1; @@ -620,6 +621,10 @@ main(int argc, char **argv) fixedPort = 1; break; + case 'E': + ecnflag = 1; + break; + case 'f': case 'M': /* FreeBSD compat. */ first_ttl = str2val(optarg, "first ttl", 1, 255); @@ -784,6 +789,10 @@ main(int argc, char **argv) outip->ip_v = IPVERSION; if (settos) outip->ip_tos = tos; + if (ecnflag) { + outip->ip_tos &= ~IPTOS_ECN_MASK; + outip->ip_tos |= IPTOS_ECN_ECT1; + } #ifdef BYTESWAP_IP_HDR outip->ip_len = htons(packlen); outip->ip_off = htons(off); @@ -1122,6 +1131,23 @@ main(int argc, char **argv) #endif precis = 3; Printf(" %.*f ms", precis, T); + if (ecnflag) { + u_char ecn = hip->ip_tos & IPTOS_ECN_MASK; + 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 (printdiff) { Printf("\n"); Printf("%*.*s%s\n", @@ -2126,7 +2152,7 @@ usage(void) Fprintf(stderr, "Version %s\n", version); Fprintf(stderr, - "Usage: %s [-adDeFInrSvx] [-f first_ttl] [-g gateway] [-i iface]\n" + "Usage: %s [-adDeEFInrSvx] [-f first_ttl] [-g gateway] [-i iface]\n" "\t[-m max_ttl] [-p port] [-P proto] [-q nqueries] [-s src_addr]\n" "\t[-t tos] [-w waittime] [-A as_server] [-z pausemsecs] host [packetlen]\n", prog); exit(1);