Author: tuexen
Date: Wed May  6 22:13:08 2020
New Revision: 360709
URL: https://svnweb.freebsd.org/changeset/base/360709

Log:
  MFC r350027, r350028: Let traceroute6 not ignore some ICMPv6 packets
  
  MFC rr350027:
  Let packet_op() explicitly return the type and code instead of doing
  this implicitly by encoding it in a number space.
  No functional change intended.
  This is done as a preparation to add support for ICMPv6 mesages
  indicating a parameter problem related to the next header.
  
  MFC r350028:
  Add support for ICMPv6 messages indicating a parameter problem related
  to an unrecognized next header.

Modified:
  stable/11/usr.sbin/traceroute6/traceroute6.8
  stable/11/usr.sbin/traceroute6/traceroute6.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/usr.sbin/traceroute6/traceroute6.8
==============================================================================
--- stable/11/usr.sbin/traceroute6/traceroute6.8        Wed May  6 22:07:48 
2020        (r360708)
+++ stable/11/usr.sbin/traceroute6/traceroute6.8        Wed May  6 22:13:08 
2020        (r360709)
@@ -29,7 +29,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd May 2, 2018
+.Dd July 16, 2019
 .Dt TRACEROUTE6 8
 .Os
 .\"
@@ -172,6 +172,8 @@ Destination Unreachable - Administratively Prohibited.
 Destination Unreachable - Not a Neighbour.
 .It !A
 Destination Unreachable - Address Unreachable.
+.It !H
+Parameter Problem - Unrecognized Next Header Type.
 .It !\&
 This is printed if the hop limit is <= 1 on a port unreachable message.
 This means that the packet got to the destination,

Modified: stable/11/usr.sbin/traceroute6/traceroute6.c
==============================================================================
--- stable/11/usr.sbin/traceroute6/traceroute6.c        Wed May  6 22:07:48 
2020        (r360708)
+++ stable/11/usr.sbin/traceroute6/traceroute6.c        Wed May  6 22:13:08 
2020        (r360709)
@@ -307,7 +307,7 @@ void        *get_uphdr(struct ip6_hdr *, u_char *);
 int    get_hoplim(struct msghdr *);
 double deltaT(struct timeval *, struct timeval *);
 const char *pr_type(int);
-int    packet_ok(struct msghdr *, int, int);
+int    packet_ok(struct msghdr *, int, int, u_char *, u_char *);
 void   print(struct msghdr *, int);
 const char *inetname(struct sockaddr *);
 u_int32_t sctp_crc32c(void *, u_int32_t);
@@ -365,6 +365,7 @@ main(int argc, char *argv[])
        struct hostent *hp;
        size_t size, minlen;
        uid_t uid;
