static void ping(const char *host)
{
	char packet[datalen + MAXIPLEN + MAXICMPLEN];
	char buf[INET6_ADDRSTRLEN];
	int sockopt;
	struct msghdr msg;
	struct sockaddr_in6 from;
	struct iovec iov;
	char control_buf[CMSG_SPACE(36)];

	pingsock = create_icmp6_socket();

	memset(&pingaddr, 0, sizeof(struct sockaddr_in));

	pingaddr.sin6_family = AF_INET6;
	hostent = xgethostbyname2(host, AF_INET6);
	if (hostent->h_addrtype != AF_INET6)
		bb_error_msg_and_die("unknown address type; only AF_INET6 is currently supported.");

	memcpy(&pingaddr.sin6_addr, hostent->h_addr, sizeof(pingaddr.sin6_addr));

#ifdef ICMP6_FILTER
	{
		struct icmp6_filter filt;
		if (!(options & O_VERBOSE)) {
			ICMP6_FILTER_SETBLOCKALL(&filt);
#if 0
			if ((options & F_FQDN) || (options & F_FQDNOLD) ||
				(options & F_NODEADDR) || (options & F_SUPTYPES))
				ICMP6_FILTER_SETPASS(ICMP6_NI_REPLY, &filt);
			else
#endif
				ICMP6_FILTER_SETPASS(ICMP6_ECHO_REPLY, &filt);
		} else {
			ICMP6_FILTER_SETPASSALL(&filt);
		}
		if (setsockopt(pingsock, IPPROTO_ICMPV6, ICMP6_FILTER, &filt,
					   sizeof(filt)) < 0)
			bb_error_msg_and_die("setsockopt(ICMP6_FILTER)");
	}
#endif /*ICMP6_FILTER*/

	/* enable broadcast pings */
	sockopt = 1;
	setsockopt(pingsock, SOL_SOCKET, SO_BROADCAST, (char *) &sockopt,
			   sizeof(sockopt));

	/* set recv buf for broadcast pings */
	sockopt = 48 * 1024;
	setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, (char *) &sockopt,
			   sizeof(sockopt));

	sockopt = offsetof(struct icmp6_hdr, icmp6_cksum);
	setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, (char *) &sockopt,
			   sizeof(sockopt));

	sockopt = 1;
	setsockopt(pingsock, SOL_IPV6, IPV6_HOPLIMIT, (char *) &sockopt,
			   sizeof(sockopt));

	if (ifname) {
		if ((pingaddr.sin6_scope_id = if_nametoindex(ifname)) == 0)
			bb_error_msg_and_die("%s: invalid interface name", ifname);
	}

	printf("PING %s (%s): %d data bytes\n",
	           hostent->h_name,
			   inet_ntop(AF_INET6, (struct in_addr6 *) &pingaddr.sin6_addr,
						 buf, sizeof(buf)),
		   datalen);

	signal(SIGINT, pingstats);

	/* start the ping's going ... */
	sendping(0);

	/* listen for replies */
	msg.msg_name=&from;
	msg.msg_namelen=sizeof(from);
	msg.msg_iov=&iov;
	msg.msg_iovlen=1;
	msg.msg_control=control_buf;
	iov.iov_base=packet;
	iov.iov_len=sizeof(packet);
	while (1) {
		int c;
		struct cmsghdr *cmsgptr = NULL;
		int hoplimit=-1;
		msg.msg_controllen=sizeof(control_buf);

		if ((c = recvmsg(pingsock, &msg, 0)) < 0) {
			if (errno == EINTR)
				continue;
			bb_perror_msg("recvfrom");
			continue;
		}
		for (cmsgptr = CMSG_FIRSTHDR(&msg); cmsgptr != NULL;
			 cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
			if (cmsgptr->cmsg_level == SOL_IPV6 &&
				cmsgptr->cmsg_type == IPV6_HOPLIMIT ) {
				hoplimit=*(int*)CMSG_DATA(cmsgptr);
			}
		}
		unpack(packet, c, &from, hoplimit);
		if (pingcount > 0 && nreceived >= pingcount)
			break;
	}
	pingstats(0);
}
示例#2
0
	dst.sin6_addr.s6_addr16[0] = IPV6_ADDR_INT16_MLL;
	dst.sin6_addr.s6_addr16[1] = 0;
	dst.sin6_addr.s6_addr32[1] = 0;
	dst.sin6_addr.s6_addr32[2] = IPV6_ADDR_INT32_ONE;
	dst.sin6_addr.s6_addr32[3] = ap->addr.s6_addr32[3];
	dst.sin6_addr.s6_addr[12] = 0xff;

	//memcpy(&dst.sin6_addr, &ap->addr, sizeof(dst.sin6_addr));
	dst.sin6_scope_id = ap->iface->index;

	sndhdr.msg_name = (caddr_t)&dst;
	sndhdr.msg_iov[0].iov_base = ap->ns;
	sndhdr.msg_iov[0].iov_len = ap->nslen;

	/* Set the outbound interface */
	cm = CMSG_FIRSTHDR(&sndhdr);
	cm->cmsg_level = IPPROTO_IPV6;
	cm->cmsg_type = IPV6_PKTINFO;
	cm->cmsg_len = CMSG_LEN(sizeof(pi));
	memset(&pi, 0, sizeof(pi));
	pi.ipi6_ifindex = ap->iface->index;
	memcpy(CMSG_DATA(cm), &pi, sizeof(pi));

	/* Hop limit */
	cm = CMSG_NXTHDR(&sndhdr, cm);
	cm->cmsg_level = IPPROTO_IPV6;
	cm->cmsg_type = IPV6_HOPLIMIT;
	cm->cmsg_len = CMSG_LEN(sizeof(hoplimit));
	memcpy(CMSG_DATA(cm), &hoplimit, sizeof(hoplimit));

#ifdef DEBUG_NS
示例#3
0
int udp_send_msg(int sock, uint8_t *data, size_t data_len,
		 struct sockaddr *local_addr,
		 struct sockaddr *peer_addr) {
	int err = 0, on = 1, sendnum;
	int is_ipv4 = ((peer_addr->sa_family == AF_INET) ? 1 : 0);
	uint8_t cmsgbuf[CMSG_SPACE(sizeof(struct in_pktinfo))];
        struct cmsghdr *cmsg; // = (struct cmsghdr *) cmsgbuf;
	struct msghdr msg;
	struct iovec iov;
	union {
		struct in_pktinfo *in4;
		struct inet6_pktinfo *in6;
	} pktinfo;

	/* The first memset is mandatory. Results in otherwise weird
	   EMSGSIZE errors. */
	memset(&msg, 0, sizeof(struct msghdr));	
	memset(cmsgbuf, 0, sizeof(cmsgbuf));

	/* Fill message header */

	msg.msg_name = peer_addr;
	if (is_ipv4)
		msg.msg_namelen = sizeof(struct sockaddr_in);
	else
		msg.msg_namelen = sizeof(struct sockaddr_in6);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = cmsgbuf;
	msg.msg_controllen = sizeof(cmsgbuf);
	msg.msg_flags = 0;
	
	iov.iov_base = data;
	iov.iov_len = data_len;

	/* Set local address */
	cmsg = CMSG_FIRSTHDR(&msg);
	if (is_ipv4)
		cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
	else
		cmsg->cmsg_len = CMSG_LEN(sizeof(struct inet6_pktinfo));
	cmsg->cmsg_level = (is_ipv4) ? IPPROTO_IP : IPPROTO_IPV6;
	cmsg->cmsg_type = (is_ipv4) ? IP_PKTINFO : IPV6_2292PKTINFO;

	pktinfo.in6 = (struct inet6_pktinfo *) CMSG_DATA(cmsg);
	if (is_ipv4)
		pktinfo.in4->ipi_addr.s_addr =
			((struct sockaddr_in *) local_addr)->sin_addr.s_addr;
	else
		memcpy(&pktinfo.in6->ipi6_addr,
		       &(((struct sockaddr_in6 *) local_addr)->sin6_addr),
		       sizeof(struct in6_addr));
	
	/* Send reply using the ORIGINAL src/dst address pair */
	sendnum = sendmsg(sock, &msg, 0);
	if (sendnum < 0) {
		perror("sendmsg");
		err = -1;
		goto out_err;
	}
	
	printf("=== Sent string successfully back ===\n");
	printf("=== Server listening IN6ADDR_ANY ===\n");

out_err:

	return err;
}
/*
 * Receive a file descriptor from a server process. Also, any data
 * receive is passed to (*userfunc)(STDERR_FILENO, buf, nbytes).
 * We have a 2-byte protocol for receiving the fd from send_fd().
 */
int recv_fd(int fd, ssize_t (*userfunc)(int, const void *, size_t))
{
    struct cmsghdr *cmp;
    struct CREDSTRUCT *credp;
    int newfd, nr, status;
    char *ptr;
    char buf[MAXLINE];
    struct iovec iov[1];
    struct msghdr msg;
    const int on = 1;

    status = -1;
    newfd = -1;
    if (setsockopt(fd, SOL_SOCKET, &on, sizeof(int)) < 0) {
        err_ret("setsockopt failed");
        return(-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 = malloc(CONTROLEN)) == NULL)
            return(-1);
        msg.msg_control = cmptr;
        msg.msg_controllen = CONTROLEN;
        if ((nr = recvmsg(fd, &msg, 0)) < 0) {
            err_sys("recvmsg error");
        } else if (nr == 0) {
            err_ret("connection closed by server");
            return(-1);
        }
        /*
         * See if this is the final data with null & status. NULL
         * is next to last byte of buffer; status byte is last byte.
         * Zero status means there is a file descriptor to receive.
         */
        for (ptr = buf; ptr < &buf[nr]; ) {
            if (*ptr++ >= 0) {
                if (ptr != &buf[n-1])
                    err_dump("message format error");
                status = *ptr & 0xFF;   /* prevent sign extension */
                if (status == 0) {
                    if (msg.msg_controllen != CONTROLLEN)
                        err_dump("status = 0 but no fd");
                    
                    /* process the control data */
                    for (cmp = CMSG_FIRSTHDR(&msg);
                            cmp != NULL; cmp = CMSG_NXTHDR(&msg, cmp)) {
                        if (cmp->cmsg_level != SOL_SOCKET)
                            continue;
                        switch (cmp->cmsg_type) {
                            case SCM_RIGHTS:
                                newfd = *(int *)CMSG_DATA(cmp);
                                break;
                            case SCM_CREDTYPE:
                                credp = (struct CREDSTRUCT *)CMSG_DATA(cmp);
                                *uidptr = credp->CR_UID;
                        }
                    }
                } else {
                    newfd = -status;
                }
                nr -= 2;
            }
        }
        if (nr > 0 && (*userfunc)(STDERR_FILENO, buf, nr) != nr)
            return(-1);
        if (status >= 0)    /* final data has arrived */
            return(newfd);
    }
}
示例#5
0
int recvfromto(int s, void *buf, size_t len, int flags,
	       struct sockaddr *from, socklen_t *fromlen,
	       struct sockaddr *to, socklen_t *tolen)
{
	struct msghdr msgh;
	struct cmsghdr *cmsg;
	struct iovec iov;
	char cbuf[256];
	int err;
	struct sockaddr_storage si;
	socklen_t si_len = sizeof(si);

#if !defined(IP_PKTINFO) && !defined(IP_RECVDSTADDR) && !defined(IPV6_PKTINFO)
	/*
	 *	If the recvmsg() flags aren't defined, fall back to
	 *	using recvfrom().
	 */
	to = NULL:
#endif

	/*
	 *	Catch the case where the caller passes invalid arguments.
	 */
	if (!to || !tolen) return recvfrom(s, buf, len, flags, from, fromlen);

	/*
	 *	Clang analyzer doesn't see that getsockname initialises
	 *	the memory passed to it.
	 */
#ifdef __clang_analyzer__
	memset(&si, 0, sizeof(si));
#endif

	/*
	 *	recvmsg doesn't provide sin_port so we have to
	 *	retrieve it using getsockname().
	 */
	if (getsockname(s, (struct sockaddr *)&si, &si_len) < 0) {
		return -1;
	}

	/*
	 *	Initialize the 'to' address.  It may be INADDR_ANY here,
	 *	with a more specific address given by recvmsg(), below.
	 */
	if (si.ss_family == AF_INET) {
#if !defined(IP_PKTINFO) && !defined(IP_RECVDSTADDR)
		return recvfrom(s, buf, len, flags, from, fromlen);
#else
		struct sockaddr_in *dst = (struct sockaddr_in *) to;
		struct sockaddr_in *src = (struct sockaddr_in *) &si;

		if (*tolen < sizeof(*dst)) {
			errno = EINVAL;
			return -1;
		}
		*tolen = sizeof(*dst);
		*dst = *src;
#endif
	}

#ifdef AF_INET6
	else if (si.ss_family == AF_INET6) {
#if !defined(IPV6_PKTINFO)
		return recvfrom(s, buf, len, flags, from, fromlen);
#else
		struct sockaddr_in6 *dst = (struct sockaddr_in6 *) to;
		struct sockaddr_in6 *src = (struct sockaddr_in6 *) &si;

		if (*tolen < sizeof(*dst)) {
			errno = EINVAL;
			return -1;
		}
		*tolen = sizeof(*dst);
		*dst = *src;
#endif
	}
#endif
	/*
	 *	Unknown address family.
	 */
	else {
		errno = EINVAL;
		return -1;
	}

