bool Connection::sendOutgoingMessage(std::unique_ptr<MessageEncoder> encoder)
{
    COMPILE_ASSERT(sizeof(MessageInfo) + attachmentMaxAmount * sizeof(size_t) <= messageMaxSize, AttachmentsFitToMessageInline);

    Vector<Attachment> attachments = encoder->releaseAttachments();
    if (attachments.size() > (attachmentMaxAmount - 1)) {
        ASSERT_NOT_REACHED();
        return false;
    }

    MessageInfo messageInfo(encoder->bufferSize(), attachments.size());
    size_t messageSizeWithBodyInline = sizeof(messageInfo) + (attachments.size() * sizeof(AttachmentInfo)) + encoder->bufferSize();
    if (messageSizeWithBodyInline > messageMaxSize && encoder->bufferSize()) {
        RefPtr<WebKit::SharedMemory> oolMessageBody = WebKit::SharedMemory::allocate(encoder->bufferSize());
        if (!oolMessageBody)
            return false;

        WebKit::SharedMemory::Handle handle;
        if (!oolMessageBody->createHandle(handle, WebKit::SharedMemory::Protection::ReadOnly))
            return false;

        messageInfo.setMessageBodyIsOutOfLine();

        memcpy(oolMessageBody->data(), encoder->buffer(), encoder->bufferSize());

        attachments.append(handle.releaseAttachment());
    }

    struct msghdr message;
    memset(&message, 0, sizeof(message));

    struct iovec iov[3];
    memset(&iov, 0, sizeof(iov));

    message.msg_iov = iov;
    int iovLength = 1;

    iov[0].iov_base = reinterpret_cast<void*>(&messageInfo);
    iov[0].iov_len = sizeof(messageInfo);

    std::unique_ptr<AttachmentInfo[]> attachmentInfo;
    MallocPtr<char> attachmentFDBuffer;

    if (!attachments.isEmpty()) {
        int* fdPtr = 0;

        size_t attachmentFDBufferLength = std::count_if(attachments.begin(), attachments.end(),
            [](const Attachment& attachment) {
                return attachment.fileDescriptor() != -1;
            });

        if (attachmentFDBufferLength) {
            attachmentFDBuffer = MallocPtr<char>::malloc(sizeof(char) * CMSG_SPACE(sizeof(int) * attachmentFDBufferLength));

            message.msg_control = attachmentFDBuffer.get();
            message.msg_controllen = CMSG_SPACE(sizeof(int) * attachmentFDBufferLength);
            memset(message.msg_control, 0, message.msg_controllen);

            struct cmsghdr* cmsg = CMSG_FIRSTHDR(&message);
            cmsg->cmsg_level = SOL_SOCKET;
            cmsg->cmsg_type = SCM_RIGHTS;
            cmsg->cmsg_len = CMSG_LEN(sizeof(int) * attachmentFDBufferLength);

            fdPtr = reinterpret_cast<int*>(CMSG_DATA(cmsg));
        }

        attachmentInfo = std::make_unique<AttachmentInfo[]>(attachments.size());
        int fdIndex = 0;
        for (size_t i = 0; i < attachments.size(); ++i) {
            attachmentInfo[i].setType(attachments[i].type());

            switch (attachments[i].type()) {
            case Attachment::MappedMemoryType:
                attachmentInfo[i].setSize(attachments[i].size());
                // Fall trhough, set file descriptor or null.
            case Attachment::SocketType:
                if (attachments[i].fileDescriptor() != -1) {
                    ASSERT(fdPtr);
                    fdPtr[fdIndex++] = attachments[i].fileDescriptor();
                } else
                    attachmentInfo[i].setNull();
                break;
            case Attachment::Uninitialized:
            default:
                break;
            }
        }

        iov[iovLength].iov_base = attachmentInfo.get();
        iov[iovLength].iov_len = sizeof(AttachmentInfo) * attachments.size();
        ++iovLength;
    }

    if (!messageInfo.isMessageBodyIsOutOfLine() && encoder->bufferSize()) {
        iov[iovLength].iov_base = reinterpret_cast<void*>(encoder->buffer());
        iov[iovLength].iov_len = encoder->bufferSize();
        ++iovLength;
    }

    message.msg_iovlen = iovLength;

    while (sendmsg(m_socketDescriptor, &message, 0) == -1) {
        if (errno == EINTR)
            continue;
        if (errno == EAGAIN || errno == EWOULDBLOCK) {
            struct pollfd pollfd;

            pollfd.fd = m_socketDescriptor;
            pollfd.events = POLLOUT;
            pollfd.revents = 0;
            poll(&pollfd, 1, -1);
            continue;
        }

        if (m_isConnected)
            WTFLogAlways("Error sending IPC message: %s", strerror(errno));
        return false;
    }
    return true;
}
Exemplo n.º 2
0
//RY: start here
void udp_xmit6 (struct buffer6 *buf, struct tunnel6 *t)
{
	struct cmsghdr *cmsg;
    char cbuf[CMSG_SPACE(sizeof (unsigned int))];
    unsigned int *refp;
    struct msghdr msgh;
    int err;
    struct iovec iov;
//RY: start, for testing
    struct sockaddr_in6 clientaddr;
    struct iovec iov1[1];
    char a[10];
//RY: end
    /*
     * OKAY, now send a packet with the right SAref values.
     */
    memset(&msgh, 0, sizeof(struct msghdr));

    msgh.msg_control = cbuf;
    msgh.msg_controllen = 0;
//TODO: need to take decision on IPSEC
    if(gconfig.ipsecsaref && t->refhim != IPSEC_SAREF_NULL) {
	msgh.msg_controllen = sizeof(cbuf);

	cmsg = CMSG_FIRSTHDR(&msgh);
	cmsg->cmsg_level = SOL_IP;
	//RY: start
	//cmsg->cmsg_type  = IP_IPSEC_REFINFO;
	cmsg->cmsg_type  = IPV6_DSTOPTS;	//RY: updated for IPV6 com.
	//RY: end
	cmsg->cmsg_len   = CMSG_LEN(sizeof(unsigned int));

	if(gconfig.debug_network) {
		l2tp_log(LOG_DEBUG,"sending with saref=%d\n", t->refhim);
	}
	refp = (unsigned int *)CMSG_DATA(cmsg);
	*refp = t->refhim;

	msgh.msg_controllen = cmsg->cmsg_len;
    }

    iov.iov_base = buf->start;
    iov.iov_len  = buf->len;

    /* return packet from whence it came */
    //RY: start
    inet_pton(AF_INET6, "2003::1", &buf->peer.sin6_addr);
    buf->peer.sin6_family = AF_INET6;
    buf->peer.sin6_port = htons(1701);
    //RY: end
    msgh.msg_name    = &buf->peer;
    msgh.msg_namelen = sizeof(buf->peer);

    msgh.msg_iov  = &iov;
    msgh.msg_iovlen = 1;
    msgh.msg_flags = 0;

#if 0
    //RY: start
    inet_pton(AF_INET6, "2005::1", &buf->peer.sin6_addr);

    printf("dest addr:%s\n", IPADDY6(buf->peer.sin6_addr));
    buf->peer.sin6_family = AF_INET6;
    buf->peer.sin6_port = htons(23156);

    msgh.msg_name = &buf->peer;

    iov.iov_base = a;
    iov.iov_len = sizeof(a);
    msgh.msg_iov->iov_base = &iov;
    msgh.msg_iovlen = 1;
    msgh.msg_control = NULL;
    msgh.msg_controllen = 0;
    msgh.msg_flags = 0;

//#ifdef RY:
//    memset(&clientaddr, 0, sizeof(clientaddr));
//    	inet_pton(AF_INET6,"2005::1", &clientaddr.sin6_addr);
//    	clientaddr.sin6_port = htons(1701);
//    	clientaddr.sin6_family = AF_INET6;
//    memset(a, 'a', sizeof(a));
//        for(;;)
//          sendto(server_socket6, a, sizeof(a), 0,
//  							&clientaddr, sizeof(clientaddr));
 //   for(;;)
#endif
    //for(;;)
    if((err = sendmsg(server_socket6, &msgh, 0)) < 0)
	{
    	//RY: start
    	printf("udp_xmit6 failed with err=%d:%s\n",err,strerror(errno));
		//RY: end
		l2tp_log(LOG_ERR, "udp_xmit6 failed with err=%d:%s\n",
    			err,strerror(errno));
    }//RY: start
    else
    {
    	printf("sent:bytes = %d\n", err);
    //sleep(1)
    }
    //RY: end
}
Exemplo n.º 3
0
ssize_t 
recvfrom_flags(int fd, void *ptr, size_t nbytes, int *flagsp,
               struct sockaddr *sa, socklen_t *salenptr, struct my_in_pktinfo *pktp, u_char *ttl)
{
    struct msghdr   msg;
    struct iovec    iov[1];
    ssize_t         n;

#ifdef CMSG_FIRSTHDR
    struct cmsghdr  *cmptr;
    union {
      struct cmsghdr    cm;
      char              control[1024];
    } control_un;

	*ttl = 255;			// If kernel fails to provide TTL data then assume the TTL was 255 as it should be

    msg.msg_control = control_un.control;
    msg.msg_controllen = sizeof(control_un.control);
    msg.msg_flags = 0;
#else
    memset(&msg, 0, sizeof(msg));   /* make certain msg_accrightslen = 0 */
#endif /* CMSG_FIRSTHDR */

    msg.msg_name = (char *) sa;
    msg.msg_namelen = *salenptr;
    iov[0].iov_base = (char *)ptr;
    iov[0].iov_len = nbytes;
    msg.msg_iov = iov;
    msg.msg_iovlen = 1;

    if ( (n = recvmsg(fd, &msg, *flagsp)) < 0)
        return(n);

    *salenptr = msg.msg_namelen;    /* pass back results */
    if (pktp) {
        /* 0.0.0.0, i/f = -1 */
        /* We set the interface to -1 so that the caller can 
           tell whether we returned a meaningful value or 
           just some default.  Previously this code just 
           set the value to 0, but I'm concerned that 0 
           might be a valid interface value.
        */
        memset(pktp, 0, sizeof(struct my_in_pktinfo));
        pktp->ipi_ifindex = -1;
    }
/* end recvfrom_flags1 */

/* include recvfrom_flags2 */
#ifndef CMSG_FIRSTHDR
	#warning CMSG_FIRSTHDR not defined. Will not be able to determine destination address, received interface, etc.
    *flagsp = 0;                    /* pass back results */
    return(n);
#else

    *flagsp = msg.msg_flags;        /* pass back results */
    if (msg.msg_controllen < (socklen_t)sizeof(struct cmsghdr) ||
        (msg.msg_flags & MSG_CTRUNC) || pktp == NULL)
        return(n);

    for (cmptr = CMSG_FIRSTHDR(&msg); cmptr != NULL;
         cmptr = CMSG_NXTHDR(&msg, cmptr)) {

#ifdef  IP_PKTINFO
#if in_pktinfo_definition_is_missing
struct in_pktinfo
{
        int             ipi_ifindex;
        struct in_addr  ipi_spec_dst;
        struct in_addr  ipi_addr;
};
#endif
        if (cmptr->cmsg_level == IPPROTO_IP && 
            cmptr->cmsg_type == IP_PKTINFO) {
            struct in_pktinfo *tmp;
            struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
            
            tmp = (struct in_pktinfo *) CMSG_DATA(cmptr);
            sin->sin_family = AF_INET;
            sin->sin_addr = tmp->ipi_addr;
            sin->sin_port = 0;
            pktp->ipi_ifindex = tmp->ipi_ifindex;
            continue;
        }
#endif

#ifdef  IP_RECVDSTADDR
        if (cmptr->cmsg_level == IPPROTO_IP &&
            cmptr->cmsg_type == IP_RECVDSTADDR) {
            struct sockaddr_in *sin = (struct sockaddr_in*)&pktp->ipi_addr;
            
            sin->sin_family = AF_INET;
            sin->sin_addr = *(struct in_addr*)CMSG_DATA(cmptr);
            sin->sin_port = 0;
            continue;
        }
#endif

#ifdef  IP_RECVIF
        if (cmptr->cmsg_level == IPPROTO_IP &&
            cmptr->cmsg_type == IP_RECVIF) {
            struct sockaddr_dl  *sdl = (struct sockaddr_dl *) CMSG_DATA(cmptr);
#ifndef HAVE_BROKEN_RECVIF_NAME
            int nameLen = (sdl->sdl_nlen < IFI_NAME - 1) ? sdl->sdl_nlen : (IFI_NAME - 1);
            strncpy(pktp->ipi_ifname, sdl->sdl_data, nameLen);
#endif
            pktp->ipi_ifindex = sdl->sdl_index;
            assert(pktp->ipi_ifname[IFI_NAME - 1] == 0);
            // null terminated because of memset above
            continue;
        }
#endif

#ifdef  IP_RECVTTL
        if (cmptr->cmsg_level == IPPROTO_IP &&
            cmptr->cmsg_type == IP_RECVTTL) {
			*ttl = *(u_char*)CMSG_DATA(cmptr);
            continue;
        }
        else if (cmptr->cmsg_level == IPPROTO_IP &&
            cmptr->cmsg_type == IP_TTL) {		// some implementations seem to send IP_TTL instead of IP_RECVTTL
			*ttl = *(int*)CMSG_DATA(cmptr);
            continue;
        }
#endif

#if defined(IPV6_PKTINFO) && HAVE_IPV6
        if (cmptr->cmsg_level == IPPROTO_IPV6 && 
            cmptr->cmsg_type == IPV6_PKTINFO) {
            struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)&pktp->ipi_addr;
			struct in6_pktinfo *ip6_info = (struct in6_pktinfo*)CMSG_DATA(cmptr);
			
            sin6->sin6_family   = AF_INET6;
#ifndef NOT_HAVE_SA_LEN
            sin6->sin6_len      = sizeof(*sin6);
#endif
            sin6->sin6_addr     = ip6_info->ipi6_addr;
            sin6->sin6_flowinfo = 0;
            sin6->sin6_scope_id = 0;
            sin6->sin6_port     = 0;
			pktp->ipi_ifindex   = ip6_info->ipi6_ifindex;
            continue;
        }
#endif

#if defined(IPV6_HOPLIMIT) && HAVE_IPV6
        if (cmptr->cmsg_level == IPPROTO_IPV6 && 
            cmptr->cmsg_type == IPV6_HOPLIMIT) {
			*ttl = *(int*)CMSG_DATA(cmptr);
            continue;
        }
#endif
        assert(0);  // unknown ancillary data
    }
    return(n);
#endif /* CMSG_FIRSTHDR */
}
Exemplo n.º 4
0
static int32_t
qb_ipcs_uc_recv_and_auth(int32_t sock, void *msg, size_t len,
			 struct ipc_auth_ugp *ugp)
{
	int32_t res = 0;
	struct msghdr msg_recv;
	struct iovec iov_recv;

#ifdef SO_PASSCRED
	char cmsg_cred[CMSG_SPACE(sizeof(struct ucred))];
	int off = 0;
	int on = 1;
#endif
	msg_recv.msg_iov = &iov_recv;
	msg_recv.msg_iovlen = 1;
	msg_recv.msg_name = 0;
	msg_recv.msg_namelen = 0;
#ifdef SO_PASSCRED
	msg_recv.msg_control = (void *)cmsg_cred;
	msg_recv.msg_controllen = sizeof(cmsg_cred);
#endif
#ifdef QB_SOLARIS
	msg_recv.msg_accrights = 0;
	msg_recv.msg_accrightslen = 0;
#else
	msg_recv.msg_flags = 0;
#endif /* QB_SOLARIS */

