static grpc_endpoint_op_status tcp_flush(grpc_tcp *tcp) {
  struct msghdr msg;
  struct iovec iov[MAX_WRITE_IOVEC];
  int iov_size;
  ssize_t sent_length;
  ssize_t sending_length;
  ssize_t trailing;
  ssize_t unwind_slice_idx;
  ssize_t unwind_byte_idx;

  for (;;) {
    sending_length = 0;
    unwind_slice_idx = tcp->outgoing_slice_idx;
    unwind_byte_idx = tcp->outgoing_byte_idx;
    for (iov_size = 0; tcp->outgoing_slice_idx != tcp->outgoing_buffer->count &&
                       iov_size != MAX_WRITE_IOVEC;
         iov_size++) {
      iov[iov_size].iov_base =
          GPR_SLICE_START_PTR(
              tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]) +
          tcp->outgoing_byte_idx;
      iov[iov_size].iov_len =
          GPR_SLICE_LENGTH(
              tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]) -
          tcp->outgoing_byte_idx;
      sending_length += iov[iov_size].iov_len;
      tcp->outgoing_slice_idx++;
      tcp->outgoing_byte_idx = 0;
    }
    GPR_ASSERT(iov_size > 0);

    msg.msg_name = NULL;
    msg.msg_namelen = 0;
    msg.msg_iov = iov;
    msg.msg_iovlen = iov_size;
    msg.msg_control = NULL;
    msg.msg_controllen = 0;
    msg.msg_flags = 0;

    GRPC_TIMER_BEGIN(GRPC_PTAG_SENDMSG, 0);
    do {
      /* TODO(klempner): Cork if this is a partial write */
      sent_length = sendmsg(tcp->fd, &msg, SENDMSG_FLAGS);
    } while (sent_length < 0 && errno == EINTR);
    GRPC_TIMER_END(GRPC_PTAG_SENDMSG, 0);

    if (sent_length < 0) {
      if (errno == EAGAIN) {
        tcp->outgoing_slice_idx = unwind_slice_idx;
        tcp->outgoing_byte_idx = unwind_byte_idx;
        return GRPC_ENDPOINT_PENDING;
      } else {
        /* TODO(klempner): Log some of these */
        return GRPC_ENDPOINT_ERROR;
      }
    }

    GPR_ASSERT(tcp->outgoing_byte_idx == 0);
    trailing = sending_length - sent_length;
    while (trailing > 0) {
      ssize_t slice_length;

      tcp->outgoing_slice_idx--;
      slice_length = GPR_SLICE_LENGTH(
          tcp->outgoing_buffer->slices[tcp->outgoing_slice_idx]);
      if (slice_length > trailing) {
        tcp->outgoing_byte_idx = slice_length - trailing;
        break;
      } else {
        trailing -= slice_length;
      }
    }

    if (tcp->outgoing_slice_idx == tcp->outgoing_buffer->count) {
      return GRPC_ENDPOINT_DONE;
    }
  };
}
Ejemplo n.º 2
0
/* Returns zero on success, less than zero on socket error and greater than
 * zero on other errors. */
static int conn_read_netlink (void)
{
#if HAVE_STRUCT_LINUX_INET_DIAG_REQ
  int fd;
  struct inet_diag_msg *r;
  char buf[8192];

  /* If this fails, it's likely a permission problem. We'll fall back to
   * reading this information from files below. */
  fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG);
  if (fd < 0)
  {
    ERROR ("tcpconns plugin: conn_read_netlink: socket(AF_NETLINK, SOCK_RAW, "
	"NETLINK_INET_DIAG) failed: %s",
	sstrerror (errno, buf, sizeof (buf)));
    return (-1);
  }

  struct sockaddr_nl nladdr = {
    .nl_family = AF_NETLINK
  };

  struct nlreq req = {
    .nlh.nlmsg_len = sizeof(req),
    .nlh.nlmsg_type = TCPDIAG_GETSOCK,
    /* NLM_F_ROOT: return the complete table instead of a single entry.
     * NLM_F_MATCH: return all entries matching criteria (not implemented)
     * NLM_F_REQUEST: must be set on all request messages */
    .nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST,
    .nlh.nlmsg_pid = 0,
    /* The sequence_number is used to track our messages. Since netlink is not
     * reliable, we don't want to end up with a corrupt or incomplete old
     * message in case the system is/was out of memory. */
    .nlh.nlmsg_seq = ++sequence_number,
    .r.idiag_family = AF_INET,
    .r.idiag_states = 0xfff,
    .r.idiag_ext = 0
  };

  struct iovec iov = {
    .iov_base = &req,
    .iov_len = sizeof(req)
  };

  struct msghdr msg = {
    .msg_name = (void*)&nladdr,
    .msg_namelen = sizeof(nladdr),
    .msg_iov = &iov,
    .msg_iovlen = 1
  };

  if (sendmsg (fd, &msg, 0) < 0)
  {
    ERROR ("tcpconns plugin: conn_read_netlink: sendmsg(2) failed: %s",
	sstrerror (errno, buf, sizeof (buf)));
    close (fd);
    return (-1);
  }

  iov.iov_base = buf;
  iov.iov_len = sizeof(buf);

  while (1)
  {
    int status;
    struct nlmsghdr *h;

    memset(&msg, 0, sizeof(msg));
    msg.msg_name = (void*)&nladdr;
    msg.msg_namelen = sizeof(nladdr);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

    status = recvmsg(fd, (void *) &msg, /* flags = */ 0);
    if (status < 0)
    {
      if ((errno == EINTR) || (errno == EAGAIN))
        continue;

      ERROR ("tcpconns plugin: conn_read_netlink: recvmsg(2) failed: %s",
	  sstrerror (errno, buf, sizeof (buf)));
      close (fd);
      return (-1);
    }
    else if (status == 0)
    {
      close (fd);
      DEBUG ("tcpconns plugin: conn_read_netlink: Unexpected zero-sized "
	  "reply from netlink socket.");
      return (0);
    }

    h = (struct nlmsghdr*)buf;
    while (NLMSG_OK(h, status))
    {
      if (h->nlmsg_seq != sequence_number)
      {
	h = NLMSG_NEXT(h, status);
	continue;
      }

      if (h->nlmsg_type == NLMSG_DONE)
      {
	close (fd);
	return (0);
      }
      else if (h->nlmsg_type == NLMSG_ERROR)
      {
	struct nlmsgerr *msg_error;

	msg_error = NLMSG_DATA(h);
	WARNING ("tcpconns plugin: conn_read_netlink: Received error %i.",
	    msg_error->error);

	close (fd);
	return (1);
      }

      r = NLMSG_DATA(h);

      /* This code does not (need to) distinguish between IPv4 and IPv6. */
      conn_handle_ports (ntohs(r->id.idiag_sport),
	  ntohs(r->id.idiag_dport),
	  r->idiag_state);

      h = NLMSG_NEXT(h, status);
    } /* while (NLMSG_OK) */
  } /* while (1) */

  /* Not reached because the while() loop above handles the exit condition. */
  return (0);
#else
  return (1);
#endif /* HAVE_STRUCT_LINUX_INET_DIAG_REQ */
} /* int conn_read_netlink */

static int conn_handle_line (char *buffer)
{
  char *fields[32];
  int   fields_len;

  char *endptr;

  char *port_local_str;
  char *port_remote_str;
  uint16_t port_local;
  uint16_t port_remote;

  uint8_t state;

  int buffer_len = strlen (buffer);

  while ((buffer_len > 0) && (buffer[buffer_len - 1] < 32))
    buffer[--buffer_len] = '\0';
  if (buffer_len <= 0)
    return (-1);

  fields_len = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
  if (fields_len < 12)
  {
    DEBUG ("tcpconns plugin: Got %i fields, expected at least 12.", fields_len);
    return (-1);
  }

  port_local_str  = strchr (fields[1], ':');
  port_remote_str = strchr (fields[2], ':');

  if ((port_local_str == NULL) || (port_remote_str == NULL))
    return (-1);
  port_local_str++;
  port_remote_str++;
  if ((*port_local_str == '\0') || (*port_remote_str == '\0'))
    return (-1);

  endptr = NULL;
  port_local = (uint16_t) strtol (port_local_str, &endptr, 16);
  if ((endptr == NULL) || (*endptr != '\0'))
    return (-1);

  endptr = NULL;
  port_remote = (uint16_t) strtol (port_remote_str, &endptr, 16);
  if ((endptr == NULL) || (*endptr != '\0'))
    return (-1);

  endptr = NULL;
  state = (uint8_t) strtol (fields[3], &endptr, 16);
  if ((endptr == NULL) || (*endptr != '\0'))
    return (-1);

  return (conn_handle_ports (port_local, port_remote, state));
} /* int conn_handle_line */

static int conn_read_file (const char *file)
{
  FILE *fh;
  char buffer[1024];

  fh = fopen (file, "r");
  if (fh == NULL)
    return (-1);

  while (fgets (buffer, sizeof (buffer), fh) != NULL)
  {
    conn_handle_line (buffer);
  } /* while (fgets) */

  fclose (fh);

  return (0);
} /* int conn_read_file */
/* #endif KERNEL_LINUX */

#elif HAVE_SYSCTLBYNAME
/* #endif HAVE_SYSCTLBYNAME */

#elif HAVE_LIBKVM_NLIST
#endif /* HAVE_LIBKVM_NLIST */

static int conn_config (const char *key, const char *value)
{
  if (strcasecmp (key, "ListeningPorts") == 0)
  {
    if (IS_TRUE (value))
      port_collect_listening = 1;
    else
      port_collect_listening = 0;
  }
  else if ((strcasecmp (key, "LocalPort") == 0)
      || (strcasecmp (key, "RemotePort") == 0))
  {
      port_entry_t *pe;
      int port = atoi (value);

      if ((port < 1) || (port > 65535))
      {
	ERROR ("tcpconns plugin: Invalid port: %i", port);
	return (1);
      }

      pe = conn_get_port_entry ((uint16_t) port, 1 /* create */);
      if (pe == NULL)
      {
	ERROR ("tcpconns plugin: conn_get_port_entry failed.");
	return (1);
      }

      if (strcasecmp (key, "LocalPort") == 0)
	pe->flags |= PORT_COLLECT_LOCAL;
      else
	pe->flags |= PORT_COLLECT_REMOTE;
  }
  else if (strcasecmp (key, "AllPortsSummary") == 0)
  {
    if (IS_TRUE (value))
      port_collect_total = 1;
    else
      port_collect_total = 0;
  }
  else
  {
    return (-1);
  }

  return (0);
} /* int conn_config */

#if KERNEL_LINUX
static int conn_init (void)
{
  if (port_collect_total == 0 && port_list_head == NULL)
    port_collect_listening = 1;

  return (0);
} /* int conn_init */

