diff options
Diffstat (limited to 'usr/src/uts/common/inet/udp/udp.c')
-rw-r--r-- | usr/src/uts/common/inet/udp/udp.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/usr/src/uts/common/inet/udp/udp.c b/usr/src/uts/common/inet/udp/udp.c index 9273d3dd92..16966452b1 100644 --- a/usr/src/uts/common/inet/udp/udp.c +++ b/usr/src/uts/common/inet/udp/udp.c @@ -35,6 +35,7 @@ const char udp_version[] = "%Z%%M% %I% %E% SMI"; #include <sys/stropts.h> #include <sys/strlog.h> #include <sys/strsun.h> +#include <sys/time.h> #define _SUN_TPI_VERSION 2 #include <sys/tihdr.h> #include <sys/timod.h> @@ -213,6 +214,7 @@ udp_stat_t udp_statistics = { { "udp_in_recvrthdr", KSTAT_DATA_UINT64 }, { "udp_in_recvpktinfo", KSTAT_DATA_UINT64 }, { "udp_in_recvtclass", KSTAT_DATA_UINT64 }, + { "udp_in_timestamp", KSTAT_DATA_UINT64 }, #ifdef DEBUG { "udp_data_conn", KSTAT_DATA_UINT64 }, { "udp_data_notconn", KSTAT_DATA_UINT64 }, @@ -2974,6 +2976,9 @@ udp_opt_get(queue_t *q, t_scalar_t level, t_scalar_t name, uchar_t *ptr) case SO_RECVUCRED: *i1 = udp->udp_recvucred; break; /* goto sizeof (int) option return */ + case SO_TIMESTAMP: + *i1 = udp->udp_timestamp; + break; default: return (-1); } @@ -3323,6 +3328,10 @@ udp_opt_set(queue_t *q, uint_t optset_context, int level, if (!checkonly) udp->udp_recvucred = onoff; break; + case SO_TIMESTAMP: + if (!checkonly) + udp->udp_timestamp = onoff; + break; default: *outlenp = 0; return (EINVAL); @@ -4374,7 +4383,17 @@ udp_input(conn_t *connp, mblk_t *mp) udi_size += sizeof (struct T_opthdr) + sizeof (uint8_t); UDP_STAT(udp_in_recvttl); } - + /* + * 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->udp_timestamp) { + udi_size += sizeof (struct T_opthdr) + + sizeof (timestruc_t) + _POINTER_ALIGNMENT; + UDP_STAT(udp_in_timestamp); + } ASSERT(IPH_HDR_LENGTH((ipha_t *)rptr) == IP_SIMPLE_HDR_LENGTH); /* Allocate a message block for the T_UNITDATA_IND structure. */ @@ -4504,6 +4523,23 @@ udp_input(conn_t *connp, mblk_t *mp) dstopt += sizeof (uint8_t); udi_size -= toh->len; } + if (udp->udp_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 = (char *)P2ROUNDUP((intptr_t)dstopt, + sizeof (intptr_t)); + gethrestime((timestruc_t *)dstopt); + dstopt += sizeof (timestruc_t); + udi_size -= toh->len; + } /* Consumed all of allocated space */ ASSERT(udi_size == 0); |