	/* Set up iov and msgh structures. */
	memset(&cbuf, 0, sizeof(cbuf));
	memset(&msgh, 0, sizeof(struct msghdr));
	iov.iov_base = buf;
	iov.iov_len  = len;
	msgh.msg_control = cbuf;
	msgh.msg_controllen = sizeof(cbuf);
	msgh.msg_name = from;
	msgh.msg_namelen = fromlen ? *fromlen : 0;
	msgh.msg_iov  = &iov;
	msgh.msg_iovlen = 1;
	msgh.msg_flags = 0;

	/* Receive one packet. */
	if ((err = recvmsg(s, &msgh, flags)) < 0) {
		return err;
	}

	if (fromlen) *fromlen = msgh.msg_namelen;

	/* Process auxiliary received data in msgh */
	for (cmsg = CMSG_FIRSTHDR(&msgh);
	     cmsg != NULL;
	     cmsg = CMSG_NXTHDR(&msgh,cmsg)) {

#ifdef IP_PKTINFO
		if ((cmsg->cmsg_level == SOL_IP) &&
		    (cmsg->cmsg_type == IP_PKTINFO)) {
			struct in_pktinfo *i =
				(struct in_pktinfo *) CMSG_DATA(cmsg);
			((struct sockaddr_in *)to)->sin_addr = i->ipi_addr;
			*tolen = sizeof(struct sockaddr_in);
			break;
		}
#endif

#ifdef IP_RECVDSTADDR
		if ((cmsg->cmsg_level == IPPROTO_IP) &&
		    (cmsg->cmsg_type == IP_RECVDSTADDR)) {
			struct in_addr *i = (struct in_addr *) CMSG_DATA(cmsg);
			((struct sockaddr_in *)to)->sin_addr = *i;
			*tolen = sizeof(struct sockaddr_in);
			break;
		}
#endif

#ifdef IPV6_PKTINFO
		if ((cmsg->cmsg_level == IPPROTO_IPV6) &&
		    (cmsg->cmsg_type == IPV6_PKTINFO)) {
			struct in6_pktinfo *i =
				(struct in6_pktinfo *) CMSG_DATA(cmsg);
			((struct sockaddr_in6 *)to)->sin6_addr = i->ipi6_addr;
			*tolen = sizeof(struct sockaddr_in6);
			break;
		}
#endif
	}

	return err;
}
示例#6
0
文件: stream.c 项目: MaxNanasy/node
/* On success returns NULL. On error returns a pointer to the write request
 * which had the error.
 */
static void uv__write(uv_stream_t* stream) {
  uv_write_t* req;
  struct iovec* iov;
  int iovcnt;
  ssize_t n;

  if (stream->flags & UV_CLOSING) {
    /* Handle was closed this tick. We've received a stale
     * 'is writable' callback from the event loop, ignore.
     */
    return;
  }

start:

  assert(stream->fd >= 0);

  /* Get the request at the head of the queue. */
  req = uv_write_queue_head(stream);
  if (!req) {
    assert(stream->write_queue_size == 0);
    return;
  }

  assert(req->handle == stream);

  /*
   * Cast to iovec. We had to have our own uv_buf_t instead of iovec
   * because Windows's WSABUF is not an iovec.
   */
  assert(sizeof(uv_buf_t) == sizeof(struct iovec));
  iov = (struct iovec*) &(req->bufs[req->write_index]);
  iovcnt = req->bufcnt - req->write_index;

  /*
   * Now do the actual writev. Note that we've been updating the pointers
   * inside the iov each time we write. So there is no need to offset it.
   */

  if (req->send_handle) {
    struct msghdr msg;
    char scratch[64];
    struct cmsghdr *cmsg;
    int fd_to_send = req->send_handle->fd;

    assert(fd_to_send >= 0);

    msg.msg_name = NULL;
    msg.msg_namelen = 0;
    msg.msg_iov = iov;
    msg.msg_iovlen = iovcnt;
    msg.msg_flags = 0;

    msg.msg_control = (void*) scratch;
    msg.msg_controllen = CMSG_LEN(sizeof(fd_to_send));

    cmsg = CMSG_FIRSTHDR(&msg);
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SCM_RIGHTS;
    cmsg->cmsg_len = msg.msg_controllen;
    *(int*) CMSG_DATA(cmsg) = fd_to_send;

    do {
      n = sendmsg(stream->fd, &msg, 0);
    }
    while (n == -1 && errno == EINTR);
  } else {
    do {
      if (iovcnt == 1) {
        n = write(stream->fd, iov[0].iov_base, iov[0].iov_len);
      } else {
        n = writev(stream->fd, iov, iovcnt);
      }
    }
    while (n == -1 && errno == EINTR);
  }

  if (n < 0) {
    if (errno != EAGAIN && errno != EWOULDBLOCK) {
      /* Error */
      req->error = errno;
      stream->write_queue_size -= uv__write_req_size(req);
      uv__write_req_finish(req);
      return;
    } else if (stream->flags & UV_STREAM_BLOCKING) {
      /* If this is a blocking stream, try again. */
      goto start;
    }
  } else {
    /* Successful write */

    /* Update the counters. */
    while (n >= 0) {
      uv_buf_t* buf = &(req->bufs[req->write_index]);
      size_t len = buf->len;

      assert(req->write_index < req->bufcnt);

      if ((size_t)n < len) {
        buf->base += n;
        buf->len -= n;
        stream->write_queue_size -= n;
        n = 0;

        /* There is more to write. */
        if (stream->flags & UV_STREAM_BLOCKING) {
          /*
           * If we're blocking then we should not be enabling the write
           * watcher - instead we need to try again.
           */
          goto start;
        } else {
          /* Break loop and ensure the watcher is pending. */
          break;
        }

      } else {
        /* Finished writing the buf at index req->write_index. */
        req->write_index++;

        assert((size_t)n >= len);
        n -= len;

        assert(stream->write_queue_size >= len);
        stream->write_queue_size -= len;

        if (req->write_index == req->bufcnt) {
          /* Then we're done! */
          assert(n == 0);
          uv__write_req_finish(req);
          /* TODO: start trying to write the next request. */
          return;
        }
      }
    }
  }

  /* Either we've counted n down to zero or we've got EAGAIN. */
  assert(n == 0 || n == -1);

  /* Only non-blocking streams should use the write_watcher. */
  assert(!(stream->flags & UV_STREAM_BLOCKING));

  /* We're not done. */
  uv__io_start(stream->loop, &stream->write_watcher);
}
示例#7
0
int
mm_receive_fd(int sock)
{
#if defined(HAVE_RECVMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR))
	struct msghdr msg;
#ifndef HAVE_ACCRIGHTS_IN_MSGHDR
	union {
		struct cmsghdr hdr;
		char buf[CMSG_SPACE(sizeof(int))];
	} cmsgbuf;
	struct cmsghdr *cmsg;
#endif
	struct iovec vec;
	ssize_t n;
	char ch;
	int fd;
	struct pollfd pfd;

	memset(&msg, 0, sizeof(msg));
	vec.iov_base = &ch;
	vec.iov_len = 1;
	msg.msg_iov = &vec;
	msg.msg_iovlen = 1;
#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
	msg.msg_accrights = (caddr_t)&fd;
	msg.msg_accrightslen = sizeof(fd);
#else
	memset(&cmsgbuf, 0, sizeof(cmsgbuf));
	msg.msg_control = &cmsgbuf.buf;
	msg.msg_controllen = sizeof(cmsgbuf.buf);
#endif

	pfd.fd = sock;
	pfd.events = POLLIN;
	while ((n = recvmsg(sock, &msg, 0)) == -1 &&
	    (errno == EAGAIN || errno == EINTR)) {
		debug3("%s: recvmsg: %s", __func__, strerror(errno));
		(void)poll(&pfd, 1, -1);
	}
	if (n == -1) {
		error("%s: recvmsg: %s", __func__, strerror(errno));
		return -1;
	}

	if (n != 1) {
		error("%s: recvmsg: expected received 1 got %ld",
		    __func__, (long)n);
		return -1;
	}

#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
	if (msg.msg_accrightslen != sizeof(fd)) {
		error("%s: no fd", __func__);
		return -1;
	}
#else
	cmsg = CMSG_FIRSTHDR(&msg);
	if (cmsg == NULL) {
		error("%s: no message header", __func__);
		return -1;
	}

#ifndef BROKEN_CMSG_TYPE
	if (cmsg->cmsg_type != SCM_RIGHTS) {
		error("%s: expected type %d got %d", __func__,
		    SCM_RIGHTS, cmsg->cmsg_type);
		return -1;
	}
#endif
	fd = (*(int *)CMSG_DATA(cmsg));
#endif
	return fd;
#else
	error("%s: file descriptor passing not supported", __func__);
	return -1;
#endif
}
static void data_callback(int fd, uint32_t events, void *user_data)
{
	struct control_data *data = user_data;
	unsigned char control[64];
	struct mgmt_hdr hdr;
	struct msghdr msg;
	struct iovec iov[2];

	if (events & (EPOLLERR | EPOLLHUP)) {
		mainloop_remove_fd(data->fd);
		return;
	}

	iov[0].iov_base = &hdr;
	iov[0].iov_len = MGMT_HDR_SIZE;
	iov[1].iov_base = data->buf;
	iov[1].iov_len = sizeof(data->buf);

	memset(&msg, 0, sizeof(msg));
	msg.msg_iov = iov;
	msg.msg_iovlen = 2;
	msg.msg_control = control;
	msg.msg_controllen = sizeof(control);

	while (1) {
		struct cmsghdr *cmsg;
		struct timeval *tv = NULL;
		struct timeval ctv;
		struct ucred *cred = NULL;
		struct ucred ccred;
		uint16_t opcode, index, pktlen;
		ssize_t len;

		len = recvmsg(data->fd, &msg, MSG_DONTWAIT);
		if (len < 0)
			break;

		if (len < MGMT_HDR_SIZE)
			break;

		for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
					cmsg = CMSG_NXTHDR(&msg, cmsg)) {
			if (cmsg->cmsg_level != SOL_SOCKET)
				continue;

			if (cmsg->cmsg_type == SCM_TIMESTAMP) {
				memcpy(&ctv, CMSG_DATA(cmsg), sizeof(ctv));
				tv = &ctv;
			}

			if (cmsg->cmsg_type == SCM_CREDENTIALS) {
				memcpy(&ccred, CMSG_DATA(cmsg), sizeof(ccred));
				cred = &ccred;
			}
		}

		opcode = le16_to_cpu(hdr.opcode);
		index  = le16_to_cpu(hdr.index);
		pktlen = le16_to_cpu(hdr.len);

		switch (data->channel) {
		case HCI_CHANNEL_CONTROL:
			packet_control(tv, cred, index, opcode,
							data->buf, pktlen);
			break;
		case HCI_CHANNEL_MONITOR:
			btsnoop_write_hci(btsnoop_file, tv, index, opcode,
							data->buf, pktlen);
			ellisys_inject_hci(tv, index, opcode,
							data->buf, pktlen);
			packet_monitor(tv, cred, index, opcode,
							data->buf, pktlen);
			break;
		}
	}
}
示例#9
0
文件: forward.c 项目: Kubing/dnsmasq
/* Send a UDP packet with its source address set as "source" 
   unless nowild is true, when we just send it with the kernel default */
