Ejemplo n.º 1
0
/**
 * @return whether host can be kept as a valid contact
 */
bool
knode_is_usable(const knode_t *kn)
{
	knode_check(kn);

	if (!host_is_valid(kn->addr, kn->port))
		return FALSE;

	if (hostiles_is_bad(kn->addr))
		return FALSE;

	return TRUE;
}
Ejemplo n.º 2
0
/**
 * Tree message iterator to handle "NH" nodes and extract their IP:port.
 */
static void
g2_node_extract_nh(void *data, void *udata)
{
	const g2_tree_t *t = data;

	(void) udata;

	if (0 == strcmp("NH", g2_tree_name(t))) {
		host_addr_t addr;
		uint16 port;

		if (
			g2_node_parse_address(t, &addr, &port) &&
			host_is_valid(addr, port)
		) {
			hcache_add_caught(HOST_G2HUB, addr, port, "/KHL/NH");
		}
	}
}
Ejemplo n.º 3
0
/**
 * Extract the UDP IP:port from a /Q2/UDP and populate the search request info
 * if we have a valid address.
 */
static void
g2_node_extract_udp(const g2_tree_t *t, search_request_info_t *sri,
	const gnutella_node_t *n)
{
	const char *p;
	size_t paylen;

	p = g2_tree_node_payload(t, &paylen);

	/*
	 * Only handle if we have an IP:port entry.
	 * We only handle IPv4 because G2 does not support IPv6.
	 *
	 * We don't care about the presence of the query key because as G2 leaf,
	 * we only process /Q2 coming from our TCP-connected hubs, and they
	 * are in charge of validating it.  Now hubs may forward us /Q2 coming
	 * from neighbouring hubs and those won't have a query key, hence we
	 * need to handle payloads with no trailing 32-bit QK.
	 */

	if (6 == paylen || 10 == paylen) {	/* IPv4 + port (+ QK usually) */
		host_addr_t addr = host_addr_peek_ipv4(p);
		uint16 port = peek_le16(&p[4]);

		if (host_is_valid(addr, port)) {
			sri->addr = addr;
			sri->port = port;

			/*
			 * If the address is that of the node sending us the query,
			 * and it is not a UDP node, then we can deliver the hit
			 * back via the TCP connection we have, so no need to use OOB.
			 */

			if (n->port == port && host_addr_equiv(addr, n->gnet_addr))
				sri->oob = NODE_IS_UDP(n);
			else
				sri->oob = TRUE;
		}
	}
}
Ejemplo n.º 4
0
/**
 * Tree message iterator to handle "CH" nodes and extract their IP:port.
 */
static void
g2_node_extract_ch(void *data, void *udata)
{
	const g2_tree_t *t = data;

	(void) udata;

	if (0 == strcmp("CH", g2_tree_name(t))) {
		const char *payload;
		size_t paylen;

		payload = g2_tree_node_payload(t, &paylen);

		if (10 == paylen) {		/* IPv4:port + 32-bit timestamp */
			host_addr_t addr = host_addr_peek_ipv4(payload);
			uint16 port = peek_le16(&payload[4]);

			if (host_is_valid(addr, port) && !hostiles_is_bad(addr))
				guess_add_hub(addr, port);
		}
	}
}
Ejemplo n.º 5
0
/** Create a http site object.
 *
 * The function nth_site_create() allocates and initializes a web site
 * object. A web site object can be either
 * - a primary http server (@a parent is NULL),
 * - a virtual http server (@a address contains hostpart), or
 * - a site within a server
 *   (@a address does not have hostpart, only path part).
 *
 * @param parent pointer to parent site
 *               (NULL when creating a primary server object)
 * @param callback pointer to callback function called when
 *                 a request is received
 * @param magic    application context included in callback parameters
 * @param address  absolute or relative URI specifying the address of
 *                 site
 * @param tag, value, ... list of tagged parameters
 *
 * @TAGS
 * If the @a parent is NULL, the list of tagged parameters must contain
 * NTHTAG_ROOT() used to create the server engine. Tags supported when @a
 * parent is NULL are NTHTAG_ROOT(), NTHTAG_MCLASS(), TPTAG_REUSE(),
 * HTTPTAG_SERVER(), and HTTPTAG_SERVER_STR(). All the tags are passed to
 * tport_tcreate() and tport_tbind(), too.
 *
 * @since Support for multiple sites was added to @VERSION_1_12_4
 */