static int conn_read (void)
{
  int status;

  conn_reset_port_entry ();

  if (linux_source == SRC_NETLINK)
  {
    status = conn_read_netlink ();
  }
  else if (linux_source == SRC_PROC)
  {
    int errors_num = 0;

    if (conn_read_file ("/proc/net/tcp") != 0)
      errors_num++;
    if (conn_read_file ("/proc/net/tcp6") != 0)
      errors_num++;

    if (errors_num < 2)
      status = 0;
    else
      status = ENOENT;
  }
  else /* if (linux_source == SRC_DUNNO) */
  {
    /* Try to use netlink for getting this data, it is _much_ faster on systems
     * with a large amount of connections. */
    status = conn_read_netlink ();
    if (status == 0)
    {
      INFO ("tcpconns plugin: Reading from netlink succeeded. "
	  "Will use the netlink method from now on.");
      linux_source = SRC_NETLINK;
    }
    else
    {
      INFO ("tcpconns plugin: Reading from netlink failed. "
	  "Will read from /proc from now on.");
      linux_source = SRC_PROC;

      /* return success here to avoid the "plugin failed" message. */
      return (0);
    }
  }

  if (status == 0)
    conn_submit_all ();
  else
    return (status);

  return (0);
} /* int conn_read */
Ejemplo n.º 3
0
int
emf_cfg_request_send(emf_cfg_request_t *buffer, int length)
{
	struct sockaddr_nl src_addr, dest_addr;
	struct nlmsghdr *nlh = NULL;
	struct msghdr msg;
	struct iovec iov;
	int    sock_fd, ret;

	if ((buffer == NULL) || (length > MAX_DATA_SIZE))
	{
		fprintf(stderr, "Invalid parameters %p %d\n", buffer, length);
		return (FAILURE);
	}

	/* Create a netlink socket */
	sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_EMFC);

	if (sock_fd < 0)
	{
		fprintf(stderr, "Netlink socket create failed\n");
		return (FAILURE);
	}

	/* Associate a local address with the opened socket */
	memset(&src_addr, 0, sizeof(struct sockaddr_nl));
	src_addr.nl_family = AF_NETLINK;
	src_addr.nl_pid = getpid();
	src_addr.nl_groups = 0;
	bind(sock_fd, (struct sockaddr *)&src_addr, sizeof(src_addr));

	/* Fill the destination address, pid of 0 indicates kernel */
	memset(&dest_addr, 0, sizeof(struct sockaddr_nl));
	dest_addr.nl_family = AF_NETLINK;
	dest_addr.nl_pid = 0;
	dest_addr.nl_groups = 0;

	/* Allocate memory for sending configuration request */
	nlh = (struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_DATA_SIZE));

	if (nlh == NULL)
	{
		fprintf(stderr, "Out of memory allocating cfg buffer\n");
		return (FAILURE);
	}

	/* Fill the netlink message header. The configuration request
	 * contains netlink header followed by data.
	 */
	nlh->nlmsg_len = NLMSG_SPACE(MAX_DATA_SIZE);
	nlh->nlmsg_pid = getpid();
	nlh->nlmsg_flags = 0;

	/* Fill the data part */
	memcpy(NLMSG_DATA(nlh), buffer, length);
	iov.iov_base = (void *)nlh;
	iov.iov_len = nlh->nlmsg_len;
	memset(&msg, 0, sizeof(struct msghdr));
	msg.msg_name = (void *)&dest_addr;
	msg.msg_namelen = sizeof(dest_addr);
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;

	/* Send request to kernel module */
	ret = sendmsg(sock_fd, &msg, 0);
	if (ret < 0)
	{
		perror("sendmsg:");
		free(nlh);
		return (ret);
	}

	/* Wait for the response */
	memset(nlh, 0, NLMSG_SPACE(MAX_DATA_SIZE));
	ret = recvmsg(sock_fd, &msg, 0);
	if (ret < 0)
	{
		perror("recvmsg:");
		free(nlh);
		return (ret);
	}

	/* Copy data to user buffer */
	memcpy(buffer, NLMSG_DATA(nlh), length);

	free(nlh);

	close(sock_fd);

	return (ret);
}
Ejemplo n.º 4
0
void thread_loop(void *userdata)
{
	struct state *state = userdata;

	pthread_spin_init(&state->lock, PTHREAD_PROCESS_PRIVATE);

	pthread_spin_lock(&state->lock);
	stddev_init(&state->stddev);
	stddev_init(&state->stddev_packet);
	pthread_spin_unlock(&state->lock);

	char send_buf[MTU_SIZE], recv_buf[MTU_SIZE];
	struct msghdr *msg = calloc(2, sizeof(struct msghdr));
	struct iovec *iovec = calloc(2, sizeof(struct iovec));
	int i;
	for (i = 0; i < 2; i++) {
		msg[i].msg_iov = &iovec[i];
		msg[i].msg_iovlen = 1;
		iovec[i].iov_len = sizeof(send_buf);
		iovec[i].iov_len = state->packet_size;
	}

	iovec[0].iov_base = send_buf;
	iovec[1].iov_base = recv_buf;

	char pktinfo[4096];
	msg[1].msg_control = pktinfo;
	msg[1].msg_controllen = sizeof(pktinfo);

	uint64_t packet_no = 0;

	while (1) {
		int fd = net_connect_udp(state->target_addr, state->src_port,
					 state->busy_poll);

		struct timeval tv = {1, 0}; // 1 second
		int r = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv,
				   sizeof(tv));
		if (r < 0) {
			PFATAL("setsockopt(SO_RCVTIMEO)");
		}

		for (;; packet_no++) {
			memset(send_buf, 0, sizeof(send_buf));
			snprintf(send_buf, state->packet_size, "%i-%li-%lu",
				 getpid(), gettid(), packet_no);

			uint64_t t0 = realtime_now(), t1 = 0, tp = 0;
			int r = sendmsg(fd, &msg[0], 0);
			if (r <= 0) {
				if (errno == EAGAIN || errno == EWOULDBLOCK ||
				    errno == ECONNREFUSED) {
					break;
				}
				if (errno == EINTR) {
					continue;
				}
				PFATAL("sendmmsg()");
			}

			msg[1].msg_controllen = sizeof(pktinfo);
			while (1) {
				int flags = state->polling ? MSG_DONTWAIT : 0;
				r = recvmsg(fd, &msg[1], flags);
				t1 = realtime_now();
				if (t1 - t0 >= 1000000000) {
					/* No msg for 1s */
					errno = ECONNREFUSED;
					break;
				}

				if (r <= 0 &&
				    (errno == EINTR || errno == EAGAIN ||
				     errno == EWOULDBLOCK)) {
					continue;
				}

				if (r == 0 && state->polling) {
					continue;
				}
				break;
			}

			if (r <= 0 && errno == ECONNREFUSED) {
				sleep(1);
				break;
			}

			if (r <= 0) {
				PFATAL("recvmmsg()");
			}

			if (memcmp(send_buf, recv_buf, sizeof(recv_buf)) != 0) {
				fprintf(stderr, "[!] bad message\n");
				sleep(1);
				break;
			}

			struct cmsghdr *cmsg;
			for (cmsg = CMSG_FIRSTHDR(&msg[1]); cmsg;
			     cmsg = CMSG_NXTHDR(&msg[1], cmsg)) {
				switch (cmsg->cmsg_level) {
				case SOL_SOCKET:
					switch (cmsg->cmsg_type) {
					case SO_TIMESTAMPNS: {
						struct timespec *ts =
							(struct timespec *)
							CMSG_DATA(cmsg);
						tp = TIMESPEC_NSEC(ts);
						break;
					}
					}
					break;
				}
			}

			pthread_spin_lock(&state->lock);
			stddev_add(&state->stddev, t1 - t0);
			if (tp != 0) {
				stddev_add(&state->stddev_packet, t1 - tp);
			}
			pthread_spin_unlock(&state->lock);
		}
		close(fd);
	}
}
Ejemplo n.º 5
0
ssize_t _ribified_sendmsg(int sockfd, const struct msghdr *msg, int flags) {
    int res;
    while ((res = sendmsg(sockfd, msg, flags)) < 0 &&
           yield_if_eagain(sockfd));
    return res;
}
Ejemplo n.º 6
0
void test_sendmsg_server(cyg_addrword_t pnetdata)
{
	int s, i, sendmsglen;
	struct sockaddr_in sa, r_sa;
	struct hostent *hp;
	struct msghdr msghdr_msg;
	struct iovec *piov;
	int j;
	int perIov_len;
	char tmp[TEST_SENDMSG_MSG_LEN];
	
	int threadid;
		
	int port = ((TEST_SENDMSG_DATA_T*)pnetdata)->iport;
	char *pbuf = ((TEST_SENDMSG_DATA_T*)pnetdata)->pbuf;
	
	threadid = port;
	
    if(inet_aton(TEST_SENDMSG_SERVER_ADDR, &sa.sin_addr, pbuf, RNT_BUFFER_LEN) == 0)
    {
		test_printf_error("test_sendmsg_server");
		cyg_thread_exit();
    }
    sa.sin_family = AF_INET;
    sa.sin_port = htons(IPPORT_USERRESERVED + port);
    
	if((hp = gethostbyname(TEST_REMOTEFUNC_HOSTNAME, pbuf, RNT_BUFFER_LEN)) == NULL)
	{
		test_printf_error("test_sendmsg_server");
		cyg_thread_exit();
	}
	
	memcpy(&(r_sa.sin_addr), hp->h_addr_list0, hp->h_length);
	r_sa.sin_family = AF_INET;
	r_sa.sin_port = htons(IPPORT_USERRESERVED + port);
	
	if((s = socket(AF_INET, SOCK_STREAM, PF_UNSPEC, pbuf, RNT_BUFFER_LEN)) == -1)
	{
		test_printf_error("test_sendmsg_server");
		cyg_thread_exit();
	}
	
	if(set_reuseaddr(s, pbuf, RNT_BUFFER_LEN) == -1)
	{
		test_printf_error("test_sendmsg_server");
		netclose(s, pbuf, RNT_BUFFER_LEN);
		cyg_thread_exit();
	}
	
	if(bind(s, (struct sockaddr*)&r_sa, sizeof(r_sa), pbuf, RNT_BUFFER_LEN) == -1)
	{
		test_printf_error("test_sendmsg_server");
		netclose(s, pbuf, RNT_BUFFER_LEN);
		cyg_thread_exit();
	}

    if(connect(s, (struct sockaddr*)&sa, sizeof(sa), pbuf, RNT_BUFFER_LEN) == -1)
    {
		test_printf_error("test_sendmsg_server");
		cyg_thread_exit();
    }
	
    for(i = 0; i < TEST_SENDMSG_WRITE_TIMES; i++)
	{
		strcpy(tmp, TEST_SENDMSG_MSG);
		
		perIov_len = TEST_SENDMSG_MSG_PART_LEN;
		piov = malloc(TEST_SENDMSG_MSG_PARTS*sizeof(struct iovec));
		if(piov == NULL)
		{
			test_printf_error("test_sendmsg_server");
			goto fail;
		}
		memset(piov, 0, TEST_SENDMSG_MSG_PARTS*sizeof(struct iovec));
		
		for(j = 0; j < TEST_SENDMSG_MSG_PARTS; j++)
		{
			piov[j].iov_base = malloc(perIov_len);
			if(piov[j].iov_base == NULL)
			{
				test_printf_error("test_sendmsg_server");
				for(i = 0; i < j; i++) free(piov[j].iov_base);
				if(piov != NULL) free(piov);
				goto fail;
			}
			piov[j].iov_len = perIov_len;
			memcpy(piov[j].iov_base, tmp + j * TEST_SENDMSG_MSG_PART_LEN, TEST_SENDMSG_MSG_PART_LEN);
		}
		
		msghdr_msg.msg_name = NULL;
		msghdr_msg.msg_namelen = 0;
		msghdr_msg.msg_iov = piov;
		msghdr_msg.msg_iovlen = TEST_SENDMSG_MSG_PARTS;
		msghdr_msg.msg_control = NULL;
		msghdr_msg.msg_controllen = 0;
		msghdr_msg.msg_flags = 0;
		
		sendmsglen = sendmsg(s, &msghdr_msg, 0, pbuf, RNT_BUFFER_LEN);
		if(sendmsglen < 0)
		{
			test_printf_error("test_sendmsg_server");
			for(j = 0; j < TEST_SENDMSG_MSG_PARTS; j++)
			{
				if(piov[j].iov_base != NULL) free(piov[j].iov_base);
			}
			if(piov != NULL) free(piov);
			break;
		}
		
		for(j = 0; j < TEST_SENDMSG_MSG_PARTS; j++)
		{
			if(piov[j].iov_base != NULL) free(piov[j].iov_base);
		}
		if(piov != NULL) free(piov);
	}
	
	test_printf_success("test_sendmsg_server");
	
fail:	
	netclose(s, pbuf, RNT_BUFFER_LEN);
	cyg_thread_exit();
}
Ejemplo n.º 7
0
int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr *ether_addr)
{
        struct sockaddr_in6 dst = {
                .sin6_family = AF_INET6,
                .sin6_addr = IN6ADDR_ALL_ROUTERS_MULTICAST_INIT,
        };
        struct {
                struct nd_router_solicit rs;
                struct nd_opt_hdr rs_opt;
                struct ether_addr rs_opt_mac;
        } _packed_ rs = {
                .rs.nd_rs_type = ND_ROUTER_SOLICIT,
        };
        struct iovec iov[1] = {
                { &rs, },
        };
        struct msghdr msg = {
                .msg_name = &dst,
                .msg_namelen = sizeof(dst),
                .msg_iov = iov,
                .msg_iovlen = 1,
        };
        int r;

        if (ether_addr) {
                memcpy(&rs.rs_opt_mac, ether_addr, ETH_ALEN);
                rs.rs_opt.nd_opt_type = ND_OPT_SOURCE_LINKADDR;
                rs.rs_opt.nd_opt_len = 1;
                iov[0].iov_len = sizeof(rs);
        } else
                iov[0].iov_len = sizeof(rs.rs);

        r = sendmsg(s, &msg, 0);
        if (r < 0)
                return -errno;

        return 0;
}