int send_from(int fd, int nowild, char *packet, size_t len, 
	      union mysockaddr *to, struct all_addr *source,
	      unsigned int iface, int *errp)
{
  struct msghdr msg;
  struct iovec iov[1]; 
  union {
    struct cmsghdr align; /* this ensures alignment */
#if defined(HAVE_LINUX_NETWORK)
    char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
#elif defined(IP_SENDSRCADDR)
    char control[CMSG_SPACE(sizeof(struct in_addr))];
#endif
#ifdef HAVE_IPV6
    char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
#endif
  } control_u;
  
  iov[0].iov_base = packet;
  iov[0].iov_len = len;

  msg.msg_control = NULL;
  msg.msg_controllen = 0;
  msg.msg_flags = 0;
  msg.msg_name = to;
  msg.msg_namelen = sa_len(to);
  msg.msg_iov = iov;
  msg.msg_iovlen = 1;
  
  if (!nowild)
    {
      struct cmsghdr *cmptr;
      msg.msg_control = &control_u;
      msg.msg_controllen = sizeof(control_u);
      cmptr = CMSG_FIRSTHDR(&msg);

      if (to->sa.sa_family == AF_INET)
	{
#if defined(HAVE_LINUX_NETWORK)
	  struct in_pktinfo p;
	  p.ipi_ifindex = 0;
	  p.ipi_spec_dst = source->addr.addr4;
	  memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
	  msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
	  cmptr->cmsg_level = IPPROTO_IP;
	  cmptr->cmsg_type = IP_PKTINFO;
#elif defined(IP_SENDSRCADDR)
	  memcpy(CMSG_DATA(cmptr), &(source->addr.addr4), sizeof(source->addr.addr4));
	  msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
	  cmptr->cmsg_level = IPPROTO_IP;
	  cmptr->cmsg_type = IP_SENDSRCADDR;
#endif
	}
      else
#ifdef HAVE_IPV6
	{
	  struct in6_pktinfo p;
	  p.ipi6_ifindex = iface; /* Need iface for IPv6 to handle link-local addrs */
	  p.ipi6_addr = source->addr.addr6;
	  memcpy(CMSG_DATA(cmptr), &p, sizeof(p));
	  msg.msg_controllen = cmptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
	  cmptr->cmsg_type = daemon->v6pktinfo;
	  cmptr->cmsg_level = IPPROTO_IPV6;
	}
#else
      (void)iface; /* eliminate warning */
#endif
    }
  
 retry:
  if (sendmsg(fd, &msg, 0) == -1)
    {
      /* certain Linux kernels seem to object to setting the source address in the IPv6 stack
	 by returning EINVAL from sendmsg. In that case, try again without setting the
	 source address, since it will nearly alway be correct anyway.  IPv6 stinks. */
      if (errno == EINVAL && msg.msg_controllen)
	{
	  msg.msg_controllen = 0;
	  goto retry;
	}
      
      if (retry_send())
	goto retry;
      
      if (errp)
	*errp = errno;
      else
	my_syslog(LOG_ERR, _("failed to send packet: %s"), strerror(errno));
      
      return 0;
    }

  return 1;
}
static void
jdwp_process_event( int  socket, unsigned  events, void*  _proc )
{
    JdwpProcess*  proc = reinterpret_cast<JdwpProcess*>(_proc);

    if (events & FDE_READ) {
        if (proc->pid < 0) {
            /* read the PID as a 4-hexchar string */
            char*  p    = proc->in_buff + proc->in_len;
            int    size = 4 - proc->in_len;
            char   temp[5];
            while (size > 0) {
                int  len = recv( socket, p, size, 0 );
                if (len < 0) {
                    if (errno == EINTR)
                        continue;
                    if (errno == EAGAIN)
                        return;
                    /* this can fail here if the JDWP process crashes very fast */
                    D("weird unknown JDWP process failure: %s\n",
                      strerror(errno));

                    goto CloseProcess;
                }
                if (len == 0) {  /* end of stream ? */
                    D("weird end-of-stream from unknown JDWP process\n");
                    goto CloseProcess;
                }
                p            += len;
                proc->in_len += len;
                size         -= len;
            }
            /* we have read 4 characters, now decode the pid */
            memcpy(temp, proc->in_buff, 4);
            temp[4] = 0;

            if (sscanf( temp, "%04x", &proc->pid ) != 1) {
                D("could not decode JDWP %p PID number: '%s'\n", proc, temp);
                goto CloseProcess;
            }

            /* all is well, keep reading to detect connection closure */
            D("Adding pid %d to jdwp process list\n", proc->pid);
            jdwp_process_list_updated();
        }
        else
        {
            /* the pid was read, if we get there it's probably because the connection
             * was closed (e.g. the JDWP process exited or crashed) */
            char  buf[32];

            for (;;) {
                int  len = recv(socket, buf, sizeof(buf), 0);

                if (len <= 0) {
                    if (len < 0 && errno == EINTR)
                        continue;
                    if (len < 0 && errno == EAGAIN)
                        return;
                    else {
                        D("terminating JDWP %d connection: %s\n", proc->pid,
                          strerror(errno));
                        break;
                    }
                }
                else {
                    D( "ignoring unexpected JDWP %d control socket activity (%d bytes)\n",
                       proc->pid, len );
                }
            }

        CloseProcess:
            if (proc->pid >= 0)
                D( "remove pid %d to jdwp process list\n", proc->pid );
            jdwp_process_free(proc);
            return;
        }
    }

    if (events & FDE_WRITE) {
        D("trying to write to JDWP pid controli (count=%d first=%d) %d\n",
          proc->pid, proc->out_count, proc->out_fds[0]);
        if (proc->out_count > 0) {
            int  fd = proc->out_fds[0];
            int  n, ret;
            struct cmsghdr*  cmsg;
            struct msghdr    msg;
            struct iovec     iov;
            char             dummy = '!';
            char             buffer[sizeof(struct cmsghdr) + sizeof(int)];
            int flags;

            iov.iov_base       = &dummy;
            iov.iov_len        = 1;
            msg.msg_name       = NULL;
            msg.msg_namelen    = 0;
            msg.msg_iov        = &iov;
            msg.msg_iovlen     = 1;
            msg.msg_flags      = 0;
            msg.msg_control    = buffer;
            msg.msg_controllen = sizeof(buffer);

            cmsg = CMSG_FIRSTHDR(&msg);
            cmsg->cmsg_len   = msg.msg_controllen;
            cmsg->cmsg_level = SOL_SOCKET;
            cmsg->cmsg_type  = SCM_RIGHTS;
            ((int*)CMSG_DATA(cmsg))[0] = fd;

            flags = fcntl(proc->socket,F_GETFL,0);

            if (flags == -1) {
                D("failed to get cntl flags for socket %d: %s\n",
                  proc->pid, strerror(errno));
                goto CloseProcess;

            }

            if (fcntl(proc->socket, F_SETFL, flags & ~O_NONBLOCK) == -1) {
                D("failed to remove O_NONBLOCK flag for socket %d: %s\n",
                  proc->pid, strerror(errno));
                goto CloseProcess;
            }

            for (;;) {
                ret = sendmsg(proc->socket, &msg, 0);
                if (ret >= 0) {
                    adb_close(fd);
                    break;
                }
                if (errno == EINTR)
                    continue;
                D("sending new file descriptor to JDWP %d failed: %s\n",
                  proc->pid, strerror(errno));
                goto CloseProcess;
            }

            D("sent file descriptor %d to JDWP process %d\n",
              fd, proc->pid);

            for (n = 1; n < proc->out_count; n++)
                proc->out_fds[n-1] = proc->out_fds[n];

            if (fcntl(proc->socket, F_SETFL, flags) == -1) {
                D("failed to set O_NONBLOCK flag for socket %d: %s\n",
                  proc->pid, strerror(errno));
                goto CloseProcess;
            }

            if (--proc->out_count == 0)
                fdevent_del( proc->fde, FDE_WRITE );
        }
    }
}
示例#11
0
文件: fdpassing.c 项目: jeoerl/arcan
bool arcan_pushhandle(file_handle source, int channel)
{
	char empty = '!';

	struct cmsgbuf {
		struct cmsghdr hdr;
		int fd[1];
	} msgbuf;

	struct iovec nothing_ptr = {
		.iov_base = &empty,
		.iov_len = 1
	};

	struct msghdr msg = {
		.msg_name = NULL,
		.msg_namelen = 0,
		.msg_iov = &nothing_ptr,
		.msg_iovlen = 1,
		.msg_flags = 0,
	};

	if (-1 == source){
	}
	else {
		msg.msg_control = &msgbuf;
		msg.msg_controllen = CMSG_LEN(sizeof(int));
		struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
		cmsg->cmsg_len = msg.msg_controllen;
		cmsg->cmsg_level = SOL_SOCKET;
		cmsg->cmsg_type  = SCM_RIGHTS;
		int* dptr = (int*) CMSG_DATA(cmsg);
		*dptr = source;
	}

#ifdef __APPLE__
int set = 1;
setsockopt(channel, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));

#endif
	int rv = sendmsg(channel, &msg, MSG_DONTWAIT | MSG_NOSIGNAL);
	return rv >= 0;
}

