int network_pass_proxy (const char *proxy, int sock, const char *address, int port) { int rc; struct t_proxy *ptr_proxy; rc = 0; ptr_proxy = proxy_search (proxy); if (ptr_proxy) { switch (CONFIG_INTEGER(ptr_proxy->options[PROXY_OPTION_TYPE])) { case PROXY_TYPE_HTTP: rc = network_pass_httpproxy (ptr_proxy, sock, address, port); break; case PROXY_TYPE_SOCKS4: rc = network_pass_socks4proxy (ptr_proxy, sock, address, port); break; case PROXY_TYPE_SOCKS5: rc = network_pass_socks5proxy (ptr_proxy, sock, address, port); break; } } return rc; }
struct t_proxy * proxy_new (const char *name, const char *type, const char *ipv6, const char *address, const char *port, const char *username, const char *password) { struct t_config_option *option_type, *option_ipv6, *option_address; struct t_config_option *option_port, *option_username, *option_password; struct t_proxy *new_proxy; if (!name || !name[0]) return NULL; /* it's not possible to create 2 proxies with same name */ if (proxy_search (name)) return NULL; /* look for type */ if (proxy_search_type (type) < 0) return NULL; option_type = proxy_create_option (name, PROXY_OPTION_TYPE, type); option_ipv6 = proxy_create_option (name, PROXY_OPTION_IPV6, ipv6); option_address = proxy_create_option (name, PROXY_OPTION_ADDRESS, (address) ? address : ""); option_port = proxy_create_option (name, PROXY_OPTION_PORT, port); option_username = proxy_create_option (name, PROXY_OPTION_USERNAME, (username) ? username : ""); option_password = proxy_create_option (name, PROXY_OPTION_PASSWORD, (password) ? password : ""); new_proxy = proxy_new_with_options (name, option_type, option_ipv6, option_address, option_port, option_username, option_password); if (!new_proxy) { if (option_type) config_file_option_free (option_type); if (option_ipv6) config_file_option_free (option_ipv6); if (option_address) config_file_option_free (option_address); if (option_port) config_file_option_free (option_port); if (option_username) config_file_option_free (option_username); if (option_password) config_file_option_free (option_password); } return new_proxy; }
static GList * search_path (const char *path) { GList *results = NULL; GList *iter = NULL; /* Proxy first */ results = proxy_search (path); if (!results) { /* Indexers second */ if (index_get (path, &results) == true) { DEBUG (" (index result:)\n"); } else { /* Search database next */ results = db_search (path); /* Append any provided paths */ GList *providers = NULL; providers = cb_match (&provide_list, path, CB_MATCH_PART); for (iter = providers; iter; iter = g_list_next (iter)) { cb_info_t *provider = iter->data; int len = strlen (path); /* If there is a provider for a single node below here it may * show as a "*" entry in this list, which is not desirable */ if (strlen (provider->path) > strlen (path) && provider->path[strlen (path)] == '*') { continue; } char *ptr, *provider_path = g_strdup (provider->path); if ((ptr = strchr (&provider_path[len ? len : len+1], '/')) != 0) *ptr = '\0'; if (!g_list_find_custom (results, provider_path, (GCompareFunc) strcmp)) results = g_list_prepend (results, provider_path); else g_free (provider_path); } g_list_free_full (providers, (GDestroyNotify) cb_release); } } return results; }
int network_connect_to (const char *proxy, int sock, unsigned long address, int port) { struct t_proxy *ptr_proxy; struct sockaddr_in addr; struct hostent *hostent; char *ip4; ptr_proxy = NULL; if (proxy && proxy[0]) { ptr_proxy = proxy_search (proxy); if (!ptr_proxy) return 0; } if (ptr_proxy) { memset (&addr, 0, sizeof (addr)); addr.sin_addr.s_addr = htonl (address); ip4 = inet_ntoa(addr.sin_addr); memset (&addr, 0, sizeof (addr)); addr.sin_port = htons (CONFIG_INTEGER(ptr_proxy->options[PROXY_OPTION_PORT])); addr.sin_family = AF_INET; hostent = gethostbyname (CONFIG_STRING(ptr_proxy->options[PROXY_OPTION_ADDRESS])); if (!hostent) return 0; memcpy(&(addr.sin_addr), *(hostent->h_addr_list), sizeof(struct in_addr)); if (!network_connect (sock, (struct sockaddr *) &addr, sizeof (addr))) return 0; if (!network_pass_proxy (proxy, sock, ip4, port)) return 0; } else { memset (&addr, 0, sizeof (addr)); addr.sin_port = htons (port); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl (address); if (!network_connect (sock, (struct sockaddr *) &addr, sizeof (addr))) return 0; } return 1; }
int weeurl_download (const char *url, struct t_hashtable *options) { CURL *curl; struct t_url_file url_file[2]; char *url_file_option[2] = { "file_in", "file_out" }; char *url_file_mode[2] = { "rb", "wb" }; CURLoption url_file_opt_func[2] = { CURLOPT_READFUNCTION, CURLOPT_WRITEFUNCTION }; CURLoption url_file_opt_data[2] = { CURLOPT_READDATA, CURLOPT_WRITEDATA }; void *url_file_opt_cb[2] = { &weeurl_read, &weeurl_write }; struct t_proxy *ptr_proxy; int rc, curl_rc, i; rc = 0; for (i = 0; i < 2; i++) { url_file[i].filename = NULL; url_file[i].stream = NULL; } if (!url || !url[0]) { rc = 1; goto end; } curl = curl_easy_init(); if (!curl) { rc = 3; goto end; } /* set default options */ curl_easy_setopt (curl, CURLOPT_URL, url); curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1L); /* set proxy (if option weechat.network.proxy_curl is set) */ if (CONFIG_STRING(config_network_proxy_curl) && CONFIG_STRING(config_network_proxy_curl)[0]) { ptr_proxy = proxy_search (CONFIG_STRING(config_network_proxy_curl)); if (ptr_proxy) weeurl_set_proxy (curl, ptr_proxy); } /* set file in/out from options in hashtable */ if (options) { for (i = 0; i < 2; i++) { url_file[i].filename = hashtable_get (options, url_file_option[i]); if (url_file[i].filename) { url_file[i].stream = fopen (url_file[i].filename, url_file_mode[i]); if (!url_file[i].stream) { rc = 4; goto end; } curl_easy_setopt (curl, url_file_opt_func[i], url_file_opt_cb[i]); curl_easy_setopt (curl, url_file_opt_data[i], url_file[i].stream); } } } /* set other options in hashtable */ hashtable_map (options, &weeurl_option_map_cb, curl); /* set error buffer */ curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, url_error); /* perform action! */ curl_rc = curl_easy_perform (curl); if (curl_rc != CURLE_OK) { fprintf (stderr, _("curl error %d (%s) (URL: \"%s\")\n"), curl_rc, url_error, url); rc = 2; } /* cleanup */ curl_easy_cleanup (curl); end: for (i = 0; i < 2; i++) { if (url_file[i].stream) fclose (url_file[i].stream); } return rc; }
void network_connect_child (struct t_hook *hook_connect) { struct t_proxy *ptr_proxy; struct addrinfo hints, *res, *res_local, *ptr_res; char status_str[2], *ptr_address, *status_with_string; char ipv4_address[INET_ADDRSTRLEN + 1], ipv6_address[INET6_ADDRSTRLEN + 1]; char status_without_string[1 + 5 + 1]; const char *error; int rc, length, num_written; res = NULL; res_local = NULL; status_str[1] = '\0'; ptr_address = NULL; ptr_proxy = NULL; if (HOOK_CONNECT(hook_connect, proxy) && HOOK_CONNECT(hook_connect, proxy)[0]) { ptr_proxy = proxy_search (HOOK_CONNECT(hook_connect, proxy)); if (!ptr_proxy) { /* proxy not found */ snprintf (status_without_string, sizeof (status_without_string), "%c00000", '0' + WEECHAT_HOOK_CONNECT_PROXY_ERROR); num_written = write (HOOK_CONNECT(hook_connect, child_write), status_without_string, strlen (status_without_string)); (void) num_written; return; } } if (ptr_proxy) { /* get info about peer */ memset (&hints, 0, sizeof (hints)); hints.ai_family = (CONFIG_BOOLEAN(ptr_proxy->options[PROXY_OPTION_IPV6])) ? AF_INET6 : AF_INET; hints.ai_socktype = SOCK_STREAM; rc = getaddrinfo (CONFIG_STRING(ptr_proxy->options[PROXY_OPTION_ADDRESS]), NULL, &hints, &res); if (rc != 0) { /* address not found */ status_with_string = NULL; error = gai_strerror (rc); if (error) { length = 1 + 5 + strlen (error) + 1; status_with_string = malloc (length); if (status_with_string) { snprintf (status_with_string, length, "%c%05d%s", '0' + WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND, (int)strlen (error), error); } } if (status_with_string) { num_written = write (HOOK_CONNECT(hook_connect, child_write), status_with_string, strlen (status_with_string)); } else { snprintf (status_without_string, sizeof (status_without_string), "%c00000", '0' + WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND); num_written = write (HOOK_CONNECT(hook_connect, child_write), status_without_string, strlen (status_without_string)); } if (status_with_string) free (status_with_string); (void) num_written; return; } if (!res) { /* adddress not found */ snprintf (status_without_string, sizeof (status_without_string), "%c00000", '0' + WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND); num_written = write (HOOK_CONNECT(hook_connect, child_write), status_without_string, strlen (status_without_string)); (void) num_written; return; } if ((CONFIG_BOOLEAN(ptr_proxy->options[PROXY_OPTION_IPV6]) && (res->ai_family != AF_INET6)) || ((!CONFIG_BOOLEAN(ptr_proxy->options[PROXY_OPTION_IPV6]) && (res->ai_family != AF_INET)))) { /* IP address not found */ snprintf (status_without_string, sizeof (status_without_string), "%c00000", '0' + WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND); num_written = write (HOOK_CONNECT(hook_connect, child_write), status_without_string, strlen (status_without_string)); (void) num_written; freeaddrinfo (res); return; } if (CONFIG_BOOLEAN(ptr_proxy->options[PROXY_OPTION_IPV6])) ((struct sockaddr_in6 *)(res->ai_addr))->sin6_port = htons (CONFIG_INTEGER(ptr_proxy->options[PROXY_OPTION_PORT])); else ((struct sockaddr_in *)(res->ai_addr))->sin_port = htons (CONFIG_INTEGER(ptr_proxy->options[PROXY_OPTION_PORT])); /* connect to peer */ if (!network_connect (HOOK_CONNECT(hook_connect, sock), res->ai_addr, res->ai_addrlen)) { /* connection refused */ snprintf (status_without_string, sizeof (status_without_string), "%c00000", '0' + WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED); num_written = write (HOOK_CONNECT(hook_connect, child_write), status_without_string, strlen (status_without_string)); (void) num_written; freeaddrinfo (res); return; } if (!network_pass_proxy (HOOK_CONNECT(hook_connect, proxy), HOOK_CONNECT(hook_connect, sock), HOOK_CONNECT(hook_connect, address), HOOK_CONNECT(hook_connect, port))) { /* proxy fails to connect to peer */ snprintf (status_without_string, sizeof (status_without_string), "%c00000", '0' + WEECHAT_HOOK_CONNECT_PROXY_ERROR); num_written = write (HOOK_CONNECT(hook_connect, child_write), status_without_string, strlen (status_without_string)); (void) num_written; freeaddrinfo (res); return; } status_str[0] = '0' + WEECHAT_HOOK_CONNECT_OK; } else { /* set local hostname/IP if asked by user */ if (HOOK_CONNECT(hook_connect, local_hostname) && HOOK_CONNECT(hook_connect, local_hostname[0])) { memset (&hints, 0, sizeof(hints)); hints.ai_family = (HOOK_CONNECT(hook_connect, ipv6)) ? AF_INET6 : AF_INET; hints.ai_socktype = SOCK_STREAM; rc = getaddrinfo (HOOK_CONNECT(hook_connect, local_hostname), NULL, &hints, &res_local); if (rc != 0) { /* fails to set local hostname/IP */ status_with_string = NULL; error = gai_strerror (rc); if (error) { length = 1 + 5 + strlen (error) + 1; status_with_string = malloc (length); if (status_with_string) { snprintf (status_with_string, length, "%c%05d%s", '0' + WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR, (int)strlen (error), error); } } if (status_with_string) { num_written = write (HOOK_CONNECT(hook_connect, child_write), status_with_string, strlen (status_with_string)); } else { snprintf (status_without_string, sizeof (status_without_string), "%c00000", '0' + WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR); num_written = write (HOOK_CONNECT(hook_connect, child_write), status_without_string, strlen (status_without_string)); } if (status_with_string) free (status_with_string); (void) num_written; if (res_local) freeaddrinfo (res_local); return; } else if (!res_local || (HOOK_CONNECT(hook_connect, ipv6) && (res_local->ai_family != AF_INET6)) || ((!HOOK_CONNECT(hook_connect, ipv6) && (res_local->ai_family != AF_INET)))) { /* fails to set local hostname/IP */ snprintf (status_without_string, sizeof (status_without_string), "%c00000", '0' + WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR); num_written = write (HOOK_CONNECT(hook_connect, child_write), status_without_string, strlen (status_without_string)); (void) num_written; if (res_local) freeaddrinfo (res_local); return; } if (bind (HOOK_CONNECT(hook_connect, sock), res_local->ai_addr, res_local->ai_addrlen) < 0) { /* fails to set local hostname/IP */ snprintf (status_without_string, sizeof (status_without_string), "%c00000", '0' + WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR); num_written = write (HOOK_CONNECT(hook_connect, child_write), status_without_string, strlen (status_without_string)); (void) num_written; if (res_local) freeaddrinfo (res_local); return; } } /* get info about peer */ memset (&hints, 0, sizeof(hints)); hints.ai_family = (HOOK_CONNECT(hook_connect, ipv6)) ? AF_INET6 : AF_INET; hints.ai_socktype = SOCK_STREAM; rc = getaddrinfo (HOOK_CONNECT(hook_connect, address), NULL, &hints, &res); if (rc != 0) { status_with_string = NULL; error = gai_strerror (rc); if (error) { length = 1 + 5 + strlen (error) + 1; status_with_string = malloc (length); if (status_with_string) { snprintf (status_with_string, length, "%c%05d%s", '0' + WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND, (int)strlen (error), error); } } if (status_with_string) { num_written = write (HOOK_CONNECT(hook_connect, child_write), status_with_string, strlen (status_with_string)); } else { snprintf (status_without_string, sizeof (status_without_string), "%c00000", '0' + WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND); num_written = write (HOOK_CONNECT(hook_connect, child_write), status_without_string, strlen (status_without_string)); } if (status_with_string) free (status_with_string); (void) num_written; if (res) freeaddrinfo (res); if (res_local) freeaddrinfo (res_local); return; } else if (!res) { /* address not found */ snprintf (status_without_string, sizeof (status_without_string), "%c00000", '0' + WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND); num_written = write (HOOK_CONNECT(hook_connect, child_write), status_without_string, strlen (status_without_string)); (void) num_written; if (res) freeaddrinfo (res); if (res_local) freeaddrinfo (res_local); return; } status_str[0] = '0' + WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND; /* try all IP addresses found, stop when connection is ok */ for (ptr_res = res; ptr_res; ptr_res = ptr_res->ai_next) { /* skip IP address if it's not good family */ if ((HOOK_CONNECT(hook_connect, ipv6) && (ptr_res->ai_family != AF_INET6)) || ((!HOOK_CONNECT(hook_connect, ipv6) && (ptr_res->ai_family != AF_INET)))) continue; /* connect to peer */ if (HOOK_CONNECT(hook_connect, ipv6)) ((struct sockaddr_in6 *)(ptr_res->ai_addr))->sin6_port = htons (HOOK_CONNECT(hook_connect, port)); else ((struct sockaddr_in *)(ptr_res->ai_addr))->sin_port = htons (HOOK_CONNECT(hook_connect, port)); if (network_connect (HOOK_CONNECT(hook_connect, sock), ptr_res->ai_addr, ptr_res->ai_addrlen)) { status_str[0] = '0' + WEECHAT_HOOK_CONNECT_OK; if (HOOK_CONNECT(hook_connect, ipv6)) { if (inet_ntop (AF_INET6, &((struct sockaddr_in6 *)(ptr_res->ai_addr))->sin6_addr, ipv6_address, INET6_ADDRSTRLEN)) { ptr_address = ipv6_address; } } else { if (inet_ntop (AF_INET, &((struct sockaddr_in *)(ptr_res->ai_addr))->sin_addr, ipv4_address, INET_ADDRSTRLEN)) { ptr_address = ipv4_address; } } break; } else status_str[0] = '0' + WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED; } } if (status_str[0] == '0' + WEECHAT_HOOK_CONNECT_OK) { status_with_string = NULL; if (ptr_address) { length = strlen (status_str) + 5 + strlen (ptr_address) + 1; status_with_string = malloc (length); if (status_with_string) { snprintf (status_with_string, length, "%s%05d%s", status_str, (int)strlen (ptr_address), ptr_address); } } if (status_with_string) { num_written = write (HOOK_CONNECT(hook_connect, child_write), status_with_string, strlen (status_with_string)); (void) num_written; free (status_with_string); } else { snprintf (status_without_string, sizeof (status_without_string), "%s00000", status_str); num_written = write (HOOK_CONNECT(hook_connect, child_write), status_without_string, strlen (status_without_string)); (void) num_written; } } else { snprintf (status_without_string, sizeof (status_without_string), "%s00000", status_str); num_written = write (HOOK_CONNECT(hook_connect, child_write), status_without_string, strlen (status_without_string)); (void) num_written; } if (res) freeaddrinfo (res); if (res_local) freeaddrinfo (res_local); }