int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
        struct in6_pktinfo pktinfo = {
                .ipi6_ifindex = index,
        };
        union sockaddr_union src = {
                .in6.sin6_family = AF_INET6,
                .in6.sin6_port = htobe16(DHCP6_PORT_CLIENT),
                .in6.sin6_addr = IN6ADDR_ANY_INIT,
        };
        _cleanup_close_ int s = -1;
        int r, off = 0, on = 1;

        if (local_address)
                memcpy(&src.in6.sin6_addr, local_address,
                       sizeof(src.in6.sin6_addr));

        s = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
                   IPPROTO_UDP);
        if (s < 0)
                return -errno;

        r = setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, &pktinfo,
                       sizeof(pktinfo));
        if (r < 0)
                return -errno;

        r = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
        if (r < 0)
                return -errno;

        r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, sizeof(off));
        if (r < 0)
                return -errno;

        r = bind(s, &src.sa, sizeof(src.in6));
        if (r < 0)
                return -errno;

        r = s;
        s = -1;
        return r;
}

int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address,
                                  const void *packet, size_t len) {
        union sockaddr_union dest = {
                .in6.sin6_family = AF_INET6,
                .in6.sin6_port = htobe16(DHCP6_PORT_SERVER),
        };
        int r;

        assert(server_address);

        memcpy(&dest.in6.sin6_addr, server_address, sizeof(dest.in6.sin6_addr));

        r = sendto(s, packet, len, 0, &dest.sa, sizeof(dest.in6));
        if (r < 0)
                return -errno;

        return 0;
}
Ejemplo n.º 8
0
ssize_t
sctp_sendv(int sd,
    const struct iovec *iov, int iovcnt,
    struct sockaddr *addrs, int addrcnt,
    void *info, socklen_t infolen, unsigned int infotype,
    int flags)
{
	ssize_t ret;
	int i;
	socklen_t addr_len;
	struct msghdr msg;
	in_port_t port;
	struct sctp_sendv_spa *spa_info;
	struct cmsghdr *cmsg;
	char *cmsgbuf;
	struct sockaddr *addr;
	struct sockaddr_in *addr_in;
	struct sockaddr_in6 *addr_in6;

	if ((addrcnt < 0) ||
	    (iovcnt < 0) ||
	    ((addrs == NULL) && (addrcnt > 0)) ||
	    ((addrs != NULL) && (addrcnt == 0)) ||
	    ((iov == NULL) && (iovcnt > 0)) ||
	    ((iov != NULL) && (iovcnt == 0))) {
		errno = EINVAL;
		return (-1);
	}
	cmsgbuf = malloc(CMSG_SPACE(sizeof(struct sctp_sndinfo)) +
	    CMSG_SPACE(sizeof(struct sctp_prinfo)) +
	    CMSG_SPACE(sizeof(struct sctp_authinfo)) +
	    (size_t)addrcnt * CMSG_SPACE(sizeof(struct in6_addr)));
	if (cmsgbuf == NULL) {
		errno = ENOMEM;
		return (-1);
	}
	msg.msg_control = cmsgbuf;
	msg.msg_controllen = 0;
	cmsg = (struct cmsghdr *)cmsgbuf;
	switch (infotype) {
	case SCTP_SENDV_NOINFO:
		if ((infolen != 0) || (info != NULL)) {
			free(cmsgbuf);
			errno = EINVAL;
			return (-1);
		}
		break;
	case SCTP_SENDV_SNDINFO:
		if ((info == NULL) || (infolen < sizeof(struct sctp_sndinfo))) {
			free(cmsgbuf);
			errno = EINVAL;
			return (-1);
		}
		cmsg->cmsg_level = IPPROTO_SCTP;
		cmsg->cmsg_type = SCTP_SNDINFO;
		cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));
		memcpy(CMSG_DATA(cmsg), info, sizeof(struct sctp_sndinfo));
		msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));
		cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_sndinfo)));
		break;
	case SCTP_SENDV_PRINFO:
		if ((info == NULL) || (infolen < sizeof(struct sctp_prinfo))) {
			free(cmsgbuf);
			errno = EINVAL;
			return (-1);
		}
		cmsg->cmsg_level = IPPROTO_SCTP;
		cmsg->cmsg_type = SCTP_PRINFO;
		cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));
		memcpy(CMSG_DATA(cmsg), info, sizeof(struct sctp_prinfo));
		msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));
		cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_prinfo)));
		break;
	case SCTP_SENDV_AUTHINFO:
		if ((info == NULL) || (infolen < sizeof(struct sctp_authinfo))) {
			free(cmsgbuf);
			errno = EINVAL;
			return (-1);
		}
		cmsg->cmsg_level = IPPROTO_SCTP;
		cmsg->cmsg_type = SCTP_AUTHINFO;
		cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_authinfo));
		memcpy(CMSG_DATA(cmsg), info, sizeof(struct sctp_authinfo));
		msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_authinfo));
		cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_authinfo)));
		break;
	case SCTP_SENDV_SPA:
		if ((info == NULL) || (infolen < sizeof(struct sctp_sendv_spa))) {
			free(cmsgbuf);
			errno = EINVAL;
			return (-1);
		}
		spa_info = (struct sctp_sendv_spa *)info;
		if (spa_info->sendv_flags & SCTP_SEND_SNDINFO_VALID) {
			cmsg->cmsg_level = IPPROTO_SCTP;
			cmsg->cmsg_type = SCTP_SNDINFO;
			cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));
			memcpy(CMSG_DATA(cmsg), &spa_info->sendv_sndinfo, sizeof(struct sctp_sndinfo));
			msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));
			cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_sndinfo)));
		}
		if (spa_info->sendv_flags & SCTP_SEND_PRINFO_VALID) {
			cmsg->cmsg_level = IPPROTO_SCTP;
			cmsg->cmsg_type = SCTP_PRINFO;
			cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));
			memcpy(CMSG_DATA(cmsg), &spa_info->sendv_prinfo, sizeof(struct sctp_prinfo));
			msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));
			cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_prinfo)));
		}
		if (spa_info->sendv_flags & SCTP_SEND_AUTHINFO_VALID) {
			cmsg->cmsg_level = IPPROTO_SCTP;
			cmsg->cmsg_type = SCTP_AUTHINFO;
			cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_authinfo));
			memcpy(CMSG_DATA(cmsg), &spa_info->sendv_authinfo, sizeof(struct sctp_authinfo));
			msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_authinfo));
			cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_authinfo)));
		}
		break;
	default:
		free(cmsgbuf);
		errno = EINVAL;
		return (-1);
	}
	addr = addrs;
	msg.msg_name = NULL;
	msg.msg_namelen = 0;

	for (i = 0; i < addrcnt; i++) {
		switch (addr->sa_family) {
		case AF_INET:
			addr_len = (socklen_t) sizeof(struct sockaddr_in);
			addr_in = (struct sockaddr_in *)addr;
			if (addr_in->sin_len != addr_len) {
				free(cmsgbuf);
				errno = EINVAL;
				return (-1);
			}
			if (i == 0) {
				port = addr_in->sin_port;
			} else {
				if (port == addr_in->sin_port) {
					cmsg->cmsg_level = IPPROTO_SCTP;
					cmsg->cmsg_type = SCTP_DSTADDRV4;
					cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
					memcpy(CMSG_DATA(cmsg), &addr_in->sin_addr, sizeof(struct in_addr));
					msg.msg_controllen += CMSG_SPACE(sizeof(struct in_addr));
					cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct in_addr)));
				} else {
					free(cmsgbuf);
					errno = EINVAL;
					return (-1);
				}
			}
			break;
		case AF_INET6:
			addr_len = (socklen_t) sizeof(struct sockaddr_in6);
			addr_in6 = (struct sockaddr_in6 *)addr;
			if (addr_in6->sin6_len != addr_len) {
				free(cmsgbuf);
				errno = EINVAL;
				return (-1);
			}
			if (i == 0) {
				port = addr_in6->sin6_port;
			} else {
				if (port == addr_in6->sin6_port) {
					cmsg->cmsg_level = IPPROTO_SCTP;
					cmsg->cmsg_type = SCTP_DSTADDRV6;
					cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_addr));
					memcpy(CMSG_DATA(cmsg), &addr_in6->sin6_addr, sizeof(struct in6_addr));
					msg.msg_controllen += CMSG_SPACE(sizeof(struct in6_addr));
					cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct in6_addr)));
				} else {
					free(cmsgbuf);
					errno = EINVAL;
					return (-1);
				}
			}
			break;
		default:
			free(cmsgbuf);
			errno = EINVAL;
			return (-1);
		}
		if (i == 0) {
			msg.msg_name = addr;
			msg.msg_namelen = addr_len;
		}
		addr = (struct sockaddr *)((caddr_t)addr + addr_len);
	}
	if (msg.msg_controllen == 0) {
		msg.msg_control = NULL;
	}
	msg.msg_iov = (struct iovec *)iov;
	msg.msg_iovlen = iovcnt;
	msg.msg_flags = 0;
	ret = sendmsg(sd, &msg, flags);
	free(cmsgbuf);
	return (ret);
}
Ejemplo n.º 9
0
ssize_t
sctp_sendmsg(int s,
    const void *data,
    size_t len,
    const struct sockaddr *to,
    socklen_t tolen,
    uint32_t ppid,
    uint32_t flags,
    uint16_t stream_no,
    uint32_t timetolive,
    uint32_t context)
{
#ifdef SYS_sctp_generic_sendmsg
	struct sctp_sndrcvinfo sinfo;

	memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
	sinfo.sinfo_ppid = ppid;
	sinfo.sinfo_flags = flags;
	sinfo.sinfo_stream = stream_no;
	sinfo.sinfo_timetolive = timetolive;
	sinfo.sinfo_context = context;
	sinfo.sinfo_assoc_id = 0;
	return (syscall(SYS_sctp_generic_sendmsg, s,
	    data, len, to, tolen, &sinfo, 0));
#else
	ssize_t sz;
	struct msghdr msg;
	struct sctp_sndrcvinfo *s_info;
	struct iovec iov;
	char controlVector[SCTP_CONTROL_VEC_SIZE_RCV];
	struct cmsghdr *cmsg;
	struct sockaddr *who = NULL;
	union {
		struct sockaddr_in in;
		struct sockaddr_in6 in6;
	}     addr;

	if ((tolen > 0) &&
	    ((to == NULL) || (tolen < sizeof(struct sockaddr)))) {
		errno = EINVAL;
		return (-1);
	}
	if (to && (tolen > 0)) {
		if (to->sa_family == AF_INET) {
			if (tolen != sizeof(struct sockaddr_in)) {
				errno = EINVAL;
				return (-1);
			}
			if ((to->sa_len > 0) &&
			    (to->sa_len != sizeof(struct sockaddr_in))) {
				errno = EINVAL;
				return (-1);
			}
			memcpy(&addr, to, sizeof(struct sockaddr_in));
			addr.in.sin_len = sizeof(struct sockaddr_in);
		} else if (to->sa_family == AF_INET6) {
			if (tolen != sizeof(struct sockaddr_in6)) {
				errno = EINVAL;
				return (-1);
			}
			if ((to->sa_len > 0) &&
			    (to->sa_len != sizeof(struct sockaddr_in6))) {
				errno = EINVAL;
				return (-1);
			}
			memcpy(&addr, to, sizeof(struct sockaddr_in6));
			addr.in6.sin6_len = sizeof(struct sockaddr_in6);
		} else {
			errno = EAFNOSUPPORT;
			return (-1);
		}
		who = (struct sockaddr *)&addr;
	}
	iov.iov_base = (char *)data;
	iov.iov_len = len;

	if (who) {
		msg.msg_name = (caddr_t)who;
		msg.msg_namelen = who->sa_len;
	} else {
		msg.msg_name = (caddr_t)NULL;
		msg.msg_namelen = 0;
	}
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	msg.msg_control = (caddr_t)controlVector;

	cmsg = (struct cmsghdr *)controlVector;

	cmsg->cmsg_level = IPPROTO_SCTP;
	cmsg->cmsg_type = SCTP_SNDRCV;
	cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
	s_info = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);

	s_info->sinfo_stream = stream_no;
	s_info->sinfo_ssn = 0;
	s_info->sinfo_flags = flags;
	s_info->sinfo_ppid = ppid;
	s_info->sinfo_context = context;
	s_info->sinfo_assoc_id = 0;
	s_info->sinfo_timetolive = timetolive;
	errno = 0;
	msg.msg_controllen = cmsg->cmsg_len;
	sz = sendmsg(s, &msg, 0);
	return (sz);