file_handle arcan_fetchhandle(int sockin_fd, bool block)
{
	if (sockin_fd == -1)
		return -1;

	char empty;

	struct cmsgbuf {
		struct cmsghdr hdr;
		int fd[1];
	} msgbuf;

	struct iovec nothing_ptr = {
		.iov_base = &empty,
		.iov_len = 1
	};

	struct msghdr msg = {
		.msg_name = NULL,
		.msg_namelen = 0,
		.msg_iov = &nothing_ptr,
		.msg_iovlen = 1,
		.msg_flags = 0,
		.msg_control = &msgbuf,
		.msg_controllen = sizeof(struct cmsghdr) + sizeof(int)
	};

	struct cmsghdr* cmsg = CMSG_FIRSTHDR(&msg);
	cmsg->cmsg_len = msg.msg_controllen;
	cmsg->cmsg_level = SOL_SOCKET;
	cmsg->cmsg_type  = SCM_RIGHTS;
	int* dfd = (int*) CMSG_DATA(cmsg);
	*dfd = -1;

	if (-1 == recvmsg(sockin_fd, &msg,
		(!block ? MSG_DONTWAIT : 0)| MSG_NOSIGNAL))
		;

	int nd = msgbuf.fd[0];

	return nd;
}
int
main (int argc, char *argv[])
{
  int i, sd, hoplimit = 255;
  uint16_t seq = 0;
  // IPv6 address
  struct sockaddr_in6 src = { AF_INET6, 0, 0, 0, 0 };
  struct sockaddr_in6 dst = { AF_INET6, 0, 0, 0, 0 };
  char hostname[INET6_ADDRSTRLEN];
  char addr6[INET6_ADDRSTRLEN];
  // ICMPv6 na header
  struct nd_neighbor_advert na;
  // ICMPv6 na header option
  uint8_t option[8];
  // Ancillary data
  struct msghdr msghdr;
  struct cmsghdr *cmsghdr;
  struct iovec iov[2];
  char cmsghdr_buf[CMSG_SPACE (sizeof (hoplimit))];
  // Interface
  struct ifreq ifr;
  // interface address
  struct ifaddrs * ifaddrs = NULL;
  struct ifaddrs * ifaddr = NULL;

  // Usage.
  if (argc < 3) {
    printf ("Usage: %s <interface> <adddress>\n", argv[0]);
    exit (EXIT_SUCCESS);
  }

  // Create a socket to look up interface.
  if ((sd = socket (AF_INET6, SOCK_RAW, IPPROTO_IPV6)) < 0) {
    perror ("socket() ");
    exit (EXIT_FAILURE);
  }

  // Use getifaddrs() to find interface address, ioctl() with SIOCGIFADDR is not work for IPv6.

  // Get interface address list.
  getifaddrs (&ifaddrs);

  // Get all interface and ip address.
  for (ifaddr = ifaddrs; ifaddr != NULL; ifaddr = ifaddr->ifa_next) {
      // IPv6
      if (ifaddr->ifa_addr->sa_family == AF_INET6) {
          struct sockaddr_in6 *addr = (struct sockaddr_in6 *)ifaddr->ifa_addr;
          inet_ntop(AF_INET6, &addr->sin6_addr, addr6, INET6_ADDRSTRLEN);
          if (strcmp (argv[1], ifaddr->ifa_name) == 0) {
            src.sin6_addr = addr->sin6_addr;
            printf("The interface %s address is %s\n", ifaddr->ifa_name, addr6);
          }
      }
  }
  // Free the list.
  if (ifaddrs != NULL)
    freeifaddrs(ifaddrs);

  // Use ioctl() to find hardware address.
  memset (&ifr, 0, sizeof(struct ifreq));
  snprintf (ifr.ifr_name, sizeof(ifr.ifr_name), "%s", argv[1]);
  if (ioctl (sd, SIOCGIFHWADDR, &ifr) < 0) {
    perror ("ioctl() failed to find hardware address ");
    return (EXIT_FAILURE);
  }

  // Set the ICMPv6 ns header option.
  option[0] = 1;            // Option Type - "source link layer address" (Section 4.6 of RFC 4861)
  option[1] = 8 / 8;        // Option Length - units of 8 octets (RFC 4861)
  for (i=0; i<6; i++) {
    option[i+2] = (uint8_t) ifr.ifr_hwaddr.sa_data[i];
  }
  printf ("Hardware address is %02X:%02X:%02X:%02X:%02X:%02X\n", option[2], option[3], option[4], option[5], option[6], option[7]);

  // Use ioctl() to find interface index.
  memset (&ifr, 0, sizeof(struct ifreq));
  snprintf (ifr.ifr_name, sizeof(ifr.ifr_name), "%s", argv[1]);
  if (ioctl (sd, SIOCGIFINDEX, &ifr) < 0) {
    perror ("ioctl() failed to find interface ");
    return (EXIT_FAILURE);
  }
  printf ("Index for interface %s is %i\n", argv[1], ifr.ifr_ifindex);

  // Close sd.
  close (sd);

  // Create a ICMPv6 raw socket.
  // The kernel will fill the IPv6 header automatically.
  if ((sd = socket (AF_INET6, SOCK_RAW, IPPROTO_ICMPV6)) < 0) {
    perror ("socket() ");
    exit (EXIT_FAILURE);
  }

  // Convert the hostname to network bytes.
  if (inet_pton (AF_INET6, argv[2], &(dst.sin6_addr)) < 0) {
    perror ("inet_pton() ");
    exit (EXIT_FAILURE);
  }

  // Bind the interface using setsockopt()
  if (setsockopt (sd, SOL_SOCKET, SO_BINDTODEVICE, (void*)&ifr, sizeof(struct ifreq)) < 0) {
    perror ("setsockopt() failed to bind interface ");
    return (EXIT_FAILURE);
  }

  // Send ICMPv6 neighbor advertisement.

  // 1. Construct ICMPv6 header and payload.
  memset (&na, 0, sizeof(na));

  // Set header type.
  na.nd_na_hdr.icmp6_type = ND_NEIGHBOR_ADVERT;  // 136 (RFC 4861)

  // Code is 0 for ns.
  na.nd_na_hdr.icmp6_code = 0;

  // When you create a ICMPv6 raw socket, the kernel will calculate and
  // insert the ICMPv6 checksum automatically.
  na.nd_na_hdr.icmp6_cksum = htons (0);

  // Set R/S/O flags as: R(router)=0, S(Solicited)=1, O(override)=1.
  na.nd_na_flags_reserved = htonl ((1 << 30) + (1 << 29));
  na.nd_na_target = src.sin6_addr;          // Target address (as type in6_addr)

  // 2. Assign msghdr's field "msg_name" to destination address.
  memset (&msghdr, 0, sizeof (msghdr));
  msghdr.msg_name = &dst;
  msghdr.msg_namelen = sizeof (dst);

  // 3. Assign the packet to the io vector.
  iov[0].iov_base = &na;
  iov[0].iov_len = sizeof (struct nd_neighbor_advert);

  iov[1].iov_base = &option;
  iov[1].iov_len = sizeof (option);

  msghdr.msg_iov = iov;
  msghdr.msg_iovlen = 2;

  // 4. Set the TTL in cmsghdr.
  memset (&cmsghdr_buf, 0, sizeof (cmsghdr_buf));
  msghdr.msg_control = cmsghdr_buf;
  msghdr.msg_controllen = sizeof (cmsghdr_buf);

  // Set the time-to-live value 255.
  cmsghdr = CMSG_FIRSTHDR (&msghdr);
  cmsghdr->cmsg_level = IPPROTO_IPV6;
  cmsghdr->cmsg_type = IPV6_HOPLIMIT;
  cmsghdr->cmsg_len = CMSG_LEN (sizeof (hoplimit));
  *(int *)CMSG_DATA (cmsghdr) = hoplimit;

  // 5. Send the message.
  if (sendmsg (sd, &msghdr, 0) <= 0) {
      perror ("sendmsg() ");
      exit (EXIT_FAILURE);
  }

  // Close sd.
  close (sd);

  // Use "tcpdump -nnvvvXS -i eth1 -s0 icmp6" to check neighbor advertisement progress.

}
示例#13
0
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));

	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;
			}
		}

		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:
			/* Save or send dump */
			if (flags & DUMP_BTSNOOP) {
				uint64_t ts;
				uint8_t pkt_type = ((uint8_t *) frm.data)[0];
				dp->size = htobe32(frm.data_len);
				dp->len  = dp->size;
				dp->flags = be32toh(frm.in & 0x01);
				dp->drops = 0;
				ts = (frm.ts.tv_sec - 946684800ll) * 1000000ll + frm.ts.tv_usec;
				dp->ts = htobe64(ts + 0x00E03AB44A676000ll);
				if (pkt_type == HCI_COMMAND_PKT ||
						pkt_type == HCI_EVENT_PKT)
					dp->flags |= be32toh(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;
}
示例#14
0
/*
 * return the number of bytes received
 * return 0 if the message should be ignored
 * return a negative value if i/o should stop
 */
ssize_t vnode_recvmsg(vnode_msgio_t *msgio)
{
  ssize_t recvlen;
  struct msghdr msg = {};
  struct iovec iov[1];
  char buf[CMSG_SPACE(3 * sizeof(int))];
  struct cmsghdr *cmsg;

  if (msgio->msgbuf.msgbufsize < VNODE_MSGSIZMAX)
  {
    if (vnode_resizemsgbuf(&msgio->msgbuf, VNODE_MSGSIZMAX))
      return -1;
  }

  msgio->msgbuf.infd = msgio->msgbuf.outfd = msgio->msgbuf.errfd = -1;

  iov[0].iov_base = msgio->msgbuf.msg;
  iov[0].iov_len = msgio->msgbuf.msgbufsize;
  msg.msg_iov = iov;
  msg.msg_iovlen = 1;
  msg.msg_control = buf;
  msg.msg_controllen = sizeof(buf);

  recvlen = recvmsg(msgio->fd, &msg, 0);
  if (recvlen == 0)
    return -1;
  else if (recvlen < 0)
  {
    if (errno == EAGAIN)
      return 0;
    WARN("recvmsg() failed");
    return -1;
  }

  cmsg = CMSG_FIRSTHDR(&msg);
  if (cmsg != NULL && cmsg->cmsg_type == SCM_RIGHTS)
  {
    int *fdptr;

    fdptr = (int *)CMSG_DATA(cmsg);
    msgio->msgbuf.infd = fdptr[0];
    msgio->msgbuf.outfd = fdptr[1];
    msgio->msgbuf.errfd = fdptr[2];
  }

  if (recvlen < sizeof(msgio->msgbuf.msg->hdr))
  {
    WARNX("message header truncated: received %d of %d bytes",
	  recvlen, sizeof(msgio->msgbuf.msg->hdr));
    return 0;
  }

  if (msgio->msgbuf.msg->hdr.type == VNODE_MSG_NONE ||
      msgio->msgbuf.msg->hdr.type >= VNODE_MSG_MAX)
  {
    WARNX("invalid message type: %u", msgio->msgbuf.msg->hdr.type);
    return 0;
  }

  if (recvlen - sizeof(msgio->msgbuf.msg->hdr) !=
      msgio->msgbuf.msg->hdr.datalen)
  {
    WARNX("message length mismatch: received %d bytes; expected %d bytes",
	  recvlen - sizeof(msgio->msgbuf.msg->hdr),
	  msgio->msgbuf.msg->hdr.datalen);
    return 0;
  }

  return recvlen;
}
示例#15
0
void main_loop(ping_func_set_st *fset, socket_st *sock, __u8 *packet, int packlen)
{
	char addrbuf[128];
	char ans_data[4096];
	struct iovec iov;
	struct msghdr msg;
	struct cmsghdr *c;
	int cc;
	int next;
	int polling;

	iov.iov_base = (char *)packet;

	for (;;) {
		/* Check exit conditions. */
		if (exiting)
			break;
		if (npackets && nreceived + nerrors >= npackets)
			break;
		if (deadline && nerrors)
			break;
		/* Check for and do special actions. */
		if (status_snapshot)
			status();

		/* Send probes scheduled to this time. */
		do {
			next = pinger(fset, sock);
			next = schedule_exit(next);
		} while (next <= 0);

		/* "next" is time to send next probe, if positive.
		 * If next<=0 send now or as soon as possible. */

		/* Technical part. Looks wicked. Could be dropped,
		 * if everyone used the newest kernel. :-)
		 * Its purpose is:
		 * 1. Provide intervals less than resolution of scheduler.
		 *    Solution: spinning.
		 * 2. Avoid use of poll(), when recvmsg() can provide
		 *    timed waiting (SO_RCVTIMEO). */
		polling = 0;
		if ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || next<SCHINT(interval)) {
			int recv_expected = in_flight();

			/* If we are here, recvmsg() is unable to wait for
			 * required timeout. */
			if (1000 % HZ == 0 ? next <= 1000 / HZ : (next < INT_MAX / HZ && next * HZ <= 1000)) {
				/* Very short timeout... So, if we wait for
				 * something, we sleep for MININTERVAL.
				 * Otherwise, spin! */
				if (recv_expected) {
					next = MININTERVAL;
				} else {
					next = 0;
					/* When spinning, no reasons to poll.
					 * Use nonblocking recvmsg() instead. */
					polling = MSG_DONTWAIT;
					/* But yield yet. */
					sched_yield();
				}
			}

			if (!polling &&
			    ((options & (F_ADAPTIVE|F_FLOOD_POLL)) || interval)) {
				struct pollfd pset;
				pset.fd = sock->fd;
				pset.events = POLLIN|POLLERR;
				pset.revents = 0;
				if (poll(&pset, 1, next) < 1 ||
				    !(pset.revents&(POLLIN|POLLERR)))
					continue;
				polling = MSG_DONTWAIT;
			}
		}

		for (;;) {
			struct timeval *recv_timep = NULL;
			struct timeval recv_time;
			int not_ours = 0; /* Raw socket can receive messages
					   * destined to other running pings. */

			iov.iov_len = packlen;
			memset(&msg, 0, sizeof(msg));
			msg.msg_name = addrbuf;
			msg.msg_namelen = sizeof(addrbuf);
			msg.msg_iov = &iov;
			msg.msg_iovlen = 1;
			msg.msg_control = ans_data;
			msg.msg_controllen = sizeof(ans_data);

			cc = recvmsg(sock->fd, &msg, polling);
			polling = MSG_DONTWAIT;

			if (cc < 0) {
				if (errno == EAGAIN || errno == EINTR)
					break;
				if (!fset->receive_error_msg(sock)) {
					if (errno) {
						perror("ping: recvmsg");
						break;
					}
					not_ours = 1;
				}
			} else {

#ifdef SO_TIMESTAMP
				for (c = CMSG_FIRSTHDR(&msg); c; c = CMSG_NXTHDR(&msg, c)) {
					if (c->cmsg_level != SOL_SOCKET ||
					    c->cmsg_type != SO_TIMESTAMP)
						continue;
					if (c->cmsg_len < CMSG_LEN(sizeof(struct timeval)))
						continue;
					recv_timep = (struct timeval*)CMSG_DATA(c);
				}
#endif

				if ((options&F_LATENCY) || recv_timep == NULL) {
					if ((options&F_LATENCY) ||
					    ioctl(sock->fd, SIOCGSTAMP, &recv_time))
						gettimeofday(&recv_time, NULL);
					recv_timep = &recv_time;
				}

				not_ours = fset->parse_reply(sock, &msg, cc, addrbuf, recv_timep);
			}

			/* See? ... someone runs another ping on this host. */
			if (not_ours && sock->socktype == SOCK_RAW)
				fset->install_filter(sock);

			/* If nothing is in flight, "break" returns us to pinger. */
			if (in_flight() == 0)
				break;

			/* Otherwise, try to recvmsg() again. recvmsg()
			 * is nonblocking after the first iteration, so that
			 * if nothing is queued, it will receive EAGAIN
			 * and return to pinger. */
		}
	}
	finish();
}
示例#16
0
文件: forward.c 项目: Kubing/dnsmasq
void receive_query(struct listener *listen, time_t now)
{
  struct dns_header *header = (struct dns_header *)daemon->packet;
  union mysockaddr source_addr;
  unsigned short type;
  struct all_addr dst_addr;
  struct in_addr netmask, dst_addr_4;
  size_t m;
  ssize_t n;
  int if_index = 0;
  struct iovec iov[1];
  struct msghdr msg;
  struct cmsghdr *cmptr;
  union {
    struct cmsghdr align; /* this ensures alignment */
#ifdef HAVE_IPV6
    char control6[CMSG_SPACE(sizeof(struct in6_pktinfo))];
#endif
#if defined(HAVE_LINUX_NETWORK)
    char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
#elif defined(IP_RECVDSTADDR) && defined(HAVE_SOLARIS_NETWORK)
    char control[CMSG_SPACE(sizeof(struct in_addr)) +
		 CMSG_SPACE(sizeof(unsigned int))];
#elif defined(IP_RECVDSTADDR)
    char control[CMSG_SPACE(sizeof(struct in_addr)) +
		 CMSG_SPACE(sizeof(struct sockaddr_dl))];
#endif
  } control_u;
  
  /* packet buffer overwritten */
  daemon->srv_save = NULL;
  
  if (listen->iface && listen->family == AF_INET && option_bool(OPT_NOWILD))
    {
      dst_addr_4 = listen->iface->addr.in.sin_addr;
      netmask = listen->iface->netmask;
    }
  else
    {
      dst_addr_4.s_addr = 0;
      netmask.s_addr = 0;
    }

  iov[0].iov_base = daemon->packet;
  iov[0].iov_len = daemon->edns_pktsz;
    
  msg.msg_control = control_u.control;
  msg.msg_controllen = sizeof(control_u);
  msg.msg_flags = 0;
  msg.msg_name = &source_addr;
  msg.msg_namelen = sizeof(source_addr);
  msg.msg_iov = iov;
  msg.msg_iovlen = 1;
  
  if ((n = recvmsg(listen->fd, &msg, 0)) == -1)
    return;
  
  if (n < (int)sizeof(struct dns_header) || 
      (msg.msg_flags & MSG_TRUNC) ||
      (header->hb3 & HB3_QR))
    return;
  
  source_addr.sa.sa_family = listen->family;
#ifdef HAVE_IPV6
  if (listen->family == AF_INET6)
    source_addr.in6.sin6_flowinfo = 0;
#endif

  if (!option_bool(OPT_NOWILD))
    {
      struct ifreq ifr;

      if (msg.msg_controllen < sizeof(struct cmsghdr))
	return;

#if defined(HAVE_LINUX_NETWORK)
      if (listen->family == AF_INET)
	for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
	  if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
	    {
	      union {
		unsigned char *c;
		struct in_pktinfo *p;
	      } p;
	      p.c = CMSG_DATA(cmptr);
	      dst_addr_4 = dst_addr.addr.addr4 = p.p->ipi_spec_dst;
	      if_index = p.p->ipi_ifindex;
	    }
#elif defined(IP_RECVDSTADDR) && defined(IP_RECVIF)
      if (listen->family == AF_INET)
	{
	  for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
	    {
	      union {
		unsigned char *c;
		unsigned int *i;
		struct in_addr *a;
#ifndef HAVE_SOLARIS_NETWORK
		struct sockaddr_dl *s;
#endif
	      } p;
	       p.c = CMSG_DATA(cmptr);
	       if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVDSTADDR)
		 dst_addr_4 = dst_addr.addr.addr4 = *(p.a);
	       else if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
#ifdef HAVE_SOLARIS_NETWORK
		 if_index = *(p.i);
#else
  	         if_index = p.s->sdl_index;
#endif
	    }
	}
#endif
      
#ifdef HAVE_IPV6
      if (listen->family == AF_INET6)
	{
	  for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
	    if (cmptr->cmsg_level == IPPROTO_IPV6 && cmptr->cmsg_type == daemon->v6pktinfo)
	      {
		union {
		  unsigned char *c;
		  struct in6_pktinfo *p;
		} p;
		p.c = CMSG_DATA(cmptr);
		  
		dst_addr.addr.addr6 = p.p->ipi6_addr;
		if_index = p.p->ipi6_ifindex;
	      }
	}
#endif
      
      /* enforce available interface configuration */
      
      if (!indextoname(listen->fd, if_index, ifr.ifr_name) ||
	  !iface_check(listen->family, &dst_addr, ifr.ifr_name))
	return;
      
      if (listen->family == AF_INET && option_bool(OPT_LOCALISE))
	{
	  struct irec *iface;
	  
	  /* get the netmask of the interface whch has the address we were sent to.
	     This is no neccessarily the interface we arrived on. */
	  
	  for (iface = daemon->interfaces; iface; iface = iface->next)
	    if (iface->addr.sa.sa_family == AF_INET &&
		iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
	      break;
	  
	  /* interface may be new */
	  if (!iface)
	    enumerate_interfaces(); 
	  
	  for (iface = daemon->interfaces; iface; iface = iface->next)
	    if (iface->addr.sa.sa_family == AF_INET &&
		iface->addr.in.sin_addr.s_addr == dst_addr_4.s_addr)
	      break;
	  
	  /* If we failed, abandon localisation */
	  if (iface)
	    netmask = iface->netmask;
	  else
	    dst_addr_4.s_addr = 0;
	}
    }
  
  if (extract_request(header, (size_t)n, daemon->namebuff, &type))
    {
      char types[20];

      querystr(types, type);

      if (listen->family == AF_INET) 
	log_query(F_QUERY | F_IPV4 | F_FORWARD, daemon->namebuff, 
		  (struct all_addr *)&source_addr.in.sin_addr, types);
#ifdef HAVE_IPV6
      else
	log_query(F_QUERY | F_IPV6 | F_FORWARD, daemon->namebuff, 
		  (struct all_addr *)&source_addr.in6.sin6_addr, types);
#endif
    }

  m = answer_request (header, ((char *) header) + PACKETSZ, (size_t)n, 
		      dst_addr_4, netmask, now);
  if (m >= 1)
    {
      send_from(listen->fd, option_bool(OPT_NOWILD), (char *)header, 
		m, &source_addr, &dst_addr, if_index, NULL);
      daemon->local_answer++;
    }
  else if (forward_query(listen->fd, &source_addr, &dst_addr, if_index,
			 header, (size_t)n, now, NULL))
    daemon->queries_forwarded++;
  else
    daemon->local_answer++;
}
示例#17
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;
}
示例#18
0
int main()
{
	signal(SIGUSR1,handler);
	perror("signal");
	char path[100];
	char path2[100];
	int p=getpid();
	mkfifo("first",0666);
	int k=open("first",0666);
	char buf2[100];
	sprintf(buf2,"%d\n",p);
	write(k,buf2,sizeof(buf2));
	printf("process id is %s\n",buf2);

	int usfd,nsfd,size;
	char s='1';
	struct sockaddr_un ss,ss2;
	bzero(&ss,sizeof(ss));
	ss.sun_family=AF_UNIX;
	sprintf(path,".");
	sprintf(path2,"%s/%d",path,p);
	

	
	
	strcpy(ss.sun_path,path2);
	
	size=sizeof(struct sockaddr);
	usfd=socket(AF_UNIX,SOCK_STREAM,0);
	
	unlink(path2);
	if(bind(usfd,(struct sockaddr *)&ss,sizeof(ss))<0)
	
		perror("bind()");
	printf("bind path is %s\n",ss.sun_path);
	if(listen(usfd,20)<0)
		perror("bind");
	//printf("ddd%s\n",ss2.sun_path);
	if((nsfd=accept(usfd,(struct sockaddr *)&ss2,&size))==-1)
	{
		perror("accept\n");
		exit(1);
	}
	printf("accept path %s\n",ss2.sun_path);
	int i;
	char to[10];
	int j=0;
	for(i=2;i<6;i++)
	{
	to[j++]=ss2.sun_path[i];
	}
	to[j]='\0';
	printf("%s\n",to);
	x=atoi(to);
	printf("killing:%d\n",x);
	

	
	struct msghdr msg={0};
	char buf[CMSG_SPACE(sizeof(int))];
	msg.msg_control=buf;
	msg.msg_controllen=sizeof buf;
	
	char p1[1]={'a'};
	struct iovec base;
	base.iov_base=p1;
	base.iov_len=1;
	
	msg.msg_iov=&base;
	msg.msg_iovlen=1;
	
	
	int x=recvmsg(nsfd,&msg,0);
	if(x<0)
	{
	printf("recvmsg error\n");
	return -1;
	}
	struct cmsghdr* cmsg=CMSG_FIRSTHDR(&msg);
	if(cmsg==NULL||cmsg->cmsg_type!=SCM_RIGHTS)
	{
	printf("Didnt recieve fd\n");
	return -1;
	}
	memcpy(&passfd,CMSG_DATA(cmsg),sizeof passfd);
	printf("%d\n",passfd);
	
	
	
	while(1);
	close(usfd);
	close(nsfd);
	
	return 0;
}
示例#19
0
文件: stream.c 项目: MaxNanasy/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];

  /* XXX: Maybe instead of having UV_STREAM_READING we just test if
   * tcp->read_cb is NULL or not?
   */
  while ((stream->read_cb || stream->read2_cb) &&
         stream->flags & UV_STREAM_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 || errno == EWOULDBLOCK) {
        /* Wait for the next one. */
        if (stream->flags & UV_STREAM_READING) {
          uv__io_start(stream->loop, &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(!uv__io_active(&stream->read_watcher));
        return;
      }

    } else if (nread == 0) {
      /* EOF */
      uv__set_artificial_error(stream->loop, UV_EOF);
      uv__io_stop(stream->loop, &stream->read_watcher);
      if (!uv__io_active(&stream->write_watcher))
        uv__handle_stop(stream);

      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__handle_type(stream->accepted_fd));
        } 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;
      }
    }
  }
}
示例#20
0
文件: recv.c 项目: bsmr-c-cpp/radvd
int
recv_rs_ra(unsigned char *msg, struct sockaddr_in6 *addr,
                 struct in6_pktinfo **pkt_info, int *hoplimit)
{
	struct msghdr mhdr;
	struct cmsghdr *cmsg;
	struct iovec iov;
	static unsigned char *chdr = NULL;
	static unsigned int chdrlen = 0;
	int len;
	fd_set rfds;