	iov_recv.iov_base = msg;
	iov_recv.iov_len = len;
#ifdef SO_PASSCRED
	setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
#endif

	res = qb_ipc_us_recv_msghdr(sock, &msg_recv, msg, len);
	if (res < 0) {
		goto cleanup_and_return;
	}
	if (res != len) {
		res = -EIO;
		goto cleanup_and_return;
	}

	/*
	 * currently support getpeerucred, getpeereid, and SO_PASSCRED credential
	 * retrieval mechanisms for various Platforms
	 */
#ifdef HAVE_GETPEERUCRED
	/*
	 * Solaris and some BSD systems
	 */
	{
		ucred_t *uc = NULL;

		if (getpeerucred(sock, &uc) == 0) {
			res = 0;
			ugp->uid = ucred_geteuid(uc);
			ugp->gid = ucred_getegid(uc);
			ugp->pid = ucred_getpid(uc);
			ucred_free(uc);
		} else {
			res = -errno;
		}
	}
#elif HAVE_GETPEEREID
	/*
	 * Usually MacOSX systems
	 */
	{
		/*
		 * TODO get the peer's pid.
		 * c->pid = ?;
		 */
		if (getpeereid(sock, &ugp->uid, &ugp->gid) == 0) {
			res = 0;
		} else {
			res = -errno;
		}
	}

#elif SO_PASSCRED
	/*
	 * Usually Linux systems
	 */
	{
		struct ucred cred;
		struct cmsghdr *cmsg;

		res = -EINVAL;
		for (cmsg = CMSG_FIRSTHDR(&msg_recv); cmsg != NULL;
		     cmsg = CMSG_NXTHDR(&msg_recv, cmsg)) {
			if (cmsg->cmsg_type != SCM_CREDENTIALS)
				continue;

			memcpy(&cred, CMSG_DATA(cmsg), sizeof(struct ucred));
			res = 0;
			ugp->pid = cred.pid;
			ugp->uid = cred.uid;
			ugp->gid = cred.gid;
			break;
		}
	}
#else /* no credentials */
	ugp->pid = 0;
	ugp->uid = 0;
	ugp->gid = 0;
	res = -ENOTSUP;
#endif /* no credentials */

cleanup_and_return:

#ifdef SO_PASSCRED
	setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &off, sizeof(off));
#endif

	return res;
}
Exemplo n.º 5
0
static int
ping_recv (PING * p)
{
  int dupflag, n;
  int hops = -1;
  struct msghdr msg;
  struct iovec iov;
  struct icmp6_hdr *icmp6;
  struct cmsghdr *cmsg;
  char cmsg_data[1024];

  iov.iov_base = p->ping_buffer;
  iov.iov_len = _PING_BUFLEN (p, USE_IPV6);
  msg.msg_name = &p->ping_from.ping_sockaddr6;
  msg.msg_namelen = sizeof (p->ping_from.ping_sockaddr6);
  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;
  msg.msg_control = cmsg_data;
  msg.msg_controllen = sizeof (cmsg_data);
  msg.msg_flags = 0;

  n = recvmsg (p->ping_fd, &msg, 0);
  if (n < 0)
    return -1;

  for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg))
    {
      if (cmsg->cmsg_level == IPPROTO_IPV6
	  && cmsg->cmsg_type == IPV6_HOPLIMIT)
	{
	  hops = *(int *) CMSG_DATA (cmsg);
	  break;
	}
    }

  icmp6 = (struct icmp6_hdr *) p->ping_buffer;
  if (icmp6->icmp6_type == ICMP6_ECHO_REPLY)
    {
      /* We got an echo reply.  */
      if (ntohs (icmp6->icmp6_id) != p->ping_ident)
	return -1;		/* It's not a response to us.  */

      if (_PING_TST (p, ntohs (icmp6->icmp6_seq)))
	{
	  /* We already got the reply for this echo request.  */
	  p->ping_num_rept++;
	  dupflag = 1;
	}
      else
	{
	  _PING_SET (p, ntohs (icmp6->icmp6_seq));
	  p->ping_num_recv++;
	  dupflag = 0;
	}

      print_echo (dupflag, hops, p->ping_closure, &p->ping_dest.ping_sockaddr6,
		  &p->ping_from.ping_sockaddr6, icmp6, n);

    }
  else
    {
      /* We got an error reply.  */
      if (!my_echo_reply (p, icmp6))
	return -1;		/* It's not for us.  */

      print_icmp_error (&p->ping_from.ping_sockaddr6, icmp6, n);
    }

  return 0;
}
Exemplo n.º 6
0
int SP_ProcPduUtils :: recv_fd( int sockfd )
{
	struct msghdr msg;
	struct iovec iov[1];

#ifdef	HAVE_MSGHDR_MSG_CONTROL
	union
	{
		cmsghdr cm;
		char control[CMSG_SPACE(sizeof(int))];
	} control_un;
	struct cmsghdr *cmptr;

	msg.msg_control = control_un.control;
	msg.msg_controllen = sizeof(control_un.control);
#else
	int newfd;

	msg.msg_accrights = (caddr_t) &newfd;
	msg.msg_accrightslen = sizeof(int);
#endif

	msg.msg_name = NULL;
	msg.msg_namelen = 0;

	char buf[1];
	iov[0].iov_base = buf;
	iov[0].iov_len = 1;
	msg.msg_iov = iov;
	msg.msg_iovlen = 1;

	for( ; ; ) {
		errno = 0;
		if (recvmsg(sockfd, &msg, 0) <= 0) {
			if( EINTR == errno ) {
				continue;
			} else {
				return -1;
			}
		} else {
			break;
		}
	}

#ifdef	HAVE_MSGHDR_MSG_CONTROL
	if ((cmptr = CMSG_FIRSTHDR(&msg)) != NULL && cmptr->cmsg_len == CMSG_LEN(sizeof(int)))
	{
		if (cmptr->cmsg_level != SOL_SOCKET)
		{
			syslog( LOG_WARNING,"control level != SOL_SOCKET");
			return -1;
		}
		if (cmptr->cmsg_type != SCM_RIGHTS)
		{
			syslog( LOG_WARNING,"control type != SCM_RIGHTS");
			return -1;
		}
		return *((int *) CMSG_DATA(cmptr));
	}
	else
		return -1; /* descriptor was not passed */
#else
	/* *INDENT-OFF* */
	if (msg.msg_accrightslen == sizeof(int))
		return newfd;
	else
		return -1; /* descriptor was not passed */
	/* *INDENT-ON* */
#endif

/*
	char tmpbuf[CONTROLLEN];
	struct cmsghdr *cmptr = (struct cmsghdr *) tmpbuf;
	struct iovec iov[1];
	struct msghdr msg;
	char buf[1];

	iov[0].iov_base = buf;
	iov[0].iov_len = sizeof (buf);
	msg.msg_iov = iov;
	msg.msg_iovlen = 1;
	msg.msg_name = NULL;
	msg.msg_namelen = 0;

	msg.msg_control = cmptr;
	msg.msg_controllen = CONTROLLEN;

	for( ; ; ) {
		errno = 0;
		if (recvmsg(sockfd, &msg, 0) <= 0) {
			if( EINTR == errno ) {
				continue;
			} else {
				return -1;
			}
		} else {
			break;
		}
	}

	return *(int *) CMSG_DATA (cmptr);
*/
}
Exemplo n.º 7
0
/* There is a lot of hair here because the alignment rules (and
 * thus placement) of cmsg headers and length are different for
 * 32-bit apps.  -DaveM
 */
int cmsghdr_from_user_compat_to_kern(struct msghdr *kmsg, struct sock *sk,
			       unsigned char *stackbuf, int stackbuf_size)
{
	struct compat_cmsghdr __user *ucmsg;
	struct cmsghdr *kcmsg, *kcmsg_base;
	compat_size_t ucmlen;
	__kernel_size_t kcmlen, tmp;
	int err = -EFAULT;

	kcmlen = 0;
	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;
	ucmsg = CMSG_COMPAT_FIRSTHDR(kmsg);
	while (ucmsg != NULL) {
		if (get_user(ucmlen, &ucmsg->cmsg_len))
			return -EFAULT;

		/* Catch bogons. */
		if (!CMSG_COMPAT_OK(ucmlen, ucmsg, kmsg))
			return -EINVAL;

		tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) +
		       CMSG_ALIGN(sizeof(struct cmsghdr)));
		tmp = CMSG_ALIGN(tmp);
		kcmlen += tmp;
		ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen);
	}
	if (kcmlen == 0)
		return -EINVAL;

	/* The kcmlen holds the 64-bit version of the control length.
	 * It may not be modified as we do not stick it into the kmsg
	 * until we have successfully copied over all of the data
	 * from the user.
	 */
	if (kcmlen > stackbuf_size)
		kcmsg_base = kcmsg = sock_kmalloc(sk, kcmlen, GFP_KERNEL);
	if (kcmsg == NULL)
		return -ENOBUFS;

	/* Now copy them over neatly. */
	memset(kcmsg, 0, kcmlen);
	ucmsg = CMSG_COMPAT_FIRSTHDR(kmsg);
	while (ucmsg != NULL) {
		if (__get_user(ucmlen, &ucmsg->cmsg_len))
			goto Efault;
		if (!CMSG_COMPAT_OK(ucmlen, ucmsg, kmsg))
			goto Einval;
		tmp = ((ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg))) +
		       CMSG_ALIGN(sizeof(struct cmsghdr)));
		if ((char *)kcmsg_base + kcmlen - (char *)kcmsg < CMSG_ALIGN(tmp))
			goto Einval;
		kcmsg->cmsg_len = tmp;
		tmp = CMSG_ALIGN(tmp);
		if (__get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level) ||
		    __get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type) ||
		    copy_from_user(CMSG_DATA(kcmsg),
				   CMSG_COMPAT_DATA(ucmsg),
				   (ucmlen - CMSG_COMPAT_ALIGN(sizeof(*ucmsg)))))
			goto Efault;

		/* Advance. */
		kcmsg = (struct cmsghdr *)((char *)kcmsg + tmp);
		ucmsg = cmsg_compat_nxthdr(kmsg, ucmsg, ucmlen);
	}

	/* Ok, looks like we made it.  Hook it up and return success. */
	kmsg->msg_control = kcmsg_base;
	kmsg->msg_controllen = kcmlen;
	return 0;

Einval:
	err = -EINVAL;