#endif
}
Ejemplo n.º 10
0
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
int
pdcp_fifo_flush_sdus ()
{
//-----------------------------------------------------------------------------

  mem_block_t     *sdu = list_get_head (&pdcp_sdu_list);
  int             bytes_wrote = 0;
  int             pdcp_nb_sdu_sent = 0;
  uint8_t              cont = 1;
  int ret;


  while ((sdu) && (cont)) {

#ifdef USER_MODE
    // asjust the instance id when passing sdu to IP
    ((pdcp_data_ind_header_t *)(sdu->data))->inst = (((pdcp_data_ind_header_t *)(sdu->data))->inst >= NB_eNB_INST) ?
      ((pdcp_data_ind_header_t *)(sdu->data))->inst - NB_eNB_INST +oai_emulation.info.nb_enb_local - oai_emulation.info.first_ue_local :// UE
      ((pdcp_data_ind_header_t *)(sdu->data))->inst - oai_emulation.info.first_ue_local; // ENB
#else
    ((pdcp_data_ind_header_t *)(sdu->data))->inst = 0;
#endif

#ifdef PDCP_DEBUG
	  msg("[PDCP][INFO] PDCP->IP TTI %d INST %d: Preparing %d Bytes of data from rab %d to Nas_mesh\n",
	      Mac_rlc_xface->frame,
	      ((pdcp_data_ind_header_t *)(sdu->data))->inst,
	      ((pdcp_data_ind_header_t *)(sdu->data))->data_size,
	      ((pdcp_data_ind_header_t *)(sdu->data))->rb_id);
#endif //PDCP_DEBUG

    cont = 0;

    if (!pdcp_output_sdu_bytes_to_write) {
      if (!pdcp_output_header_bytes_to_write) {
        pdcp_output_header_bytes_to_write = sizeof (pdcp_data_ind_header_t);
      }

#ifndef USER_MODE
      bytes_wrote = rtf_put (PDCP2NAS_FIFO,
			     &(((uint8_t *) sdu->data)[sizeof (pdcp_data_ind_header_t) - pdcp_output_header_bytes_to_write]),
			     pdcp_output_header_bytes_to_write);

#else
#ifdef NAS_NETLINK
#ifdef LINUX
      memcpy(NLMSG_DATA(nas_nlh), &(((uint8_t *) sdu->data)[sizeof (pdcp_data_ind_header_t) - pdcp_output_header_bytes_to_write]),
                             pdcp_output_header_bytes_to_write);
      nas_nlh->nlmsg_len = pdcp_output_header_bytes_to_write;
#endif //LINUX
#endif //NAS_NETLINK

      bytes_wrote = pdcp_output_header_bytes_to_write;
#endif //USER_MODE


#ifdef PDCP_DEBUG
      msg("[PDCP][INFO] TTI %d Sent %d Bytes of header to Nas_mesh\n",
	  Mac_rlc_xface->frame,
	  bytes_wrote);
#endif //PDCP_DEBUG

      if (bytes_wrote > 0) {
        pdcp_output_header_bytes_to_write = pdcp_output_header_bytes_to_write - bytes_wrote;

        if (!pdcp_output_header_bytes_to_write) { // continue with sdu

          pdcp_output_sdu_bytes_to_write = ((pdcp_data_ind_header_t *) sdu->data)->data_size;

#ifndef USER_MODE
          bytes_wrote = rtf_put (PDCP2NAS_FIFO, &(sdu->data[sizeof (pdcp_data_ind_header_t)]), pdcp_output_sdu_bytes_to_write);
#else

#ifdef NAS_NETLINK
#ifdef LINUX
	  memcpy(NLMSG_DATA(nas_nlh)+sizeof(pdcp_data_ind_header_t), &(sdu->data[sizeof (pdcp_data_ind_header_t)]), pdcp_output_sdu_bytes_to_write);
	  nas_nlh->nlmsg_len += pdcp_output_sdu_bytes_to_write;
	  ret = sendmsg(nas_sock_fd,&nas_msg,0);
	  if (ret<0) {
	    msg("[PDCP_FIFOS] sendmsg returns %d\n",ret);
	    perror("error code:");
	    mac_xface->macphy_exit("");
	    break;
	  }
#endif // LINUX
#endif //NAS_NETLINK
	  bytes_wrote= pdcp_output_sdu_bytes_to_write;
#endif // USER_MODE

#ifdef PDCP_DEBUG
	  msg("[PDCP][INFO] PDCP->IP TTI %d INST %d: Sent %d Bytes of data from rab %d to Nas_mesh\n",
	      Mac_rlc_xface->frame,
	      ((pdcp_data_ind_header_t *)(sdu->data))->inst,
	      bytes_wrote,
	      ((pdcp_data_ind_header_t *)(sdu->data))->rb_id);
#endif //PDCP_DEBUG
          if (bytes_wrote > 0) {
            pdcp_output_sdu_bytes_to_write -= bytes_wrote;

            if (!pdcp_output_sdu_bytes_to_write) { // OK finish with this SDU
	      // msg("rb sent a sdu qos_sap %d\n",sapiP);

              list_remove_head (&pdcp_sdu_list);
              free_mem_block (sdu);
              cont = 1;
              pdcp_nb_sdu_sent += 1;
              sdu = list_get_head (&pdcp_sdu_list);
            }
          } else {
            msg ("[PDCP] RADIO->IP SEND SDU CONGESTION!\n");
          }
        } else {
          msg ("[PDCP] RADIO->IP SEND SDU CONGESTION!\n");
        }
      }
    } else {
      // continue writing sdu
#ifndef USER_MODE
      bytes_wrote = rtf_put (PDCP2NAS_FIFO,
                             (uint8_t *) (&(sdu->data[sizeof (pdcp_data_ind_header_t) + ((pdcp_data_ind_header_t *) sdu->data)->data_size - pdcp_output_sdu_bytes_to_write])),
                             pdcp_output_sdu_bytes_to_write);
#else  // USER_MODE
      bytes_wrote = pdcp_output_sdu_bytes_to_write;
#endif  // USER_MODE

      if (bytes_wrote > 0) {
        pdcp_output_sdu_bytes_to_write -= bytes_wrote;

        if (!pdcp_output_sdu_bytes_to_write) {     // OK finish with this SDU
          //PRINT_RB_SEND_OUTPUT_SDU ("[PDCP] RADIO->IP SEND SDU\n");
          list_remove_head (&pdcp_sdu_list);
          free_mem_block (sdu);
          cont = 1;
          pdcp_nb_sdu_sent += 1;
          sdu = list_get_head (&pdcp_sdu_list);
	  // msg("rb sent a sdu from rab\n");
        }
      }
    }
  }
#ifndef USER_MODE
    if ((pdcp_nb_sdu_sent)) {
      if ((pdcp_2_nas_irq > 0)) {
#ifdef PDCP_DEBUG
	msg("[PDCP][INFO] TTI %d : Trigger NAS RX interrupt\n",
	    Mac_rlc_xface->frame);
#endif //PDCP_DEBUG

           rt_pend_linux_srq (pdcp_2_nas_irq);
      } else {
        msg ("[PDCP] TTI %d: ERROR IF IP STACK WANTED : NOTIF PACKET(S) pdcp_2_nas_irq not initialized : %d\n",
	     Mac_rlc_xface->frame,
	     pdcp_2_nas_irq);
      }
    }
#endif  //USER_MODE

  return pdcp_nb_sdu_sent;
}
Ejemplo n.º 11
0
ssize_t
send_to_from(int fd, void *buf, size_t len, int flags,
		const struct sockaddr *to,
		const struct sockaddr *from,
		socklen_t tolen)
{
#ifndef IP_PKTINFO
	return sendto(fd, buf, len, flags, to, tolen);
#else
	struct iovec iov[1];
	struct msghdr msg;
	char cbuf[sizeof(struct in_pktinfo)
#if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO)
		| sizeof(struct in6_pktinfo) /* (a|b) is poor man's max(a,b) */
#endif
	];
	struct cmsghdr* cmsgptr;

	if (from->sa_family != AF_INET
#if ENABLE_FEATURE_IPV6
	 && from->sa_family != AF_INET6
#endif
	) {
		/* ANY local address */
		return sendto(fd, buf, len, flags, to, tolen);
	}

	/* man recvmsg and man cmsg is needed to make sense of code below */

	iov[0].iov_base = buf;
	iov[0].iov_len = len;

	memset(cbuf, 0, sizeof(cbuf));

	memset(&msg, 0, sizeof(msg));
	msg.msg_name = (void *)(struct sockaddr *)to; /* or compiler will annoy us */
	msg.msg_namelen = tolen;
	msg.msg_iov = iov;
	msg.msg_iovlen = 1;
	msg.msg_control = cbuf;
	msg.msg_controllen = sizeof(cbuf);
	msg.msg_flags = flags;

	cmsgptr = CMSG_FIRSTHDR(&msg);
	if (to->sa_family == AF_INET && from->sa_family == AF_INET) {
		struct in_pktinfo *pktptr;
		cmsgptr->cmsg_level = IPPROTO_IP;
		cmsgptr->cmsg_type = IP_PKTINFO;
		cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
		pktptr = (struct in_pktinfo *)(CMSG_DATA(cmsgptr));
		/* pktptr->ipi_ifindex = 0; -- already done by memset(cbuf...) */
		pktptr->ipi_spec_dst = ((struct sockaddr_in*)from)->sin_addr;
	}
#if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO)
	else if (to->sa_family == AF_INET6 && from->sa_family == AF_INET6) {
		struct in6_pktinfo *pktptr;
		cmsgptr->cmsg_level = IPPROTO_IPV6;
		cmsgptr->cmsg_type = IPV6_PKTINFO;
		cmsgptr->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo));
		pktptr = (struct in6_pktinfo *)(CMSG_DATA(cmsgptr));
		/* pktptr->ipi6_ifindex = 0; -- already done by memset(cbuf...) */
		pktptr->ipi6_addr = ((struct sockaddr_in6*)from)->sin6_addr;
	}
