Example #1
0
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;
}
Example #2
0
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;
}
Example #3
0
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;
}
Example #4
0
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;
}
Example #5
0
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;
}
Example #6
0
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);
}