Efault:
	if (kcmsg_base != (struct cmsghdr *)stackbuf)
		sock_kfree_s(sk, kcmsg_base, kcmlen);
	return err;
}
Exemplo n.º 8
0
static int32_t
qb_ipc_auth_creds(struct ipc_auth_data *data)
{
	int32_t res = 0;

	/*
	 * currently support getpeerucred, getpeereid, and SO_PASSCRED credential
	 * retrieval mechanisms for various Platforms
	 */
#ifdef HAVE_GETPEERUCRED
	/*
	 * Solaris and some BSD systems
	 */
	{
		ucred_t *uc = NULL;

		if (getpeerucred(data->sock, &uc) == 0) {
			res = 0;
			data->ugp.uid = ucred_geteuid(uc);
			data->ugp.gid = ucred_getegid(uc);
			data->ugp.pid = ucred_getpid(uc);
			ucred_free(uc);
		} else {
			res = -errno;
		}
	}
#elif defined(HAVE_GETPEEREID)
	/*
	* Usually MacOSX systems
	*/
	{
		/*
		* TODO get the peer's pid.
		* c->pid = ?;
		*/
		if (getpeereid(data->sock, &data->ugp.uid, &data->ugp.gid) == 0) {
			res = 0;
		} else {
			res = -errno;
		}
	}

#elif defined(SO_PASSCRED)
	/*
	* Usually Linux systems
	*/
	{
		struct ucred cred;
		struct cmsghdr *cmsg;

		res = -EINVAL;
		for (cmsg = CMSG_FIRSTHDR(&data->msg_recv); cmsg != NULL;
			cmsg = CMSG_NXTHDR(&data->msg_recv, cmsg)) {
			if (cmsg->cmsg_type != SCM_CREDENTIALS)
				continue;

			memcpy(&cred, CMSG_DATA(cmsg), sizeof(struct ucred));
			res = 0;
			data->ugp.pid = cred.pid;
			data->ugp.uid = cred.uid;
			data->ugp.gid = cred.gid;
			break;
		}
	}
#else /* no credentials */
	data->ugp.pid = 0;
	data->ugp.uid = 0;
	data->ugp.gid = 0;
	res = -ENOTSUP;
#endif /* no credentials */

	return res;
}
static int process_frames(int dev, int sock, int fd, unsigned long flags)
{
	struct cmsghdr *cmsg;
	struct msghdr msg;
	struct iovec  iv;
	struct hcidump_hdr *dh;
	struct btsnoop_pkt *dp;
	struct frame frm;
	struct pollfd fds[2];
	int nfds = 0;
	char *buf, *ctrl;
	int len, hdr_size = HCIDUMP_HDR_SIZE;

	if (sock < 0)
		return -1;

	if (snap_len < SNAP_LEN)
		snap_len = SNAP_LEN;

	if (flags & DUMP_BTSNOOP)
		hdr_size = BTSNOOP_PKT_SIZE;

	buf = malloc(snap_len + hdr_size);
	if (!buf) {
		perror("Can't allocate data buffer");
		return -1;
	}

	dh = (void *) buf;
	dp = (void *) buf;
	frm.data = buf + hdr_size;

	ctrl = malloc(100);
	if (!ctrl) {
		free(buf);
		perror("Can't allocate control buffer");
		return -1;
	}

	if (dev == HCI_DEV_NONE)
		printf("system: ");
	else
		printf("device: hci%d ", dev);

	printf("snap_len: %d filter: 0x%lx\n", snap_len, parser.filter);

	memset(&msg, 0, sizeof(msg));

	if (mode == SERVER) {
		struct btsnoop_hdr *hdr = (void *) buf;

		btsnoop_version = 1;
		btsnoop_type = 1002;

		memcpy(hdr->id, btsnoop_id, sizeof(btsnoop_id));
		hdr->version = htonl(btsnoop_version);
		hdr->type = htonl(btsnoop_type);

		printf("btsnoop version: %d datalink type: %d\n",
						btsnoop_version, btsnoop_type);

		len = write(fd, buf, BTSNOOP_HDR_SIZE);
		if (len < 0) {
			perror("Can't create dump header");
			return -1;
		}

		if (len != BTSNOOP_HDR_SIZE) {
			fprintf(stderr, "Header size mismatch\n");
			return -1;
		}

		fds[nfds].fd = fd;
		fds[nfds].events = POLLIN;
		fds[nfds].revents = 0;
		nfds++;
	}

	fds[nfds].fd = sock;
	fds[nfds].events = POLLIN;
	fds[nfds].revents = 0;
	nfds++;

	while (1) {
		int i, n = poll(fds, nfds, -1);
		if (n <= 0)
			continue;

		for (i = 0; i < nfds; i++) {
			if (fds[i].revents & (POLLHUP | POLLERR | POLLNVAL)) {
				if (fds[i].fd == sock)
					printf("device: disconnected\n");
				else
					printf("client: disconnect\n");
				return 0;
			}
		}

		if (mode == SERVER) {
			len = recv(fd, buf, snap_len, MSG_DONTWAIT);
			if (len == 0) {
				printf("client: disconnect\n");
				return 0;
			}
			if (len < 0 && errno != EAGAIN && errno != EINTR) {
				perror("Connection read failure");
				return -1;
			}
		}

		iv.iov_base = frm.data;
		iv.iov_len  = snap_len;

		msg.msg_iov = &iv;
		msg.msg_iovlen = 1;
		msg.msg_control = ctrl;
		msg.msg_controllen = 100;

		len = recvmsg(sock, &msg, MSG_DONTWAIT);
		if (len < 0) {
			if (errno == EAGAIN || errno == EINTR)
				continue;
			perror("Receive failed");
			return -1;
		}

		/* Process control message */
		frm.data_len = len;
		frm.dev_id = dev;
		frm.in = 0;
		frm.pppdump_fd = parser.pppdump_fd;
		frm.audio_fd   = parser.audio_fd;

		cmsg = CMSG_FIRSTHDR(&msg);
		while (cmsg) {
			int dir;
			switch (cmsg->cmsg_type) {
			case HCI_CMSG_DIR:
				memcpy(&dir, CMSG_DATA(cmsg), sizeof(int));
				frm.in = (uint8_t) dir;
				break;
			case HCI_CMSG_TSTAMP:
				memcpy(&frm.ts, CMSG_DATA(cmsg),
						sizeof(struct timeval));
				break;
			}
			cmsg = CMSG_NXTHDR(&msg, cmsg);
		}

		frm.ptr = frm.data;
		frm.len = frm.data_len;

		switch (mode) {
		case WRITE:
		case SERVER:
			/* Save or send dump */
			if (flags & DUMP_BTSNOOP) {
				uint64_t ts;
				uint8_t pkt_type = ((uint8_t *) frm.data)[0];
				dp->size = htonl(frm.data_len);
				dp->len  = dp->size;
				dp->flags = ntohl(frm.in & 0x01);
				dp->drops = 0;
				ts = (frm.ts.tv_sec - 946684800ll) * 1000000ll + frm.ts.tv_usec;
				dp->ts = hton64(ts + 0x00E03AB44A676000ll);
				if (pkt_type == HCI_COMMAND_PKT ||
						pkt_type == HCI_EVENT_PKT)
					dp->flags |= ntohl(0x02);
			} else {
				dh->len = htobs(frm.data_len);
				dh->in  = frm.in;
				dh->ts_sec  = htobl(frm.ts.tv_sec);
				dh->ts_usec = htobl(frm.ts.tv_usec);
			}

			if (write_n(fd, buf, frm.data_len + hdr_size) < 0) {
				perror("Write error");
				return -1;
			}
			break;

		default:
			/* Parse and print */
			parse(&frm);
			break;
		}
	}

	return 0;
}
Exemplo n.º 10
0
int bind( int sockfd, const struct sockaddr *my_addr, socklen_t addrlen)
{
#ifdef SO_REUSEPORT
   // parse environment property (just once)
   if (reuse_ports.count < 0){
     char *env_reuse = getenv("PRIVBIND_REUSE_PORTS");
     if (env_reuse == NULL){
       reuse_ports.count = 0;
     }else{
       if (parselist(env_reuse, &reuse_ports, 1, 65535) != 0){
         reuse_ports.count = -1;
         return -1;
       }
     }
   }
   
   // get bind port
   int port = -1;
   if (my_addr->sa_family==AF_INET)
      port = (int) ntohs(((struct sockaddr_in *) my_addr)->sin_port);
   else if (my_addr->sa_family==AF_INET6)
      port = (int) ntohs(((struct sockaddr_in6 *) my_addr)->sin6_port);
   
   // check if we should setup SO_REUSEPORT for this port
   if (port != -1 && is_in_list(&reuse_ports, port)){
      int optval = 1;
      int retval = setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
      if (retval != 0)
        return retval;
   }
#endif
  
   /* First of all, attempt the bind. We only need the socket if it fails with access denied */

   int oret=_bind( sockfd, my_addr, addrlen );
   if( oret==0 || errno!=EACCES )
      return oret;

   /* In most cases, we can let the bind go through as is */
   if( master_quit || (my_addr->sa_family!=AF_INET && my_addr->sa_family!=AF_INET6) 
       || (my_addr->sa_family==AF_INET && addrlen<sizeof(struct sockaddr_in)) 
       || (my_addr->sa_family==AF_INET6 && addrlen<sizeof(struct sockaddr_in6))  
     ) { 
      errno=EACCES;
      return oret;
   }

   /* Prepare the ancillary data for passing the actual FD */
   struct msghdr msghdr={.msg_name=NULL};
   struct cmsghdr *cmsg;
   char buf[CMSG_SPACE(sizeof(int))];
   int *fdptr;

    msghdr.msg_control=buf;
    msghdr.msg_controllen=sizeof(buf);

    cmsg=CMSG_FIRSTHDR(&msghdr);
    cmsg->cmsg_level=SOL_SOCKET;
    cmsg->cmsg_type=SCM_RIGHTS;
    cmsg->cmsg_len=CMSG_LEN(sizeof(int));

    /* Initialize the payload */
    fdptr=(int *)CMSG_DATA(cmsg);
    fdptr[0]=sockfd;
    msghdr.msg_controllen=cmsg->cmsg_len;

    /* Don't forget the data component */
    struct ipc_msg_req request;
    struct iovec iov;

    msghdr.msg_iov=&iov;
    msghdr.msg_iovlen=1;

    iov.iov_base=&request;
    iov.iov_len=sizeof(request);

    request.type=MSG_REQ_BIND;

    /* Check family of the request, only INET and INET6 should make it here */
    if (my_addr->sa_family==AF_INET)
      request.data.bind4.addr=*(struct sockaddr_in *) my_addr;
    else if (my_addr->sa_family==AF_INET6)
      request.data.bind6.addr=*(struct sockaddr_in6 *) my_addr;

    int retval=oret;

    if( acquire_lock(1) ) {
       if( sendmsg( COMM_SOCKET, &msghdr, MSG_NOSIGNAL )>0 ) {
          /* Request was sent - wait for reply */
          struct ipc_msg_reply reply;

          if( recv( COMM_SOCKET, &reply, sizeof(reply), 0 )>0 ) {
             retval=reply.data.stat.retval;
             if( retval<0 )
                errno=reply.data.stat.error;
          } else {
             /* It would appear that the other process has closed, just return the original retval */
             master_cleanup();
          }
       } else {
          /* An error has occured! */
          if( errno==EPIPE || errno==ENOTCONN || errno==EBADF ) {
             master_cleanup();
          } else {
             perror("privbind communication socket error");
             master_cleanup();
          }
       }

       acquire_lock(0);
    }

    /* Make sure we return the original errno, regardless of what caused us to fail */
    if( retval!=0 )
        errno=EACCES;

    return retval;
}
Exemplo n.º 11
0
static int process_frames(bdaddr_t address, unsigned long flags)
{
	struct cmsghdr *cmsg;
	struct msghdr msg;
	struct iovec  iv;
	struct hcidump_hdr *dh;
	struct btsnoop_pkt *dp;
	struct frame frm;
	struct pollfd fds[2];
	int nfds = 0;
	char *buf, *ctrl;
	int len, hdr_size = HCIDUMP_HDR_SIZE;
	int polltimeout = -1;
	int sock = -1;
	int device = -1;

	if (snap_len < SNAP_LEN)
		snap_len = SNAP_LEN;

	if (flags & DUMP_BTSNOOP)
		hdr_size = BTSNOOP_PKT_SIZE;

	buf = malloc(snap_len + hdr_size);
	if (!buf) {
		perror("Can't allocate data buffer");
		return -1;
	}

	dh = (void *) buf;
	dp = (void *) buf;
	frm.data = buf + hdr_size;

	ctrl = malloc(100);
	if (!ctrl) {
		free(buf);
		perror("Can't allocate control buffer");
		return -1;
	}

	printf("snap_len: %d filter: 0x%lx\n", snap_len, parser.filter);

	memset(&msg, 0, sizeof(msg));

	while (1)
	{
	    nfds = 0;
	    if (sock == -1)
	    {
            device = hci_for_each_dev(0, find_device_by_address_callback, (long)&address);
            if (device != -1)
            {
                sock = open_socket(device, flags);
                if (sock != -1)
                {
                    printf("hci%d Connected\n", device);
                    (void)fflush(stdout);
                    onBtConnect();
                }
            }
	    }

        if (sock != -1)
        {
            fds[nfds].fd = sock;
            fds[nfds].events = POLLIN;
            fds[nfds].revents = 0;
            nfds++;
        }

        /* ------------------------------------------------------------- */
        /* Remote sme                                                    */
        /* ------------------------------------------------------------- */
#ifdef IPC_IP
        // If we are not connected attempt to connect
        if (!smeConnection)
        {
            //printf("Sme Connect :: tcp:localhost:10101\n");
            //(void)fflush(stdout);
            smeConnection = ipc_ip_connect("tcp:localhost:10101", NULL, NULL, NULL, NULL);
            if (smeConnection)
            {
                printf("Sme Connected\n");
                (void)fflush(stdout);
                onIpcConnect();
            }
        }

        if (smeConnection)
        {
            fds[nfds].fd = ipc_getFd(smeConnection);
            fds[nfds].events = POLLIN;
            fds[nfds].revents = 0;
            nfds++;
        }

        polltimeout = sock==-1?500:smeConnection?-1:500;
#endif
        /* ------------------------------------------------------------- */
        (void)fflush(stdout);
	    int i, n = poll(fds, nfds, polltimeout);
        (void)fflush(stdout);

	    if (n <= 0)
			continue;

		for (i = 0; i < nfds; i++) {
			if (fds[i].revents & (POLLHUP | POLLERR | POLLNVAL)) {
				if (fds[i].fd == sock)
				{
					printf("device: disconnected\n");
					sock = -1;
                    onBtDisconnect();
                    continue;
				}
#ifdef IPC_IP
                else if (smeConnection && fds[i].fd == ipc_getFd(smeConnection))
                {
                    printf("Sme Disconnected\n");
                    (void)fflush(stdout);
                    ipc_disconnect(smeConnection);
                    smeConnection = NULL;
                    continue;
                }
#endif
				else
				{
					printf("client: disconnect\n");
				}
			}
		}

        for (i = 0; i < nfds; i++)
        {
#ifdef IPC_IP
            if (smeConnection && fds[i].fd == ipc_getFd(smeConnection) && fds[i].revents & (POLLIN | POLLPRI))
            {
                CsrUint8* smeRxBuffer;
                CsrUint32 smeRxLength = 0;

                printf("Sme fd Triggered\n");
                (void)fflush(stdout);

                if (ipc_message_recv(smeConnection, 0, &smeRxBuffer, &smeRxLength))
                {
                    if (smeRxLength != 0)
                    {
                        if (!remote_bt_signal_receive(NULL, smeRxBuffer, (CsrUint16)smeRxLength))
                        {
                            printf("Sme unhandled ipc message\n");
                            (void)fflush(stdout);
                        }
                        ipc_message_free(smeConnection, smeRxBuffer);
                    }
                    continue;
                }

                /* Opps Disconnected */
                printf("Sme Disconnected\n");
                (void)fflush(stdout);
                ipc_disconnect(smeConnection);
                smeConnection = NULL;
                nfds--;
                onIpcDisconnect();
                continue;
            }
#endif

            if (sock != -1 && fds[i].fd == sock && fds[i].revents & (POLLIN | POLLPRI))
            {
                iv.iov_base = frm.data;
                iv.iov_len  = snap_len;

                msg.msg_iov = &iv;
                msg.msg_iovlen = 1;
                msg.msg_control = ctrl;
                msg.msg_controllen = 100;

                len = recvmsg(sock, &msg, MSG_DONTWAIT);
                if (len < 0) {
                    if (errno == EAGAIN || errno == EINTR)
                        continue;
                    perror("Receive failed");
                    return -1;
                }

                /* Process control message */
                frm.data_len = len;
                frm.dev_id = device;
                frm.in = 0;
                frm.pppdump_fd = parser.pppdump_fd;
                frm.audio_fd   = parser.audio_fd;

                cmsg = CMSG_FIRSTHDR(&msg);
                while (cmsg) {
                    switch (cmsg->cmsg_type) {
                    case HCI_CMSG_DIR:
                        frm.in = *((int *) CMSG_DATA(cmsg));
                        break;
                    case HCI_CMSG_TSTAMP:
                        frm.ts = *((struct timeval *) CMSG_DATA(cmsg));
                        break;
                    }
                    cmsg = CMSG_NXTHDR(&msg, cmsg);
                }

                frm.ptr = frm.data;
                frm.len = frm.data_len;

                /* Parse and print */
                parse(&frm);
            }
        }
	}

	return 0;
}
Exemplo n.º 12
0
/* writes generated buffer to desired destination. For TCP syslog,
 * we use RFC6587 octet-stuffing (unless octet-counting is selected).
 * This is not great, but doing full blown RFC5425 (TLS) looks like
 * it is too much for the logger utility. If octet-counting is
 * selected, we use that.
 */
