Esempio n. 1
0
int
xfer_network_connect (struct t_xfer *xfer)
{
    if (xfer->type == XFER_TYPE_CHAT_SEND)
        xfer->status = XFER_STATUS_WAITING;
    else
        xfer->status = XFER_STATUS_CONNECTING;
    
    if (xfer->sock < 0)
    {
        xfer->sock = socket (AF_INET, SOCK_STREAM, 0);
        if (xfer->sock < 0)
            return 0;
    }
    
    if (XFER_IS_SEND(xfer->type))
    {
        /* listen to socket */
        if (fcntl (xfer->sock, F_SETFL, O_NONBLOCK) == -1)
            return 0;	
        if (listen (xfer->sock, 1) == -1)
            return 0;
        if (fcntl (xfer->sock, F_SETFL, 0) == -1)
            return 0;

        xfer->hook_fd = weechat_hook_fd (xfer->sock,
                                         1, 0, 0,
                                         &xfer_network_fd_cb,
                                         xfer);
        
        /* add timeout */
        if (weechat_config_integer (xfer_config_network_timeout) > 0)
        {
            xfer->hook_timer = weechat_hook_timer (weechat_config_integer (xfer_config_network_timeout) * 1000,
                                                   0, 1,
                                                   &xfer_network_timer_cb,
                                                   xfer);
        }
    }
    
    /* for chat receiving, connect to listening host */
    if (xfer->type == XFER_TYPE_CHAT_RECV)
    {
        if (fcntl (xfer->sock, F_SETFL, O_NONBLOCK) == -1)
            return 0;
        weechat_network_connect_to (xfer->proxy, xfer->sock, xfer->address,
                                    xfer->port);
        
        xfer->hook_fd = weechat_hook_fd (xfer->sock,
                                         1, 0, 0,
                                         &xfer_chat_recv_cb,
                                         xfer);
    }
    
    /* for file receiving, connection is made in child process (blocking) */
    
    return 1;
}
Esempio n. 2
0
void
xfer_network_recv_file_fork (struct t_xfer *xfer)
{
    pid_t pid;
    int rc;

    if (!xfer_network_create_pipe (xfer))
        return;

    if (xfer->start_resume > 0)
        xfer->file = open (xfer->local_filename,
                           O_APPEND | O_WRONLY | O_NONBLOCK);
    else
        xfer->file = open (xfer->local_filename,
                           O_CREAT | O_TRUNC | O_WRONLY | O_NONBLOCK,
                           0644);

    switch (pid = fork ())
    {
        case -1:  /* fork failed */
            weechat_printf (NULL,
                            _("%s%s: unable to fork (%s)"),
                            weechat_prefix ("error"),
                            XFER_PLUGIN_NAME,
                            strerror (errno));
            xfer_close (xfer, XFER_STATUS_FAILED);
            xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
            return;
        case 0:  /* child process */
            rc = setuid (getuid ());
            (void) rc;
            close (xfer->child_read);
            switch (xfer->protocol)
            {
                case XFER_NO_PROTOCOL:
                    _exit (EXIT_SUCCESS);
                    break;
                case XFER_PROTOCOL_DCC:
                    xfer_dcc_recv_file_child (xfer);
                    break;
                case XFER_NUM_PROTOCOLS:
                    break;
            }
            _exit (EXIT_SUCCESS);
    }

    /* parent process */
    xfer->child_pid = pid;
    close (xfer->child_write);
    xfer->child_write = -1;
    xfer->hook_fd = weechat_hook_fd (xfer->child_read,
                                     1, 0, 0,
                                     &xfer_network_child_read_cb,
                                     xfer, NULL);
}
Esempio n. 3
0
void
xfer_network_send_file_fork (struct t_xfer *xfer)
{
    pid_t pid;
    
    if (!xfer_network_create_pipe (xfer))
        return;
    
    xfer->file = open (xfer->local_filename, O_RDONLY | O_NONBLOCK, 0644);
    
    switch (pid = fork ())
    {
        /* fork failed */
        case -1:
            weechat_printf (NULL,
                            _("%s%s: unable to fork"),
                            weechat_prefix ("error"), XFER_PLUGIN_NAME);
            xfer_close (xfer, XFER_STATUS_FAILED);
            xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
            return;
            /* child process */
        case 0:
            setuid (getuid ());
            close (xfer->child_read);
            switch (xfer->protocol)
            {
                case XFER_NO_PROTOCOL:
                    _exit (EXIT_SUCCESS);
                    break;
                case XFER_PROTOCOL_DCC:
                    xfer_dcc_send_file_child (xfer);
                    break;
                case XFER_NUM_PROTOCOLS:
                    break;
            }
            _exit (EXIT_SUCCESS);
    }
    
    /* parent process */
    xfer->child_pid = pid;
    close (xfer->child_write);
    xfer->child_write = -1;
    xfer->hook_fd = weechat_hook_fd (xfer->child_read,
                                     1, 0, 0,
                                     &xfer_network_child_read_cb,
                                     xfer);
}
Esempio n. 4
0
static gint
_wec_try_connect(gconstpointer user_data, gpointer data, gint remaining_calls)
{
    gint error = 0;
    if ( eventc_light_connection_is_connected(_wec_context.client, &error) )
        return WEECHAT_RC_OK;
    if ( _wec_context.connect_hook != NULL )
        return WEECHAT_RC_ERROR;

    if ( eventc_light_connection_connect(_wec_context.client) < 0 )
    {
        _wec_context.connect_hook = weechat_hook_timer(GPOINTER_TO_UINT(user_data) * 1000, 60, 1, _wec_try_connect, GUINT_TO_POINTER(GPOINTER_TO_UINT(user_data) * 2), NULL);
        return WEECHAT_RC_ERROR;
    }

    _wec_context.connect_hook = NULL;
    _wec_context.fd = eventc_light_connection_get_socket(_wec_context.client);
    _wec_context.fd_hook = weechat_hook_fd(_wec_context.fd, 1, 0, 0, _wec_fd_callback, NULL, NULL);
    return WEECHAT_RC_OK;
}
Esempio n. 5
0
int
irc_upgrade_read_cb (void *data,
                     struct t_upgrade_file *upgrade_file,
                     int object_id,
                     struct t_infolist *infolist)
{
    int flags, sock, size, i, index, nicks_count, num_items;
    long number;
    time_t join_time;
    char *buf, option_name[64], **nicks, *nick_join, *pos, *error;
    char **items;
    const char *buffer_name, *str, *nick;
    struct t_irc_nick *ptr_nick;
    struct t_irc_redirect *ptr_redirect;
    struct t_irc_notify *ptr_notify;
    struct t_gui_buffer *ptr_buffer;

    /* make C compiler happy */
    (void) data;
    (void) upgrade_file;

