From cc9afd6b1e03cf849122d10ba661f0cbec4d4c57 Mon Sep 17 00:00:00 2001 From: Arnaud Cornet Date: Sun, 25 Nov 2007 14:50:22 +0100 Subject: [PATCH] Support live addition and removal of connection. --- src/bip.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/bip.h | 3 +- src/irc.c | 15 ++++----- 3 files changed, 99 insertions(+), 10 deletions(-) diff --git a/src/bip.c b/src/bip.c index c84a1a8..02150b9 100644 --- a/src/bip.c +++ b/src/bip.c @@ -355,6 +355,74 @@ static int add_network(bip_t *bip, list_t *data) return 1; } +void adm_bip_delconn(bip_t *bip, struct link_client *ic, char *conn_name) +{ + struct user *user = LINK(ic)->user; + struct link *l; + + if (!hash_get(&user->connections, conn_name)) { + adm_reply(ic, "cannot find this connection"); + return; + } + + l = hash_get(&user->connections, conn_name); + link_kill(bip, l); + adm_reply(ic, "deleted"); +} + +void adm_bip_addconn(bip_t *bip, struct link_client *ic, char *conn_name, + char *network_name) +{ + struct user *user = LINK(ic)->user; + struct network *network; + + /* check name uniqueness */ + if (hash_get(&user->connections, conn_name)) { + adm_reply(ic, "connection name already exists for this user."); + return; + } + + /* check we know about this network */ + network = hash_get(&bip->networks, network_name); + if (!network) { + adm_reply(ic, "no such network name"); + return; + } + + struct link *l; + l = irc_link_new(); + l->name = strdup(conn_name); + hash_insert(&user->connections, conn_name, l); + list_add_last(&bip->link_list, l); + l->user = user; + l->network = network; + l->log = log_new(user, conn_name); +#ifdef HAVE_LIBSSL + l->ssl_check_mode = user->ssl_check_mode; + l->untrusted_certs = sk_X509_new_null(); +#endif + + +#define SCOPY(member) l->member = (LINK(ic)->member ? strdup(LINK(ic)->member) : NULL) +#define ICOPY(member) l->member = LINK(ic)->member + + SCOPY(connect_nick); + SCOPY(username); + SCOPY(realname); + /* we don't copy server password */ + SCOPY(vhost); + ICOPY(follow_nick); + ICOPY(ignore_first_nick); + SCOPY(away_nick); + SCOPY(no_client_away_msg); + /* we don't copy on_connect_send */ +#ifdef HAVE_LIBSSL + ICOPY(ssl_check_mode); +#endif +#undef SCOPY +#undef ICOPY +} + static int add_connection(bip_t *bip, struct user *user, list_t *data) { struct tuple *t, *t2; @@ -725,6 +793,7 @@ void clear_marks(bip_t *bip) void user_kill(bip_t *bip, struct user *user) { + (void)bip; if (!hash_is_empty(&user->connections)) fatal("user_kill, user still has connections"); free(user->name); @@ -1745,7 +1814,8 @@ void adm_bip_help(struct link_client *ic, int admin) adm_reply(ic, "/BIP AWAY_NICK # clear away nick"); } -int adm_bip(struct link_client *ic, struct line *line, unsigned int privmsg) +int adm_bip(bip_t *bip, struct link_client *ic, struct line *line, + unsigned int privmsg) { int admin = LINK(ic)->user->admin; @@ -1850,7 +1920,8 @@ int adm_bip(struct link_client *ic, struct line *line, unsigned int privmsg) if (line->elemc == privmsg + 2) { adm_on_connect_send(ic, NULL); } else if (line->elemc == privmsg + 3) { - // TODO: on connect send should not be limited to one word + // TODO: on connect send should not be limited to one + // word adm_on_connect_send(ic, line->elemv[privmsg + 2]); } else { adm_reply(ic, "/BIP ON_CONNECT_SEND needs zero or one " @@ -1865,6 +1936,22 @@ int adm_bip(struct link_client *ic, struct line *line, unsigned int privmsg) adm_reply(ic, "/BIP AWAY_NICK needs zero or one " "argument"); } + } else if (admin && + strcasecmp(line->elemv[privmsg + 1], "ADD_CONN") == 0) { + if (line->elemc != privmsg + 4) { + adm_reply(ic, "/BIP ADD_CONN " + ""); + } else { + adm_bip_addconn(bip, ic, line->elemv[privmsg + 2], + line->elemv[privmsg + 3]); + } + } else if (admin && + strcasecmp(line->elemv[privmsg + 1], "DEL_CONN") == 0) { + if (line->elemc != privmsg + 3) { + adm_reply(ic, "/BIP DEL_CONN "); + } else { + adm_bip_delconn(bip, ic, line->elemv[privmsg + 2]); + } #ifdef HAVE_LIBSSL } else if (strcasecmp(line->elemv[privmsg + 1], "TRUST") == 0) { /* TODO : warn the user of results */ diff --git a/src/bip.h b/src/bip.h index 00b2666..21b65c4 100644 --- a/src/bip.h +++ b/src/bip.h @@ -17,7 +17,8 @@ #ifdef HAVE_LIBSSL int adm_trust(struct link_client *ic, struct line *line); #endif -int adm_bip(struct link_client *ic, struct line *line, unsigned int privmsg); +int adm_bip(bip_t *bip, struct link_client *ic, struct line *line, + unsigned int privmsg); int ssl_check_trust(struct link_client *ic); void adm_blreset(struct link_client *ic); diff --git a/src/irc.c b/src/irc.c index 285a995..1969a74 100644 --- a/src/irc.c +++ b/src/irc.c @@ -56,6 +56,7 @@ static void irc_copy_cli(struct link_client *src, struct link_client *dest, struct line *line); static void irc_cli_make_join(struct link_client *ic); static void server_setup_reconnect_timer(struct link *link); +int irc_cli_bip(bip_t *bip, struct link_client *ic, struct line *line); #define LAGOUT_TIME 480 #define LAGCHECK_TIME (90) @@ -605,9 +606,9 @@ void unbind_from_link(struct link_client *ic) fatal("realloc"); } -int irc_cli_bip(struct link_client *ic, struct line *line) +int irc_cli_bip(bip_t *bip, struct link_client *ic, struct line *line) { - return adm_bip(ic, line, 0); + return adm_bip(bip, ic, line, 0); } #define PASS_SEP ':' @@ -857,13 +858,14 @@ static int irc_cli_quit(struct link_client *ic, struct line *line) return OK_CLOSE; } -static int irc_cli_privmsg(struct link_client *ic, struct line *line) +static int irc_cli_privmsg(bip_t *bip, struct link_client *ic, + struct line *line) { if (line->elemc >= 3) log_cli_privmsg(LINK(ic)->log, LINK(ic)->l_server->nick, line->elemv[1], line->elemv[2]); if (strcmp(line->elemv[1], "-bip") == 0) - return adm_bip(ic, line, 1); + return adm_bip(bip, ic, line, 1); if (LINK(ic)->user->blreset_on_talk) log_reinit_all(LINK(ic)->log); @@ -1052,7 +1054,6 @@ static int irc_dispatch_trust_client(struct link_client *ic, struct line *line) } #endif -int irc_cli_bip(struct link_client *ic, struct line *line); static int irc_dispatch_client(bip_t *bip, struct link_client *ic, struct line *line) { @@ -1071,7 +1072,7 @@ static int irc_dispatch_client(bip_t *bip, struct link_client *ic, "before sending commands\r\n"); r = OK_FORGET; } else if (strcasecmp(line->elemv[0], "BIP") == 0) { - r = irc_cli_bip(ic, line); + r = irc_cli_bip(bip, ic, line); } else if (strcmp(line->elemv[0], "JOIN") == 0) { r = irc_cli_join(ic, line); } else if (strcmp(line->elemv[0], "PART") == 0) { @@ -1081,7 +1082,7 @@ static int irc_dispatch_client(bip_t *bip, struct link_client *ic, } else if (strcmp(line->elemv[0], "QUIT") == 0) { r = irc_cli_quit(ic, line); } else if (strcmp(line->elemv[0], "PRIVMSG") == 0) { - r = irc_cli_privmsg(ic, line); + r = irc_cli_privmsg(bip, ic, line); } else if (strcmp(line->elemv[0], "NOTICE") == 0) { r = irc_cli_notice(ic, line); } else if (strcmp(line->elemv[0], "WHO") == 0) {