recvmsg.c raw

   1  #include <sys/socket.h>
   2  #include <limits.h>
   3  #include <time.h>
   4  #include <sys/time.h>
   5  #include <string.h>
   6  #include "syscall.h"
   7  
   8  hidden void __convert_scm_timestamps(struct msghdr *, socklen_t);
   9  
  10  void __convert_scm_timestamps(struct msghdr *msg, socklen_t csize)
  11  {
  12  	if (SCM_TIMESTAMP == SCM_TIMESTAMP_OLD) return;
  13  	if (!msg->msg_control || !msg->msg_controllen) return;
  14  
  15  	struct cmsghdr *cmsg, *last=0;
  16  	long tmp;
  17  	long long tvts[2];
  18  	int type = 0;
  19  
  20  	for (cmsg=CMSG_FIRSTHDR(msg); cmsg; cmsg=CMSG_NXTHDR(msg, cmsg)) {
  21  		if (cmsg->cmsg_level==SOL_SOCKET) switch (cmsg->cmsg_type) {
  22  		case SCM_TIMESTAMP_OLD:
  23  			if (type) break;
  24  			type = SCM_TIMESTAMP;
  25  			goto common;
  26  		case SCM_TIMESTAMPNS_OLD:
  27  			type = SCM_TIMESTAMPNS;
  28  		common:
  29  			memcpy(&tmp, CMSG_DATA(cmsg), sizeof tmp);
  30  			tvts[0] = tmp;
  31  			memcpy(&tmp, CMSG_DATA(cmsg) + sizeof tmp, sizeof tmp);
  32  			tvts[1] = tmp;
  33  			break;
  34  		}
  35  		last = cmsg;
  36  	}
  37  	if (!last || !type) return;
  38  	if (CMSG_SPACE(sizeof tvts) > csize-msg->msg_controllen) {
  39  		msg->msg_flags |= MSG_CTRUNC;
  40  		return;
  41  	}
  42  	msg->msg_controllen += CMSG_SPACE(sizeof tvts);
  43  	cmsg = CMSG_NXTHDR(msg, last);
  44  	cmsg->cmsg_level = SOL_SOCKET;
  45  	cmsg->cmsg_type = type;
  46  	cmsg->cmsg_len = CMSG_LEN(sizeof tvts);
  47  	memcpy(CMSG_DATA(cmsg), &tvts, sizeof tvts);
  48  }
  49  
  50  ssize_t recvmsg(int fd, struct msghdr *msg, int flags)
  51  {
  52  	ssize_t r;
  53  	socklen_t orig_controllen = msg->msg_controllen;
  54  #if LONG_MAX > INT_MAX
  55  	struct msghdr h, *orig = msg;
  56  	if (msg) {
  57  		h = *msg;
  58  		h.__pad1 = h.__pad2 = 0;
  59  		msg = &h;
  60  	}
  61  #endif
  62  	r = socketcall_cp(recvmsg, fd, msg, flags, 0, 0, 0);
  63  	if (r >= 0) __convert_scm_timestamps(msg, orig_controllen);
  64  #if LONG_MAX > INT_MAX
  65  	if (orig) *orig = h;
  66  #endif
  67  	return r;
  68  }
  69