    weechat_infolist_reset_item_cursor (infolist);
    while (weechat_infolist_next (infolist))
    {
        switch (object_id)
        {
            case IRC_UPGRADE_TYPE_SERVER:
                irc_upgrade_current_server = irc_server_search (weechat_infolist_string (infolist, "name"));
                if (irc_upgrade_current_server)
                {
                    irc_upgrade_current_server->temp_server =
                        weechat_infolist_integer (infolist, "temp_server");
                    irc_upgrade_current_server->buffer = NULL;
                    buffer_name = weechat_infolist_string (infolist, "buffer_name");
                    if (buffer_name && buffer_name[0])
                    {
                        ptr_buffer = weechat_buffer_search (IRC_PLUGIN_NAME,
                                                            buffer_name);
                        if (ptr_buffer)
                            irc_upgrade_current_server->buffer = ptr_buffer;
                    }
                    irc_upgrade_current_server->index_current_address =
                        weechat_infolist_integer (infolist, "index_current_address");
                    str = weechat_infolist_string (infolist, "current_address");
                    if (str)
                    {
                        irc_upgrade_current_server->current_address = strdup (str);
                        irc_upgrade_current_server->current_port = weechat_infolist_integer (infolist, "current_port");
                    }
                    else
                    {
                        if (irc_upgrade_current_server->index_current_address < irc_upgrade_current_server->addresses_count)
                        {
                            irc_upgrade_current_server->current_address =
                                strdup (irc_upgrade_current_server->addresses_array[irc_upgrade_current_server->index_current_address]);
                            irc_upgrade_current_server->current_port =
                                irc_upgrade_current_server->ports_array[irc_upgrade_current_server->index_current_address];
                        }
                    }
                    str = weechat_infolist_string (infolist, "current_ip");
                    if (str)
                        irc_upgrade_current_server->current_ip = strdup (str);
                    sock = weechat_infolist_integer (infolist, "sock");
                    if (sock >= 0)
                    {
                        irc_upgrade_current_server->sock = sock;
                        irc_upgrade_current_server->hook_fd = weechat_hook_fd (irc_upgrade_current_server->sock,
                                                                               1, 0, 0,
                                                                               &irc_server_recv_cb,
                                                                               irc_upgrade_current_server);
                    }
                    irc_upgrade_current_server->is_connected = weechat_infolist_integer (infolist, "is_connected");
                    irc_upgrade_current_server->ssl_connected = weechat_infolist_integer (infolist, "ssl_connected");
                    irc_upgrade_current_server->disconnected = weechat_infolist_integer (infolist, "disconnected");
                    str = weechat_infolist_string (infolist, "unterminated_message");
                    if (str)
                        irc_upgrade_current_server->unterminated_message = strdup (str);
                    str = weechat_infolist_string (infolist, "nick");
                    if (str)
                        irc_server_set_nick (irc_upgrade_current_server, str);
                    str = weechat_infolist_string (infolist, "nick_modes");
                    if (str)
                        irc_upgrade_current_server->nick_modes = strdup (str);
                    str = weechat_infolist_string (infolist, "isupport");
                    if (str)
                        irc_upgrade_current_server->isupport = strdup (str);
                    /*
                     * "prefix" is not any more in this infolist (since
                     * WeeChat 0.3.4), but we read it to keep compatibility
                     * with old WeeChat versions, on /upgrade)
                     */
                    str = weechat_infolist_string (infolist, "prefix");
                    if (str)
                        irc_server_set_prefix_modes_chars (irc_upgrade_current_server, str);
                    /* "prefix_modes" is new in WeeChat 0.3.4 */
                    str = weechat_infolist_string (infolist, "prefix_modes");
                    if (str)
                    {
                        if (irc_upgrade_current_server->prefix_modes)
                            free (irc_upgrade_current_server->prefix_modes);
                        irc_upgrade_current_server->prefix_modes = strdup (str);
                    }
                    /* "prefix_chars" is new in WeeChat 0.3.4 */
                    str = weechat_infolist_string (infolist, "prefix_chars");
                    if (str)
                    {
                        if (irc_upgrade_current_server->prefix_chars)
                            free (irc_upgrade_current_server->prefix_chars);
                        irc_upgrade_current_server->prefix_chars = strdup (str);
                    }
                    irc_upgrade_current_server->nick_max_length = weechat_infolist_integer (infolist, "nick_max_length");
                    irc_upgrade_current_server->casemapping = weechat_infolist_integer (infolist, "casemapping");
                    str = weechat_infolist_string (infolist, "chantypes");
                    if (str)
                        irc_upgrade_current_server->chantypes = strdup (str);
                    str = weechat_infolist_string (infolist, "chanmodes");
                    if (str)
                        irc_upgrade_current_server->chanmodes = strdup (str);
                    else
                    {
                        str = irc_server_get_isupport_value (irc_upgrade_current_server,
                                                             "CHANMODES");
                        if (str)
                            irc_upgrade_current_server->chanmodes = strdup (str);
                    }
                    /* "monitor" is new in WeeChat 0.4.3 */
                    if (weechat_infolist_search_var (infolist, "monitor"))
                    {
                        irc_upgrade_current_server->monitor = weechat_infolist_integer (infolist, "monitor");
                    }
                    else
                    {
                        /* WeeChat <= 0.4.2 */
                        str = irc_server_get_isupport_value (irc_upgrade_current_server,
                                                             "MONITOR");
                        if (str)
                        {
                            error = NULL;
                            number = strtol (str, &error, 10);
                            if (error && !error[0])
                                irc_upgrade_current_server->monitor = (int)number;
                        }
                    }
                    irc_upgrade_current_server->reconnect_delay = weechat_infolist_integer (infolist, "reconnect_delay");
                    irc_upgrade_current_server->reconnect_start = weechat_infolist_time (infolist, "reconnect_start");
                    irc_upgrade_current_server->command_time = weechat_infolist_time (infolist, "command_time");
                    irc_upgrade_current_server->reconnect_join = weechat_infolist_integer (infolist, "reconnect_join");
                    irc_upgrade_current_server->disable_autojoin = weechat_infolist_integer (infolist, "disable_autojoin");
                    irc_upgrade_current_server->is_away = weechat_infolist_integer (infolist, "is_away");
                    str = weechat_infolist_string (infolist, "away_message");
                    if (str)
                        irc_upgrade_current_server->away_message = strdup (str);
                    irc_upgrade_current_server->away_time = weechat_infolist_time (infolist, "away_time");
                    irc_upgrade_current_server->lag = weechat_infolist_integer (infolist, "lag");
                    buf = weechat_infolist_buffer (infolist, "lag_check_time", &size);
                    if (buf)
                        memcpy (&(irc_upgrade_current_server->lag_check_time), buf, size);
                    irc_upgrade_current_server->lag_next_check = weechat_infolist_time (infolist, "lag_next_check");
                    irc_upgrade_current_server->lag_last_refresh = weechat_infolist_time (infolist, "lag_last_refresh");
                    irc_upgrade_current_server->last_user_message = weechat_infolist_time (infolist, "last_user_message");
                    irc_upgrade_current_server->last_away_check = weechat_infolist_time (infolist, "last_away_check");
                    irc_upgrade_current_server->last_data_purge = weechat_infolist_time (infolist, "last_data_purge");
                }
                break;
            case IRC_UPGRADE_TYPE_CHANNEL:
                if (irc_upgrade_current_server)
                {
                    irc_upgrade_current_channel = irc_channel_new (irc_upgrade_current_server,
                                                                   weechat_infolist_integer (infolist, "type"),
                                                                   weechat_infolist_string (infolist, "name"),
                                                                   0, 0);
                    if (irc_upgrade_current_channel)
                    {
                        str = weechat_infolist_string (infolist, "topic");
                        if (str)
                            irc_channel_set_topic (irc_upgrade_current_channel, str);
                        str = weechat_infolist_string (infolist, "modes");
                        if (str)
                            irc_upgrade_current_channel->modes = strdup (str);
                        irc_upgrade_current_channel->limit = weechat_infolist_integer (infolist, "limit");
                        str = weechat_infolist_string (infolist, "key");
                        if (str)
                            irc_upgrade_current_channel->key = strdup (str);
                        str = weechat_infolist_string (infolist, "join_msg_received");
                        if (str)
                        {
                            items = weechat_string_split (str, ",", 0, 0,
                                                          &num_items);
                            if (items)
                            {
                                for (i = 0; i < num_items; i++)
                                {
                                    weechat_hashtable_set (irc_upgrade_current_channel->join_msg_received,
                                                           items[i], "1");
                                }
                                weechat_string_free_split (items);
                            }
                        }
                        irc_upgrade_current_channel->checking_away = weechat_infolist_integer (infolist, "checking_away");
                        str = weechat_infolist_string (infolist, "away_message");
                        if (str)
                            irc_upgrade_current_channel->away_message = strdup (str);
                        irc_upgrade_current_channel->has_quit_server = weechat_infolist_integer (infolist, "has_quit_server");
                        irc_upgrade_current_channel->cycle = weechat_infolist_integer (infolist, "cycle");
                        irc_upgrade_current_channel->part = weechat_infolist_integer (infolist, "part");
                        irc_upgrade_current_channel->nick_completion_reset = weechat_infolist_integer (infolist, "nick_completion_reset");
                        for (i = 0; i < 2; i++)
                        {
                            index = 0;
                            while (1)
                            {
                                snprintf (option_name, sizeof (option_name),
                                          "nick_speaking%d_%05d", i, index);
                                nick = weechat_infolist_string (infolist, option_name);
                                if (!nick)
                                    break;
                                irc_channel_nick_speaking_add (irc_upgrade_current_channel,
                                                               nick,
                                                               i);
                                index++;
                            }
                        }
                        index = 0;
                        while (1)
                        {
                            snprintf (option_name, sizeof (option_name),
                                      "nick_speaking_time_nick_%05d", index);
                            nick = weechat_infolist_string (infolist, option_name);
                            if (!nick)
                                break;
                            snprintf (option_name, sizeof (option_name),
                                      "nick_speaking_time_time_%05d", index);
                            irc_channel_nick_speaking_time_add (irc_upgrade_current_server,
                                                                irc_upgrade_current_channel,
                                                                nick,
                                                                weechat_infolist_time (infolist,
                                                                                       option_name));
                            index++;
                        }
                        str = weechat_infolist_string (infolist, "join_smart_filtered");
                        if (str)
                        {
                            nicks = weechat_string_split (str, ",", 0, 0,
                                                          &nicks_count);
                            if (nicks)
                            {
                                for (i = 0; i < nicks_count; i++)
                                {
                                    pos = strchr (nicks[i], ':');
                                    if (pos)
                                    {
                                        nick_join = weechat_strndup (nicks[i],
                                                                     pos - nicks[i]);
                                        if (nick_join)
                                        {
                                            error = NULL;
                                            number = strtol (pos + 1, &error, 10);
                                            if (error && !error[0])
                                            {
                                                join_time = (time_t)number;
                                                irc_channel_join_smart_filtered_add (irc_upgrade_current_channel,
                                                                                     nick_join,
                                                                                     join_time);
                                            }
                                            free (nick_join);
                                        }
                                    }
                                }
                                weechat_string_free_split (nicks);
                            }
                        }
                    }
                }
                break;
            case IRC_UPGRADE_TYPE_NICK:
                if (irc_upgrade_current_server && irc_upgrade_current_channel)
                {
                    ptr_nick = irc_nick_new (irc_upgrade_current_server,
                                             irc_upgrade_current_channel,
                                             weechat_infolist_string (infolist, "name"),
                                             weechat_infolist_string (infolist, "host"),
                                             weechat_infolist_string (infolist, "prefixes"),
                                             weechat_infolist_integer (infolist, "away"));
                    if (ptr_nick)
                    {
                        /*
                         * "flags" is not any more in this infolist (since
                         * WeeChat 0.3.4), but we read it to keep compatibility
                         * with old WeeChat versions, on /upgrade)
                         * We try to restore prefixes with old flags, but
                         * this is approximation, it's not sure we will
                         * restore good prefixes here (a /names on channel
                         * will fix problem if prefixes are wrong).
                         * Flags were defined in irc-nick.h:
                         *   #define IRC_NICK_CHANOWNER  1
                         *   #define IRC_NICK_CHANADMIN  2
                         *   #define IRC_NICK_CHANADMIN2 4
                         *   #define IRC_NICK_OP         8
                         *   #define IRC_NICK_HALFOP     16
                         *   #define IRC_NICK_VOICE      32
                         *   #define IRC_NICK_AWAY       64
                         *   #define IRC_NICK_CHANUSER   128
                         */
                        flags = weechat_infolist_integer (infolist, "flags");
                        if (flags > 0)
                        {
                            /* channel owner */
                            if (flags & 1)
                            {
                                irc_nick_set_mode (irc_upgrade_current_server,
                                                   irc_upgrade_current_channel,
                                                   ptr_nick, 1, 'q');
                            }
                            /* channel admin */
                            if ((flags & 2) || (flags & 4))
                            {
                                irc_nick_set_mode (irc_upgrade_current_server,
                                                   irc_upgrade_current_channel,
                                                   ptr_nick, 1, 'a');
                            }
                            /* op */
                            if (flags & 8)
                            {
                                irc_nick_set_mode (irc_upgrade_current_server,
                                                   irc_upgrade_current_channel,
                                                   ptr_nick, 1, 'o');
                            }
                            /* half-op */
                            if (flags & 16)
                            {
                                irc_nick_set_mode (irc_upgrade_current_server,
                                                   irc_upgrade_current_channel,
                                                   ptr_nick, 1, 'h');
                            }
                            /* voice */
                            if (flags & 32)
                            {
                                irc_nick_set_mode (irc_upgrade_current_server,
                                                   irc_upgrade_current_channel,
                                                   ptr_nick, 1, 'v');
                            }
                            /* away */
                            if (flags & 64)
                            {
                                irc_nick_set_away (irc_upgrade_current_server,
                                                   irc_upgrade_current_channel,
                                                   ptr_nick, 1);
                            }
                            /* channel user */
                            if (flags & 128)
                            {
                                irc_nick_set_mode (irc_upgrade_current_server,
                                                   irc_upgrade_current_channel,
                                                   ptr_nick, 1, 'u');
                            }
                        }
                    }
                }
                break;
            case IRC_UPGRADE_TYPE_REDIRECT:
                if (irc_upgrade_current_server)
                {
                    ptr_redirect = irc_redirect_new_with_commands (
                        irc_upgrade_current_server,
                        weechat_infolist_string (infolist, "pattern"),
                        weechat_infolist_string (infolist, "signal"),
                        weechat_infolist_integer (infolist, "count"),
                        weechat_infolist_string (infolist, "string"),
                        weechat_infolist_integer (infolist, "timeout"),
                        weechat_infolist_string (infolist, "cmd_start"),
                        weechat_infolist_string (infolist, "cmd_stop"),
                        weechat_infolist_string (infolist, "cmd_extra"),
                        weechat_infolist_string (infolist, "cmd_filter"));
                    if (ptr_redirect)
                    {
                        ptr_redirect->current_count = weechat_infolist_integer (infolist, "current_count");
                        str = weechat_infolist_string (infolist, "command");
                        if (str)
                            ptr_redirect->command = strdup (str);
                        ptr_redirect->assigned_to_command = weechat_infolist_integer (infolist, "assigned_to_command");
                        ptr_redirect->start_time = weechat_infolist_time (infolist, "start_time");
                        ptr_redirect->cmd_start_received = weechat_infolist_integer (infolist, "cmd_start_received");
                        ptr_redirect->cmd_stop_received = weechat_infolist_integer (infolist, "cmd_stop_received");
                        str = weechat_infolist_string (infolist, "output");
                        if (str)
                            ptr_redirect->output = strdup (str);
                        ptr_redirect->output_size = weechat_infolist_integer (infolist, "output_size");
                    }
                }
                break;
            case IRC_UPGRADE_TYPE_REDIRECT_PATTERN:
                irc_redirect_pattern_new (
                    weechat_infolist_string (infolist, "name"),
                    weechat_infolist_integer (infolist, "temp_pattern"),
                    weechat_infolist_integer (infolist, "timeout"),
                    weechat_infolist_string (infolist, "cmd_start"),
                    weechat_infolist_string (infolist, "cmd_stop"),
                    weechat_infolist_string (infolist, "cmd_extra"));
                break;
            case IRC_UPGRADE_TYPE_NOTIFY:
                if (irc_upgrade_current_server)
                {
                    ptr_notify = irc_notify_search (irc_upgrade_current_server,
                                                    weechat_infolist_string (infolist, "nick"));
                    if (ptr_notify)
                    {
                        ptr_notify->is_on_server = weechat_infolist_integer (infolist, "is_on_server");
                        str = weechat_infolist_string (infolist, "away_message");
                        if (str)
                            ptr_notify->away_message = strdup (str);
                    }
                }
                break;
            case IRC_UPGRADE_TYPE_RAW_MESSAGE:
                irc_raw_message_add_to_list (weechat_infolist_time (infolist, "date"),
                                             weechat_infolist_string (infolist, "prefix"),
                                             weechat_infolist_string (infolist, "message"));
                break;
        }
    }