#endif
	return sendmsg(fd, &msg, flags);
#endif
}
Ejemplo n.º 12
0
/* Returns zero on success, less than zero on socket error and greater than
 * zero on other errors. */
static int conn_read_netlink (void)
{
  int fd;
  struct sockaddr_nl nladdr;
  struct nlreq req;
  struct msghdr msg;
  struct iovec iov;
  struct inet_diag_msg *r;
  char buf[8192];

  /* If this fails, it's likely a permission problem. We'll fall back to
   * reading this information from files below. */
  fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_INET_DIAG);
  if (fd < 0)
  {
    ERROR ("tcpconns plugin: conn_read_netlink: socket(AF_NETLINK, SOCK_RAW, "
	"NETLINK_INET_DIAG) failed: %s",
	sstrerror (errno, buf, sizeof (buf)));
    return (-1);
  }

  memset(&nladdr, 0, sizeof(nladdr));
  nladdr.nl_family = AF_NETLINK;

  memset(&req, 0, sizeof(req));
  req.nlh.nlmsg_len = sizeof(req);
  req.nlh.nlmsg_type = TCPDIAG_GETSOCK;
  /* NLM_F_ROOT: return the complete table instead of a single entry.
   * NLM_F_MATCH: return all entries matching criteria (not implemented)
   * NLM_F_REQUEST: must be set on all request messages */
  req.nlh.nlmsg_flags = NLM_F_ROOT | NLM_F_MATCH | NLM_F_REQUEST;
  req.nlh.nlmsg_pid = 0;
  /* The sequence_number is used to track our messages. Since netlink is not
   * reliable, we don't want to end up with a corrupt or incomplete old
   * message in case the system is/was out of memory. */
  req.nlh.nlmsg_seq = ++sequence_number;
  req.r.idiag_family = AF_INET;
  req.r.idiag_states = 0xfff;
  req.r.idiag_ext = 0;

  memset(&iov, 0, sizeof(iov));
  iov.iov_base = &req;
  iov.iov_len = sizeof(req);

  memset(&msg, 0, sizeof(msg));
  msg.msg_name = (void*)&nladdr;
  msg.msg_namelen = sizeof(nladdr);
  msg.msg_iov = &iov;
  msg.msg_iovlen = 1;

  if (sendmsg (fd, &msg, 0) < 0)
  {
    ERROR ("tcpconns plugin: conn_read_netlink: sendmsg(2) failed: %s",
	sstrerror (errno, buf, sizeof (buf)));
    close (fd);
    return (-1);
  }

  iov.iov_base = buf;
  iov.iov_len = sizeof(buf);

  while (1)
  {
    int status;
    struct nlmsghdr *h;

    memset(&msg, 0, sizeof(msg));
    msg.msg_name = (void*)&nladdr;
    msg.msg_namelen = sizeof(nladdr);
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;

    status = recvmsg(fd, (void *) &msg, /* flags = */ 0);
    if (status < 0)
    {
      if ((errno == EINTR) || (errno == EAGAIN))
        continue;

      ERROR ("tcpconns plugin: conn_read_netlink: recvmsg(2) failed: %s",
	  sstrerror (errno, buf, sizeof (buf)));
      close (fd);
      return (-1);
    }
    else if (status == 0)
    {
      close (fd);
      DEBUG ("tcpconns plugin: conn_read_netlink: Unexpected zero-sized "
	  "reply from netlink socket.");
      return (0);
    }

    h = (struct nlmsghdr*)buf;
    while (NLMSG_OK(h, status))
    {
      if (h->nlmsg_seq != sequence_number)
      {
	h = NLMSG_NEXT(h, status);
	continue;
      }

      if (h->nlmsg_type == NLMSG_DONE)
      {
	close (fd);
	return (0);
      }
      else if (h->nlmsg_type == NLMSG_ERROR)
      {
	struct nlmsgerr *msg_error;

	msg_error = NLMSG_DATA(h);
	WARNING ("tcpconns plugin: conn_read_netlink: Received error %i.",
	    msg_error->error);

	close (fd);
	return (1);
      }

      r = NLMSG_DATA(h);

      /* This code does not (need to) distinguish between IPv4 and IPv6. */
      conn_handle_ports (ntohs(r->id.idiag_sport),
	  ntohs(r->id.idiag_dport),
	  r->idiag_state);

      h = NLMSG_NEXT(h, status);
    } /* while (NLMSG_OK) */
  } /* while (1) */

  /* Not reached because the while() loop above handles the exit condition. */
  return (0);
} /* int conn_read_netlink */
Ejemplo n.º 13
0
Archivo: nl.c Proyecto: Altiscale/lxc
extern int netlink_rcv(struct nl_handler *handler, struct nlmsg *answer)
{
	int ret;
        struct sockaddr_nl nladdr;
        struct iovec iov = {
                .iov_base = answer->nlmsghdr,
                .iov_len = answer->nlmsghdr->nlmsg_len,
        };
	
	struct msghdr msg = {
                .msg_name = &nladdr,
                .msg_namelen = sizeof(nladdr),
                .msg_iov = &iov,
                .msg_iovlen = 1,
        };
	
        memset(&nladdr, 0, sizeof(nladdr));
        nladdr.nl_family = AF_NETLINK;
        nladdr.nl_pid = 0;
        nladdr.nl_groups = 0;

again:
	ret = recvmsg(handler->fd, &msg, 0);
	if (ret < 0) {
		if (errno == EINTR)
			goto again;
		return -errno;
	}

	if (!ret)
		return 0;

	if (msg.msg_flags & MSG_TRUNC &&
	    ret == answer->nlmsghdr->nlmsg_len)
		return -EMSGSIZE;

	return ret;
}

extern int netlink_send(struct nl_handler *handler, struct nlmsg *nlmsg)
{
        struct sockaddr_nl nladdr;
        struct iovec iov = {
                .iov_base = nlmsg->nlmsghdr,
                .iov_len = nlmsg->nlmsghdr->nlmsg_len,
        };
	struct msghdr msg = {
                .msg_name = &nladdr,
                .msg_namelen = sizeof(nladdr),
                .msg_iov = &iov,
                .msg_iovlen = 1,
        };
	int ret;
	
        memset(&nladdr, 0, sizeof(nladdr));
        nladdr.nl_family = AF_NETLINK;
        nladdr.nl_pid = 0;
        nladdr.nl_groups = 0;

	ret = sendmsg(handler->fd, &msg, 0);
	if (ret < 0)
		return -errno;

	return ret;
}

#ifndef NLMSG_ERROR
#define NLMSG_ERROR                0x2
#endif
extern int netlink_transaction(struct nl_handler *handler,
			       struct nlmsg *request, struct nlmsg *answer)
{
	int ret;

	ret = netlink_send(handler, request);
	if (ret < 0)
		return ret;

	ret = netlink_rcv(handler, answer);
	if (ret < 0)
		return ret;

	if (answer->nlmsghdr->nlmsg_type == NLMSG_ERROR) {
		struct nlmsgerr *err = (struct nlmsgerr*)NLMSG_DATA(answer->nlmsghdr);
		return err->error;
	}

	return 0;
}

extern int netlink_open(struct nl_handler *handler, int protocol)
{
	socklen_t socklen;
        int sndbuf = 32768;
        int rcvbuf = 32768;

        memset(handler, 0, sizeof(*handler));

        handler->fd = socket(AF_NETLINK, SOCK_RAW, protocol);
        if (handler->fd < 0)
                return -errno;

        if (setsockopt(handler->fd, SOL_SOCKET, SO_SNDBUF,
		       &sndbuf, sizeof(sndbuf)) < 0)
                return -errno;

        if (setsockopt(handler->fd, SOL_SOCKET, SO_RCVBUF,
		       &rcvbuf,sizeof(rcvbuf)) < 0)
                return -errno;

        memset(&handler->local, 0, sizeof(handler->local));
        handler->local.nl_family = AF_NETLINK;
        handler->local.nl_groups = 0;

        if (bind(handler->fd, (struct sockaddr*)&handler->local,
		 sizeof(handler->local)) < 0)
                return -errno;

        socklen = sizeof(handler->local);
        if (getsockname(handler->fd, (struct sockaddr*)&handler->local,
			&socklen) < 0)
                return -errno;

        if (socklen != sizeof(handler->local))
                return -EINVAL;

        if (handler->local.nl_family != AF_NETLINK)
                return -EINVAL;

	handler->seq = time(NULL);

        return 0;
}

