예제 #1
0
파일: ghc.c 프로젝트: graaff/gtk-gnutella
/**
 * Called from parse_dispatch_lines() for each complete line of output.
 *
 * @return FALSE to stop processing of any remaining data.
 */
static bool
ghc_host_line(struct parse_context *ctx, const char *buf, size_t len)
{
	if (GNET_PROPERTY(bootstrap_debug) > 2)
		g_debug("BOOT GHC host line #%u (%zu bytes): %s",
			ctx->processed + 1, len, buf);

	if (len) {
		host_addr_t addr;
		uint16 port;

		if (string_to_host_addr_port(buf, NULL, &addr, &port)) {
			ctx->processed++;
			hcache_add_caught(HOST_ULTRA, addr, port, "GHC");

			if (GNET_PROPERTY(bootstrap_debug) > 1)
				g_debug("BOOT collected %s from GHC %s",
					host_addr_to_string(addr), http_async_url(ctx->handle));
		}
	}

	return TRUE;
}
예제 #2
0
/**
 * Loads the whitelist into memory.
 */
static void G_COLD
whitelist_retrieve(void)
{
	char line[1024];
	FILE *f;
	filestat_t st;
	unsigned linenum = 0;
	file_path_t fp[1];

	whitelist_generation++;

	file_path_set(fp, settings_config_dir(), whitelist_file);
	f = file_config_open_read_norename("Host Whitelist", fp, N_ITEMS(fp));
	if (!f)
		return;

	if (fstat(fileno(f), &st)) {
		g_warning("%s(): fstat() failed: %m", G_STRFUNC);
		fclose(f);
		return;
	}

    while (fgets(line, sizeof line, f)) {
		pslist_t *sl_addr, *sl;
		const char *endptr, *start;
		host_addr_t addr;
    	uint16 port;
		uint8 bits;
		bool item_ok;
		bool use_tls;
		char *hname;

        linenum++;

		if (!file_line_chomp_tail(line, sizeof line, NULL)) {
			g_warning("%s(): line %u too long, aborting", G_STRFUNC, linenum);
			break;
		}

        if (file_line_is_skipable(line))
			continue;

		sl_addr = NULL;
		addr = zero_host_addr;
		endptr = NULL;
		hname = NULL;

		endptr = is_strprefix(line, "tls:");
		if (endptr) {
			use_tls = TRUE;
			start = endptr;
		} else {
			use_tls = FALSE;
			start = line;
		}

		port = 0;
		if (string_to_host_addr_port(start, &endptr, &addr, &port)) {
       		sl_addr = name_to_host_addr(host_addr_to_string(addr),
							settings_dns_net());
		} else if (string_to_host_or_addr(start, &endptr, &addr)) {
			uchar c = *endptr;

			switch (c) {
			case '\0':
			case ':':
			case '/':
				break;
			default:
				if (!is_ascii_space(c))
					endptr = NULL;
			}

			if (!endptr) {
				g_warning("%s(): line %d: "
					"expected a hostname or IP address \"%s\"",
					G_STRFUNC, linenum, line);
				continue;
			}

			/* Terminate the string for name_to_host_addr() */
			hname = h_strndup(start, endptr - start);
		} else {
            g_warning("%s(): line %d: expected hostname or IP address \"%s\"",
				G_STRFUNC, linenum, line);
			continue;
		}

       	g_assert(sl_addr != NULL || hname != NULL);
		g_assert(NULL != endptr);
		bits = 0;
		item_ok = TRUE;

		/*
		 * When an explicit address is given (no hostname) and with no
		 * port, one can suffix the address with bits to indicate a CIDR
		 * range of whitelisted addresses.
		 */

		if (0 == port) {
			/* Ignore trailing items separated by a space */
			while ('\0' != *endptr && !is_ascii_space(*endptr)) {
				uchar c = *endptr++;

				if (':' == c) {
					int error;
					uint32 v;

					if (0 != port) {
						g_warning("%s(): line %d: multiple colons after host",
							G_STRFUNC, linenum);
						item_ok = FALSE;
						break;
					}

					v = parse_uint32(endptr, &endptr, 10, &error);
					port = (error || v > 0xffff) ? 0 : v;
					if (0 == port) {
						g_warning("%s(): line %d: "
							"invalid port value after host",
							G_STRFUNC, linenum);
						item_ok = FALSE;
						break;
					}
				} else if ('/' == c) {
					const char *ep;
					uint32 mask;

					if (0 != bits) {
						g_warning("%s(): line %d: "
							"multiple slashes after host", G_STRFUNC, linenum);
						item_ok = FALSE;
						break;
					}

					if (string_to_ip_strict(endptr, &mask, &ep)) {
						if (!host_addr_is_ipv4(addr)) {
							g_warning("%s(): line %d: "
								"IPv4 netmask after non-IPv4 address",
								G_STRFUNC, linenum);
							item_ok = FALSE;
							break;
						}
						endptr = ep;

						if (0 == (bits = netmask_to_cidr(mask))) {
							g_warning("%s(): line %d: "
								"IPv4 netmask after non-IPv4 address",
								G_STRFUNC, linenum);
							item_ok = FALSE;
							break;
						}

					} else {
						int error;
						uint32 v;

						v = parse_uint32(endptr, &endptr, 10, &error);
						if (
							error ||
							0 == v ||
							(v > 32 && host_addr_is_ipv4(addr)) ||
							(v > 128 && host_addr_is_ipv6(addr))
						) {
							g_warning("%s(): line %d: "
								"invalid numeric netmask after host",
								G_STRFUNC, linenum);
							item_ok = FALSE;
							break;
						}
						bits = v;
					}
				} else {
					g_warning("%s(): line %d: "
						"unexpected character after host", G_STRFUNC, linenum);
					item_ok = FALSE;
					break;
				}
			}
		}

		if (item_ok) {
			struct whitelist *item;
			if (hname) {
				item = whitelist_hostname_create(use_tls, hname, port);
				whitelist_dns_resolve(item, FALSE);
			} else {
				PSLIST_FOREACH(sl_addr, sl) {
					host_addr_t *aptr = sl->data;
					g_assert(aptr != NULL);
					item = whitelist_addr_create(use_tls, *aptr, port, bits);
					whitelist_add(item);
				}
			}
		} else {
예제 #3
0
/**
 * Called from gwc_parse_dispatch_lines() for each complete line of output.
 *
 * @return FALSE to stop processing of any remaining data.
 */
static bool
gwc_host_line(struct gwc_parse_context *ctx, const char *buf, size_t len)
{
    int c;

    if (GNET_PROPERTY(bootstrap_debug) > 3)
        g_message("BOOT GWC host line (%lu bytes): %s", (ulong) len, buf);

    if (is_strprefix(buf, "ERROR")) {
        g_warning("GWC cache \"%s\" returned %s",
                  http_async_url(ctx->handle), buf);
        http_async_cancel(ctx->handle);
        return FALSE;
    }

    if (len <= 2)
        return TRUE;		/* Skip this line silently */

    /*
     * A line starting with "H|" is a host, with "U|" a GWC URL.
     * Letters are case-insensitive.
     */

    if (buf[1] != '|')
        goto malformed;

    c = ascii_toupper(buf[0]);

    if ('H' == c) {
        host_addr_t addr;
        uint16 port;

        if (string_to_host_addr_port(&buf[2], NULL, &addr, &port)) {
            ctx->processed++;
            hcache_add_caught(HOST_G2HUB, addr, port, "GWC");
            if (GNET_PROPERTY(bootstrap_debug) > 1) {
                g_message("BOOT (G2) collected %s from GWC %s",
                          host_addr_port_to_string(addr, port),
                          http_async_url(ctx->handle));
            }
        }
        return TRUE;
    } else if ('U' == c) {
        char *end = strchr(&buf[2], '|');
        char *url;

        if (NULL == end)
            goto malformed;

        ctx->processed++;
        url = h_strndup(&buf[2], ptr_diff(end, &buf[2]));
        gwc_add(url);
        hfree(url);
        return TRUE;
    } else if ('I' == c) {
        return TRUE;		/* Ignore information line */
    }

    /*
     * If we come here, we did not recognize the line properly.
     */

    if (GNET_PROPERTY(bootstrap_debug) > 2) {
        g_warning("GWC ignoring unknown line \"%s\" from %s",
                  buf, http_async_url(ctx->handle));
    }

    return TRUE;

malformed:
    if (GNET_PROPERTY(bootstrap_debug)) {
        g_warning("GWC ignoring malformed line \"%s\" from %s",
                  buf, http_async_url(ctx->handle));
    }

    return TRUE;
}