double                   latency;
        uint32_t                 dropped;
        int                      recv_ttl;
+       unsigned                 recv_tos;
        char                    *data;
 
        void                    *context;
        double                   timeout;
        int                      ttl;
        int                      addrfamily;
+       unsigned                 tos;
        char                    *data;
 
        struct sockaddr         *srcaddr;
                                ident, seq);
        }
 
-       if (ptr != NULL)
+       if (ptr != NULL){
                ptr->recv_ttl = ip_hdr->ip_ttl;
-
+               ptr->recv_tos = ip_hdr->ip_tos;
+       }
        return (ptr);
 }
 
        struct timeval diff;
        pinghost_t *host = NULL;
        int recv_ttl;
+       unsigned recv_tos;
        
        /*
         * Set up the receive buffer..
 
        /* Iterate over all auxiliary data in msghdr */
        recv_ttl = -1;
+       recv_tos = 0xffff;
        for (cmsg = CMSG_FIRSTHDR (&msghdr); /* {{{ */
                        cmsg != NULL;
                        cmsg = CMSG_NXTHDR (&msghdr, cmsg))
                        if (cmsg->cmsg_level != IPPROTO_IP)
                                continue;
 
+                       if (cmsg->cmsg_type == IP_TOS)
+                       {
+                               memcpy (&recv_tos, CMSG_DATA (cmsg),
+                                               sizeof (recv_tos));
+                               dprintf ("TOSv4 = %u;\n", recv_tos);
+                       } else
                        if (cmsg->cmsg_type == IP_TTL)
                        {
                                memcpy (&recv_ttl, CMSG_DATA (cmsg),
                        if (cmsg->cmsg_level != IPPROTO_IPV6)
                                continue;
 
+                       if (cmsg->cmsg_type == IPV6_RECVTCLASS)
+                       {
+                               memcpy (&recv_tos, CMSG_DATA (cmsg),
+                                               sizeof (recv_tos));
+                               dprintf ("TOSv6 = %u;\n", recv_tos);
+                       } else
                        if (cmsg->cmsg_type == IPV6_HOPLIMIT)
                        {
                                memcpy (&recv_ttl, CMSG_DATA (cmsg),
 
        if (recv_ttl >= 0)
                host->recv_ttl = recv_ttl;
+       if (recv_tos != 0xffff)
+               host->recv_tos = recv_tos;
 
        host->latency  = ((double) diff.tv_usec) / 1000.0;
        host->latency += ((double) diff.tv_sec)  * 1000.0;
        return (ret);
 }
 
+/*
+ * Set the TOS of a socket protocol independently.
+ */
+static int ping_set_tos (pinghost_t *ph, unsigned tos)
+{
+       int ret = -2;
+
+       if (ph->addrfamily == AF_INET)
+       {
+               dprintf ("Setting TP_TOS to %i\n", ttl);
+               ret = setsockopt (ph->fd, IPPROTO_IP, IP_TOS,
+                               &tos, sizeof (tos));
+       }
+       else if (ph->addrfamily == AF_INET6)
+       {
+               dprintf ("Setting IPV6_TCLASS to %i\n", ttl);
+               ret = setsockopt (ph->fd, IPPROTO_IPV6, IPV6_TCLASS,
+                               &tos, sizeof (tos));
+       }
+
+       return (ret);
+}
+
 static int ping_get_ident (void)
 {
        int fd;
        obj->ttl        = PING_DEF_TTL;
        obj->addrfamily = PING_DEF_AF;
        obj->data       = strdup (PING_DEF_DATA);
+       obj->tos        = 0;
 
        return (obj);
 }
 
        switch (option)
        {
+               case PING_OPT_TOS:{
+                       obj->tos=*(unsigned *)value;
+                       pinghost_t *ph;
+                       for (ph = obj->head; ph != NULL; ph = ph->next)
+                               ping_set_tos (ph, obj->tos);
+                       break;
+               }
                case PING_OPT_TIMEOUT:
                        obj->timeout = *((double *) value);
                        if (obj->timeout < 0.0)
        }
 
        ping_set_ttl (ph, obj->ttl);
+       ping_set_tos (ph, obj->tos);
 
        return (0);
 } /* int ping_host_add */
                        *((int *) buffer) = iter->recv_ttl;
                        ret = 0;
                        break;
+
+               case PING_INFO_TOS:
+                       ret = ENOMEM;
+                       if (*buffer_len>sizeof(unsigned)) *buffer_len=sizeof(unsigned);
+                       if (!*buffer_len) *buffer_len=1;
+                       if (orig_buffer_len < *buffer_len)
+                               break;
+                       memcpy(buffer,&iter->recv_tos,*buffer_len);
+                       ret = 0;
+                       break;
        }
 
        return (ret);
 
 static char   *opt_filename   = NULL;
 static int     opt_count      = -1;
 static int     opt_send_ttl   = 64;
+static unsigned opt_send_tos  = 0;
 
 static int host_num = 0;
 
                        "  -c count     number of ICMP packets to send\n"
                        "  -i interval  interval with which to send ICMP packets\n"
                        "  -t ttl       time to live for each ICMP packet\n"
+                       "  -z tos       Type-of-service/class-of-service for each ICMP packet\n"
                        "  -I srcaddr   source address\n"
                        "  -D device    outgoing interface name\n"
                        "  -f filename  filename to read hosts from\n"
 
        while (1)
        {
-               optchar = getopt (argc, argv, "46c:hi:I:t:f:D:");
+               optchar = getopt (argc, argv, "46c:hi:I:t:z:f:D:");
 
                if (optchar == -1)
                        break;
                                break;
                        }
 
+                       case 'z':
+                       {
+                               int new_send_tos;
+                               new_send_tos = atoi (optarg);
+                               if ((new_send_tos > 0) && (new_send_tos < 256))
+                                       opt_send_tos = new_send_tos;
+                               else
+                                       fprintf (stderr, "Ignoring invalid TOS argument: %s\n",
+                                                       optarg);
+                               break;
+                       }
+
                        case 'h':
                                usage_exit (argv[0], 0);
                                break;
        double          latency;
        unsigned int    sequence;
        int             recv_ttl;
+       unsigned        recv_tos;
        size_t          buffer_len;
        size_t          data_len;
        ping_context_t *context;
        ping_iterator_get_info (iter, PING_INFO_RECV_TTL,
                        &recv_ttl, &buffer_len);
 
+       recv_tos = 0;
+       buffer_len = sizeof (recv_tos);
+       ping_iterator_get_info (iter, PING_INFO_TOS,
+                       &recv_tos, &buffer_len);
+
        data_len = 0;
        ping_iterator_get_info (iter, PING_INFO_DATA,
                        NULL, &data_len);
                                        || (latency > (average + stddev)))
                                color = OPING_YELLOW;
 