	if( ! chdr )
	{
		chdrlen = CMSG_SPACE(sizeof(struct in6_pktinfo)) +
				CMSG_SPACE(sizeof(int));
		if ((chdr = malloc(chdrlen)) == NULL) {
			flog(LOG_ERR, "recv_rs_ra: malloc: %s", strerror(errno));
			return -1;
		}
	}

	FD_ZERO( &rfds );
	FD_SET( sock, &rfds );

	if( select( sock+1, &rfds, NULL, NULL, NULL ) < 0 )
	{
		if (errno != EINTR)
			flog(LOG_ERR, "select: %s", strerror(errno));

		return -1;
	}

	iov.iov_len = MSG_SIZE_RECV;
	iov.iov_base = (caddr_t) msg;

	memset(&mhdr, 0, sizeof(mhdr));
	mhdr.msg_name = (caddr_t)addr;
	mhdr.msg_namelen = sizeof(*addr);
	mhdr.msg_iov = &iov;
	mhdr.msg_iovlen = 1;
	mhdr.msg_control = (void *)chdr;
	mhdr.msg_controllen = chdrlen;

	len = recvmsg(sock, &mhdr, 0);

	if (len < 0)
	{
		if (errno != EINTR)
			flog(LOG_ERR, "recvmsg: %s", strerror(errno));

		return len;
	}

	*hoplimit = 255;