static void write_output(const struct logger_ctl *ctl, const char *const msg)
{
	struct iovec iov[4];
	int iovlen = 0;
	char *octet = NULL;

	/* 1) octen count */
	if (ctl->octet_count) {
		size_t len = xasprintf(&octet, "%zu ", strlen(ctl->hdr) + strlen(msg));
		iovec_add_string(iov, iovlen, octet, len);
	}

	/* 2) header */
	iovec_add_string(iov, iovlen, ctl->hdr, 0);

	/* 3) message */
	iovec_add_string(iov, iovlen, msg, 0);

	if (!ctl->noact) {
		struct msghdr message = { 0 };
		struct cmsghdr *cmhp;
		struct ucred *cred;
		union {
			struct cmsghdr cmh;
			char   control[CMSG_SPACE(sizeof(struct ucred))];
		} cbuf;

		/* 4) add extra \n to make sure message is terminated */
		if ((ctl->socket_type == TYPE_TCP) && !ctl->octet_count)
			iovec_add_string(iov, iovlen, "\n", 1);

		message.msg_iov = iov;
		message.msg_iovlen = iovlen;

		/* syslog/journald may follow local socket credentials rather
		 * than in the message PID. If we use --id as root than we can
		 * force kernel to accept another valid PID than the real logger(1)
		 * PID.
		 */
		if (ctl->pid && !ctl->server && ctl->pid != getpid()
		    && geteuid() == 0 && kill(ctl->pid, 0) == 0) {

			message.msg_control = cbuf.control;
			message.msg_controllen = CMSG_SPACE(sizeof(struct ucred));

			cmhp = CMSG_FIRSTHDR(&message);
			cmhp->cmsg_len = CMSG_LEN(sizeof(struct ucred));
			cmhp->cmsg_level = SOL_SOCKET;
			cmhp->cmsg_type = SCM_CREDENTIALS;
			cred = (struct ucred *) CMSG_DATA(cmhp);

			cred->pid = ctl->pid;
		}

		if (sendmsg(ctl->fd, &message, 0) < 0)
			warn(_("send message failed"));
	}

	if (ctl->stderr_printout) {
		/* make sure it's terminated for stderr */
		if (iovec_memcmp(iov, iovlen, "\n", 1) != 0)
			iovec_add_string(iov, iovlen, "\n", 1);

		ignore_result( writev(STDERR_FILENO, iov, iovlen) );
	}

	free(octet);
}
Exemplo n.º 13
0
Arquivo: icsim.c Projeto: JMaz/ICSim
int main(int argc, char *argv[]) {
    int opt;
    int can;
    struct ifreq ifr;
    struct sockaddr_can addr;
    struct canfd_frame frame;
    struct iovec iov;
    struct msghdr msg;
    struct cmsghdr *cmsg;
    struct timeval tv, timeout_config = { 0, 0 };
    fd_set rdfs;
    char ctrlmsg[CMSG_SPACE(sizeof(struct timeval)) + CMSG_SPACE(sizeof(__u32))];
    int running = 1;
    int nbytes, maxdlen;
    int ret;
    int seed = 0;
    int door_id, signal_id, speed_id;
    SDL_Event event;

    while ((opt = getopt(argc, argv, "rs:dh?")) != -1) {
        switch(opt) {
        case 'r':
            randomize = 1;
            break;
        case 's':
            seed = atoi(optarg);
            break;
        case 'd':
            debug = 1;
            break;
        case 'h':
        case '?':
        default:
            Usage(NULL);
            break;
        }
    }

    if (optind >= argc) Usage("You must specify at least one can device");

    if (seed && randomize) Usage("You can not specify a seed value AND randomize the seed");

    // Create a new raw CAN socket
    can = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if(can < 0) Usage("Couldn't create raw socket");

    addr.can_family = AF_CAN;
    memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
    strncpy(ifr.ifr_name, argv[optind], strlen(argv[optind]));
    printf("Using CAN interface %s\n", ifr.ifr_name);
    if (ioctl(can, SIOCGIFINDEX, &ifr) < 0) {
        perror("SIOCGIFINDEX");
        exit(1);
    }
    addr.can_ifindex = ifr.ifr_ifindex;
    // CAN FD Mode
    setsockopt(can, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfd_on, sizeof(canfd_on));

    iov.iov_base = &frame;
    iov.iov_len = sizeof(frame);
    msg.msg_name = &addr;
    msg.msg_namelen = sizeof(addr);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    msg.msg_control = &ctrlmsg;
    msg.msg_controllen = sizeof(ctrlmsg);
    msg.msg_flags = 0;

    if (bind(can, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
        perror("bind");
        return 1;
    }

    init_car_state();

    door_id = DEFAULT_DOOR_ID;
    signal_id = DEFAULT_SIGNAL_ID;
    speed_id = DEFAULT_SPEED_ID;

    if (randomize || seed) {
        if(randomize) seed = time(NULL);
        srand(seed);
        door_id = (rand() % 2046) + 1;
        signal_id = (rand() % 2046) + 1;
        speed_id = (rand() % 2046) + 1;
        door_pos = rand() % 9;
        signal_pos = rand() % 9;
        speed_pos = rand() % 8;
        printf("Seed: %d\n", seed);
    }

    SDL_Window *window = NULL;
    SDL_Surface *screenSurface = NULL;
    if(SDL_Init ( SDL_INIT_VIDEO ) < 0 ) {
        printf("SDL Could not initializes\n");
        exit(40);
    }
    window = SDL_CreateWindow("IC Simulator", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN );
    if(window == NULL) {
        printf("Window could not be shown\n");
    }
    renderer = SDL_CreateRenderer(window, -1, 0);
    SDL_Surface *image = IMG_Load(get_data("ic.png"));
    SDL_Surface *needle = IMG_Load(get_data("needle.png"));
    SDL_Surface *sprites = IMG_Load(get_data("spritesheet.png"));
    base_texture = SDL_CreateTextureFromSurface(renderer, image);
    needle_tex = SDL_CreateTextureFromSurface(renderer, needle);
    sprite_tex = SDL_CreateTextureFromSurface(renderer, sprites);

    speed_rect.x = 212;
    speed_rect.y = 175;
    speed_rect.h = needle->h;
    speed_rect.w = needle->w;

    // Draw the IC
    redraw_ic();

    /* For now we will just operate on one CAN interface */
    while(running) {
        while( SDL_PollEvent(&event) != 0 ) {
            switch(event.type) {
            case SDL_QUIT:
                running = 0;
                break;
            }
        }

        nbytes = recvmsg(can, &msg, 0);
        if (nbytes < 0) {
            perror("read");
            return 1;
        }
        if ((size_t)nbytes == CAN_MTU)
            maxdlen = CAN_MAX_DLEN;
        else if ((size_t)nbytes == CANFD_MTU)
            maxdlen = CANFD_MAX_DLEN;
        else {
            fprintf(stderr, "read: incomplete CAN frame\n");
            return 1;
        }
        for (cmsg = CMSG_FIRSTHDR(&msg);
                cmsg && (cmsg->cmsg_level == SOL_SOCKET);
                cmsg = CMSG_NXTHDR(&msg,cmsg)) {
            if (cmsg->cmsg_type == SO_TIMESTAMP)
                tv = *(struct timeval *)CMSG_DATA(cmsg);
            else if (cmsg->cmsg_type == SO_RXQ_OVFL)
                //dropcnt[i] = *(__u32 *)CMSG_DATA(cmsg);
                fprintf(stderr, "Dropped packet\n");
        }
//      if(debug) fprint_canframe(stdout, &frame, "\n", 0, maxdlen);
        if(frame.can_id == door_id) update_door_status(&frame, maxdlen);
        if(frame.can_id == signal_id) update_signal_status(&frame, maxdlen);
        if(frame.can_id == speed_id) update_speed_status(&frame, maxdlen);
    }

    SDL_DestroyTexture(base_texture);
    SDL_DestroyTexture(needle_tex);
    SDL_DestroyTexture(sprite_tex);
    SDL_FreeSurface(image);
    SDL_FreeSurface(needle);
    SDL_FreeSurface(sprites);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    IMG_Quit();
    SDL_Quit();

    return 0;
}
Exemplo n.º 14
0
void
send_packet(struct interface *ifp,
	    struct stream *s, u_int32_t dst, struct prefix *p, u_int32_t ttl)
{
	static struct sockaddr_in sockdst = { AF_INET };
	struct ip *ip;
	struct icmphdr *icmp;
	struct msghdr *msg;
	struct cmsghdr *cmsg;
	struct iovec iovector;
	char msgbuf[256];
	char buf[256];
	struct in_pktinfo *pktinfo;
	u_long src;
	int on;

	if (!(ifp->flags & IFF_UP))
		return;

	if (p)
		src = ntohl(p->u.prefix4.s_addr);
	else
		src = 0;	/* Is filled in */

	ip = (struct ip *)buf;
	ip->ip_hl = sizeof(struct ip) >> 2;
	ip->ip_v = IPVERSION;
	ip->ip_tos = 0xC0;
	ip->ip_off = 0L;
	ip->ip_p = 1;		/* IP_ICMP */
	ip->ip_ttl = ttl;
	ip->ip_src.s_addr = src;
	ip->ip_dst.s_addr = dst;
	icmp = (struct icmphdr *)(buf + sizeof(struct ip));

	/* Merge IP header with icmp packet */
	assert(stream_get_endp(s) < (sizeof(buf) - sizeof(struct ip)));
	stream_get(icmp, s, stream_get_endp(s));

	/* icmp->checksum is already calculated */
	ip->ip_len = sizeof(struct ip) + stream_get_endp(s);

	on = 1;
	if (setsockopt(irdp_sock, IPPROTO_IP, IP_HDRINCL,
		       (char *)&on, sizeof(on)) < 0)
		zlog_warn("sendto %s", safe_strerror(errno));

	if (dst == INADDR_BROADCAST) {
		on = 1;
		if (setsockopt(irdp_sock, SOL_SOCKET, SO_BROADCAST,
			       (char *)&on, sizeof(on)) < 0)
			zlog_warn("sendto %s", safe_strerror(errno));
	}

	if (dst != INADDR_BROADCAST) {
		on = 0;
		if (setsockopt(irdp_sock, IPPROTO_IP, IP_MULTICAST_LOOP,
			       (char *)&on, sizeof(on)) < 0)
			zlog_warn("sendto %s", safe_strerror(errno));
	}

	memset(&sockdst, 0, sizeof(sockdst));
	sockdst.sin_family = AF_INET;
	sockdst.sin_addr.s_addr = dst;

	cmsg = (struct cmsghdr *)(msgbuf + sizeof(struct msghdr));
	cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(struct in_pktinfo);
	cmsg->cmsg_level = SOL_IP;
	cmsg->cmsg_type = IP_PKTINFO;
	pktinfo = (struct in_pktinfo *)CMSG_DATA(cmsg);
	pktinfo->ipi_ifindex = ifp->ifindex;
	pktinfo->ipi_spec_dst.s_addr = src;
	pktinfo->ipi_addr.s_addr = src;

	iovector.iov_base = (void *)buf;
	iovector.iov_len = ip->ip_len;
	msg = (struct msghdr *)msgbuf;
	msg->msg_name = &sockdst;
	msg->msg_namelen = sizeof(sockdst);
	msg->msg_iov = &iovector;
	msg->msg_iovlen = 1;
	msg->msg_control = cmsg;
	msg->msg_controllen = cmsg->cmsg_len;

	sockopt_iphdrincl_swab_htosys(ip);

	if (sendmsg(irdp_sock, msg, 0) < 0) {
		zlog_warn("sendto %s", safe_strerror(errno));
	}
	/*   printf("TX on %s idx %d\n", ifp->name, ifp->ifindex); */
}
Exemplo n.º 15
0
/** receives an ipv4 packet using a raw socket.
 * An ipv4 packet is received in buf, using IP_PKTINFO or IP_RECVDSTADDR.
 * from and to are filled (only the ip part the ports are 0 since this
 * function doesn't try to look beyond the IP level).
 * @param sock - raw socket
 * @param buf - detination buffer.
 * @param len - buffer len (should be enough for receiving a packet +
 *               IP header).
 * @param from - result parameter, the IP address part of it will be filled
 *                with the source address and the port with 0.
 * @param to - result parameter, the IP address part of it will be filled
 *                with the destination (local) address and the port with 0.
 * @return packet len or <0 on error: -1 (check errno),
 *        -2 no IP_PKTINFO/IP_RECVDSTADDR found or AF mismatch
 */
int recvpkt4(int sock, char* buf, int len, union sockaddr_union* from,
					union sockaddr_union* to)
{
	struct iovec iov[1];
	struct msghdr rcv_msg;
	struct cmsghdr* cmsg;
#ifdef IP_PKTINFO
	struct in_pktinfo* rcv_pktinfo;
#endif /* IP_PKTINFO */
	int n, ret;
	char msg_ctrl_buf[1024];

	iov[0].iov_base=buf;
	iov[0].iov_len=len;
	memset(&rcv_msg, 0, sizeof(struct msghdr));
	rcv_msg.msg_name=from;
	rcv_msg.msg_namelen=sockaddru_len(*from);
	rcv_msg.msg_control=msg_ctrl_buf;
	rcv_msg.msg_controllen=sizeof(msg_ctrl_buf);
	rcv_msg.msg_iov=&iov[0];
	rcv_msg.msg_iovlen=1;
	ret=-2; /* no PKT_INFO or AF mismatch */
retry:
	n=recvmsg(sock, &rcv_msg, MSG_WAITALL);
	if (unlikely(n==-1)){
		if (errno==EINTR)
			goto retry;
		ret=n;
		goto end;
	}
	/* find the pkt info */
	for (cmsg=CMSG_FIRSTHDR(&rcv_msg); cmsg; cmsg=CMSG_NXTHDR(&rcv_msg, cmsg)){
#ifdef IP_PKTINFO
		if (likely((cmsg->cmsg_level==IPPROTO_IP) &&
					(cmsg->cmsg_type==IP_PKTINFO))) {
			rcv_pktinfo=(struct in_pktinfo*)CMSG_DATA(cmsg);
			to->sin.sin_family=AF_INET;
			memcpy(&to->sin.sin_addr, &rcv_pktinfo->ipi_spec_dst.s_addr, 
									sizeof(to->sin.sin_addr));
			to->sin.sin_port=0; /* not known */
			/* interface no. in ipi_ifindex */
			ret=n; /* success */
			break;
		}
#elif defined (IP_RECVDSTADDR)
		if (likely((cmsg->cmsg_level==IPPROTO_IP) &&
					(cmsg->cmsg_type==IP_RECVDSTADDR))) {
			to->sin.sin_family=AF_INET;
			memcpy(&to->sin.sin_addr, CMSG_DATA(cmsg),
									sizeof(to->sin.sin_addr));
			to->sin.sin_port=0; /* not known */
			ret=n; /* success */
			break;
		}
#else
#error "no method of getting the destination ip address supported"
#endif /* IP_PKTINFO / IP_RECVDSTADDR */
	}
end:
	return ret;
}
Exemplo n.º 16
0
static int receive_message(int sock, void *buf, size_t buflen, int *fdp,
			   int *numfds)
{
	struct msghdr msg;
	struct iovec iov;
	size_t ccmsg[CMSG_SPACE(sizeof(int) * MAX_SEND_FDS) / sizeof(size_t)];
	struct cmsghdr *cmsg;
	int res;
	int i;

	assert(*numfds <= MAX_SEND_FDS);
	iov.iov_base = buf;
	iov.iov_len = buflen;

	memset(&msg, 0, sizeof(msg));
	memset(ccmsg, -1, sizeof(ccmsg));
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = ccmsg;
	msg.msg_controllen = sizeof(ccmsg);

	res = recvmsg(sock, &msg, MSG_WAITALL);
	if (!res) {
		/* retry on zero return, see do_recv() in ulockmgr.c */
		res = recvmsg(sock, &msg, MSG_WAITALL);
		if (!res)
			return 0;
	}
	if (res == -1) {
		perror("ulockmgr_server: recvmsg");
		return -1;
	}
	if ((size_t) res != buflen) {
		fprintf(stderr, "ulockmgr_server: short message received\n");
		return -1;
	}

	cmsg = CMSG_FIRSTHDR(&msg);
	if (cmsg) {
		if (!cmsg->cmsg_type == SCM_RIGHTS) {
			fprintf(stderr,
				"ulockmgr_server: unknown control message %d\n",
				cmsg->cmsg_type);
			return -1;
		}
		memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
		if (msg.msg_flags & MSG_CTRUNC) {
			fprintf(stderr,
				"ulockmgr_server: control message truncated\n");
			for (i = 0; i < *numfds; i++)
				close(fdp[i]);
			*numfds = 0;
		}
	} else {
		if (msg.msg_flags & MSG_CTRUNC) {
			fprintf(stderr,
				"ulockmgr_server: control message truncated(*)\n");

			/* There's a bug in the Linux kernel, that if
			   not all file descriptors were allocated,
			   then the cmsg header is not filled in */
			cmsg = (struct cmsghdr *) ccmsg;
			memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
			for (i = 0; i < *numfds; i++)
				close(fdp[i]);
		}
		*numfds = 0;
	}
	return res;
}
Exemplo n.º 17
0
static int
handle_open(struct weston_launch *wl, struct msghdr *msg, ssize_t len)
{
	int fd = -1, ret = -1;
	char control[CMSG_SPACE(sizeof(fd))];
	struct cmsghdr *cmsg;
	struct stat s;
	struct msghdr nmsg;
	struct iovec iov;
	struct weston_launcher_open *message;
	union cmsg_data *data;

	message = msg->msg_iov->iov_base;
	if ((size_t)len < sizeof(*message))
		goto err0;

	/* Ensure path is null-terminated */
	((char *) message)[len-1] = '\0';

	fd = open(message->path, message->flags);
	if (fd < 0) {
		fprintf(stderr, "Error opening device %s: %m\n",
			message->path);
		goto err0;
	}

	if (fstat(fd, &s) < 0) {
		close(fd);
		fd = -1;
		fprintf(stderr, "Failed to stat %s\n", message->path);
		goto err0;
	}

	if (major(s.st_rdev) != INPUT_MAJOR &&
	    major(s.st_rdev) != DRM_MAJOR) {
		close(fd);
		fd = -1;
		fprintf(stderr, "Device %s is not an input or drm device\n",
			message->path);
		goto err0;
	}

err0:
	memset(&nmsg, 0, sizeof nmsg);
	nmsg.msg_iov = &iov;
	nmsg.msg_iovlen = 1;
	if (fd != -1) {
		nmsg.msg_control = control;
		nmsg.msg_controllen = sizeof control;
		cmsg = CMSG_FIRSTHDR(&nmsg);
		cmsg->cmsg_level = SOL_SOCKET;
		cmsg->cmsg_type = SCM_RIGHTS;
		cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
		data = (union cmsg_data *) CMSG_DATA(cmsg);
		data->fd = fd;
		nmsg.msg_controllen = cmsg->cmsg_len;
		ret = 0;
	}
	iov.iov_base = &ret;
	iov.iov_len = sizeof ret;

	if (wl->verbose)
		fprintf(stderr, "weston-launch: opened %s: ret: %d, fd: %d\n",
			message->path, ret, fd);
	do {
		len = sendmsg(wl->sock[0], &nmsg, 0);
	} while (len < 0 && errno == EINTR);

	if (len < 0)
		return -1;

	if (fd != -1 && major(s.st_rdev) == DRM_MAJOR)
		wl->drm_fd = fd;
	if (fd != -1 && major(s.st_rdev) == INPUT_MAJOR &&
	    wl->last_input_fd < fd)
		wl->last_input_fd = fd;

	return 0;
}
Exemplo n.º 18
0
int main(int argc, char *argv[])
{
	int sk1, sk2;
	sockaddr_storage_t loop1;
	sockaddr_storage_t loop2;
	struct iovec iov;
	struct msghdr inmessage;
	struct msghdr outmessage;
	char incmsg[CMSG_SPACE(sizeof(sctp_cmsg_data_t))];
	char outcmsg[CMSG_SPACE(sizeof(struct sctp_sndrcvinfo))];
	struct cmsghdr *cmsg;
	struct sctp_sndrcvinfo *sinfo;
	struct iovec out_iov;
	int error;
	int pf_class, af_family;
	uint32_t ppid;
	uint32_t stream;
	sctp_assoc_t associd1, associd2;
	struct sctp_assoc_change *sac;
	struct sctp_event_subscribe subscribe;
	char *big_buffer;
	int offset;
	struct sctp_send_failed *ssf;
	socklen_t len;		/* Really becomes 2xlen when set. */
	int orig_len;
	struct sctp_status gstatus;

	/* Rather than fflush() throughout the code, set stdout to
	 * be unbuffered.
	 */
	setvbuf(stdout, NULL, _IONBF, 0);

	/* Set some basic values which depend on the address family. */
#if TEST_V6
	pf_class = PF_INET6;
	af_family = AF_INET6;

	loop1.v6.sin6_family = AF_INET6;
	loop1.v6.sin6_addr = in6addr_loopback;
	loop1.v6.sin6_port = htons(SCTP_TESTPORT_1);

	loop2.v6.sin6_family = AF_INET6;
	loop2.v6.sin6_addr = in6addr_loopback;
	loop2.v6.sin6_port = htons(SCTP_TESTPORT_2);
#else
	pf_class = PF_INET;
	af_family = AF_INET;

	loop1.v4.sin_family = AF_INET;
	loop1.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK;
	loop1.v4.sin_port = htons(SCTP_TESTPORT_1);

	loop2.v4.sin_family = AF_INET;
	loop2.v4.sin_addr.s_addr = SCTP_IP_LOOPBACK;
	loop2.v4.sin_port = htons(SCTP_TESTPORT_2);
#endif /* TEST_V6 */

	/* Create the two endpoints which will talk to each other.  */
	sk1 = test_socket(pf_class, SOCK_SEQPACKET, IPPROTO_SCTP);
	sk2 = test_socket(pf_class, SOCK_SEQPACKET, IPPROTO_SCTP);

	len = sizeof(int);
	error = getsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &orig_len, &len);
	if (error)
		tst_brkm(TBROK, NULL, "can't get rcvbuf size: %s",
			 strerror(errno));
	/* Set the MAXSEG to something smallish. */
	{
		int val = SMALL_MAXSEG;
		test_setsockopt(sk1, SCTP_MAXSEG, &val, sizeof(val));
	}

	memset(&subscribe, 0, sizeof(subscribe));
	subscribe.sctp_data_io_event = 1;
	subscribe.sctp_association_event = 1;
	subscribe.sctp_send_failure_event = 1;
	test_setsockopt(sk1, SCTP_EVENTS, &subscribe, sizeof(subscribe));
	test_setsockopt(sk2, SCTP_EVENTS, &subscribe, sizeof(subscribe));

	/* Bind these sockets to the test ports.  */
	test_bind(sk1, &loop1.sa, sizeof(loop1));
	test_bind(sk2, &loop2.sa, sizeof(loop2));

	/*
	 * This code sets the associations RWND very small so we can
	 * fill it.  It does this by manipulating the rcvbuf as follows:
	 * 1) Reduce the rcvbuf size on the socket
	 * 2) create an association so that we advertize rcvbuf/2 as
	 *    our initial rwnd
	 * 3) raise the rcvbuf value so that we don't drop data wile
	 *    receiving later data
	 */
	len = SMALL_RCVBUF;
	error = setsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
	if (error)
		tst_brkm(TBROK, NULL, "setsockopt(SO_RCVBUF): %s",
			 strerror(errno));

	/* Mark sk2 as being able to accept new associations.  */
	test_listen(sk2, 1);

	/* Send the first message.  This will create the association.  */
	outmessage.msg_name = &loop2;
	outmessage.msg_namelen = sizeof(loop2);
	outmessage.msg_iov = &out_iov;
	outmessage.msg_iovlen = 1;
	outmessage.msg_control = outcmsg;
	outmessage.msg_controllen = sizeof(outcmsg);
	outmessage.msg_flags = 0;
	cmsg = CMSG_FIRSTHDR(&outmessage);
	cmsg->cmsg_level = IPPROTO_SCTP;
	cmsg->cmsg_type = SCTP_SNDRCV;
	cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
	outmessage.msg_controllen = cmsg->cmsg_len;
	sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
	memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));
	ppid = rand();		/* Choose an arbitrary value. */
	stream = 1;
	sinfo->sinfo_ppid = ppid;
	sinfo->sinfo_stream = stream;
	outmessage.msg_iov->iov_base = message;
	outmessage.msg_iov->iov_len = strlen(message) + 1;
	test_sendmsg(sk1, &outmessage, 0, strlen(message) + 1);

	/* Initialize inmessage for all receives. */
	big_buffer = test_malloc(REALLY_BIG);
	memset(&inmessage, 0, sizeof(inmessage));
	iov.iov_base = big_buffer;
	iov.iov_len = REALLY_BIG;
	inmessage.msg_iov = &iov;
	inmessage.msg_iovlen = 1;
	inmessage.msg_control = incmsg;

	/* Get the communication up message on sk2.  */
	inmessage.msg_controllen = sizeof(incmsg);
	error = test_recvmsg(sk2, &inmessage, MSG_WAITALL);
	test_check_msg_notification(&inmessage, error,
				    sizeof(struct sctp_assoc_change),
				    SCTP_ASSOC_CHANGE, SCTP_COMM_UP);
	sac = (struct sctp_assoc_change *)iov.iov_base;
	associd2 = sac->sac_assoc_id;

	/* Get the communication up message on sk1.  */
	inmessage.msg_controllen = sizeof(incmsg);
	error = test_recvmsg(sk1, &inmessage, MSG_WAITALL);
	test_check_msg_notification(&inmessage, error,
				    sizeof(struct sctp_assoc_change),
				    SCTP_ASSOC_CHANGE, SCTP_COMM_UP);
	sac = (struct sctp_assoc_change *)iov.iov_base;
	associd1 = sac->sac_assoc_id;

	/* restore the rcvbuffer size for the receiving socket */
	error = setsockopt(sk2, SOL_SOCKET, SO_RCVBUF, &orig_len,
			   sizeof(orig_len));

	if (error)
		tst_brkm(TBROK, NULL, "setsockopt(SO_RCVBUF): %s",
			 strerror(errno));

	/* Get the first data message which was sent.  */
	inmessage.msg_controllen = sizeof(incmsg);
	error = test_recvmsg(sk2, &inmessage, MSG_WAITALL);
	test_check_msg_data(&inmessage, error, strlen(message) + 1,
			    MSG_EOR, stream, ppid);

	/* Figure out how big to make our fillmsg */
	len = sizeof(struct sctp_status);
	memset(&gstatus, 0, sizeof(struct sctp_status));
	gstatus.sstat_assoc_id = associd1;
	error = getsockopt(sk1, IPPROTO_SCTP, SCTP_STATUS, &gstatus, &len);

	if (error)
		tst_brkm(TBROK, NULL, "can't get rwnd size: %s",
			 strerror(errno));
	tst_resm(TINFO, "Creating fillmsg of size %d",
		 gstatus.sstat_rwnd + RWND_SLOP);
	fillmsg = malloc(gstatus.sstat_rwnd + RWND_SLOP);

	/* Send a fillmsg */
	outmessage.msg_controllen = sizeof(outcmsg);
	outmessage.msg_flags = 0;
	cmsg = CMSG_FIRSTHDR(&outmessage);
	cmsg->cmsg_level = IPPROTO_SCTP;
	cmsg->cmsg_type = SCTP_SNDRCV;
	cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
	outmessage.msg_controllen = cmsg->cmsg_len;
	sinfo = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
	memset(sinfo, 0x00, sizeof(struct sctp_sndrcvinfo));
	ppid++;
	stream++;
	sinfo->sinfo_ppid = ppid;
	sinfo->sinfo_stream = stream;
	memset(fillmsg, 'X', gstatus.sstat_rwnd + RWND_SLOP);
	fillmsg[gstatus.sstat_rwnd + RWND_SLOP - 1] = '\0';
	outmessage.msg_iov->iov_base = fillmsg;
	outmessage.msg_iov->iov_len = gstatus.sstat_rwnd + RWND_SLOP;
	outmessage.msg_name = NULL;
	outmessage.msg_namelen = 0;
	sinfo->sinfo_assoc_id = associd1;
	sinfo->sinfo_timetolive = 0;
	test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL,
		     gstatus.sstat_rwnd + RWND_SLOP);

	/* Now send the message with timeout. */
	sinfo->sinfo_ppid = ppid;
	sinfo->sinfo_stream = stream;
	outmessage.msg_iov->iov_base = ttlmsg;
	outmessage.msg_iov->iov_len = strlen(ttlmsg) + 1;
	outmessage.msg_name = NULL;
	outmessage.msg_namelen = 0;
	sinfo->sinfo_assoc_id = associd1;
	sinfo->sinfo_timetolive = 2000;
	test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, strlen(ttlmsg) + 1);

	tst_resm(TPASS, "Send a message with timeout");

	/* Next send a message with no timeout. */
	sinfo->sinfo_ppid = ppid;
	sinfo->sinfo_stream = stream;
	outmessage.msg_iov->iov_base = nottlmsg;
	outmessage.msg_iov->iov_len = strlen(nottlmsg) + 1;
	outmessage.msg_name = NULL;
	outmessage.msg_namelen = 0;
	sinfo->sinfo_assoc_id = associd1;
	sinfo->sinfo_timetolive = 0;
	test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, strlen(nottlmsg) + 1);

	tst_resm(TPASS, "Send a message with no timeout");

	/* And finally a fragmented message that will time out. */
	sinfo->sinfo_ppid = ppid;
	sinfo->sinfo_stream = stream;
	memset(ttlfrag, '0', sizeof(ttlfrag));
	ttlfrag[sizeof(ttlfrag) - 1] = '\0';
	outmessage.msg_iov->iov_base = ttlfrag;
	outmessage.msg_iov->iov_len = sizeof(ttlfrag);
	outmessage.msg_name = NULL;
	outmessage.msg_namelen = 0;
	sinfo->sinfo_assoc_id = associd1;
	sinfo->sinfo_timetolive = 2000;
	test_sendmsg(sk1, &outmessage, MSG_NOSIGNAL, sizeof(ttlfrag));

	tst_resm(TPASS, "Send a fragmented message with timeout");

	/* Sleep waiting for the message to time out. */
	tst_resm(TINFO, " **  SLEEPING for 3 seconds **");
	sleep(3);

	/* Read the fillmsg snuck in between the ttl'd messages. */
	do {
		inmessage.msg_controllen = sizeof(incmsg);
		error = test_recvmsg(sk2, &inmessage, MSG_WAITALL);
	} while (!(inmessage.msg_flags & MSG_EOR));

	/* Now get the message that did NOT time out. */
	inmessage.msg_controllen = sizeof(incmsg);
	error = test_recvmsg(sk2, &inmessage, MSG_WAITALL);
	test_check_msg_data(&inmessage, error, strlen(nottlmsg) + 1,
			    MSG_EOR, stream, ppid);
	if (0 != strncmp(iov.iov_base, nottlmsg, strlen(nottlmsg) + 1))
		tst_brkm(TBROK, NULL, "Received Wrong Message !!!");

	tst_resm(TPASS, "Receive message with no timeout");

	/* Get the SEND_FAILED notification for the message that DID
	 * time out.
	 */
	inmessage.msg_controllen = sizeof(incmsg);
	error = test_recvmsg(sk1, &inmessage, MSG_WAITALL);
	test_check_msg_notification(&inmessage, error,
				    sizeof(struct sctp_send_failed) +
				    strlen(ttlmsg) + 1, SCTP_SEND_FAILED, 0);
	ssf = (struct sctp_send_failed *)iov.iov_base;
	if (0 != strncmp(ttlmsg, (char *)ssf->ssf_data, strlen(ttlmsg) + 1))
		tst_brkm(TBROK, NULL, "SEND_FAILED data mismatch");

	tst_resm(TPASS, "Receive SEND_FAILED for message with timeout");

	/* Get the SEND_FAILED notification for the fragmented message that
	 * DID time out.
	 */
	offset = 0;
	do {
		inmessage.msg_controllen = sizeof(incmsg);
		error = test_recvmsg(sk1, &inmessage, MSG_WAITALL);
		test_check_msg_notification(&inmessage, error,
					    sizeof(struct sctp_send_failed) +
					    SMALL_MAXSEG, SCTP_SEND_FAILED, 0);
		ssf = (struct sctp_send_failed *)iov.iov_base;
		if (0 != strncmp(&ttlfrag[offset], (char *)ssf->ssf_data,
				 SMALL_MAXSEG))
			tst_brkm(TBROK, NULL, "SEND_FAILED data mismatch");
		offset += SMALL_MAXSEG;
	} while (!(ssf->ssf_info.sinfo_flags & 0x01));	/* LAST_FRAG */

	tst_resm(TPASS, "Receive SEND_FAILED for fragmented message with "
		 "timeout");

	/* Shut down the link.  */
	close(sk1);

	/* Get the shutdown complete notification. */
	inmessage.msg_controllen = sizeof(incmsg);
	error = test_recvmsg(sk2, &inmessage, MSG_WAITALL);
	test_check_msg_notification(&inmessage, error,
				    sizeof(struct sctp_assoc_change),
				    SCTP_ASSOC_CHANGE, SCTP_SHUTDOWN_COMP);

	close(sk2);

	/* Indicate successful completion.  */
	tst_exit();
}
Exemplo n.º 19
0
int SP_ProcPduUtils :: send_fd (int sockfd, int fd)
{

	struct msghdr msg;
	struct iovec iov[1];

#ifdef	HAVE_MSGHDR_MSG_CONTROL
	union
	{
		struct cmsghdr cm;
		char control[CMSG_SPACE(sizeof(int))];
	} control_un;
	struct cmsghdr *cmptr;

	msg.msg_control = control_un.control;
	msg.msg_controllen = sizeof(control_un.control);

	cmptr = CMSG_FIRSTHDR(&msg);
	cmptr->cmsg_len = CMSG_LEN(sizeof(int));
	cmptr->cmsg_level = SOL_SOCKET;
	cmptr->cmsg_type = SCM_RIGHTS;
	*((int *) CMSG_DATA(cmptr)) = fd;
	#else
		msg.msg_accrights = (caddr_t) &fd;
		msg.msg_accrightslen = sizeof(int);
	#endif

	msg.msg_name = NULL;
	msg.msg_namelen = 0;

	char buf[1];
	iov[0].iov_base = buf;
	iov[0].iov_len = 1;
	msg.msg_iov = iov;
	msg.msg_iovlen = 1;


	for( ; ; ) {
		errno = 0;
		if (sendmsg(sockfd, &msg, 0) != 1) {
			if( EINTR == errno ) {
				continue;
			} else {
				return -1;
			}
		} else {
			break;
		}
	}

	return 0;

/*
	char tmpbuf[CONTROLLEN];
	struct cmsghdr *cmptr = (struct cmsghdr *) tmpbuf;
	struct iovec iov[1];
	struct msghdr msg;
	char buf[1];

	iov[0].iov_base = buf;
	iov[0].iov_len = 1;
	msg.msg_iov = iov;
	msg.msg_iovlen = 1;
	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_control = cmptr;
	msg.msg_controllen = CONTROLLEN;

	cmptr->cmsg_level = SOL_SOCKET;
	cmptr->cmsg_type = SCM_RIGHTS;
	cmptr->cmsg_len = CONTROLLEN;
	*(int *)CMSG_DATA (cmptr) = fd;

	for( ; ; ) {
		errno = 0;
		if (sendmsg(sockfd, &msg, 0) != 1) {
			if( EINTR == errno ) {
				continue;
			} else {
				return -1;
			}
		} else {
			break;
		}
	}

	return 0;
	*/
}
Exemplo n.º 20
0
int main_tls_client() {
  SSL_CTX *ctx;
  SSL *ssl;
  int server = 0;
  int ret;

  if ( (ctx = SSL_CTX_new(SSLv23_client_method())) == NULL)
    printf("Unable to create a new SSL context structure.\n");

  SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2);
  // Force gcm(aes) mode
  SSL_CTX_set_cipher_list(ctx, "ECDH-ECDSA-AES128-GCM-SHA256");

  ssl = SSL_new(ctx);

  server = create_socket();

  SSL_set_fd(ssl, server);

  if ( SSL_connect(ssl) != 1 ) {
    printf("Error: Could not build a SSL session\n");
    exit(-1);
  }

