Exemplo n.º 1
0
Arquivo: geoip.c Projeto: majek/tor
/** Add an entry to the GeoIP table indicated by <b>family</b>,
 * parsing it from <b>line</b>. The format is as for geoip_load_file(). */
/*private*/ int
geoip_parse_entry(const char *line, sa_family_t family)
{
  tor_addr_t low_addr, high_addr;
  char c[3];
  char *country = NULL;

  if (!geoip_countries)
    init_geoip_countries();
  if (family == AF_INET) {
    if (!geoip_ipv4_entries)
      geoip_ipv4_entries = smartlist_new();
  } else if (family == AF_INET6) {
    if (!geoip_ipv6_entries)
      geoip_ipv6_entries = smartlist_new();
  } else {
    log_warn(LD_GENERAL, "Unsupported family: %d", family);
    return -1;
  }

  while (TOR_ISSPACE(*line))
    ++line;
  if (*line == '#')
    return 0;

  if (family == AF_INET) {
    unsigned int low, high;
    if (tor_sscanf(line,"%u,%u,%2s", &low, &high, c) == 3 ||
        tor_sscanf(line,"\"%u\",\"%u\",\"%2s\",", &low, &high, c) == 3) {
      tor_addr_from_ipv4h(&low_addr, low);
      tor_addr_from_ipv4h(&high_addr, high);
    } else
      goto fail;
    country = c;
  } else {                      /* AF_INET6 */
    char buf[512];
    char *low_str, *high_str;
    struct in6_addr low, high;
    char *strtok_state;
    strlcpy(buf, line, sizeof(buf));
    low_str = tor_strtok_r(buf, ",", &strtok_state);
    if (!low_str)
      goto fail;
    high_str = tor_strtok_r(NULL, ",", &strtok_state);
    if (!high_str)
      goto fail;
    country = tor_strtok_r(NULL, "\n", &strtok_state);
    if (!country)
      goto fail;
    if (strlen(country) != 2)
      goto fail;
    if (tor_inet_pton(AF_INET6, low_str, &low) <= 0)
      goto fail;
    tor_addr_from_in6(&low_addr, &low);
    if (tor_inet_pton(AF_INET6, high_str, &high) <= 0)
      goto fail;
    tor_addr_from_in6(&high_addr, &high);
  }
  geoip_add_entry(&low_addr, &high_addr, country);
  return 0;

  fail:
  log_warn(LD_GENERAL, "Unable to parse line from GEOIP %s file: %s",
           family == AF_INET ? "IPv4" : "IPv6", escaped(line));
  return -1;
}
Exemplo n.º 2
0
/**
 * Helper function to parse out a line in the measured bandwidth file
 * into a measured_bw_line_t output structure.
 *
 * If <b>line_is_after_headers</b> is true, then if we encounter an incomplete
 * bw line, return -1 and warn, since we are after the headers and we should
 * only parse bw lines. Return 0 otherwise.
 *
 * If <b>line_is_after_headers</b> is false then it means that we are not past
 * the header block yet. If we encounter an incomplete bw line, return -1 but
 * don't warn since there could be additional header lines coming. If we
 * encounter a proper bw line, return 0 (and we got past the headers).
 *
 * If the line contains "vote=0", stop parsing it, and return -1, so that the
 * line is ignored during voting.
 */
STATIC int
measured_bw_line_parse(measured_bw_line_t *out, const char *orig_line,
                       int line_is_after_headers)
{
  char *line = tor_strdup(orig_line);
  char *cp = line;
  int got_bw = 0;
  int got_node_id = 0;
  char *strtok_state; /* lame sauce d'jour */

  if (strlen(line) == 0) {
    log_warn(LD_DIRSERV, "Empty line in bandwidth file");
    tor_free(line);
    return -1;
  }

  /* Remove end of line character, so that is not part of the token */
  if (line[strlen(line) - 1] == '\n') {
    line[strlen(line) - 1] = '\0';
  }

  cp = tor_strtok_r(cp, " \t", &strtok_state);

  if (!cp) {
    log_warn(LD_DIRSERV, "Invalid line in bandwidth file: %s",
             escaped(orig_line));
    tor_free(line);
    return -1;
  }

  if (orig_line[strlen(orig_line)-1] != '\n') {
    log_warn(LD_DIRSERV, "Incomplete line in bandwidth file: %s",
             escaped(orig_line));
    tor_free(line);
    return -1;
  }

  do {
    // If the line contains vote=0, ignore it.
    if (strcmpstart(cp, "vote=0") == 0) {
      log_debug(LD_DIRSERV, "Ignoring bandwidth file line that contains "
                "vote=0: %s",escaped(orig_line));
      tor_free(line);
      return -1;
    } else if (strcmpstart(cp, "bw=") == 0) {
      int parse_ok = 0;
      char *endptr;
      if (got_bw) {
        log_warn(LD_DIRSERV, "Double bw= in bandwidth file line: %s",
                 escaped(orig_line));
        tor_free(line);
        return -1;
      }
      cp+=strlen("bw=");

      out->bw_kb = tor_parse_long(cp, 10, 0, LONG_MAX, &parse_ok, &endptr);
      if (!parse_ok || (*endptr && !TOR_ISSPACE(*endptr))) {
        log_warn(LD_DIRSERV, "Invalid bandwidth in bandwidth file line: %s",
                 escaped(orig_line));
        tor_free(line);
        return -1;
      }
      got_bw=1;
    } else if (strcmpstart(cp, "node_id=$") == 0) {
      if (got_node_id) {
        log_warn(LD_DIRSERV, "Double node_id= in bandwidth file line: %s",
                 escaped(orig_line));
        tor_free(line);
        return -1;
      }
      cp+=strlen("node_id=$");

      if (strlen(cp) != HEX_DIGEST_LEN ||
          base16_decode(out->node_id, DIGEST_LEN,
                        cp, HEX_DIGEST_LEN) != DIGEST_LEN) {
        log_warn(LD_DIRSERV, "Invalid node_id in bandwidth file line: %s",
                 escaped(orig_line));
        tor_free(line);
        return -1;
      }
      strlcpy(out->node_hex, cp, sizeof(out->node_hex));
      got_node_id=1;
    }
  } while ((cp = tor_strtok_r(NULL, " \t", &strtok_state)));

  if (got_bw && got_node_id) {
    tor_free(line);
    return 0;
  } else if (line_is_after_headers == 0) {
    /* There could be additional header lines, therefore do not give warnings
     * but returns -1 since it's not a complete bw line. */
    log_debug(LD_DIRSERV, "Missing bw or node_id in bandwidth file line: %s",
             escaped(orig_line));
    tor_free(line);
    return -1;
  } else {
    log_warn(LD_DIRSERV, "Incomplete line in bandwidth file: %s",
             escaped(orig_line));
    tor_free(line);
    return -1;
  }
}