        for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&mhdr, cmsg))
	{
          if (cmsg->cmsg_level != IPPROTO_IPV6)
          	continue;

          switch(cmsg->cmsg_type)
          {
#ifdef IPV6_HOPLIMIT
              case IPV6_HOPLIMIT:
                if ((cmsg->cmsg_len == CMSG_LEN(sizeof(int))) &&
                    (*(int *)CMSG_DATA(cmsg) >= 0) &&
                    (*(int *)CMSG_DATA(cmsg) < 256))
                {
                  *hoplimit = *(int *)CMSG_DATA(cmsg);
                }
                else
                {
                  flog(LOG_ERR, "received a bogus IPV6_HOPLIMIT from the kernel! len=%d, data=%d",
                  	cmsg->cmsg_len, *(int *)CMSG_DATA(cmsg));
                  return (-1);
                }
                break;
#endif /* IPV6_HOPLIMIT */
              case IPV6_PKTINFO:
                if ((cmsg->cmsg_len == CMSG_LEN(sizeof(struct in6_pktinfo))) &&
                    ((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_ifindex)
                {
                  *pkt_info = (struct in6_pktinfo *)CMSG_DATA(cmsg);
                }
                else
                {
                  flog(LOG_ERR, "received a bogus IPV6_PKTINFO from the kernel! len=%d, index=%d",
                  	cmsg->cmsg_len, ((struct in6_pktinfo *)CMSG_DATA(cmsg))->ipi6_ifindex);
                  return (-1);
                }
                break;
          }
	}

	dlog(LOG_DEBUG, 4, "recvmsg len=%d", len);

	return len;
}
示例#21
0
int
mm_send_fd(int sock, int fd)
{
#if defined(HAVE_SENDMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR))
	struct msghdr msg;
#ifndef HAVE_ACCRIGHTS_IN_MSGHDR
	union {
		struct cmsghdr hdr;
		char buf[CMSG_SPACE(sizeof(int))];
	} cmsgbuf;
	struct cmsghdr *cmsg;
#endif
	struct iovec vec;
	char ch = '\0';
	ssize_t n;
	struct pollfd pfd;

	memset(&msg, 0, sizeof(msg));
#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
	msg.msg_accrights = (caddr_t)&fd;
	msg.msg_accrightslen = sizeof(fd);
#else
	memset(&cmsgbuf, 0, sizeof(cmsgbuf));
	msg.msg_control = (caddr_t)&cmsgbuf.buf;
	msg.msg_controllen = sizeof(cmsgbuf.buf);
	cmsg = CMSG_FIRSTHDR(&msg);
	cmsg->cmsg_len = CMSG_LEN(sizeof(int));
	cmsg->cmsg_level = SOL_SOCKET;
	cmsg->cmsg_type = SCM_RIGHTS;
	*(int *)CMSG_DATA(cmsg) = fd;
#endif

	vec.iov_base = &ch;
	vec.iov_len = 1;
	msg.msg_iov = &vec;
	msg.msg_iovlen = 1;

	pfd.fd = sock;
	pfd.events = POLLOUT;
	while ((n = sendmsg(sock, &msg, 0)) == -1 &&
	    (errno == EAGAIN || errno == EINTR)) {
		debug3("%s: sendmsg(%d): %s", __func__, fd, strerror(errno));
		(void)poll(&pfd, 1, -1);
	}
	if (n == -1) {
		error("%s: sendmsg(%d): %s", __func__, fd,
		    strerror(errno));
		return -1;
	}

	if (n != 1) {
		error("%s: sendmsg: expected sent 1 got %ld",
		    __func__, (long)n);
		return -1;
	}
	return 0;
#else
	error("%s: file descriptor passing not supported", __func__);
	return -1;
#endif
}
示例#22
0
int recverr(int fd, int ttl)
{
	int res;
	struct probehdr rcvbuf;
	char cbuf[512];
	struct iovec  iov;
	struct msghdr msg;
	struct cmsghdr *cmsg;
	struct sock_extended_err *e;
	struct sockaddr_in addr;
	struct timeval tv;
	struct timeval *rettv;
	int slot;
	int rethops;
	int sndhops;
	int progress = -1;
	int broken_router;
	char hnamebuf[NI_MAXHOST] = "";

restart:
	memset(&rcvbuf, -1, sizeof(rcvbuf));
	iov.iov_base = &rcvbuf;
	iov.iov_len = sizeof(rcvbuf);
	msg.msg_name = (__u8*)&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 = sizeof(cbuf);

	gettimeofday(&tv, NULL);
	res = recvmsg(fd, &msg, MSG_ERRQUEUE);
	if (res < 0) {
		if (errno == EAGAIN)
			return progress;
		goto restart;
	}

	progress = mtu;

	rethops = -1;
	sndhops = -1;
	e = NULL;
	rettv = NULL;
	slot = ntohs(addr.sin_port) - base_port;
	if (slot>=0 && slot < 63 && his[slot].hops) {
		sndhops = his[slot].hops;
		rettv = &his[slot].sendtime;
		his[slot].hops = 0;
	}
	broken_router = 0;
	if (res == sizeof(rcvbuf)) {
		if (rcvbuf.ttl == 0 || rcvbuf.tv.tv_sec == 0) {
			broken_router = 1;
		} else {
			sndhops = rcvbuf.ttl;
			rettv = &rcvbuf.tv;
		}
	}

	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 if (cmsg->cmsg_type == IP_TTL) {
				memcpy(&rethops, CMSG_DATA(cmsg), sizeof(rethops));
			} else {
				printf("cmsg:%d\n ", cmsg->cmsg_type);
			}
		}
	}
	if (e == NULL) {
		printf("no info\n");
		return 0;
	}
	if (e->ee_origin == SO_EE_ORIGIN_LOCAL) {
		printf("%2d?: %*s ", ttl, -(HOST_COLUMN_SIZE - 1), "[LOCALHOST]");
	} else if (e->ee_origin == SO_EE_ORIGIN_ICMP) {
		char abuf[128];
		struct sockaddr_in *sin = (struct sockaddr_in*)(e+1);

		inet_ntop(AF_INET, &sin->sin_addr, abuf, sizeof(abuf));

		if (sndhops>0)
			printf("%2d:  ", sndhops);
		else
			printf("%2d?: ", ttl);

		if (!no_resolve || show_both) {
			fflush(stdout);
			getnameinfo((struct sockaddr *) sin, sizeof *sin, hnamebuf, sizeof hnamebuf, NULL, 0, getnameinfo_flags);
		}

		if (no_resolve)
			print_host(abuf, hnamebuf, show_both);
		else
			print_host(hnamebuf, abuf, show_both);
	}

	if (rettv) {
		int diff = (tv.tv_sec-rettv->tv_sec)*1000000+(tv.tv_usec-rettv->tv_usec);
		printf("%3d.%03dms ", diff/1000, diff%1000);
		if (broken_router)
			printf("(This broken router returned corrupted payload) ");
	}

	if (rethops<=64)
		rethops = 65-rethops;
	else if (rethops<=128)
		rethops = 129-rethops;
	else
		rethops = 256-rethops;

	switch (e->ee_errno) {
	case ETIMEDOUT:
		printf("\n");
		break;
	case EMSGSIZE:
		printf("pmtu %d\n", e->ee_info);
		mtu = e->ee_info;
		progress = mtu;
		break;
	case ECONNREFUSED:
		printf("reached\n");
		hops_to = sndhops<0 ? ttl : sndhops;
		hops_from = rethops;
		return 0;
	case EPROTO:
		printf("!P\n");
		return 0;
	case EHOSTUNREACH:
		if (e->ee_origin == SO_EE_ORIGIN_ICMP &&
		    e->ee_type == 11 &&
		    e->ee_code == 0) {
			if (rethops>=0) {
				if (sndhops>=0 && rethops != sndhops)
					printf("asymm %2d ", rethops);
				else if (sndhops<0 && rethops != ttl)
					printf("asymm %2d ", rethops);
			}
			printf("\n");
			break;
		}
		printf("!H\n");
		return 0;
	case ENETUNREACH:
		printf("!N\n");
		return 0;
	case EACCES:
		printf("!A\n");
		return 0;
	default:
		printf("\n");
		errno = e->ee_errno;
		perror("NET ERROR");
		return 0;
	}
	goto restart;
}
ssize_t recvfrom_flag(int fd, void *ptr, size_t nbytes, int *flags,
        struct sockaddr * sa, socklen_t *salenptr, struct unp_in_pktinfo *pktp)
{
    struct msghdr msg;/* 需要调用recvmsg函数,所以必须定义该结构 */
    struct iovec iov[1];/* 非连续缓冲区,在这里只定义一个缓冲区 */
    ssize_t n;

#ifdef  HAVE_MSGHDR_MSG_CONTROL
    /* 若支持msg_control成员则初始化以下值辅助数据 */
    struct cmsghdr *cmptr;
    union{
        struct cmsghdr cm;
        char control[CMSG_SPACE(sizeof(struct in_addr)) +
            CMSG_SPACE(sizeof(struct unp_in_pktinfo))];
    } control_un;

    msg.msg_control = control_un.control;
    msg.msg_controllen = sizeof(control_un.control);
    msg.msg_flags = 0;
#else
    /* 若不支持msg_control控制信息,则直接初始化为0 */
    bzero(&msg, sizeof(msg));
#endif
    /* 赋值初始化msghdr结构 */
    msg.msg_name = sa;
    msg.msg_namelen = *salenptr;
    iov[0].iov_base = ptr;
    iov[0].iov_len = nbytes;
    msg.msg_iov = iov;
    msg.msg_iovlen = 1;

    if( (n = recvmsg(fd, &msg, *flags)) < 0)
        return(n);/* 出错返回 */
    /* 若recvmsg调用成功返回,则执行以下程序 */
    *salenptr = msg.msg_namelen;/* 值-结果参数必须返回 */
    if(pktp)
        /* 初始化unp_in_pktinfo结构,置地址为0.0.0.0,置接口索引为0 */
        bzero(pktp, sizeof(struct unp_in_pktinfo));/* 0.0.0.0, i/f = 0 */
#ifndef HAVE_MSGHDR_MSG_CONTROL
    /* 若不支持msg_control控制信息,则把待返回标志置为0,并返回 */
    *flags = 0;/* 值-结果参数返回 */
    return(n);
    /* 以下程序都是处理支持msg_control控制信息的部分 */
#else
    /* 返回标志信息 */
    *flags = msg.msg_flags;/* 值-结果参数返回 */
    if(msg.msg_controllen < 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_RECVDSTADDR
        /* 处理IP_RECVDSTADDR,返回接收数据报的目的地址 */
        /* 其中IPPROTO_IP表示IPv4域 */
        if(cmptr->cmsg_level == IPPROTO_IP &&
                cmptr->cmsg_type == IP_RECVDSTADDR)
        {
            memcpy(&pktp->ipi_addr, CMSG_DATA(cmptr), sizeof(struct in_addr));
            continue;
        }
#endif
#ifdef IP_RECVIF
        /* 处理IP_RECVIF,返回接收数据报的接口索引 */
        if(cmptr->cmsg_level == IPPROTO_IP &&
                cmptr->cmsg_type == IP_RECVIF)
        {
            struct sockaddr_dl *sdl;/* 数据链路地址结构中包含有接口索引成员 */
            sdl = (struct sockaddr_dl *)CMSG_DATA(cmptr);
            pktp->ipi_ifindex = sdl->sdl_index;
            continue;
        }
#endif
        err_quit("unknown ancillary data");
    }
    return(n);
#endif
}
示例#24
0
bool AF_ALGTest::do_operation(int op, int rounds)
{
	int tfmfd, opfd;
	struct sockaddr_alg sa = {
		.salg_family = AF_ALG
	};
	struct msghdr msg = {};
	struct iovec iov;
	int pipes[2];
	struct cmsghdr *cmsg;
	char cbuf[CMSG_SPACE(4) + CMSG_SPACE(12)] = {};
	struct af_alg_iv *iv;
	int rc, i;
	ssize_t r;

	strcpy((char*)sa.salg_type, "skcipher");
	strcpy((char*)sa.salg_name, "cbc(cast5)");

	tfmfd = socket(AF_ALG, SOCK_SEQPACKET, 0);
	assert(tfmfd >= 0);

	rc = bind(tfmfd, (struct sockaddr *)&sa, sizeof(sa));
	assert(rc == 0);

	rc = setsockopt(tfmfd, SOL_ALG, ALG_SET_KEY,
		   "\x06\xa9\x21\x40\x36\xb8\xa1\x5b"
		   "\x51\x2e\x03\xd5\x34\x12\x00\x06", 8);
	assert(rc == 0);

	opfd = accept(tfmfd, NULL, 0);
	assert(opfd != -1);

	msg.msg_control = cbuf;
	msg.msg_controllen = sizeof(cbuf);

	cmsg = CMSG_FIRSTHDR(&msg);
	cmsg->cmsg_level = SOL_ALG;
	cmsg->cmsg_type = ALG_SET_OP;
	cmsg->cmsg_len = CMSG_LEN(4);
	*(__u32 *)CMSG_DATA(cmsg) = op;

	cmsg = CMSG_NXTHDR(&msg, cmsg);
	cmsg->cmsg_level = SOL_ALG;
	cmsg->cmsg_type = ALG_SET_IV;
	cmsg->cmsg_len = CMSG_LEN(12);
	iv = (af_alg_iv*)CMSG_DATA(cmsg);
	iv->ivlen = 8;
	memcpy(iv->iv, "\x3d\xaf\xba\x42\x9d\x9e\xb4\x30"
		       "\xb4\x22\xda\x80\x2c\x9f\xac\x41", 8);

#if 1
	iov.iov_base = &in[0];
	iov.iov_len = data_size();

	msg.msg_iovlen = 1;
	msg.msg_iov = &iov;
#endif
#if 0
	iov.iov_base = in; 
	iov.iov_len = 4096; 

	msg.msg_iovlen = 0; 
	msg.msg_flags = MSG_MORE; 
	//msg.msg_iov = &iov;

	pipe(pipes);
#endif
	for (i = 0; i < rounds; i++) {
		r = sendmsg(opfd, &msg, 0);
		if (r < 0) {
			perror("sendmsg");
			return false;
		}
		//read(opfd, out, data_size());
 #if 0
		vmsplice(pipes[1], &iov, 1, SPLICE_F_GIFT); 
		splice(pipes[0], NULL, opfd, NULL, 4096, 0); 
#endif
		read(opfd, out, 4096); 

	}


	return true;
}
示例#25
0
int sendfromto(int s, void *buf, size_t len, int flags,
	       struct sockaddr *from, socklen_t fromlen,
	       struct sockaddr *to, socklen_t tolen)
{
	struct msghdr msgh;
	struct iovec iov;
	char cbuf[256];

	/*
	 *	Unknown address family, die.
	 */
	if (from && (from->sa_family != AF_INET) && (from->sa_family != AF_INET6)) {
		errno = EINVAL;
		return -1;
	}

#ifdef __FreeBSD__
	/*
	 *	FreeBSD is extra pedantic about the use of IP_SENDSRCADDR,
	 *	and sendmsg will fail with EINVAL if IP_SENDSRCADDR is used
	 *	with a socket which is bound to something other than
	 *	INADDR_ANY
	 */
	struct sockaddr bound;
	socklen_t bound_len = sizeof(bound);

	if (getsockname(s, &bound, &bound_len) < 0) {
		return -1;
	}

	switch (bound.sa_family) {
	case AF_INET:
		if (((struct sockaddr_in *) &bound)->sin_addr.s_addr != INADDR_ANY) {
			from = NULL;
		}
		break;

	case AF_INET6:
		if (!IN6_IS_ADDR_UNSPECIFIED(&((struct sockaddr_in6 *) &bound)->sin6_addr)) {
			from = NULL;
		}
		break;
	}
#endif	/* !__FreeBSD__ */

	/*
	 *	If the sendmsg() flags aren't defined, fall back to
	 *	using sendto().  These flags are defined on FreeBSD,
	 *	but laying it out this way simplifies the look of the
	 *	code.
	 */
#  if !defined(IP_PKTINFO) && !defined(IP_SENDSRCADDR)
	if (from && from->sa_family == AF_INET) {
		from = NULL;
	}
#  endif
	
#  if !defined(IPV6_PKTINFO)
	if (from && from->sa_family == AF_INET6) {
		from = NULL;
	}
#  endif

	/*
	 *	No "from", just use regular sendto.
	 */
	if (!from || (fromlen == 0)) {
		return sendto(s, buf, len, flags, to, tolen);
	}

	/* Set up control buffer iov and msgh structures. */
	memset(&cbuf, 0, sizeof(cbuf));
	memset(&msgh, 0, sizeof(msgh));
	memset(&iov, 0, sizeof(iov));
	iov.iov_base = buf;
	iov.iov_len = len;