// Start tests

  clock_t start, end;
  double cpu_time_used;

  int filefd;
  int bytes;
  int totalbytes = 0;
  bytes_recv = 0;
  char buf[16384];

  int res = 0;
  int total_recv = 0;

  start = clock();

  filefd = open(test_data, O_RDONLY);
  totalbytes = 0;

  do {
    bytes = read(filefd, buf, sizeof(buf));
    totalbytes += bytes;
    if (bytes > 0)
      SSL_write(ssl, buf, bytes);
  } while(bytes > 0);

  close(filefd);


    end = clock();
    cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;

    printf("OpenSSL receive time: %.02f\n", cpu_time_used);

  res = 0;
  total_recv = 0;

  res = SSL_read(ssl, buf, 1);

  total_recv += res;
  if (res < 0) {
    printf("SSL Read error: %i\n", res);
  }
  printf("Received openssl test data: %i %i\n", res, total_recv);

/* Kernel TLS tests */
  int tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
  if (tfmfd == -1) {
    perror("socket error:");
    exit(-1);
  }

  struct sockaddr_alg sa = {
    .salg_family = AF_ALG,
    .salg_type = "tls", /* this selects the hash logic in the kernel */
    .salg_name = "rfc5288(gcm(aes))" /* this is the cipher name */
  };

  if (bind(tfmfd, (struct sockaddr *)&sa, sizeof(sa)) == -1) {
    perror("AF_ALG: bind failed");
    close(tfmfd);
    exit(-1);
  }

  int opfd = accept(tfmfd, NULL, 0);
  if (opfd == -1) {
    perror("accept:");
    close(tfmfd);
    exit(-1);
  }

  if (setsockopt(tfmfd, SOL_ALG, ALG_SET_AEAD_AUTHSIZE, NULL, 16)) {
    perror("AF_ALG: set authsize failed\n");
    exit(-1);
  }

  EVP_CIPHER_CTX * writeCtx = ssl->enc_write_ctx;
  EVP_CIPHER_CTX * readCtx = ssl->enc_read_ctx;

  EVP_AES_GCM_CTX* gcmWrite = (EVP_AES_GCM_CTX*)(writeCtx->cipher_data);
  EVP_AES_GCM_CTX* gcmRead = (EVP_AES_GCM_CTX*)(readCtx->cipher_data);

  unsigned char* writeKey = (unsigned char*)(gcmWrite->gcm.key);
  unsigned char* readKey = (unsigned char*)(gcmRead->gcm.key);

  unsigned char* writeIV = gcmWrite->iv;
  unsigned char* readIV = gcmRead->iv;

  char keyiv[20];
  memcpy(keyiv, writeKey, 16);
  memcpy(keyiv + 16, writeIV, 4);

  if (setsockopt(tfmfd, SOL_ALG, ALG_SET_KEY, keyiv, 20)) {
    perror("AF_ALG: set write key failed\n");
    exit(-1);
  }

  memcpy(keyiv, readKey, 16);
  memcpy(keyiv + 16, readIV, 4);

  if (setsockopt(tfmfd, SOL_ALG, ALG_SET_KEY, keyiv, 20)) {
    perror("AF_ALG: set read key failed\n");
    exit(-1);
  }

  // Load up the cmsg data
  struct cmsghdr *header = NULL;
  uint32_t *type = NULL;
  struct msghdr msg;

  /* IV data */
  struct af_alg_iv *alg_iv = NULL;
  int ivsize = 12;
  uint32_t iv_msg_size = CMSG_SPACE(sizeof(*alg_iv) + ivsize);

  /* AEAD data */
  uint32_t *assoclen = NULL;
  uint32_t assoc_msg_size = CMSG_SPACE(sizeof(*assoclen));

  uint32_t bufferlen =
    CMSG_SPACE(sizeof(*type)) + /* Encryption / Decryption */
    iv_msg_size +/* IV */
    assoc_msg_size;/* AEAD associated data size */

  memset(&msg, 0, sizeof(msg));

  char* buffer = calloc(1, bufferlen);
  if (!buffer)
    return -ENOMEM;

  msg.msg_control = buffer;
  msg.msg_controllen = bufferlen;
  msg.msg_iov = NULL;
  msg.msg_iovlen = 0;

  /* encrypt/decrypt operation */
  header = CMSG_FIRSTHDR(&msg);
  header->cmsg_level = SOL_ALG;
  header->cmsg_type = ALG_SET_OP;
  header->cmsg_len = CMSG_LEN(sizeof(*type));
  type = (void*)CMSG_DATA(header);
  *type = server;


  /* set IV */
  header = CMSG_NXTHDR(&msg, header);
  header->cmsg_level = SOL_ALG;
  header->cmsg_type = ALG_SET_IV;
  header->cmsg_len = iv_msg_size;
  alg_iv = (void*)CMSG_DATA(header);
  alg_iv->ivlen = 8;
  uint64_t writeSeq;
  unsigned char* writeSeqNum = ssl->s3->write_sequence;
  memcpy(&writeSeq, writeSeqNum, sizeof(writeSeq));

  memcpy(alg_iv->iv, &writeSeq, 8);


  /* set AEAD information */
  /* Set associated data length */
  header = CMSG_NXTHDR(&msg, header);
  header->cmsg_level = SOL_ALG;
  header->cmsg_type = ALG_SET_AEAD_ASSOCLEN;
  header->cmsg_len = CMSG_LEN(sizeof(*assoclen));
  assoclen = (void*)CMSG_DATA(header);
  *assoclen = 13 + 8;

  ret = sendmsg(opfd, &msg, MSG_MORE);
  if (ret < 0) {
    perror("sendmsg");
    exit(-1);
  }

  header = CMSG_FIRSTHDR(&msg);
  header = CMSG_NXTHDR(&msg, header);
  alg_iv = (void*)CMSG_DATA(header);
  uint64_t readSeq;
  unsigned char* readSeqNum = ssl->s3->read_sequence;
  memcpy(&readSeq, readSeqNum, sizeof(readSeq));
  memcpy(alg_iv->iv, &readSeq, 8);

  ret = sendmsg(opfd, &msg, MSG_MORE);
  if (ret < 0) {
    perror("sendmsg recv");
    exit(-1);
  }

  // Try some simple writes

  send(opfd, buf, 10, 0);
  send(opfd, buf, 100, 0);
  send(opfd, buf, 16000, 0);
  printf("Successful send\n");

  res = 0;
  total_recv = 0;

  res = recv(opfd, &buf, 1, 0);

  total_recv += res;
  if (res < 0) {
    printf("Ktls recv error: %i\n", res);
  }
  printf("Recvd ktls test data: %i %i\n", res, total_recv);

  start = clock();
  off_t offset = 0;


  filefd = open(test_data, O_RDONLY);

  res = sendfile(opfd, filefd, &offset, totalbytes);

  close(filefd);

  end = clock();
  cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;

  printf("ktls receive time: %.02f\n", cpu_time_used);

  SSL_free(ssl);
  close(server);
  SSL_CTX_free(ctx);
  return(0);
}