extern int netlink_close(struct nl_handler *handler)
{
	close(handler->fd);
	handler->fd = -1;
	return 0;
}
Ejemplo n.º 14
0
bool
SharedPortClient::PassSocket(Sock *sock_to_pass,char const *shared_port_id,char const *requested_by)
{
#ifndef HAVE_SHARED_PORT
	dprintf(D_ALWAYS,"SharedPortClient::PassSocket() not supported on this platform\n");
	return false;
#elif WIN32
	if( !SharedPortIdIsValid(shared_port_id) ) {
		dprintf(D_ALWAYS,
				"ERROR: SharedPortClient: refusing to connect to shared port"
				"%s, because specified id is illegal! (%s)\n",
				requested_by, shared_port_id );
		return false;
	}

	MyString pipe_name;
	MyString socket_dir;

	SharedPortEndpoint::paramDaemonSocketDir(pipe_name);
	pipe_name.sprintf_cat("%c%s",DIR_DELIM_CHAR,shared_port_id);

	MyString requested_by_buf;
	if( !requested_by ) {
		requested_by_buf.sprintf(
			" as requested by %s", sock_to_pass->peer_description());
		requested_by = requested_by_buf.Value();
	}

	HANDLE child_pipe;
	
	while(true)
	{
		child_pipe = CreateFile(
			pipe_name.Value(),
			GENERIC_READ | GENERIC_WRITE,
			0,
			NULL,
			OPEN_EXISTING,
			0,
			NULL);

		if(child_pipe != INVALID_HANDLE_VALUE)
			break;

		if(GetLastError() == ERROR_PIPE_BUSY)
		{
			if (!WaitNamedPipe(pipe_name.Value(), 20000)) 
			{
				dprintf(D_ALWAYS, "ERROR: SharedPortClient: Wait for named pipe for sending socket timed out: %d\n", GetLastError());
				return false;
			}
		}
		else
		{
			dprintf(D_ALWAYS, "ERROR: SharedPortClient: Failed to open named pipe for sending socket: %d\n", GetLastError());
			return false;
		}
	}

	DWORD child_pid;
	DWORD read_bytes = 0;

	BOOL read_result = ReadFile(child_pipe, &child_pid, sizeof(DWORD), &read_bytes, NULL);

	if(!read_result)
	{
		DWORD last_error = GetLastError();
		dprintf(D_ALWAYS, "ERROR: SharedPortClient: Failed to read PID from pipe: %d.\n", last_error);
		CloseHandle(child_pipe);
		return false;
	}
	else
	{
		dprintf(D_FULLDEBUG, "SharedPortClient: Read PID: %d\n", child_pid);
	}

#if 1  // tj:2012 kill the else block later
	#pragma pack(push, 4)
	struct {
		int id; // condor commmand id
		WSAPROTOCOL_INFO wsa; // payload.
	} protocol_command;
	#pragma pack(pop)
	ZeroMemory(&protocol_command, sizeof(protocol_command));

	int dup_result = WSADuplicateSocket(sock_to_pass->get_file_desc(), child_pid, &protocol_command.wsa);
	if(dup_result == SOCKET_ERROR)
	{
		dprintf(D_ALWAYS, "ERROR: SharedPortClient: Failed to duplicate socket.\n");
		CloseHandle(child_pipe);
		return false;
	}
	protocol_command.id = SHARED_PORT_PASS_SOCK;
	BOOL write_result = WriteFile(child_pipe, &protocol_command, sizeof(protocol_command), &read_bytes, 0);
#else
	WSAPROTOCOL_INFO protocol_info;
	int dup_result = WSADuplicateSocket(sock_to_pass->get_file_desc(), child_pid, &protocol_info);
	if(dup_result == SOCKET_ERROR)
	{
		dprintf(D_ALWAYS, "ERROR: SharedPortClient: Failed to duplicate socket.\n");
		CloseHandle(child_pipe);
		return false;
	}
	int bufferSize = (sizeof(int) + sizeof(protocol_info));
	char *buffer = new char[bufferSize];
	ASSERT( buffer );
	int cmd = SHARED_PORT_PASS_SOCK;
	memcpy_s(buffer, sizeof(int), &cmd, sizeof(int));
	memcpy_s(buffer+sizeof(int), sizeof(protocol_info), &protocol_info, sizeof(protocol_info));
	BOOL write_result = WriteFile(child_pipe, buffer, bufferSize, &read_bytes, 0);

	delete [] buffer;
#endif
	if(!write_result)
	{
		dprintf(D_ALWAYS, "ERROR: SharedPortClient: Failed to send WSAPROTOCOL_INFO struct: %d\n", GetLastError());
		CloseHandle(child_pipe);
		return false;
	}
	dprintf(D_FULLDEBUG, "SharedPortClient: Wrote %d bytes to named pipe.\n", read_bytes);
	FlushFileBuffers(child_pipe);

	CloseHandle(child_pipe);

	return true;
#elif HAVE_SCM_RIGHTS_PASSFD
	if( !SharedPortIdIsValid(shared_port_id) ) {
		dprintf(D_ALWAYS,
				"ERROR: SharedPortClient: refusing to connect to shared port"
				"%s, because specified id is illegal! (%s)\n",
				requested_by, shared_port_id );
		return false;
	}

	MyString sock_name;
	MyString socket_dir;

	SharedPortEndpoint::paramDaemonSocketDir(sock_name);
	sock_name.sprintf_cat("%c%s",DIR_DELIM_CHAR,shared_port_id);

	MyString requested_by_buf;
	if( !requested_by ) {
		requested_by_buf.sprintf(
			" as requested by %s", sock_to_pass->peer_description());
		requested_by = requested_by_buf.Value();
	}

	struct sockaddr_un named_sock_addr;
	memset(&named_sock_addr, 0, sizeof(named_sock_addr));
	named_sock_addr.sun_family = AF_UNIX;
	strncpy(named_sock_addr.sun_path,sock_name.Value(),sizeof(named_sock_addr.sun_path)-1);
	if( strcmp(named_sock_addr.sun_path,sock_name.Value()) ) {
		dprintf(D_ALWAYS,"ERROR: SharedPortClient: full socket name%s is too long: %s\n",
				requested_by,
				sock_name.Value());
		return false;
	}

	int named_sock_fd = socket(AF_UNIX,SOCK_STREAM,0);
	if( named_sock_fd == -1 ) {
		dprintf(D_ALWAYS,"ERROR: SharedPortClient: failed to created named socket%s to connect to %s: %s\n",
				requested_by,
				shared_port_id,
				strerror(errno));
		return false;
	}

	ReliSock named_sock;
	named_sock.assign(named_sock_fd);
	named_sock.set_deadline( sock_to_pass->get_deadline() );

	priv_state orig_priv = set_root_priv();

	int connect_rc = connect(named_sock_fd,(struct sockaddr *)&named_sock_addr, SUN_LEN(&named_sock_addr));

	set_priv( orig_priv );

	if( connect_rc != 0 )
	{
		dprintf(D_ALWAYS,"SharedPortClient: failed to connect to %s%s: %s\n",
				sock_name.Value(),
				requested_by,
				strerror(errno));
		return false;
	}

	// Make certain SO_LINGER is Off.  This will result in the default
	// of closesocket returning immediately and the system attempts to 
	// send any unsent data.

	struct linger linger = {0,0};
	setsockopt(named_sock_fd, SOL_SOCKET, SO_LINGER, (char*)&linger, sizeof(linger));


	// Now prepare to pass the file descriptor
	// to the target process via named_sock.

	// First tell the target daemon that we are about to send the fd.
	named_sock.encode();
	if( !named_sock.put((int)SHARED_PORT_PASS_SOCK) ||
		!named_sock.end_of_message() )
	{
		dprintf(D_ALWAYS,"SharedPortClient: failed to send SHARED_PORT_PASS_FD to %s%s: %s\n",
				sock_name.Value(),
				requested_by,
				strerror(errno));
		return false;
	}


	// Now send the fd.

	// The documented way to initialize msghdr is to first set msg_controllen
	// to the size of the cmsghdr buffer and then after initializing
	// cmsghdr(s) to set it to the sum of CMSG_LEN() across all cmsghdrs.

	struct msghdr msg;
	char *buf = (char *) malloc(CMSG_SPACE(sizeof(int)));
	msg.msg_name = NULL;
	msg.msg_namelen = 0;
	msg.msg_control = buf;
	msg.msg_controllen = CMSG_SPACE(sizeof(int));
	msg.msg_flags = 0;

		// I have found that on MacOS X 10.5, we must send at least 1 byte,
		// or we get "Message too long" when trying to send 0-byte message.
	struct iovec iov[1];
	int junk = 0;
	iov[0].iov_base = &junk;
	iov[0].iov_len = 1;
	msg.msg_iov = iov;
	msg.msg_iovlen = 1;

	struct cmsghdr *cmsg = CMSG_FIRSTHDR((&msg));
	void *cmsg_data = CMSG_DATA(cmsg);
	ASSERT( cmsg && cmsg_data );

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

	int fd_to_pass = sock_to_pass->get_file_desc();
	memcpy(cmsg_data,&fd_to_pass,sizeof(int));

	msg.msg_controllen = cmsg->cmsg_len;

	if( sendmsg(named_sock.get_file_desc(),&msg,0) != 1 ) {
		dprintf(D_ALWAYS,"SharedPortClient: failed to pass socket to %s%s: %s\n",
				sock_name.Value(),
				requested_by,
				strerror(errno));
		free(buf);
		return false;
	}


		// The following final ACK appears to be necessary on Mac OS X
		// 10.5.8 (not sure of others).  It does not appear to be
		// necessary on any version of linux that I have tried.  The
		// observed problem that this solves is random failures where
		// the endpoint sees the passed socket close right away.  It
		// would be nice not to have an ACK, because then the whole
		// PassSocket() protocol would be non-blocking.  Since the
		// protocol is blocking with this ACK, it means we could
		// temporarily deadlock if the endpoint we are passing the
		// socket to is blocking on us on some other channel.  If
		// this becomes a problem, we can at least make the ACK only
		// happen on platforms that need it.  This protocol is always
		// just local to the machine, so need to worry about keeping
		// it compatible between different platforms.


	named_sock.decode();
	int status = 0;
	if( !named_sock.get(status) || !named_sock.end_of_message() ) {
		dprintf(D_ALWAYS,"SharedPortClient: failed to receive result for SHARED_PORT_PASS_FD to %s%s: %s\n",
				sock_name.Value(),
				requested_by,
				strerror(errno));

		free(buf);
		return false;
	}
	if( status != 0 ) {
		dprintf(D_ALWAYS,"SharedPortClient: received failure response for SHARED_PORT_PASS_FD to %s%s\n",
				sock_name.Value(),
				requested_by);
		free(buf);
		return false;
	}


	dprintf(D_FULLDEBUG,"SharedPortClient: passed socket to %s%s\n",
			sock_name.Value(),
			requested_by);
	free(buf);
	return true;
#else
#error HAVE_SHARED_PORT is defined, but no method for passing fds is enabled.
#endif
}
Ejemplo n.º 15
0
int main(int argc, char **argv)
{
    struct sockaddr_un sun;
    char buf[1024];
    int s, sunlen, ret, buflen;
    struct msghdr msg = { 0 };
    struct iovec iov;
    struct cmsghdr *cmsg;
    int myfd = 0;
    char cmsgbuf[CMSG_SPACE(sizeof myfd)];
    int *fdptr;

    if (argc != 3) {
        fprintf(stderr, "usage:  %s testfile address\n", argv[0]);
        exit(-1);
    }

    myfd = open(argv[1], O_RDWR);
    if (myfd < 0) {
        perror(argv[1]);
        exit(-1);
    }

    s = socket(AF_UNIX, SOCK_STREAM, 0);
    if (s < 0) {
        perror("socket");
        exit(-1);
    }

    sun.sun_family = AF_UNIX;
    strcpy(sun.sun_path, argv[2]);
    sunlen = strlen(sun.sun_path) + 1 + sizeof(short);
    ret = connect(s, (struct sockaddr *)&sun, sunlen);
    if (ret < 0) {
        perror("connect");
        exit(-1);
    }

    printf("client: Connected to server via %s\n", sun.sun_path);

    strcpy(buf, "hello world");
    buflen = strlen(buf)+1;
    iov.iov_base = buf;
    iov.iov_len = buflen;
    msg.msg_name = 0;
    msg.msg_namelen = 0;
    msg.msg_iov = &iov;
    msg.msg_iovlen = 1;
    msg.msg_control = cmsgbuf;
    msg.msg_controllen = sizeof cmsgbuf;
    cmsg = CMSG_FIRSTHDR(&msg);
    cmsg->cmsg_level = SOL_SOCKET;
    cmsg->cmsg_type = SCM_RIGHTS;
    cmsg->cmsg_len = CMSG_LEN(sizeof(int));
    fdptr = (int *)CMSG_DATA(cmsg);
    memcpy(fdptr, &myfd, sizeof(int));
    msg.msg_controllen = cmsg->cmsg_len;

    ret = sendmsg(s, &msg, 0);
    if (ret < 0) {
        perror("sendmsg");
        exit(-1);
    }
    printf("client: Sent descriptor, waiting for reply\n");

    buf[0] = 0;
    ret = recv(s, buf, sizeof(buf), 0);
    if (ret < 0) {
        perror("recv");
        exit(-1);
    }
    printf("client: Received reply, code=%d\n", buf[0]);
    if (buf[0])
        printf("client: ...This implies the descriptor was not received\n");
    else
        printf("client: ...This implies the descriptor was received\n");

    exit(buf[0]);
}
Ejemplo n.º 16
0
void
rauth(Job *job)
{
	sendmsg(job, "dns: authentication not required");
}
Ejemplo n.º 17
0
int	DL_send( channel chan, int32 address, int16 port, sys_scatter *scat )
{

#ifndef ARCH_SCATTER_NONE
        struct	msghdr		msg;
#else	/* ARCH_SCATTER_NONE */
        char	pseudo_scat[MAX_PACKET_SIZE];
#endif	/* ARCH_SCATTER_NONE */
	
	struct  sockaddr_in	soc_addr;
	struct timeval 		select_delay = { 0, 10000 };
	int			ret;
	int			total_len;
	int			i;
	int			num_try;
        char                    *send_errormsg = NULL; /* fool compiler */

        /* Check that the scatter passed is small enough to be a valid system scatter */
        assert(scat->num_elements <= ARCH_SCATTER_SIZE);

        memset(&soc_addr, 0, sizeof(soc_addr));
	soc_addr.sin_family 	= AF_INET;
	soc_addr.sin_addr.s_addr= htonl(address);
	soc_addr.sin_port	= htons(port);

#ifdef HAVE_SIN_LEN_IN_STRUCT_SOCKADDR_IN
        soc_addr.sin_len       = sizeof(soc_addr);
#endif

#ifdef ARCH_PC_HOME
	soc_addr.sin_addr.s_addr= htonl(-1073741814);
#endif /* ARCH_PC_HOME */

#ifndef ARCH_SCATTER_NONE
        memset(&msg, 0, sizeof(msg));
	msg.msg_name 	= (caddr_t) &soc_addr;
	msg.msg_namelen = sizeof(soc_addr);
	msg.msg_iov	= (struct iovec *)scat->elements;
	msg.msg_iovlen	= scat->num_elements;
#endif /* ARCH_SCATTER_NONE */

#ifdef	ARCH_SCATTER_CONTROL
	msg.msg_controllen = 0;
#endif	/* ARCH_SCATTER_CONTROL */
#ifdef	ARCH_SCATTER_ACCRIGHTS
	msg.msg_accrightslen = 0;
#endif	/* ARCH_SCATTER_ACCRIGHTS */

	for( i=0, total_len=0; i < scat->num_elements; i++)
	{
#ifdef	ARCH_SCATTER_NONE
		memcpy( &pseudo_scat[total_len], scat->elements[i].buf, 
				scat->elements[i].len );
#endif	/* ARCH_SCATTER_NONE */
		total_len+=scat->elements[i].len;
	}
#if 0
#ifndef ARCH_SCATTER_NONE
        if( msg.msg_iovlen > 16)
        {
                Alarm(EXIT, "Too Big iovec of size %d\n", msg.msg_iovlen);
        }
#endif
#endif
	for( ret=-10, num_try=0; ret < 0 && num_try < 10; num_try++ )
	{
#ifndef	ARCH_SCATTER_NONE
		ret = sendmsg(chan, &msg, 0); 
#else	/* ARCH_SCATTER_NONE */
		ret = sendto(chan, pseudo_scat, total_len, 0,
			     (struct sockaddr *)&soc_addr, sizeof(soc_addr) );
#endif	/* ARCH_SCATTER_NONE */
		if(ret < 0) {
			/* delay for a short while */
                        send_errormsg = sock_strerror(sock_errno);
			Alarm( DATA_LINK, "DL_send: delaying after failure in send to " IPF ", ret is %d\n", IP(address), ret);
			select( 0, 0, 0, 0, &select_delay );
			select_delay.tv_sec = 0;
			select_delay.tv_usec = 10000;
		}
	}
	if (ret < 0)
	{		
        	for( i=0; i < scat->num_elements; i++)
		    Alarm( DATA_LINK, "DL_send: element[%d]: %d bytes\n",
			    i,scat->elements[i].len);
		Alarm( DATA_LINK, "DL_send: error: %s\n sending %d bytes on channel %d to address " IPF "\n",
                       send_errormsg, total_len,chan,IP(address) );
	}else if(ret < total_len){
		Alarm( DATA_LINK, "DL_send: partial sending %d out of %d\n",
			ret,total_len);
	}
	Alarm( DATA_LINK, "DL_send: sent a message of %d bytes to (" IPF ":%d) on channel %d\n",
		ret,IP(address),port,chan);

	return(ret);
}
Ejemplo n.º 18
0
/*
 *  don't flush till all the slaves are done
 */