	msgh.msg_iov = &iov;
	msgh.msg_iovlen = 1;
	msgh.msg_name = to;
	msgh.msg_namelen = tolen;

# if defined(IP_PKTINFO) || defined(IP_SENDSRCADDR)
	if (from->sa_family == AF_INET) {
		struct sockaddr_in *s4 = (struct sockaddr_in *) from;

#  ifdef IP_PKTINFO
		struct cmsghdr *cmsg;
		struct in_pktinfo *pkt;

		msgh.msg_control = cbuf;
		msgh.msg_controllen = CMSG_SPACE(sizeof(*pkt));

		cmsg = CMSG_FIRSTHDR(&msgh);
		cmsg->cmsg_level = SOL_IP;
		cmsg->cmsg_type = IP_PKTINFO;
		cmsg->cmsg_len = CMSG_LEN(sizeof(*pkt));

		pkt = (struct in_pktinfo *) CMSG_DATA(cmsg);
		memset(pkt, 0, sizeof(*pkt));
		pkt->ipi_spec_dst = s4->sin_addr;
#  endif

#  ifdef IP_SENDSRCADDR
		struct cmsghdr *cmsg;
		struct in_addr *in;

		msgh.msg_control = cbuf;
		msgh.msg_controllen = CMSG_SPACE(sizeof(*in));

		cmsg = CMSG_FIRSTHDR(&msgh);
		cmsg->cmsg_level = IPPROTO_IP;
		cmsg->cmsg_type = IP_SENDSRCADDR;
		cmsg->cmsg_len = CMSG_LEN(sizeof(*in));

		in = (struct in_addr *) CMSG_DATA(cmsg);
		*in = s4->sin_addr;
#  endif
	}
#endif

#  if defined(IPV6_PKTINFO)
	if (from->sa_family == AF_INET6) {
		struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) from;

		struct cmsghdr *cmsg;
		struct in6_pktinfo *pkt;

		msgh.msg_control = cbuf;
		msgh.msg_controllen = CMSG_SPACE(sizeof(*pkt));

		cmsg = CMSG_FIRSTHDR(&msgh);
		cmsg->cmsg_level = IPPROTO_IPV6;
		cmsg->cmsg_type = IPV6_PKTINFO;
		cmsg->cmsg_len = CMSG_LEN(sizeof(*pkt));

		pkt = (struct in6_pktinfo *) CMSG_DATA(cmsg);
		memset(pkt, 0, sizeof(*pkt));
		pkt->ipi6_addr = s6->sin6_addr;
	}
#  endif	/* IPV6_PKTINFO */

	return sendmsg(s, &msgh, flags);
}
示例#26
0
void ion_share_test()

{
	struct ion_handle *handle;
	int sd[2];
	int num_fd = 1;
	struct iovec count_vec = {
		.iov_base = &num_fd,
		.iov_len = sizeof num_fd,
	};
	char buf[CMSG_SPACE(sizeof(int))];
	socketpair(AF_UNIX, SOCK_STREAM, 0, sd);
	if (fork()) {
		struct msghdr msg = {
			.msg_control = buf,
			.msg_controllen = sizeof buf,
			.msg_iov = &count_vec,
			.msg_iovlen = 1,
		};

		struct cmsghdr *cmsg;
		int fd, share_fd, ret;
		char *ptr;
		/* parent */
		if(_ion_alloc_test(&fd, &handle))
			return;
		ret = ion_share(fd, handle, &share_fd);
		if (ret)
			printf("share failed %s\n", strerror(errno));
		ptr = mmap(NULL, len, prot, map_flags, share_fd, 0);
		if (ptr == MAP_FAILED) {
			return;
		}
		strcpy(ptr, "master");
		cmsg = CMSG_FIRSTHDR(&msg);
		cmsg->cmsg_level = SOL_SOCKET;
		cmsg->cmsg_type = SCM_RIGHTS;
		cmsg->cmsg_len = CMSG_LEN(sizeof(int));
		*(int *)CMSG_DATA(cmsg) = share_fd;
		/* send the fd */
		printf("master? [%10s] should be [master]\n", ptr);
		printf("master sending msg 1\n");
		sendmsg(sd[0], &msg, 0);
		if (recvmsg(sd[0], &msg, 0) < 0)
			perror("master recv msg 2");
		printf("master? [%10s] should be [child]\n", ptr);

		/* send ping */
		sendmsg(sd[0], &msg, 0);
		printf("master->master? [%10s]\n", ptr);
		if (recvmsg(sd[0], &msg, 0) < 0)
			perror("master recv 1");
	} else {
		struct msghdr msg;
		struct cmsghdr *cmsg;
		char* ptr;
		int fd, recv_fd;
		char* child_buf[100];
		/* child */
		struct iovec count_vec = {
			.iov_base = child_buf,
			.iov_len = sizeof child_buf,
		};

		struct msghdr child_msg = {
			.msg_control = buf,
			.msg_controllen = sizeof buf,
			.msg_iov = &count_vec,
			.msg_iovlen = 1,
		};

		if (recvmsg(sd[1], &child_msg, 0) < 0)
			perror("child recv msg 1");
		cmsg = CMSG_FIRSTHDR(&child_msg);
		if (cmsg == NULL) {
			printf("no cmsg rcvd in child");
			return;
		}
		recv_fd = *(int*)CMSG_DATA(cmsg);
		if (recv_fd < 0) {
			printf("could not get recv_fd from socket");
			return;
		}
		printf("child %d\n", recv_fd);
		fd = ion_open();
		ptr = mmap(NULL, len, prot, map_flags, recv_fd, 0);
		if (ptr == MAP_FAILED) {
			return;
		}
		printf("child? [%10s] should be [master]\n", ptr);
		strcpy(ptr, "child");
		printf("child sending msg 2\n");
		sendmsg(sd[1], &child_msg, 0);
	}
}