+       u_char type, code;
 
        /*
         * Receive ICMP
@@ -935,7 +936,7 @@ main(int argc, char *argv[])
                        send_probe(++seq, hops);
                        while ((cc = wait_for_reply(rcvsock, &rcvmhdr))) {
                                (void) gettimeofday(&t2, NULL);
-                               if ((i = packet_ok(&rcvmhdr, cc, seq))) {
+                               if (packet_ok(&rcvmhdr, cc, seq, &type, &code)) 
{
                                        if (!IN6_ARE_ADDR_EQUAL(&Rcv.sin6_addr,
                                            &lastaddr)) {
                                                if (probe > 0)
@@ -944,29 +945,40 @@ main(int argc, char *argv[])
                                                lastaddr = Rcv.sin6_addr;
                                        }
                                        printf("  %.3f ms", deltaT(&t1, &t2));
-                                       switch (i - 1) {
-                                       case ICMP6_DST_UNREACH_NOROUTE:
-                                               ++unreachable;
-                                               printf(" !N");
-                                               break;
-                                       case ICMP6_DST_UNREACH_ADMIN:
-                                               ++unreachable;
-                                               printf(" !P");
-                                               break;
-                                       case ICMP6_DST_UNREACH_NOTNEIGHBOR:
-                                               ++unreachable;
-                                               printf(" !S");
-                                               break;
-                                       case ICMP6_DST_UNREACH_ADDR:
-                                               ++unreachable;
-                                               printf(" !A");
-                                               break;
-                                       case ICMP6_DST_UNREACH_NOPORT:
+                                       if (type == ICMP6_DST_UNREACH) {
+                                               switch (code) {
+                                               case ICMP6_DST_UNREACH_NOROUTE:
+                                                       ++unreachable;
+                                                       printf(" !N");
+                                                       break;
+                                               case ICMP6_DST_UNREACH_ADMIN:
+                                                       ++unreachable;
+                                                       printf(" !P");
+                                                       break;
+                                               case 
ICMP6_DST_UNREACH_NOTNEIGHBOR:
+                                                       ++unreachable;
+                                                       printf(" !S");
+                                                       break;
+                                               case ICMP6_DST_UNREACH_ADDR:
+                                                       ++unreachable;
+                                                       printf(" !A");
+                                                       break;
+                                               case ICMP6_DST_UNREACH_NOPORT:
+                                                       if (rcvhlim >= 0 &&
+                                                           rcvhlim <= 1)
+                                                               printf(" !");
+                                                       ++got_there;
+                                                       break;
+                                               }
+                                       } else if (type == ICMP6_PARAM_PROB &&
+                                           code == ICMP6_PARAMPROB_NEXTHEADER) 
{
+                                               printf(" !H");
+                                               ++got_there;
+                                       } else if (type == ICMP6_ECHO_REPLY) {
                                                if (rcvhlim >= 0 &&
                                                    rcvhlim <= 1)
                                                        printf(" !");
                                                ++got_there;
-                                               break;
                                        }
                                        break;
                                } else if (deltaT(&t1, &t2) > waittime * 1000) {
@@ -1263,11 +1275,10 @@ pr_type(int t0)
 }
 
 int
-packet_ok(struct msghdr *mhdr, int cc, int seq)
+packet_ok(struct msghdr *mhdr, int cc, int seq, u_char *type, u_char *code)
 {
        struct icmp6_hdr *icp;
        struct sockaddr_in6 *from = (struct sockaddr_in6 *)mhdr->msg_name;
-       u_char type, code;
        char *buf = (char *)mhdr->msg_iov[0].iov_base;
        struct cmsghdr *cm;
        int *hlimp;
@@ -1332,10 +1343,13 @@ packet_ok(struct msghdr *mhdr, int cc, int seq)
        else
                rcvhlim = *hlimp;
 
-       type = icp->icmp6_type;
-       code = icp->icmp6_code;
-       if ((type == ICMP6_TIME_EXCEEDED && code == ICMP6_TIME_EXCEED_TRANSIT)
-           || type == ICMP6_DST_UNREACH) {
+       *type = icp->icmp6_type;
+       *code = icp->icmp6_code;
+       if ((*type == ICMP6_TIME_EXCEEDED &&
+           *code == ICMP6_TIME_EXCEED_TRANSIT) ||
+           (*type == ICMP6_DST_UNREACH) ||
+           (*type == ICMP6_PARAM_PROB &&
+           *code == ICMP6_PARAMPROB_NEXTHEADER)) {
                struct ip6_hdr *hip;
                struct icmp6_hdr *icmp;
                struct sctp_init_chunk *init;
@@ -1355,15 +1369,13 @@ packet_ok(struct msghdr *mhdr, int cc, int seq)
                        icmp = (struct icmp6_hdr *)up;
                        if (icmp->icmp6_id == ident &&
                            icmp->icmp6_seq == htons(seq))
-                               return (type == ICMP6_TIME_EXCEEDED ?
-                                   -1 : code + 1);
+                               return (1);
                        break;
                case IPPROTO_UDP:
                        udp = (struct udphdr *)up;
                        if (udp->uh_sport == htons(srcport) &&
                            udp->uh_dport == htons(port + seq))
-                               return (type == ICMP6_TIME_EXCEEDED ?
-                                   -1 : code + 1);
+                               return (1);
                        break;
                case IPPROTO_SCTP:
                        sctp = (struct sctphdr *)up;
@@ -1379,20 +1391,17 @@ packet_ok(struct msghdr *mhdr, int cc, int seq)
                                init = (struct sctp_init_chunk *)(sctp + 1);
                                /* Check the initiate tag, if available. */
                                if ((char *)&init->init.a_rwnd > buf + cc) {
-                                       return (type == ICMP6_TIME_EXCEEDED ?
-                                           -1 : code + 1);
+                                       return (1);
                                }
                                if (init->init.initiate_tag == (u_int32_t)
                                    ((sctp->src_port << 16) | sctp->dest_port)) 
{
-                                       return (type == ICMP6_TIME_EXCEEDED ?
-                                           -1 : code + 1);
+                                       return (1);
                                }
                        } else {
                                if (sctp->v_tag ==
                                    (u_int32_t)((sctp->src_port << 16) |
                                    sctp->dest_port)) {
-                                       return (type == ICMP6_TIME_EXCEEDED ?
-                                           -1 : code + 1);
+                                       return (1);
                                }
                        }
                        break;
@@ -1402,19 +1411,18 @@ packet_ok(struct msghdr *mhdr, int cc, int seq)
                            tcp->th_dport == htons(port + seq) &&
                            tcp->th_seq ==
                            (tcp_seq)((tcp->th_sport << 16) | tcp->th_dport))
-                               return (type == ICMP6_TIME_EXCEEDED ?
-                                   -1 : code + 1);
+                               return (1);
                        break;
                case IPPROTO_NONE:
-                       return (type == ICMP6_TIME_EXCEEDED ?  -1 : code + 1);
+                       return (1);
                default:
                        fprintf(stderr, "Unknown probe proto %d.\n", useproto);
                        break;
                }
-       } else if (useproto == IPPROTO_ICMPV6 && type == ICMP6_ECHO_REPLY) {
+       } else if (useproto == IPPROTO_ICMPV6 && *type == ICMP6_ECHO_REPLY) {
                if (icp->icmp6_id == ident &&
                    icp->icmp6_seq == htons(seq))
-                       return (ICMP6_DST_UNREACH_NOPORT + 1);
+                       return (1);
        }
        if (verbose) {
                char sbuf[NI_MAXHOST+1], dbuf[INET6_ADDRSTRLEN];
@@ -1427,8 +1435,8 @@ packet_ok(struct msghdr *mhdr, int cc, int seq)
                printf("\n%d bytes from %s to %s", cc, sbuf,
                    rcvpktinfo ? inet_ntop(AF_INET6, &rcvpktinfo->ipi6_addr,
                    dbuf, sizeof(dbuf)) : "?");
-               printf(": icmp type %d (%s) code %d\n", type, pr_type(type),
-                   icp->icmp6_code);
+               printf(": icmp type %d (%s) code %d\n", *type, pr_type(*type),
+                   *code);
                p = (u_int8_t *)(icp + 1);
 #define WIDTH  16
                for (i = 0; i < cc; i++) {
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to