static SOCKET xmlNanoHTTPConnectHost(const char *host, int port) { struct hostent *h; struct sockaddr *addr = NULL; struct in_addr ia; struct sockaddr_in sockin; #ifdef SUPPORT_IP6 struct in6_addr ia6; struct sockaddr_in6 sockin6; #endif int i; SOCKET s; memset (&sockin, 0, sizeof(sockin)); #ifdef SUPPORT_IP6 memset (&sockin6, 0, sizeof(sockin6)); #endif #if !defined(HAVE_GETADDRINFO) && defined(SUPPORT_IP6) && defined(RES_USE_INET6) if (have_ipv6 ()) { if (!(_res.options & RES_INIT)) res_init(); _res.options |= RES_USE_INET6; } #endif #if defined(HAVE_GETADDRINFO) && defined(SUPPORT_IP6) && !defined(_WIN32) if (have_ipv6 ()) #endif #if defined(HAVE_GETADDRINFO) && (defined(SUPPORT_IP6) || defined(_WIN32)) { int status; struct addrinfo hints, *res, *result; result = NULL; memset (&hints, 0,sizeof(hints)); hints.ai_socktype = SOCK_STREAM; status = getaddrinfo (host, NULL, &hints, &result); if (status) { __xmlIOErr(XML_FROM_HTTP, 0, "getaddrinfo failed\n"); return INVALID_SOCKET; } for (res = result; res; res = res->ai_next) { if (res->ai_family == AF_INET) { if (res->ai_addrlen > sizeof(sockin)) { __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n"); freeaddrinfo (result); return INVALID_SOCKET; } memcpy (&sockin, res->ai_addr, res->ai_addrlen); sockin.sin_port = htons (port); addr = (struct sockaddr *)&sockin; #ifdef SUPPORT_IP6 } else if (have_ipv6 () && (res->ai_family == AF_INET6)) { if (res->ai_addrlen > sizeof(sockin6)) { __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n"); freeaddrinfo (result); return INVALID_SOCKET; } memcpy (&sockin6, res->ai_addr, res->ai_addrlen); sockin6.sin6_port = htons (port); addr = (struct sockaddr *)&sockin6; #endif } else continue; /* for */ s = xmlNanoHTTPConnectAttempt (addr); if (s != INVALID_SOCKET) { freeaddrinfo (result); return (s); } } if (result) freeaddrinfo (result); } #endif #if defined(HAVE_GETADDRINFO) && defined(SUPPORT_IP6) && !defined(_WIN32) else #endif #if !defined(HAVE_GETADDRINFO) || !defined(_WIN32) { h = gethostbyname (host); if (h == NULL) { /* * Okay, I got fed up by the non-portability of this error message * extraction code. it work on Linux, if it work on your platform * and one want to enable it, send me the defined(foobar) needed */ #if defined(HAVE_NETDB_H) && defined(HOST_NOT_FOUND) && defined(linux) const char *h_err_txt = ""; switch (h_errno) { case HOST_NOT_FOUND: h_err_txt = "Authoritive host not found"; break; case TRY_AGAIN: h_err_txt = "Non-authoritive host not found or server failure."; break; case NO_RECOVERY: h_err_txt = "Non-recoverable errors: FORMERR, REFUSED, or NOTIMP."; break; case NO_ADDRESS: h_err_txt = "Valid name, no data record of requested type."; break; default: h_err_txt = "No error text defined."; break; } __xmlIOErr(XML_FROM_HTTP, 0, h_err_txt); #else __xmlIOErr(XML_FROM_HTTP, 0, "Failed to resolve host"); #endif return INVALID_SOCKET; } for (i = 0; h->h_addr_list[i]; i++) { if (h->h_addrtype == AF_INET) { /* A records (IPv4) */ if ((unsigned int) h->h_length > sizeof(ia)) { __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n"); return INVALID_SOCKET; } memcpy (&ia, h->h_addr_list[i], h->h_length); sockin.sin_family = h->h_addrtype; sockin.sin_addr = ia; sockin.sin_port = (u_short)htons ((unsigned short)port); addr = (struct sockaddr *) &sockin; #ifdef SUPPORT_IP6 } else if (have_ipv6 () && (h->h_addrtype == AF_INET6)) { /* AAAA records (IPv6) */ if ((unsigned int) h->h_length > sizeof(ia6)) { __xmlIOErr(XML_FROM_HTTP, 0, "address size mismatch\n"); return INVALID_SOCKET; } memcpy (&ia6, h->h_addr_list[i], h->h_length); sockin6.sin6_family = h->h_addrtype; sockin6.sin6_addr = ia6; sockin6.sin6_port = htons (port); addr = (struct sockaddr *) &sockin6; #endif } else break; /* for */ s = xmlNanoHTTPConnectAttempt (addr); if (s != INVALID_SOCKET) return (s); } } #endif #ifdef DEBUG_HTTP xmlGenericError(xmlGenericErrorContext, "xmlNanoHTTPConnectHost: unable to connect to '%s'.\n", host); #endif return INVALID_SOCKET; }
/* Connect to a CDDB server */ static int CDDBConnect (CDDBServer *server) { int sock = -1; #ifdef ENABLE_IPV6 struct sockaddr_in6 sin6; struct addrinfo hints, *result, *res; /*info abt the IP of node*/ #endif struct sockaddr_in sin; struct hostent *host; char *sname; #ifdef ENABLE_IPV6 if (have_ipv6 ()) { result = NULL; memset (&sin6, 0 , sizeof (sin6)); sin6.sin6_family = AF_INET6; if (server->use_proxy) { sin6.sin6_port = htons (server->proxy->port); } else { sin6.sin6_port = htons (server->port); } } #endif memset (&sin, 0, sizeof (sin)); sin.sin_family = AF_INET; if (server->use_proxy) sin.sin_port=htons(server->proxy->port); else sin.sin_port = htons(server->port); if (server->use_proxy) sname=server->proxy->name; else sname=server->name; #ifdef ENABLE_IPV6 if (have_ipv6 ()) { memset (&hints, 0, sizeof (hints)); hints.ai_socktype = SOCK_STREAM; if ((getaddrinfo (sname, NULL, &hints, &result)) != 0) { return -1; } for (res = result; res; res = res->ai_next) { if (res->ai_family != AF_INET && res->ai_family != AF_INET6) { continue; } sock = socket (res->ai_family, SOCK_STREAM, 0); if (sock < 0) { continue; } if (res->ai_family == AF_INET) { memcpy (&sin.sin_addr, &((struct sockaddr_in *)res->ai_addr)->sin_addr, sizeof (struct in_addr)); if (connect (sock, (struct sockaddr *)&sin, sizeof (sin)) != -1) { break; } } if (res->ai_family == AF_INET6) { memcpy (&sin6.sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, sizeof (struct in6_addr)); if (connect (sock, (struct sockaddr *)&sin6, sizeof (sin6)) != -1) { break; } } close (sock); } freeaddrinfo (result); if (!res) { /* No valid address found. */ return -1; } } else #endif /*IPv4*/ { sin.sin_addr.s_addr = inet_addr (sname); #ifdef SOLARIS if (sin.sin_addr.s_addr == (unsigned long)-1) #else if (sin.sin_addr.s_addr == INADDR_NONE) #endif { host = gethostbyname (sname); if (host == NULL) { return -1; } bcopy (host->h_addr, &sin.sin_addr, host->h_length); } sock = socket (AF_INET, SOCK_STREAM, 0); if (sock < 0) { return -1; } if (connect (sock, (struct sockaddr *)&sin, sizeof (sin)) < 0) { return -1; } } return sock; }
static void parse_ignore_host(gpointer data, gpointer user_data) { gchar *hostname, *input, *netmask; gboolean ip_addr = FALSE, has_error = FALSE; struct in_addr host; #ifdef ENABLE_IPV6 struct in6_addr host6, mask6; gint i; #endif ProxyHostAddr *elt; input = (gchar *) data; elt = g_new0(ProxyHostAddr, 1); if ((netmask = strchr(input, '/')) != NULL) { hostname = g_strndup(input, netmask - input); ++netmask; } else { hostname = g_ascii_strdown(input, -1); } if (inet_pton(AF_INET, hostname, &host) > 0) { ip_addr = TRUE; elt->type = PROXY_IPv4; elt->addr.s_addr = host.s_addr; if (netmask) { gchar *endptr; gint width = strtol(netmask, &endptr, 10); if (*endptr != '\0' || width < 0 || width > 32) { has_error = TRUE; } elt->mask.s_addr = htonl(~0 << width); elt->addr.s_addr &= elt->mask.s_addr; } else { elt->mask.s_addr = 0xffffffff; } } #ifdef ENABLE_IPV6 else if (have_ipv6() && inet_pton(AF_INET6, hostname, &host6) > 0) { ip_addr = TRUE; elt->type = PROXY_IPv6; for (i = 0; i < 16; ++i) { elt->addr6.s6_addr[i] = host6.s6_addr[i]; } if (netmask) { gchar *endptr; gint width = strtol(netmask, &endptr, 10); if (*endptr != '\0' || width < 0 || width > 128) { has_error = TRUE; } for (i = 0; i < 16; ++i) { elt->mask6.s6_addr[i] = 0; } for (i = 0; i < width / 8; i++) { elt->mask6.s6_addr[i] = 0xff; } elt->mask6.s6_addr[i] = (0xff << (8 - width % 8)) & 0xff; ipv6_network_addr(&elt->addr6, &mask6, &elt->addr6); } else { for (i = 0; i < 16; ++i) { elt->mask6.s6_addr[i] = 0xff; } } } #endif if (ip_addr) { if (!has_error) { gchar *dst = g_new0(gchar, INET_ADDRSTRLEN); gl_ignore_addrs = g_slist_append(gl_ignore_addrs, elt); DEBUG_HTTP(("Host %s/%s does not go through proxy.", hostname, inet_ntop(AF_INET, &elt->mask, dst, INET_ADDRSTRLEN))); g_free(dst); } g_free(hostname); } else { /* It is a hostname. */ gl_ignore_hosts = g_slist_append(gl_ignore_hosts, hostname); DEBUG_HTTP(("Host %s does not go through proxy.", hostname)); g_free(elt); } }
int bg_listen_socket_create_inet(bg_socket_address_t * addr, int port, int queue_size, int flags) { int ret, err, use_ipv6 = 0; struct sockaddr_in name_ipv4; struct sockaddr_in6 name_ipv6; if(addr) { if(addr->addr.ss_family == AF_INET6) use_ipv6 = 1; } else if(flags & BG_SOCKET_LOOPBACK) use_ipv6 = have_ipv6(); memset(&name_ipv4, 0, sizeof(name_ipv4)); memset(&name_ipv6, 0, sizeof(name_ipv6)); if(use_ipv6) ret = create_socket(PF_INET6, SOCK_STREAM, 0); else ret = create_socket(PF_INET, SOCK_STREAM, 0); /* Create the socket. */ if(ret < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot create TCP server socket"); return -1; } /* Give the socket a name. */ if(addr) { err = bind(ret, (struct sockaddr*)&addr->addr, addr->len); } else if(use_ipv6) { name_ipv6.sin6_family = AF_INET6; name_ipv6.sin6_port = htons(port); if(flags & BG_SOCKET_LOOPBACK) name_ipv6.sin6_addr = in6addr_loopback; else name_ipv6.sin6_addr = in6addr_any; err = bind(ret, (struct sockaddr *)&name_ipv6, sizeof(name_ipv6)); } else { name_ipv4.sin_family = AF_INET; name_ipv4.sin_port = htons(port); if(flags & BG_SOCKET_LOOPBACK) name_ipv4.sin_addr.s_addr = htonl(INADDR_LOOPBACK); else name_ipv4.sin_addr.s_addr = htonl(INADDR_ANY); err = bind(ret, (struct sockaddr *)&name_ipv4, sizeof(name_ipv4)); } if(err < 0) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot bind inet socket: %s", strerror(errno)); return -1; } if(listen(ret, queue_size)) { bg_log(BG_LOG_ERROR, LOG_DOMAIN, "Cannot put socket into listening mode"); return -1; } return ret; }
static gboolean proxy_should_for_hostname(const char *hostname) { #ifdef ENABLE_IPV6 struct in6_addr in6, net6; #endif struct in_addr in; GSList *elt; ProxyHostAddr *addr; /* IPv4 address */ if (inet_pton(AF_INET, hostname, &in) > 0) { for (elt = gl_ignore_addrs; elt; elt = g_slist_next(elt)) { addr = (ProxyHostAddr *) (elt->data); if (addr->type == PROXY_IPv4 && (in.s_addr & addr->mask.s_addr) == addr->addr.s_addr) { DEBUG_HTTP(("Host %s using direct connection.", hostname)); return FALSE; } } } #ifdef ENABLE_IPV6 else if (have_ipv6() && inet_pton(AF_INET6, hostname, &in6)) { for (elt = gl_ignore_addrs; elt; elt = g_slist_next(elt)) { addr = (ProxyHostAddr *) (elt->data); ipv6_network_addr(&in6, &addr->mask6, &net6); if (addr->type == PROXY_IPv6 && IN6_ARE_ADDR_EQUAL(&net6, &addr->addr6)) { DEBUG_HTTP(("Host %s using direct connection.", hostname)); return FALSE; } /* Handle IPv6-wrapped IPv4 addresses. */ else if (addr->type == PROXY_IPv4 && IN6_IS_ADDR_V4MAPPED(&net6)) { guint32 v4addr; v4addr = net6.s6_addr[12] << 24 | net6. s6_addr[13] << 16 | net6. s6_addr[14] << 8 | net6.s6_addr[15]; if ((v4addr & addr->mask.s_addr) != addr->addr.s_addr) { DEBUG_HTTP(("Host %s using direct connection.", hostname)); return FALSE; } } } } #endif /* All hostnames (foo.bar.com) -- independent of IPv4 or IPv6 */ /* If there are IPv6 addresses in the ignore_hosts list but we do not * have IPv6 available at runtime, then those addresses will also fall * through to here (and harmlessly fail to match). */ else { gchar *hn = g_ascii_strdown(hostname, -1); for (elt = gl_ignore_hosts; elt; elt = g_slist_next(elt)) { if (*(gchar *) (elt->data) == '*') { if (g_str_has_suffix(hn, (gchar *) (elt->data) + 1)) { DEBUG_HTTP(("Host %s using direct connection.", hn)); g_free(hn); return FALSE; } } else if (strcmp(hn, elt->data) == 0) { DEBUG_HTTP(("Host %s using direct connection.", hn)); g_free(hn); return FALSE; } } g_free(hn); } return TRUE; }