Beispiel #1
0
static void test_extra_filter(const struct test_params p)
{
	struct sockaddr * const addr =
		new_any_sockaddr(p.recv_family, p.recv_port);
	int fd1, fd2, opt;

	fprintf(stderr, "Testing too many filters...\n");
	fd1 = socket(p.recv_family, p.protocol, 0);
	if (fd1 < 0)
		error(1, errno, "failed to create socket 1");
	fd2 = socket(p.recv_family, p.protocol, 0);
	if (fd2 < 0)
		error(1, errno, "failed to create socket 2");

	opt = 1;
	if (setsockopt(fd1, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)))
		error(1, errno, "failed to set SO_REUSEPORT on socket 1");
	if (setsockopt(fd2, SOL_SOCKET, SO_REUSEPORT, &opt, sizeof(opt)))
		error(1, errno, "failed to set SO_REUSEPORT on socket 2");

	attach_ebpf(fd1, 10);
	attach_ebpf(fd2, 10);

	if (bind(fd1, addr, sockaddr_size()))
		error(1, errno, "failed to bind recv socket 1");

	if (!bind(fd2, addr, sockaddr_size()) && errno != EADDRINUSE)
		error(1, errno, "bind socket 2 should fail with EADDRINUSE");

	free(addr);
}
Beispiel #2
0
Datei: tftp.c Projekt: 8tab/qemu
static int tftp_session_allocate(Slirp *slirp, struct sockaddr_storage *srcsas,
                                 struct tftp_t *tp)
{
  struct tftp_session *spt;
  int k;

  for (k = 0; k < TFTP_SESSIONS_MAX; k++) {
    spt = &slirp->tftp_sessions[k];

    if (!tftp_session_in_use(spt))
        goto found;

    /* sessions time out after 5 inactive seconds */
    if ((int)(curtime - spt->timestamp) > 5000) {
        tftp_session_terminate(spt);
        goto found;
    }
  }

  return -1;

 found:
  memset(spt, 0, sizeof(*spt));
  memcpy(&spt->client_addr, srcsas, sockaddr_size(srcsas));
  spt->fd = -1;
  spt->block_size = 512;
  spt->client_port = tp->udp.uh_sport;
  spt->slirp = slirp;

  tftp_session_update(spt);

  return k;
}
Beispiel #3
0
static void build_recv_group(const struct test_params p, int fd[], uint16_t mod,
			     void (*attach_bpf)(int, uint16_t))
{
	struct sockaddr * const addr =
		new_any_sockaddr(p.recv_family, p.recv_port);
	int i, opt;

	for (i = 0; i < p.recv_socks; ++i) {
		fd[i] = socket(p.recv_family, p.protocol, 0);
		if (fd[i] < 0)
			error(1, errno, "failed to create recv %d", i);

		opt = 1;
		if (setsockopt(fd[i], SOL_SOCKET, SO_REUSEPORT, &opt,
			       sizeof(opt)))
			error(1, errno, "failed to set SO_REUSEPORT on %d", i);

		if (i == 0)
			attach_bpf(fd[i], mod);

		if (bind(fd[i], addr, sockaddr_size()))
			error(1, errno, "failed to bind recv socket %d", i);

		if (p.protocol == SOCK_STREAM) {
			opt = 4;
			if (setsockopt(fd[i], SOL_TCP, TCP_FASTOPEN, &opt,
				       sizeof(opt)))
				error(1, errno,
				      "failed to set TCP_FASTOPEN on %d", i);
			if (listen(fd[i], p.recv_socks * 10))
				error(1, errno, "failed to listen on socket");
		}
	}
	free(addr);
}
Beispiel #4
0
/**************************************************************************
  Try to connect to a server (get_server_address() must be called first!):
   - try to create a TCP socket and connect it to `server_addr'
   - if successful:
	  - start monitoring the socket for packets from the server
	  - send a "login request" packet to the server
      and - return 0
   - if unable to create the connection, close the socket, put an error
     message in ERRBUF and return the Unix error code (ie., errno, which
     will be non-zero).
**************************************************************************/
static int try_to_connect(const char *username, char *errbuf, int errbufsize)
{
  close_socket_set_callback(close_socket_callback);

  /* connection in progress? wait. */
  if (client.conn.used) {
    (void) mystrlcpy(errbuf, _("Connection in progress."), errbufsize);
    return -1;
  }
  
  if ((client.conn.sock = socket(server_addr.saddr.sa_family,
                                 SOCK_STREAM, 0)) == -1) {
    (void) mystrlcpy(errbuf, fc_strerror(fc_get_errno()), errbufsize);
    return -1;
  }

  if (fc_connect(client.conn.sock, &server_addr.saddr,
                 sockaddr_size(&server_addr)) == -1) {
    (void) mystrlcpy(errbuf, fc_strerror(fc_get_errno()), errbufsize);
    fc_closesocket(client.conn.sock);
    client.conn.sock = -1;
#ifdef HAVE_WINSOCK
    return -1;
#else
    return errno;
#endif
  }

  make_connection(client.conn.sock, username);

  return 0;
}
Beispiel #5
0
/*
 * sendto() a socket
 */
