static int iprange_net4_collision(const void *p, const void *q) { const struct iprange_net4 *a = p, *b = q; g_warning("iprange_sync(): %s/%u overlaps with %s/%u", ip_to_string(a->ip), a->bits, host_addr_to_string(host_addr_get_ipv4(b->ip)), b->bits); return a->bits < b->bits ? 1 : -1; }
static inline int iprange_net_collision(const void *p, const void *q) { const struct iprange_net *a = p, *b = q; g_warning("iprange_sync(): %s/0x%x overlaps with %s/0x%x", ip_to_string(a->ip), a->mask, host_addr_to_string(host_addr_get_ipv4(b->ip)), b->mask); return a->mask < b->mask ? 1 : -1; }
/** * Parses IPv4 and IPv6 addresses. The latter requires IPv6 support to be * enabled. * * For convenience, if the first character is '[' then the address is parsed * as an IPv6 one and the trailing ']' is both expected and swallowed. This * allows the routine to be used when parsing "ipv4:port" or "[ipv6]:port" * strings. * * @param s The string to parse. * @param endptr This will point to the first character after the parsed * address. * @param addr_ptr If not NULL, it is set to the parsed host address or * ``zero_host_addr'' on failure. * @return Returns TRUE on success; otherwise FALSE. */ bool string_to_host_addr(const char *s, const char **endptr, host_addr_t *addr_ptr) { uint32 ip; bool brackets = FALSE; g_assert(s); if ('[' == *s) { brackets = TRUE; s++; } if (!brackets && string_to_ip_strict(s, &ip, endptr)) { if (addr_ptr) { *addr_ptr = host_addr_get_ipv4(ip); } return TRUE; } else { uint8 ipv6[16]; const char *end; bool ok; ok = parse_ipv6_addr(s, ipv6, &end); if (ok) { if (addr_ptr) { *addr_ptr = host_addr_peek_ipv6(ipv6); } if (brackets) { if (']' == *end) { end++; } else { ok = FALSE; /* Trailing ']' required if we had '[' */ } } } if (endptr != NULL) *endptr = end; if (ok) return TRUE; /* FALL THROUGH */ } if (addr_ptr) *addr_ptr = zero_host_addr; return FALSE; }
bool host_addr_teredo_client(const host_addr_t from, host_addr_t *to) { if (host_addr_is_teredo(from)) { if (to) { *to = host_addr_get_ipv4(host_addr_teredo_client_ipv4(from)); } return TRUE; } else { if (to) { *to = zero_host_addr; } return FALSE; } }
/** * Default implementation to get the default gateway by parsing the * output of the "netstat -rn" command. * * @param addrp where gateway address is to be written * * @return 0 on success, -1 on failure with errno set. */ static G_GNUC_COLD int parse_netstat(host_addr_t *addrp) #ifdef HAS_POPEN { FILE *f = NULL; char tmp[80]; uint32 gate = 0; /* * This implementation should be a safe default on UNIX platforms, but * it is inefficient and as such can only constitute a fallback. */ if (-1 != access("/bin/netstat", X_OK)) { f = popen("/bin/netstat -rn", "r"); } else if (-1 != access("/usr/bin/netstat", X_OK)) { f = popen("/usr/bin/netstat -rn", "r"); } if (NULL == f) { errno = ENOENT; /* netstat not found */ return -1; } /* * Typical netstat -rn output: * * Destination Gateway Flags ..... * 0.0.0.0 192.168.0.200 UG * default 192.168.0.200 UG * * Some systems like linux display "0.0.0.0", but traditional UNIX * output is "default" for the default route. */ while (fgets(tmp, sizeof tmp, f)) { char *p; uint32 ip; p = is_strprefix(tmp, "default"); if (NULL == p) p = is_strprefix(tmp, "0.0.0.0"); if (NULL == p || !is_ascii_space(*p)) continue; ip = string_to_ip(p); if (ip != 0) { gate = ip; break; } } pclose(f); if (0 == gate) { errno = ENETUNREACH; return -1; } *addrp = host_addr_get_ipv4(gate); return 0; }
/** * Handle reply to a discovery request. * * @param payload the received reply * @param len length of reply * @param rd the RPC request descriptor * * @return TRUE if we successfully processed the reply and notified the * user code about the outcome of the request, FALSE if we need to resend * the request. */ static bool natpmp_handle_discovery_reply( const void *payload, size_t len, struct natpmp_rpc *rd) { bstr_t *bs; uint8 version; uint8 code; uint16 result; uint32 ip; host_addr_t wan_ip; natpmp_t *np; natpmp_rpc_check(rd); /** * A NAT gateway will reply with the following message: * * 0 1 2 3 * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Vers = 0 | OP = 128 + 0 | Result Code | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | Seconds Since Start of Epoch | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * | External IP Address (a.b.c.d) | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ * * The first 32-bits are always present, the remaining of the packet * may or may not be there depending on the result code. */ bs = bstr_open(payload, len, GNET_PROPERTY(natpmp_debug) ? BSTR_F_ERROR : 0); /* * Make sure we got a valid reply. */ bstr_read_u8(bs, &version); bstr_read_u8(bs, &code); bstr_read_be16(bs, &result); if (bstr_has_error(bs)) goto error; if (GNET_PROPERTY(natpmp_debug) > 5) { g_debug("NATPMP version=%u, code=%u, result_code=%u (%s)", version, code, result, natpmp_strerror(result)); } if (version != NATPMP_VERSION || code != NATPMP_REPLY_OFF + rd->op) goto error; if (NATPMP_E_OK != result) goto failed; bstr_read_be32(bs, &rd->sssoe); bstr_read_be32(bs, &ip); if (bstr_has_error(bs)) goto error; wan_ip = host_addr_get_ipv4(ip); if (GNET_PROPERTY(natpmp_debug) > 5) { g_debug("NATPMP SSSOE=%u, WAN IP is %s", rd->sssoe, host_addr_to_string(wan_ip)); } if (!host_addr_is_routable(wan_ip)) goto failed; /* * Good, we got a valid reply from the gateway, with a routable WAN IP. */ if (rd->np != NULL) { natpmp_check(rd->np); np = rd->np; natpmp_update(np, rd->sssoe); np->wan_ip = wan_ip; } else { np = natpmp_alloc(rd->gateway, rd->sssoe, wan_ip); } (*rd->cb.discovery)(TRUE, np, rd->arg); bstr_free(&bs); return TRUE; /* OK */ failed: if (GNET_PROPERTY(natpmp_debug)) g_warning("NATPMP did not find any suitable NAT-PMP gateway"); (*rd->cb.discovery)(FALSE, rd->np, rd->arg); return TRUE; /* We're done for now */ error: if (GNET_PROPERTY(natpmp_debug)) { if (bstr_has_error(bs)) { g_warning("NATPMP parsing error while processing discovery reply " "(%zu byte%s): %s", len, 1 == len ? "" : "s", bstr_error(bs)); } else { g_warning("NATPMP inconsistent discovery reply (%zu byte%s)", len, 1 == len ? "" : "s"); } } bstr_free(&bs); return FALSE; }