2
* $Id: bip.c,v 1.39 2005/04/21 06:58:50 nohar Exp $
4
* This file is part of the bip project
5
* Copyright (C) 2004 2005 Arnaud Cornet and Loïc Gomez
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License as published by
9
* the Free Software Foundation; either version 2 of the License, or
10
* (at your option) any later version.
11
* See the file "COPYING" for the exact licensing terms.
22
#include <sys/resource.h>
23
#include <sys/types.h>
38
char *conf_log_format;
41
unsigned short conf_port;
44
char *conf_ssl_certfile;
50
/* log options, for sure the trickiest :) */
51
int conf_log = DEFAULT_LOG;
52
int conf_log_system = DEFAULT_LOG_SYSTEM;
53
int conf_log_sync_interval = DEFAULT_LOG_SYNC_INTERVAL;
55
list_t *parse_conf(FILE *file, int *err);
56
void conf_die(bip_t *bip, char *fmt, ...);
57
static char *get_tuple_pvalue(list_t *tuple_l, int lex);
58
void bip_notify(struct link_client *ic, char *fmt, ...);
59
void adm_list_connections(struct link_client *ic, struct bipuser *bu);
60
void free_conf(list_t *l);
63
#define OIDENTD_FILENAME ".oidentd.conf"
66
static void hash_binary(char *hex, unsigned char **password, unsigned int *seed)
72
if (strlen(hex) != 40)
73
fatal("Incorrect password format %s\n", hex);
76
for (i = 0; i < 20; i++) {
77
sscanf(hex + 2 * i, "%02x", &buf);
82
sscanf(hex, "%02x", &buf);
84
sscanf(hex + 2, "%02x", &buf);
86
sscanf(hex + 2 * 2, "%02x", &buf);
88
sscanf(hex + 2 * 3, "%02x", &buf);
94
static int add_server(bip_t *bip, struct server *s, list_t *data)
98
s->port = 6667; /* default port */
100
while ((t = list_remove_first(data))) {
103
MOVE_STRING(s->host, t->pdata);
109
fatal("Config error in server block (%d)", t->type);
111
if (t->tuple_type == TUPLE_STR && t->pdata)
117
conf_die(bip, "Server conf: host not set");
125
extern list_t *root_list;
128
void conf_die(bip_t *bip, char *fmt, ...)
133
char *error = bip_malloc(size);
137
n = vsnprintf(error, size, fmt, ap);
139
if (n > -1 && n < size) {
140
list_add_last(&bip->errors, error);
147
error = bip_realloc(error, size);
150
_mylog(LOG_ERROR, fmt, ap);
154
FILE *conf_global_log_file;
156
static pid_t daemonize(void)
160
fatal("Fork failed");
169
fatal("setsid() failed");
173
fatal("Fork failed");
184
/* This better be the very last action since fatal makes use of
185
* conf_global_log_file */
189
/* RACE CONDITION! */
190
int do_pid_stuff(void)
199
f = fopen(conf_pid_file, "r");
202
if (gethostname(hname, 1023) == -1)
203
fatal("%s %s", "gethostname", strerror(errno));
204
snprintf(longpath, 1023, "%s.%s.%ld", conf_pid_file, hname,
205
(long unsigned int)getpid());
206
if ((fd = open(longpath, O_CREAT|O_WRONLY, S_IWUSR|S_IRUSR)) == -1)
207
fatal("Cannot write to PID file (%s) %s", longpath,
209
if (link(longpath, conf_pid_file) == -1) {
211
if (stat(longpath, &buf) == -1) {
212
if (buf.st_nlink != 2) {
213
f = fopen(conf_pid_file, "r");
227
int c = fscanf(f, "%ld", &p);
230
if (c != 1 || p == 0) {
231
mylog(LOG_INFO, "pid file found but invalid "
232
"data inside. Continuing...\n");
233
if (unlink(conf_pid_file)) {
234
fatal("Cannot delete pid file '%s', "
235
"check permissions.\n",
242
int kr = kill(pid, 0);
243
if (kr == -1 && (errno == ESRCH || errno == EPERM)) {
244
/* that's not bip! */
245
if (unlink(conf_pid_file)) {
246
fatal("Cannot delete pid file '%s', check "
253
mylog(LOG_INFO, "pid file found (pid %ld).", pid);
255
"Another instance of bip is certainly runing.");
256
mylog(LOG_FATAL, "If you are sure this is not the case remove"
257
" %s.", conf_pid_file);
263
#define S_CONF "bip.conf"
265
static void usage(char *name)
268
"Usage: %s [-f config_file] [-h] [-n]\n"
269
" -f config_file: Use config_file as the configuration file\n"
270
" If no config file is given %s will try to open ~/.bip/" S_CONF "\n"
271
" -n: Don't daemonize, log in stderr\n"
272
" -v: Print version and exit\n"
273
" -h: This help\n", name, name);
277
static void version()
280
"Bip IRC Proxy - %s\n"
281
"Copyright © Arnaud Cornet and Loïc Gomez (2004 - 2008)\n"
282
"Distributed under the GNU Public License Version 2\n", BIP_VERSION);
287
void reload_config(int i)
291
_bip->reloading_client = NULL;
294
void rlimit_cpu_reached(int i)
297
mylog(LOG_WARN, "This process has reached the CPU time usage limit. "
298
"It means bip will be killed by the Operating System soon.");
301
void rlimit_bigfile_reached(int i)
304
mylog(LOG_WARN, "A file has reached the max size this process is "
305
"allowed to create. The file will not be written correctly, "
306
"an error message should follow. This is not fatal.");
312
for (list_it_init(&_bip->link_list, &it); list_it_item(&it);
314
struct link *l = list_it_item(&it);
315
struct link_server *ls = l->l_server;
316
if (ls && l->s_state == IRCS_CONNECTED) {
317
write_line_fast(CONN(ls), "QUIT :Coyote finally "
321
unlink(conf_pid_file);
325
static int add_network(bip_t *bip, list_t *data)
332
char *name = get_tuple_pvalue(data, LEX_NAME);
335
conf_die(bip, "Network with no name");
338
n = hash_get(&bip->networks, name);
340
for (i = 0; i < n->serverc; i++)
341
free(n->serverv[i].host);
346
n = bip_calloc(sizeof(struct network), 1);
347
hash_insert(&bip->networks, name, n);
350
while ((t = list_remove_first(data))) {
353
MOVE_STRING(n->name, t->pdata);
361
n->serverv = bip_realloc(n->serverv, (n->serverc + 1)
362
* sizeof(struct server));
364
memset(&n->serverv[n->serverc - 1], 0,
365
sizeof(struct server));
366
r = add_server(bip, &n->serverv[n->serverc - 1],
376
conf_die(bip, "unknown keyword in network statement");
380
if (t->tuple_type == TUPLE_STR && t->pdata)
387
void adm_bip_delconn(bip_t *bip, struct link_client *ic, const char *conn_name)
389
struct bipuser *user = LINK(ic)->user;
392
if (!(l = hash_get(&user->connections, conn_name))) {
393
bip_notify(ic, "cannot find this connection");
397
bip_notify(ic, "deleting");
401
void adm_bip_addconn(bip_t *bip, struct link_client *ic, const char *conn_name,
402
const char *network_name)
404
struct bipuser *user = LINK(ic)->user;
405
struct network *network;
407
/* check name uniqueness */
408
if (hash_get(&user->connections, conn_name)) {
409
bip_notify(ic, "connection name already exists for this user.");
413
/* check we know about this network */
414
network = hash_get(&bip->networks, network_name);
416
bip_notify(ic, "no such network name");
422
l->name = bip_strdup(conn_name);
423
hash_insert(&user->connections, conn_name, l);
424
list_add_last(&bip->link_list, l);
426
l->network = network;
427
l->log = log_new(user, conn_name);
429
l->ssl_check_mode = user->ssl_check_mode;
430
l->untrusted_certs = sk_X509_new_null();
434
#define SCOPY(member) l->member = (LINK(ic)->member ? bip_strdup(LINK(ic)->member) : NULL)
435
#define ICOPY(member) l->member = LINK(ic)->member
440
/* we don't copy server password */
443
ICOPY(ignore_first_nick);
445
SCOPY(no_client_away_msg);
446
/* we don't copy on_connect_send */
448
ICOPY(ssl_check_mode);
452
bip_notify(ic, "connection added, you should soon be able to connect");
455
static int add_connection(bip_t *bip, struct bipuser *user, list_t *data)
457
struct tuple *t, *t2;
459
struct chan_info *ci;
460
char *name = get_tuple_pvalue(data, LEX_NAME);
463
conf_die(bip, "Connection with no name");
466
l = hash_get(&user->connections, name);
469
hash_insert(&user->connections, name, l);
470
list_add_last(&bip->link_list, l);
472
l->log = log_new(user, name);
474
l->ssl_check_mode = user->ssl_check_mode;
475
l->untrusted_certs = sk_X509_new_null();
479
log_reset_all(l->log);
482
while ((t = list_remove_first(data))) {
485
MOVE_STRING(l->name, t->pdata);
488
l->network = hash_get(&bip->networks, t->pdata);
490
conf_die(bip, "Undefined network %s.\n",
496
if (!is_valid_nick(t->pdata)) {
497
conf_die(bip, "Invalid nickname %s.", t->pdata);
500
MOVE_STRING(l->connect_nick, t->pdata);
503
MOVE_STRING(l->username, t->pdata);
506
MOVE_STRING(l->realname, t->pdata);
509
MOVE_STRING(l->s_password, t->pdata);
512
MOVE_STRING(l->vhost, t->pdata);
515
name = get_tuple_pvalue(t->pdata, LEX_NAME);
517
conf_die(bip, "Channel with no name");
521
ci = hash_get(&l->chan_infos, name);
523
ci = chan_info_new();
524
hash_insert(&l->chan_infos, name, ci);
525
/* FIXME: this order is not reloaded */
526
list_add_last(&l->chan_infos_order, ci);
530
while ((t2 = list_remove_first(t->pdata))) {
533
MOVE_STRING(ci->name, t2->pdata);
536
MOVE_STRING(ci->key, t2->pdata);
539
ci->backlog = t2->ndata;
542
if (t2->tuple_type == TUPLE_STR && t2->pdata)
548
case LEX_AUTOJOIN_ON_KICK:
549
l->autojoin_on_kick = t->ndata;
551
case LEX_FOLLOW_NICK:
552
l->follow_nick = t->ndata;
554
case LEX_IGN_FIRST_NICK:
555
l->ignore_first_nick = t->ndata;
557
case LEX_IGNORE_CAPAB:
558
l->ignore_server_capab = t->ndata;
561
MOVE_STRING(l->away_nick, t->pdata);
563
case LEX_NO_CLIENT_AWAY_MSG:
564
MOVE_STRING(l->no_client_away_msg, t->pdata);
566
case LEX_ON_CONNECT_SEND:
567
list_add_last(&l->on_connect_send, t->pdata);
571
l->log->log_to_file = t->ndata;
574
case LEX_SSL_CHECK_MODE:
575
if (strcmp(t->pdata, "basic") == 0)
576
l->ssl_check_mode = SSL_CHECK_BASIC;
577
if (strcmp(t->pdata, "ca") == 0)
578
l->ssl_check_mode = SSL_CHECK_CA;
579
if (strcmp(t->pdata, "none") == 0)
580
l->ssl_check_mode = SSL_CHECK_NONE;
583
case LEX_SSL_CHECK_MODE:
584
mylog(LOG_WARN, "Found SSL option whereas bip is "
585
"not built with SSL support.");
589
conf_die(bip, "Unknown keyword in connection "
593
if (t->tuple_type == TUPLE_STR && t->pdata)
597
/* checks that can only be here, or must */
599
conf_die(bip, "Missing network in connection block");
602
if (!l->connect_nick) {
603
if (!user->default_nick) {
604
conf_die(bip, "No nick set and no default nick.");
607
l->connect_nick = bip_strdup(user->default_nick);
610
if (!user->default_username) {
611
conf_die(bip, "No username set and no default "
615
l->username = bip_strdup(user->default_username);
618
if (!user->default_realname) {
619
conf_die(bip, "No realname set and no default "
623
l->realname = bip_strdup(user->default_realname);
630
static char *get_tuple_pvalue(list_t *tuple_l, int lex)
635
for (list_it_init(tuple_l, &it); (t = list_it_item(&it));
643
static int get_tuple_nvalue(list_t *tuple_l, int lex)
648
for (list_it_init(tuple_l, &it); (t = list_it_item(&it));
656
struct historical_directives {
661
int backlog_no_timestamp;
665
static int add_user(bip_t *bip, list_t *data, struct historical_directives *hds)
670
char *name = get_tuple_pvalue(data, LEX_NAME);
671
list_t connection_list, *cl;
673
list_init(&connection_list, NULL);
676
conf_die(bip, "User with no name");
679
u = hash_get(&bip->users, name);
681
u = bip_calloc(sizeof(struct bipuser), 1);
682
hash_insert(&bip->users, name, u);
683
hash_init(&u->connections, HASH_NOCASE);
685
u->backlog = DEFAULT_BACKLOG;
686
u->always_backlog = DEFAULT_ALWAYS_BACKLOG;
687
u->bl_msg_only = DEFAULT_BL_MSG_ONLY;
688
u->backlog_lines = DEFAULT_BACKLOG_LINES;
689
u->backlog_no_timestamp = DEFAULT_BACKLOG_NO_TIMESTAMP;
690
u->blreset_on_talk = DEFAULT_BLRESET_ON_TALK;
691
u->blreset_connection = DEFAULT_BLRESET_CONNECTION;
692
u->bip_use_notice = DEFAULT_BIP_USE_NOTICE;
696
FREE(u->default_nick);
697
FREE(u->default_username);
698
FREE(u->default_realname);
700
FREE(u->ssl_check_store);
701
FREE(u->ssl_client_certfile);
705
u->backlog = hds->backlog;
706
u->always_backlog = hds->always_backlog;
707
u->bl_msg_only = hds->bl_msg_only;
708
u->backlog_lines = hds->backlog_lines;
709
u->backlog_no_timestamp = hds->backlog_no_timestamp;
710
u->blreset_on_talk = hds->blreset_on_talk;
712
while ((t = list_remove_first(data))) {
715
MOVE_STRING(u->name, t->pdata);
721
hash_binary(t->pdata, &u->password, &u->seed);
725
case LEX_DEFAULT_NICK:
726
MOVE_STRING(u->default_nick, t->pdata);
728
case LEX_DEFAULT_USER:
729
MOVE_STRING(u->default_username, t->pdata);
731
case LEX_DEFAULT_REALNAME:
732
MOVE_STRING(u->default_realname, t->pdata);
734
case LEX_ALWAYS_BACKLOG:
735
u->always_backlog = t->ndata;
738
u->backlog = t->ndata;
740
case LEX_BL_MSG_ONLY:
741
u->bl_msg_only = t->ndata;
743
case LEX_BACKLOG_LINES:
744
u->backlog_lines = t->ndata;
746
case LEX_BACKLOG_NO_TIMESTAMP:
747
u->backlog_no_timestamp = t->ndata;
749
case LEX_BLRESET_ON_TALK:
750
u->blreset_on_talk = t->ndata;
752
case LEX_BLRESET_CONNECTION:
753
u->blreset_connection = t->ndata;
755
case LEX_BIP_USE_NOTICE:
756
u->bip_use_notice = t->ndata;
759
list_add_last(&connection_list, t->pdata);
763
case LEX_SSL_CHECK_MODE:
764
if (!strcmp(t->pdata, "basic"))
765
u->ssl_check_mode = SSL_CHECK_BASIC;
766
if (!strcmp(t->pdata, "ca"))
767
u->ssl_check_mode = SSL_CHECK_CA;
768
if (!strcmp(t->pdata, "none"))
769
u->ssl_check_mode = SSL_CHECK_NONE;
773
case LEX_SSL_CHECK_STORE:
774
MOVE_STRING(u->ssl_check_store, t->pdata);
776
case LEX_SSL_CLIENT_CERTFILE:
777
MOVE_STRING(u->ssl_client_certfile, t->pdata);
780
case LEX_SSL_CLIENT_CERTFILE:
781
case LEX_SSL_CHECK_MODE:
782
case LEX_SSL_CHECK_STORE:
783
mylog(LOG_WARN, "Found SSL option whereas bip is "
784
"not built with SSL support.");
788
conf_die(bip, "Uknown keyword in user statement");
791
if (t->tuple_type == TUPLE_STR && t->pdata)
796
conf_die(bip, "Missing password in user block");
800
while ((cl = list_remove_first(&connection_list))) {
801
r = add_connection(bip, u, cl);
811
static int validate_config(bip_t *bip)
813
/* nick username realname or default_{nick,username,realname} in user */
814
hash_iterator_t it, sit, cit;
815
struct bipuser *user;
817
struct chan_info *ci;
820
for (hash_it_init(&bip->users, &it); (user = hash_it_item(&it));
822
for (hash_it_init(&user->connections, &sit);
823
(link = hash_it_item(&sit));
824
hash_it_next(&sit)) {
825
if (!user->default_nick || !user->default_username ||
826
!user->default_realname) {
827
if ((!link->username &&
828
!user->default_username) ||
829
(!link->connect_nick &&
830
!user->default_nick) ||
832
!user->default_realname)) {
833
conf_die(bip, "user %s, "
834
"connection %s: you must defin"
835
"e nick, user and realname.",
836
user->name, link->name);
837
link_kill(bip, link);
843
for (hash_it_init(&link->chan_infos, &cit);
844
(ci = hash_it_item(&cit));
845
hash_it_next(&cit)) {
847
conf_die(bip, "user %s, "
849
"%s: channel must have"
850
"a name.", user->name,
858
if (user->backlog && !conf_log && user->backlog_lines == 0) {
859
conf_die(bip, "If conf_log = false, you must set "
861
"lines to a non-nul value for each user with"
862
"backlog = true. Faulty user is %s",
869
hash_it_init(&bip->users, &it);
871
if (hash_it_item(&it) && !strstr(conf_log_format, "%u"))
872
mylog(LOG_WARN, "log_format does not contain %%u, all users'"
873
" logs will be mixed !");
877
void clear_marks(bip_t *bip)
882
for (list_it_init(&bip->link_list, &lit); list_it_item(&lit);
884
((struct link *)list_it_item(&lit))->in_use = 0;
885
for (hash_it_init(&bip->users, &hit); hash_it_item(&hit);
887
((struct bipuser *)hash_it_item(&hit))->in_use = 0;
890
void user_kill(bip_t *bip, struct bipuser *user)
893
if (!hash_is_empty(&user->connections))
894
fatal("user_kill, user still has connections");
896
free(user->password);
897
MAYFREE(user->default_nick);
898
MAYFREE(user->default_username);
899
MAYFREE(user->default_realname);
902
MAYFREE(user->ssl_check_store);
903
MAYFREE(user->ssl_client_certfile);
908
void sweep(bip_t *bip)
913
for (list_it_init(&bip->link_list, &lit); list_it_item(&lit);
914
list_it_next(&lit)) {
915
struct link *l = ((struct link *)list_it_item(&lit));
917
mylog(LOG_INFO, "Administratively killing %s/%s",
918
l->user->name, l->name);
919
list_remove_if_exists(&bip->conn_list, l);
921
list_it_remove(&lit);
924
for (hash_it_init(&bip->users, &hit); hash_it_item(&hit);
925
hash_it_next(&hit)) {
926
struct bipuser *u = (struct bipuser *)hash_it_item(&hit);
928
hash_it_remove(&hit);
934
int fireup(bip_t *bip, FILE *conf)
939
struct historical_directives hds;
943
while ((l = list_remove_first(&bip->errors)))
945
parse_conf(conf, &err);
947
free_conf(root_list);
952
#define SET_HV(d, n) do {\
953
int __gtv = get_tuple_nvalue(root_list, LEX_##n);\
959
SET_HV(hds.always_backlog, ALWAYS_BACKLOG);
960
SET_HV(hds.backlog, BACKLOG);
961
SET_HV(hds.bl_msg_only, BL_MSG_ONLY);
962
SET_HV(hds.backlog_lines, BACKLOG_LINES);
963
SET_HV(hds.backlog_no_timestamp, BACKLOG_NO_TIMESTAMP);
964
SET_HV(hds.blreset_on_talk, BLRESET_ON_TALK);
967
while ((t = list_remove_first(root_list))) {
969
case LEX_LOG_SYNC_INTERVAL:
970
conf_log_sync_interval = t->ndata;
976
conf_log_system = t->ndata;
979
MOVE_STRING(conf_log_root, t->pdata);
982
MOVE_STRING(conf_log_format, t->pdata);
985
conf_log_level = t->ndata;
988
MOVE_STRING(conf_ip, t->pdata);
991
conf_port = t->ndata;
998
MOVE_STRING(conf_ssl_certfile, t->pdata);
1003
mylog(LOG_WARN, "Found SSL option whereas bip is "
1004
"not built with SSL support.");
1008
MOVE_STRING(conf_pid_file, t->pdata);
1010
case LEX_ALWAYS_BACKLOG:
1011
hds.always_backlog = t->ndata;
1014
hds.backlog = t->ndata;
1016
case LEX_BL_MSG_ONLY:
1017
hds.bl_msg_only = t->ndata;
1019
case LEX_BACKLOG_LINES:
1020
hds.backlog_lines = t->ndata;
1022
case LEX_BACKLOG_NO_TIMESTAMP:
1023
hds.backlog_no_timestamp = t->ndata;
1025
case LEX_BLRESET_ON_TALK:
1026
hds.blreset_on_talk = t->ndata;
1029
r = add_network(bip, t->pdata);
1030
list_free(t->pdata);
1032
goto out_conf_error;
1035
r = add_user(bip, t->pdata, &hds);
1036
list_free(t->pdata);
1038
goto out_conf_error;
1041
conf_die(bip, "Config error in base config (%d)",
1043
goto out_conf_error;
1045
if (t->tuple_type == TUPLE_STR && t->pdata)
1052
if (validate_config(bip)) {
1059
free_conf(root_list);
1064
static void log_file_setup(void)
1068
if (conf_log_system && conf_daemonize) {
1069
if (conf_global_log_file && conf_global_log_file != stderr)
1070
fclose(conf_global_log_file);
1071
snprintf(buf, 4095, "%s/bip.log", conf_log_root);
1072
FILE *f = fopen(buf, "a");
1074
fatal("Can't open %s: %s", buf, strerror(errno));
1075
conf_global_log_file = f;
1077
conf_global_log_file = stderr;
1081
void check_rlimits()
1089
r = getrlimit(RLIMIT_AS, <);
1091
mylog(LOG_ERROR, "getrlimit(): failed with %s",
1094
if (lt.rlim_max != RLIM_INFINITY) {
1095
mylog(LOG_WARN, "virtual memory rlimit active, "
1096
"bip may be KILLED by the system");
1102
r = getrlimit(RLIMIT_CPU, <);
1104
mylog(LOG_ERROR, "getrlimit(): failed with %s",
1107
if (lt.rlim_max != RLIM_INFINITY) {
1108
mylog(LOG_WARN, "CPU rlimit active, bip may "
1109
"be OFTEN KILLED by the system");
1114
r = getrlimit(RLIMIT_FSIZE, <);
1116
mylog(LOG_ERROR, "getrlimit(): failed with %s",
1119
if (lt.rlim_max != RLIM_INFINITY) {
1120
mylog(LOG_WARN, "FSIZE rlimit active, bip will "
1121
"fail to create files of size greater than "
1122
"%d bytes.", (int)lt.rlim_max);
1127
r = getrlimit(RLIMIT_NOFILE, <);
1129
mylog(LOG_ERROR, "getrlimit(): failed with %s",
1132
if (lt.rlim_max != RLIM_INFINITY && lt.rlim_max < 256) {
1133
mylog(LOG_WARN, "opened files count rlimit "
1134
"active, bip will not be allowed to open more "
1135
"than %d files at a time", (int)lt.rlim_max);
1140
r = getrlimit(RLIMIT_STACK, <);
1142
mylog(LOG_ERROR, "getrlimit(): failed with %s",
1145
if (lt.rlim_max != RLIM_INFINITY) {
1146
mylog(LOG_WARN, "stack rlimit active, "
1147
"bip may be KILLED by the system");
1153
mylog(LOG_WARN, "You can check your limits with `ulimit -a'");
1156
int main(int argc, char **argv)
1159
char *confpath = NULL;
1168
conf_ip = bip_strdup("0.0.0.0");
1172
signal(SIGPIPE, SIG_IGN);
1173
signal(SIGHUP, reload_config);
1174
signal(SIGINT, bad_quit);
1175
signal(SIGQUIT, bad_quit);
1176
signal(SIGTERM, bad_quit);
1177
signal(SIGXFSZ, rlimit_bigfile_reached);
1178
signal(SIGXCPU, rlimit_cpu_reached);
1180
conf_log_root = NULL;
1181
conf_log_format = bip_strdup(DEFAULT_LOG_FORMAT);
1182
conf_log_level = DEFAULT_LOG_LEVEL;
1184
conf_global_log_file = stderr;
1185
conf_pid_file = NULL;
1187
conf_ssl_certfile = NULL;
1190
while ((ch = getopt(argc, argv, "hvnf:s:")) != -1) {
1193
confpath = bip_strdup(optarg);
1199
conf_biphome = bip_strdup(optarg);
1215
char *home = NULL; /* oidentd path searching ignores conf_biphome */
1216
home = getenv("HOME");
1218
conf_die(&bip, "no $HOME !, do you live in a trailer ?");
1222
bip.oidentdpath = bip_malloc(strlen(home) + 1 +
1223
strlen(OIDENTD_FILENAME) + 1);
1224
strcpy(bip.oidentdpath, home);
1225
strcat(bip.oidentdpath, "/");
1226
strcat(bip.oidentdpath, OIDENTD_FILENAME);
1230
if (!conf_biphome) {
1231
conf_biphome = bip_malloc(strlen(home) + strlen("/.bip") + 1);
1232
strcpy(conf_biphome, home);
1233
strcat(conf_biphome, "/.bip");
1237
confpath = bip_malloc(strlen(conf_biphome) + 1 +
1238
strlen(S_CONF) + 1);
1239
strcpy(confpath, conf_biphome);
1240
strcat(confpath, "/");
1241
strcat(confpath, S_CONF);
1243
conf = fopen(confpath, "r");
1245
fatal("config file not found");
1247
r = fireup(&bip, conf);
1250
fatal("Not starting: error in config file.");
1252
if (!conf_log_root) {
1254
conf_log_root = bip_malloc(strlen(conf_biphome) +
1256
strcpy(conf_log_root, conf_biphome);
1257
strcat(conf_log_root, ap);
1258
mylog(LOG_INFO, "Default log root: %s", conf_log_root);
1260
if (!conf_pid_file) {
1261
char *pid = "/bip.pid";
1262
conf_pid_file = bip_malloc(strlen(conf_biphome) +
1264
strcpy(conf_pid_file, conf_biphome);
1265
strcat(conf_pid_file, pid);
1266
mylog(LOG_INFO, "Default pid file: %s", conf_pid_file);
1274
if (!conf_ssl_certfile) {
1275
char *ap = "/bip.pem";
1276
conf_ssl_certfile = bip_malloc(strlen(conf_biphome) +
1278
strcpy(conf_ssl_certfile, conf_biphome);
1279
strcat(conf_ssl_certfile, ap);
1280
mylog(LOG_INFO, "Using default SSL certificate file: "
1281
"%s", conf_ssl_certfile);
1284
if ((fd = open(conf_ssl_certfile, O_RDONLY)) == -1)
1285
fatal("Unable to open PEM file %s for reading",
1290
e = stat(conf_ssl_certfile, &fs);
1292
mylog(LOG_WARN, "Unable to check PEM file, stat(%s): "
1293
"%s", conf_ssl_certfile, strerror(errno));
1294
else if ((fs.st_mode & S_IROTH) | (fs.st_mode & S_IWOTH))
1295
mylog(LOG_ERROR, "PEM file %s should not be world "
1296
"readable / writable. Please fix the modes.",
1301
check_dir(conf_log_root, 1);
1302
fd = do_pid_stuff();
1310
snprintf(buf, 29, "%ld\n", (long unsigned int)pid);
1311
write(fd, buf, strlen(buf));
1314
bip.listener = listen_new(conf_ip, conf_port, conf_css);
1316
fatal("Could not create listening socket");
1323
conf = fopen(confpath, "r");
1325
fatal("%s config file not found", confpath);
1329
/* re-open to allow logfile rotate */
1335
#define RET_STR_LEN 256
1336
#define LINE_SIZE_LIM 70
1337
void adm_print_connection(struct link_client *ic, struct link *lnk,
1340
hash_iterator_t lit;
1341
char buf[RET_STR_LEN + 1];
1347
bip_notify(ic, "* %s to %s as \"%s\" (%s!%s) :", lnk->name,
1349
(lnk->realname ? lnk->realname : bu->default_realname),
1350
(lnk->connect_nick ? lnk->connect_nick : bu->default_nick),
1351
(lnk->username ? lnk->username : bu->default_username));
1353
t_written = snprintf(buf, RET_STR_LEN, " Options:");
1354
if (t_written >= RET_STR_LEN)
1356
if (lnk->follow_nick) {
1357
t_written += snprintf(buf + t_written,
1358
RET_STR_LEN - t_written, " follow_nick");
1359
if (t_written >= RET_STR_LEN)
1362
if (lnk->ignore_first_nick) {
1363
t_written += snprintf(buf + t_written,
1364
RET_STR_LEN - t_written, " ignore_first_nick");
1365
if (t_written >= RET_STR_LEN)
1368
if (lnk->away_nick) {
1369
t_written += snprintf(buf + t_written,
1370
RET_STR_LEN - t_written, " away_nick=%s",
1372
if (t_written >= RET_STR_LEN)
1375
if (lnk->no_client_away_msg) {
1376
t_written += snprintf(buf + t_written,
1377
RET_STR_LEN - t_written, " no_client_away_msg=%s",
1378
lnk->no_client_away_msg);
1379
if (t_written >= RET_STR_LEN)
1383
t_written += snprintf(buf + t_written,
1384
RET_STR_LEN - t_written, " vhost=%s",
1386
if (t_written >= RET_STR_LEN)
1389
if (lnk->bind_port) {
1390
t_written += snprintf(buf + t_written,
1391
RET_STR_LEN - t_written, " bind_port=%u",
1393
if (t_written >= RET_STR_LEN)
1396
noroom: /* that means the line is larger that RET_STR_LEN. We're not likely to
1397
even read such a long line */
1398
buf[RET_STR_LEN] = 0;
1399
bip_notify(ic, "%s", buf);
1401
// TODO: on_connect_send
1403
// TODO : check channels struct
1404
t_written = snprintf(buf, RET_STR_LEN, " Channels (* with key, ` no backlog)");
1405
if (t_written >= RET_STR_LEN)
1407
for (hash_it_init(&lnk->chan_infos, &lit); hash_it_item(&lit);
1408
hash_it_next(&lit)) {
1409
struct chan_info *ch = hash_it_item(&lit);
1411
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written, " %s%s%s",
1412
ch->name, (ch->key ? "*" : ""),
1413
(ch->backlog ? "" : "`"));
1414
if (t_written > LINE_SIZE_LIM) {
1415
buf[RET_STR_LEN] = 0;
1416
bip_notify(ic, "%s", buf);
1421
buf[RET_STR_LEN] = 0;
1422
bip_notify(ic, "%s", buf);
1424
t_written = snprintf(buf, RET_STR_LEN, " Status: ");
1425
if (t_written >= RET_STR_LEN)
1427
switch (lnk->s_state) {
1429
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written,
1431
if (t_written >= RET_STR_LEN)
1434
case IRCS_CONNECTING:
1435
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written,
1436
"connecting... attempts: %d, last: %s",
1437
lnk->s_conn_attempt,
1438
hrtime(lnk->last_connection_attempt));
1439
if (t_written >= RET_STR_LEN)
1442
case IRCS_CONNECTED:
1443
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written,
1445
if (t_written >= RET_STR_LEN)
1448
case IRCS_WAS_CONNECTED:
1449
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written,
1450
"disconnected, attempts: %d, last: %s",
1451
lnk->s_conn_attempt,
1452
hrtime(lnk->last_connection_attempt));
1453
if (t_written >= RET_STR_LEN)
1456
case IRCS_RECONNECTING:
1457
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written,
1458
"reconnecting... attempts: %d, last: %s",
1459
lnk->s_conn_attempt,
1460
hrtime(lnk->last_connection_attempt));
1461
if (t_written >= RET_STR_LEN)
1464
case IRCS_TIMER_WAIT:
1465
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written,
1466
"waiting to reconnect, attempts: %d, last: %s",
1467
lnk->s_conn_attempt,
1468
hrtime(lnk->last_connection_attempt));
1469
if (t_written >= RET_STR_LEN)
1473
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written,
1475
if (t_written >= RET_STR_LEN)
1478
// s_conn_attempt recon_timer last_connection_attempt
1481
buf[RET_STR_LEN] = 0;
1482
bip_notify(ic, "%s", buf);
1485
void adm_list_all_links(struct link_client *ic)
1489
bip_notify(ic, "-- All links");
1490
for (list_it_init(&_bip->link_list, &it); list_it_item(&it);
1491
list_it_next(&it)) {
1492
struct link *l = list_it_item(&it);
1494
adm_print_connection(ic, l, NULL);
1496
bip_notify(ic, "-- End of All links");
1499
void adm_list_all_connections(struct link_client *ic)
1503
bip_notify(ic, "-- All connections");
1504
for (hash_it_init(&_bip->users, &it); hash_it_item(&it);
1505
hash_it_next(&it)) {
1506
struct bipuser *u = hash_it_item(&it);
1508
adm_list_connections(ic, u);
1510
bip_notify(ic, "-- End of All connections");
1513
#define STRORNULL(s) ((s) == NULL ? "unset" : (s))
1515
void adm_info_user(struct link_client *ic, const char *name)
1518
char buf[RET_STR_LEN + 1];
1521
bip_notify(ic, "-- User '%s' info", name);
1522
u = hash_get(&_bip->users, name);
1524
bip_notify(ic, "Unknown user");
1528
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written,
1529
"user: %s", u->name);
1530
if (t_written >= RET_STR_LEN)
1533
t_written += snprintf(buf + t_written, RET_STR_LEN - t_written,
1535
if (t_written >= RET_STR_LEN)
1540
buf[RET_STR_LEN] = 0;
1541
bip_notify(ic, "%s", buf);
1544
bip_notify(ic, "SSL check mode '%s', stored into '%s'",
1545
checkmode2text(u->ssl_check_mode),
1546
STRORNULL(u->ssl_check_store));
1547
if (u->ssl_client_certfile)
1548
bip_notify(ic, "SSL client certificate stored into '%s'",
1549
u->ssl_client_certfile);
1551
bip_notify(ic, "Defaults nick: %s, user: %s, realname: %s",
1552
STRORNULL(u->default_nick), STRORNULL(u->default_username),
1553
STRORNULL(u->default_realname));
1555
bip_notify(ic, "Backlog enabled, lines: %d, no timestamp: %s,"
1556
" messages only: %s", u->backlog_lines,
1557
bool2text(u->backlog_no_timestamp),
1558
bool2text(u->bl_msg_only));
1559
bip_notify(ic, "always backlog: %s, reset on talk: %s",
1560
bool2text(u->always_backlog),
1561
bool2text(u->blreset_on_talk));
1563
bip_notify(ic, "Backlog disabled");
1565
adm_list_connections(ic, u);
1566
bip_notify(ic, "-- End of User '%s' info", name);
1569
void adm_list_users(struct link_client *ic)
1572
hash_iterator_t lit;
1573
char buf[RET_STR_LEN + 1];
1578
bip_notify(ic, "-- User list");
1579
for (hash_it_init(&_bip->users, &it); hash_it_item(&it);
1580
hash_it_next(&it)) {
1581
struct bipuser *u = hash_it_item(&it);
1585
buf[RET_STR_LEN] = 0;
1586
t_written += snprintf(buf, RET_STR_LEN, "* %s%s:", u->name,
1587
(u->admin ? "(admin)": ""));
1588
if (t_written >= RET_STR_LEN)
1590
for (hash_it_init(&u->connections, &lit); hash_it_item(&lit);
1591
hash_it_next(&lit)) {
1592
struct link *lnk = hash_it_item(&lit);
1596
t_written += snprintf(buf + t_written,
1597
RET_STR_LEN - t_written, ",");
1598
if (t_written >= RET_STR_LEN)
1602
t_written += snprintf(buf + t_written,
1603
RET_STR_LEN - t_written,
1605
if (t_written >= RET_STR_LEN)
1607
if (t_written > LINE_SIZE_LIM) {
1608
buf[RET_STR_LEN] = 0;
1609
bip_notify(ic, "%s", buf);
1614
buf[RET_STR_LEN] = 0;
1615
bip_notify(ic, "%s", buf);
1617
bip_notify(ic, "-- End of User list");
1620
void adm_list_networks(struct link_client *ic)
1623
char buf[RET_STR_LEN + 1];
1628
bip_notify(ic, "-- Network list (* means SSL):");
1629
for (hash_it_init(&_bip->networks, &it); hash_it_item(&it);
1630
hash_it_next(&it)) {
1631
struct network *n = hash_it_item(&it);
1635
buf[RET_STR_LEN] = 0;
1638
t_written += snprintf(buf, RET_STR_LEN, "- %s*:",
1640
if (t_written >= RET_STR_LEN)
1644
t_written += snprintf(buf, RET_STR_LEN, "- %s:", n->name);
1645
if (t_written >= RET_STR_LEN)
1650
for (i = 0; i < n->serverc; i++) {
1651
struct server *serv = i+n->serverv;
1652
t_written += snprintf(buf + t_written, RET_STR_LEN
1653
- t_written, " %s:%d", serv->host,
1655
if (t_written >= RET_STR_LEN)
1657
if (t_written > LINE_SIZE_LIM) {
1658
buf[RET_STR_LEN] = 0;
1659
bip_notify(ic, "%s", buf);
1664
buf[RET_STR_LEN] = 0;
1665
bip_notify(ic, "%s", buf);
1667
bip_notify(ic, "-- End of Network list");
1670
void adm_list_connections(struct link_client *ic, struct bipuser *bu)
1677
bip_notify(ic, "-- Your connections:");
1678
bu = LINK(ic)->user;
1680
bip_notify(ic, "-- User %s's connections:", bu->name);
1683
for (hash_it_init(&bu->connections, &it); hash_it_item(&it);
1684
hash_it_next(&it)) {
1685
struct link *lnk= hash_it_item(&it);
1686
adm_print_connection(ic, lnk, bu);
1688
bip_notify(ic, "-- End of Connection list");
1692
int link_add_untrusted(struct link_server *ls, X509 *cert)
1696
/* Check whether the cert is already in the stack */
1697
for (i = 0; i < sk_X509_num(LINK(ls)->untrusted_certs); i++) {
1699
sk_X509_value(LINK(ls)->untrusted_certs, i)))
1703
return sk_X509_push(LINK(ls)->untrusted_certs, cert);
1706
int ssl_check_trust(struct link_client *ic)
1708
X509 *trustcert = NULL;
1711
unsigned char fp[EVP_MAX_MD_SIZE];
1712
char fpstr[EVP_MAX_MD_SIZE * 3 + 20];
1716
if(!LINK(ic)->untrusted_certs ||
1717
sk_X509_num(LINK(ic)->untrusted_certs) <= 0)
1720
trustcert = sk_X509_value(LINK(ic)->untrusted_certs, 0);
1721
strcpy(subject, "Subject: ");
1722
strcpy(issuer, "Issuer: ");
1723
strcpy(fpstr, "MD5 fingerprint: ");
1724
X509_NAME_oneline(X509_get_subject_name(trustcert), subject + 9, 256);
1725
X509_NAME_oneline(X509_get_issuer_name(trustcert), issuer + 9, 256);
1727
X509_digest(trustcert, EVP_md5(), fp, &fplen);
1728
for(i = 0; i < (int)fplen; i++)
1729
sprintf(fpstr + 17 + (i * 3), "%02X%c",
1730
fp[i], (i == (int)fplen - 1) ? '\0' : ':');
1732
WRITE_LINE2(CONN(ic), P_SERV, "NOTICE", "TrustEm",
1733
"This server SSL certificate was not "
1734
"accepted because it is not in your store "
1735
"of trusted certificates:");
1737
WRITE_LINE2(CONN(ic), P_SERV, "NOTICE", "TrustEm", subject);
1738
WRITE_LINE2(CONN(ic), P_SERV, "NOTICE", "TrustEm", issuer);
1739
WRITE_LINE2(CONN(ic), P_SERV, "NOTICE", "TrustEm", fpstr);
1741
WRITE_LINE2(CONN(ic), P_SERV, "NOTICE", "TrustEm",
1742
"WARNING: if you've already trusted a "
1743
"certificate for this server before, that "
1744
"probably means it has changed.");
1746
WRITE_LINE2(CONN(ic), P_SERV, "NOTICE", "TrustEm",
1747
"If so, YOU MAY BE SUBJECT OF A "
1748
"MAN-IN-THE-MIDDLE ATTACK! PLEASE DON'T TRUST "
1749
"THIS CERTIFICATE IF YOU'RE NOT SURE THIS IS "
1752
WRITE_LINE2(CONN(ic), P_SERV, "NOTICE", "TrustEm",
1753
"Type /QUOTE BIP TRUST OK to trust this "
1754
"certificate, /QUOTE BIP TRUST NO to discard it.");
1760
static int ssl_trust_next_cert(struct link_client *ic)
1765
static int ssl_discard_next_cert(struct link_client *ic)
1773
int adm_trust(struct link_client *ic, struct line *line)
1775
if (ic->allow_trust != 1) {
1776
mylog(LOG_ERROR, "User attempted TRUST command without "
1777
"being allowed to!");
1778
unbind_from_link(ic);
1782
if(!LINK(ic)->untrusted_certs ||
1783
sk_X509_num(LINK(ic)->untrusted_certs) <= 0) {
1784
/* shouldn't have been asked to /QUOTE BIP TRUST but well... */
1785
WRITE_LINE2(CONN(ic), P_SERV, "NOTICE", "TrustEm",
1786
"No untrusted certificates.");
1787
return ERR_PROTOCOL;
1790
if (irc_line_count(line) != 3)
1791
return ERR_PROTOCOL;
1793
if (irc_line_elem_case_equals(line, 2, "OK")) {
1794
/* OK, attempt to trust the cert! */
1795
BIO *bio = BIO_new_file(LINK(ic)->user->ssl_check_store, "a+");
1796
X509 *trustcert = sk_X509_shift(LINK(ic)->untrusted_certs);
1798
if(!bio || !trustcert ||
1799
PEM_write_bio_X509(bio, trustcert) <= 0)
1800
write_line_fast(CONN(ic), ":irc.bip.net NOTICE pouet "
1801
":==== Error while trusting test!\r\n");
1803
write_line_fast(CONN(ic), ":irc.bip.net NOTICE pouet "
1804
":==== Certificate now trusted.\r\n");
1807
X509_free(trustcert);
1808
} else if (irc_line_elem_case_equals(line, 2, "NO")) {
1809
/* NO, discard the cert! */
1810
write_line_fast(CONN(ic), ":irc.bip.net NOTICE pouet "
1811
":==== Certificate discarded.\r\n");
1813
X509_free(sk_X509_shift(LINK(ic)->untrusted_certs));
1815
return ERR_PROTOCOL;
1817
if (!ssl_check_trust(ic)) {
1818
write_line_fast(CONN(ic), ":irc.bip.net NOTICE pouet "
1819
":No more certificates waiting awaiting "
1820
"user trust, thanks!\r\n");
1821
write_line_fast(CONN(ic), ":irc.bip.net NOTICE pouet "
1822
":If the certificate is trusted, bip should "
1823
"be able to connect to the server on the "
1824
"next retry. Please wait a while and try "
1825
"connecting your client again.\r\n");
1827
LINK(ic)->recon_timer = 1; /* Speed up reconnection... */
1828
unbind_from_link(ic);
1835
void _bip_notify(struct link_client *ic, char *fmt, va_list ap)
1840
if (LINK(ic)->l_server)
1841
nick = LINK(ic)->l_server->nick;
1843
nick = LINK(ic)->prev_nick;
1845
vsnprintf(str, 4095, fmt, ap);
1847
WRITE_LINE2(CONN(ic), P_IRCMASK, (LINK(ic)->user->bip_use_notice ?
1848
"NOTICE" : "PRIVMSG"), nick, str);
1851
void bip_notify(struct link_client *ic, char *fmt, ...)
1856
_bip_notify(ic, fmt, ap);
1860
void adm_blreset(struct link_client *ic)
1862
log_reset_all(LINK(ic)->log);
1863
bip_notify(ic, "backlog resetted for this network.");
1866
void adm_blreset_store(struct link_client *ic, const char *store)
1868
log_reset_store(LINK(ic)->log, store);
1869
bip_notify(ic, "backlog resetted for %s.", store);
1872
void adm_follow_nick(struct link_client *ic, const char *val)
1874
struct link *link = LINK(ic);
1875
if (strcasecmp(val, "TRUE") == 0) {
1876
link->follow_nick = 1;
1877
bip_notify(ic, "follow_nick is now true.");
1879
link->follow_nick = 0;
1880
bip_notify(ic, "follow_nick is now false.");
1884
void adm_ignore_first_nick(struct link_client *ic, const char *val)
1886
struct link *link = LINK(ic);
1887
if (strcasecmp(val, "TRUE") == 0) {
1888
link->ignore_first_nick = 1;
1889
bip_notify(ic, "ignore_first_nick is now true.");
1891
link->ignore_first_nick = 0;
1892
bip_notify(ic, "ignore_first_nick is now false.");
1896
void set_on_connect_send(struct link_client *ic, char *val)
1898
struct link *link = LINK(ic);
1902
list_add_last(&link->on_connect_send, bip_strdup(val));
1903
bip_notify(ic, "added to on_connect_send.");
1905
s = list_remove_last(&link->on_connect_send);
1908
bip_notify(ic, "last on_connect_send string deleted.");
1912
#define ON_CONNECT_MAX_STRSIZE 1024
1913
void adm_on_connect_send(struct link_client *ic, struct line *line,
1914
unsigned int privmsg)
1916
char buf[ON_CONNECT_MAX_STRSIZE];
1921
set_on_connect_send(ic, NULL);
1925
if (irc_line_includes(line, 2))
1928
for (i = privmsg + 2; i < irc_line_count(line); i++) {
1930
t_written += snprintf(buf,
1931
ON_CONNECT_MAX_STRSIZE - 1 - t_written,
1932
" %s", irc_line_elem(line, i));
1933
if (t_written >= ON_CONNECT_MAX_STRSIZE)
1936
t_written = snprintf(buf, ON_CONNECT_MAX_STRSIZE - 1,
1937
"%s", irc_line_elem(line, i));
1938
if (t_written >= ON_CONNECT_MAX_STRSIZE)
1943
buf[ON_CONNECT_MAX_STRSIZE - 1] = 0;
1944
set_on_connect_send(ic, buf);
1947
bip_notify(ic, "on connect send string too big, truncated");
1951
void adm_away_nick(struct link_client *ic, const char *val)
1953
struct link *link = LINK(ic);
1954
if (link->away_nick) {
1955
free(link->away_nick);
1956
link->away_nick = NULL;
1959
link->away_nick = bip_strdup(val);
1960
bip_notify(ic, "away_nick set.");
1962
bip_notify(ic, "away_nick cleared.");
1966
void adm_bip_help(struct link_client *ic, int admin, const char *subhelp)
1968
if (subhelp == NULL) {
1970
bip_notify(ic, "/BIP RELOAD # Re-read bip "
1971
"configuration and apply changes.");
1972
bip_notify(ic, "/BIP INFO user <username> "
1973
"# show a user's configuration");
1974
bip_notify(ic, "/BIP LIST networks|users|connections|"
1975
"all_links|all_connections");
1976
bip_notify(ic, "/BIP ADD_CONN <connection name> "
1978
bip_notify(ic, "/BIP DEL_CONN <connection name>");
1980
bip_notify(ic, "/BIP LIST networks|connections");
1982
bip_notify(ic, "/BIP JUMP # jump to next server (in same "
1984
bip_notify(ic, "/BIP BLRESET [channel|query]# reset backlog "
1985
"(this connection only). Add -q flag and the "
1986
"operation is quiet. You can specify a channel "
1987
"or a nick to reset only this channel/query.");
1988
bip_notify(ic, "/BIP HELP [subhelp] # show this help...");
1989
bip_notify(ic, "## Temporary changes for this connection:");
1990
bip_notify(ic, "/BIP FOLLOW_NICK|IGNORE_FIRST_NICK TRUE|FALSE");
1991
bip_notify(ic, "/BIP ON_CONNECT_SEND <str> # Adds a string to "
1993
bip_notify(ic, "/BIP ON_CONNECT_SEND # Clears on_connect_send");
1994
bip_notify(ic, "/BIP AWAY_NICK <nick> # Set away nick");
1995
bip_notify(ic, "/BIP AWAY_NICK # clear away nick");
1996
bip_notify(ic, "/BIP BACKLOG [n] # backlog text of the n last "
1998
} else if (admin && strcasecmp(subhelp, "RELOAD") == 0) {
1999
bip_notify(ic, "/BIP RELOAD (admin only) :");
2000
bip_notify(ic, " Reloads bip configuration file and apply "
2002
bip_notify(ic, " Please note that changes to 'user' or "
2003
"'realname' will not be applied without a JUMP.");
2004
} else if (admin && strcasecmp(subhelp, "INFO") == 0) {
2005
bip_notify(ic, "/BIP INFO USER <user> (admin only) :");
2006
bip_notify(ic, " Show <user>'s current configuration.");
2007
bip_notify(ic, " That means it may be different from the "
2008
"configuration stored in bip.conf");
2009
} else if (admin && strcasecmp(subhelp, "ADD_CONN") == 0) {
2010
bip_notify(ic, "/BIP ADD_CONN <connection name> <network> "
2012
bip_notify(ic, " Add a connection named <connection name> to "
2013
"the network <network> to your connection list");
2014
bip_notify(ic, " <network> should already exist in bip's "
2016
} else if (admin && strcasecmp(subhelp, "DEL_CONN") == 0) {
2017
bip_notify(ic, "/BIP DEL_CONN <connection name> (admin only) "
2019
bip_notify(ic, " Remove the connection named <connection "
2020
"name> from your connection list.");
2021
bip_notify(ic, " Removing a connection will cause "
2022
"its disconnection.");
2023
} else if (strcasecmp(subhelp, "JUMP") == 0) {
2024
bip_notify(ic, "/BIP JUMP :");
2025
bip_notify(ic, " Jump to next server in current network.");
2026
} else if (strcasecmp(subhelp, "BLRESET") == 0) {
2027
bip_notify(ic, "/BIP BLRESET :");
2028
bip_notify(ic, " Reset backlog on this network.");
2029
} else if (strcasecmp(subhelp, "FOLLOW_NICK") == 0) {
2030
bip_notify(ic, "/BIP FOLLOW_NICK TRUE|FALSE :");
2031
bip_notify(ic, " Change the value of the follow_nick option "
2032
"for this connection.");
2033
bip_notify(ic, " If set to true, when you change nick, "
2034
"BIP stores the new nickname as the new default "
2036
bip_notify(ic, " Thus, if you are disconnected from the "
2037
"server, BIP will restore the correct nickname.");
2038
} else if (strcasecmp(subhelp, "IGNORE_FIRST_NICK") == 0) {
2039
bip_notify(ic, "/BIP IGNORE_FIRST_NICK TRUE|FALSE :");
2040
bip_notify(ic, " Change the value of the ignore_first_nick "
2041
"option for this connection.");
2042
bip_notify(ic, " If set to TRUE, BIP will ignore the nickname"
2043
"sent by the client upon connect.");
2044
bip_notify(ic, " Further nickname changes will be processed "
2046
} else if (strcasecmp(subhelp, "ON_CONNECT_SEND") == 0) {
2047
bip_notify(ic, "/BIP ON_CONNECT_SEND [some text] :");
2048
bip_notify(ic, " BIP will send the text as is to the server "
2049
"upon connection.");
2050
bip_notify(ic, " You can call this command more than once.");
2051
bip_notify(ic, " If [some text] is empty, this command will "
2052
"remove any on_connect_send defined for this connection.");
2053
} else if (strcasecmp(subhelp, "AWAY_NICK") == 0) {
2054
bip_notify(ic, "/BIP AWAY_NICK [some_nick] :");
2055
bip_notify(ic, " If [some_nick] is set, BIP will change "
2056
"nickname to [some_nick] if there are no more client "
2058
bip_notify(ic, " If [some_nick] is empty, this command will "
2059
"unset current connection's away_nick.");
2060
} else if (strcasecmp(subhelp, "LIST") == 0) {
2061
bip_notify(ic, "/BIP LIST <section> :");
2062
bip_notify(ic, " List information from a these sections :");
2063
bip_notify(ic, " - networks: list all available networks");
2064
bip_notify(ic, " - connections: list all your configured "
2065
"connections and their state.");
2067
bip_notify(ic, " - users: list all users (admin)");
2068
bip_notify(ic, " - all_links: list all connected "
2069
"sockets from and to BIP (admin)");
2070
bip_notify(ic, " - all_connections: list all users' "
2071
"configured connections (admin)");
2074
bip_notify(ic, "-- No sub-help for '%s'", subhelp);
2078
int adm_bip(bip_t *bip, struct link_client *ic, struct line *line, int privmsg)
2080
int admin = LINK(ic)->user->admin;
2083
char *linestr, *elemstr;
2087
if (irc_line_count(line) != 3)
2090
linestr = irc_line_pop(line);
2093
/* all elem size <= linestr size */
2094
elemstr = bip_malloc(strlen(linestr) + 1);
2096
while((eptr = strstr(ptr, " "))) {
2102
memcpy(elemstr, ptr, slen);
2104
irc_line_append(line, elemstr);
2107
eptr = ptr + strlen(ptr);
2110
memcpy(elemstr, ptr, slen);
2112
irc_line_append(line, elemstr);
2118
if (!irc_line_includes(line, privmsg + 1))
2121
mylog(LOG_INFO, "/BIP %s from %s", irc_line_elem(line, privmsg + 1),
2122
LINK(ic)->user->name);
2123
if (strcasecmp(irc_line_elem(line, privmsg + 1), "RELOAD") == 0) {
2125
bip_notify(ic, "-- You're not allowed to reload bip");
2128
bip_notify(ic, "-- Reloading bip...");
2129
bip->reloading_client = ic;
2131
} else if (strcasecmp(irc_line_elem(line, privmsg + 1), "LIST") == 0) {
2132
if (irc_line_count(line) != privmsg + 3) {
2133
bip_notify(ic, "-- LIST command needs one argument");
2137
if (admin && strcasecmp(irc_line_elem(line, privmsg + 2),
2140
} else if (strcasecmp(irc_line_elem(line, privmsg + 2),
2142
adm_list_networks(ic);
2143
} else if (strcasecmp(irc_line_elem(line, privmsg + 2),
2144
"connections") == 0) {
2145
adm_list_connections(ic, NULL);
2146
} else if (admin && strcasecmp(irc_line_elem(line, privmsg + 2),
2147
"all_connections") == 0) {
2148
adm_list_all_connections(ic);
2149
} else if (admin && strcasecmp(irc_line_elem(line, privmsg + 2),
2150
"all_links") == 0) {
2151
adm_list_all_links(ic);
2153
bip_notify(ic, "-- Invalid LIST request");
2155
} else if (strcasecmp(irc_line_elem(line, privmsg + 1), "INFO") == 0) {
2156
if (!irc_line_includes(line, privmsg + 2)) {
2157
bip_notify(ic, "-- INFO command needs at least one "
2162
if (admin && irc_line_elem_case_equals(line, privmsg + 2,
2164
if (irc_line_count(line) == privmsg + 4) {
2166
irc_line_elem(line, privmsg + 3));
2168
bip_notify(ic, "-- INFO USER command needs one"
2175
bip_notify(ic, "-- Invalid INFO request");
2177
} else if (irc_line_elem_case_equals(line, privmsg + 1, "JUMP")) {
2178
if (LINK(ic)->l_server) {
2179
WRITE_LINE1(CONN(LINK(ic)->l_server), NULL, "QUIT",
2181
connection_close(CONN(LINK(ic)->l_server));
2183
bip_notify(ic, "-- Jumping to next server");
2184
} else if (irc_line_elem_case_equals(line, privmsg + 1, "BLRESET")) {
2185
if (irc_line_includes(line, privmsg + 2)) {
2186
if (irc_line_elem_equals(line, privmsg + 2, "-q")) {
2187
if (irc_line_includes(line, privmsg + 3)) {
2188
log_reset_store(LINK(ic)->log,
2192
log_reset_all(LINK(ic)->log);
2195
adm_blreset_store(ic, irc_line_elem(line,
2201
} else if (irc_line_elem_case_equals(line, privmsg + 1, "HELP")) {
2202
if (irc_line_count(line) == privmsg + 2)
2203
adm_bip_help(ic, admin, NULL);
2204
else if (irc_line_count(line) == privmsg + 3)
2205
adm_bip_help(ic, admin,
2206
irc_line_elem(line, privmsg + 2));
2209
"-- HELP command needs at most one argument");
2210
} else if (irc_line_elem_case_equals(line, privmsg + 1, "FOLLOW_NICK")) {
2211
if (irc_line_count(line) != privmsg + 3) {
2213
"-- FOLLOW_NICK command needs one argument");
2216
adm_follow_nick(ic, irc_line_elem(line, privmsg + 2));
2217
} else if (irc_line_elem_case_equals(line, privmsg + 1,
2218
"IGNORE_FIRST_NICK")) {
2219
if (irc_line_count(line) != privmsg + 3) {
2220
bip_notify(ic, "-- IGNORE_FIRST_NICK "
2221
"command needs one argument");
2224
adm_ignore_first_nick(ic, irc_line_elem(line, privmsg + 2));
2225
} else if (irc_line_elem_case_equals(line, privmsg + 1,
2226
"ON_CONNECT_SEND")) {
2227
if (irc_line_count(line) == privmsg + 2) {
2228
adm_on_connect_send(ic, NULL, 0);
2229
} else if (irc_line_includes(line, privmsg + 2)) {
2230
adm_on_connect_send(ic, line, privmsg);
2232
bip_notify(ic, "-- ON_CONNECT_SEND command needs at "
2233
"least one argument");
2235
} else if (irc_line_elem_case_equals(line, privmsg + 1, "AWAY_NICK")) {
2236
if (irc_line_count(line) == privmsg + 2) {
2237
adm_away_nick(ic, NULL);
2238
} else if (irc_line_count(line) == privmsg + 3) {
2239
adm_away_nick(ic, irc_line_elem(line, privmsg + 2));
2241
bip_notify(ic, "-- AWAY_NICK command needs zero or one"
2244
} else if (irc_line_elem_case_equals(line, privmsg + 1, "BACKLOG")) {
2245
if (irc_line_count(line) == privmsg + 2) {
2246
irc_cli_backlog(ic, 0);
2247
} else if (irc_line_count(line) == privmsg + 3) {
2248
int hours = atoi(irc_line_elem(line, privmsg + 2));
2249
irc_cli_backlog(ic, hours);
2251
bip_notify(ic, "-- BACKLOG takes 0 or one argument");
2253
} else if (admin && irc_line_elem_case_equals(line, privmsg + 1,
2255
if (irc_line_count(line) != privmsg + 4) {
2256
bip_notify(ic, "/BIP ADD_CONN <connection name> "
2259
adm_bip_addconn(bip, ic,
2260
irc_line_elem(line, privmsg + 2),
2261
irc_line_elem(line, privmsg + 3));
2263
} else if (admin && irc_line_elem_case_equals(line, privmsg + 1,
2265
if (irc_line_count(line) != privmsg + 3) {
2266
bip_notify(ic, "/BIP DEL_CONN <connection name>");
2268
adm_bip_delconn(bip, ic,
2269
irc_line_elem(line, privmsg + 2));
2272
bip_notify(ic, "Unknown command.");
2277
void free_conf(list_t *l)
2282
for (list_it_init(l, &li); (t = list_it_item(&li)); list_it_next(&li)) {
2283
switch (t->tuple_type) {
2290
free_conf(t->pdata);
2293
fatal("internal error free_conf");