int
sosendto(struct socket *so, struct mbuf *m)
{
	int ret;
	struct sockaddr_storage addr;

	DEBUG_CALL("sosendto");
	DEBUG_ARG("so = %p", so);
	DEBUG_ARG("m = %p", m);

	addr = so->fhost.ss;
	DEBUG_CALL(" sendto()ing)");
	sotranslate_out(so, &addr);

	/* Don't care what port we get */
	ret = sendto(so->s, m->m_data, m->m_len, 0,
		     (struct sockaddr *)&addr, sockaddr_size(&addr));
	if (ret < 0)
		return -1;

	/*
	 * Kill the socket if there's no reply in 4 minutes,
	 * but only if it's an expirable socket
	 */
	if (so->so_expire)
		so->so_expire = curtime + SO_EXPIRE;
	so->so_state &= SS_PERSISTENT_MASK;
	so->so_state |= SS_ISFCONNECTED; /* So that it gets select()ed */
	return 0;
}
Beispiel #6
0
static void test_filter_no_reuseport(const struct test_params p)
{
	struct sockaddr * const addr =
		new_any_sockaddr(p.recv_family, p.recv_port);
	const char bpf_license[] = "GPL";
	struct bpf_insn ecode[] = {
		{ BPF_ALU64 | BPF_MOV | BPF_K, BPF_REG_0, 0, 0, 10 },
		{ BPF_JMP | BPF_EXIT, 0, 0, 0, 0 }
	};
	struct sock_filter ccode[] = {{ BPF_RET | BPF_A, 0, 0, 0 }};
	union bpf_attr eprog;
	struct sock_fprog cprog;
	int fd, bpf_fd;

	fprintf(stderr, "Testing filters on non-SO_REUSEPORT socket...\n");

	memset(&eprog, 0, sizeof(eprog));
	eprog.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
	eprog.insn_cnt = ARRAY_SIZE(ecode);
	eprog.insns = (unsigned long) &ecode;
	eprog.license = (unsigned long) &bpf_license;
	eprog.kern_version = 0;

	memset(&cprog, 0, sizeof(cprog));
	cprog.len = ARRAY_SIZE(ccode);
	cprog.filter = ccode;


	bpf_fd = syscall(__NR_bpf, BPF_PROG_LOAD, &eprog, sizeof(eprog));
	if (bpf_fd < 0)
		error(1, errno, "ebpf error");
	fd = socket(p.recv_family, p.protocol, 0);
	if (fd < 0)
		error(1, errno, "failed to create socket 1");

	if (bind(fd, addr, sockaddr_size()))
		error(1, errno, "failed to bind recv socket 1");

	errno = 0;
	if (!setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &bpf_fd,
			sizeof(bpf_fd)) || errno != EINVAL)
		error(1, errno, "setsockopt should have returned EINVAL");

	errno = 0;
	if (!setsockopt(fd, SOL_SOCKET, SO_ATTACH_REUSEPORT_CBPF, &cprog,
		       sizeof(cprog)) || errno != EINVAL)
		error(1, errno, "setsockopt should have returned EINVAL");

	free(addr);
}
Beispiel #7
0
static void send_from(struct test_params p, uint16_t sport, char *buf,
		      size_t len)
{
	struct sockaddr * const saddr = new_any_sockaddr(p.send_family, sport);
	struct sockaddr * const daddr =
		new_loopback_sockaddr(p.send_family, p.recv_port);
	const int fd = socket(p.send_family, p.protocol, 0), one = 1;

	if (fd < 0)
		error(1, errno, "failed to create send socket");

	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)))
		error(1, errno, "failed to set reuseaddr");

	if (bind(fd, saddr, sockaddr_size()))
		error(1, errno, "failed to bind send socket");

	if (sendto(fd, buf, len, MSG_FASTOPEN, daddr, sockaddr_size()) < 0)
		error(1, errno, "failed to send message");

	close(fd);
	free(saddr);
	free(daddr);
}
Beispiel #8
0
/**************************************************************************
  Try to connect to a server (get_server_address() must be called first!):
   - try to create a TCP socket and connect it to `names'
   - if successful:
	  - start monitoring the socket for packets from the server
	  - send a "login request" packet to the server
      and - return 0
   - if unable to create the connection, close the socket, put an error
     message in ERRBUF and return the Unix error code (ie., errno, which
     will be non-zero).
**************************************************************************/
static int try_to_connect(const char *username, char *errbuf, int errbufsize)
{
  int i;
  int sock = -1;

  connections_set_close_callback(client_conn_close_callback);

  /* connection in progress? wait. */
  if (client.conn.used) {
    (void) fc_strlcpy(errbuf, _("Connection in progress."), errbufsize);
    return -1;
  }

  /* Try all (IPv4, IPv6, ...) addresses until we have a connection. */
  sock = -1;
  for (i = 0; i < name_count; i++) {
    if ((sock = socket(names[i].saddr.sa_family, SOCK_STREAM, 0)) == -1) {
      /* Probably EAFNOSUPPORT or EPROTONOSUPPORT. */
      continue;
    }

    if (fc_connect(sock, &names[i].saddr,
                   sockaddr_size(&names[i])) == -1) {
      fc_closesocket(sock);
      sock = -1;
      continue;
    } else {
      /* We have a connection! */
      break;
    }
  }

  client.conn.sock = sock;
  if (client.conn.sock == -1) {
    fc_errno err = fc_get_errno(); /* Save errno value before calling anything */

    (void) fc_strlcpy(errbuf, fc_strerror(err), errbufsize);
#ifdef HAVE_WINSOCK
    return -1;
#else
    return err;
#endif /* HAVE_WINSOCK */
  }

  make_connection(client.conn.sock, username);

  return 0;
}
Beispiel #9
0
/****************************************************************************
  Begin a metaserver scan for servers.  This just initiates the connection
  to the metaserver; later get_meta_server_list should be called whenever
  the socket has data pending to read and parse it.

  Returns FALSE on error (in which case errbuf will contain an error
  message).
****************************************************************************/
static bool begin_metaserver_scan(struct server_scan *scan)
{
  union fc_sockaddr addr;
  int s;

  scan->meta.urlpath = fc_lookup_httpd(scan->meta.name, &scan->meta.port,
				       metaserver);
  if (!scan->meta.urlpath) {
    scan->error_func(scan,
                     _("Invalid $http_proxy or metaserver value, must "
                       "start with 'http://'"));
    return FALSE;
  }

  if (!net_lookup_service(scan->meta.name, scan->meta.port, &addr, FALSE)) {
    scan->error_func(scan, _("Failed looking up metaserver's host"));
    return FALSE;
  }
  
  if ((s = socket(addr.saddr.sa_family, SOCK_STREAM, 0)) == -1) {
    scan->error_func(scan, fc_strerror(fc_get_errno()));
    return FALSE;
  }

  fc_nonblock(s);
  
  if (fc_connect(s, &addr.saddr, sockaddr_size(&addr)) == -1) {
    if (errno == EINPROGRESS) {
      /* With non-blocking sockets this is the expected result. */
      scan->meta.state = META_CONNECTING;
      scan->sock = s;
    } else {
      fc_closesocket(s);
      scan->error_func(scan, fc_strerror(fc_get_errno()));
      return FALSE;
    }
  } else {
    /* Instant connection?  Whoa. */
    scan->sock = s;
    scan->meta.state = META_CONNECTING;
    meta_send_request(scan);
  }

  return TRUE;
}
Beispiel #10
0
/************************************************************************** 
  Finds the next (lowest) free port.
**************************************************************************/ 
int find_next_free_port(int starting_port)
{
  int port, s = socket(AF_INET, SOCK_STREAM, 0);

  for (port = starting_port;; port++) {
    union fc_sockaddr tmp;
    struct sockaddr_in *sock = &tmp.saddr_in4;

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

    sock->sin_family = AF_INET;
    sock->sin_port = htons(port);
    sock->sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(s, &tmp.saddr, sockaddr_size(&tmp)) == 0) {
      break;
    }
  }

  fc_closesocket(s);
  
  return port;
}
Beispiel #11
0
/************************************************************************** 
  Finds the next (lowest) free port.
**************************************************************************/ 
int find_next_free_port(int starting_port, enum fc_addr_family family)
{
  int port;
  int s;
  int gafamily;
  bool found = FALSE;

#ifndef IPV6_SUPPORT
  fc_assert(family == FC_ADDR_IPV4 || family == FC_ADDR_ANY);
#endif

  switch (family) {
   case FC_ADDR_IPV4:
     gafamily = AF_INET;
     break;
#ifdef IPV6_SUPPORT
   case FC_ADDR_IPV6:
     gafamily = AF_INET6;
     break;
#endif /* IPV6_SUPPORT */
   case FC_ADDR_ANY:
     gafamily = AF_UNSPEC;
     break;
   default:
     fc_assert(FALSE);

     return -1;
  }

  s = socket(gafamily, SOCK_STREAM, 0);

  for (port = starting_port; !found ; port++) {
    /* HAVE_GETADDRINFO implies IPv6 support */
#ifdef HAVE_GETADDRINFO
    struct addrinfo hints;
    int err;
    char servname[8];
    struct addrinfo *res;

    fc_snprintf(servname, sizeof(servname), "%d", port);

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = gafamily;
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_flags = AI_PASSIVE | FC_AI_NUMERICSERV;

    err = getaddrinfo(NULL, servname, &hints, &res);
    if (!err) {
      struct addrinfo *current = res;

      while (current != NULL && !found) {
        if (bind(s, current->ai_addr, current->ai_addrlen) == 0) {
          found = TRUE;
        }
        current = current->ai_next;
      }

      freeaddrinfo(res);
    }
#else /* HAVE_GETADDRINFO */
    union fc_sockaddr tmp;
    struct sockaddr_in *sock4;

    sock4 = &tmp.saddr_in4;
    memset(&tmp, 0, sizeof(tmp));
    sock4->sin_family = AF_INET;
    sock4->sin_port = htons(port);
    sock4->sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(s, &tmp.saddr, sockaddr_size(&tmp)) == 0) {
      found = TRUE;
    }
#endif /* HAVE_GETADDRINFO */
  }

  fc_closesocket(s);
  
  return port;
}
Beispiel #12
0
/************************************************************************** 
  Finds the next (lowest) free port.
**************************************************************************/ 
int find_next_free_port(int starting_port, int highest_port,
                        enum fc_addr_family family,
                        char *net_interface, bool not_avail_ok)
{
  int port;
  int s;
  int gafamily;
  bool found = FALSE;

#ifndef IPV6_SUPPORT
  fc_assert(family == FC_ADDR_IPV4 || family == FC_ADDR_ANY);
#endif

  switch (family) {
   case FC_ADDR_IPV4:
     gafamily = AF_INET;
     break;
#ifdef IPV6_SUPPORT
   case FC_ADDR_IPV6:
     gafamily = AF_INET6;
     break;
#endif /* IPV6_SUPPORT */
   case FC_ADDR_ANY:
     gafamily = AF_UNSPEC;
     break;
   default:
     fc_assert(FALSE);
     log_error("Port from unsupported address family requested!");

     return -1;
  }

  for (port = starting_port; !found && highest_port > port; port++) {
    /* HAVE_GETADDRINFO implies IPv6 support */
#ifdef HAVE_GETADDRINFO
    struct addrinfo hints;
    int err;
    char servname[8];
    struct addrinfo *res;

    fc_snprintf(servname, sizeof(servname), "%d", port);

    memset(&hints, 0, sizeof(hints));
    hints.ai_family = gafamily;
    hints.ai_socktype = SOCK_DGRAM;
    hints.ai_flags = AI_PASSIVE | FC_AI_NUMERICSERV;

    err = getaddrinfo(net_interface, servname, &hints, &res);
    if (!err) {
      struct addrinfo *current = res;
      bool unusable = FALSE;

      while (current != NULL && !unusable) {
        s = socket(current->ai_family, SOCK_STREAM, 0);

        if (s == -1) {
          log_error("socket(): %s", fc_strerror(fc_get_errno()));
        } else {
          if (bind(s, current->ai_addr, current->ai_addrlen) != 0) {
            if (!not_avail_ok || fc_get_errno() != EADDRNOTAVAIL) {
              unusable = TRUE;
            }
          }
        }
        current = current->ai_next;
        fc_closesocket(s);
      }

      freeaddrinfo(res);

      if (!unusable && res != NULL) {
        found = TRUE;
      }
    }
#else /* HAVE_GETADDRINFO */
    union fc_sockaddr tmp;
    struct sockaddr_in *sock4;

    s = socket(gafamily, SOCK_STREAM, 0);

    sock4 = &tmp.saddr_in4;
    memset(&tmp, 0, sizeof(tmp));
    sock4->sin_family = AF_INET;
    sock4->sin_port = htons(port);
    if (net_interface != NULL) {
#if defined(HAVE_INET_ATON)
      if (inet_aton(net_interface, &sock4->sin_addr) == 0) {
#else /* HAVE_INET_ATON */
      sock4->sin_addr.s_addr = inet_addr(net_interface);
      if (sock4->sin_addr.s_addr == INADDR_NONE) {
#endif /* HAVE_INET_ATON */
        struct hostent *hp;

        hp = gethostbyname(net_interface);
        if (hp == NULL) {
          log_error("No hostent for %s!", net_interface);

          return -1;
        }
        if (hp->h_addrtype != AF_INET) {
          log_error("Requested IPv4 address for %s, got something else! (%d)",
                    net_interface, hp->h_addrtype);

          return -1;
        }

        memcpy(&sock4->sin_addr, hp->h_addr, hp->h_length);
      }
    } else {
      sock4->sin_addr.s_addr = htonl(INADDR_ANY);
    }

    if (bind(s, &tmp.saddr, sockaddr_size(&tmp)) == 0) {
      found = TRUE;
    }

    fc_closesocket(s);
#endif /* HAVE_GETADDRINFO */
  }

  if (!found) {
    log_error("None of the ports %d - %d is available.",
              starting_port, highest_port);

    return -1;
  }

  /* Rollback the last increment from the loop, back to the port
   * number found to be free. */
  port--;

  return port;
}