nth_site_t *nth_site_create(nth_site_t *parent,
			    nth_request_f *callback,
			    nth_site_magic_t *magic,
			    url_string_t const *address,
			    tag_type_t tag, tag_value_t value,
			    ...)
{
  nth_site_t *site = NULL, **prev = NULL;
  su_home_t home[SU_HOME_AUTO_SIZE(256)];
  url_t *url, url0[1];
  server_t *srv = NULL;
  ta_list ta;
  char *path = NULL;
  size_t usize;
  int is_host, is_path, wildcard = 0;

  su_home_auto(home, sizeof home);

  if (parent && url_is_string(address)) {
    char const *s = (char const *)address;
    size_t sep = strcspn(s, "/:");

    if (parent->site_path) {
      /* subpath */
      url_init(url0, (enum url_type_e)parent->site_url->url_type);
      url0->url_path = s;
      address = (url_string_t*)url0;
    }
    else if (s[sep] == ':')
      /* absolute URL with scheme */;
    else if (s[sep] == '\0' && strchr(s, '.') && host_is_valid(s)) {
      /* looks like a domain name */;
      url_init(url0, (enum url_type_e)parent->site_url->url_type);
      url0->url_host = s;
      address = (url_string_t*)url0;
    }
    else {
      /* looks like a path */
      url_init(url0, (enum url_type_e)parent->site_url->url_type);
      url0->url_path = s;
      address = (url_string_t*)url0;
    }
  }

  url = url_hdup(home, address->us_url);

  if (!url || !callback)
    return NULL;

  is_host = url->url_host != NULL;
  is_path = url->url_path != NULL;

  if (is_host && is_path) {
    SU_DEBUG_3(("nth_site_create(): virtual host and path simultanously\n"));
    errno = EINVAL;
    goto error;
  }

  if (!parent && !is_host) {
    SU_DEBUG_3(("nth_site_create(): host is required\n"));
    errno = EINVAL;
    goto error;
  }

  if (parent) {
    if (!parent->site_isdir) {
      SU_DEBUG_3(("nth_site_create(): invalid parent resource \n"));
      errno = EINVAL;
      goto error;
    }

    srv = parent->site_server; assert(srv);
    if (is_host) {
      prev = site_get_host(&srv->srv_sites, url->url_host, url->url_port);

      if (prev == NULL) {
	SU_DEBUG_3(("nth_site_create(): host %s:%s already exists\n",
		    url->url_host, url->url_port ? url->url_port : ""));
	errno = EEXIST;
	goto error;
      }
    }
    else {
      size_t i, j;

      path = (char *)url->url_path;
      while (path[0] == '/')
	path++;

      /* Remove duplicate // */
      for (i = j = 0; path[i];) {
	while (path[i] == '/' && path[i + 1] == '/')
	  i++;
	path[j++] = path[i++];
      }
      path[j] = path[i];

      url = url0, *url = *parent->site_url;

      if (url->url_path) {
	url->url_path = su_strcat(home, url->url_path, path);
	if (!url->url_path)
	  goto error;
	path = (char *)url->url_path + strlen(parent->site_url->url_path);
      }
      else
	url->url_path = path;

      prev = site_get_rslot(parent, path, &path);

      if (!prev || path[0] == '\0') {
	SU_DEBUG_3(("nth_site_create(): directory \"%s\" already exists\n",
		    url->url_path));
	errno = EEXIST;
	goto error;
      }
    }
  }

  if (!parent) {
    if (strcmp(url->url_host, "*") == 0 ||
	host_cmp(url->url_host, "0.0.0.0") == 0 ||
	host_cmp(url->url_host, "::") == 0)
      wildcard = 1, url->url_host = "*";
  }

  usize = sizeof(*url) + url_xtra(url);

  ta_start(ta, tag, value);

  if (!parent) {
    srv = server_create(url, ta_tags(ta));
    prev = &srv->srv_sites;
  }

  if (srv && (site = su_zalloc(srv->srv_home, (sizeof *site) + usize))) {
    site->site_url = (url_t *)(site + 1);
    url_dup((void *)(site->site_url + 1), usize - sizeof(*url),
	    site->site_url, url);

    assert(prev);
    if ((site->site_next = *prev))
      site->site_next->site_prev = &site->site_next;
    *prev = site, site->site_prev = prev;
    site->site_server = srv;

    if (path) {
      size_t path_len;

      site->site_path = site->site_url->url_path + (path - url->url_path);
      path_len = strlen(site->site_path); assert(path_len > 0);
      if (path_len > 0 && site->site_path[path_len - 1] == '/')
	path_len--, site->site_isdir = 1;
      site->site_path_len = path_len;
    }
    else {
      site->site_isdir = is_host;
      site->site_path = "";
      site->site_path_len = 0;
    }

    site->site_wildcard = wildcard;
    site->site_callback = callback;
    site->site_magic = magic;

    if (parent)
      site->site_auth = parent->site_auth;

    nth_site_set_params(site, ta_tags(ta));
  }

  ta_end(ta);

 error:
  su_home_deinit(home);
  return site;
}