Print this page
13175 Add support for IP_RECVTOS
13182 CMSG_ macros should have man pages
Change-ID: I784aa36cfd3c17e3cccbf1fd329fa7e69b663ef9

@@ -19,10 +19,11 @@
  * CDDL HEADER END
  */
 
 /*
  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
  */
 /* Copyright (c) 1990 Mentat Inc. */
 
 #include <sys/types.h>
 #include <sys/stream.h>

@@ -233,15 +234,26 @@
                     sizeof (timestruc_t) + _POINTER_ALIGNMENT;
                 IP_STAT(ipst, conn_in_timestamp);
         }
 
         /*
+         * If IP_RECVTOS is set allocate the appropriately sized buffer
+         */
+        if (recv_ancillary.crb_recvtos &&
+            (ira->ira_flags & IRAF_IS_IPV4)) {
+                ancil_size += sizeof (struct T_opthdr) +
+                    P2ROUNDUP(sizeof (uint8_t), __TPI_ALIGN_SIZE);
+                IP_STAT(ipst, conn_in_recvtos);
+        }
+
+        /*
          * If IP_RECVTTL is set allocate the appropriate sized buffer
          */
         if (recv_ancillary.crb_recvttl &&
             (ira->ira_flags & IRAF_IS_IPV4)) {
-                ancil_size += sizeof (struct T_opthdr) + sizeof (uint8_t);
+                ancil_size += sizeof (struct T_opthdr) +
+                    P2ROUNDUP(sizeof (uint8_t), __TPI_ALIGN_SIZE);
                 IP_STAT(ipst, conn_in_recvttl);
         }
 
         return (ancil_size);
 }

@@ -547,33 +559,46 @@
                 gethrestime((timestruc_t *)ancil_buf);
                 ancil_buf = (uchar_t *)toh + toh->len;
                 ancil_size -= toh->len;
         }
 
-        /*
-         * CAUTION:
-         * Due to aligment issues
-         * Processing of IP_RECVTTL option
-         * should always be the last. Adding
-         * any option processing after this will
-         * cause alignment panic.
-         */
+        if (recv_ancillary.crb_recvtos &&
+            (ira->ira_flags & IRAF_IS_IPV4)) {
+                struct  T_opthdr *toh;
+                uint8_t *dstptr;
+
+                toh = (struct T_opthdr *)ancil_buf;
+                toh->level = IPPROTO_IP;
+                toh->name = IP_RECVTOS;
+                toh->len = sizeof (struct T_opthdr) +
+                    P2ROUNDUP(sizeof (uint8_t), __TPI_ALIGN_SIZE);
+                toh->status = 0;
+                ancil_buf += sizeof (struct T_opthdr);
+                dstptr = (uint8_t *)ancil_buf;
+                *dstptr = ipp->ipp_type_of_service;
+                ancil_buf = (uchar_t *)toh + toh->len;
+                ancil_size -= toh->len;
+                ASSERT(__TPI_TOPT_ISALIGNED(toh));
+        }
+
         if (recv_ancillary.crb_recvttl &&
             (ira->ira_flags & IRAF_IS_IPV4)) {
                 struct  T_opthdr *toh;
                 uint8_t *dstptr;
 
                 toh = (struct T_opthdr *)ancil_buf;
                 toh->level = IPPROTO_IP;
                 toh->name = IP_RECVTTL;
-                toh->len = sizeof (struct T_opthdr) + sizeof (uint8_t);
+                toh->len = sizeof (struct T_opthdr) +
+                    P2ROUNDUP(sizeof (uint8_t), __TPI_ALIGN_SIZE);
                 toh->status = 0;
                 ancil_buf += sizeof (struct T_opthdr);
                 dstptr = (uint8_t *)ancil_buf;
                 *dstptr = ipp->ipp_hoplimit;
-                ancil_buf += sizeof (uint8_t);
+                ancil_buf = (uchar_t *)toh + toh->len;
                 ancil_size -= toh->len;
+                ASSERT(__TPI_TOPT_ISALIGNED(toh));
         }
 
         /* Consumed all of allocated space */
         ASSERT(ancil_size == 0);
 

@@ -771,10 +796,13 @@
                         *i1 = connp->conn_recv_ancillary.crb_recvslla;
                         break;  /* goto sizeof (int) option return */
                 case IP_RECVTTL:
                         *i1 = connp->conn_recv_ancillary.crb_recvttl;
                         break;  /* goto sizeof (int) option return */
+                case IP_RECVTOS:
+                        *i1 = connp->conn_recv_ancillary.crb_recvtos;
+                        break;  /* goto sizeof (int) option return */
                 case IP_ADD_MEMBERSHIP:
                 case IP_DROP_MEMBERSHIP:
                 case MCAST_JOIN_GROUP:
                 case MCAST_LEAVE_GROUP:
                 case IP_BLOCK_SOURCE:

@@ -1363,10 +1391,15 @@
         case IP_RECVTTL:
                 mutex_enter(&connp->conn_lock);
                 connp->conn_recv_ancillary.crb_recvttl = onoff;
                 mutex_exit(&connp->conn_lock);
                 break;
+        case IP_RECVTOS:
+                mutex_enter(&connp->conn_lock);
+                connp->conn_recv_ancillary.crb_recvtos = onoff;
+                mutex_exit(&connp->conn_lock);
+                break;
         case IP_PKTINFO: {
                 /*
                  * This also handles IP_RECVPKTINFO.
                  * IP_PKTINFO and IP_RECVPKTINFO have same value.
                  * Differentiation is based on the size of the