int OpenListener(int port)
{   int sd;
  struct sockaddr_in6 addr;

  sd = socket(PF_INET6, SOCK_STREAM, 0);
  bzero(&addr, sizeof(addr));
  addr.sin6_family = AF_INET6;
  addr.sin6_port = htons(port);
  memcpy(addr.sin6_addr.s6_addr, &in6addr_any, sizeof(in6addr_any));

  if ( bind(sd, (const struct sockaddr*)&addr, sizeof(addr)) != 0 )
    {
      perror("can't bind port");
      abort();
    }
  if ( listen(sd, 10) != 0 )
    {
      perror("Can't configure listening port");
      abort();
    }
  return sd;
}
Exemplo n.º 21
0
int recv_fd(int fd,ssize_t (*userfunc)(int,const void *,size_t))
{
	int newfd,nr,status;
	char *ptr;
	char buf[magicnum::localsocketfun::BUFFERSIZE];
	struct iovec iov[1];
	struct msghdr msg;
	status=-1;
	for(;;)
	{
		iov[0].iov_base=buf;
		iov[0].iov_len=sizeof(buf);
		msg.msg_iov=iov;
		msg.msg_iovlen=1;
		msg.msg_name=NULL;
		msg.msg_namelen=0;
		if(cmptr==NULL&&(cmptr=(cmsghdr*)malloc(CONTROLLEN))==NULL)
		{
			return magicnum::FAILIED;
		}
		msg.msg_control=cmptr;
		msg.msg_controllen=CONTROLLEN;
		if((nr=recvmsg(fd,&msg,0))<0)
		{
			if(errno == EAGAIN || errno == EINTR)//EAGAIN:缓存无数据;EINTR:系统中断
			{
				//printf("buffer no data\n");//缓存区已无数据可读
				//readbytes = 0;
				continue;
			}
			perror("recvmsg");
			//perror("recv");
			return magicnum::FAILIED;
		}
		else if(nr==0)
		{
			printf("connection closed by server\n");
			return magicnum::FAILIED;
		}
		for(ptr=buf;ptr<&buf[nr];)
		{
			if(*ptr++==0){
				assert(ptr == &buf[nr-1]);
				status=*ptr&0xFF;
				if(status==0)
				{
					if(msg.msg_controllen!=CONTROLLEN)
					{
						printf("status=0,but no fd\n");
						return magicnum::FAILIED;
					}
					newfd=*(int*)CMSG_DATA(cmptr);
				}
				else
				{
					newfd=-status;
				}
				nr=-2;
			}
		}
		if(nr > 0 && (*userfunc)(STDERR_FILENO,buf,nr)!=nr)
		{
			return magicnum::FAILIED;
		}
		if(status>=0)
		{
			return(newfd);
		}
	}
}
Exemplo n.º 22
0
int J1939SocketRead (int Socket, struct J1939FrameBag *Bags, unsigned int BagsCount, int TimeoutMs)
{
    struct mmsghdr msgs[BagsCount];
    struct iovec iovs[BagsCount];
    struct sockaddr_can addr[BagsCount];
    char ctrlmsgs[BagsCount][
            CMSG_SPACE(sizeof(struct timeval))
          + CMSG_SPACE(sizeof(__u8)) /* dest addr */
          + CMSG_SPACE(sizeof(__u64)) /* dest name */
          + CMSG_SPACE(sizeof(__u8)) /* priority */
          ];

    unsigned int i;
    for (i = 0; i < BagsCount; i++)
    {
        memset(&msgs[i], 0, sizeof(msgs[0]));
        memset(&iovs[i], 0, sizeof(iovs[0]));
        memset(&addr[i], 0, sizeof(addr[0]));

        msgs[i].msg_hdr.msg_name = &addr[i];
        msgs[i].msg_hdr.msg_namelen = sizeof(struct sockaddr_can);

        iovs[i].iov_base = (void *) &(Bags[i].Frame.data);
        iovs[i].iov_len = sizeof(Bags[i].Frame.data);
        msgs[i].msg_hdr.msg_iov = &iovs[i];
        msgs[i].msg_hdr.msg_iovlen = 1;

        msgs[i].msg_hdr.msg_control = &ctrlmsgs[i];
        msgs[i].msg_hdr.msg_controllen = sizeof(ctrlmsgs[0]);
        msgs[i].msg_hdr.msg_flags = 0;
    }

    struct timeval tNow, tEnd;
    for ( initTimers(&tNow, &tEnd, TimeoutMs); timercmp(&tNow, &tEnd, <); gettimeofday (&tNow, NULL) )
    {
        int rcount;
        rcount = recvmmsg(Socket, msgs, BagsCount, MSG_DONTWAIT, NULL);
        if (rcount >= 0)
        {
            int i;
            for (i = 0; i < rcount; i ++)
            {
                struct timeval tv;
                struct cmsghdr *cmsg;

                for (cmsg = CMSG_FIRSTHDR(&msgs[i].msg_hdr);
                    cmsg;
                    cmsg = CMSG_NXTHDR(&msgs[i].msg_hdr,cmsg))
                {
                    switch (cmsg->cmsg_level) {
                    case SOL_SOCKET:
                        if (cmsg->cmsg_type == SO_TIMESTAMP)
                        {
                            tv = *(struct timeval *)CMSG_DATA(cmsg);
                            Bags[i].TimeStamp.seconds = tv.tv_sec;
                            Bags[i].TimeStamp.microseconds = tv.tv_usec;
                        }
                        else if (cmsg->cmsg_type == SO_RXQ_OVFL)
                            Bags[i].DroppedMessagesCount = *(__u32 *)CMSG_DATA(cmsg);
                        break;
                    case SOL_CAN_J1939:

                        break;
                    }
                }

                Bags[i].Frame.pgn = addr[i].can_addr.j1939.pgn;
                Bags[i].Frame.length = msgs[i].msg_len;

                if (msgs[i].msg_hdr.msg_flags & MSG_CONFIRM)
                    Bags[i].Flags |= (1 << 0);
            }
            return rcount;
        }
        else
        {
            int errsv = errno;
            if (errsv == EAGAIN)
              continue;
            else
              return errsv;
        }
    }
    return 0;
}
Exemplo n.º 23
0
int
main(int argc, char *argv[])
{
    struct msghdr msgh;
    struct iovec iov;
    int data, sfd, opt, fd;
    ssize_t ns;
    Boolean useDatagramSocket;
    union {
        struct cmsghdr cmh;
        char   control[CMSG_SPACE(sizeof(int))];
                        /* Space large enough to hold an 'int' */
    } control_un;
    struct cmsghdr *cmhp;

    /* Parse command-line arguments */

    useDatagramSocket = FALSE;

    while ((opt = getopt(argc, argv, "d")) != -1) {
        switch (opt) {
        case 'd':
            useDatagramSocket = TRUE;
            break;

        default:
            usageErr("%s [-d] file\n"
                     "        -d    use datagram socket\n", argv[0]);
        }
    }

    if (argc != optind + 1)
        usageErr("%s [-d] file\n", argv[0]);

    /* Open the file named on the command line */

    fd = open(argv[optind], O_RDONLY);
    if (fd == -1)
        errExit("open");

    /* On Linux, we must transmit at least 1 byte of real data in
       order to send ancillary data */

    msgh.msg_iov = &iov;
    msgh.msg_iovlen = 1;
    iov.iov_base = &data;
    iov.iov_len = sizeof(int);
    data = 12345;

    /* We don't need to specify destination address, because we use
       connect() below */

    msgh.msg_name = NULL;
    msgh.msg_namelen = 0;

    msgh.msg_control = control_un.control;
    msgh.msg_controllen = sizeof(control_un.control);

    fprintf(stderr, "Sending fd %d\n", fd);

    /* Set message header to describe ancillary data that we want to send */

    cmhp = CMSG_FIRSTHDR(&msgh);
    cmhp->cmsg_len = CMSG_LEN(sizeof(int));
    cmhp->cmsg_level = SOL_SOCKET;
    cmhp->cmsg_type = SCM_RIGHTS;
    *((int *) CMSG_DATA(cmhp)) = fd;

    /*
    We could rewrite the preceding lines as:

    control_un.cmh.cmsg_len = CMSG_LEN(sizeof(int));
    control_un.cmh.cmsg_level = SOL_SOCKET;
    control_un.cmh.cmsg_type = SCM_RIGHTS;
    *((int *) CMSG_DATA(CMSG_FIRSTHDR(&msgh))) = fd;
    */

    /* Do the actual send */

    sfd = unixConnect(SOCK_PATH, useDatagramSocket ? SOCK_DGRAM : SOCK_STREAM);
    if (sfd == -1)
        errExit("unixConnect");

    ns = sendmsg(sfd, &msgh, 0);
    if (ns == -1)
        errExit("sendmsg");

    fprintf(stderr, "sendmsg() returned %ld\n", (long) ns);
    exit(EXIT_SUCCESS);
}
Exemplo n.º 24
0
const char *
format_extended_socket_error (int fd, int *mtu, struct gc_arena *gc)
{
    int res;
    struct probehdr rcvbuf;
    struct iovec iov;
    struct msghdr msg;
    struct cmsghdr *cmsg;
    struct sock_extended_err *e;
    struct sockaddr_in addr;
    struct buffer out = alloc_buf_gc (256, gc);
    char *cbuf = (char *) gc_malloc (256, false, gc);

    *mtu = 0;

    while (true)
    {
        memset (&rcvbuf, -1, sizeof (rcvbuf));
        iov.iov_base = &rcvbuf;
        iov.iov_len = sizeof (rcvbuf);
        msg.msg_name = (uint8_t *) &addr;
        msg.msg_namelen = sizeof (addr);
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
        msg.msg_flags = 0;
        msg.msg_control = cbuf;
        msg.msg_controllen = 256; /* size of cbuf */

        res = recvmsg (fd, &msg, MSG_ERRQUEUE);
        if (res < 0)
            goto exit;

        e = NULL;

        for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; cmsg = CMSG_NXTHDR (&msg, cmsg))
        {
            if (cmsg->cmsg_level == SOL_IP)
            {
                if (cmsg->cmsg_type == IP_RECVERR)
                {
                    e = (struct sock_extended_err *) CMSG_DATA (cmsg);
                }
                else
                {
                    buf_printf (&out ,"CMSG=%d|", cmsg->cmsg_type);
                }
            }
        }
        if (e == NULL)
        {
            buf_printf (&out, "NO-INFO|");
            goto exit;
        }

        switch (e->ee_errno)
        {
        case ETIMEDOUT:
            buf_printf (&out, "ETIMEDOUT|");
            break;
        case EMSGSIZE:
            buf_printf (&out, "EMSGSIZE Path-MTU=%d|", e->ee_info);
            *mtu = e->ee_info;
            break;
        case ECONNREFUSED:
            buf_printf (&out, "ECONNREFUSED|");
            break;
        case EPROTO:
            buf_printf (&out, "EPROTO|");
            break;
        case EHOSTUNREACH:
            buf_printf (&out, "EHOSTUNREACH|");
            break;
        case ENETUNREACH:
            buf_printf (&out, "ENETUNREACH|");
            break;
        case EACCES:
            buf_printf (&out, "EACCES|");
            break;
        default:
            buf_printf (&out, "UNKNOWN|");
            break;
        }
    }