    return WEECHAT_RC_OK;
}
Esempio n. 6
0
int
xfer_network_fd_cb (void *arg_xfer, int fd)
{
    struct t_xfer *xfer;
    int sock;
    struct sockaddr_in addr;
    socklen_t length;
    
    /* make C compiler happy */
    (void) fd;
    
    xfer = (struct t_xfer *)arg_xfer;
    
    if (xfer->status == XFER_STATUS_CONNECTING)
    {
        if (xfer->type == XFER_TYPE_FILE_SEND)
        {
            xfer->last_activity = time (NULL);
            length = sizeof (addr);
            sock = accept (xfer->sock,
                           (struct sockaddr *) &addr, &length);
            weechat_unhook (xfer->hook_fd);
            xfer->hook_fd = NULL;
            close (xfer->sock);
            xfer->sock = -1;
            if (sock < 0)
            {
                weechat_printf (NULL,
                                _("%s%s: unable to create socket for sending "
                                  "file"),
                                weechat_prefix ("error"), XFER_PLUGIN_NAME);
                xfer_close (xfer, XFER_STATUS_FAILED);
                xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
                return WEECHAT_RC_OK;
            }
            xfer->sock = sock;
            if (fcntl (xfer->sock, F_SETFL, O_NONBLOCK) == -1)
            {
                weechat_printf (NULL,
                                _("%s%s: unable to set option \"nonblock\" "
                                  "for socket"),
                                weechat_prefix ("error"), XFER_PLUGIN_NAME);
                xfer_close (xfer, XFER_STATUS_FAILED);
                xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
                return WEECHAT_RC_OK;
            }
            xfer->address = ntohl (addr.sin_addr.s_addr);
            xfer->status = XFER_STATUS_ACTIVE;
            xfer->start_transfer = time (NULL);
            xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
            xfer_network_send_file_fork (xfer);
        }
        /*
        if (xfer->type == XFER_TYPE_FILE_RECV)
        {
            if (xfer->child_read != -1)
                irc_dcc_file_child_read (dcc);
        }
        */
    }
    
    if (xfer->status == XFER_STATUS_WAITING)
    {
        if (xfer->type == XFER_TYPE_CHAT_SEND)
        {
            length = sizeof (addr);
            sock = accept (xfer->sock, (struct sockaddr *) &addr, &length);
            weechat_unhook (xfer->hook_fd);
            xfer->hook_fd = NULL;
            close (xfer->sock);
            xfer->sock = -1;
            if (sock < 0)
            {
                weechat_printf (NULL,
                                _("%s%s: unable to create socket for sending "
                                  "file"),
                                weechat_prefix ("error"), XFER_PLUGIN_NAME);
                xfer_close (xfer, XFER_STATUS_FAILED);
                xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
                return WEECHAT_RC_OK;
            }
            xfer->sock = sock;
            if (fcntl (xfer->sock, F_SETFL, O_NONBLOCK) == -1)
            {
                weechat_printf (NULL,
                                _("%s%s: unable to set option \"nonblock\" "
                                  "for socket"),
                                weechat_prefix ("error"), XFER_PLUGIN_NAME);
                xfer_close (xfer, XFER_STATUS_FAILED);
                xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
                return WEECHAT_RC_OK;
            }
            xfer->address = ntohl (addr.sin_addr.s_addr);
            xfer->status = XFER_STATUS_ACTIVE;
            xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
            xfer->hook_fd = weechat_hook_fd (xfer->sock,
                                             1, 0, 0,
                                             &xfer_chat_recv_cb,
                                             xfer);
            xfer_chat_open_buffer (xfer);
        }
    }
    /*
    if (xfer->status == XFER_STATUS_ACTIVE)
    {
        if (XFER_IS_CHAT(dcc->type))
        {
            irc_dcc_chat_recv (dcc);
        }
        else
            irc_dcc_file_child_read (dcc);
    }
    */
    return WEECHAT_RC_OK;
}
Esempio n. 7
0
struct t_relay_client *
relay_client_new (int sock, const char *address, struct t_relay_server *server)
{
    struct t_relay_client *new_client;

    new_client = malloc (sizeof (*new_client));
    if (new_client)
    {
        new_client->id = (relay_clients) ? relay_clients->id + 1 : 1;
        new_client->sock = sock;
        new_client->address = strdup ((address) ? address : "?");
        new_client->status = RELAY_STATUS_CONNECTED;
        new_client->protocol = server->protocol;
        new_client->protocol_args = (server->protocol_args) ? strdup (server->protocol_args) : NULL;
        new_client->listen_start_time = server->start_time;
        new_client->start_time = time (NULL);
        new_client->end_time = 0;
        new_client->hook_fd = NULL;
        new_client->last_activity = new_client->start_time;
        new_client->bytes_recv = 0;
        new_client->bytes_sent = 0;

        new_client->protocol_data = NULL;
        switch (new_client->protocol)
        {
            case RELAY_PROTOCOL_WEECHAT:
                relay_weechat_alloc (new_client);
                break;
            case RELAY_PROTOCOL_IRC:
                relay_irc_alloc (new_client);
                break;
            case RELAY_NUM_PROTOCOLS:
                break;
        }

        new_client->prev_client = NULL;
        new_client->next_client = relay_clients;
        if (relay_clients)
            relay_clients->prev_client = new_client;
        else
            last_relay_client = new_client;
        relay_clients = new_client;

        weechat_printf (NULL,
                        _("%s: new client from %s%s%s on port %d (id: %d, relaying: %s%s%s)"),
                        RELAY_PLUGIN_NAME,
                        RELAY_COLOR_CHAT_HOST,
                        new_client->address,
                        RELAY_COLOR_CHAT,
                        server->port,
                        new_client->id,
                        relay_protocol_string[new_client->protocol],
                        (new_client->protocol_args) ? "." : "",
                        (new_client->protocol_args) ? new_client->protocol_args : "");

        new_client->hook_fd = weechat_hook_fd (new_client->sock,
                                               1, 0, 0,
                                               &relay_client_recv_cb,
                                               new_client);

        relay_client_count++;

        if (!relay_buffer
            && weechat_config_boolean (relay_config_look_auto_open_buffer))
        {
            relay_buffer_open ();
        }

        relay_buffer_refresh (WEECHAT_HOTLIST_PRIVATE);
    }
    else
    {
        weechat_printf (NULL,
                        _("%s%s: not enough memory for new client"),
                        weechat_prefix ("error"), RELAY_PLUGIN_NAME);
    }

    return new_client;
}
Esempio n. 8
0
int
relay_server_create_socket (struct t_relay_server *server)
{
    int domain, set, max_clients, addr_size, rc;
    struct sockaddr_in server_addr;
    struct sockaddr_in6 server_addr6;
    struct sockaddr_un server_addr_unix;
    const char *bind_address;
    void *ptr_addr;

    bind_address = weechat_config_string (relay_config_network_bind_address);

    if (server->ipv6)
    {
        domain = AF_INET6;
        memset (&server_addr6, 0, sizeof (struct sockaddr_in6));
        server_addr6.sin6_family = domain;
        server_addr6.sin6_port = htons (server->port);
        server_addr6.sin6_addr = in6addr_any;
        if (bind_address && bind_address[0])
        {
            if (!inet_pton (domain, bind_address, &server_addr6.sin6_addr))
            {
                weechat_printf (NULL,
                                /* TRANSLATORS: second "%s" is "IPv4" or "IPv6" */
                                _("%s%s: invalid bind address \"%s\" for %s"),
                                weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                                bind_address, "IPv6");
                return 0;
            }
        }
        ptr_addr = &server_addr6;
        addr_size = sizeof (struct sockaddr_in6);
    }
    else if (server->ipv4)
    {
        domain = AF_INET;
        memset (&server_addr, 0, sizeof (struct sockaddr_in));
        server_addr.sin_family = domain;
        server_addr.sin_port = htons (server->port);
        server_addr.sin_addr.s_addr = INADDR_ANY;
        if (bind_address && bind_address[0])
        {
            if (!inet_pton (domain, bind_address, &server_addr.sin_addr))
            {
                weechat_printf (NULL,
                                /* TRANSLATORS: second "%s" is "IPv4" or "IPv6" */
                                _("%s%s: invalid bind address \"%s\" for %s"),
                                weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                                bind_address, "IPv4");
                return 0;
            }
        }
        ptr_addr = &server_addr;
        addr_size = sizeof (struct sockaddr_in);
    }
    else
    {
        domain = AF_UNIX;
        memset (&server_addr_unix, 0, sizeof (struct sockaddr_un));
        server_addr_unix.sun_family = domain;
        strncpy (server_addr_unix.sun_path, server->path,
                 sizeof (server_addr_unix.sun_path));
        ptr_addr = &server_addr_unix;
        addr_size = sizeof (struct sockaddr_un);
        if (!relay_config_check_path_length (server->path))
        {
            weechat_printf (NULL,
                            _("%s%s: socket path \"%s\" is invalid"),
                            weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                            server->path);
            return 0;
        }
        rc = relay_config_check_path_available (server->path);
        switch (rc)
        {
            case -1:
                weechat_printf (NULL,
                                _("%s%s: socket path \"%s\" already exists "
                                  "and is not a socket"),
                                weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                                server->path);
                break;
            case -2:
                weechat_printf (NULL,
                                _("%s%s: socket path \"%s\" is invalid"),
                                weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                                server->path);
        }
        if (rc < 0)
            return 0;
        /* just in case a socket already exists */
        unlink (server->path);
    }


    /* create socket */
    server->sock = socket (domain, SOCK_STREAM, 0);
    if (server->sock < 0)
    {
        weechat_printf (NULL,
                        _("%s%s: cannot create socket: error %d %s"),
                        weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                        errno, strerror (errno));
        if (errno == EAFNOSUPPORT)
        {
            weechat_printf (NULL,
                            _("%s%s: try /set relay.network.ipv6 off"),
                            weechat_prefix ("error"), RELAY_PLUGIN_NAME);
        }
        return 0;
    }

#if defined(IPV6_V6ONLY) && !defined(__OpenBSD__)
    /* set option IPV6_V6ONLY to 0 or 1 */
    if (server->ipv6)
    {
        set = (server->ipv4) ? 0 : 1;
        if (setsockopt (server->sock, IPPROTO_IPV6, IPV6_V6ONLY,
                        (void *) &set, sizeof (set)) < 0)
        {
            weechat_printf (NULL,
                            _("%s%s: cannot set socket option \"%s\" "
                              "to %d: error %d %s"),
                            weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                            "IPV6_V6ONLY", set, errno, strerror (errno));
            close (server->sock);
            server->sock = -1;
            return 0;
        }
    }
#endif

    /* set option SO_REUSEADDR to 1 */
    set = 1;
    if (setsockopt (server->sock, SOL_SOCKET, SO_REUSEADDR,
                    (void *) &set, sizeof (set)) < 0)
    {
        weechat_printf (NULL,
                        _("%s%s: cannot set socket option \"%s\" to %d: "
                          "error %d %s"),
                        weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                        "SO_REUSEADDR", set, errno, strerror (errno));
        close (server->sock);
        server->sock = -1;
        return 0;
    }

    /* set option SO_KEEPALIVE to 1 */
    set = 1;
    if (setsockopt (server->sock, SOL_SOCKET, SO_KEEPALIVE,
                    (void *) &set, sizeof (set)) < 0)
    {
        weechat_printf (NULL,
                        _("%s%s: cannot set socket option \"%s\" to %d: "
                          "error %d %s"),
                        weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                        "SO_KEEPALIVE", set, errno, strerror (errno));
        close (server->sock);
        server->sock = -1;
        return 0;
    }

    /* bind */
    if (bind (server->sock, (struct sockaddr *)ptr_addr, addr_size) < 0)
    {
        if (server->unix_socket)
        {
            weechat_printf (NULL,
                            _("%s%s: cannot \"bind\" on path %s (%s): "
                              "error %d %s"),
                            weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                            server->path, server->protocol_string,
                            errno, strerror (errno));
        }
        else
        {
            weechat_printf (NULL,
                            _("%s%s: cannot \"bind\" on port %d (%s): "
                              "error %d %s"),
                            weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                            server->port, server->protocol_string,
                            errno, strerror (errno));
        }
        close (server->sock);
        server->sock = -1;
        return 0;
    }

    /* change permissions: only the owner can use the unix socket */
    if (server->unix_socket)
        chmod (server->path, 0700);

#ifdef SOMAXCONN
    if (listen (server->sock, SOMAXCONN) != 0)
#else
    if (listen (server->sock, 1) != 0)
#endif
    {
        if (server->unix_socket)
        {
            weechat_printf (NULL,
                            _("%s%s: cannot \"listen\" on path %s (%s): "
                              "error %d %s"),
                            weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                            server->path, server->protocol_string,
                            errno, strerror (errno));
        }
        else
        {
            weechat_printf (NULL,
                            _("%s%s: cannot \"listen\" on port %d (%s): "
                              "error %d %s"),
                            weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                            server->port, server->protocol_string,
                            errno, strerror (errno));
        }
        close (server->sock);
        server->sock = -1;
        return 0;
    }

    max_clients = weechat_config_integer (relay_config_network_max_clients);
    if (max_clients > 0)
    {
        if (server->unix_socket)
        {
            weechat_printf (
                NULL,
                NG_("%s: listening on path %s (relay: %s, %s, max %d client)",
                    "%s: listening on path %s (relay: %s, %s, max %d clients)",
                    max_clients),
                RELAY_PLUGIN_NAME,
                server->path,
                server->protocol_string,
                ((server->ipv4 && server->ipv6) ? "IPv4+6" : ((server->ipv6) ? "IPv6" : ((server->ipv4) ? "IPv4" : "UNIX"))),
                max_clients);
        }
        else
        {
            weechat_printf (
                NULL,
                NG_("%s: listening on port %d (relay: %s, %s, max %d client)",
                    "%s: listening on port %d (relay: %s, %s, max %d clients)",
                    max_clients),
                RELAY_PLUGIN_NAME,
                server->port,
                server->protocol_string,
                ((server->ipv4 && server->ipv6) ? "IPv4+6" : ((server->ipv6) ? "IPv6" : ((server->ipv4) ? "IPv4" : "UNIX"))),
                max_clients);
        }
    }
    else
    {
        if (server->unix_socket)
        {
            weechat_printf (
                NULL,
                _("%s: listening on path %s (relay: %s, %s)"),
                RELAY_PLUGIN_NAME,
                server->path,
                server->protocol_string,
                ((server->ipv4 && server->ipv6) ? "IPv4+6" : ((server->ipv6) ? "IPv6" : ((server->ipv4) ? "IPv4" : "UNIX"))));
        }
        else
        {
            weechat_printf (
                NULL,
                _("%s: listening on port %d (relay: %s, %s)"),
                RELAY_PLUGIN_NAME,
                server->port,
                server->protocol_string,
                ((server->ipv4 && server->ipv6) ? "IPv4+6" : ((server->ipv6) ? "IPv6" : ((server->ipv4) ? "IPv4" : "UNIX"))));
        }
    }
    server->hook_fd = weechat_hook_fd (server->sock,
                                       1, 0, 0,
                                       &relay_server_sock_cb,
                                       server, NULL);

    server->start_time = time (NULL);

    return 1;
}
Esempio n. 9
0
int
xfer_network_connect (struct t_xfer *xfer)
{
    int flags;

    if (xfer->type == XFER_TYPE_CHAT_SEND)
        xfer->status = XFER_STATUS_WAITING;
    else
        xfer->status = XFER_STATUS_CONNECTING;

    if (XFER_IS_SEND(xfer->type))
    {
        /* create socket */
        if (xfer->sock < 0)
        {
            xfer->sock = socket (xfer->local_address->sa_family, SOCK_STREAM,
                                 0);
            if (xfer->sock < 0)
                return 0;
        }

        /* listen to socket */
        flags = fcntl (xfer->sock, F_GETFL);
        if (flags == -1)
            flags = 0;
        if (fcntl (xfer->sock, F_SETFL, flags | O_NONBLOCK) == -1)
            return 0;
        if (listen (xfer->sock, 1) == -1)
            return 0;
        if (fcntl (xfer->sock, F_SETFL, flags) == -1)
            return 0;

        xfer->hook_fd = weechat_hook_fd (xfer->sock,
                                         1, 0, 0,
                                         &xfer_network_fd_cb,
                                         xfer, NULL);

        /* add timeout */
        if (weechat_config_integer (xfer_config_network_timeout) > 0)
        {
            xfer->hook_timer = weechat_hook_timer (weechat_config_integer (xfer_config_network_timeout) * 1000,
                                                   0, 1,
                                                   &xfer_network_timer_cb,
                                                   xfer, NULL);
        }
    }

    /* for chat receiving, connect to listening host */
    if (xfer->type == XFER_TYPE_CHAT_RECV)
    {
        xfer->hook_connect = weechat_hook_connect (xfer->proxy,
                                                   xfer->remote_address_str,
                                                   xfer->port, 1, 0, NULL, NULL,
                                                   0, "NONE", NULL,
                                                   &xfer_network_connect_chat_recv_cb,
                                                   xfer, NULL);
    }

    /* for file receiving, connection is made in child process (blocking) */

    return 1;
}
Esempio n. 10
0
int
xfer_network_connect_chat_recv_cb (const void *pointer, void *data,
                                   int status, int gnutls_rc,
                                   int sock, const char *error,
                                   const char *ip_address)
{
    struct t_xfer *xfer;
    int flags;

    /* make C compiler happy */
    (void) data;
    (void) gnutls_rc;
    (void) ip_address;

    xfer = (struct t_xfer*)pointer;

    weechat_unhook (xfer->hook_connect);
    xfer->hook_connect = NULL;

    /* connection OK? */
    if (status == WEECHAT_HOOK_CONNECT_OK)
    {
        xfer->sock = sock;

        flags = fcntl (xfer->sock, F_GETFL);
        if (flags == -1)
            flags = 0;
        if (fcntl (xfer->sock, F_SETFL, flags | O_NONBLOCK) == -1)
        {
            weechat_printf (NULL,
                            _("%s%s: unable to set option \"nonblock\" "
                              "for socket: error %d %s"),
                            weechat_prefix ("error"), XFER_PLUGIN_NAME,
                            errno, strerror (errno));
            close (xfer->sock);
            xfer->sock = -1;
            xfer_close (xfer, XFER_STATUS_FAILED);
            xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
            return WEECHAT_RC_OK;
        }

        xfer->hook_fd = weechat_hook_fd (xfer->sock,
                                         1, 0, 0,
                                         &xfer_chat_recv_cb,
                                         xfer, NULL);

        xfer_chat_open_buffer (xfer);
        xfer->status = XFER_STATUS_ACTIVE;
        xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);

        return WEECHAT_RC_OK;
    }

    /* connection error */
    switch (status)
    {
        case WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND:
            weechat_printf (NULL,
                            (xfer->proxy && xfer->proxy[0]) ?
                            _("%s%s: proxy address \"%s\" not found") :
                            _("%s%s: address \"%s\" not found"),
                            weechat_prefix ("error"), XFER_PLUGIN_NAME,
                            xfer->remote_address_str);
            break;
        case WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND:
            weechat_printf (NULL,
                            (xfer->proxy && xfer->proxy[0]) ?
                            _("%s%s: proxy IP address not found") :
                            _("%s%s: IP address not found"),
                            weechat_prefix ("error"), XFER_PLUGIN_NAME);
            break;
        case WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED:
            weechat_printf (NULL,
                            (xfer->proxy && xfer->proxy[0]) ?
                            _("%s%s: proxy connection refused") :
                            _("%s%s: connection refused"),
                            weechat_prefix ("error"), XFER_PLUGIN_NAME);
            break;
        case WEECHAT_HOOK_CONNECT_PROXY_ERROR:
            weechat_printf (NULL,
                            _("%s%s: proxy fails to establish connection to "
                              "server (check username/password if used and if "
                              "server address/port is allowed by proxy)"),
                            weechat_prefix ("error"), XFER_PLUGIN_NAME);
            break;
        case WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR:
            weechat_printf (NULL,
                            _("%s%s: unable to set local hostname/IP"),
                            weechat_prefix ("error"), XFER_PLUGIN_NAME);
            break;
        case WEECHAT_HOOK_CONNECT_MEMORY_ERROR:
            weechat_printf (NULL,
                            _("%s%s: not enough memory (%s)"),
                            weechat_prefix ("error"), XFER_PLUGIN_NAME,
                            (error) ? error : "-");
            break;
        case WEECHAT_HOOK_CONNECT_TIMEOUT:
            weechat_printf (NULL,
                            _("%s%s: timeout"),
                            weechat_prefix ("error"), XFER_PLUGIN_NAME);
            break;
        case WEECHAT_HOOK_CONNECT_SOCKET_ERROR:
            weechat_printf (NULL,
                            _("%s%s: unable to create socket"),
                            weechat_prefix ("error"), XFER_PLUGIN_NAME);
            break;
        default:
            weechat_printf (NULL,
                            _("%s%s: unable to connect: unexpected error (%d)"),
                            weechat_prefix ("error"), XFER_PLUGIN_NAME,
                            status);
            break;
    }
    if (error && error[0])
    {
        weechat_printf (NULL,
                        _("%s%s: error: %s"),
                        weechat_prefix ("error"), XFER_PLUGIN_NAME, error);
    }

    xfer_close (xfer, XFER_STATUS_FAILED);
    xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);

    return WEECHAT_RC_OK;
}
Esempio n. 11
0
int
xfer_network_fd_cb (const void *pointer, void *data, int fd)
{
    struct t_xfer *xfer;
    int sock, flags, error;
    struct sockaddr_storage addr;
    socklen_t length;
    char str_address[NI_MAXHOST];

    /* make C compiler happy */
    (void) data;
    (void) fd;

    length = sizeof (addr);
    memset (&addr, 0, length);
    xfer = (struct t_xfer *)pointer;

    if (xfer->status == XFER_STATUS_CONNECTING)
    {
        if (xfer->type == XFER_TYPE_FILE_SEND)
        {
            xfer->last_activity = time (NULL);
            sock = accept (xfer->sock,
                           (struct sockaddr *) &addr, &length);
            error = errno;
            weechat_unhook (xfer->hook_fd);
            xfer->hook_fd = NULL;
            close (xfer->sock);
            xfer->sock = -1;
            if (sock < 0)
            {
                weechat_printf (NULL,
                                _("%s%s: unable to create socket for sending "
                                  "file: error %d %s"),
                                weechat_prefix ("error"), XFER_PLUGIN_NAME,
                                error, strerror (error));
                xfer_close (xfer, XFER_STATUS_FAILED);
                xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
                return WEECHAT_RC_OK;
            }
            xfer->sock = sock;
            flags = fcntl (xfer->sock, F_GETFL);
            if (flags == -1)
                flags = 0;
            if (fcntl (xfer->sock, F_SETFL, flags | O_NONBLOCK) == -1)
            {
                weechat_printf (NULL,
                                _("%s%s: unable to set option \"nonblock\" "
                                  "for socket: error %d %s"),
                                weechat_prefix ("error"), XFER_PLUGIN_NAME,
                                errno, strerror (errno));
                xfer_close (xfer, XFER_STATUS_FAILED);
                xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
                return WEECHAT_RC_OK;
            }
            error = getnameinfo ((struct sockaddr *)&addr, length, str_address,
                                 sizeof (str_address), NULL, 0, NI_NUMERICHOST);
            if (error != 0)
            {
                snprintf (str_address, sizeof (str_address),
                          "error: %s", gai_strerror (error));
            }
            xfer_set_remote_address (xfer, (struct sockaddr *)&addr, length,
                                     str_address);
            xfer->status = XFER_STATUS_ACTIVE;
            xfer->start_transfer = time (NULL);
            xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
            xfer_network_send_file_fork (xfer);
        }
    }

    if (xfer->status == XFER_STATUS_WAITING)
    {
        if (xfer->type == XFER_TYPE_CHAT_SEND)
        {
            length = sizeof (addr);
            sock = accept (xfer->sock, (struct sockaddr *) &addr, &length);
            error = errno;
            weechat_unhook (xfer->hook_fd);
            xfer->hook_fd = NULL;
            close (xfer->sock);
            xfer->sock = -1;
            if (sock < 0)
            {
                weechat_printf (NULL,
                                _("%s%s: unable to create socket for sending "
                                  "file: error %d %s"),
                                weechat_prefix ("error"), XFER_PLUGIN_NAME,
                                error, strerror (error));
                xfer_close (xfer, XFER_STATUS_FAILED);
                xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
                return WEECHAT_RC_OK;
            }
            xfer->sock = sock;
            flags = fcntl (xfer->sock, F_GETFL);
            if (flags == -1)
                flags = 0;
            if (fcntl (xfer->sock, F_SETFL, flags | O_NONBLOCK) == -1)
            {
                weechat_printf (NULL,
                                _("%s%s: unable to set option \"nonblock\" "
                                  "for socket: error %d %s"),
                                weechat_prefix ("error"), XFER_PLUGIN_NAME,
                                errno, strerror (errno));
                xfer_close (xfer, XFER_STATUS_FAILED);
                xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
                return WEECHAT_RC_OK;
            }
            error = getnameinfo ((struct sockaddr *)&addr, length, str_address,
                                 sizeof (str_address), NULL, 0, NI_NUMERICHOST);
            if (error != 0)
            {
                snprintf (str_address, sizeof (str_address),
                          "error: %s", gai_strerror (error));
            }
            xfer_set_remote_address (xfer, (struct sockaddr *)&addr, length,
                                     str_address);
            xfer->status = XFER_STATUS_ACTIVE;
            xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
            xfer->hook_fd = weechat_hook_fd (xfer->sock,
                                             1, 0, 0,
                                             &xfer_chat_recv_cb,
                                             xfer, NULL);
            xfer_chat_open_buffer (xfer);
        }
    }

    return WEECHAT_RC_OK;
}
Esempio n. 12
0
void
xfer_network_send_file_fork (struct t_xfer *xfer)
{
    pid_t pid;
    int rc;

    if (!xfer_network_create_pipe (xfer))
        return;

    xfer->file = open (xfer->local_filename, O_RDONLY | O_NONBLOCK, 0644);

    switch (pid = fork ())
    {
        case -1:  /* fork failed */
            weechat_printf (NULL,
                            _("%s%s: unable to fork (%s)"),
                            weechat_prefix ("error"),
                            XFER_PLUGIN_NAME,
                            strerror (errno));
            xfer_close (xfer, XFER_STATUS_FAILED);
            xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE);
            return;
        case 0:  /* child process */
            rc = setuid (getuid ());
            (void) rc;
            close (xfer->child_read);
            switch (xfer->protocol)
            {
                case XFER_NO_PROTOCOL:
                    _exit (EXIT_SUCCESS);
                    break;
                case XFER_PROTOCOL_DCC:
                    xfer_dcc_send_file_child (xfer);
                    break;
                case XFER_NUM_PROTOCOLS:
                    break;
            }
            _exit (EXIT_SUCCESS);
    }

    weechat_printf (NULL,
                    _("%s: sending file to %s (%s, %s.%s), "
                      "name: %s (local filename: %s), %llu bytes (protocol: %s)"),
                    XFER_PLUGIN_NAME,
                    xfer->remote_nick,
                    xfer->remote_address_str,
                    xfer->plugin_name,
                    xfer->plugin_id,
                    xfer->filename,
                    xfer->local_filename,
                    xfer->size,
                    xfer_protocol_string[xfer->protocol]);

    /* parent process */
    xfer->child_pid = pid;
    close (xfer->child_write);
    xfer->child_write = -1;
    xfer->hook_fd = weechat_hook_fd (xfer->child_read,
                                     1, 0, 0,
                                     &xfer_network_child_read_cb,
                                     xfer, NULL);
}
Esempio n. 13
0
int
relay_server_create_socket (struct t_relay_server *server)
{
    int set, max_clients;
    struct sockaddr_in server_addr;

    server->sock = socket (AF_INET, SOCK_STREAM, 0);
    if (server->sock < 0)
    {
        weechat_printf (NULL,
                        _("%s%s: cannot create socket"),
                        weechat_prefix ("error"), RELAY_PLUGIN_NAME);
        return 0;
    }

    set = 1;
    if (setsockopt (server->sock, SOL_SOCKET, SO_REUSEADDR,
                    (void *) &set, sizeof (set)) < 0)
    {
        weechat_printf (NULL,
                        _("%s%s: cannot set socket option "
                          "\"SO_REUSEADDR\""),
                        weechat_prefix ("error"), RELAY_PLUGIN_NAME);
        close (server->sock);
        server->sock = -1;
        return 0;
    }

    set = 1;
    if (setsockopt (server->sock, SOL_SOCKET, SO_KEEPALIVE,
                    (void *) &set, sizeof (set)) < 0)
    {
        weechat_printf (NULL,
                        _("%s%s: cannot set socket option "
                          "\"SO_KEEPALIVE\""),
                        weechat_prefix ("error"), RELAY_PLUGIN_NAME);
        close (server->sock);
        server->sock = -1;
        return 0;
    }

    memset(&server_addr, 0, sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    if (weechat_config_string (relay_config_network_bind_address)
        && weechat_config_string (relay_config_network_bind_address)[0])
    {
        server_addr.sin_addr.s_addr = inet_addr (weechat_config_string (relay_config_network_bind_address));
    }
    else
    {
        server_addr.sin_addr.s_addr = INADDR_ANY;
    }
    server_addr.sin_port = htons (server->port);

    if (bind (server->sock, (struct sockaddr *) &server_addr,
              sizeof (server_addr)) < 0)
    {
        weechat_printf (NULL,
                        _("%s%s: error with \"bind\" on port %d (%s%s%s)"),
                        weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                        server->port,
                        relay_protocol_string[server->protocol],
                        (server->protocol_args) ? "." : "",
                        (server->protocol_args) ? server->protocol_args : "");
        close (server->sock);
        server->sock = -1;
        return 0;
    }

    max_clients = weechat_config_integer (relay_config_network_max_clients);

    listen (server->sock, max_clients);

    weechat_printf (NULL,
                    _("%s: listening on port %d (relay: %s%s%s, max %d clients)"),
                    RELAY_PLUGIN_NAME,
                    server->port,
                    relay_protocol_string[server->protocol],
                    (server->protocol_args) ? "." : "",
                    (server->protocol_args) ? server->protocol_args : "",
                    max_clients);

    server->hook_fd = weechat_hook_fd (server->sock,
                                       1, 0, 0,
                                       &relay_server_sock_cb,
                                       server);

    server->start_time = time (NULL);

    return 1;
}
Esempio n. 14
0
int
relay_server_create_socket (struct t_relay_server *server)
{
    int domain, set, max_clients, addr_size;
    struct sockaddr_in server_addr;
    struct sockaddr_in6 server_addr6;
    const char *bind_address;
    void *ptr_addr;

    bind_address = weechat_config_string (relay_config_network_bind_address);

    if (server->ipv6)
    {
        domain = AF_INET6;
        memset (&server_addr6, 0, sizeof (struct sockaddr_in6));
        server_addr6.sin6_family = domain;
        server_addr6.sin6_port = htons (server->port);
        server_addr6.sin6_addr = in6addr_any;
        if (bind_address && bind_address[0])
        {
            if (!inet_pton (domain, bind_address, &server_addr6.sin6_addr))
            {
                weechat_printf (NULL,
                                /* TRANSLATORS: second "%s" is "IPv4" or "IPv6" */
                                _("%s%s: invalid bind address \"%s\" for %s"),
                                weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                                bind_address, "IPv6");
                return 0;
            }
        }
        ptr_addr = &server_addr6;
        addr_size = sizeof (struct sockaddr_in6);
    }
    else
    {
        domain = AF_INET;
        memset (&server_addr, 0, sizeof (struct sockaddr_in));
        server_addr.sin_family = domain;
        server_addr.sin_port = htons (server->port);
        server_addr.sin_addr.s_addr = INADDR_ANY;
        if (bind_address && bind_address[0])
        {
            if (!inet_pton (domain, bind_address, &server_addr.sin_addr))
            {
                weechat_printf (NULL,
                                /* TRANSLATORS: second "%s" is "IPv4" or "IPv6" */
                                _("%s%s: invalid bind address \"%s\" for %s"),
                                weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                                bind_address, "IPv4");
                return 0;
            }
        }
        ptr_addr = &server_addr;
        addr_size = sizeof (struct sockaddr_in);
    }

    /* create socket */
    server->sock = socket (domain, SOCK_STREAM, 0);
    if (server->sock < 0)
    {
        weechat_printf (NULL,
                        _("%s%s: cannot create socket: error %d %s"),
                        weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                        errno, strerror (errno));
        if (errno == EAFNOSUPPORT)
        {
            weechat_printf (NULL,
                            _("%s%s: try /set relay.network.ipv6 off"),
                            weechat_prefix ("error"), RELAY_PLUGIN_NAME);
        }
        return 0;
    }

#ifdef IPV6_V6ONLY
    /* set option IPV6_V6ONLY to 0 or 1 */
    if (server->ipv6)
    {
        set = (server->ipv4) ? 0 : 1;
        if (setsockopt (server->sock, IPPROTO_IPV6, IPV6_V6ONLY,
                        (void *) &set, sizeof (set)) < 0)
        {
            weechat_printf (NULL,
                            _("%s%s: cannot set socket option \"%s\" "
                              "to %d: error %d %s"),
                            weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                            "IPV6_V6ONLY", set, errno, strerror (errno));
            close (server->sock);
            server->sock = -1;
            return 0;
        }
    }
#endif

    /* set option SO_REUSEADDR to 1 */
    set = 1;
    if (setsockopt (server->sock, SOL_SOCKET, SO_REUSEADDR,
                    (void *) &set, sizeof (set)) < 0)
    {
        weechat_printf (NULL,
                        _("%s%s: cannot set socket option \"%s\" to %d: "
                          "error %d %s"),
                        weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                        "SO_REUSEADDR", set, errno, strerror (errno));
        close (server->sock);
        server->sock = -1;
        return 0;
    }

    /* set option SO_KEEPALIVE to 1 */
    set = 1;
    if (setsockopt (server->sock, SOL_SOCKET, SO_KEEPALIVE,
                    (void *) &set, sizeof (set)) < 0)
    {
        weechat_printf (NULL,
                        _("%s%s: cannot set socket option \"%s\" to %d: "
                          "error %d %s"),
                        weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                        "SO_KEEPALIVE", set, errno, strerror (errno));
        close (server->sock);
        server->sock = -1;
        return 0;
    }

    /* bind */
    if (bind (server->sock, (struct sockaddr *)ptr_addr, addr_size) < 0)
    {
        weechat_printf (NULL,
                        _("%s%s: cannot \"bind\" on port %d (%s): error %d %s"),
                        weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                        server->port, server->protocol_string,
                        errno, strerror (errno));
        close (server->sock);
        server->sock = -1;
        return 0;
    }

    max_clients = weechat_config_integer (relay_config_network_max_clients);

    if (listen (server->sock, max_clients) != 0)
    {
        weechat_printf (NULL,
                        _("%s%s: cannot \"listen\" on port %d (%s): error %d %s"),
                        weechat_prefix ("error"), RELAY_PLUGIN_NAME,
                        server->port, server->protocol_string,
                        errno, strerror (errno));
        close (server->sock);
        server->sock = -1;
        return 0;
    }

    weechat_printf (NULL,
                    _("%s: listening on port %d (relay: %s, %s, max %d clients)"),
                    RELAY_PLUGIN_NAME,
                    server->port,
                    server->protocol_string,
                    ((server->ipv4 && server->ipv6) ? "IPv4+6" : ((server->ipv6) ? "IPv6" : "IPv4")),
                    max_clients);

    server->hook_fd = weechat_hook_fd (server->sock,
                                       1, 0, 0,
                                       &relay_server_sock_cb,
                                       server);

    server->start_time = time (NULL);

    return 1;
}