void
rflush(Job *job)
{
	flushjob(job->request.oldtag);
	sendmsg(job, 0);
}
int
main(int argc, char *argv[])
{
    int data, sfd, opt, fd;
    ssize_t ns;
    Boolean useDatagramSocket;
    struct msghdr msgh;
    struct iovec iov;

    /* Allocate a char array of suitable size to hold the ancillary data.
       However, since this buffer is in reality a 'struct cmsghdr', use a
       union to ensure that it is aligned as required for that structure.
       Alternatively, we could allocate the buffer using malloc(), which
       returns a buffer that satisfies the strictest alignment
       requirements of any type. */

    union {
        char   buf[CMSG_SPACE(sizeof(int))];
                        /* Space large enough to hold an 'int' */
        struct cmsghdr align;
    } controlMsg;
    struct cmsghdr *cmsgp;      /* Pointer used to iterate through
                                   headers in ancillary data */

    /* Parse command-line options */

    useDatagramSocket = FALSE;

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

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

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

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

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

    /* The 'msg_name' field can be used to specify the address of the
       destination socket when sending a datagram. However, we do not
       need to use this field because we use connect() below, which sets
       a default outgoing address for datagrams. */

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

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

    msgh.msg_iov = &iov;
    msgh.msg_iovlen = 1;
    iov.iov_base = &data;
    iov.iov_len = sizeof(int);
    data = 12345;
    fprintf(stderr, "Sending data = %d\n", data);

    /* Set 'msgh' fields to describe the ancillary data buffer */

    msgh.msg_control = controlMsg.buf;
    msgh.msg_controllen = sizeof(controlMsg.buf);

    /* The control message buffer must be zero-initialized in order
       for the CMSG_NXTHDR() macro to work correctly. Although we
       don't need to use CMSG_NXTHDR() in this example (because
       there is only one block of ancillary data), we show this
       step to demonstrate best practice */

    memset(controlMsg.buf, 0, sizeof(controlMsg.buf));

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

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

    /* Connect to the peer socket */

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

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

    /* Send real plus ancillary data */

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

    fprintf(stderr, "sendmsg() returned %ld\n", (long) ns);

    exit(EXIT_SUCCESS);
}
Ejemplo n.º 20
0
void
rcreate(Job *job, Mfile *mf)
{
	USED(mf);
	sendmsg(job, "creation permission denied");
}
Ejemplo n.º 21
0
static void connect_try_next(struct dropbear_progress_connection *c) {
	struct addrinfo *r;
	int res = 0;
	int fastopen = 0;
#ifdef DROPBEAR_CLIENT_TCP_FAST_OPEN
	struct msghdr message;
#endif

	for (r = c->res_iter; r; r = r->ai_next)
	{
		dropbear_assert(c->sock == -1);

		c->sock = socket(c->res_iter->ai_family, c->res_iter->ai_socktype, c->res_iter->ai_protocol);
		if (c->sock < 0) {
			continue;
		}

		ses.maxfd = MAX(ses.maxfd, c->sock);
		set_sock_nodelay(c->sock);
		setnonblocking(c->sock);

#ifdef DROPBEAR_CLIENT_TCP_FAST_OPEN
		fastopen = (c->writequeue != NULL);

		if (fastopen) {
			memset(&message, 0x0, sizeof(message));
			message.msg_name = r->ai_addr;
			message.msg_namelen = r->ai_addrlen;
			/* 6 is arbitrary, enough to hold initial packets */
			unsigned int iovlen = 6; /* Linux msg_iovlen is a size_t */
			struct iovec iov[6];
			packet_queue_to_iovec(c->writequeue, iov, &iovlen);
			message.msg_iov = iov;
			message.msg_iovlen = iovlen;
			res = sendmsg(c->sock, &message, MSG_FASTOPEN);
			/* Returns EINPROGRESS if FASTOPEN wasn't available */
			if (res < 0) {
				if (errno != EINPROGRESS) {
					m_free(c->errstring);
					c->errstring = m_strdup(strerror(errno));
					/* Not entirely sure which kind of errors are normal - 2.6.32 seems to 
					return EPIPE for any (nonblocking?) sendmsg(). just fall back */
					TRACE(("sendmsg tcp_fastopen failed, falling back. %s", strerror(errno)));
					/* No kernel MSG_FASTOPEN support. Fall back below */
					fastopen = 0;
					/* Set to NULL to avoid trying again */
					c->writequeue = NULL;
				}
			} else {
				packet_queue_consume(c->writequeue, res);
			}
		}
#endif

		/* Normal connect(), used as fallback for TCP fastopen too */
		if (!fastopen) {
			res = connect(c->sock, r->ai_addr, r->ai_addrlen);
		}

		if (res < 0 && errno != EINPROGRESS) {
			/* failure */
			m_free(c->errstring);
			c->errstring = m_strdup(strerror(errno));
			close(c->sock);
			c->sock = -1;
			continue;
		} else {
			/* new connection was successful, wait for it to complete */
			break;
		}
	}

	if (r) {
		c->res_iter = r->ai_next;
	} else {
		c->res_iter = NULL;
	}
}
Ejemplo n.º 22
0
void
rwrite(Job *job, Mfile *mf, Request *req)
{
	int rooted, wantsav, send;
	ulong cnt;
	char *err, *p, *atype;
	char errbuf[ERRMAX];

	err = nil;
	cnt = job->request.count;
	send = 1;
	if(mf->qid.type & QTDIR)
		err = "can't write directory";
	else if (job->request.offset != 0)
		err = "writing at non-zero offset";
	else if(cnt >= Maxrequest)
		err = "request too long";
	else
		send = 0;
	if (send)
		goto send;

	job->request.data[cnt] = 0;
	if(cnt > 0 && job->request.data[cnt-1] == '\n')
		job->request.data[cnt-1] = 0;

	/*
	 *  special commands
	 */
//	dnslog("rwrite got: %s", job->request.data);
	send = 1;
	if(strcmp(job->request.data, "age")==0){
		dnslog("dump, age & dump forced");
		dndump("/lib/ndb/dnsdump1");
		dnforceage();
		dndump("/lib/ndb/dnsdump2");
	} else if(strcmp(job->request.data, "debug")==0)
		debug ^= 1;
	else if(strcmp(job->request.data, "dump")==0)
		dndump("/lib/ndb/dnsdump");
	else if(strcmp(job->request.data, "poolcheck")==0)
		poolcheck(mainmem);
	else if(strcmp(job->request.data, "refresh")==0)
		needrefresh = 1;
	else if(strcmp(job->request.data, "restart")==0)
		stop = 1;
	else if(strcmp(job->request.data, "stats")==0)
		dnstats("/lib/ndb/dnsstats");
	else if(strncmp(job->request.data, "target ", 7)==0){
		target = atol(job->request.data + 7);
		dnslog("target set to %ld", target);
	} else
		send = 0;
	if (send)
		goto send;

	/*
	 *  kill previous reply
	 */
	mf->nrr = 0;
	mf->rr[0] = 0;

	/*
	 *  break up request (into a name and a type)
	 */
	atype = strchr(job->request.data, ' ');
	if(atype == 0){
		snprint(errbuf, sizeof errbuf, "illegal request %s",
			job->request.data);
		err = errbuf;
		goto send;
	} else
		*atype++ = 0;

	/*
	 *  tracing request
	 */
	if(strcmp(atype, "trace") == 0){
		if(trace)
			free(trace);
		if(*job->request.data)
			trace = estrdup(job->request.data);
		else
			trace = 0;
		goto send;
	}

	/* normal request: domain [type] */
	stats.qrecvd9p++;
	mf->type = rrtype(atype);
	if(mf->type < 0){
		snprint(errbuf, sizeof errbuf, "unknown type %s", atype);
		err = errbuf;
		goto send;
	}

	p = atype - 2;
	if(p >= job->request.data && *p == '.'){
		rooted = 1;
		*p = 0;
	} else
		rooted = 0;

	p = job->request.data;
	if(*p == '!'){
		wantsav = 1;
		p++;
	} else
		wantsav = 0;

	err = lookupqueryold(job, mf, req, errbuf, p, wantsav, rooted);
send:
	dncheck(0, 1);
	job->reply.count = cnt;
	sendmsg(job, err);
}
Ejemplo n.º 23
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 cmsghdr *cmsg;
	struct iovec iov;
	char cbuf[256];