exit:
    buf_rmtail (&out, '|');
    return BSTR (&out);
}
Exemplo n.º 25
0
int main(int ac,char **av)
{
struct msghdr msghdr;
struct iovec iovector[10];
int i,s,j,ma;
struct sockaddr_in sockad; 
char msg[128];
struct cmsghdr *cmsg,*cm2; 
char opts[24];

ma=250;
printf("just wait and watch memory usage\n");

memset(opts,0,sizeof(opts));

while(42)
{
s=socket(PF_INET, /*SOCK_STREAM*/ SOCK_DGRAM, 0);
sockad.sin_family = AF_INET;
sockad.sin_addr.s_addr=inet_addr("127.0.0.1");
sockad.sin_port=htons(8080); 

connect(s,(struct sockaddr *) &sockad, sizeof(sockad)); 

memset(msg,'v',sizeof(msg));
#define VV (ma*(sizeof(struct cmsghdr)+sizeof(opts))+1024*1024)
cmsg = malloc(VV);
memset(cmsg,0,VV);
cmsg->cmsg_len = sizeof(struct cmsghdr) + sizeof(opts);
cmsg->cmsg_level = SOL_IP;
cmsg->cmsg_type = IP_RETOPTS;
memcpy(CMSG_DATA(cmsg), opts, sizeof(opts));

cm2= (struct cmsghdr *) (long) ((char *)CMSG_DATA(cmsg)+sizeof(opts));
for(j=0;j<ma;j++)
{
cm2->cmsg_level = SOL_IP;
cm2->cmsg_type = IP_RETOPTS;
cm2->cmsg_len =  sizeof(struct cmsghdr) + sizeof(opts); 
cm2= (struct cmsghdr *) (long) ((char *)CMSG_DATA(cm2)+sizeof(opts));
}

cm2->cmsg_level = SOL_IP;
cm2->cmsg_type = IP_RETOPTS;
cm2->cmsg_len =  sizeof(struct cmsghdr) + 8; 

msghdr.msg_name = &sockad;
msghdr.msg_namelen = sizeof(sockad);

msghdr.msg_control=cmsg;
msghdr.msg_controllen= cmsg->cmsg_len + (j)*cmsg->cmsg_len+cm2->cmsg_len;  
msghdr.msg_iov = iovector;

msghdr.msg_iovlen = 1;
iovector[0].iov_base = msg;
iovector[0].iov_len = sizeof(msg);

if ((i = sendmsg(s, &msghdr, 0)) < 0)
{perror("sendmsg");return -42;}

close(s);
free(cmsg);
}
return 42;
}
Exemplo n.º 26
0
/*
 * Read a message from the specified connection carrying file descriptors
 */
