mirror of
https://github.com/matrix-construct/construct
synced 2024-09-30 04:38:52 +02:00
ircd: Remove authproc, sslproc, wsproc, bandbi.
This commit is contained in:
parent
d36541bb86
commit
922337386e
9 changed files with 0 additions and 3045 deletions
|
@ -1,95 +0,0 @@
|
||||||
/*
|
|
||||||
* charybdis
|
|
||||||
* authproc.h: A header with the authd functions.
|
|
||||||
*
|
|
||||||
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
|
|
||||||
* Copyright (C) 1996-2002 Hybrid Development Team
|
|
||||||
* Copyright (C) 2002-2012 ircd-ratbox development team
|
|
||||||
* Copyright (C) 2016 William Pitcock <nenolod@dereferenced.org>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
||||||
* USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#define HAVE_CHARYBDIS_AUTHPROC_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
namespace ircd {
|
|
||||||
|
|
||||||
struct BlacklistStats
|
|
||||||
{
|
|
||||||
char *host;
|
|
||||||
uint8_t iptype;
|
|
||||||
unsigned int hits;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct OPMScanner
|
|
||||||
{
|
|
||||||
char type[16]; /* Type of proxy */
|
|
||||||
uint16_t port; /* Port */
|
|
||||||
|
|
||||||
rb_dlink_node node;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct OPMListener
|
|
||||||
{
|
|
||||||
char ipaddr[HOSTIPLEN]; /* Listener address */
|
|
||||||
uint16_t port; /* Listener port */
|
|
||||||
};
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
LISTEN_IPV4,
|
|
||||||
LISTEN_IPV6,
|
|
||||||
LISTEN_LAST,
|
|
||||||
};
|
|
||||||
|
|
||||||
extern rb_helper *authd_helper;
|
|
||||||
|
|
||||||
extern rb_dictionary *bl_stats;
|
|
||||||
extern rb_dlink_list opm_list;
|
|
||||||
extern struct OPMListener opm_listeners[LISTEN_LAST];
|
|
||||||
|
|
||||||
void init_authd(void);
|
|
||||||
void configure_authd(void);
|
|
||||||
void restart_authd(void);
|
|
||||||
void rehash_authd(void);
|
|
||||||
void check_authd(void);
|
|
||||||
|
|
||||||
void authd_initiate_client(client::client *, bool defer);
|
|
||||||
void authd_deferred_client(client::client *);
|
|
||||||
void authd_accept_client(client::client *client_p, const char *ident, const char *host);
|
|
||||||
void authd_reject_client(client::client *client_p, const char *ident, const char *host, char cause, const char *data, const char *reason);
|
|
||||||
void authd_abort_client(client::client *);
|
|
||||||
|
|
||||||
void add_blacklist(const char *host, const char *reason, uint8_t iptype, rb_dlink_list *filters);
|
|
||||||
void del_blacklist(const char *host);
|
|
||||||
void del_blacklist_all(void);
|
|
||||||
|
|
||||||
bool set_authd_timeout(const char *key, int timeout);
|
|
||||||
void ident_check_enable(bool enabled);
|
|
||||||
|
|
||||||
void conf_create_opm_listener(const char *ip, uint16_t port);
|
|
||||||
void create_opm_listener(const char *ip, uint16_t port);
|
|
||||||
void conf_create_opm_proxy_scanner(const char *type, uint16_t port);
|
|
||||||
void create_opm_proxy_scanner(const char *type, uint16_t port);
|
|
||||||
void delete_opm_proxy_scanner(const char *type, uint16_t port);
|
|
||||||
void delete_opm_proxy_scanner_all(void);
|
|
||||||
void delete_opm_listener_all(void);
|
|
||||||
void opm_check_enable(bool enabled);
|
|
||||||
|
|
||||||
} // namespace ircd
|
|
||||||
#endif // __cplusplus
|
|
|
@ -1,44 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (C) 2016 Charybdis Development Team
|
|
||||||
*
|
|
||||||
* Permission to use, copy, modify, and/or distribute this software for any
|
|
||||||
* purpose with or without fee is hereby granted, provided that the above
|
|
||||||
* copyright notice and this permission notice is present in all copies.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
|
||||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#define HAVE_BANDBI_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
namespace ircd {
|
|
||||||
|
|
||||||
void init_bandb(void);
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
BANDB_KLINE,
|
|
||||||
BANDB_DLINE,
|
|
||||||
BANDB_XLINE,
|
|
||||||
BANDB_RESV,
|
|
||||||
LAST_BANDB_TYPE
|
|
||||||
} bandb_type;
|
|
||||||
|
|
||||||
void bandb_add(bandb_type, client::client *source_p, const char *mask1,
|
|
||||||
const char *mask2, const char *reason, const char *oper_reason, int perm);
|
|
||||||
void bandb_del(bandb_type, const char *mask1, const char *mask2);
|
|
||||||
void bandb_rehash_bans(void);
|
|
||||||
|
|
||||||
} // namespace ircd
|
|
||||||
#endif // __cplusplus
|
|
|
@ -1,49 +0,0 @@
|
||||||
/*
|
|
||||||
* sslproc.h: An interface to the ratbox ssld helper daemon
|
|
||||||
* Copyright (C) 2007 Aaron Sethman <androsyn@ratbox.org>
|
|
||||||
* Copyright (C) 2007 ircd-ratbox development team
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
||||||
* USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#define HAVE_IRCD_SSLPROC_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
namespace ircd {
|
|
||||||
|
|
||||||
struct _ssl_ctl;
|
|
||||||
typedef struct _ssl_ctl ssl_ctl_t;
|
|
||||||
|
|
||||||
enum ssld_status {
|
|
||||||
SSLD_ACTIVE,
|
|
||||||
SSLD_SHUTDOWN,
|
|
||||||
SSLD_DEAD,
|
|
||||||
};
|
|
||||||
|
|
||||||
void init_ssld(void);
|
|
||||||
void restart_ssld(void);
|
|
||||||
int start_ssldaemon(int count);
|
|
||||||
ssl_ctl_t *start_ssld_accept(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
|
|
||||||
ssl_ctl_t *start_ssld_connect(rb_fde_t *sslF, rb_fde_t *plainF, uint32_t id);
|
|
||||||
void start_zlib_session(void *data);
|
|
||||||
void ssld_update_config(void);
|
|
||||||
void ssld_decrement_clicount(ssl_ctl_t *ctl);
|
|
||||||
int get_ssld_count(void);
|
|
||||||
void ssld_foreach_info(void (*func)(void *data, pid_t pid, int cli_count, enum ssld_status status, const char *version), void *data);
|
|
||||||
|
|
||||||
} // namespace ircd
|
|
||||||
#endif // __cplusplus
|
|
|
@ -66,9 +66,6 @@ namespace ircd
|
||||||
struct ConfItem;
|
struct ConfItem;
|
||||||
struct Blacklist;
|
struct Blacklist;
|
||||||
struct PrivilegeSet;
|
struct PrivilegeSet;
|
||||||
struct _ssl_ctl;
|
|
||||||
struct ev_ctl;
|
|
||||||
struct ws_ctl;
|
|
||||||
struct server_conf;
|
struct server_conf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -118,8 +115,6 @@ namespace ircd
|
||||||
#include "chmode.h"
|
#include "chmode.h"
|
||||||
#include "channel.h"
|
#include "channel.h"
|
||||||
|
|
||||||
#include "authproc.h"
|
|
||||||
#include "bandbi.h"
|
|
||||||
#include "capability.h"
|
#include "capability.h"
|
||||||
#include "certfp.h"
|
#include "certfp.h"
|
||||||
#include "class.h"
|
#include "class.h"
|
||||||
|
@ -135,10 +130,8 @@ namespace ircd
|
||||||
#include "send.h"
|
#include "send.h"
|
||||||
#include "s_newconf.h"
|
#include "s_newconf.h"
|
||||||
#include "s_serv.h"
|
#include "s_serv.h"
|
||||||
#include "sslproc.h"
|
|
||||||
#include "s_stats.h"
|
#include "s_stats.h"
|
||||||
#include "substitution.h"
|
#include "substitution.h"
|
||||||
#include "supported.h"
|
#include "supported.h"
|
||||||
#include "s_user.h"
|
#include "s_user.h"
|
||||||
#include "wsproc.h"
|
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
/*
|
|
||||||
* wsproc.h: An interface to the charybdis websocket helper daemon
|
|
||||||
* Copyright (C) 2007 Aaron Sethman <androsyn@ratbox.org>
|
|
||||||
* Copyright (C) 2007 ircd-ratbox development team
|
|
||||||
* Copyright (C) 2016 William Pitcock <nenolod@dereferenced.org>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
||||||
* USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
#define HAVE_IRCD_WSPROC_H
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
namespace ircd {
|
|
||||||
|
|
||||||
struct ws_ctl;
|
|
||||||
typedef struct ws_ctl ws_ctl_t;
|
|
||||||
|
|
||||||
enum wsockd_status {
|
|
||||||
WSOCKD_ACTIVE,
|
|
||||||
WSOCKD_SHUTDOWN,
|
|
||||||
WSOCKD_DEAD,
|
|
||||||
};
|
|
||||||
|
|
||||||
void init_wsockd(void);
|
|
||||||
void restart_wsockd(void);
|
|
||||||
int start_wsockd(int count);
|
|
||||||
ws_ctl_t *start_wsockd_accept(rb_fde_t *wsF, rb_fde_t *plainF, uint32_t id);
|
|
||||||
void wsockd_decrement_clicount(ws_ctl_t *ctl);
|
|
||||||
int get_wsockd_count(void);
|
|
||||||
void wsockd_foreach_info(void (*func)(void *data, pid_t pid, int cli_count, enum wsockd_status status), void *data);
|
|
||||||
|
|
||||||
} // namespace ircd
|
|
||||||
#endif // __cplusplus
|
|
781
ircd/authproc.cc
781
ircd/authproc.cc
|
@ -1,781 +0,0 @@
|
||||||
/*
|
|
||||||
* authd.c: An interface to authd.
|
|
||||||
* (based somewhat on ircd-ratbox dns.c)
|
|
||||||
*
|
|
||||||
* Copyright (C) 2005 Aaron Sethman <androsyn@ratbox.org>
|
|
||||||
* Copyright (C) 2005-2012 ircd-ratbox development team
|
|
||||||
* Copyright (C) 2016 William Pitcock <nenolod@dereferenced.org>
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
||||||
* USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace ircd {
|
|
||||||
|
|
||||||
typedef void (*authd_cb_t)(int, char **);
|
|
||||||
|
|
||||||
struct authd_cb
|
|
||||||
{
|
|
||||||
authd_cb_t fn;
|
|
||||||
int min_parc;
|
|
||||||
};
|
|
||||||
|
|
||||||
static int start_authd(void);
|
|
||||||
static void parse_authd_reply(rb_helper * helper);
|
|
||||||
static void restart_authd_cb(rb_helper * helper);
|
|
||||||
static EVH timeout_dead_authd_clients;
|
|
||||||
|
|
||||||
static void cmd_accept_client(int parc, char **parv);
|
|
||||||
static void cmd_reject_client(int parc, char **parv);
|
|
||||||
static void cmd_dns_result(int parc, char **parv);
|
|
||||||
static void cmd_notice_client(int parc, char **parv);
|
|
||||||
static void cmd_oper_warn(int parc, char **parv);
|
|
||||||
static void cmd_stats_results(int parc, char **parv);
|
|
||||||
|
|
||||||
rb_helper *authd_helper;
|
|
||||||
static char *authd_path;
|
|
||||||
|
|
||||||
uint32_t cid;
|
|
||||||
static rb_dictionary *cid_clients;
|
|
||||||
static struct ev_entry *timeout_ev;
|
|
||||||
|
|
||||||
rb_dictionary *bl_stats;
|
|
||||||
|
|
||||||
rb_dlink_list opm_list;
|
|
||||||
struct OPMListener opm_listeners[LISTEN_LAST];
|
|
||||||
|
|
||||||
std::array<authd_cb, 256> authd_cmd_tab =
|
|
||||||
[]{
|
|
||||||
std::array<authd_cb, 256> ret {0};
|
|
||||||
ret['A'] = { cmd_accept_client, 4 };
|
|
||||||
ret['E'] = { cmd_dns_result, 5 };
|
|
||||||
ret['N'] = { cmd_notice_client, 3 };
|
|
||||||
ret['R'] = { cmd_reject_client, 7 };
|
|
||||||
ret['W'] = { cmd_oper_warn, 3 };
|
|
||||||
ret['X'] = { cmd_stats_results, 3 };
|
|
||||||
ret['Y'] = { cmd_stats_results, 3 };
|
|
||||||
ret['Z'] = { cmd_stats_results, 3 };
|
|
||||||
return ret;
|
|
||||||
}();
|
|
||||||
|
|
||||||
static int
|
|
||||||
start_authd(void)
|
|
||||||
{
|
|
||||||
char fullpath[PATH_MAX + 1];
|
|
||||||
#ifdef _WIN32
|
|
||||||
const char *suffix = ".exe";
|
|
||||||
#else
|
|
||||||
const char *suffix = "";
|
|
||||||
#endif
|
|
||||||
if(authd_path == NULL)
|
|
||||||
{
|
|
||||||
snprintf(fullpath, sizeof(fullpath), "%s%cauthd%s", path::get(path::LIBEXEC), RB_PATH_SEPARATOR, suffix);
|
|
||||||
|
|
||||||
if(access(fullpath, X_OK) == -1)
|
|
||||||
{
|
|
||||||
snprintf(fullpath, sizeof(fullpath), "%s%cbin%cauthd%s",
|
|
||||||
ConfigFileEntry.dpath, RB_PATH_SEPARATOR, RB_PATH_SEPARATOR, suffix);
|
|
||||||
if(access(fullpath, X_OK) == -1)
|
|
||||||
{
|
|
||||||
// TODO: double dipping
|
|
||||||
ierror("Unable to execute authd in %s or %s/bin",
|
|
||||||
path::get(path::LIBEXEC),
|
|
||||||
ConfigFileEntry.dpath);
|
|
||||||
|
|
||||||
// TODO: double dipping
|
|
||||||
sendto_realops_snomask(sno::GENERAL, L_ALL,
|
|
||||||
"Unable to execute authd in %s or %s/bin",
|
|
||||||
path::get(path::LIBEXEC),
|
|
||||||
ConfigFileEntry.dpath);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
authd_path = rb_strdup(fullpath);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(cid_clients == NULL)
|
|
||||||
cid_clients = rb_dictionary_create("authd cid to uid mapping", rb_uint32cmp);
|
|
||||||
|
|
||||||
if(timeout_ev == NULL)
|
|
||||||
timeout_ev = rb_event_addish("timeout_dead_authd_clients", timeout_dead_authd_clients, NULL, 1);
|
|
||||||
|
|
||||||
authd_helper = rb_helper_start("authd", authd_path, parse_authd_reply, restart_authd_cb);
|
|
||||||
|
|
||||||
if(authd_helper == NULL)
|
|
||||||
{
|
|
||||||
ierror("Unable to start authd helper: %s", strerror(errno));
|
|
||||||
sendto_realops_snomask(sno::GENERAL, L_ALL, "Unable to start authd helper: %s", strerror(errno));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ilog(L_MAIN, "authd helper started");
|
|
||||||
sendto_realops_snomask(sno::GENERAL, L_ALL, "authd helper started");
|
|
||||||
rb_helper_run(authd_helper);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint32_t
|
|
||||||
str_to_cid(const char *str)
|
|
||||||
{
|
|
||||||
long lcid = strtol(str, NULL, 16);
|
|
||||||
|
|
||||||
if(lcid > UINT32_MAX || lcid <= 0)
|
|
||||||
{
|
|
||||||
iwarn("authd sent us back a bad client ID: %lx", lcid);
|
|
||||||
restart_authd();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (uint32_t)lcid;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline client::client *
|
|
||||||
cid_to_client(uint32_t ncid, bool del)
|
|
||||||
{
|
|
||||||
client::client *client_p;
|
|
||||||
|
|
||||||
if(del)
|
|
||||||
client_p = (client::client *)rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(ncid));
|
|
||||||
else
|
|
||||||
client_p = (client::client *)rb_dictionary_retrieve(cid_clients, RB_UINT_TO_POINTER(ncid));
|
|
||||||
|
|
||||||
/* If the client's not found, that's okay, it may have already gone away.
|
|
||||||
* --Elizafox */
|
|
||||||
|
|
||||||
return client_p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline client::client *
|
|
||||||
str_cid_to_client(const char *str, bool del)
|
|
||||||
{
|
|
||||||
uint32_t ncid = str_to_cid(str);
|
|
||||||
|
|
||||||
if(ncid == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return cid_to_client(ncid, del);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cmd_accept_client(int parc, char **parv)
|
|
||||||
{
|
|
||||||
client::client *client_p;
|
|
||||||
|
|
||||||
/* cid to uid (retrieve and delete) */
|
|
||||||
if((client_p = str_cid_to_client(parv[1], true)) == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
authd_accept_client(client_p, parv[2], parv[3]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cmd_dns_result(int parc, char **parv)
|
|
||||||
{
|
|
||||||
dns_results_callback(parv[1], parv[2], parv[3], parv[4]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cmd_notice_client(int parc, char **parv)
|
|
||||||
{
|
|
||||||
client::client *client_p;
|
|
||||||
|
|
||||||
if((client_p = str_cid_to_client(parv[1], false)) == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
sendto_one_notice(client_p, ":%s", parv[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cmd_reject_client(int parc, char **parv)
|
|
||||||
{
|
|
||||||
client::client *client_p;
|
|
||||||
|
|
||||||
/* cid to uid (retrieve and delete) */
|
|
||||||
if((client_p = str_cid_to_client(parv[1], true)) == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
authd_reject_client(client_p, parv[3], parv[4], toupper(*parv[2]), parv[5], parv[6]);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cmd_oper_warn(int parc, char **parv)
|
|
||||||
{
|
|
||||||
switch(*parv[1])
|
|
||||||
{
|
|
||||||
case 'D': /* Debug */
|
|
||||||
sendto_realops_snomask(sno::DEBUG, L_ALL, "authd debug: %s", parv[2]);
|
|
||||||
idebug("authd: %s", parv[2]);
|
|
||||||
break;
|
|
||||||
case 'I': /* Info */
|
|
||||||
sendto_realops_snomask(sno::GENERAL, L_ALL, "authd info: %s", parv[2]);
|
|
||||||
inotice("authd: %s", parv[2]);
|
|
||||||
break;
|
|
||||||
case 'W': /* Warning */
|
|
||||||
sendto_realops_snomask(sno::GENERAL, L_ALL, "authd WARNING: %s", parv[2]);
|
|
||||||
iwarn("authd: %s", parv[2]);
|
|
||||||
break;
|
|
||||||
case 'C': /* Critical (error) */
|
|
||||||
sendto_realops_snomask(sno::GENERAL, L_ALL, "authd CRITICAL: %s", parv[2]);
|
|
||||||
ierror("authd: %s", parv[2]);
|
|
||||||
break;
|
|
||||||
default: /* idk */
|
|
||||||
sendto_realops_snomask(sno::GENERAL, L_ALL, "authd sent us an unknown oper notice type (%s): %s", parv[1], parv[2]);
|
|
||||||
ilog(L_MAIN, "authd unknown oper notice type (%s): %s", parv[1], parv[2]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cmd_stats_results(int parc, char **parv)
|
|
||||||
{
|
|
||||||
/* Select by type */
|
|
||||||
switch(*parv[2])
|
|
||||||
{
|
|
||||||
case 'D':
|
|
||||||
/* parv[0] conveys status */
|
|
||||||
if(parc < 4)
|
|
||||||
{
|
|
||||||
iwarn("authd sent a result with wrong number of arguments: got %d", parc);
|
|
||||||
restart_authd();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dns_stats_results_callback(parv[1], parv[0], parc - 3, (const char **)&parv[3]);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
parse_authd_reply(rb_helper * helper)
|
|
||||||
{
|
|
||||||
ssize_t len;
|
|
||||||
int parc;
|
|
||||||
char buf[READBUF_SIZE];
|
|
||||||
char *parv[MAXPARA + 1];
|
|
||||||
|
|
||||||
while((len = rb_helper_read(helper, buf, sizeof(buf))) > 0)
|
|
||||||
{
|
|
||||||
struct authd_cb *cmd;
|
|
||||||
|
|
||||||
parc = rb_string_to_array(buf, parv, MAXPARA+1);
|
|
||||||
cmd = &authd_cmd_tab[(unsigned char)*parv[0]];
|
|
||||||
if(cmd->fn != NULL)
|
|
||||||
{
|
|
||||||
if(cmd->min_parc > parc)
|
|
||||||
{
|
|
||||||
iwarn("authd sent a result with wrong number of arguments: expected %d, got %d",
|
|
||||||
cmd->min_parc, parc);
|
|
||||||
restart_authd();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
cmd->fn(parc, parv);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
iwarn("authd sent us a bad command type: %c", *parv[0]);
|
|
||||||
restart_authd();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
init_authd(void)
|
|
||||||
{
|
|
||||||
if(start_authd())
|
|
||||||
{
|
|
||||||
ierror("Unable to start authd helper: %s", strerror(errno));
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
configure_authd(void)
|
|
||||||
{
|
|
||||||
/* Timeouts */
|
|
||||||
set_authd_timeout("ident_timeout", GlobalSetOptions.ident_timeout);
|
|
||||||
set_authd_timeout("rdns_timeout", ConfigFileEntry.connect_timeout);
|
|
||||||
set_authd_timeout("rbl_timeout", ConfigFileEntry.connect_timeout);
|
|
||||||
|
|
||||||
ident_check_enable(!ConfigFileEntry.disable_auth);
|
|
||||||
|
|
||||||
/* Configure OPM */
|
|
||||||
if(rb_dlink_list_length(&opm_list) > 0 &&
|
|
||||||
(opm_listeners[LISTEN_IPV4].ipaddr[0] != '\0' ||
|
|
||||||
opm_listeners[LISTEN_IPV6].ipaddr[0] != '\0'))
|
|
||||||
{
|
|
||||||
rb_dlink_node *ptr;
|
|
||||||
|
|
||||||
if(opm_listeners[LISTEN_IPV4].ipaddr[0] != '\0')
|
|
||||||
rb_helper_write(authd_helper, "O opm_listener %s %hu",
|
|
||||||
opm_listeners[LISTEN_IPV4].ipaddr, opm_listeners[LISTEN_IPV4].port);
|
|
||||||
|
|
||||||
#ifdef RB_IPV6
|
|
||||||
if(opm_listeners[LISTEN_IPV6].ipaddr[0] != '\0')
|
|
||||||
rb_helper_write(authd_helper, "O opm_listener %s %hu",
|
|
||||||
opm_listeners[LISTEN_IPV6].ipaddr, opm_listeners[LISTEN_IPV6].port);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
RB_DLINK_FOREACH(ptr, opm_list.head)
|
|
||||||
{
|
|
||||||
struct OPMScanner *scanner = (OPMScanner *)ptr->data;
|
|
||||||
rb_helper_write(authd_helper, "O opm_scanner %s %hu",
|
|
||||||
scanner->type, scanner->port);
|
|
||||||
}
|
|
||||||
|
|
||||||
opm_check_enable(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
opm_check_enable(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
authd_free_client(client::client *client_p)
|
|
||||||
{
|
|
||||||
if(client_p == NULL || client_p->preClient == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(client_p->preClient->auth.cid == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(authd_helper != NULL)
|
|
||||||
rb_helper_write(authd_helper, "E %x", client_p->preClient->auth.cid);
|
|
||||||
|
|
||||||
client_p->preClient->auth.accepted = true;
|
|
||||||
client_p->preClient->auth.cid = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
authd_free_client_cb(rb_dictionary_element *delem, void *unused)
|
|
||||||
{
|
|
||||||
client::client *client_p = (client::client *)delem->data;
|
|
||||||
authd_free_client(client_p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
authd_abort_client(client::client *client_p)
|
|
||||||
{
|
|
||||||
rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(client_p->preClient->auth.cid));
|
|
||||||
authd_free_client(client_p);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
restart_authd_cb(rb_helper * helper)
|
|
||||||
{
|
|
||||||
rb_dictionary_iter iter;
|
|
||||||
client::client *client_p;
|
|
||||||
|
|
||||||
iwarn("authd: restart_authd_cb called, authd died?");
|
|
||||||
sendto_realops_snomask(sno::GENERAL, L_ALL, "authd: restart_authd_cb called, authd died?");
|
|
||||||
|
|
||||||
if(helper != NULL)
|
|
||||||
{
|
|
||||||
rb_helper_close(helper);
|
|
||||||
authd_helper = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
rb_dictionary_destroy(cid_clients, authd_free_client_cb, NULL);
|
|
||||||
cid_clients = NULL;
|
|
||||||
|
|
||||||
start_authd();
|
|
||||||
configure_authd();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
restart_authd(void)
|
|
||||||
{
|
|
||||||
ierror("authd restarting...");
|
|
||||||
restart_authd_cb(authd_helper);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
rehash_authd(void)
|
|
||||||
{
|
|
||||||
rb_helper_write(authd_helper, "R");
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
check_authd(void)
|
|
||||||
{
|
|
||||||
if(authd_helper == NULL)
|
|
||||||
restart_authd();
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint32_t
|
|
||||||
generate_cid(void)
|
|
||||||
{
|
|
||||||
if(++cid == 0)
|
|
||||||
cid = 1;
|
|
||||||
|
|
||||||
return cid;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Basically when this is called we begin handing off the client to authd for
|
|
||||||
* processing. authd "owns" the client until processing is finished, or we
|
|
||||||
* timeout from authd. authd will make a decision whether or not to accept the
|
|
||||||
* client, but it's up to other parts of the code (for now) to decide if we're
|
|
||||||
* gonna accept the client and ignore authd's suggestion.
|
|
||||||
*
|
|
||||||
* --Elizafox
|
|
||||||
*
|
|
||||||
* If this is an SSL connection we must defer handing off the client for
|
|
||||||
* reading until it is open and we have the certificate fingerprint, otherwise
|
|
||||||
* it's possible for the client to immediately send data before authd completes
|
|
||||||
* and before the status of the connection is communicated via ssld. This data
|
|
||||||
* could then be processed too early by read_packet().
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
authd_initiate_client(client::client *client_p, bool defer)
|
|
||||||
{
|
|
||||||
char client_ipaddr[HOSTIPLEN+1];
|
|
||||||
char listen_ipaddr[HOSTIPLEN+1];
|
|
||||||
uint16_t client_port, listen_port;
|
|
||||||
uint32_t authd_cid;
|
|
||||||
|
|
||||||
if(client_p->preClient == NULL || client_p->preClient->auth.cid != 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
authd_cid = client_p->preClient->auth.cid = generate_cid();
|
|
||||||
|
|
||||||
/* Collisions are extremely unlikely, so disregard the possibility */
|
|
||||||
rb_dictionary_add(cid_clients, RB_UINT_TO_POINTER(authd_cid), client_p);
|
|
||||||
|
|
||||||
/* Retrieve listener and client IP's */
|
|
||||||
rb_inet_ntop_sock((struct sockaddr *)&client_p->preClient->lip, listen_ipaddr, sizeof(listen_ipaddr));
|
|
||||||
rb_inet_ntop_sock((struct sockaddr *)&client_p->localClient->ip, client_ipaddr, sizeof(client_ipaddr));
|
|
||||||
|
|
||||||
/* Retrieve listener and client ports */
|
|
||||||
listen_port = ntohs(GET_SS_PORT(&client_p->preClient->lip));
|
|
||||||
client_port = ntohs(GET_SS_PORT(&client_p->localClient->ip));
|
|
||||||
|
|
||||||
if(defer)
|
|
||||||
client_p->preClient->auth.flags |= AUTHC_F_DEFERRED;
|
|
||||||
|
|
||||||
/* Add a bit of a fudge factor... */
|
|
||||||
client_p->preClient->auth.timeout = rb_current_time() + ConfigFileEntry.connect_timeout + 10;
|
|
||||||
|
|
||||||
rb_helper_write(authd_helper, "C %x %s %hu %s %hu", authd_cid, listen_ipaddr, listen_port, client_ipaddr, client_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
authd_read_client(client::client *client_p)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* When a client has auth'ed, we want to start reading what it sends
|
|
||||||
* us. This is what read_packet() does.
|
|
||||||
* -- adrian
|
|
||||||
*
|
|
||||||
* Above comment was originally in s_auth.c, but moved here with below code.
|
|
||||||
* --Elizafox
|
|
||||||
*/
|
|
||||||
rb_dlinkAddTail(client_p, &client_p->node, &global_client_list);
|
|
||||||
read_packet(client_p->localClient->F, client_p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* When this is called we have a decision on client acceptance.
|
|
||||||
*
|
|
||||||
* After this point authd no longer "owns" the client, but if
|
|
||||||
* it's flagged as deferred then we're still waiting for a call
|
|
||||||
* to authd_deferred_client().
|
|
||||||
*/
|
|
||||||
static inline void
|
|
||||||
authd_decide_client(client::client *client_p, const char *ident, const char *host, bool accept, char cause, const char *data, const char *reason)
|
|
||||||
{
|
|
||||||
if(client_p->preClient == NULL || client_p->preClient->auth.cid == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(*ident != '*')
|
|
||||||
{
|
|
||||||
rb_strlcpy(client_p->username, ident, sizeof(client_p->username));
|
|
||||||
set_got_id(*client_p);
|
|
||||||
ServerStats.is_asuc++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
ServerStats.is_abad++; /* s_auth used to do this, stay compatible */
|
|
||||||
|
|
||||||
if(*host != '*')
|
|
||||||
rb_strlcpy(client_p->host, host, sizeof(client_p->host));
|
|
||||||
|
|
||||||
rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(client_p->preClient->auth.cid));
|
|
||||||
|
|
||||||
client_p->preClient->auth.accepted = accept;
|
|
||||||
client_p->preClient->auth.cause = cause;
|
|
||||||
client_p->preClient->auth.data = (data == NULL ? NULL : rb_strdup(data));
|
|
||||||
client_p->preClient->auth.reason = (reason == NULL ? NULL : rb_strdup(reason));
|
|
||||||
client_p->preClient->auth.cid = 0;
|
|
||||||
|
|
||||||
client_p->preClient->auth.flags |= AUTHC_F_COMPLETE;
|
|
||||||
if((client_p->preClient->auth.flags & AUTHC_F_DEFERRED) == 0)
|
|
||||||
authd_read_client(client_p);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
authd_deferred_client(client::client *client_p)
|
|
||||||
{
|
|
||||||
client_p->preClient->auth.flags &= ~AUTHC_F_DEFERRED;
|
|
||||||
if(client_p->preClient->auth.flags & AUTHC_F_COMPLETE)
|
|
||||||
authd_read_client(client_p);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convenience function to accept client */
|
|
||||||
void
|
|
||||||
authd_accept_client(client::client *client_p, const char *ident, const char *host)
|
|
||||||
{
|
|
||||||
authd_decide_client(client_p, ident, host, true, '\0', NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Convenience function to reject client */
|
|
||||||
void
|
|
||||||
authd_reject_client(client::client *client_p, const char *ident, const char *host, char cause, const char *data, const char *reason)
|
|
||||||
{
|
|
||||||
authd_decide_client(client_p, ident, host, false, cause, data, reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
timeout_dead_authd_clients(void *notused)
|
|
||||||
{
|
|
||||||
rb_dictionary_iter iter;
|
|
||||||
client::client *client_p;
|
|
||||||
rb_dlink_list freelist = { NULL, NULL, 0 };
|
|
||||||
rb_dlink_node *ptr, *nptr;
|
|
||||||
|
|
||||||
void *elem;
|
|
||||||
RB_DICTIONARY_FOREACH(elem, &iter, cid_clients)
|
|
||||||
{
|
|
||||||
client_p = (client::client *)elem;
|
|
||||||
if(client_p->preClient->auth.timeout < rb_current_time())
|
|
||||||
{
|
|
||||||
authd_free_client(client_p);
|
|
||||||
rb_dlinkAddAlloc(client_p, &freelist);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* RB_DICTIONARY_FOREACH is not safe for deletion, so we do this crap */
|
|
||||||
RB_DLINK_FOREACH_SAFE(ptr, nptr, freelist.head)
|
|
||||||
{
|
|
||||||
client_p = (client::client *)ptr->data;
|
|
||||||
rb_dictionary_delete(cid_clients, RB_UINT_TO_POINTER(client_p->preClient->auth.cid));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Send a new blacklist to authd */
|
|
||||||
void
|
|
||||||
add_blacklist(const char *host, const char *reason, uint8_t iptype, rb_dlink_list *filters)
|
|
||||||
{
|
|
||||||
rb_dlink_node *ptr;
|
|
||||||
struct BlacklistStats *stats = (BlacklistStats *)rb_malloc(sizeof(struct BlacklistStats));
|
|
||||||
char filterbuf[BUFSIZE] = "*";
|
|
||||||
size_t s = 0;
|
|
||||||
|
|
||||||
if(bl_stats == NULL)
|
|
||||||
bl_stats = rb_dictionary_create("blacklist statistics", reinterpret_cast<int (*)(const void *, const void *)>(rb_strcasecmp));
|
|
||||||
|
|
||||||
/* Build a list of comma-separated values for authd.
|
|
||||||
* We don't check for validity - do it elsewhere.
|
|
||||||
*/
|
|
||||||
RB_DLINK_FOREACH(ptr, filters->head)
|
|
||||||
{
|
|
||||||
char *filter = (char *)ptr->data;
|
|
||||||
size_t filterlen = strlen(filter) + 1;
|
|
||||||
|
|
||||||
if(s + filterlen > sizeof(filterbuf))
|
|
||||||
break;
|
|
||||||
|
|
||||||
snprintf(&filterbuf[s], sizeof(filterbuf) - s, "%s,", filter);
|
|
||||||
|
|
||||||
s += filterlen;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(s)
|
|
||||||
filterbuf[s - 1] = '\0';
|
|
||||||
|
|
||||||
stats->host = rb_strdup(host);
|
|
||||||
stats->iptype = iptype;
|
|
||||||
stats->hits = 0;
|
|
||||||
rb_dictionary_add(bl_stats, stats->host, stats);
|
|
||||||
|
|
||||||
rb_helper_write(authd_helper, "O rbl %s %hhu %s :%s", host, iptype, filterbuf, reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Delete a blacklist */
|
|
||||||
void
|
|
||||||
del_blacklist(const char *host)
|
|
||||||
{
|
|
||||||
struct BlacklistStats *stats = (BlacklistStats *)rb_dictionary_retrieve(bl_stats, host);
|
|
||||||
if(stats != NULL)
|
|
||||||
{
|
|
||||||
rb_dictionary_delete(bl_stats, host);
|
|
||||||
rb_free(stats->host);
|
|
||||||
rb_free(stats);
|
|
||||||
}
|
|
||||||
|
|
||||||
rb_helper_write(authd_helper, "O rbl_del %s", host);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
blacklist_delete(rb_dictionary_element *delem, void *unused)
|
|
||||||
{
|
|
||||||
struct BlacklistStats *stats = (BlacklistStats *)delem->data;
|
|
||||||
|
|
||||||
rb_free(stats->host);
|
|
||||||
rb_free(stats);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Delete all the blacklists */
|
|
||||||
void
|
|
||||||
del_blacklist_all(void)
|
|
||||||
{
|
|
||||||
if(bl_stats != NULL)
|
|
||||||
rb_dictionary_destroy(bl_stats, blacklist_delete, NULL);
|
|
||||||
bl_stats = NULL;
|
|
||||||
|
|
||||||
rb_helper_write(authd_helper, "O rbl_del_all");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Adjust an authd timeout value */
|
|
||||||
bool
|
|
||||||
set_authd_timeout(const char *key, int timeout)
|
|
||||||
{
|
|
||||||
if(timeout <= 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
rb_helper_write(authd_helper, "O %s %d", key, timeout);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Enable identd checks */
|
|
||||||
void
|
|
||||||
ident_check_enable(bool enabled)
|
|
||||||
{
|
|
||||||
rb_helper_write(authd_helper, "O ident_enabled %d", enabled ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create an OPM listener
|
|
||||||
* XXX - This is a big nasty hack, but it avoids resending duplicate data when
|
|
||||||
* configure_authd() is called.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
conf_create_opm_listener(const char *ip, uint16_t port)
|
|
||||||
{
|
|
||||||
char ipbuf[HOSTIPLEN];
|
|
||||||
struct OPMListener *listener;
|
|
||||||
|
|
||||||
rb_strlcpy(ipbuf, ip, sizeof(ipbuf));
|
|
||||||
if(ipbuf[0] == ':')
|
|
||||||
{
|
|
||||||
memmove(ipbuf + 1, ipbuf, sizeof(ipbuf) - 1);
|
|
||||||
ipbuf[0] = '0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* I am much too lazy to use rb_inet_pton and GET_SS_FAMILY for now --Elizafox */
|
|
||||||
listener = &opm_listeners[(strchr(ipbuf, ':') != NULL ? LISTEN_IPV6 : LISTEN_IPV4)];
|
|
||||||
rb_strlcpy(listener->ipaddr, ipbuf, sizeof(listener->ipaddr));
|
|
||||||
listener->port = port;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
create_opm_listener(const char *ip, uint16_t port)
|
|
||||||
{
|
|
||||||
char ipbuf[HOSTIPLEN];
|
|
||||||
|
|
||||||
/* XXX duplicated in conf_create_opm_listener */
|
|
||||||
rb_strlcpy(ipbuf, ip, sizeof(ipbuf));
|
|
||||||
if(ipbuf[0] == ':')
|
|
||||||
{
|
|
||||||
memmove(ipbuf + 1, ipbuf, sizeof(ipbuf) - 1);
|
|
||||||
ipbuf[0] = '0';
|
|
||||||
}
|
|
||||||
|
|
||||||
conf_create_opm_listener(ip, port);
|
|
||||||
rb_helper_write(authd_helper, "O opm_listener %s %hu", ipbuf, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
delete_opm_listener_all(void)
|
|
||||||
{
|
|
||||||
memset(&opm_listeners, 0, sizeof(opm_listeners));
|
|
||||||
rb_helper_write(authd_helper, "O opm_listener_del_all");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Disable all OPM scans */
|
|
||||||
void
|
|
||||||
opm_check_enable(bool enabled)
|
|
||||||
{
|
|
||||||
rb_helper_write(authd_helper, "O opm_enabled %d", enabled ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Create an OPM proxy scanner
|
|
||||||
* XXX - This is a big nasty hack, but it avoids resending duplicate data when
|
|
||||||
* configure_authd() is called.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
conf_create_opm_proxy_scanner(const char *type, uint16_t port)
|
|
||||||
{
|
|
||||||
struct OPMScanner *scanner = (OPMScanner *)rb_malloc(sizeof(struct OPMScanner));
|
|
||||||
|
|
||||||
rb_strlcpy(scanner->type, type, sizeof(scanner->type));
|
|
||||||
scanner->port = port;
|
|
||||||
rb_dlinkAdd(scanner, &scanner->node, &opm_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
create_opm_proxy_scanner(const char *type, uint16_t port)
|
|
||||||
{
|
|
||||||
conf_create_opm_proxy_scanner(type, port);
|
|
||||||
rb_helper_write(authd_helper, "O opm_scanner %s %hu", type, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
delete_opm_proxy_scanner(const char *type, uint16_t port)
|
|
||||||
{
|
|
||||||
rb_dlink_node *ptr, *nptr;
|
|
||||||
|
|
||||||
RB_DLINK_FOREACH_SAFE(ptr, nptr, opm_list.head)
|
|
||||||
{
|
|
||||||
struct OPMScanner *scanner = (OPMScanner *)ptr->data;
|
|
||||||
|
|
||||||
if(rb_strncasecmp(scanner->type, type, sizeof(scanner->type)) == 0 &&
|
|
||||||
scanner->port == port)
|
|
||||||
{
|
|
||||||
rb_dlinkDelete(ptr, &opm_list);
|
|
||||||
rb_free(scanner);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rb_helper_write(authd_helper, "O opm_scanner_del %s %hu", type, port);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
delete_opm_proxy_scanner_all(void)
|
|
||||||
{
|
|
||||||
rb_dlink_node *ptr, *nptr;
|
|
||||||
|
|
||||||
RB_DLINK_FOREACH_SAFE(ptr, nptr, opm_list.head)
|
|
||||||
{
|
|
||||||
struct OPMScanner *scanner = (OPMScanner *)ptr->data;
|
|
||||||
|
|
||||||
rb_dlinkDelete(ptr, &opm_list);
|
|
||||||
rb_free(scanner);
|
|
||||||
}
|
|
||||||
|
|
||||||
rb_helper_write(authd_helper, "O opm_scanner_del_all");
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ircd
|
|
437
ircd/bandbi.cc
437
ircd/bandbi.cc
|
@ -1,437 +0,0 @@
|
||||||
/* src/bandbi.c
|
|
||||||
* An interface to the ban db.
|
|
||||||
*
|
|
||||||
* Copyright (C) 2006 Lee Hardy <lee -at- leeh.co.uk>
|
|
||||||
* Copyright (C) 2006 ircd-ratbox development team
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without
|
|
||||||
* modification, are permitted provided that the following conditions are
|
|
||||||
* met:
|
|
||||||
*
|
|
||||||
* 1.Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2.Redistributions in binary form must reproduce the above copyright
|
|
||||||
* notice, this list of conditions and the following disclaimer in the
|
|
||||||
* documentation and/or other materials provided with the distribution.
|
|
||||||
* 3.The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
||||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
|
||||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
||||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
||||||
* POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace ircd {
|
|
||||||
|
|
||||||
static void
|
|
||||||
bandb_handle_failure(rb_helper *helper, char **parv, int parc) __attribute__((noreturn));
|
|
||||||
|
|
||||||
static char bandb_add_letter[LAST_BANDB_TYPE] = {
|
|
||||||
'K', 'D', 'X', 'R'
|
|
||||||
};
|
|
||||||
|
|
||||||
rb_dlink_list bandb_pending;
|
|
||||||
|
|
||||||
static rb_helper *bandb_helper;
|
|
||||||
static int start_bandb(void);
|
|
||||||
|
|
||||||
static void bandb_parse(rb_helper *);
|
|
||||||
static void bandb_restart_cb(rb_helper *);
|
|
||||||
static char *bandb_path;
|
|
||||||
|
|
||||||
void
|
|
||||||
init_bandb(void)
|
|
||||||
{
|
|
||||||
if(start_bandb())
|
|
||||||
{
|
|
||||||
ilog(L_MAIN, "Unable to start bandb helper: %s", strerror(errno));
|
|
||||||
exit(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static int
|
|
||||||
start_bandb(void)
|
|
||||||
{
|
|
||||||
char fullpath[PATH_MAX + 1];
|
|
||||||
#ifdef _WIN32
|
|
||||||
const char *suffix = ".exe";
|
|
||||||
#else
|
|
||||||
const char *suffix = "";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
rb_setenv("BANDB_DBPATH", path::get(path::BANDB), 1);
|
|
||||||
if(bandb_path == NULL)
|
|
||||||
{
|
|
||||||
snprintf(fullpath, sizeof(fullpath), "%s%cbandb%s", path::get(path::LIBEXEC), RB_PATH_SEPARATOR, suffix);
|
|
||||||
|
|
||||||
if(access(fullpath, X_OK) == -1)
|
|
||||||
{
|
|
||||||
snprintf(fullpath, sizeof(fullpath), "%s%cbin%cbandb%s",
|
|
||||||
ConfigFileEntry.dpath, RB_PATH_SEPARATOR, RB_PATH_SEPARATOR, suffix);
|
|
||||||
|
|
||||||
if(access(fullpath, X_OK) == -1)
|
|
||||||
{
|
|
||||||
ilog(L_MAIN,
|
|
||||||
"Unable to execute bandb%s in %s or %s/bin",
|
|
||||||
suffix, path::get(path::LIBEXEC), ConfigFileEntry.dpath);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bandb_path = rb_strdup(fullpath);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bandb_helper = rb_helper_start("bandb", bandb_path, bandb_parse, bandb_restart_cb);
|
|
||||||
|
|
||||||
if(bandb_helper == NULL)
|
|
||||||
{
|
|
||||||
ilog(L_MAIN, "Unable to start bandb: %s", strerror(errno));
|
|
||||||
sendto_realops_snomask(sno::GENERAL, L_ALL, "Unable to start bandb: %s",
|
|
||||||
strerror(errno));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rb_helper_run(bandb_helper);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
bandb_add(bandb_type type, client::client *source_p, const char *mask1,
|
|
||||||
const char *mask2, const char *reason, const char *oper_reason, int perm)
|
|
||||||
{
|
|
||||||
if(bandb_helper == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
static char buf[BUFSIZE];
|
|
||||||
|
|
||||||
snprintf(buf, sizeof(buf), "%c %s ", bandb_add_letter[type], mask1);
|
|
||||||
|
|
||||||
if(!EmptyString(mask2))
|
|
||||||
rb_snprintf_append(buf, sizeof(buf), "%s ", mask2);
|
|
||||||
|
|
||||||
rb_snprintf_append(buf, sizeof(buf), "%s %ld %d :%s",
|
|
||||||
get_oper_name(source_p), (long int)rb_current_time(), perm, reason);
|
|
||||||
|
|
||||||
if(!EmptyString(oper_reason))
|
|
||||||
rb_snprintf_append(buf, sizeof(buf), "|%s", oper_reason);
|
|
||||||
|
|
||||||
rb_helper_write(bandb_helper, "%s", buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char bandb_del_letter[LAST_BANDB_TYPE] = {
|
|
||||||
'k', 'd', 'x', 'r'
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
|
||||||
bandb_del(bandb_type type, const char *mask1, const char *mask2)
|
|
||||||
{
|
|
||||||
if(bandb_helper == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
static char buf[BUFSIZE];
|
|
||||||
|
|
||||||
buf[0] = '\0';
|
|
||||||
|
|
||||||
rb_snprintf_append(buf, sizeof(buf), "%c %s", bandb_del_letter[type], mask1);
|
|
||||||
|
|
||||||
if(!EmptyString(mask2))
|
|
||||||
rb_snprintf_append(buf, sizeof(buf), " %s", mask2);
|
|
||||||
|
|
||||||
rb_helper_write(bandb_helper, "%s", buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
bandb_handle_ban(char *parv[], int parc)
|
|
||||||
{
|
|
||||||
struct ConfItem *aconf;
|
|
||||||
char *p;
|
|
||||||
int para = 1;
|
|
||||||
|
|
||||||
aconf = make_conf();
|
|
||||||
aconf->port = 0;
|
|
||||||
|
|
||||||
if(parv[0][0] == 'K')
|
|
||||||
aconf->user = rb_strdup(parv[para++]);
|
|
||||||
|
|
||||||
aconf->host = rb_strdup(parv[para++]);
|
|
||||||
aconf->info.oper = operhash_add(parv[para++]);
|
|
||||||
|
|
||||||
switch (parv[0][0])
|
|
||||||
{
|
|
||||||
case 'K':
|
|
||||||
aconf->status = CONF_KILL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'D':
|
|
||||||
aconf->status = CONF_DLINE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'X':
|
|
||||||
aconf->status = CONF_XLINE;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'R':
|
|
||||||
if(chan::has_prefix(aconf->host))
|
|
||||||
aconf->status = CONF_RESV_CHANNEL;
|
|
||||||
else
|
|
||||||
aconf->status = CONF_RESV_NICK;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if((p = strchr(parv[para], '|')))
|
|
||||||
{
|
|
||||||
*p++ = '\0';
|
|
||||||
aconf->spasswd = rb_strdup(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
aconf->passwd = rb_strdup(parv[para]);
|
|
||||||
|
|
||||||
rb_dlinkAddAlloc(aconf, &bandb_pending);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
bandb_check_kline(struct ConfItem *aconf)
|
|
||||||
{
|
|
||||||
struct rb_sockaddr_storage daddr;
|
|
||||||
struct ConfItem *kconf = NULL;
|
|
||||||
int aftype;
|
|
||||||
const char *p;
|
|
||||||
|
|
||||||
aftype = parse_netmask(aconf->host, &daddr, NULL);
|
|
||||||
|
|
||||||
if(aftype != HM_HOST)
|
|
||||||
{
|
|
||||||
#ifdef RB_IPV6
|
|
||||||
if(aftype == HM_IPV6)
|
|
||||||
aftype = AF_INET6;
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
aftype = AF_INET;
|
|
||||||
|
|
||||||
kconf = find_conf_by_address(aconf->host, NULL, NULL, (struct sockaddr *)&daddr,
|
|
||||||
CONF_KILL, aftype, aconf->user, NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
kconf = find_conf_by_address(aconf->host, NULL, NULL, NULL, CONF_KILL, 0, aconf->user, NULL);
|
|
||||||
|
|
||||||
if(kconf && ((kconf->flags & CONF_FLAGS_TEMPORARY) == 0))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for(p = aconf->user; *p; p++)
|
|
||||||
if(!rfc1459::is_user(*p) && !rfc1459::is_kwild(*p))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for(p = aconf->host; *p; p++)
|
|
||||||
if(!rfc1459::is_host(*p) && !rfc1459::is_kwild(*p))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
bandb_check_dline(struct ConfItem *aconf)
|
|
||||||
{
|
|
||||||
struct rb_sockaddr_storage daddr;
|
|
||||||
int bits;
|
|
||||||
|
|
||||||
if(!parse_netmask(aconf->host, &daddr, &bits))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
bandb_check_xline(struct ConfItem *aconf)
|
|
||||||
{
|
|
||||||
struct ConfItem *xconf;
|
|
||||||
/* XXX perhaps convert spaces to \s? -- jilles */
|
|
||||||
|
|
||||||
xconf = find_xline_mask(aconf->host);
|
|
||||||
if(xconf != NULL && !(xconf->flags & CONF_FLAGS_TEMPORARY))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
bandb_check_resv_channel(struct ConfItem *aconf)
|
|
||||||
{
|
|
||||||
const char *p;
|
|
||||||
|
|
||||||
if(hash_find_resv(aconf->host) || strlen(aconf->host) > CHANNELLEN)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
for(p = aconf->host; *p; p++)
|
|
||||||
if(!rfc1459::is_chan(*p))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int
|
|
||||||
bandb_check_resv_nick(struct ConfItem *aconf)
|
|
||||||
{
|
|
||||||
if(!clean_resv_nick(aconf->host))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if(find_nick_resv(aconf->host))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
bandb_handle_clear(void)
|
|
||||||
{
|
|
||||||
rb_dlink_node *ptr, *next_ptr;
|
|
||||||
|
|
||||||
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
|
|
||||||
{
|
|
||||||
free_conf((ConfItem *)ptr->data);
|
|
||||||
rb_dlinkDestroy(ptr, &bandb_pending);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
bandb_handle_finish(void)
|
|
||||||
{
|
|
||||||
struct ConfItem *aconf;
|
|
||||||
rb_dlink_node *ptr, *next_ptr;
|
|
||||||
|
|
||||||
clear_out_address_conf_bans();
|
|
||||||
clear_s_newconf_bans();
|
|
||||||
|
|
||||||
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, bandb_pending.head)
|
|
||||||
{
|
|
||||||
aconf = (ConfItem *)ptr->data;
|
|
||||||
|
|
||||||
rb_dlinkDestroy(ptr, &bandb_pending);
|
|
||||||
|
|
||||||
switch (aconf->status)
|
|
||||||
{
|
|
||||||
case CONF_KILL:
|
|
||||||
if(bandb_check_kline(aconf))
|
|
||||||
add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf);
|
|
||||||
else
|
|
||||||
free_conf(aconf);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CONF_DLINE:
|
|
||||||
if(bandb_check_dline(aconf))
|
|
||||||
add_conf_by_address(aconf->host, CONF_DLINE, aconf->user, NULL, aconf);
|
|
||||||
else
|
|
||||||
free_conf(aconf);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CONF_XLINE:
|
|
||||||
if(bandb_check_xline(aconf))
|
|
||||||
rb_dlinkAddAlloc(aconf, &xline_conf_list);
|
|
||||||
else
|
|
||||||
free_conf(aconf);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CONF_RESV_CHANNEL:
|
|
||||||
if(bandb_check_resv_channel(aconf))
|
|
||||||
add_to_resv_hash(aconf->host, aconf);
|
|
||||||
else
|
|
||||||
free_conf(aconf);
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case CONF_RESV_NICK:
|
|
||||||
if(bandb_check_resv_nick(aconf))
|
|
||||||
rb_dlinkAddAlloc(aconf, &resv_conf_list);
|
|
||||||
else
|
|
||||||
free_conf(aconf);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
client::check_banned_lines();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
bandb_handle_failure(rb_helper *helper, char **parv, int parc)
|
|
||||||
{
|
|
||||||
if(server_state_foreground)
|
|
||||||
fprintf(stderr, "bandb - bandb failure: %s\n", parv[1]);
|
|
||||||
|
|
||||||
ilog(L_MAIN, "bandb - bandb failure: %s", parv[1]);
|
|
||||||
sendto_realops_snomask(sno::GENERAL, L_ALL, "bandb - bandb failure: %s", parv[1]);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
bandb_parse(rb_helper *helper)
|
|
||||||
{
|
|
||||||
static char buf[READBUF_SIZE];
|
|
||||||
char *parv[MAXPARA + 1];
|
|
||||||
int len, parc;
|
|
||||||
|
|
||||||
while((len = rb_helper_read(helper, buf, sizeof(buf))))
|
|
||||||
{
|
|
||||||
parc = rb_string_to_array(buf, parv, MAXPARA);
|
|
||||||
|
|
||||||
if(parc < 1)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
switch (parv[0][0])
|
|
||||||
{
|
|
||||||
case '!':
|
|
||||||
bandb_handle_failure(helper, parv, parc);
|
|
||||||
break;
|
|
||||||
case 'K':
|
|
||||||
case 'D':
|
|
||||||
case 'X':
|
|
||||||
case 'R':
|
|
||||||
bandb_handle_ban(parv, parc);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'C':
|
|
||||||
bandb_handle_clear();
|
|
||||||
break;
|
|
||||||
case 'F':
|
|
||||||
bandb_handle_finish();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
bandb_rehash_bans(void)
|
|
||||||
{
|
|
||||||
if(bandb_helper != NULL)
|
|
||||||
rb_helper_write(bandb_helper, "L");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
bandb_restart_cb(rb_helper *helper)
|
|
||||||
{
|
|
||||||
ilog(L_MAIN, "bandb - bandb_restart_cb called, bandb helper died?");
|
|
||||||
sendto_realops_snomask(sno::GENERAL, L_ALL,
|
|
||||||
"bandb - bandb_restart_cb called, bandb helper died?");
|
|
||||||
if(helper != NULL)
|
|
||||||
{
|
|
||||||
rb_helper_close(helper);
|
|
||||||
bandb_helper = NULL;
|
|
||||||
}
|
|
||||||
start_bandb();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace ircd
|
|
1002
ircd/sslproc.cc
1002
ircd/sslproc.cc
File diff suppressed because it is too large
Load diff
583
ircd/wsproc.cc
583
ircd/wsproc.cc
|
@ -1,583 +0,0 @@
|
||||||
/*
|
|
||||||
* sslproc.c: An interface to wsockd
|
|
||||||
* Copyright (C) 2007 Aaron Sethman <androsyn@ratbox.org>
|
|
||||||
* Copyright (C) 2007 ircd-ratbox development team
|
|
||||||
*
|
|
||||||
* This program is free software; you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program; if not, write to the Free Software
|
|
||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
|
|
||||||
* USA
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace ircd {
|
|
||||||
|
|
||||||
static void ws_read_ctl(rb_fde_t * F, void *data);
|
|
||||||
static int wsockd_count;
|
|
||||||
|
|
||||||
static char tmpbuf[READBUF_SIZE];
|
|
||||||
static char nul = '\0';
|
|
||||||
|
|
||||||
#define MAXPASSFD 4
|
|
||||||
#define READSIZE 1024
|
|
||||||
typedef struct _ws_ctl_buf
|
|
||||||
{
|
|
||||||
rb_dlink_node node;
|
|
||||||
char *buf;
|
|
||||||
size_t buflen;
|
|
||||||
rb_fde_t *F[MAXPASSFD];
|
|
||||||
int nfds;
|
|
||||||
} ws_ctl_buf_t;
|
|
||||||
|
|
||||||
|
|
||||||
struct ws_ctl
|
|
||||||
{
|
|
||||||
rb_dlink_node node;
|
|
||||||
int cli_count;
|
|
||||||
rb_fde_t *F;
|
|
||||||
rb_fde_t *P;
|
|
||||||
pid_t pid;
|
|
||||||
rb_dlink_list readq;
|
|
||||||
rb_dlink_list writeq;
|
|
||||||
uint8_t shutdown;
|
|
||||||
uint8_t dead;
|
|
||||||
};
|
|
||||||
|
|
||||||
static rb_dlink_list wsock_daemons;
|
|
||||||
|
|
||||||
static inline uint32_t
|
|
||||||
buf_to_uint32(char *buf)
|
|
||||||
{
|
|
||||||
uint32_t x;
|
|
||||||
memcpy(&x, buf, sizeof(x));
|
|
||||||
return x;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void
|
|
||||||
uint32_to_buf(char *buf, uint32_t x)
|
|
||||||
{
|
|
||||||
memcpy(buf, &x, sizeof(x));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ws_ctl_t *
|
|
||||||
allocate_ws_daemon(rb_fde_t * F, rb_fde_t * P, int pid)
|
|
||||||
{
|
|
||||||
ws_ctl_t *ctl;
|
|
||||||
|
|
||||||
if(F == NULL || pid < 0)
|
|
||||||
return NULL;
|
|
||||||
ctl = (ws_ctl_t *)rb_malloc(sizeof(ws_ctl_t));
|
|
||||||
ctl->F = F;
|
|
||||||
ctl->P = P;
|
|
||||||
ctl->pid = pid;
|
|
||||||
wsockd_count++;
|
|
||||||
rb_dlinkAdd(ctl, &ctl->node, &wsock_daemons);
|
|
||||||
return ctl;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
free_ws_daemon(ws_ctl_t * ctl)
|
|
||||||
{
|
|
||||||
rb_dlink_node *ptr;
|
|
||||||
ws_ctl_buf_t *ctl_buf;
|
|
||||||
int x;
|
|
||||||
if(ctl->cli_count)
|
|
||||||
return;
|
|
||||||
|
|
||||||
RB_DLINK_FOREACH(ptr, ctl->readq.head)
|
|
||||||
{
|
|
||||||
ctl_buf = (ws_ctl_buf_t *)ptr->data;
|
|
||||||
for(x = 0; x < ctl_buf->nfds; x++)
|
|
||||||
rb_close(ctl_buf->F[x]);
|
|
||||||
|
|
||||||
rb_free(ctl_buf->buf);
|
|
||||||
rb_free(ctl_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
RB_DLINK_FOREACH(ptr, ctl->writeq.head)
|
|
||||||
{
|
|
||||||
ctl_buf = (ws_ctl_buf_t *)ptr->data;
|
|
||||||
for(x = 0; x < ctl_buf->nfds; x++)
|
|
||||||
rb_close(ctl_buf->F[x]);
|
|
||||||
|
|
||||||
rb_free(ctl_buf->buf);
|
|
||||||
rb_free(ctl_buf);
|
|
||||||
}
|
|
||||||
rb_close(ctl->F);
|
|
||||||
rb_close(ctl->P);
|
|
||||||
rb_dlinkDelete(&ctl->node, &wsock_daemons);
|
|
||||||
rb_free(ctl);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *wsockd_path;
|
|
||||||
|
|
||||||
static int wsockd_spin_count = 0;
|
|
||||||
static time_t last_spin;
|
|
||||||
static int wsockd_wait = 0;
|
|
||||||
|
|
||||||
void
|
|
||||||
restart_wsockd(void)
|
|
||||||
{
|
|
||||||
rb_dlink_node *ptr, *next;
|
|
||||||
ws_ctl_t *ctl;
|
|
||||||
|
|
||||||
RB_DLINK_FOREACH_SAFE(ptr, next, wsock_daemons.head)
|
|
||||||
{
|
|
||||||
ctl = (ws_ctl_t *)ptr->data;
|
|
||||||
if(ctl->dead)
|
|
||||||
continue;
|
|
||||||
if(ctl->shutdown)
|
|
||||||
continue;
|
|
||||||
ctl->shutdown = 1;
|
|
||||||
wsockd_count--;
|
|
||||||
if(!ctl->cli_count)
|
|
||||||
{
|
|
||||||
rb_kill(ctl->pid, SIGKILL);
|
|
||||||
free_ws_daemon(ctl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
start_wsockd(ServerInfo.wsockd_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
static void
|
|
||||||
ws_killall(void)
|
|
||||||
{
|
|
||||||
rb_dlink_node *ptr, *next;
|
|
||||||
ws_ctl_t *ctl;
|
|
||||||
RB_DLINK_FOREACH_SAFE(ptr, next, wsock_daemons.head)
|
|
||||||
{
|
|
||||||
ctl = ptr->data;
|
|
||||||
if(ctl->dead)
|
|
||||||
continue;
|
|
||||||
ctl->dead = 1;
|
|
||||||
if(!ctl->shutdown)
|
|
||||||
wsockd_count--;
|
|
||||||
rb_kill(ctl->pid, SIGKILL);
|
|
||||||
if(!ctl->cli_count)
|
|
||||||
free_ws_daemon(ctl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void
|
|
||||||
ws_dead(ws_ctl_t * ctl)
|
|
||||||
{
|
|
||||||
if(ctl->dead)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ctl->dead = 1;
|
|
||||||
rb_kill(ctl->pid, SIGKILL); /* make sure the process is really gone */
|
|
||||||
|
|
||||||
if(!ctl->shutdown)
|
|
||||||
{
|
|
||||||
wsockd_count--;
|
|
||||||
ilog(L_MAIN, "wsockd helper died - attempting to restart");
|
|
||||||
sendto_realops_snomask(sno::GENERAL, L_ALL, "wsockd helper died - attempting to restart");
|
|
||||||
start_wsockd(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ws_do_pipe(rb_fde_t * F, void *data)
|
|
||||||
{
|
|
||||||
int retlen;
|
|
||||||
ws_ctl_t *ctl = (ws_ctl_t *)data;
|
|
||||||
retlen = rb_write(F, "0", 1);
|
|
||||||
if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
|
|
||||||
{
|
|
||||||
ws_dead(ctl);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
rb_setselect(F, RB_SELECT_READ, ws_do_pipe, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
restart_wsockd_event(void *unused)
|
|
||||||
{
|
|
||||||
wsockd_spin_count = 0;
|
|
||||||
last_spin = 0;
|
|
||||||
wsockd_wait = 0;
|
|
||||||
if(ServerInfo.wsockd_count > get_wsockd_count())
|
|
||||||
{
|
|
||||||
int start = ServerInfo.wsockd_count - get_wsockd_count();
|
|
||||||
ilog(L_MAIN, "Attempting to restart wsockd processes");
|
|
||||||
sendto_realops_snomask(sno::GENERAL, L_ALL, "Attempting to restart wsockd processes");
|
|
||||||
start_wsockd(start);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
start_wsockd(int count)
|
|
||||||
{
|
|
||||||
rb_fde_t *F1, *F2;
|
|
||||||
rb_fde_t *P1, *P2;
|
|
||||||
#ifdef _WIN32
|
|
||||||
const char *suffix = ".exe";
|
|
||||||
#else
|
|
||||||
const char *suffix = "";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char fullpath[PATH_MAX + 1];
|
|
||||||
char fdarg[6];
|
|
||||||
const char *parv[2];
|
|
||||||
char buf[128];
|
|
||||||
char s_pid[10];
|
|
||||||
pid_t pid;
|
|
||||||
int started = 0, i;
|
|
||||||
|
|
||||||
if(wsockd_wait)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if(wsockd_spin_count > 20 && (rb_current_time() - last_spin < 5))
|
|
||||||
{
|
|
||||||
ilog(L_MAIN, "wsockd helper is spinning - will attempt to restart in 1 minute");
|
|
||||||
sendto_realops_snomask(sno::GENERAL, L_ALL,
|
|
||||||
"wsockd helper is spinning - will attempt to restart in 1 minute");
|
|
||||||
rb_event_add("restart_wsockd_event", restart_wsockd_event, NULL, 60);
|
|
||||||
wsockd_wait = 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
wsockd_spin_count++;
|
|
||||||
last_spin = rb_current_time();
|
|
||||||
|
|
||||||
if(wsockd_path == NULL)
|
|
||||||
{
|
|
||||||
snprintf(fullpath, sizeof(fullpath), "%s%cwsockd%s", path::get(path::LIBEXEC), RB_PATH_SEPARATOR, suffix);
|
|
||||||
|
|
||||||
if(access(fullpath, X_OK) == -1)
|
|
||||||
{
|
|
||||||
snprintf(fullpath, sizeof(fullpath), "%s%cbin%cwsockd%s",
|
|
||||||
ConfigFileEntry.dpath, RB_PATH_SEPARATOR, RB_PATH_SEPARATOR, suffix);
|
|
||||||
if(access(fullpath, X_OK) == -1)
|
|
||||||
{
|
|
||||||
ilog(L_MAIN,
|
|
||||||
"Unable to execute wsockd%s in %s or %s/bin",
|
|
||||||
suffix, path::get(path::LIBEXEC), ConfigFileEntry.dpath);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wsockd_path = rb_strdup(fullpath);
|
|
||||||
}
|
|
||||||
rb_strlcpy(buf, "-ircd wsockd daemon", sizeof(buf));
|
|
||||||
parv[0] = buf;
|
|
||||||
parv[1] = NULL;
|
|
||||||
|
|
||||||
for(i = 0; i < count; i++)
|
|
||||||
{
|
|
||||||
ws_ctl_t *ctl;
|
|
||||||
if(rb_socketpair(AF_UNIX, SOCK_DGRAM, 0, &F1, &F2, "wsockd handle passing socket") == -1)
|
|
||||||
{
|
|
||||||
ilog(L_MAIN, "Unable to create wsockd - rb_socketpair failed: %s", strerror(errno));
|
|
||||||
return started;
|
|
||||||
}
|
|
||||||
|
|
||||||
rb_set_buffers(F1, READBUF_SIZE);
|
|
||||||
rb_set_buffers(F2, READBUF_SIZE);
|
|
||||||
snprintf(fdarg, sizeof(fdarg), "%d", rb_get_fd(F2));
|
|
||||||
rb_setenv("CTL_FD", fdarg, 1);
|
|
||||||
if(rb_pipe(&P1, &P2, "wsockd pipe") == -1)
|
|
||||||
{
|
|
||||||
ilog(L_MAIN, "Unable to create wsockd - rb_pipe failed: %s", strerror(errno));
|
|
||||||
return started;
|
|
||||||
}
|
|
||||||
snprintf(fdarg, sizeof(fdarg), "%d", rb_get_fd(P1));
|
|
||||||
rb_setenv("CTL_PIPE", fdarg, 1);
|
|
||||||
snprintf(s_pid, sizeof(s_pid), "%d", (int)getpid());
|
|
||||||
rb_setenv("CTL_PPID", s_pid, 1);
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
|
||||||
SetHandleInformation((HANDLE) rb_get_fd(F2), HANDLE_FLAG_INHERIT, 1);
|
|
||||||
SetHandleInformation((HANDLE) rb_get_fd(P1), HANDLE_FLAG_INHERIT, 1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
pid = rb_spawn_process(wsockd_path, (const char **) parv);
|
|
||||||
if(pid == -1)
|
|
||||||
{
|
|
||||||
ilog(L_MAIN, "Unable to create wsockd: %s\n", strerror(errno));
|
|
||||||
rb_close(F1);
|
|
||||||
rb_close(F2);
|
|
||||||
rb_close(P1);
|
|
||||||
rb_close(P2);
|
|
||||||
return started;
|
|
||||||
}
|
|
||||||
started++;
|
|
||||||
rb_close(F2);
|
|
||||||
rb_close(P1);
|
|
||||||
ctl = allocate_ws_daemon(F1, P2, pid);
|
|
||||||
ws_read_ctl(ctl->F, ctl);
|
|
||||||
ws_do_pipe(P2, ctl);
|
|
||||||
|
|
||||||
}
|
|
||||||
return started;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ws_process_dead_fd(ws_ctl_t * ctl, ws_ctl_buf_t * ctl_buf)
|
|
||||||
{
|
|
||||||
client::client *client_p;
|
|
||||||
char reason[256];
|
|
||||||
uint32_t fd;
|
|
||||||
|
|
||||||
if(ctl_buf->buflen < 6)
|
|
||||||
return; /* bogus message..drop it.. XXX should warn here */
|
|
||||||
|
|
||||||
fd = buf_to_uint32(&ctl_buf->buf[1]);
|
|
||||||
rb_strlcpy(reason, &ctl_buf->buf[5], sizeof(reason));
|
|
||||||
client_p = find_cli_connid_hash(fd);
|
|
||||||
if(client_p == NULL)
|
|
||||||
return;
|
|
||||||
if(is_any_server(*client_p) || is_registered(*client_p))
|
|
||||||
{
|
|
||||||
/* read any last moment ERROR, QUIT or the like -- jilles */
|
|
||||||
if (!strcmp(reason, "Remote host closed the connection"))
|
|
||||||
read_packet(client_p->localClient->F, client_p);
|
|
||||||
if (is_any_dead(*client_p))
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
exit_client(client_p, client_p, &me, reason);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ws_process_cmd_recv(ws_ctl_t * ctl)
|
|
||||||
{
|
|
||||||
rb_dlink_node *ptr, *next;
|
|
||||||
ws_ctl_buf_t *ctl_buf;
|
|
||||||
unsigned long len;
|
|
||||||
|
|
||||||
if(ctl->dead)
|
|
||||||
return;
|
|
||||||
|
|
||||||
RB_DLINK_FOREACH_SAFE(ptr, next, ctl->readq.head)
|
|
||||||
{
|
|
||||||
ctl_buf = (ws_ctl_buf_t *)ptr->data;
|
|
||||||
switch (*ctl_buf->buf)
|
|
||||||
{
|
|
||||||
case 'D':
|
|
||||||
ws_process_dead_fd(ctl, ctl_buf);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
ilog(L_MAIN, "Received invalid command from wsockd: %s", ctl_buf->buf);
|
|
||||||
sendto_realops_snomask(sno::GENERAL, L_ALL, "Received invalid command from wsockd");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
rb_dlinkDelete(ptr, &ctl->readq);
|
|
||||||
rb_free(ctl_buf->buf);
|
|
||||||
rb_free(ctl_buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
ws_read_ctl(rb_fde_t * F, void *data)
|
|
||||||
{
|
|
||||||
ws_ctl_buf_t *ctl_buf;
|
|
||||||
ws_ctl_t *ctl = (ws_ctl_t *)data;
|
|
||||||
int retlen;
|
|
||||||
|
|
||||||
if(ctl->dead)
|
|
||||||
return;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
ctl_buf = (ws_ctl_buf_t *)rb_malloc(sizeof(ws_ctl_buf_t));
|
|
||||||
ctl_buf->buf = (char *)rb_malloc(READSIZE);
|
|
||||||
retlen = rb_recv_fd_buf(ctl->F, ctl_buf->buf, READSIZE, ctl_buf->F, 4);
|
|
||||||
ctl_buf->buflen = retlen;
|
|
||||||
if(retlen <= 0)
|
|
||||||
{
|
|
||||||
rb_free(ctl_buf->buf);
|
|
||||||
rb_free(ctl_buf);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->readq);
|
|
||||||
}
|
|
||||||
while(retlen > 0);
|
|
||||||
|
|
||||||
if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
|
|
||||||
{
|
|
||||||
ws_dead(ctl);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ws_process_cmd_recv(ctl);
|
|
||||||
rb_setselect(ctl->F, RB_SELECT_READ, ws_read_ctl, ctl);
|
|
||||||
}
|
|
||||||
|
|
||||||
static ws_ctl_t *
|
|
||||||
which_wsockd(void)
|
|
||||||
{
|
|
||||||
ws_ctl_t *ctl, *lowest = NULL;
|
|
||||||
rb_dlink_node *ptr;
|
|
||||||
|
|
||||||
RB_DLINK_FOREACH(ptr, wsock_daemons.head)
|
|
||||||
{
|
|
||||||
ctl = (ws_ctl_t *)ptr->data;
|
|
||||||
if(ctl->dead)
|
|
||||||
continue;
|
|
||||||
if(ctl->shutdown)
|
|
||||||
continue;
|
|
||||||
if(lowest == NULL)
|
|
||||||
{
|
|
||||||
lowest = ctl;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(ctl->cli_count < lowest->cli_count)
|
|
||||||
lowest = ctl;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (lowest);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ws_write_ctl(rb_fde_t * F, void *data)
|
|
||||||
{
|
|
||||||
ws_ctl_t *ctl = (ws_ctl_t *)data;
|
|
||||||
ws_ctl_buf_t *ctl_buf;
|
|
||||||
rb_dlink_node *ptr, *next;
|
|
||||||
int retlen, x;
|
|
||||||
|
|
||||||
if(ctl->dead)
|
|
||||||
return;
|
|
||||||
|
|
||||||
RB_DLINK_FOREACH_SAFE(ptr, next, ctl->writeq.head)
|
|
||||||
{
|
|
||||||
ctl_buf = (ws_ctl_buf_t *)ptr->data;
|
|
||||||
/* in theory unix sock_dgram shouldn't ever short write this.. */
|
|
||||||
retlen = rb_send_fd_buf(ctl->F, ctl_buf->F, ctl_buf->nfds, ctl_buf->buf, ctl_buf->buflen, ctl->pid);
|
|
||||||
if(retlen > 0)
|
|
||||||
{
|
|
||||||
rb_dlinkDelete(ptr, &ctl->writeq);
|
|
||||||
for(x = 0; x < ctl_buf->nfds; x++)
|
|
||||||
rb_close(ctl_buf->F[x]);
|
|
||||||
rb_free(ctl_buf->buf);
|
|
||||||
rb_free(ctl_buf);
|
|
||||||
|
|
||||||
}
|
|
||||||
if(retlen == 0 || (retlen < 0 && !rb_ignore_errno(errno)))
|
|
||||||
{
|
|
||||||
ws_dead(ctl);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rb_setselect(ctl->F, RB_SELECT_WRITE, ws_write_ctl, ctl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
ws_cmd_write_queue(ws_ctl_t * ctl, rb_fde_t ** F, int count, const void *buf, size_t buflen)
|
|
||||||
{
|
|
||||||
ws_ctl_buf_t *ctl_buf;
|
|
||||||
int x;
|
|
||||||
|
|
||||||
/* don't bother */
|
|
||||||
if(ctl->dead)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ctl_buf = (ws_ctl_buf_t *)rb_malloc(sizeof(ws_ctl_buf_t));
|
|
||||||
ctl_buf->buf = (char *)rb_malloc(buflen);
|
|
||||||
memcpy(ctl_buf->buf, buf, buflen);
|
|
||||||
ctl_buf->buflen = buflen;
|
|
||||||
|
|
||||||
for(x = 0; x < count && x < MAXPASSFD; x++)
|
|
||||||
{
|
|
||||||
ctl_buf->F[x] = F[x];
|
|
||||||
}
|
|
||||||
ctl_buf->nfds = count;
|
|
||||||
rb_dlinkAddTail(ctl_buf, &ctl_buf->node, &ctl->writeq);
|
|
||||||
ws_write_ctl(ctl->F, ctl);
|
|
||||||
}
|
|
||||||
|
|
||||||
ws_ctl_t *
|
|
||||||
start_wsockd_accept(rb_fde_t * sslF, rb_fde_t * plainF, uint32_t id)
|
|
||||||
{
|
|
||||||
rb_fde_t *F[2];
|
|
||||||
ws_ctl_t *ctl;
|
|
||||||
char buf[5];
|
|
||||||
F[0] = sslF;
|
|
||||||
F[1] = plainF;
|
|
||||||
|
|
||||||
buf[0] = 'A';
|
|
||||||
uint32_to_buf(&buf[1], id);
|
|
||||||
ctl = which_wsockd();
|
|
||||||
if(!ctl)
|
|
||||||
return NULL;
|
|
||||||
ctl->cli_count++;
|
|
||||||
ws_cmd_write_queue(ctl, F, 2, buf, sizeof(buf));
|
|
||||||
return ctl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
wsockd_decrement_clicount(ws_ctl_t * ctl)
|
|
||||||
{
|
|
||||||
if(ctl == NULL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ctl->cli_count--;
|
|
||||||
if(ctl->shutdown && !ctl->cli_count)
|
|
||||||
{
|
|
||||||
ctl->dead = 1;
|
|
||||||
rb_kill(ctl->pid, SIGKILL);
|
|
||||||
}
|
|
||||||
if(ctl->dead && !ctl->cli_count)
|
|
||||||
{
|
|
||||||
free_ws_daemon(ctl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
cleanup_dead_ws(void *unused)
|
|
||||||
{
|
|
||||||
rb_dlink_node *ptr, *next;
|
|
||||||
ws_ctl_t *ctl;
|
|
||||||
RB_DLINK_FOREACH_SAFE(ptr, next, wsock_daemons.head)
|
|
||||||
{
|
|
||||||
ctl = (ws_ctl_t *)ptr->data;
|
|
||||||
if(ctl->dead && !ctl->cli_count)
|
|
||||||
{
|
|
||||||
free_ws_daemon(ctl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
get_wsockd_count(void)
|
|
||||||
{
|
|
||||||
return wsockd_count;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
wsockd_foreach_info(void (*func)(void *data, pid_t pid, int cli_count, enum wsockd_status status), void *data)
|
|
||||||
{
|
|
||||||
rb_dlink_node *ptr, *next;
|
|
||||||
ws_ctl_t *ctl;
|
|
||||||
RB_DLINK_FOREACH_SAFE(ptr, next, wsock_daemons.head)
|
|
||||||
{
|
|
||||||
ctl = (ws_ctl_t *)ptr->data;
|
|
||||||
func(data, ctl->pid, ctl->cli_count,
|
|
||||||
ctl->dead ? WSOCKD_DEAD :
|
|
||||||
(ctl->shutdown ? WSOCKD_SHUTDOWN : WSOCKD_ACTIVE));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
init_wsockd(void)
|
|
||||||
{
|
|
||||||
rb_event_addish("cleanup_dead_ws", cleanup_dead_ws, NULL, 60);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
Loading…
Reference in a new issue