From ffefd1b7851c3ee01ef259ea406fbcfaa564bead Mon Sep 17 00:00:00 2001 From: Ryan Farley Date: Sun, 12 May 2019 18:51:13 +0200 Subject: relay: add UNIX socket support (closes #733) --- src/plugins/relay/relay-client.c | 4 +- src/plugins/relay/relay-command.c | 48 +++++++---- src/plugins/relay/relay-config.c | 130 ++++++++++++++++++++++++++--- src/plugins/relay/relay-config.h | 2 + src/plugins/relay/relay-server.c | 167 ++++++++++++++++++++++++++++---------- src/plugins/relay/relay-server.h | 14 +++- 6 files changed, 291 insertions(+), 74 deletions(-) (limited to 'src/plugins/relay') diff --git a/src/plugins/relay/relay-client.c b/src/plugins/relay/relay-client.c index 0ea02c356..4455d5301 100644 --- a/src/plugins/relay/relay-client.c +++ b/src/plugins/relay/relay-client.c @@ -1355,9 +1355,9 @@ relay_client_new (int sock, const char *address, struct t_relay_server *server) relay_clients = new_client; weechat_printf_date_tags (NULL, 0, "relay_client", - _("%s: new client on port %d: %s%s%s"), + _("%s: new client on port/path %s: %s%s%s"), RELAY_PLUGIN_NAME, - server->port, + server->path, RELAY_COLOR_CHAT_CLIENT, new_client->desc, RELAY_COLOR_CHAT); diff --git a/src/plugins/relay/relay-command.c b/src/plugins/relay/relay-command.c index 539b3aef7..8f3627368 100644 --- a/src/plugins/relay/relay-command.c +++ b/src/plugins/relay/relay-command.c @@ -134,7 +134,7 @@ relay_command_server_list () if (relay_servers) { weechat_printf (NULL, ""); - weechat_printf (NULL, _("Listening on ports:")); + weechat_printf (NULL, _("Listening on:")); i = 1; for (ptr_server = relay_servers; ptr_server; ptr_server = ptr_server->next_server) @@ -143,14 +143,15 @@ relay_command_server_list () { weechat_printf ( NULL, - _(" port %s%d%s, relay: %s%s%s, %s (not started)"), + _(" %s %s%s%s, relay: %s%s%s, %s (not started)"), RELAY_COLOR_CHAT_BUFFER, - ptr_server->port, + ptr_server->un ? _("path") : _("port"), + ptr_server->path, RELAY_COLOR_CHAT, RELAY_COLOR_CHAT_BUFFER, ptr_server->protocol_string, RELAY_COLOR_CHAT, - ((ptr_server->ipv4 && ptr_server->ipv6) ? "IPv4+6" : ((ptr_server->ipv6) ? "IPv6" : "IPv4"))); + ((ptr_server->ipv4 && ptr_server->ipv6) ? "IPv4+6" : ((ptr_server->ipv6) ? "IPv6" : ((ptr_server->ipv4) ? "IPv4" : "UNIX")))); } else { @@ -164,15 +165,16 @@ relay_command_server_list () } weechat_printf ( NULL, - _(" port %s%d%s, relay: %s%s%s, %s, started on: %s"), + _(" %s %s%s%s, relay: %s%s%s, %s, started on: %s"), + ptr_server->un ? _("path") : _("port"), RELAY_COLOR_CHAT_BUFFER, - ptr_server->port, + ptr_server->path, RELAY_COLOR_CHAT, RELAY_COLOR_CHAT_BUFFER, ptr_server->protocol_string, RELAY_COLOR_CHAT, - ((ptr_server->ipv4 && ptr_server->ipv6) ? "IPv4+6" : ((ptr_server->ipv6) ? "IPv6" : "IPv4")), - date_start); + ((ptr_server->ipv4 && ptr_server->ipv6) ? "IPv4+6" : ((ptr_server->ipv6) ? "IPv6" : ((ptr_server->ipv4) ? "IPv4" : "UNIX"))), + date_start); } i++; } @@ -192,7 +194,8 @@ relay_command_relay (const void *pointer, void *data, { struct t_relay_server *ptr_server; struct t_config_option *ptr_option; - int port; + struct t_config_section *port_path_section; + char *path; /* make C compiler happy */ (void) pointer; @@ -222,15 +225,19 @@ relay_command_relay (const void *pointer, void *data, if (weechat_strcasecmp (argv[1], "add") == 0) { WEECHAT_COMMAND_MIN_ARGS(4, "add"); + /* check if we're expecting a path or a port */ + port_path_section = strncmp (argv[2], "unix.", 5) ? + relay_config_section_port : + relay_config_section_path; if (relay_config_create_option_port ( NULL, NULL, relay_config_file, - relay_config_section_port, + port_path_section, argv[2], argv_eol[3]) != WEECHAT_CONFIG_OPTION_SET_ERROR) { weechat_printf (NULL, - _("%s: relay \"%s\" (port %s) added"), + _("%s: relay \"%s\" (path/port: %s) added"), RELAY_PLUGIN_NAME, argv[2], argv_eol[3]); } @@ -243,17 +250,21 @@ relay_command_relay (const void *pointer, void *data, ptr_server = relay_server_search (argv_eol[2]); if (ptr_server) { - port = ptr_server->port; + path = strdup (ptr_server->path); relay_server_free (ptr_server); ptr_option = weechat_config_search_option (relay_config_file, - relay_config_section_port, + ptr_server->un ? + relay_config_section_path : + relay_config_section_port, argv_eol[2]); if (ptr_option) weechat_config_option_free (ptr_option); weechat_printf (NULL, - _("%s: relay \"%s\" (port %d) removed"), + _("%s: relay \"%s\" (%s %s) removed"), RELAY_PLUGIN_NAME, - argv[2], port); + argv[2], ptr_server->un ? _("path") : _("port"), + path); + free (path); } else { @@ -391,7 +402,7 @@ relay_command_init () N_(" list: list relay clients (only active relays)\n" " listfull: list relay clients (verbose, all relays)\n" " listrelay: list relays (name and port)\n" - " add: add a relay (listen on a port)\n" + " add: add a relay (listen on a port/path)\n" " del: remove a relay (clients remain connected)\n" " start: listen on port\n" " restart: close the server socket and listen again on port " @@ -407,6 +418,7 @@ relay_command_init () " ipv4: force use of IPv4\n" " ipv6: force use of IPv6\n" " ssl: enable SSL\n" + " unix: use UNIX domain socket\n" "protocol.name: protocol and name to relay:\n" " - protocol \"irc\": name is the server to share " "(optional, if not given, the server name must be sent by client in " @@ -437,7 +449,9 @@ relay_command_init () " weechat protocol with SSL, using only IPv6:\n" " /relay add ipv6.ssl.weechat 9001\n" " weechat protocol with SSL, using IPv4 + IPv6:\n" - " /relay add ipv4.ipv6.ssl.weechat 9001"), + " /relay add ipv4.ipv6.ssl.weechat 9001\n" + " weechat protocol over UNIX domain socket:\n" + " /relay add unix.weechat /tmp/weesock\n"), "list %(relay_relays)" " || listfull %(relay_relays)" " || listrelay" diff --git a/src/plugins/relay/relay-config.c b/src/plugins/relay/relay-config.c index 93e3e978c..f4d1be9ff 100644 --- a/src/plugins/relay/relay-config.c +++ b/src/plugins/relay/relay-config.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "../weechat-plugin.h" #include "relay.h" @@ -36,6 +37,7 @@ struct t_config_file *relay_config_file = NULL; struct t_config_section *relay_config_section_port = NULL; +struct t_config_section *relay_config_section_path = NULL; /* relay config, look section */ @@ -185,7 +187,7 @@ relay_config_change_network_ipv6_cb (const void *pointer, void *data, { relay_server_get_protocol_args (ptr_server->protocol_string, &ptr_server->ipv4, &ptr_server->ipv6, - NULL, NULL, NULL); + NULL, &ptr_server->un, NULL, NULL); relay_server_close_socket (ptr_server); relay_server_create_socket (ptr_server); } @@ -509,6 +511,75 @@ relay_config_check_port_cb (const void *pointer, void *data, return 1; } +/* + * Checks if a UNIX path is too long or empty. + * + * Returns: + * 1: path is valid + * 0: path is empty, or too long + */ + +int +relay_config_check_path_len (const char *path) +{ + struct sockaddr_un addr; + size_t max_path, path_len; + + max_path = sizeof (addr.sun_path); + path_len = strlen (path); + if (!path_len) + { + weechat_printf (NULL, _("%s%s: error: path is empty"), + weechat_prefix ("error"), RELAY_PLUGIN_NAME); + return 0; + } + if (path_len >= max_path) + { + weechat_printf (NULL, + _("%s%s: error: path \"%s\" too long (length: %d; max: %d)"), + weechat_prefix ("error"), RELAY_PLUGIN_NAME, path, + path_len, max_path); + return 0; + } + + return 1; +} + +/* + * Checks if a path is valid. + * + * Returns: + * 1: path is valid + * 0: path is not valid + */ + +int +relay_config_check_path_cb (const void *pointer, void *data, + struct t_config_option *option, + const char *value) +{ + struct t_relay_server *ptr_server; + + /* make C compiler happy */ + (void) pointer; + (void) data; + (void) option; + + if (!relay_config_check_path_len (value)) + return 0; + + ptr_server = relay_server_search_path (value); + if (ptr_server) + { + weechat_printf (NULL, _("%s%s: error: path \"%s\" is already used"), + weechat_prefix ("error"), + RELAY_PLUGIN_NAME, value); + return 0; + } + + return 1; +} + /* * Callback for changes on options in section "port". */ @@ -561,7 +632,7 @@ relay_config_create_option_port (const void *pointer, void *data, const char *option_name, const char *value) { - int rc, protocol_number, ipv4, ipv6, ssl; + int rc, protocol_number, ipv4, ipv6, ssl, un; char *error, *protocol, *protocol_args; long port; struct t_relay_server *ptr_server; @@ -575,7 +646,7 @@ relay_config_create_option_port (const void *pointer, void *data, protocol_number = -1; port = -1; - relay_server_get_protocol_args (option_name, &ipv4, &ipv6, &ssl, + relay_server_get_protocol_args (option_name, &ipv4, &ipv6, &ssl, &un, &protocol, &protocol_args); #ifndef HAVE_GNUTLS @@ -625,14 +696,23 @@ relay_config_create_option_port (const void *pointer, void *data, if (rc != WEECHAT_CONFIG_OPTION_SET_ERROR) { - error = NULL; - port = strtol (value, &error, 10); - ptr_server = relay_server_search_port ((int)port); + if (un) + { + ptr_server = relay_server_search_path (value); + } + else + { + error = NULL; + port = strtol (value, &error, 10); + ptr_server = relay_server_search_port ((int)port); + } if (ptr_server) { - weechat_printf (NULL, _("%s%s: error: port \"%d\" is already used"), + weechat_printf (NULL, _("%s%s: error: %s \"%s\" is already used"), weechat_prefix ("error"), - RELAY_PLUGIN_NAME, (int)port); + RELAY_PLUGIN_NAME, + un ? _("path") : _("port"), + value); rc = WEECHAT_CONFIG_OPTION_SET_ERROR; } } @@ -640,16 +720,29 @@ relay_config_create_option_port (const void *pointer, void *data, if (rc != WEECHAT_CONFIG_OPTION_SET_ERROR) { if (relay_server_new (option_name, protocol_number, protocol_args, - port, ipv4, ipv6, ssl)) + port, value, ipv4, ipv6, ssl, un)) { /* create configuration option */ - weechat_config_new_option ( + if (un) + { + weechat_config_new_option ( + config_file, section, + option_name, "string", NULL, + NULL, 0, 0, "", value, 0, + &relay_config_check_path_cb, NULL, NULL, + &relay_config_change_port_cb, NULL, NULL, + &relay_config_delete_port_cb, NULL, NULL); + } + else + { + weechat_config_new_option ( config_file, section, option_name, "integer", NULL, NULL, 0, 65535, "", value, 0, &relay_config_check_port_cb, NULL, NULL, &relay_config_change_port_cb, NULL, NULL, &relay_config_delete_port_cb, NULL, NULL); + } rc = WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE; } else @@ -1067,6 +1160,23 @@ relay_config_init () relay_config_section_port = ptr_section; + /* section path */ + ptr_section = weechat_config_new_section ( + relay_config_file, "path", + 1, 1, + NULL, NULL, NULL, + NULL, NULL, NULL, + NULL, NULL, NULL, + &relay_config_create_option_port, NULL, NULL, + NULL, NULL, NULL); + if (!ptr_section) + { + weechat_config_free (relay_config_file); + relay_config_file = NULL; + return 0; + } + + relay_config_section_path = ptr_section; return 1; } diff --git a/src/plugins/relay/relay-config.h b/src/plugins/relay/relay-config.h index 14fce3420..52ab8ae64 100644 --- a/src/plugins/relay/relay-config.h +++ b/src/plugins/relay/relay-config.h @@ -26,6 +26,7 @@ extern struct t_config_file *relay_config_file; extern struct t_config_section *relay_config_section_port; +extern struct t_config_section *relay_config_section_path; extern struct t_config_option *relay_config_look_auto_open_buffer; extern struct t_config_option *relay_config_look_raw_messages; @@ -72,6 +73,7 @@ extern int relay_config_create_option_port (const void *pointer, void *data, struct t_config_section *section, const char *option_name, const char *value); +extern int relay_config_check_path_len (const char *path); extern int relay_config_init (); extern int relay_config_read (); extern int relay_config_write (); diff --git a/src/plugins/relay/relay-server.c b/src/plugins/relay/relay-server.c index 713acc063..f73c3dd80 100644 --- a/src/plugins/relay/relay-server.c +++ b/src/plugins/relay/relay-server.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "../weechat-plugin.h" #include "relay.h" @@ -49,32 +50,34 @@ struct t_relay_server *last_relay_server = NULL; * * Examples: * - * string ipv4 ipv6 ssl protocol protocol_args + * string ipv4 ipv6 ssl unix protocol protocol_args * --------------------------------------------------------------- - * irc.freenode 1 1 0 irc freenode - * ssl.irc.freenode 1 1 1 irc freenode - * ipv4.irc.freenode 1 0 0 irc freenode - * ipv6.irc.freenode 0 1 0 irc freenode - * ipv4.ipv6.irc.freenode 1 1 0 irc freenode - * ipv6.ssl.irc.freenode 0 1 1 irc freenode - * weechat 1 1 0 weechat - * ssl.weechat 1 1 1 weechat - * ipv6.ssl.weechat 0 1 1 weechat + * irc.freenode 1 1 0 0 irc freenode + * ssl.irc.freenode 1 1 1 0 irc freenode + * ipv4.irc.freenode 1 0 0 0 irc freenode + * ipv6.irc.freenode 0 1 0 0 irc freenode + * ipv4.ipv6.irc.freenode 1 1 0 0 irc freenode + * ipv6.ssl.irc.freenode 0 1 1 0 irc freenode + * weechat 1 1 0 0 weechat + * ssl.weechat 1 1 1 0 weechat + * ipv6.ssl.weechat 0 1 1 0 weechat + * unix.weechat 0 0 0 1 weechat * * Note: *protocol and *protocol_args must be freed after use. */ void relay_server_get_protocol_args (const char *protocol_and_args, - int *ipv4, int *ipv6, int *ssl, + int *ipv4, int *ipv6, int *ssl, int *un, char **protocol, char **protocol_args) { - int opt_ipv4, opt_ipv6, opt_ssl; + int opt_ipv4, opt_ipv6, opt_ssl, opt_un; char *pos; opt_ipv4 = -1; opt_ipv6 = -1; opt_ssl = 0; + opt_un = -1; while (1) { if (strncmp (protocol_and_args, "ipv4.", 5) == 0) @@ -92,18 +95,24 @@ relay_server_get_protocol_args (const char *protocol_and_args, opt_ssl = 1; protocol_and_args += 4; } + else if (strncmp (protocol_and_args, "unix.", 5) == 0) + { + opt_un = 1; + protocol_and_args += 5; + } else break; } - if ((opt_ipv4 == -1) && (opt_ipv6 == -1)) + if ((opt_ipv4 == -1) && (opt_ipv6 == -1) && (opt_un == -1)) { /* - * no IPv4/IPv6 specified, then use defaults: + * no IPv4/IPv6/UNIX specified, then use defaults: * - IPv4 enabled * - IPv6 enabled if option relay.network.ipv6 is on */ opt_ipv4 = 1; opt_ipv6 = weechat_config_boolean (relay_config_network_ipv6); + opt_un = 0; } else { @@ -111,10 +120,12 @@ relay_server_get_protocol_args (const char *protocol_and_args, opt_ipv4 = 0; if (opt_ipv6 == -1) opt_ipv6 = 0; + if (opt_un == -1) + opt_un = 0; } - if (!opt_ipv4 && !opt_ipv6) + if (!opt_ipv4 && !opt_ipv6 && !opt_un) { - /* both IPv4/IPv6 disabled (should never occur!) */ + /* IPv4/IPv6/UNIX disabled (should never occur!) */ opt_ipv4 = 1; } if (ipv4) @@ -123,6 +134,8 @@ relay_server_get_protocol_args (const char *protocol_and_args, *ipv6 = opt_ipv6; if (ssl) *ssl = opt_ssl; + if (un) + *un = opt_un; pos = strchr (protocol_and_args, '.'); if (pos) @@ -187,6 +200,28 @@ relay_server_search_port (int port) return NULL; } +/* + * Searches for a server by path. Only returns servers using a UNIX socket. + * + * Returns pointer to new server, NULL if not found. + */ + +struct t_relay_server * +relay_server_search_path (const char *path) +{ + struct t_relay_server *ptr_server; + + for (ptr_server = relay_servers; ptr_server; + ptr_server = ptr_server->next_server) + { + /* only include UNIX socket relays, to allow for numerical paths */ + if (!strcmp (path, ptr_server->path) && ptr_server->un) + return ptr_server; + } + + /* server not found */ + return NULL; +} /* * Closes socket for a relay server. */ @@ -203,13 +238,17 @@ relay_server_close_socket (struct t_relay_server *server) { close (server->sock); server->sock = -1; - + if (server->un) + { + unlink (server->path); + } if (!relay_signal_upgrade_received) { weechat_printf (NULL, - _("%s: socket closed for %s (port %d)"), + _("%s: socket closed for %s (%s %s)"), RELAY_PLUGIN_NAME, server->protocol_string, - server->port); + server->un ? _("path") : _("port"), + server->path); } } } @@ -224,10 +263,13 @@ relay_server_sock_cb (const void *pointer, void *data, int fd) struct t_relay_server *server; struct sockaddr_in client_addr; struct sockaddr_in6 client_addr6; + struct sockaddr_un client_addr_un; + socklen_t client_addr_size; void *ptr_addr; int client_fd, flags, set, max_clients, num_clients_on_port; char ipv4_address[INET_ADDRSTRLEN + 1], ipv6_address[INET6_ADDRSTRLEN + 1]; + char un_address[sizeof (client_addr_un.sun_path)]; char *ptr_ip_address, *relay_password, *relay_totp_secret; /* make C compiler happy */ @@ -245,11 +287,16 @@ relay_server_sock_cb (const void *pointer, void *data, int fd) ptr_addr = &client_addr6; client_addr_size = sizeof (struct sockaddr_in6); } - else + else if (server->ipv4) { ptr_addr = &client_addr; client_addr_size = sizeof (struct sockaddr_in); } + else if (server->un) + { + ptr_addr = &client_addr_un; + client_addr_size = sizeof (struct sockaddr_un); + } memset (ptr_addr, 0, client_addr_size); @@ -258,9 +305,10 @@ relay_server_sock_cb (const void *pointer, void *data, int fd) if (client_fd < 0) { weechat_printf (NULL, - _("%s%s: cannot accept client on port %d (%s): error %d %s"), + _("%s%s: cannot accept client on %s %s (%s): error %d %s"), weechat_prefix ("error"), RELAY_PLUGIN_NAME, - server->port, server->protocol_string, + server->un ? _("path") : _("port"), + server->path, server->protocol_string, errno, strerror (errno)); goto error; } @@ -345,7 +393,7 @@ relay_server_sock_cb (const void *pointer, void *data, int fd) } } } - else + else if (server->ipv4) { if (inet_ntop (AF_INET, &(client_addr.sin_addr), @@ -355,6 +403,11 @@ relay_server_sock_cb (const void *pointer, void *data, int fd) ptr_ip_address = ipv4_address; } } + else + { + strncpy (un_address, client_addr_un.sun_path, sizeof (un_address)); + ptr_ip_address = un_address; + } /* check if IP is allowed, if not, just close socket */ if (relay_config_regex_allowed_ips @@ -422,6 +475,7 @@ 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; + struct sockaddr_un server_addr_un; const char *bind_address; void *ptr_addr; @@ -449,7 +503,7 @@ relay_server_create_socket (struct t_relay_server *server) ptr_addr = &server_addr6; addr_size = sizeof (struct sockaddr_in6); } - else + else if (server->ipv4) { domain = AF_INET; memset (&server_addr, 0, sizeof (struct sockaddr_in)); @@ -471,6 +525,21 @@ relay_server_create_socket (struct t_relay_server *server) ptr_addr = &server_addr; addr_size = sizeof (struct sockaddr_in); } + else + { + domain = AF_UNIX; + memset (&server_addr_un, 0, sizeof (struct sockaddr_un)); + server_addr_un.sun_family = domain; + strncpy (server_addr_un.sun_path, server->path, + sizeof (server_addr_un.sun_path)); + ptr_addr = &server_addr_un; + addr_size = sizeof (struct sockaddr_un); + if (!relay_config_check_path_len (server->path)) + return 0; + /* just in case it already exists */ + unlink (server->path); + } + /* create socket */ server->sock = socket (domain, SOCK_STREAM, 0); @@ -543,9 +612,10 @@ relay_server_create_socket (struct t_relay_server *server) 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"), + _("%s%s: cannot \"bind\" on %s %s (%s): error %d %s"), weechat_prefix ("error"), RELAY_PLUGIN_NAME, - server->port, server->protocol_string, + server->un ? _("path") : _("port"), + server->path, server->protocol_string, errno, strerror (errno)); close (server->sock); server->sock = -1; @@ -559,9 +629,10 @@ relay_server_create_socket (struct t_relay_server *server) #endif { weechat_printf (NULL, - _("%s%s: cannot \"listen\" on port %d (%s): error %d %s"), + _("%s%s: cannot \"listen\" on %s %s (%s): error %d %s"), weechat_prefix ("error"), RELAY_PLUGIN_NAME, - server->port, server->protocol_string, + server->un ? _("path") : _("port"), + server->path, server->protocol_string, errno, strerror (errno)); close (server->sock); server->sock = -1; @@ -573,24 +644,26 @@ relay_server_create_socket (struct t_relay_server *server) { 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)", + NG_("%s: listening on %s %s (relay: %s, %s, max %d client)", + "%s: listening on %s %s (relay: %s, %s, max %d clients)", max_clients), RELAY_PLUGIN_NAME, - server->port, + server->un ? _("path") : _("port"), + server->path, server->protocol_string, - ((server->ipv4 && server->ipv6) ? "IPv4+6" : ((server->ipv6) ? "IPv6" : "IPv4")), + ((server->ipv4 && server->ipv6) ? "IPv4+6" : ((server->ipv6) ? "IPv6" : ((server->ipv4) ? "IPv4" : "UNIX"))), max_clients); } else { weechat_printf ( NULL, - _("%s: listening on port %d (relay: %s, %s)"), + _("%s: listening on %s %s (relay: %s, %s)"), RELAY_PLUGIN_NAME, - server->port, + server->un ? _("path") : _("port"), + server->path, server->protocol_string, - ((server->ipv4 && server->ipv6) ? "IPv4+6" : ((server->ipv6) ? "IPv6" : "IPv4"))); + ((server->ipv4 && server->ipv6) ? "IPv4+6" : ((server->ipv6) ? "IPv6" : ((server->ipv4) ? "IPv4" : "UNIX")))); } server->hook_fd = weechat_hook_fd (server->sock, 1, 0, 0, @@ -610,17 +683,21 @@ relay_server_create_socket (struct t_relay_server *server) struct t_relay_server * relay_server_new (const char *protocol_string, enum t_relay_protocol protocol, - const char *protocol_args, int port, int ipv4, int ipv6, - int ssl) + const char *protocol_args, int port, const char *path, + int ipv4, int ipv6, int ssl, int un) { - struct t_relay_server *new_server; + struct t_relay_server *new_server, *dup_server; if (!protocol_string) return NULL; - if (relay_server_search_port (port)) + /* look for duplicate ports/paths */ + dup_server = un ? + relay_server_search_path (path) : relay_server_search_port (port); + if (dup_server) { - weechat_printf (NULL, _("%s%s: error: port \"%d\" is already used"), + weechat_printf (NULL, _("%s%s: error: %s \"%s\" is already used"), + un ? _("path") : _("port"), weechat_prefix ("error"), RELAY_PLUGIN_NAME, port); return NULL; @@ -634,9 +711,11 @@ relay_server_new (const char *protocol_string, enum t_relay_protocol protocol, new_server->protocol_args = (protocol_args) ? strdup (protocol_args) : NULL; new_server->port = port; + new_server->path = strdup (path); new_server->ipv4 = ipv4; new_server->ipv6 = ipv6; new_server->ssl = ssl; + new_server->un = un; new_server->sock = -1; new_server->hook_fd = NULL; new_server->start_time = 0; @@ -708,7 +787,7 @@ relay_server_free (struct t_relay_server *server) free (server->protocol_string); if (server->protocol_args) free (server->protocol_args); - + free (server->path); free (server); relay_servers = new_relay_servers; @@ -756,12 +835,16 @@ relay_server_add_to_infolist (struct t_infolist *infolist, return 0; if (!weechat_infolist_new_var_integer (ptr_item, "port", server->port)) return 0; + if (!weechat_infolist_new_var_string (ptr_item, "path", server->path)) + return 0; if (!weechat_infolist_new_var_integer (ptr_item, "ipv4", server->ipv4)) return 0; if (!weechat_infolist_new_var_integer (ptr_item, "ipv6", server->ipv6)) return 0; if (!weechat_infolist_new_var_integer (ptr_item, "ssl", server->ssl)) return 0; + if (!weechat_infolist_new_var_integer (ptr_item, "un", server->un)) + return 0; if (!weechat_infolist_new_var_integer (ptr_item, "sock", server->sock)) return 0; if (!weechat_infolist_new_var_pointer (ptr_item, "hook_fd", server->hook_fd)) @@ -794,9 +877,11 @@ relay_server_print_log () relay_protocol_string[ptr_server->protocol]); weechat_log_printf (" protocol_args . . . . : '%s'", ptr_server->protocol_args); weechat_log_printf (" port. . . . . . . . . : %d", ptr_server->port); + weechat_log_printf (" path. . . . . . . . . : %s", ptr_server->path); weechat_log_printf (" ipv4. . . . . . . . . : %d", ptr_server->ipv4); weechat_log_printf (" ipv6. . . . . . . . . : %d", ptr_server->ipv6); weechat_log_printf (" ssl . . . . . . . . . : %d", ptr_server->ssl); + weechat_log_printf (" unix. . . . . . . . . : %d", ptr_server->un); weechat_log_printf (" sock. . . . . . . . . : %d", ptr_server->sock); weechat_log_printf (" hook_fd . . . . . . . : 0x%lx", ptr_server->hook_fd); weechat_log_printf (" start_time. . . . . . : %lld", (long long)ptr_server->start_time); diff --git a/src/plugins/relay/relay-server.h b/src/plugins/relay/relay-server.h index db7ace2cd..edbf4b187 100644 --- a/src/plugins/relay/relay-server.h +++ b/src/plugins/relay/relay-server.h @@ -21,7 +21,6 @@ #define WEECHAT_PLUGIN_RELAY_SERVER_H #include - #ifdef HAVE_GNUTLS #define RELAY_SERVER_GNUTLS_DH_BITS 1024 #endif /* HAVE_GNUTLS */ @@ -33,9 +32,14 @@ struct t_relay_server char *protocol_args; /* arguments used for protocol */ /* example: server for irc protocol */ int port; /* listening on this port */ + /* or UNIX socket, if negative. */ + char *path; /* listening on this path (UNIX) */ + /* contains string representation of */ + /* port if IP */ int ipv4; /* IPv4 protocol enabled */ int ipv6; /* IPv6 protocol enabled */ int ssl; /* 1 if SSL is enabled */ + int un; /* 1 if UNIX socket */ int sock; /* socket for connection */ struct t_hook *hook_fd; /* hook for socket */ time_t start_time; /* start time */ @@ -49,18 +53,20 @@ extern struct t_relay_server *last_relay_server; extern void relay_server_get_protocol_args (const char *protocol_and_string, int *ipv4, int *ipv6, - int *ssl, + int *ssl, int *un, char **protocol, char **protocol_args); extern struct t_relay_server *relay_server_search (const char *protocol_and_args); extern struct t_relay_server *relay_server_search_port (int port); +extern struct t_relay_server *relay_server_search_path (const char *path); extern void relay_server_close_socket (struct t_relay_server *server); extern int relay_server_create_socket (struct t_relay_server *server); extern struct t_relay_server *relay_server_new (const char *protocol_string, enum t_relay_protocol protocol, const char *protocol_args, - int port, int ipv4, int ipv6, - int ssl); + int port, const char *path, + int ipv4, int ipv6, + int ssl, int un); extern void relay_server_update_port (struct t_relay_server *server, int port); extern void relay_server_free (struct t_relay_server *server); extern void relay_server_free_all (); -- cgit v1.2.3