int
pool_recvfds(PoolPort *port, int *fds, int count)
{
	int			r;
	uint		n32;
	char		buf[SEND_MSG_BUFFER_SIZE];
	struct iovec iov[1];
	struct msghdr msg;
	int                     controllen = CMSG_LEN(count * sizeof(int));
	struct cmsghdr *cmptr = malloc(CMSG_SPACE(count * sizeof(int)));

	if (cmptr == NULL)
		return EOF;

	iov[0].iov_base = buf;
	iov[0].iov_len = SEND_MSG_BUFFER_SIZE;
	msg.msg_iov = iov;
	msg.msg_iovlen = 1;
	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_control = (caddr_t) cmptr;
	msg.msg_controllen = controllen;

	r = recvmsg(Socket(*port), &msg, 0);
	if (r < 0)
	{
		/*
		 * Report broken connection
		 */
		ereport(ERROR,
				(errcode_for_socket_access(),
				 errmsg("could not receive data from client: %m")));
		goto failure;
	}
	else if (r == 0)
	{
		goto failure;
	}
	else if (r != SEND_MSG_BUFFER_SIZE)
	{
		ereport(ERROR,
				(errcode(ERRCODE_PROTOCOL_VIOLATION),
				 errmsg("incomplete message from client [size: %u errno %u]",r,errno)));
		goto failure;
	}

	/* Verify response */
	if (buf[0] != 'f')
	{
		ereport(ERROR,
				(errcode(ERRCODE_PROTOCOL_VIOLATION),
				 errmsg("unexpected message code")));
		goto failure;
	}

	memcpy(&n32, buf + 1, 4);
	n32 = ntohl(n32);
	if (n32 != 8)
	{
		ereport(ERROR,
				(errcode(ERRCODE_PROTOCOL_VIOLATION),
				 errmsg("invalid message size")));
		goto failure;
	}

	/*
	 * If connection count is 0 it means pool does not have connections
	 * to  fulfill request. Otherwise number of returned connections
	 * should be equal to requested count. If it not the case consider this
	 * a protocol violation. (Probably connection went out of sync)
	 */
	memcpy(&n32, buf + 5, 4);
	n32 = ntohl(n32);
	if (n32 == 0)
	{
		ereport(LOG,
				(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
				 errmsg("failed to acquire connections")));
		goto failure;
	}

	if (n32 != count)
	{
		ereport(ERROR,
				(errcode(ERRCODE_PROTOCOL_VIOLATION),
				 errmsg("unexpected connection count")));
		goto failure;
	}

	memcpy(fds, CMSG_DATA(CMSG_FIRSTHDR(&msg)), count * sizeof(int));
	free(cmptr);
	return 0;
failure:
	free(cmptr);
	return EOF;
}
Exemplo n.º 27
0
//RY: start here
void network_thread_IPv6()
{
	/*
     * We loop forever waiting on either data from the ppp drivers or from
     * our network socket.  Control handling is no longer done here.
     */
    struct sockaddr_in6 from, to;
    unsigned int fromlen, tolen;
    int tunnel, call;           /* Tunnel and call */
    int recvsize;               /* Length of data received */
    struct buffer6 *buf;         /* Payload buffer */
    struct call6 *c, *sc;        /* Call to send this off to */
    struct tunnel6 *st;          /* Tunnel */
    fd_set readfds;             /* Descriptors to watch for reading */
    int max;                    /* Highest fd */
    struct timeval tv;          /* Timeout for select */
    struct msghdr msgh;
    struct iovec iov;
    char cbuf[256];
    unsigned int refme, refhim;

    /* This one buffer can be recycled for everything except control packets */
    buf = new_buf6 (MAX_RECV_SIZE);

    tunnel = 0;
    call = 0;

    for (;;)
    {
        max = build_fdset_ipv6 (&readfds);
        tv.tv_sec = 1;//RY:commented for testing
        //tv.tv_sec = 0;//RY: made 0 for testing, anyways not being used in select().
        tv.tv_usec = 0;
        schedule_unlock ();

		// RY: start
#if 0
		buf->peer = from;
		buf->len = sizeof(from);
		buf->start = NULL;
        udp_xmit6 (buf, st);
        udp_xmit6 (buf, st);
        udp_xmit6 (buf, st);

#endif
        //RY: end
        select (max + 1, &readfds, NULL, NULL, NULL);
        schedule_lock ();
        if (FD_ISSET (control_fd, &readfds))
        {
            do_control6 ();
        }
        //TODO: Mistake prone line.RY:
        if (FD_ISSET (server_socket6, &readfds))
        {
            /*
             * Okay, now we're ready for reading and processing new data.
             */
            recycle_buf6 (buf);

            /* Reserve space for expanding payload packet headers */
            buf->start += PAYLOAD_BUF;
            buf->len -= PAYLOAD_BUF;

            memset(&from, 0, sizeof(from));
            memset(&to,   0, sizeof(to));

            fromlen = sizeof(from);
            tolen   = sizeof(to);

            memset(&msgh, 0, sizeof(struct msghdr));
            iov.iov_base = buf->start;
            iov.iov_len  = buf->len;
            msgh.msg_control = cbuf;
            msgh.msg_controllen = sizeof(cbuf);
            msgh.msg_name = &from;
            msgh.msg_namelen = fromlen;
            msgh.msg_iov  = &iov;
            msgh.msg_iovlen = 1;
            msgh.msg_flags = 0;
//RY: start here
	    /* Receive one packet. */
            recvsize = recvmsg(server_socket6, &msgh, 0);

//RY: ends here
            if (recvsize < MIN_PAYLOAD_HDR_LEN)
            {
                if (recvsize < 0)
                {
                    if (errno != EAGAIN)
                        l2tp_log (LOG_WARNING,
                             "%s: recvfrom returned error %d (%s)\n",
                             __FUNCTION__, errno, strerror (errno));
                }
                else
                {
                    l2tp_log (LOG_WARNING, "%s: received too small a packet\n",
                         __FUNCTION__);
                }
                continue;
            }

	    refme=refhim=0;

	    /* extract IPsec info out */
	    if(gconfig.ipsecsaref) {
		    struct cmsghdr *cmsg;
		    /* Process auxiliary received data in msgh */
		    for (cmsg = CMSG_FIRSTHDR(&msgh);
			 cmsg != NULL;
			 cmsg = CMSG_NXTHDR(&msgh,cmsg)) {
			    if (cmsg->cmsg_level == IPPROTO_IPV6
				&& cmsg->cmsg_type == IP_IPSEC_REFINFO) {	//RY: can be changed to
				    unsigned int *refp;

				    refp = (unsigned int *)CMSG_DATA(cmsg);
				    refme =refp[0];
				    refhim=refp[1];
			    }
		    }
	    }

	    /*
	     * some logic could be added here to verify that we only
	     * get L2TP packets inside of IPsec, or to provide different
	     * classes of service to packets not inside of IPsec.
	     */
	    buf->len = recvsize;
	    fix_hdr (buf->start);
	    extract (buf->start, &tunnel, &call);

	    if (gconfig.debug_network)
	    {
	    	//RY: start
	    	//TODO: un-comment later..
	    	l2tp_log(LOG_DEBUG, "RY: packet received");
//		l2tp_log(LOG_DEBUG, "%s: recv packet from %s, size = %d, "
//			 "tunnel = %d, call = %d ref=%u refhim=%u\n",
//			 __FUNCTION__, inet_ntop(from.sin6_addr),
//			 recvsize, tunnel, call, refme, refhim);
	    	//RY: end
	    }

	    if (gconfig.packet_dump)
	    {
	    	do_packet_dump6 (buf);
	    }
	    if (!
		(c = get_call6 (tunnel, call, from.sin6_addr,
			       from.sin6_port, refme, refhim)))
	    {
			if ((c =
				get_tunnel6 (tunnel, from.sin6_port)))
			{
		    /*
		     * It is theoretically possible that we could be sent
		     * a control message (say a StopCCN) on a call that we
		     * have already closed or some such nonsense.  To
		     * prevent this from closing the tunnel, if we get a
		     * call on a valid tunnel, but not with a valid CID,
		     * we'll just send a ZLB to ack receiving the packet.
		     */
				if (gconfig.debug_tunnel)
				l2tp_log (LOG_DEBUG,
				  "%s: no such call %d on tunnel %d.  Sending special ZLB\n",
				  __FUNCTION__);
				handle_special6 (buf, c, call);

				/* get a new buffer */
				buf = new_buf6 (MAX_RECV_SIZE);
			}
			else
				l2tp_log (LOG_DEBUG,
			      "%s: unable to find call or tunnel to handle packet.  call = %d, tunnel = %d Dumping.\n",
			      __FUNCTION__, call, tunnel);

		}
	    else
	    {
	    	buf->peer = from;
			/* Handle the packet */
			c->container->chal_us.vector = NULL;
			if (handle_packet6 (buf, c->container, c))
			{
				if (gconfig.debug_tunnel)
				l2tp_log (LOG_DEBUG, "%s: bad packet\n", __FUNCTION__);
			}
			if (c->cnu)
			{
				/* Send Zero Byte Packet */
				control_zlb6 (buf, c->container, c);
				c->cnu = 0;
			}
	    }
	}

	/*
	 * finished obvious sources, look for data from PPP connections.
	 */
	st = tunnels6.head;
        while (st)
        {
            sc = st->call_head;
            while (sc)
            {
                if ((sc->fd >= 0) && FD_ISSET (sc->fd, &readfds))
                {
                    /* Got some payload to send */
                    int result;
                    recycle_payload6 (buf, sc->container->peer);
/*
#ifdef DEBUG_FLOW_MORE
                    l2tp_log (LOG_DEBUG, "%s: rws = %d, pSs = %d, pLr = %d\n",
                         __FUNCTION__, sc->rws, sc->pSs, sc->pLr);
#endif
		    if ((sc->rws>0) && (sc->pSs > sc->pLr + sc->rws) && !sc->rbit) {
#ifdef DEBUG_FLOW
						log(LOG_DEBUG, "%s: throttling payload (call = %d, tunnel = %d, Lr = %d, Ss = %d, rws = %d)!\n",__FUNCTION__,
								 sc->cid, sc->container->tid, sc->pLr, sc->pSs, sc->rws);
#endif
						sc->throttle = -1;
						We unthrottle in handle_packet if we get a payload packet,
						valid or ZLB, but we also schedule a dethrottle in which
						case the R-bit will be set
						FIXME: Rate Adaptive timeout?
						tv.tv_sec = 2;
						tv.tv_usec = 0;
						sc->dethrottle = schedule(tv, dethrottle, sc);
					} else */
/*					while ((result=read_packet(buf,sc->fd,sc->frame & SYNC_FRAMING))>0) { */
                    while ((result =
                            read_packet6 (buf, sc->fd, SYNC_FRAMING)) > 0)
                    {
                        add_payload_hdr6 (sc->container, sc, buf);
                        if (gconfig.packet_dump)
                        {
                            do_packet_dump6 (buf);
                        }

                        sc->prx = sc->data_rec_seq_num;
                        if (sc->zlb_xmit6)
                        {
                            deschedule (sc->zlb_xmit6);
                            sc->zlb_xmit6 = NULL;
                        }
                        sc->tx_bytes += buf->len;
                        sc->tx_pkts++;
                        udp_xmit6 (buf, st);
                        recycle_payload6 (buf, sc->container->peer);
                    }
                    if (result != 0)
                    {
                        l2tp_log (LOG_WARNING,
                             "%s: tossing read packet, error = %s (%d).  Closing call.\n",
                             __FUNCTION__, strerror (-result), -result);
                        strcpy (sc->errormsg, strerror (-result));
                        sc->needclose = -1;
                    }
                }
                sc = sc->next;
            }
            st = st->next;
        }
    }
}
Exemplo n.º 28
0
static int NaClDescConnCapFdConnectAddr(struct NaClDesc *vself,
                                        struct NaClDesc **out_desc) {
  struct NaClDescConnCapFd  *self = (struct NaClDescConnCapFd *) vself;
  NaClHandle                sock_pair[2];
  struct NaClDescImcDesc    *connected_socket;
  char                      control_buf[CMSG_SPACE_KHANDLE_COUNT_MAX_INTS];
  struct iovec              iovec;
  struct msghdr             connect_msg;
  struct cmsghdr            *cmsg;
  int                       sent;
  int                       retval;

  assert(CMSG_SPACE(sizeof(int)) <= CMSG_SPACE_KHANDLE_COUNT_MAX_INTS);

  sock_pair[0] = NACL_INVALID_HANDLE;
  sock_pair[1] = NACL_INVALID_HANDLE;
  connected_socket = (struct NaClDescImcDesc *) NULL;

  retval = -NACL_ABI_EINVAL;

  if (0 != NaClSocketPair(sock_pair)) {
    retval = -NACL_ABI_EMFILE;
    goto cleanup;
  }

  iovec.iov_base = "c";
  iovec.iov_len = 1;
  connect_msg.msg_iov = &iovec;
  connect_msg.msg_iovlen = 1;
  connect_msg.msg_name = NULL;
  connect_msg.msg_namelen = 0;
  connect_msg.msg_control = control_buf;
  connect_msg.msg_controllen = sizeof(control_buf);
  connect_msg.msg_flags = 0;

  cmsg = CMSG_FIRSTHDR(&connect_msg);
  cmsg->cmsg_len = CMSG_LEN(sizeof(int));
  cmsg->cmsg_level = SOL_SOCKET;
  cmsg->cmsg_type = SCM_RIGHTS;
  /*
   * We use memcpy() rather than assignment through a cast to avoid
   * strict-aliasing warnings
   */
  memcpy(CMSG_DATA(cmsg), &sock_pair[0], sizeof(int));
  /* Set msg_controllen to the actual size of the cmsg. */
  connect_msg.msg_controllen = cmsg->cmsg_len;

  sent = sendmsg(self->connect_fd, &connect_msg, 0);
  if (1 != sent) {
    retval = -NACL_ABI_EIO;
    goto cleanup;
  }

  if (NACL_OSX) {
    /*
     * Mac OS X has a kernel bug in which a socket descriptor that is
     * referenced only from the message queue of another socket can
     * get garbage collected.  This causes the socket descriptor not
     * to work properly.  To work around this, we don't close our
     * reference to the socket until we receive an acknowledgement
     * that it has been successfully received.
     *
     * We cannot receive the acknowledgement through self->connect_fd
     * because this FD could be shared between multiple processes.  So
     * we receive the acknowledgement through the socket pair that we
     * have just created.
     *
     * However, this creates a risk that we are left hanging if the
     * other process dies after our sendmsg() call, because we are
     * holding on to the socket that it would use to send the ack.  To
     * avoid this problem, we use poll() so that we will be notified
     * if self->connect_fd becomes unwritable.
     * TODO(mseaborn): Add a test case to simulate that scenario.
     *
     * See http://code.google.com/p/nativeclient/issues/detail?id=1796
     *
     * Note that we are relying on a corner case of poll() here.
     * Using POLLHUP in "events" is not meaningful on Linux, which is
     * documented as ignoring POLLHUP as an input argument and will
     * return POLLHUP in "revents" even if it not present in "events".
     * On Mac OS X, however, passing events == 0 does not work if we
     * want to get POLLHUP.  We are in the unusual situation of
     * waiting for a socket to become *un*writable.
     */
    struct pollfd poll_fds[2];
    poll_fds[0].fd = self->connect_fd;
    poll_fds[0].events = POLLHUP;
    poll_fds[1].fd = sock_pair[1];
    poll_fds[1].events = POLLIN;
    if (poll(poll_fds, 2, -1) < 0) {
      NaClLog(LOG_ERROR,
              "NaClDescConnCapFdConnectAddr: poll() failed, errno %d\n", errno);
      retval = -NACL_ABI_EIO;
      goto cleanup;
    }
    /*
     * It is not necessarily an error if POLLHUP fires on
     * self->connect_fd: The other process could have done
     * imc_accept(S) and then closed S.  This means it will have
     * received sock_pair[0] successfully, so we can close our
     * reference to sock_pair[0] and then receive the ack.
     * TODO(mseaborn): Add a test case to cover this scenario.
     */
  }

  (void) NaClClose(sock_pair[0]);
  sock_pair[0] = NACL_INVALID_HANDLE;

  if (NACL_OSX) {
    /* Receive the acknowledgement.  We do not expect this to block. */
    char ack_buffer[1];
    ssize_t received = recv(sock_pair[1], ack_buffer, sizeof(ack_buffer), 0);
    if (received != 1 || ack_buffer[0] != 'a') {
      retval = -NACL_ABI_EIO;
      goto cleanup;
    }
  }

  connected_socket = malloc(sizeof(*connected_socket));
  if (NULL == connected_socket ||
      !NaClDescImcDescCtor(connected_socket, sock_pair[1])) {
    retval = -NACL_ABI_ENOMEM;
    goto cleanup;
  }
  sock_pair[1] = NACL_INVALID_HANDLE;

  *out_desc = (struct NaClDesc *) connected_socket;
  connected_socket = NULL;
  retval = 0;

cleanup:
  NaClSafeCloseNaClHandle(sock_pair[0]);
  NaClSafeCloseNaClHandle(sock_pair[1]);
  free(connected_socket);

  return retval;
}
Exemplo n.º 29
0
void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
{
	struct cmsghdr __user *cm
		= (__force struct cmsghdr __user*)msg->msg_control;

	int fdmax = 0;
	int fdnum = scm->fp->count;
	struct file **fp = scm->fp->fp;
	int __user *cmfptr;
	int err = 0, i;

	if (MSG_CMSG_COMPAT & msg->msg_flags) {
		scm_detach_fds_compat(msg, scm);
		return;
	}

	if (msg->msg_controllen > sizeof(struct cmsghdr))
		fdmax = ((msg->msg_controllen - sizeof(struct cmsghdr))
			 / sizeof(int));

	if (fdnum < fdmax)
		fdmax = fdnum;

	for (i=0, cmfptr=(__force int __user *)CMSG_DATA(cm); i<fdmax;
	     i++, cmfptr++)
	{
		int new_fd;
		err = security_file_receive(fp[i]);
		if (err)
			break;
		err = get_unused_fd_flags(MSG_CMSG_CLOEXEC & msg->msg_flags
					  ? O_CLOEXEC : 0);
		if (err < 0)
			break;
		new_fd = err;
		err = put_user(new_fd, cmfptr);
		if (err) {
			put_unused_fd(new_fd);
			break;
		}
		/* Bump the usage count and install the file. */
		get_file(fp[i]);
		fd_install(new_fd, fp[i]);
	}

	if (i > 0)
	{
		int cmlen = CMSG_LEN(i*sizeof(int));
		err = put_user(SOL_SOCKET, &cm->cmsg_level);
		if (!err)
			err = put_user(SCM_RIGHTS, &cm->cmsg_type);
		if (!err)
			err = put_user(cmlen, &cm->cmsg_len);
		if (!err) {
			cmlen = CMSG_SPACE(i*sizeof(int));
			msg->msg_control += cmlen;
			msg->msg_controllen -= cmlen;
		}
	}
	if (i < fdnum || (fdnum && fdmax <= 0))
		msg->msg_flags |= MSG_CTRUNC;

	/*
	 * All of the files that fit in the message have had their
	 * usage counts incremented, so we just free the list.
	 */
	__scm_destroy(scm);
}
Exemplo n.º 30
0
Arquivo: stream.c Projeto: Darkie/node
static void uv__read(uv_stream_t* stream) {
  uv_buf_t buf;
  ssize_t nread;
  struct msghdr msg;
  struct cmsghdr* cmsg;
  char cmsg_space[64];
  struct ev_loop* ev = stream->loop->ev;

  /* XXX: Maybe instead of having UV_READING we just test if
   * tcp->read_cb is NULL or not?
   */
  while ((stream->read_cb || stream->read2_cb) &&
         stream->flags & UV_READING) {
    assert(stream->alloc_cb);
    buf = stream->alloc_cb((uv_handle_t*)stream, 64 * 1024);

    assert(buf.len > 0);
    assert(buf.base);
    assert(stream->fd >= 0);

    if (stream->read_cb) {
      do {
        nread = read(stream->fd, buf.base, buf.len);
      }
      while (nread < 0 && errno == EINTR);
    } else {
      assert(stream->read2_cb);
      /* read2_cb uses recvmsg */
      msg.msg_flags = 0;
      msg.msg_iov = (struct iovec*) &buf;
      msg.msg_iovlen = 1;
      msg.msg_name = NULL;
      msg.msg_namelen = 0;
      /* Set up to receive a descriptor even if one isn't in the message */
      msg.msg_controllen = 64;
      msg.msg_control = (void *) cmsg_space;

      do {
        nread = recvmsg(stream->fd, &msg, 0);
      }
      while (nread < 0 && errno == EINTR);
    }


    if (nread < 0) {
      /* Error */
      if (errno == EAGAIN) {
        /* Wait for the next one. */
        if (stream->flags & UV_READING) {
          ev_io_start(ev, &stream->read_watcher);
        }
        uv__set_sys_error(stream->loop, EAGAIN);

        if (stream->read_cb) {
          stream->read_cb(stream, 0, buf);
        } else {
          stream->read2_cb((uv_pipe_t*)stream, 0, buf, UV_UNKNOWN_HANDLE);
        }

        return;
      } else {
        /* Error. User should call uv_close(). */
        uv__set_sys_error(stream->loop, errno);

        if (stream->read_cb) {
          stream->read_cb(stream, -1, buf);
        } else {
          stream->read2_cb((uv_pipe_t*)stream, -1, buf, UV_UNKNOWN_HANDLE);
        }

        assert(!ev_is_active(&stream->read_watcher));
        return;
      }

    } else if (nread == 0) {
      /* EOF */
      uv__set_artificial_error(stream->loop, UV_EOF);
      ev_io_stop(ev, &stream->read_watcher);

      if (stream->read_cb) {
        stream->read_cb(stream, -1, buf);
      } else {
        stream->read2_cb((uv_pipe_t*)stream, -1, buf, UV_UNKNOWN_HANDLE);
      }
      return;
    } else {
      /* Successful read */
      ssize_t buflen = buf.len;

      if (stream->read_cb) {
        stream->read_cb(stream, nread, buf);
      } else {
        assert(stream->read2_cb);

        /*
         * XXX: Some implementations can send multiple file descriptors in a
         * single message. We should be using CMSG_NXTHDR() to walk the
         * chain to get at them all. This would require changing the API to
         * hand these back up the caller, is a pain.
         */

        for (cmsg = CMSG_FIRSTHDR(&msg);
             msg.msg_controllen > 0 && cmsg != NULL;
             cmsg = CMSG_NXTHDR(&msg, cmsg)) {

          if (cmsg->cmsg_type == SCM_RIGHTS) {
            if (stream->accepted_fd != -1) {
              fprintf(stderr, "(libuv) ignoring extra FD received\n");
            }

            stream->accepted_fd = *(int *) CMSG_DATA(cmsg);

          } else {
            fprintf(stderr, "ignoring non-SCM_RIGHTS ancillary data: %d\n",
                cmsg->cmsg_type);
          }
        }


        if (stream->accepted_fd >= 0) {
          stream->read2_cb((uv_pipe_t*)stream, nread, buf, UV_TCP);
        } else {
          stream->read2_cb((uv_pipe_t*)stream, nread, buf, UV_UNKNOWN_HANDLE);
        }
      }

      /* Return if we didn't fill the buffer, there is no more data to read. */
      if (nread < buflen) {
        return;
      }
    }
  }
}