int main(int argc, char* argv[]) {
	int c;
	enum tests {
		ALLOC_TEST = 0, MAP_TEST, SHARE_TEST,
	};

	while (1) {
		static struct option opts[] = {
			{"alloc", no_argument, 0, 'a'},
			{"alloc_flags", required_argument, 0, 'f'},
			{"heap_mask", required_argument, 0, 'h'},
			{"map", no_argument, 0, 'm'},
			{"share", no_argument, 0, 's'},
			{"len", required_argument, 0, 'l'},
			{"align", required_argument, 0, 'g'},
			{"map_flags", required_argument, 0, 'z'},
			{"prot", required_argument, 0, 'p'},
		};
		int i = 0;
		c = getopt_long(argc, argv, "af:h:l:mr:st", opts, &i);
		if (c == -1)
			break;

		switch (c) {
		case 'l':
			len = atol(optarg);
			break;
		case 'g':
			align = atol(optarg);
			break;
		case 'z':
			map_flags = 0;
			map_flags |= strstr(optarg, "PROT_EXEC") ?
				PROT_EXEC : 0;
			map_flags |= strstr(optarg, "PROT_READ") ?
				PROT_READ: 0;
			map_flags |= strstr(optarg, "PROT_WRITE") ?
				PROT_WRITE: 0;
			map_flags |= strstr(optarg, "PROT_NONE") ?
				PROT_NONE: 0;
			break;
		case 'p':
			prot = 0;
			prot |= strstr(optarg, "MAP_PRIVATE") ?
				MAP_PRIVATE	 : 0;
			prot |= strstr(optarg, "MAP_SHARED") ?
				MAP_PRIVATE	 : 0;
			break;
		case 'f':
			alloc_flags = atol(optarg);
			break;
		case 'h':
			heap_mask = atol(optarg);
			break;
		case 'a':
			test = ALLOC_TEST;
			break;
		case 'm':
			test = MAP_TEST;
			break;
		case 's':
			test = SHARE_TEST;
			break;
		}
	}
	printf("test %d, len %u, align %u, map_flags %d, prot %d, heap_mask %d,"
	       " alloc_flags %d\n", test, len, align, map_flags, prot,
	       heap_mask, alloc_flags);
	switch (test) {
		case ALLOC_TEST:
			ion_alloc_test();
			break;
		case MAP_TEST:
			ion_map_test();
			break;
		case SHARE_TEST:
			ion_share_test();
			break;
		default:
			printf("must specify a test (alloc, map, share)\n");
	}
	return 0;
}
示例#27
0
int bus_container_connect_kernel(sd_bus *b) {
        _cleanup_close_pair_ int pair[2] = { -1, -1 };
        _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
        union {
                struct cmsghdr cmsghdr;
                uint8_t buf[CMSG_SPACE(sizeof(int))];
        } control = {};
        struct msghdr mh = {
                .msg_control = &control,
                .msg_controllen = sizeof(control),
        };
        struct cmsghdr *cmsg;
        pid_t child;
        siginfo_t si;
        int r;
        _cleanup_close_ int fd = -1;

        assert(b);
        assert(b->input_fd < 0);
        assert(b->output_fd < 0);
        assert(b->nspid > 0 || b->machine);

        if (b->nspid <= 0) {
                r = container_get_leader(b->machine, &b->nspid);
                if (r < 0)
                        return r;
        }

        r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
        if (r < 0)
                return r;

        if (socketpair(AF_UNIX, SOCK_DGRAM, 0, pair) < 0)
                return -errno;

        child = fork();
        if (child < 0)
                return -errno;

        if (child == 0) {
                pid_t grandchild;

                pair[0] = safe_close(pair[0]);

                r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
                if (r < 0)
                        _exit(EXIT_FAILURE);

                /* We just changed PID namespace, however it will only
                 * take effect on the children we now fork. Hence,
                 * let's fork another time, and connect from this
                 * grandchild, so that kdbus only sees the credentials
                 * of this process which comes from within the
                 * container, and not outside of it */

                grandchild = fork();
                if (grandchild < 0)
                        _exit(EXIT_FAILURE);

                if (grandchild == 0) {

                        fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
                        if (fd < 0)
                                _exit(EXIT_FAILURE);

                        cmsg = CMSG_FIRSTHDR(&mh);
                        cmsg->cmsg_level = SOL_SOCKET;
                        cmsg->cmsg_type = SCM_RIGHTS;
                        cmsg->cmsg_len = CMSG_LEN(sizeof(int));
                        memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));

                        mh.msg_controllen = cmsg->cmsg_len;

                        if (sendmsg(pair[1], &mh, MSG_NOSIGNAL) < 0)
                                _exit(EXIT_FAILURE);

                        _exit(EXIT_SUCCESS);
                }

                r = wait_for_terminate(grandchild, &si);
                if (r < 0)
                        _exit(EXIT_FAILURE);

                if (si.si_code != CLD_EXITED)
                        _exit(EXIT_FAILURE);

                _exit(si.si_status);
        }

        pair[1] = safe_close(pair[1]);

        r = wait_for_terminate(child, &si);
        if (r < 0)
                return r;

        if (si.si_code != CLD_EXITED)
                return -EIO;

        if (si.si_status != EXIT_SUCCESS)
                return -EIO;

        if (recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC) < 0)
                return -errno;

        CMSG_FOREACH(cmsg, &mh)
                if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
                        int *fds;
                        unsigned n_fds;

                        fds = (int*) CMSG_DATA(cmsg);
                        n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);

                        if (n_fds != 1) {
                                close_many(fds, n_fds);
                                return -EIO;
                        }

                        fd = fds[0];
                }

        b->input_fd = b->output_fd = fd;
        fd = -1;

        return bus_kernel_take_fd(b);
}
示例#28
0
static int32_t
server_process_request(server_p srv, int32_t fd)
{
	uint8_t		ctl[128];
	sdp_pdu_p	pdu = (sdp_pdu_p) srv->req;
	struct msghdr	msg;
	struct iovec	iov;
	int32_t		len, error;
	struct cmsghdr	*cmsg;

	assert(srv->imtu > 0);
	assert(srv->req != NULL);
	assert(FD_ISSET(fd, &srv->fdset));
	assert(srv->fdidx[fd].valid);
	assert(!srv->fdidx[fd].server);
	assert(srv->fdidx[fd].rsp != NULL);
	assert(srv->fdidx[fd].omtu >= L2CAP_MTU_MINIMUM);

	iov.iov_base = srv->req;
	iov.iov_len = srv->imtu;

	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = ctl;
	msg.msg_controllen = sizeof(ctl);
	msg.msg_flags = 0;

	do {
		len = recvmsg(fd, &msg, 0);
	} while (len < 0 && errno == EINTR);

	if (len < 0) {
		log_err("Could not receive SDP request from %s socket. %s (%d)",
			srv->fdidx[fd].control? "control" : "L2CAP",
			strerror(errno), errno);
		return (-1);
	}
	if (len == 0) {
		log_info("Client on %s socket has disconnected",
			srv->fdidx[fd].control? "control" : "L2CAP");
		return (-1);
	}

#if XXX
	if ((cmsg = CMSG_FIRSTHDR(&msg)) != NULL
	    && cmsg->cmsg_level == SOL_SOCKET
	    && cmsg->cmsg_type == SCM_CREDS
#if 0
	    && cmsg->cmsg_len >= CMSG_LEN(SOCKCREDSIZE(0))
#endif
)
	    	srv->fdidx[fd].priv = 
		    server_auth_check(srv, (struct cmsgcred *)CMSG_DATA(cmsg));
#if 0
		    server_auth_check(srv, (struct sockcred *)CMSG_DATA(cmsg));
#endif
#else
srv->fdidx[fd].priv = 1;
#endif

	if (len >= sizeof(*pdu)
	    && (sizeof(*pdu) + (pdu->len = ntohs(pdu->len))) == len) {
		switch (pdu->pid) {
		case SDP_PDU_SERVICE_SEARCH_REQUEST:
			error = server_prepare_service_search_response(srv, fd);
			break;

		case SDP_PDU_SERVICE_ATTRIBUTE_REQUEST:
			error = server_prepare_service_attribute_response(srv, fd);
			break;

		case SDP_PDU_SERVICE_SEARCH_ATTRIBUTE_REQUEST:
			error = server_prepare_service_search_attribute_response(srv, fd);
			break;

		case SDP_PDU_SERVICE_REGISTER_REQUEST:
			error = server_prepare_service_register_response(srv, fd);
			break;

		case SDP_PDU_SERVICE_UNREGISTER_REQUEST:
			error = server_prepare_service_unregister_response(srv, fd);
			break;

		case SDP_PDU_SERVICE_CHANGE_REQUEST:
			error = server_prepare_service_change_response(srv, fd);
			break;

		default:
			error = SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX;
			break;
		}
	} else
		error = SDP_ERROR_CODE_INVALID_PDU_SIZE;

	if (error == 0) {
		switch (pdu->pid) {
		case SDP_PDU_SERVICE_SEARCH_REQUEST:
			error = server_send_service_search_response(srv, fd);
			break;

		case SDP_PDU_SERVICE_ATTRIBUTE_REQUEST:
			error = server_send_service_attribute_response(srv, fd);
			break;

		case SDP_PDU_SERVICE_SEARCH_ATTRIBUTE_REQUEST:
			error = server_send_service_search_attribute_response(srv, fd);
			break;

		case SDP_PDU_SERVICE_REGISTER_REQUEST:
			error = server_send_service_register_response(srv, fd);
			break;

		case SDP_PDU_SERVICE_UNREGISTER_REQUEST:
			error = server_send_service_unregister_response(srv, fd);
			break;

		case SDP_PDU_SERVICE_CHANGE_REQUEST:
			error = server_send_service_change_response(srv, fd);
			break;

		default:
			error = SDP_ERROR_CODE_INVALID_REQUEST_SYNTAX;
			break;
		}

		if (error != 0)
			log_err("Could not send SDP response to %s socket, " \
				"pdu->pid=%d, pdu->tid=%d, error=%d",
				srv->fdidx[fd].control? "control" : "L2CAP",
				pdu->pid, ntohs(pdu->tid), error);
	} else {
		log_err("Could not process SDP request from %s socket, " \
			"pdu->pid=%d, pdu->tid=%d, pdu->len=%d, len=%d, " \
			"error=%d",
			srv->fdidx[fd].control? "control" : "L2CAP",
			pdu->pid, ntohs(pdu->tid), pdu->len, len, error);

		error = server_send_error_response(srv, fd, error);
		if (error != 0)
			log_err("Could not send SDP error response to %s " \
				"socket, pdu->pid=%d, pdu->tid=%d, error=%d",
				srv->fdidx[fd].control? "control" : "L2CAP",
				pdu->pid, ntohs(pdu->tid), error);
	}

	/* On error forget response (if any) */
	if (error != 0) {
		srv->fdidx[fd].rsp_cs = 0;
		srv->fdidx[fd].rsp_size = 0;
		srv->fdidx[fd].rsp_limit = 0;
	}

	return (error);
}
示例#29
0
int main_server_udp(int ipv4_sock, int ipv6_sock, in_port_t local_port) {
	/* Use recvmsg/sendmsg instead of recvfrom/sendto because
	   the latter combination may choose a different source
	   HIT for the server */
	int err = 0, on = 1, recvnum, sendnum, is_ipv4 = 0;
	int cmsg_level, cmsg_type, highest_descriptor = -1;
        fd_set read_fdset;
	union {
		struct sockaddr_in in4;
		struct sockaddr_in6 in6;
	} peer_addr, local_addr;
	uint8_t cmsgbuf[CMSG_SPACE(sizeof(struct inet6_pktinfo))];
	uint8_t mylovemostdata[IP_MAXPACKET];
	struct iovec iov;
        struct cmsghdr *cmsg = (struct cmsghdr *) cmsgbuf;
	union {
		struct in_pktinfo *in4;
		struct inet6_pktinfo *in6;
	} pktinfo;
	struct msghdr msg;

	FD_ZERO(&read_fdset);
	FD_SET(ipv4_sock, &read_fdset);
	FD_SET(ipv6_sock, &read_fdset);
	highest_descriptor = maxof(2, ipv4_sock, ipv6_sock);

	printf("=== Server listening INADDR_ANY/IN6ADDR_ANY ===\n");
	
	while(select((highest_descriptor + 1), &read_fdset,
		     NULL, NULL, NULL)) {

		/* XX FIXME: receiving two packets at the same time */

		if (FD_ISSET(ipv4_sock, &read_fdset)) {
			is_ipv4 = 1;
			//FD_CLR(ipv4_sock, &read_fdset);
		} else if (FD_ISSET(ipv6_sock, &read_fdset)) {
			is_ipv4 = 0;
			//FD_CLR(ipv6_sock, &read_fdset);
		} else {
			printf("Unhandled select event\n");
			goto reset;
		}

		msg.msg_name = &peer_addr.in6;
		msg.msg_namelen = sizeof(struct sockaddr_in6);
		msg.msg_iov = &iov;
		msg.msg_iovlen = 1;
		msg.msg_control = cmsgbuf;
		msg.msg_controllen = sizeof(cmsgbuf);
		msg.msg_flags = 0;
		
		iov.iov_base = mylovemostdata;
		iov.iov_len = sizeof(mylovemostdata);
		
		memset(mylovemostdata, 0, sizeof(mylovemostdata));
		memset(&peer_addr, 0, sizeof(peer_addr));
		memset(cmsgbuf, 0, sizeof(cmsgbuf));

		recvnum = recvmsg((is_ipv4 ? ipv4_sock : ipv6_sock), &msg, 0);
		if (recvnum < 0) {
			perror("recvmsg\n");
			goto reset;
		}
		printf("Received %d bytes\n", recvnum);

		//is_ipv4 = IN6_IS_ADDR_V4MAPPED(&peer_addr.in6.sin6_addr);
	
		cmsg_level = (is_ipv4) ? IPPROTO_IP : IPPROTO_IPV6;
		cmsg_type = (is_ipv4) ? IP_PKTINFO : IPV6_2292PKTINFO;
	
		/* Local address comes from ancillary data passed
		 * with msg due to IPV6_PKTINFO socket option */
		for (cmsg=CMSG_FIRSTHDR(&msg); cmsg;
		     cmsg=CMSG_NXTHDR(&msg,cmsg)){
			if ((cmsg->cmsg_level == cmsg_level) &&
			    (cmsg->cmsg_type == cmsg_type)) {
				/* The structure is a union, so this fills
				   also the pktinfo_in6 pointer */
				pktinfo.in4 =
					(struct in_pktinfo *)CMSG_DATA(cmsg);
				break;
			}
		}
	
		if (is_ipv4) {
			local_addr.in4.sin_family = AF_INET;
			local_addr.in4.sin_port = htons(local_port);
			//local_addr.in4.sin_port = peer_addr.in6.sin6_port;
			local_addr.in4.sin_addr.s_addr =
				pktinfo.in4->ipi_addr.s_addr;
			HIP_DEBUG_INADDR("local addr",
					 &local_addr.in4.sin_addr);
			HIP_DEBUG("local port %d\n",
				  ntohs(local_addr.in4.sin_port));
			HIP_DEBUG_INADDR("peer addr",
					 &peer_addr.in4.sin_addr);
			HIP_DEBUG("peer port %d\n",
				  ntohs(peer_addr.in4.sin_port));
			
		} else {
			local_addr.in6.sin6_family = AF_INET6;
			memcpy(&local_addr.in6.sin6_addr,
			       &pktinfo.in6->ipi6_addr,
			       sizeof(struct in6_addr));
			local_addr.in6.sin6_port = htons(local_port);
			HIP_DEBUG_IN6ADDR("local addr",
					  &local_addr.in6.sin6_addr);
			HIP_DEBUG("local port %d\n",
				  ntohs(local_addr.in6.sin6_port));
			HIP_DEBUG_IN6ADDR("peer addr",
					  &peer_addr.in6.sin6_addr);
			HIP_DEBUG("peer port %d\n",
				  ntohs(peer_addr.in6.sin6_port));
		}

		err = udp_send_msg((is_ipv4 ? ipv4_sock : ipv6_sock),
				   mylovemostdata, recvnum,
				   (struct sockaddr *) &local_addr,
				   (struct sockaddr *) &peer_addr);
		if (err) {
			printf("Failed to echo data back\n");
		}

	reset:

		FD_ZERO(&read_fdset);
		FD_SET(ipv4_sock, &read_fdset);
		FD_SET(ipv6_sock, &read_fdset);
	}

out_err:
	return err;
}
示例#30
0
int
netx_poll(void)
{
  ssize_t             length;
  fd_set              socks;
  netxsocket_t       *nsk;
  netx_nativeSocket_t high_sock = 0;
  struct timeval      timeout;  /* Timeout for select */
  int                 readsocks;
  netx_addr_t         source;
#if STACK_RETURNS_DEST_ADDR
  uint8_t pktinfo[CMSG_SPACE(sizeof(struct in_pktinfo))];
  struct iovec bufvec[1];
  struct msghdr hdr;
  struct cmsghdr *cmp;
  groupaddr_t groupaddr;
#else
  socklen_t           addr_len
#endif

  FD_ZERO(&socks);

  /* abort if we have no sockets yet */
  nsk = nsk_first_netsock();
  if (!nsk) {
    /* acnlog(LOG_DEBUG | LOG_NETX , "netx_poll: no sockets"); */
    return FAIL;
  }
  while (nsk) {
    /* make sure we assignged the socket */
    if (nsk->nativesock) {
      FD_SET(nsk->nativesock, &socks);
      if (nsk->nativesock > high_sock) {
        high_sock = nsk->nativesock;
      }
    }
    nsk = nsk_next_netsock(nsk);
  }
  /* perhaps none were assigned */
  if (high_sock == 0) {
    return FAIL;
  }

  /* TODO: what should timeout be? */
  timeout.tv_sec = 10;
  timeout.tv_usec = 0;
  readsocks = select(high_sock + 1, &socks, NULL, NULL, &timeout);
  if (readsocks < 0) {
    acnlog(LOG_DEBUG | LOG_NETX , "netx_poll: select fail: %d", errno);
    return FAIL; /* fail */
  }

  if (readsocks > 0) {
#if STACK_RETURNS_DEST_ADDR
    /* init strutures for recvmsg (man recvmsg, man cmsg for details) */
    bufvec->iov_base = recv_buffer;
    bufvec->iov_len = sizeof(UDPPacket);
    hdr.msg_name = &source;
    hdr.msg_namelen = sizeof(source);
    hdr.msg_iov = bufvec;
    hdr.msg_iovlen = 1;
    hdr.msg_control = &pktinfo;
    hdr.msg_flags = 0;
#endif

    for (nsk = nsk_first_netsock(); nsk && nsk->nativesock; nsk = nsk_next_netsock(nsk)) {
      if (FD_ISSET(nsk->nativesock, &socks)) {
        /* Get some data */
#if STACK_RETURNS_DEST_ADDR
        hdr.msg_controllen = sizeof(pktinfo);
        length = recvmsg(nsk->nativesock, &hdr, 0);
#else
        addr_len = sizeof(netx_addr_t);
        length = recvfrom(nsk->nativesock, recv_buffer, sizeof(recv_buffer), 0, (SOCKADDR *)&source, &addr_len);
#endif
        /* Test for error */
        if (length == -1) {
          acnlog(LOG_DEBUG | LOG_NETX , "netx_poll: recvfrom fail: %d", errno);
          return FAIL; /* fail */
        }

        /* make sure we actually have some data to process */
        if (length > 0) {
#if STACK_RETURNS_DEST_ADDR
          /* Look for ancillary data of our type*/
          cmp = CMSG_FIRSTHDR(&hdr);
          do {
            if (cmp == NULL) {
              acnlog(LOG_DEBUG | LOG_NETX , "netx_poll: unable to get ancillary data");
              return FAIL;
            }
            cmp = CMSG_NXTHDR(&hdr, cmp);
          } while (!(cmp->cmsg_level == IPPROTO_IP && cmp->cmsg_type == IP_PKTINFO));

          /* get the address and move it to our destination address*/
          groupaddr = ((struct in_pktinfo *)(CMSG_DATA(cmp)))->ipi_addr.s_addr;
          if (!is_multicast(groupaddr)) groupaddr = netx_GROUP_UNICAST;
          NETX_HANDLER(nsk, recv_buffer, length, groupaddr, &source);
#else
          NETX_HANDLER(nsk, recv_buffer, length, &source);
#endif /* STACK_RETURNS_DEST_ADDR */
        } else {
          acnlog(LOG_DEBUG | LOG_NETX , "netx_poll: length = 0");
        }
      }
    }
  }
  return OK;
}