-                       HOST_PRINTF ("%zu bytes from %s (%s): icmp_seq=%u ttl=%i "
+                       HOST_PRINTF ("%zu bytes from %s (%s): icmp_seq=%u ttl=%i tos=%u "
                                        "time=",
                                        data_len, context->host, context->addr,
-                                       sequence, recv_ttl);
+                                       sequence, recv_ttl, recv_tos);
                        wattron (main_win, COLOR_PAIR(color));
                        HOST_PRINTF ("%.2f", latency);
                        wattroff (main_win, COLOR_PAIR(color));
                else
                {
 #endif
-               HOST_PRINTF ("%zu bytes from %s (%s): icmp_seq=%u ttl=%i "
+               HOST_PRINTF ("%zu bytes from %s (%s): icmp_seq=%u ttl=%i tos=%u "
                                "time=%.2f ms\n",
                                data_len,
                                context->host, context->addr,
-                               sequence, recv_ttl, latency);
+                               sequence, recv_ttl, recv_tos, latency);
 #if USE_NCURSES
                }
 #endif
                                opt_send_ttl, ping_get_error (ping));
        }
 
+       if (ping_setopt (ping, PING_OPT_TOS, &opt_send_tos) != 0)
+       {
+               fprintf (stderr, "Setting TOS to %i failed: %s\n",
+                               opt_send_tos, ping_get_error (ping));
+       }
+
        {
                double temp_sec;
                double temp_nsec;
 
 #define PING_OPT_DATA    0x08
 #define PING_OPT_SOURCE  0x10
 #define PING_OPT_DEVICE  0x20
+#define PING_OPT_TOS     0x40
 
 #define PING_DEF_TIMEOUT 1.0
 #define PING_DEF_TTL     255
 #define PING_INFO_USERNAME  8
 #define PING_INFO_DROPPED   9
 #define PING_INFO_RECV_TTL 10
+#define PING_INFO_TOS      11
 int ping_iterator_get_info (pingobj_iter_t *iter, int info,
                void *buffer, size_t *buffer_len);