int 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_unix; 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 unix_address[sizeof (client_addr_unix.sun_path)]; char *ptr_ip_address, *relay_password, *relay_totp_secret; /* make C compiler happy */ (void) data; (void) fd; client_fd = -1; relay_password = NULL; relay_totp_secret = NULL; server = (struct t_relay_server *)pointer; if (server->ipv6) { ptr_addr = &client_addr6; client_addr_size = sizeof (struct sockaddr_in6); } else if (server->ipv4) { ptr_addr = &client_addr; client_addr_size = sizeof (struct sockaddr_in); } else { ptr_addr = &client_addr_unix; client_addr_size = sizeof (struct sockaddr_un); } memset (ptr_addr, 0, client_addr_size); client_fd = accept (server->sock, (struct sockaddr *)ptr_addr, &client_addr_size); if (client_fd < 0) { if (server->unix_socket) { weechat_printf (NULL, _("%s%s: cannot accept client 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 accept client on port %d (%s): " "error %d %s"), weechat_prefix ("error"), RELAY_PLUGIN_NAME, server->port, server->protocol_string, errno, strerror (errno)); } goto error; } /* check if relay password is empty and if it is not allowed */ relay_password = weechat_string_eval_expression ( weechat_config_string (relay_config_network_password), NULL, NULL, NULL); if (!weechat_config_boolean (relay_config_network_allow_empty_password) && (!relay_password || !relay_password[0])) { weechat_printf (NULL, _("%s%s: cannot accept client because relay password " "is empty, and option " "relay.network.allow_empty_password is off"), weechat_prefix ("error"), RELAY_PLUGIN_NAME); goto error; } if (server->protocol == RELAY_PROTOCOL_WEECHAT) { /* * TOTP can be enabled only as second factor, in addition to the * password (only for weechat protocol) */ relay_totp_secret = weechat_string_eval_expression ( weechat_config_string (relay_config_network_totp_secret), NULL, NULL, NULL); if ((!relay_password || !relay_password[0]) && relay_totp_secret && relay_totp_secret[0]) { weechat_printf (NULL, _("%s%s: Time-based One-Time Password (TOTP) " "can be enabled only as second factor, if the " "password is not empty"), weechat_prefix ("error"), RELAY_PLUGIN_NAME); goto error; } if (!relay_config_check_network_totp_secret ( NULL, NULL, NULL, weechat_config_string (relay_config_network_totp_secret))) { goto error; } } /* check if we have reached the max number of clients on this port */ max_clients = weechat_config_integer (relay_config_network_max_clients); if (max_clients > 0) { num_clients_on_port = relay_client_count_active_by_port (server->port); if (num_clients_on_port >= max_clients) { weechat_printf ( NULL, NG_("%s%s: client not allowed (max %d client is " "allowed at same time)", "%s%s: client not allowed (max %d clients are " "allowed at same time)", max_clients), weechat_prefix ("error"), RELAY_PLUGIN_NAME, max_clients); goto error; } } /* get the IP address */ ptr_ip_address = NULL; if (server->ipv6) { if (inet_ntop (AF_INET6, &(client_addr6.sin6_addr), ipv6_address, INET6_ADDRSTRLEN)) { ptr_ip_address = ipv6_address; if (strncmp (ptr_ip_address, "::ffff:", 7) == 0) { /* actually an IPv4-mapped IPv6 address, so skip "::ffff:" */ ptr_ip_address += 7; } } } else if (server->ipv4) { if (inet_ntop (AF_INET, &(client_addr.sin_addr), ipv4_address, INET_ADDRSTRLEN)) { ptr_ip_address = ipv4_address; } } else { strncpy (unix_address, client_addr_unix.sun_path, sizeof (unix_address)); ptr_ip_address = unix_address; } /* check if IP is allowed, if not, just close socket */ if (relay_config_regex_allowed_ips && (regexec (relay_config_regex_allowed_ips, ptr_ip_address, 0, NULL, 0) != 0)) { if (weechat_relay_plugin->debug >= 1) { weechat_printf (NULL, _("%s%s: IP address \"%s\" not allowed for relay"), weechat_prefix ("error"), RELAY_PLUGIN_NAME, ptr_ip_address); } goto error; } /* set non-blocking mode for socket */ flags = fcntl (client_fd, F_GETFL); if (flags == -1) flags = 0; fcntl (client_fd, F_SETFL, flags | O_NONBLOCK); /* set socket option SO_REUSEADDR */ set = 1; if (setsockopt (client_fd, 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)); goto error; } /* add the client */ relay_client_new (client_fd, ptr_ip_address, server); goto end; error: if (client_fd >= 0) close (client_fd); end: if (relay_password) free (relay_password); if (relay_totp_secret) free (relay_totp_secret); return WEECHAT_RC_OK; }
int relay_server_sock_cb (void *data, int fd) { struct t_relay_server *server; struct sockaddr_in client_addr; struct sockaddr_in6 client_addr6; socklen_t client_addr_size; void *ptr_addr; int client_fd, flags, set; char ipv4_address[INET_ADDRSTRLEN + 1], ipv6_address[INET6_ADDRSTRLEN + 1]; char *ptr_ip_address; /* make C compiler happy */ (void) fd; server = (struct t_relay_server *)data; if (server->ipv6) { ptr_addr = &client_addr6; client_addr_size = sizeof (struct sockaddr_in6); } else { ptr_addr = &client_addr; client_addr_size = sizeof (struct sockaddr_in); } memset (ptr_addr, 0, client_addr_size); client_fd = accept (server->sock, (struct sockaddr *)ptr_addr, &client_addr_size); if (client_fd < 0) { dogechat_printf (NULL, _("%s%s: cannot accept client on port %d (%s): error %d %s"), dogechat_prefix ("error"), RELAY_PLUGIN_NAME, server->port, server->protocol_string, errno, strerror (errno)); return DOGECHAT_RC_OK; } ptr_ip_address = NULL; if (server->ipv6) { if (inet_ntop (AF_INET6, &(client_addr6.sin6_addr), ipv6_address, INET6_ADDRSTRLEN)) { ptr_ip_address = ipv6_address; if (strncmp (ptr_ip_address, "::ffff:", 7) == 0) { /* actually an IPv4-mapped IPv6 address, so skip "::ffff:" */ ptr_ip_address += 7; } } } else { if (inet_ntop (AF_INET, &(client_addr.sin_addr), ipv4_address, INET_ADDRSTRLEN)) { ptr_ip_address = ipv4_address; } } /* check if IP is allowed, if not, just close socket */ if (relay_config_regex_allowed_ips && (regexec (relay_config_regex_allowed_ips, ptr_ip_address, 0, NULL, 0) != 0)) { if (dogechat_relay_plugin->debug >= 1) { dogechat_printf (NULL, _("%s%s: IP address \"%s\" not allowed for relay"), dogechat_prefix ("error"), RELAY_PLUGIN_NAME, ptr_ip_address); } close (client_fd); return DOGECHAT_RC_OK; } /* set non-blocking mode for socket */ flags = fcntl (client_fd, F_GETFL); if (flags == -1) flags = 0; fcntl (client_fd, F_SETFL, flags | O_NONBLOCK); /* set socket option SO_REUSEADDR */ set = 1; if (setsockopt (client_fd, SOL_SOCKET, SO_REUSEADDR, (void *) &set, sizeof (set)) < 0) { dogechat_printf (NULL, _("%s%s: cannot set socket option \"%s\" to %d: " "error %d %s"), dogechat_prefix ("error"), RELAY_PLUGIN_NAME, "SO_REUSEADDR", set, errno, strerror (errno)); close (client_fd); return DOGECHAT_RC_OK; } /* add the client */ relay_client_new (client_fd, ptr_ip_address, server); return DOGECHAT_RC_OK; }
int relay_server_sock_cb (void *data, int fd) { struct t_relay_server *server; struct sockaddr_in client_addr; socklen_t client_length; int client_fd; char ipv4_address[INET_ADDRSTRLEN + 1], *ptr_address; /* make C compiler happy */ (void) fd; server = (struct t_relay_server *)data; client_length = sizeof (client_addr); memset (&client_addr, 0, client_length); client_fd = accept (server->sock, (struct sockaddr *) &client_addr, &client_length); if (client_fd < 0) { weechat_printf (NULL, _("%s%s: cannot accept client 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 : ""); return WEECHAT_RC_OK; } ptr_address = NULL; if (inet_ntop (AF_INET, &(client_addr.sin_addr), ipv4_address, INET_ADDRSTRLEN)) { ptr_address = ipv4_address; } /* check if IP is allowed, if not, just close socket */ if (relay_config_regex_allowed_ips && (regexec (relay_config_regex_allowed_ips, ptr_address, 0, NULL, 0) != 0)) { if (weechat_relay_plugin->debug >= 2) { weechat_printf (NULL, _("%s%s: IP address \"%s\" not allowed for relay"), weechat_prefix ("error"), RELAY_PLUGIN_NAME, ptr_address); } close (client_fd); return WEECHAT_RC_OK; } relay_client_new (client_fd, ptr_address, server); return WEECHAT_RC_OK; }