#if !defined(IP_PKTINFO) && !defined(IP_SENDSRCADDR) && !defined(IPV6_PKTINFO)
	/*
	 *	If the sendmsg() flags aren't defined, fall back to
	 *	using sendto().
	 */
	from = NULL;
#endif

	/*
	 *	Catch the case where the caller passes invalid arguments.
	 */
	if (!from || (fromlen == 0) || (from->sa_family == AF_UNSPEC)) {
		return sendto(s, buf, len, flags, to, tolen);
	}

	/* Set up iov and msgh structures. */
	memset(&msgh, 0, sizeof(struct msghdr));
	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 (from->sa_family == AF_INET) {
#if !defined(IP_PKTINFO) && !defined(IP_SENDSRCADDR)
		return sendto(s, buf, len, flags, to, tolen);
#else
		struct sockaddr_in *s4 = (struct sockaddr_in *) from;

#  ifdef IP_PKTINFO
		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 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	/* IP_PKTINFO or IP_SENDSRCADDR */
	}

#ifdef AF_INET6
	else if (from->sa_family == AF_INET6) {
#  if !defined(IPV6_PKTINFO)
		return sendto(s, buf, len, flags, to, tolen);
#  else
		struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) from;

		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 */
	}
#endif

	/*
	 *	Unknown address family.
	 */
	else {
		errno = EINVAL;
		return -1;
	}

	return sendmsg(s, &msgh, flags);
}
Ejemplo n.º 24
0
void
rclunk(Job *job, Mfile *mf)
{
	freefid(mf);
	sendmsg(job, 0);
}
void test_msg_dgram(const struct socket_test_info *info)
{
	int rc;
	int src;
	int dst;
	struct sockaddr_storage addr;
	struct iovec iov[3];
	struct msghdr msg1;
	struct msghdr msg2;
	char buf1[BUFSIZE];
	char buf2[BUFSIZE];
	char buf3[BUFSIZE];

	debug("entering test_msg_dgram");

	info->callback_cleanup();

	src = socket(info->domain, SOCK_DGRAM, 0);
	if (src == -1) {
		test_fail("socket");
	}

	dst = socket(info->domain, SOCK_DGRAM, 0);
	if (dst == -1) {
		test_fail("socket");
	}

	rc = bind(src, info->serveraddr2, info->serveraddr2len);
	if (rc == -1) {
		test_fail("bind");
	}

	assert(info->clientaddrlen <= sizeof(addr));
	memcpy(&addr, info->clientaddr, info->clientaddrlen);

	rc = bind(dst, info->serveraddr, info->serveraddrlen);
	if (rc == -1) {
		test_fail("bind");
	}

	memset(&buf1, '\0', BUFSIZE);
	memset(&buf2, '\0', BUFSIZE);
	memset(&buf3, '\0', BUFSIZE);

	strncpy(buf1, "Minix ", BUFSIZE-1);
	strncpy(buf2, "is ", BUFSIZE-1);
	strncpy(buf3, "great!", BUFSIZE-1);

	iov[0].iov_base = buf1;
	iov[0].iov_len  = 6;
	iov[1].iov_base = buf2;
	iov[1].iov_len  = 3;
	iov[2].iov_base = buf3;
	iov[2].iov_len  = 32;

	memset(&msg1, '\0', sizeof(struct msghdr));
	msg1.msg_name = &addr;
	msg1.msg_namelen = info->clientaddrlen;
	msg1.msg_iov = iov;
	msg1.msg_iovlen = 3;
	msg1.msg_control = NULL;
	msg1.msg_controllen = 0;
	msg1.msg_flags = 0;

	rc = sendmsg(src, &msg1, 0);
	if (rc == -1) {
		test_fail("sendmsg");
	}

	memset(&buf1, '\0', BUFSIZE);
	memset(&buf2, '\0', BUFSIZE);

	iov[0].iov_base = buf1;
	iov[0].iov_len  = 9;
	iov[1].iov_base = buf2;
	iov[1].iov_len  = 32;

	memset(&addr, '\0', sizeof(addr));
	memset(&msg2, '\0', sizeof(struct msghdr));
	msg2.msg_name = &addr;
	msg2.msg_namelen = sizeof(addr);
	msg2.msg_iov = iov;
	msg2.msg_iovlen = 2;
	msg2.msg_control = NULL;
	msg2.msg_controllen = 0;
	msg2.msg_flags = 0;

	rc = recvmsg(dst, &msg2, 0);
	if (rc == -1) {
		test_fail("recvmsg");
	}

	if (strncmp(buf1, "Minix is ", 9) || strncmp(buf2, "great!", 6)) {
		test_fail("recvmsg");
	}

	info->callback_check_sockaddr((struct sockaddr *) &addr,
		msg2.msg_namelen, "recvmsg", 2);

	rc = close(dst);
	if (rc == -1) {
		test_fail("close");
	}

	rc = close(src);
	if (rc == -1) {
		test_fail("close");
	}

	info->callback_cleanup();
	debug("leaving test_msg_dgram");
}
Ejemplo n.º 26
0
void
rremove(Job *job, Mfile *mf)
{
	USED(mf);
	sendmsg(job, "remove permission denied");
}
Ejemplo n.º 27
0
ngx_int_t ngx_write_channel(ngx_socket_t s, ngx_channel_t *ch, size_t size,
    ngx_log_t *log)
{
    ssize_t             n;
    ngx_err_t           err;
    struct iovec        iov[1];
    struct msghdr       msg;

#if (NGX_HAVE_MSGHDR_MSG_CONTROL)
    union {
        struct cmsghdr  cm;
        char            space[CMSG_SPACE(sizeof(int))];
    } cmsg;

    if (ch->fd == -1) {
        msg.msg_control = NULL;
        msg.msg_controllen = 0;

    } else {
        msg.msg_control = (caddr_t) &cmsg;
        msg.msg_controllen = sizeof(cmsg);

        cmsg.cm.cmsg_len = CMSG_LEN(sizeof(int));
        cmsg.cm.cmsg_level = SOL_SOCKET;
        cmsg.cm.cmsg_type = SCM_RIGHTS;

        /*
         * We have to use ngx_memcpy() instead of simple
         *   *(int *) CMSG_DATA(&cmsg.cm) = ch->fd;
         * because some gcc 4.4 with -O2/3/s optimization issues the warning:
         *   dereferencing type-punned pointer will break strict-aliasing rules
         *
         * Fortunately, gcc with -O1 compiles this ngx_memcpy()
         * in the same simple assignment as in the code above
         */

        ngx_memcpy(CMSG_DATA(&cmsg.cm), &ch->fd, sizeof(int));
    }

    msg.msg_flags = 0;

#else

    if (ch->fd == -1) {
        msg.msg_accrights = NULL;
        msg.msg_accrightslen = 0;
    } else {
        msg.msg_accrights = (caddr_t) &ch->fd;
        msg.msg_accrightslen = sizeof(int);
    }

#endif

    iov[0].iov_base = (char *) ch;
    iov[0].iov_len = size;

    msg.msg_name = NULL;
    msg.msg_namelen = 0;
    msg.msg_iov = iov;
    msg.msg_iovlen = 1;

    n = sendmsg(s, &msg, 0);
    if (n == -1) {
        err = ngx_errno;
        if (err == NGX_EAGAIN) {
            return NGX_AGAIN;
        }

        ngx_log_error(NGX_LOG_ALERT, log, err, "sendmsg() failed");
        return NGX_ERROR;
    }

    return NGX_OK;
}
Ejemplo n.º 28
0
void
rwstat(Job *job, Mfile *mf)
{
	USED(mf);
	sendmsg(job, "wstat permission denied");
}
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.

}
Ejemplo n.º 30
0
/*
 * Simulate a blocking sendmsg on the non-blocking socket.
 * It's non blocking because it was set that way for recvmsg.
 */
int
rxi_Sendmsg(osi_socket socket, struct msghdr *msg_p, int flags)
{
    fd_set *sfds = (fd_set *) 0;
    while (sendmsg(socket, msg_p, flags) == -1) {
	int err;
	if (rx_stats_active)
	    rx_atomic_inc(&rx_stats.sendSelects);

	if (!sfds) {
	    if (!(sfds = IOMGR_AllocFDSet())) {
		(osi_Msg "rx failed to alloc fd_set: ");
		perror("rx_sendmsg");
		return -1;
	    }
	    FD_SET(socket, sfds);
	}
#if defined(HAVE_LINUX_ERRQUEUE_H) && defined(ADAPT_PMTU)
	while((rxi_HandleSocketError(socket)) > 0)
	  ;
#endif
#ifdef AFS_NT40_ENV
	if (WSAGetLastError())
#elif defined(AFS_LINUX22_ENV)
	/* linux unfortunately returns ECONNREFUSED if the target port
	 * is no longer in use */
	/* and EAGAIN if a UDP checksum is incorrect */
	if (errno != EWOULDBLOCK && errno != ENOBUFS && errno != ECONNREFUSED
	    && errno != EAGAIN)
#else
	if (errno != EWOULDBLOCK && errno != ENOBUFS)
#endif
	{
	    (osi_Msg "rx failed to send packet: ");
	    perror("rx_sendmsg");
#ifndef AFS_NT40_ENV
            if (errno > 0)
              return -errno;
#else
            if (WSAGetLastError() > 0)
              return -WSAGetLastError();
#endif
	    return -1;
	}
	while ((err = select(
#ifdef AFS_NT40_ENV
                             0,
#else
                             socket + 1,
#endif
                             0, sfds, 0, 0)) != 1) {
	    if (err >= 0 || errno != EINTR)
		osi_Panic("rxi_sendmsg: select error %d.%d", err, errno);
	    FD_ZERO(sfds);
	    FD_SET(socket, sfds);
	}
    }
    if (sfds)
	IOMGR_FreeFDSet(sfds);
    return 0;
}