summaryrefslogtreecommitdiff
path: root/usr/src/uts/common/inet/udp/udp.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts/common/inet/udp/udp.c')
-rw-r--r--usr/src/uts/common/inet/udp/udp.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/usr/src/uts/common/inet/udp/udp.c b/usr/src/uts/common/inet/udp/udp.c
index 33f2bc1e8a..d3bd3055b1 100644
--- a/usr/src/uts/common/inet/udp/udp.c
+++ b/usr/src/uts/common/inet/udp/udp.c
@@ -4386,7 +4386,6 @@ udp_input(void *arg1, mblk_t *mp, void *arg2)
UDP_STAT(us, udp_in_recvucred);
}
- /* XXX FIXME: apply to AF_INET6 as well */
/*
* If SO_TIMESTAMP is set allocate the appropriate sized
* buffer. Since gethrestime() expects a pointer aligned
@@ -4662,6 +4661,18 @@ udp_input(void *arg1, mblk_t *mp, void *arg2)
UDP_STAT(us, udp_in_recvucred);
}
+ /*
+ * If SO_TIMESTAMP is set allocate the appropriate sized
+ * buffer. Since gethrestime() expects a pointer aligned
+ * argument, we allocate space necessary for extra
+ * alignment (even though it might not be used).
+ */
+ if (udp_bits.udpb_timestamp) {
+ udi_size += sizeof (struct T_opthdr) +
+ sizeof (timestruc_t) + _POINTER_ALIGNMENT;
+ UDP_STAT(us, udp_in_timestamp);
+ }
+
if (udp_bits.udpb_ipv6_recvhoplimit) {
udi_size += sizeof (struct T_opthdr) + sizeof (int);
UDP_STAT(us, udp_in_recvhoplimit);
@@ -4857,6 +4868,24 @@ udp_input(void *arg1, mblk_t *mp, void *arg2)
dstopt += toh->len;
udi_size -= toh->len;
}
+ if (udp_bits.udpb_timestamp) {
+ struct T_opthdr *toh;
+
+ toh = (struct T_opthdr *)dstopt;
+ toh->level = SOL_SOCKET;
+ toh->name = SCM_TIMESTAMP;
+ toh->len = sizeof (struct T_opthdr) +
+ sizeof (timestruc_t) + _POINTER_ALIGNMENT;
+ toh->status = 0;
+ dstopt += sizeof (struct T_opthdr);
+ /* Align for gethrestime() */
+ dstopt = (uchar_t *)P2ROUNDUP((intptr_t)dstopt,
+ sizeof (intptr_t));
+ gethrestime((timestruc_t *)dstopt);
+ dstopt = (uchar_t *)toh + toh->len;
+ udi_size -= toh->len;
+ }
+
/* Consumed all of allocated space */
ASSERT(udi_size == 0);
}