This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-mbse/mbtask/taskibc.c

1822 lines
51 KiB
C
Raw Normal View History

2005-04-15 21:36:44 +00:00
/*****************************************************************************
*
* $Id$
2005-04-16 14:49:58 +00:00
* Purpose ...............: mbtask - Internet BBS Chat (but it looks like...)
2005-04-15 21:36:44 +00:00
*
*****************************************************************************
* Copyright (C) 1997-2006
2005-04-15 21:36:44 +00:00
*
* Michiel Broek FIDO: 2:280/2802
* Beekmansbos 10
* 1971 BV IJmuiden
* the Netherlands
*
* This file is part of MBSE BBS.
*
* This BBS 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, or (at your option) any
* later version.
*
* MBSE BBS 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 MBSE BBS; see the file COPYING. If not, write to the Free
* Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*****************************************************************************/
#include "../config.h"
#include "../lib/mbselib.h"
2005-04-17 10:32:41 +00:00
#include "taskstat.h"
2005-04-18 13:37:19 +00:00
#include "taskutil.h"
2005-04-22 21:18:45 +00:00
#include "taskchat.h"
2005-04-16 14:49:58 +00:00
#include "taskibc.h"
2005-04-15 21:36:44 +00:00
2006-02-15 19:56:26 +00:00
extern int internet; /* Internet status */
time_t scfg_time = (time_t)0; /* Servers config time */
time_t now; /* Current time */
int callchg = FALSE; /* Is call state changed */
int srvchg = FALSE; /* Is serverlist changed */
int usrchg = FALSE; /* Is userlist changed */
int chnchg = FALSE; /* Is channellist changed */
int banchg = FALSE; /* Is banned users changed */
int nickchg = FALSE; /* Is nicknames changed */
time_t resettime; /* Time to reset all */
int do_reset = FALSE; /* Reset init */
int link_reset = FALSE; /* Reset one link */
extern struct sockaddr_in clientaddr_in; /* IBC remote socket */
2005-05-01 13:12:41 +00:00
2006-01-31 19:21:36 +00:00
#define PING_PONG_LOG 1
2006-01-25 18:53:21 +00:00
2005-04-17 14:14:56 +00:00
typedef enum {NCS_INIT, NCS_CALL, NCS_WAITPWD, NCS_CONNECT, NCS_HANGUP, NCS_FAIL, NCS_DEAD} NCSTYPE;
2005-04-17 10:32:41 +00:00
static char *ncsstate[] = {
2005-04-17 14:14:56 +00:00
(char *)"init", (char *)"call", (char *)"waitpwd", (char *)"connect",
(char *)"hangup", (char *)"fail", (char *)"dead"
2005-04-17 10:32:41 +00:00
};
2005-04-15 21:36:44 +00:00
2006-01-29 16:47:32 +00:00
static char *mon[] = {
(char *)"Jan",(char *)"Feb",(char *)"Mar",
(char *)"Apr",(char *)"May",(char *)"Jun",
(char *)"Jul",(char *)"Aug",(char *)"Sep",
(char *)"Oct",(char *)"Nov",(char *)"Dec"
};
2005-04-20 16:59:32 +00:00
2005-04-15 21:36:44 +00:00
/*
2005-04-18 08:54:55 +00:00
* Internal prototypes
2005-04-15 21:36:44 +00:00
*/
2006-05-25 16:37:52 +00:00
void fill_ncslist(char *, char *, char *, int, unsigned int);
2005-04-18 08:54:55 +00:00
void dump_ncslist(void);
2006-05-25 16:37:52 +00:00
int add_server(char *, int, char *, char *, char *, char *);
void del_server(char *);
void del_router(char *);
int send_msg(int, char *);
2006-03-06 16:34:26 +00:00
void broadcast(char *, char *);
2005-04-18 08:54:55 +00:00
void check_servers(void);
2006-05-25 16:37:52 +00:00
int command_pass(int, char *, char *);
2005-04-27 18:02:30 +00:00
int command_server(char *, char *);
2006-05-25 16:37:52 +00:00
int command_squit(int, char *, char *);
int command_user(int, char *, char *);
int command_quit(int, char *, char *);
int command_nick(int, char *, char *);
int command_join(int, char *, char *);
int command_part(int, char *, char *);
int command_topic(int, char *, char *);
int command_privmsg(int, char *, char *);
2006-01-25 18:53:21 +00:00
2005-04-18 08:54:55 +00:00
/*
2006-05-25 16:37:52 +00:00
* Add a server to the neighbour serverlist
2005-04-18 08:54:55 +00:00
*/
2006-05-25 16:37:52 +00:00
void fill_ncslist(char *server, char *myname, char *passwd, int dyndns, unsigned int crc)
2005-04-15 21:36:44 +00:00
{
2006-05-25 16:37:52 +00:00
int i;
for (i = 0; i < MAXIBC_NCS; i++) {
if (strlen(ncs_list[i].server) == 0) {
strncpy(ncs_list[i].server, server, 63);
strncpy(ncs_list[i].resolved, server, 63);
strncpy(ncs_list[i].myname, myname, 63);
strncpy(ncs_list[i].passwd, passwd, 15);
ncs_list[i].state = NCS_INIT;
ncs_list[i].action = now;
ncs_list[i].last = (time_t)0;
ncs_list[i].version = 0;
ncs_list[i].remove = FALSE;
ncs_list[i].socket = -1;
ncs_list[i].token = 0;
ncs_list[i].gotpass = FALSE;
ncs_list[i].gotserver = FALSE;
ncs_list[i].dyndns = dyndns;
ncs_list[i].halfdead = 0;
ncs_list[i].crc = crc;
return;
2005-04-17 10:32:41 +00:00
}
2005-04-15 21:36:44 +00:00
}
2006-05-25 16:37:52 +00:00
WriteError("IBC: ncs_list is full");
2005-04-17 10:32:41 +00:00
}
2005-04-15 21:36:44 +00:00
2005-04-17 10:32:41 +00:00
void dump_ncslist(void)
{
2006-01-29 16:47:32 +00:00
char temp1[128], temp2[128], buf[21];
struct tm ptm;
2006-01-29 20:35:18 +00:00
time_t tnow;
2006-05-25 16:37:52 +00:00
int i, first;
2005-04-15 21:36:44 +00:00
2005-05-08 13:17:43 +00:00
if (!callchg && !srvchg && !usrchg && !chnchg && !banchg && !nickchg)
2005-04-17 14:14:56 +00:00
return;
2005-04-15 21:36:44 +00:00
2005-05-08 13:17:43 +00:00
if (callchg) {
2006-05-25 16:37:52 +00:00
first = FALSE;
for (i = 0; i < MAXIBC_NCS; i++) {
if (strlen(ncs_list[i].server)) {
if (! first) {
Syslog('r', "IBC: Idx Server State Del Pwd Srv Dyn 1/2 Next action");
Syslog('r', "IBC: --- ------------------------------ ------- --- --- --- --- --- -----------");
first = TRUE;
}
snprintf(temp1, 30, "%s", ncs_list[i].server);
Syslog('r', "IBC: %3d %-30s %-7s %s %s %s %s %3d %d", i, temp1, ncsstate[ncs_list[i].state],
ncs_list[i].remove ? "yes":"no ", ncs_list[i].gotpass ? "yes":"no ",
ncs_list[i].gotserver ? "yes":"no ", ncs_list[i].dyndns ? "yes":"no ",
ncs_list[i].halfdead, (int)ncs_list[i].action - (int)now);
2005-05-01 13:12:41 +00:00
}
2006-05-25 16:37:52 +00:00
}
if (! first) {
Syslog('r', "IBC: No servers configured");
2005-05-01 13:12:41 +00:00
}
2005-05-08 13:17:43 +00:00
}
2005-05-01 13:12:41 +00:00
2005-05-08 13:17:43 +00:00
if (srvchg) {
2006-05-25 16:37:52 +00:00
first = FALSE;
for (i = 0; i < MAXIBC_SRV; i++) {
if (strlen(srv_list[i].server)) {
if (! first) {
2006-05-25 19:17:49 +00:00
Syslog('+', "IBC: Idx Server Router Hops User Connect time");
Syslog('+', "IBC: --- ------------------------- ------------------------- ---- ---- --------------------");
2006-05-25 16:37:52 +00:00
first = TRUE;
}
snprintf(temp1, 25, "%s", srv_list[i].server);
snprintf(temp2, 25, "%s", srv_list[i].router);
tnow = (time_t)srv_list[i].connected;
2006-01-29 20:35:18 +00:00
localtime_r(&tnow, &ptm);
2006-01-29 16:47:32 +00:00
snprintf(buf, 21, "%02d-%s-%04d %02d:%02d:%02d", ptm.tm_mday, mon[ptm.tm_mon], ptm.tm_year+1900,
ptm.tm_hour, ptm.tm_min, ptm.tm_sec);
2006-05-25 19:17:49 +00:00
Syslog('+', "IBC: %3d %-25s %-25s %4d %4d %s", i, temp1, temp2, srv_list[i].hops, srv_list[i].users, buf);
2005-05-01 13:12:41 +00:00
}
2006-05-25 16:37:52 +00:00
}
if (! first) {
2005-05-01 13:12:41 +00:00
Syslog('+', "IBC: Servers list is empty");
2005-04-18 20:54:21 +00:00
}
2005-04-18 13:21:31 +00:00
}
2005-04-18 20:54:21 +00:00
2005-04-20 16:59:32 +00:00
if (usrchg) {
2006-05-25 16:37:52 +00:00
first = FALSE;
for (i = 0; i < MAXIBC_USR; i++) {
if (strlen(usr_list[i].server)) {
if (! first) {
Syslog('+', "IBC: Idx Server User Name/Nick Channel Sys Connect time");
Syslog('+', "IBC: --- -------------------- ---------------- --------- ------------- --- --------------------");
first = TRUE;
}
snprintf(temp1, 20, "%s", usr_list[i].server);
snprintf(temp2, 16, "%s", usr_list[i].realname);
tnow = (time_t)usr_list[i].connected;
2006-01-29 20:35:18 +00:00
localtime_r(&tnow, &ptm);
2006-01-29 16:47:32 +00:00
snprintf(buf, 21, "%02d-%s-%04d %02d:%02d:%02d", ptm.tm_mday, mon[ptm.tm_mon], ptm.tm_year+1900,
ptm.tm_hour, ptm.tm_min, ptm.tm_sec);
2006-05-25 16:37:52 +00:00
Syslog('+', "IBC: %3d %-20s %-16s %-9s %-13s %s %s", i, temp1, temp2, usr_list[i].nick, usr_list[i].channel,
usr_list[i].sysop ? "yes":"no ", buf);
}
2006-05-25 16:37:52 +00:00
}
if (! first) {
Syslog('+', "IBC: Users list is empty");
2005-04-20 16:59:32 +00:00
}
}
2005-04-23 14:27:52 +00:00
if (chnchg) {
2006-05-25 16:37:52 +00:00
first = FALSE;
for (i = 0; i < MAXIBC_CHN; i++) {
if (strlen(chn_list[i].server)) {
if (! first) {
Syslog('+', "IBC: Idx Channel Owner Topic Usr Created");
Syslog('+', "IBC: --- -------------------- --------- ------------------------------- --- --------------------");
first = TRUE;
}
tnow = (time_t)chn_list[i].created;
2006-01-29 20:35:18 +00:00
localtime_r(&tnow, &ptm);
2006-01-29 16:47:32 +00:00
snprintf(buf, 21, "%02d-%s-%04d %02d:%02d:%02d", ptm.tm_mday, mon[ptm.tm_mon], ptm.tm_year+1900,
ptm.tm_hour, ptm.tm_min, ptm.tm_sec);
2006-05-25 16:37:52 +00:00
Syslog('+', "IBC: %3d %-20s %-9s %-31s %3d %s", i, chn_list[i].name,
chn_list[i].owner, chn_list[i].topic, chn_list[i].users, buf);
2005-04-23 14:27:52 +00:00
}
2006-05-25 16:37:52 +00:00
}
if (! first) {
2005-04-23 14:27:52 +00:00
Syslog('+', "IBC: Channels list is empty");
}
}
callchg = srvchg = usrchg = chnchg = banchg = nickchg = FALSE;
2005-04-15 21:36:44 +00:00
}
2005-04-20 16:59:32 +00:00
/*
2005-04-21 21:12:50 +00:00
* Add one user to the userlist. Returns:
* 0 = Ok
* 1 = User already registered.
2006-05-25 16:37:52 +00:00
* 2 = Too many users.
2005-04-20 16:59:32 +00:00
*/
2006-05-25 16:37:52 +00:00
int add_user(char *server, char *name, char *realname)
2005-04-20 16:59:32 +00:00
{
2006-05-25 16:37:52 +00:00
int i, j, Found = FALSE;
2005-04-20 16:59:32 +00:00
2006-05-25 16:37:52 +00:00
for (j = 0; j < MAXIBC_USR; j++) {
if ((strcmp(usr_list[j].server, server) == 0) && (strcmp(usr_list[j].realname, realname) == 0)) {
Syslog('!', "IBC: add_user(%s, %s, %s), already registered", server, name, realname);
2005-04-21 21:12:50 +00:00
return 1;
2005-04-20 16:59:32 +00:00
}
}
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_SRV; i++) {
if (strcmp(srv_list[i].server, server) == 0) {
Found = TRUE;
break;
}
}
if (!Found) {
Syslog('!', "IBC: add_user(%s, %s, %s), unknown server", server, name, realname);
return 1;
}
2006-05-25 16:37:52 +00:00
for (j = 0; j < MAXIBC_USR; j++) {
if (strlen(usr_list[j].server) == 0) {
strncpy(usr_list[j].server, server, 63);
strncpy(usr_list[j].name, name, 9);
strncpy(usr_list[j].nick, name, 9);
strncpy(usr_list[j].realname, realname, 36);
usr_list[j].connected = now;
srv_list[i].users++;
srvchg = usrchg = TRUE;
Syslog('r', "IBC: add_user (%s, %s, %s) slot=%d", server, name, realname, i);
2006-05-25 16:37:52 +00:00
return 0;
2005-04-20 16:59:32 +00:00
}
}
WriteError("IBC: add_user(%s, %s, %s), user list is full", server, name, realname);
2006-05-25 16:37:52 +00:00
return 2;
2005-04-20 16:59:32 +00:00
}
/*
* Delete user from channel
*/
void del_userchannel(char *channel)
{
int i;
for (i = 0; i < MAXIBC_CHN; i++) {
if (strcmp(chn_list[i].name, channel) == 0 && chn_list[i].users) {
chnchg = TRUE;
chn_list[i].users--;
Syslog('r', "IBC: del_userchannel(%s), %d users left", channel, chn_list[i].users);
if (chn_list[i].users == 0) {
Syslog('+', "IBC: deleted empty channel %s", channel);
del_channel(channel);
}
break;
}
}
}
2005-04-20 16:59:32 +00:00
/*
2005-04-23 10:58:43 +00:00
* Delete one user. If name == NULL then delete all users of a server.
2005-04-20 16:59:32 +00:00
*/
2006-05-25 16:37:52 +00:00
void del_user(char *server, char *name)
2005-04-20 16:59:32 +00:00
{
2006-05-25 16:37:52 +00:00
int i, count = 0;
2005-04-20 16:59:32 +00:00
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_USR; i++) {
if (name && (strcmp(usr_list[i].server, server) == 0) && (strcmp(usr_list[i].name, name) == 0)) {
if (strlen(usr_list[i].channel))
del_userchannel(usr_list[i].channel);
Syslog('r', "IBC: del_user(%s, %s) from slot %d", server, printable(name, 0), i);
2006-05-25 16:37:52 +00:00
memset(&usr_list[i], 0, sizeof(_usr_list));
2005-04-23 10:58:43 +00:00
usrchg = TRUE;
count++;
2006-05-25 16:37:52 +00:00
} else if ((name == NULL) && (strcmp(usr_list[i].server, server) == 0)) {
if (strlen(usr_list[i].channel))
del_userchannel(usr_list[i].channel);
Syslog('r', "IBC: del_user(%s, %s) user %s from slot %d", server, printable(name, 0), usr_list[i].name, i);
2006-05-25 16:37:52 +00:00
memset(&usr_list[i], 0, sizeof(_usr_list));
2005-04-20 16:59:32 +00:00
usrchg = TRUE;
count++;
2005-04-20 16:59:32 +00:00
}
}
/*
* Update users list of the server
*/
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_SRV; i++) {
if ((strcmp(srv_list[i].server, server) == 0) && srv_list[i].users) {
srv_list[i].users -= count;
if (srv_list[i].users < 0)
srv_list[i].users = 0; /* Just in case, nothing is perfect */
2005-04-20 16:59:32 +00:00
srvchg = TRUE;
}
}
}
2005-04-23 14:27:52 +00:00
/*
2006-05-25 16:37:52 +00:00
* Add channel with owner, returns:
* 0 = Success
* 1 = Already registered
* 2 = Too many channels
2005-04-23 14:27:52 +00:00
*/
2006-05-25 16:37:52 +00:00
int add_channel(char *name, char *owner, char *server)
2005-04-23 14:27:52 +00:00
{
2006-05-25 16:37:52 +00:00
int i;
2005-04-23 14:27:52 +00:00
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_CHN; i++) {
if ((strcmp(chn_list[i].name, name) == 0) && (strcmp(chn_list[i].owner, owner) == 0) &&
(strcmp(chn_list[i].server, server) == 0)) {
Syslog('!', "IBC: add_channel(%s, %s, %s), already registered", name, owner, server);
2005-04-23 14:27:52 +00:00
return 1;
}
}
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_CHN; i++) {
if (strlen(chn_list[i].server) == 0) {
strncpy(chn_list[i].name, name, 20);
strncpy(chn_list[i].owner, owner, 9);
strncpy(chn_list[i].server, server, 63);
chn_list[i].users = 1;
chn_list[i].created = now;
chnchg = TRUE;
Syslog('r', "IBC: add_channel (%s, %s, %s) slot=%d", name, owner, server, i);
2006-05-25 16:37:52 +00:00
return 0;
2005-04-30 11:31:31 +00:00
}
2005-04-23 14:27:52 +00:00
}
WriteError("IBC: add_channel(%s, %s, %s), too many channels", name, owner, server);
2006-05-25 16:37:52 +00:00
return 2;
2005-04-23 14:27:52 +00:00
}
2006-05-25 16:37:52 +00:00
void del_channel(char *name)
2005-04-23 14:27:52 +00:00
{
2006-05-25 16:37:52 +00:00
int i;
2005-04-23 14:27:52 +00:00
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_CHN; i++) {
2006-05-28 09:44:07 +00:00
if (strlen(chn_list[i].server) && (strcmp(chn_list[i].name, name) == 0)) {
Syslog('r', "IBC: del_channel(%s), slot=%d", name, i);
2006-05-25 16:37:52 +00:00
memset(&chn_list[i], 0, sizeof(_chn_list));
2006-05-28 09:44:07 +00:00
return;
2005-04-23 14:27:52 +00:00
}
}
}
/*
* Add a server to the list, returns
* 0 = error
* 1 = success
*/
2006-05-25 16:37:52 +00:00
int add_server(char *name, int hops, char *prod, char *vers, char *fullname, char *router)
2005-04-18 13:21:31 +00:00
{
2006-05-25 16:37:52 +00:00
int i, haverouter = FALSE;
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_SRV; i++) {
if (strlen(srv_list[i].server) && (strcmp(srv_list[i].server, name) == 0)) {
Syslog('r', "IBC: add_server %s %d %s %s \"%s\" %s, duplicate, ignore", name, hops, prod, vers, fullname, router);
return 0;
}
}
/*
* If name <> router it's a remote server, then check if we have a router in our list.
*/
if (strcmp(name, router) && hops) {
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_SRV; i++) {
if (strcmp(srv_list[i].server, router) == 0) {
haverouter = TRUE;
break;
}
}
if (! haverouter) {
Syslog('r', "IBC: add_server %s %d %s %s \"%s\" %s, no router, ignore", name, hops, prod, vers, fullname, router);
return 0;
2005-04-18 19:13:14 +00:00
}
}
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_SRV; i++) {
if (strlen(srv_list[i].server) == 0) {
strncpy(srv_list[i].server, name, 63);
strncpy(srv_list[i].router, router, 63);
strncpy(srv_list[i].prod, prod, 20);
strncpy(srv_list[i].vers, vers, 20);
strncpy(srv_list[i].fullname, fullname, 35);
srv_list[i].connected = now;
srv_list[i].users = 0;
srv_list[i].hops = hops;
srvchg = TRUE;
Syslog('r', "IBC: add_server %s %d %s %s \"%s\" %s, slot=%d", name, hops, prod, vers, fullname, router, i);
2006-05-25 16:37:52 +00:00
return 1;
2005-04-30 11:31:31 +00:00
}
2005-04-18 13:21:31 +00:00
}
2005-04-18 20:36:22 +00:00
WriteError("IBC: add_server %s %d %s %s \"%s\" %s, serverlist full", name, hops, prod, vers, fullname, router);
2006-05-25 16:37:52 +00:00
return 0;
2005-04-18 13:21:31 +00:00
}
2005-04-18 18:46:08 +00:00
/*
* Delete server.
*/
2006-05-25 16:37:52 +00:00
void del_server(char *name)
2005-04-18 14:28:41 +00:00
{
2006-05-25 16:37:52 +00:00
int i;
2005-04-18 14:28:41 +00:00
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_SRV; i++) {
if (strcmp(srv_list[i].server, name) == 0) {
Syslog('r', "IBC: del_server(%s), slot %d", name, i);
del_user(srv_list[i].server, NULL);
2006-05-25 16:37:52 +00:00
memset(&srv_list[i], 0, sizeof(_srv_list));
2005-04-18 20:54:21 +00:00
srvchg = TRUE;
2005-04-18 14:28:41 +00:00
}
}
}
2005-04-18 18:46:08 +00:00
/*
* Delete router.
*/
2006-05-25 16:37:52 +00:00
void del_router(char *name)
2005-04-18 18:46:08 +00:00
{
2006-05-25 16:37:52 +00:00
int i;
2005-04-18 20:36:22 +00:00
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_SRV; i++) {
if (strcmp(srv_list[i].router, name) == 0) {
Syslog('r', "IBC: del_router(%s) slot %d", name, i);
2006-05-25 16:37:52 +00:00
del_user(srv_list[i].server, NULL);
memset(&srv_list[i], 0, sizeof(_srv_list));
2005-04-18 20:54:21 +00:00
srvchg = TRUE;
2005-04-18 18:46:08 +00:00
}
}
}
2005-04-15 21:36:44 +00:00
/*
* Send a message to all servers
*/
2006-03-06 16:34:26 +00:00
void send_all(char *msg)
2005-04-15 21:36:44 +00:00
{
2006-05-25 16:37:52 +00:00
int i;
2005-04-18 12:56:28 +00:00
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_NCS; i++) {
if (strlen(ncs_list[i].server) && (ncs_list[i].state == NCS_CONNECT)) {
send_msg(i, msg);
2005-04-18 12:56:28 +00:00
}
}
2005-04-17 10:32:41 +00:00
}
/*
* Send command message to each connected neighbour server and use the correct own fqdn.
*/
void send_at(char *cmd, char *nick, char *param)
2006-05-25 16:37:52 +00:00
{
int i;
char *p;
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_NCS; i++) {
if (strlen(ncs_list[i].server) && (ncs_list[i].state == NCS_CONNECT)) {
2006-03-06 16:34:26 +00:00
p = xstrcpy(cmd);
p = xstrcat(p, (char *)" ");
p = xstrcat(p, nick);
p = xstrcat(p, (char *)"@");
2006-05-25 16:37:52 +00:00
p = xstrcat(p, ncs_list[i].myname);
2006-03-06 16:34:26 +00:00
p = xstrcat(p, (char *)" ");
p = xstrcat(p, param);
p = xstrcat(p, (char *)"\r\n");
2006-05-25 16:37:52 +00:00
send_msg(i, p);
2006-03-06 16:34:26 +00:00
free(p);
}
}
}
void send_nick(char *nick, char *name, char *realname)
{
2006-05-25 16:37:52 +00:00
int i;
char *p;
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_NCS; i++) {
if (strlen(ncs_list[i].server) && (ncs_list[i].state == NCS_CONNECT)) {
2006-03-06 16:34:26 +00:00
p = xstrcpy((char *)"NICK ");
p = xstrcat(p, nick);
p = xstrcat(p, (char *)" ");
p = xstrcat(p, name);
p = xstrcat(p, (char *)" ");
2006-05-25 16:37:52 +00:00
p = xstrcat(p, ncs_list[i].myname);
2006-03-06 16:34:26 +00:00
p = xstrcat(p, (char *)" ");
p = xstrcat(p, realname);
p = xstrcat(p, (char *)"\r\n");
2006-05-25 16:37:52 +00:00
send_msg(i, p);
2006-03-06 16:34:26 +00:00
free(p);
}
}
}
2005-04-18 16:48:51 +00:00
/*
* Broadcast a message to all servers except the originating server
*/
2006-03-06 16:34:26 +00:00
void broadcast(char *origin, char *msg)
2005-04-18 16:48:51 +00:00
{
2006-05-25 16:37:52 +00:00
int i;
2005-04-18 16:48:51 +00:00
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_NCS; i++) {
if (strlen(ncs_list[i].server) && (ncs_list[i].state == NCS_CONNECT) && (strcmp(origin, ncs_list[i].server))) {
send_msg(i, msg);
2005-04-18 16:48:51 +00:00
}
}
}
2005-04-17 11:26:48 +00:00
/*
* Send message to a server
*/
2006-05-25 16:37:52 +00:00
int send_msg(int slot, char *msg)
2005-04-17 11:26:48 +00:00
{
2006-03-06 19:55:10 +00:00
char *p;
2005-04-21 21:12:50 +00:00
2005-12-17 19:47:27 +00:00
#ifndef PING_PONG_LOG
2006-03-06 19:55:10 +00:00
if (strcmp(msg, "PING\r\n") && strcmp(msg, "PONG\r\n")) {
#endif
p = xstrcpy((char *)"IBC: > ");
2006-05-25 16:37:52 +00:00
p = xstrcat(p, ncs_list[slot].server);
2006-03-06 19:55:10 +00:00
p = xstrcat(p, (char *)": ");
p = xstrcat(p, printable(msg, 0));
Syslogp('r', p);
free(p);
#ifndef PING_PONG_LOG
}
2005-12-17 19:47:27 +00:00
#endif
2005-04-17 11:26:48 +00:00
2006-05-25 16:37:52 +00:00
if (sendto(ncs_list[slot].socket, msg, strlen(msg), 0,
(struct sockaddr *)&ncs_list[slot].servaddr_in, sizeof(struct sockaddr_in)) == -1) {
WriteError("$IBC: can't send message");
2005-04-17 11:26:48 +00:00
return -1;
}
return 0;
}
2005-04-17 10:32:41 +00:00
void check_servers(void)
{
2006-03-06 16:34:26 +00:00
char *errmsg, *p, scfgfn[PATH_MAX];
2005-04-18 08:54:55 +00:00
FILE *fp;
2006-05-25 16:37:52 +00:00
int i, j, inlist, Remove, local_reset, conf_changed;
int a1, a2, a3, a4, users = 0, channels = 0;
unsigned int crc;
2005-04-18 08:54:55 +00:00
struct servent *se;
struct hostent *he;
2005-04-17 10:32:41 +00:00
2006-02-13 19:26:30 +00:00
now = time(NULL);
2005-08-29 21:03:28 +00:00
snprintf(scfgfn, PATH_MAX, "%s/etc/ibcsrv.data", getenv("MBSE_ROOT"));
2005-04-17 10:32:41 +00:00
/*
* Check if we reached the global reset time
*/
2006-02-13 19:26:30 +00:00
if (((int)now > (int)resettime) && !do_reset) {
resettime = time(NULL) + (time_t)86400;
do_reset = TRUE;
Syslog('+', "IBC: global reset time reached, preparing reset");
}
2006-01-31 19:21:36 +00:00
local_reset = conf_changed = FALSE;
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_USR; i++)
if (strlen(usr_list[i].server))
users++;
for (i = 0; i < MAXIBC_CHN; i++)
if (strlen(chn_list[i].server))
channels++;
if (!users && !channels && do_reset) {
Syslog('+', "IBC: no channels and users, performing reset");
local_reset = TRUE;
do_reset = FALSE;
}
2006-01-31 19:21:36 +00:00
if (file_time(scfgfn) != scfg_time) {
conf_changed = TRUE;
Syslog('+', "IBC: %s filetime changed, rereading configuration", scfgfn);
}
2005-04-17 10:32:41 +00:00
/*
* Check if configuration is changed, if so then apply the changes.
*/
2006-01-31 19:21:36 +00:00
if (conf_changed || local_reset || link_reset) {
2005-04-17 10:32:41 +00:00
2006-05-25 16:37:52 +00:00
if (strlen(srv_list[0].server) == 0) {
2005-04-20 16:59:32 +00:00
/*
* First add this server name to the servers database.
*/
2006-05-25 16:37:52 +00:00
add_server(CFG.myfqdn, 0, (char *)"mbsebbs", (char *)VERSION, CFG.bbs_name, (char *)"none");
2005-04-20 16:59:32 +00:00
}
/*
* Local reset, make all crc's invalid so the connections will restart.
*/
if (local_reset) {
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_NCS; i++)
if (strlen(ncs_list[i].server))
ncs_list[i].crc--;
}
2006-01-31 19:21:36 +00:00
if (link_reset) {
Syslog('r', "IBC: link_reset starting");
link_reset = FALSE;
}
2005-04-17 10:32:41 +00:00
if ((fp = fopen(scfgfn, "r"))) {
fread(&ibcsrvhdr, sizeof(ibcsrvhdr), 1, fp);
/*
* Check for neighbour servers to delete
*/
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_NCS; i++) {
if (strlen(ncs_list[i].server)) {
fseek(fp, ibcsrvhdr.hdrsize, SEEK_SET);
inlist = FALSE;
while (fread(&ibcsrv, ibcsrvhdr.recsize, 1, fp)) {
crc = 0xffffffff;
crc = upd_crc32((char *)&ibcsrv, crc, sizeof(ibcsrv));
if ((strcmp(ncs_list[i].server, ibcsrv.server) == 0) && ibcsrv.Active && (ncs_list[i].crc == crc)) {
inlist = TRUE;
}
}
if (!inlist) {
if (local_reset || link_reset)
Syslog('+', "IBC: server %s connection reset", ncs_list[i].server);
else
Syslog('+', "IBC: server %s configuration changed or removed", ncs_list[i].server);
ncs_list[i].remove = TRUE;
ncs_list[i].action = now;
srvchg = TRUE;
callchg = TRUE;
}
}
}
/*
* Start removing servers
*/
Remove = FALSE;
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_NCS; i++) {
if (ncs_list[i].remove) {
Remove = TRUE;
2006-05-25 16:37:52 +00:00
Syslog('r', "IBC: Remove server %s", ncs_list[i].server);
if (ncs_list[i].state == NCS_CONNECT) {
2006-03-06 16:34:26 +00:00
p = calloc(512, sizeof(char));
if (local_reset) {
2006-05-25 16:37:52 +00:00
snprintf(p, 512, "SQUIT %s Reset connection\r\n", ncs_list[i].server);
broadcast(ncs_list[i].server, p);
snprintf(p, 512, "SQUIT %s Your system connection is reset\r\n", ncs_list[i].myname);
send_msg(i, p);
} else {
2006-05-25 16:37:52 +00:00
snprintf(p, 512, "SQUIT %s Removed from configuration\r\n", ncs_list[i].server);
broadcast(ncs_list[i].server, p);
snprintf(p, 512, "SQUIT %s Your system is removed from configuration\r\n", ncs_list[i].myname);
send_msg(i, p);
}
2006-03-06 16:34:26 +00:00
free(p);
2006-05-25 16:37:52 +00:00
del_router(ncs_list[i].server);
}
2006-05-25 16:37:52 +00:00
if (ncs_list[i].socket != -1) {
Syslog('r', "IBC: Closing socket %d", ncs_list[i].socket);
shutdown(ncs_list[i].socket, SHUT_WR);
ncs_list[i].socket = -1;
ncs_list[i].state = NCS_HANGUP;
}
callchg = TRUE;
srvchg = TRUE;
}
}
dump_ncslist();
2006-01-31 19:21:36 +00:00
if (link_reset) {
link_reset = FALSE;
}
/*
* If a neighbour is removed by configuration, remove it from the list.
*/
if (Remove) {
Syslog('r', "IBC: Starting remove list");
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_NCS; i++) {
if (ncs_list[i].remove) {
Syslog('r', " do %s", ncs_list[i].server);
2006-05-25 16:37:52 +00:00
memset(&ncs_list[i], 0, sizeof(_ncs_list));
2006-02-13 19:26:30 +00:00
callchg = TRUE;
}
}
}
dump_ncslist();
/*
* Changed or deleted servers are now removed, add new
* configured servers or changed servers.
*/
fseek(fp, ibcsrvhdr.hdrsize, SEEK_SET);
2005-04-17 10:32:41 +00:00
while (fread(&ibcsrv, ibcsrvhdr.recsize, 1, fp)) {
/*
* Check for new configured servers
*/
if (ibcsrv.Active && strlen(ibcsrv.myname) && strlen(ibcsrv.server) && strlen(ibcsrv.passwd)) {
2005-04-17 10:32:41 +00:00
inlist = FALSE;
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_NCS; i++) {
if (strcmp(ncs_list[i].server, ibcsrv.server) == 0) {
2005-04-17 10:32:41 +00:00
inlist = TRUE;
}
}
2006-05-25 16:37:52 +00:00
for (j = 0; j < MAXIBC_SRV; j++) {
if ((strcmp(srv_list[j].server, ibcsrv.server) == 0) && (strcmp(srv_list[j].router, ibcsrv.server))) {
2005-12-09 19:22:20 +00:00
inlist = TRUE;
Syslog('+', "IBC: can't add new configured server %s: already connected via %s",
2006-05-25 16:37:52 +00:00
ibcsrv.server, srv_list[j].router);
2005-12-09 19:22:20 +00:00
}
}
2005-04-17 10:32:41 +00:00
if (!inlist ) {
crc = 0xffffffff;
crc = upd_crc32((char *)&ibcsrv, crc, sizeof(ibcsrv));
2006-05-25 16:37:52 +00:00
fill_ncslist(ibcsrv.server, ibcsrv.myname, ibcsrv.passwd, ibcsrv.Dyndns, crc);
2005-05-01 13:12:41 +00:00
srvchg = TRUE;
2005-05-08 15:50:59 +00:00
callchg = TRUE;
2005-04-30 11:31:31 +00:00
Syslog('+', "IBC: new configured Internet BBS Chatserver: %s", ibcsrv.server);
2005-04-17 10:32:41 +00:00
}
}
}
fclose(fp);
}
scfg_time = file_time(scfgfn);
}
2005-05-08 15:50:59 +00:00
dump_ncslist();
2005-04-17 10:32:41 +00:00
/*
* Check if we need to make state changes
*/
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_NCS; i++) {
if (strlen(ncs_list[i].server) == 0)
continue;
if (((int)ncs_list[i].action - (int)now) <= 0) {
switch (ncs_list[i].state) {
case NCS_INIT: if (internet) {
2005-04-17 10:32:41 +00:00
/*
* Internet is available, setup the connection.
* Get IP address for the hostname.
* Set default next action to 60 seconds.
2005-04-17 10:32:41 +00:00
*/
2006-05-25 16:37:52 +00:00
ncs_list[i].action = now + (time_t)60;
memset(&ncs_list[i].servaddr_in, 0, sizeof(struct sockaddr_in));
2005-04-17 10:32:41 +00:00
se = getservbyname("fido", "udp");
2006-05-25 16:37:52 +00:00
ncs_list[i].servaddr_in.sin_family = AF_INET;
ncs_list[i].servaddr_in.sin_port = se->s_port;
2005-04-17 10:32:41 +00:00
2006-05-25 16:37:52 +00:00
if (sscanf(ncs_list[i].server,"%d.%d.%d.%d",&a1,&a2,&a3,&a4) == 4)
ncs_list[i].servaddr_in.sin_addr.s_addr = inet_addr(ncs_list[i].server);
else if ((he = gethostbyname(ncs_list[i].server)))
memcpy(&ncs_list[i].servaddr_in.sin_addr, he->h_addr, he->h_length);
2005-04-17 10:32:41 +00:00
else {
switch (h_errno) {
case HOST_NOT_FOUND: errmsg = (char *)"Authoritative: Host not found"; break;
case TRY_AGAIN: errmsg = (char *)"Non-Authoritive: Host not found"; break;
case NO_RECOVERY: errmsg = (char *)"Non recoverable errors"; break;
default: errmsg = (char *)"Unknown error"; break;
}
2006-05-25 16:37:52 +00:00
Syslog('!', "IBC: no IP address for %s: %s", ncs_list[i].server, errmsg);
ncs_list[i].action = now + (time_t)120;
ncs_list[i].state = NCS_FAIL;
2005-05-08 13:17:43 +00:00
callchg = TRUE;
2005-04-17 10:32:41 +00:00
break;
}
2006-05-25 16:37:52 +00:00
if (ncs_list[i].socket == -1) {
ncs_list[i].socket = socket(AF_INET, SOCK_DGRAM, 0);
if (ncs_list[i].socket == -1) {
Syslog('!', "$IBC: can't create socket for %s", ncs_list[i].server);
ncs_list[i].state = NCS_FAIL;
ncs_list[i].action = now + (time_t)120;
callchg = TRUE;
break;
}
Syslog('r', "IBC: socket %d created for %s", ncs_list[i].socket, ncs_list[i].server);
} else {
Syslog('r', "IBC: socket %d reused for %s", ncs_list[i].socket, ncs_list[i].server);
2005-04-17 10:32:41 +00:00
}
2006-05-25 16:37:52 +00:00
ncs_list[i].state = NCS_CALL;
ncs_list[i].action = now + (time_t)1;
2005-05-08 13:17:43 +00:00
callchg = TRUE;
2005-04-17 10:32:41 +00:00
} else {
/*
* No internet, just wait
*/
2006-05-25 16:37:52 +00:00
ncs_list[i].action = now + (time_t)10;
2005-04-17 10:32:41 +00:00
}
break;
2005-04-18 08:54:55 +00:00
case NCS_CALL: /*
* In this state we accept PASS and SERVER commands from
* the remote with the same token as we have sent.
*/
2006-05-25 16:37:52 +00:00
Syslog('r', "IBC: %s call", ncs_list[i].server);
if (strlen(ncs_list[i].passwd) == 0) {
Syslog('!', "IBC: no password configured for %s", ncs_list[i].server);
ncs_list[i].state = NCS_FAIL;
ncs_list[i].action = now + (time_t)300;
callchg = TRUE;
break;
}
2006-05-25 16:37:52 +00:00
ncs_list[i].token = gettoken();
2006-03-06 19:55:10 +00:00
p = calloc(512, sizeof(char));
2006-05-25 16:37:52 +00:00
snprintf(p, 512, "PASS %s 0100 %s\r\n", ncs_list[i].passwd, ncs_list[i].compress ? "Z":"");
send_msg(i, p);
snprintf(p, 512, "SERVER %s 0 %d mbsebbs %s %s\r\n", ncs_list[i].myname, ncs_list[i].token,
2005-04-18 15:19:39 +00:00
VERSION, CFG.bbs_name);
2006-05-25 16:37:52 +00:00
send_msg(i, p);
2006-03-06 19:55:10 +00:00
free(p);
2006-05-25 16:37:52 +00:00
ncs_list[i].action = now + (time_t)10;
ncs_list[i].state = NCS_WAITPWD;
2005-05-08 13:17:43 +00:00
callchg = TRUE;
2005-04-17 10:32:41 +00:00
break;
case NCS_WAITPWD: /*
* This state can be left by before the timeout is reached
* by a reply from the remote if the connection is accepted.
*/
2006-05-25 16:37:52 +00:00
Syslog('r', "IBC: %s waitpwd", ncs_list[i].server);
ncs_list[i].token = 0;
ncs_list[i].state = NCS_CALL;
2005-04-18 08:54:55 +00:00
while (TRUE) {
j = 1+(int) (1.0 * CFG.dialdelay * rand() / (RAND_MAX + 1.0));
if ((j > (CFG.dialdelay / 10)) && (j > 9))
break;
}
Syslog('r', "IBC: next call in %d %d seconds", CFG.dialdelay, j);
2006-05-25 16:37:52 +00:00
ncs_list[i].action = now + (time_t)j;
2005-05-08 13:17:43 +00:00
callchg = TRUE;
2005-04-17 10:32:41 +00:00
break;
2005-04-18 10:06:12 +00:00
case NCS_CONNECT: /*
* In this state we check if the connection is still alive
*/
2006-05-25 16:37:52 +00:00
j = (int)now - (int)ncs_list[i].last;
if (ncs_list[i].halfdead > 5) {
/*
* Halfdead means 5 times received a PASS while we are in
* connected state. This means the other side "thinks" it's
* not connected and tries to connect. This can be caused by
* temporary internet problems.
* Reset our side of the connection.
*/
2006-05-25 16:37:52 +00:00
Syslog('+', "IBC: server %s connection is half dead", ncs_list[i].server);
ncs_list[i].state = NCS_DEAD;
ncs_list[i].action = now + (time_t)60; // 1 minute delay before calling again.
ncs_list[i].gotpass = FALSE;
ncs_list[i].gotserver = FALSE;
ncs_list[i].token = 0;
ncs_list[i].halfdead = 0;
2006-03-06 16:34:26 +00:00
p = calloc(81, sizeof(char));
2006-05-25 16:37:52 +00:00
snprintf(p, 81, "SQUIT %s Connection died\r\n", ncs_list[i].server);
broadcast(ncs_list[i].server, p);
2006-03-06 16:34:26 +00:00
free(p);
callchg = TRUE;
srvchg = TRUE;
2006-05-25 16:37:52 +00:00
system_shout("*** NETWORK SPLIT, lost connection with server %s", ncs_list[i].server);
del_router(ncs_list[i].server);
break;
}
2006-05-25 16:37:52 +00:00
if (((int)now - (int)ncs_list[i].last) > 130) {
2005-04-23 10:58:43 +00:00
/*
* Missed 3 PING replies
*/
2006-05-25 16:37:52 +00:00
Syslog('+', "IBC: server %s connection is dead", ncs_list[i].server);
ncs_list[i].state = NCS_DEAD;
ncs_list[i].action = now + (time_t)120; // 2 minutes delay before calling again.
ncs_list[i].gotpass = FALSE;
ncs_list[i].gotserver = FALSE;
ncs_list[i].token = 0;
ncs_list[i].halfdead = 0;
2006-03-06 16:34:26 +00:00
p = calloc(81, sizeof(char));
2006-05-25 16:37:52 +00:00
snprintf(p, 81, "SQUIT %s Connection died\r\n", ncs_list[i].server);
broadcast(ncs_list[i].server, p);
2006-03-06 16:34:26 +00:00
free(p);
2005-05-08 13:17:43 +00:00
callchg = TRUE;
2005-05-01 13:12:41 +00:00
srvchg = TRUE;
2006-05-25 16:37:52 +00:00
system_shout("*** NETWORK SPLIT, lost connection with server %s", ncs_list[i].server);
del_router(ncs_list[i].server);
2005-04-18 11:52:53 +00:00
break;
2005-04-18 10:06:12 +00:00
}
2005-04-23 10:58:43 +00:00
/*
* Ping at 60, 90 and 120 seconds
*/
2006-05-25 16:37:52 +00:00
if (((int)now - (int)ncs_list[i].last) > 120) {
Syslog('r', "IBC: sending 3rd PING at 120 seconds");
2006-05-25 16:37:52 +00:00
send_msg(i, (char *)"PING\r\n");
} else if (((int)now - (int)ncs_list[i].last) > 90) {
Syslog('r', "IBC: sending 2nd PING at 90 seconds");
2006-05-25 16:37:52 +00:00
send_msg(i, (char *)"PING\r\n");
} else if (((int)now - (int)ncs_list[i].last) > 60) {
send_msg(i, (char *)"PING\r\n");
2005-04-18 10:06:12 +00:00
}
2006-05-25 16:37:52 +00:00
ncs_list[i].action = now + (time_t)10;
2005-04-18 10:06:12 +00:00
break;
2005-04-18 11:38:44 +00:00
2006-05-25 16:37:52 +00:00
case NCS_HANGUP: Syslog('r', "IBC: %s hangup => call", ncs_list[i].server);
ncs_list[i].action = now + (time_t)1;
ncs_list[i].state = NCS_CALL;
2005-05-08 13:17:43 +00:00
callchg = TRUE;
2005-05-01 13:12:41 +00:00
srvchg = TRUE;
2005-04-18 11:52:53 +00:00
break;
2006-05-25 16:37:52 +00:00
case NCS_DEAD: Syslog('r', "IBC: %s dead -> call", ncs_list[i].server);
ncs_list[i].action = now + (time_t)1;
ncs_list[i].state = NCS_CALL;
2005-05-08 13:17:43 +00:00
callchg = TRUE;
2005-05-01 13:12:41 +00:00
srvchg = TRUE;
2005-04-18 11:38:44 +00:00
break;
2005-04-18 12:18:41 +00:00
2006-05-25 16:37:52 +00:00
case NCS_FAIL: Syslog('r', "IBC: %s fail => init", ncs_list[i].server);
ncs_list[i].action = now + (time_t)1;
ncs_list[i].state = NCS_INIT;
2005-05-08 13:17:43 +00:00
callchg = TRUE;
2005-05-01 13:12:41 +00:00
srvchg = TRUE;
2005-04-18 12:18:41 +00:00
break;
2005-04-17 10:32:41 +00:00
}
}
}
2005-04-17 14:14:56 +00:00
dump_ncslist();
}
2006-05-25 16:37:52 +00:00
int command_pass(int slot, char *hostname, char *parameters)
2005-04-17 14:14:56 +00:00
{
2006-05-25 16:37:52 +00:00
char *passwd, *version, *lnk;
2005-04-18 08:54:55 +00:00
2006-05-25 16:37:52 +00:00
ncs_list[slot].gotpass = FALSE;
2005-04-18 08:54:55 +00:00
passwd = strtok(parameters, " \0");
version = strtok(NULL, " \0");
lnk = strtok(NULL, " \0");
if (strcmp(passwd, "0100") == 0) {
2006-05-25 16:37:52 +00:00
send_msg(slot, (char *)"414 PASS: Got empty password\r\n");
return 414;
}
2005-04-18 08:54:55 +00:00
if (version == NULL) {
2006-05-25 16:37:52 +00:00
send_msg(slot, (char *)"400 PASS: Not enough parameters\r\n");
2005-05-01 20:46:30 +00:00
return 400;
2005-04-18 08:54:55 +00:00
}
2006-05-25 16:37:52 +00:00
if (strcmp(passwd, ncs_list[slot].passwd)) {
2005-04-18 08:54:55 +00:00
Syslog('!', "IBC: got bad password %s from %s", passwd, hostname);
2005-04-27 18:02:30 +00:00
return 0;
2005-04-18 08:54:55 +00:00
}
2006-05-25 16:37:52 +00:00
if (ncs_list[slot].state == NCS_CONNECT) {
send_msg(slot, (char *)"401: PASS: Already registered\r\n");
ncs_list[slot].halfdead++; /* Count them */
srvchg = TRUE;
2005-05-01 20:46:30 +00:00
return 401;
}
2006-05-25 16:37:52 +00:00
ncs_list[slot].gotpass = TRUE;
ncs_list[slot].version = atoi(version);
2005-04-18 08:54:55 +00:00
if (lnk && strchr(lnk, 'Z'))
2006-05-25 16:37:52 +00:00
ncs_list[slot].compress = TRUE;
2005-04-27 18:02:30 +00:00
return 0;
2005-04-17 14:14:56 +00:00
}
2005-04-18 08:54:55 +00:00
2005-04-27 18:02:30 +00:00
int command_server(char *hostname, char *parameters)
2005-04-18 08:54:55 +00:00
{
2006-05-25 20:25:13 +00:00
char *p, *name, *hops, *prod, *vers, *fullname;
2005-10-11 20:49:41 +00:00
unsigned int token;
2006-05-25 16:37:52 +00:00
int i, j, ihops, found = FALSE;
2005-04-18 08:54:55 +00:00
name = strtok(parameters, " \0");
hops = strtok(NULL, " \0");
2006-05-25 20:25:13 +00:00
token = atoi(strtok(NULL, " \0"));
2005-04-18 15:19:38 +00:00
prod = strtok(NULL, " \0");
2005-04-18 15:26:10 +00:00
vers = strtok(NULL, " \0");
2005-04-18 15:19:38 +00:00
fullname = strtok(NULL, "\0");
ihops = atoi(hops) + 1;
2005-04-18 08:54:55 +00:00
2006-05-25 21:02:22 +00:00
/*
* Check if this is our neighbour server
*/
2006-05-25 20:53:49 +00:00
for (i = 0; i < MAXIBC_NCS; i++) {
2006-05-25 16:37:52 +00:00
if (strcmp(ncs_list[i].server, name) == 0) {
2005-04-18 18:08:07 +00:00
found = TRUE;
break;
}
}
2006-05-25 16:37:52 +00:00
if (found && fullname == NULL) {
send_msg(i, (char *)"400 SERVER: Not enough parameters\r\n");
2005-05-01 20:46:30 +00:00
return 400;
2005-04-18 08:54:55 +00:00
}
2006-05-25 16:37:52 +00:00
if (found && ncs_list[i].token) {
2005-04-18 08:54:55 +00:00
/*
* We are in calling state, so we expect the token from the
* remote is the same as the token we sent.
* In that case, the session is authorized.
*/
2006-05-25 16:37:52 +00:00
if (ncs_list[i].token == token) {
2006-03-06 16:34:26 +00:00
p = calloc(512, sizeof(char));
2006-05-25 20:25:13 +00:00
snprintf(p, 512, "SERVER %s %d %d %s %s %s\r\n", name, ihops, token, prod, vers, fullname);
2006-05-25 16:37:52 +00:00
broadcast(ncs_list[i].server, p);
2006-03-06 16:34:26 +00:00
free(p);
2005-04-23 11:25:32 +00:00
system_shout("* New server: %s, %s", name, fullname);
2006-05-25 16:37:52 +00:00
ncs_list[i].gotserver = TRUE;
2005-05-08 13:17:43 +00:00
callchg = TRUE;
2005-05-01 13:12:41 +00:00
srvchg = TRUE;
2006-05-25 16:37:52 +00:00
ncs_list[i].state = NCS_CONNECT;
ncs_list[i].action = now + (time_t)10;
Syslog('+', "IBC: connected with neighbour server: %s", ncs_list[i].server);
2005-04-18 18:22:09 +00:00
/*
* Send all already known servers
*/
2006-05-25 16:37:52 +00:00
for (j = 0; j < MAXIBC_SRV; j++) {
if (strlen(srv_list[j].server) && srv_list[j].hops) {
2006-03-06 19:55:10 +00:00
p = calloc(512, sizeof(char));
2006-05-25 16:37:52 +00:00
snprintf(p, 512, "SERVER %s %d 0 %s %s %s\r\n", srv_list[j].server,
srv_list[j].hops, srv_list[j].prod, srv_list[j].vers, srv_list[j].fullname);
send_msg(i, p);
2006-03-06 19:55:10 +00:00
free(p);
2005-04-18 18:22:09 +00:00
}
}
/*
2006-01-25 21:09:57 +00:00
* Send all known users, nicknames and join channels
*/
2006-05-25 16:37:52 +00:00
for (j = 0; j < MAXIBC_USR; j++) {
if (strlen(usr_list[j].server)) {
p = calloc(512, sizeof(char));
snprintf(p, 512, "USER %s@%s %s\r\n", usr_list[j].name, usr_list[j].server, usr_list[j].realname);
send_msg(i, p);
if (strcmp(usr_list[j].name, usr_list[j].nick)) {
snprintf(p, 512, "NICK %s %s %s %s\r\n", usr_list[j].nick,
usr_list[j].name, usr_list[j].server, usr_list[j].realname);
send_msg(i, p);
}
if (strlen(usr_list[j].channel)) {
snprintf(p, 512, "JOIN %s@%s %s\r\n", usr_list[j].name, usr_list[j].server, usr_list[j].channel);
send_msg(i, p);
}
free(p);
2006-03-06 19:55:10 +00:00
}
2006-01-25 21:09:57 +00:00
}
/*
* Send all known channel topics
*/
2006-05-25 16:37:52 +00:00
for (j = 0; j < MAXIBC_CHN; j++) {
if (strlen(chn_list[j].topic) && (strcmp(chn_list[j].server, CFG.myfqdn) == 0)) {
2006-03-06 19:55:10 +00:00
p = xstrcpy((char *)"TOPIC ");
2006-05-25 16:37:52 +00:00
p = xstrcat(p, chn_list[j].name);
2006-03-06 19:55:10 +00:00
p = xstrcat(p, (char *)" ");
2006-05-25 16:37:52 +00:00
p = xstrcat(p, chn_list[j].topic);
2006-03-06 19:55:10 +00:00
p = xstrcat(p, (char *)"\r\n");
2006-05-25 16:37:52 +00:00
send_msg(i, p);
2006-03-06 19:55:10 +00:00
free(p);
}
}
2006-05-25 16:37:52 +00:00
add_server(ncs_list[i].server, ihops, prod, vers, fullname, hostname);
2005-04-27 18:02:30 +00:00
return 0;
2005-04-18 08:54:55 +00:00
}
2006-05-25 16:37:52 +00:00
Syslog('r', "IBC: call collision with %s", ncs_list[i].server);
ncs_list[i].state = NCS_WAITPWD; /* Experimental, should fix state when state was connect while it wasn't. */
2005-04-27 18:02:30 +00:00
return 0;
2005-04-18 08:54:55 +00:00
}
/*
* We are in waiting state, so we sent our PASS and SERVER
* messages and set the session to connected if we got a
* valid PASS command.
*/
2006-05-25 16:37:52 +00:00
if (found && ncs_list[i].gotpass) {
2006-03-06 16:34:26 +00:00
p = calloc(512, sizeof(char));
2006-05-25 16:37:52 +00:00
snprintf(p, 512, "PASS %s 0100 %s\r\n", ncs_list[i].passwd, ncs_list[i].compress ? "Z":"");
send_msg(i, p);
snprintf(p, 512, "SERVER %s 0 %d mbsebbs %s %s\r\n", ncs_list[i].myname, token, VERSION, CFG.bbs_name);
send_msg(i, p);
2006-05-25 20:25:13 +00:00
snprintf(p, 512, "SERVER %s %d 0 %s %s %s\r\n", name, ihops, prod, vers, fullname);
2006-05-25 16:37:52 +00:00
broadcast(ncs_list[i].server, p);
2005-04-23 11:25:32 +00:00
system_shout("* New server: %s, %s", name, fullname);
2006-05-25 16:37:52 +00:00
ncs_list[i].gotserver = TRUE;
ncs_list[i].state = NCS_CONNECT;
ncs_list[i].action = now + (time_t)10;
Syslog('+', "IBC: connected with neighbour server: %s", ncs_list[i].server);
2005-04-18 18:22:09 +00:00
/*
* Send all already known servers
*/
2006-05-25 16:37:52 +00:00
for (j = 0; j < MAXIBC_SRV; j++) {
if (strlen(srv_list[j].server) && srv_list[j].hops) {
snprintf(p, 512, "SERVER %s %d 0 %s %s %s\r\n", srv_list[j].server,
srv_list[j].hops, srv_list[j].prod, srv_list[j].vers, srv_list[j].fullname);
send_msg(i, p);
2005-04-18 18:22:09 +00:00
}
}
/*
2005-04-27 18:53:30 +00:00
* Send all known users. If a user is in a channel, send a JOIN.
* If the user is one of our own and has set a channel topic, send it.
*/
2006-05-25 16:37:52 +00:00
for (j = 0; j < MAXIBC_USR; j++) {
2006-05-25 19:17:49 +00:00
if (strlen(usr_list[j].server)) {
snprintf(p, 512, "USER %s@%s %s\r\n", usr_list[j].name, usr_list[j].server, usr_list[j].realname);
2006-05-25 16:37:52 +00:00
send_msg(i, p);
2006-05-25 19:17:49 +00:00
if (strcmp(usr_list[j].name, usr_list[j].nick)) {
snprintf(p, 512, "NICK %s %s %s %s\r\n", usr_list[j].nick,
usr_list[j].name, usr_list[j].server, usr_list[j].realname);
send_msg(i, p);
}
if (strlen(usr_list[j].channel)) {
snprintf(p, 512, "JOIN %s@%s %s\r\n", usr_list[j].name, usr_list[j].server, usr_list[j].channel);
send_msg(i, p);
}
2006-03-06 19:55:10 +00:00
}
2006-01-25 21:09:57 +00:00
}
2006-03-06 19:55:10 +00:00
free(p);
2006-05-25 16:37:52 +00:00
for (j = 0; j < MAXIBC_CHN; j++) {
if (strlen(chn_list[j].topic) && (strcmp(chn_list[j].server, CFG.myfqdn) == 0)) {
2006-03-06 19:55:10 +00:00
p = xstrcpy((char *)"TOPIC ");
2006-05-25 16:37:52 +00:00
p = xstrcat(p, chn_list[j].name);
2006-03-06 19:55:10 +00:00
p = xstrcat(p, (char *)" ");
2006-05-25 16:37:52 +00:00
p = xstrcat(p, chn_list[j].topic);
2006-03-06 19:55:10 +00:00
p = xstrcat(p, (char *)"\r\n");
2006-05-25 16:37:52 +00:00
send_msg(i, p);
2006-03-06 19:55:10 +00:00
free(p);
}
}
2006-05-25 16:37:52 +00:00
add_server(ncs_list[i].server, ihops, prod, vers, fullname, hostname);
2005-05-01 13:12:41 +00:00
srvchg = TRUE;
2005-05-08 13:17:43 +00:00
callchg = TRUE;
2005-04-27 18:02:30 +00:00
return 0;
2005-04-18 08:54:55 +00:00
}
2005-04-18 18:08:07 +00:00
if (! found) {
/*
* Got a message about a server that is not our neighbour, could be a relayed server.
2005-04-18 18:08:07 +00:00
*/
2006-05-25 16:37:52 +00:00
if (add_server(name, ihops, prod, vers, fullname, hostname)) {
2006-03-06 16:34:26 +00:00
p = calloc(512, sizeof(char));
2006-05-25 20:25:13 +00:00
snprintf(p, 512, "SERVER %s %d 0 %s %s %s\r\n", name, ihops, prod, vers, fullname);
2006-03-06 16:34:26 +00:00
broadcast(hostname, p);
free(p);
srvchg = TRUE;
Syslog('+', "IBC: new relay server %s: %s", name, fullname);
system_shout("* New server: %s, %s", name, fullname);
}
2005-04-27 18:02:30 +00:00
return 0;
2005-04-18 18:08:07 +00:00
}
Syslog('r', "IBC: got SERVER command without PASS command from %s", hostname);
2005-04-27 18:02:30 +00:00
return 0;
2005-04-18 08:54:55 +00:00
}
2006-05-25 16:37:52 +00:00
int command_squit(int slot, char *hostname, char *parameters)
2005-04-18 11:38:44 +00:00
{
2006-05-25 16:37:52 +00:00
char *p, *name, *message;
2005-04-18 15:19:38 +00:00
2005-04-18 11:38:44 +00:00
name = strtok(parameters, " \0");
message = strtok(NULL, "\0");
2006-05-25 16:37:52 +00:00
if (strcmp(name, ncs_list[slot].server) == 0) {
2005-04-30 11:31:31 +00:00
Syslog('+', "IBC: disconnect neighbour server %s: %s", name, message);
2006-05-25 16:37:52 +00:00
ncs_list[slot].state = NCS_HANGUP;
ncs_list[slot].action = now + (time_t)120; // 2 minutes delay before calling again.
ncs_list[slot].gotpass = FALSE;
ncs_list[slot].gotserver = FALSE;
ncs_list[slot].token = 0;
del_router(name);
2005-04-18 12:56:28 +00:00
} else {
2005-04-30 11:31:31 +00:00
Syslog('+', "IBC: disconnect relay server %s: %s", name, message);
2006-05-25 16:37:52 +00:00
del_server(name);
2005-04-18 11:38:44 +00:00
}
2005-04-18 16:48:51 +00:00
2005-04-23 11:25:32 +00:00
system_shout("* Server %s disconnected: %s", name, message);
2006-03-06 16:34:26 +00:00
p = calloc(512, sizeof(char));
snprintf(p, 512, "SQUIT %s %s\r\n", name, message);
broadcast(hostname, p);
free(p);
2005-05-01 13:12:41 +00:00
srvchg = TRUE;
2005-04-27 18:02:30 +00:00
return 0;
2005-04-18 11:38:44 +00:00
}
2006-05-25 16:37:52 +00:00
int command_user(int slot, char *hostname, char *parameters)
2005-04-20 21:27:25 +00:00
{
2006-05-25 16:37:52 +00:00
char *p, *name, *server, *realname;
2005-04-20 21:27:25 +00:00
2005-04-22 18:39:48 +00:00
name = strtok(parameters, "@\0");
2005-04-20 21:27:25 +00:00
server = strtok(NULL, " \0");
realname = strtok(NULL, "\0");
if (realname == NULL) {
2006-05-25 16:37:52 +00:00
send_msg(slot, (char *)"400 USER: Not enough parameters\r\n");
2005-05-01 20:46:30 +00:00
return 400;
2005-04-20 21:27:25 +00:00
}
2006-05-25 16:37:52 +00:00
if (add_user(server, name, realname) == 0) {
2006-03-06 16:34:26 +00:00
p = calloc(512, sizeof(char));
snprintf(p, 512, "USER %s@%s %s\r\n", name, server, realname);
broadcast(hostname, p);
free(p);
2005-04-23 11:25:32 +00:00
system_shout("* New user %s@%s (%s)", name, server, realname);
2005-04-22 21:18:45 +00:00
}
2005-04-27 18:02:30 +00:00
return 0;
2005-04-20 21:27:25 +00:00
}
2006-05-25 16:37:52 +00:00
int command_quit(int slot, char *hostname, char *parameters)
2005-04-20 21:27:25 +00:00
{
2006-05-25 16:37:52 +00:00
char *p, *name, *server, *message;
2005-04-20 21:27:25 +00:00
2005-04-22 18:39:48 +00:00
name = strtok(parameters, "@\0");
2005-04-20 21:27:25 +00:00
server = strtok(NULL, " \0");
message = strtok(NULL, "\0");
if (server == NULL) {
2006-05-25 16:37:52 +00:00
send_msg(slot, (char *)"400 QUIT: Not enough parameters\r\n");
2005-05-01 20:46:30 +00:00
return 400;
2005-04-20 21:27:25 +00:00
}
2005-04-22 21:18:45 +00:00
if (message) {
2005-04-23 11:25:32 +00:00
system_shout("* User %s is leaving: %s", name, message);
2005-04-22 21:18:45 +00:00
} else {
2005-04-23 11:25:32 +00:00
system_shout("* User %s is leaving", name);
2005-04-22 21:18:45 +00:00
}
2006-05-25 16:37:52 +00:00
del_user(server, name);
2006-03-06 16:34:26 +00:00
p = calloc(512, sizeof(char));
snprintf(p, 512, "QUIT %s@%s %s\r\n", name, server, parameters);
broadcast(hostname, p);
free(p);
2005-04-27 18:02:30 +00:00
return 0;
2005-04-20 21:27:25 +00:00
}
2006-05-25 16:37:52 +00:00
int command_nick(int slot, char *hostname, char *parameters)
2005-04-22 19:40:05 +00:00
{
2006-05-25 16:37:52 +00:00
char *p, *nick, *name, *server, *realname;
2006-05-25 19:17:49 +00:00
int i, found, nickerror = FALSE;
2005-04-22 19:40:05 +00:00
nick = strtok(parameters, " \0");
name = strtok(NULL, " \0");
server = strtok(NULL, " \0");
realname = strtok(NULL, "\0");
if (realname == NULL) {
2006-05-25 16:37:52 +00:00
send_msg(slot, (char *)"400 NICK: Not enough parameters\r\n");
2005-04-22 19:40:05 +00:00
return 1;
}
2006-05-25 19:17:49 +00:00
/*
* Check nickname syntax, max 9 characters, first is alpha, rest alpha or digits.
*/
2005-04-22 19:40:05 +00:00
if (strlen(nick) > 9) {
2006-05-25 19:17:49 +00:00
nickerror = TRUE;
}
if (! nickerror) {
if (! isalpha(nick[0]))
nickerror = TRUE;
}
if (! nickerror) {
for (i = 1; i < strlen(nick); i++) {
if (! isalnum(nick[i])) {
nickerror = TRUE;
break;
}
}
}
if (nickerror) {
2006-03-06 19:55:10 +00:00
p = calloc(81, sizeof(char));
snprintf(p, 81, "402 %s: Erroneous nickname\r\n", nick);
2006-05-25 16:37:52 +00:00
send_msg(slot, p);
2006-03-06 19:55:10 +00:00
free(p);
2005-05-01 20:46:30 +00:00
return 402;
2005-04-22 19:40:05 +00:00
}
found = FALSE;
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_USR; i++) {
if ((strcmp(usr_list[i].name, nick) == 0) || (strcmp(usr_list[i].nick, nick) == 0)) {
2005-04-22 19:40:05 +00:00
found = TRUE;
break;
}
}
if (found) {
2006-03-06 19:55:10 +00:00
p = calloc(81, sizeof(char));
snprintf(p, 81, "403 %s: Nickname is already in use\r\n", nick);
2006-05-25 16:37:52 +00:00
send_msg(slot, p);
2006-03-06 19:55:10 +00:00
free(p);
2005-05-01 20:46:30 +00:00
return 403;
2005-04-22 19:40:05 +00:00
}
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_USR; i++) {
if ((strcmp(usr_list[i].server, server) == 0) &&
(strcmp(usr_list[i].realname, realname) == 0) && (strcmp(usr_list[i].name, name) == 0)) {
strncpy(usr_list[i].nick, nick, 9);
2005-04-22 19:40:05 +00:00
found = TRUE;
Syslog('+', "IBC: user %s set nick to %s", name, nick);
usrchg = TRUE;
}
}
if (!found) {
2006-03-06 19:55:10 +00:00
p = calloc(81, sizeof(char));
snprintf(p, 81, "404 %s@%s: Can't change nick\r\n", name, server);
2006-05-25 16:37:52 +00:00
send_msg(slot, p);
2006-03-06 19:55:10 +00:00
free(p);
2005-05-01 20:46:30 +00:00
return 404;
2005-04-22 19:40:05 +00:00
}
2006-03-06 16:34:26 +00:00
p = calloc(512, sizeof(char));
snprintf(p, 512, "NICK %s %s %s %s\r\n", nick, name, server, realname);
broadcast(hostname, p);
free(p);
2005-04-22 19:40:05 +00:00
return 0;
}
2006-05-25 16:37:52 +00:00
int command_join(int slot, char *hostname, char *parameters)
2005-04-23 15:35:39 +00:00
{
2006-03-06 16:34:26 +00:00
char *p, *nick, *server, *channel, msg[81];
2006-05-25 16:37:52 +00:00
int i, found;
2005-04-23 15:35:39 +00:00
2005-04-23 15:47:48 +00:00
nick = strtok(parameters, "@\0");
2005-04-23 15:35:39 +00:00
server = strtok(NULL, " \0");
channel = strtok(NULL, "\0");
if (channel == NULL) {
2006-05-25 16:37:52 +00:00
send_msg(slot, (char *)"400 JOIN: Not enough parameters\r\n");
2005-05-01 20:46:30 +00:00
return 400;
2005-04-23 15:35:39 +00:00
}
if (strlen(channel) > 20) {
2006-03-06 19:55:10 +00:00
p = calloc(81, sizeof(char));
snprintf(p, 81, "402 %s: Erroneous channelname\r\n", nick);
2006-05-25 16:37:52 +00:00
send_msg(slot, p);
2006-03-06 19:55:10 +00:00
free(p);
2005-05-01 20:46:30 +00:00
return 402;
2005-04-23 15:35:39 +00:00
}
if (strcasecmp(channel, "#sysop") == 0) {
Syslog('+', "IBC: ignored JOIN for #sysop channel");
return 0;
}
2005-04-23 15:35:39 +00:00
found = FALSE;
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_CHN; i++) {
if (strcmp(chn_list[i].name, channel) == 0) {
2005-04-23 15:35:39 +00:00
found = TRUE;
2006-05-25 16:37:52 +00:00
chn_list[i].users++;
2005-04-23 15:35:39 +00:00
break;
}
}
if (!found) {
Syslog('+', "IBC: create channel %s owned by %s@%s", channel, nick, server);
2006-05-25 16:37:52 +00:00
add_channel(channel, nick, server);
2005-04-27 20:54:13 +00:00
system_shout("* New channel %s created by %s@%s", channel, nick, server);
2005-04-23 15:35:39 +00:00
}
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_USR; i++) {
if ((strcmp(usr_list[i].server, server) == 0) &&
((strcmp(usr_list[i].nick, nick) == 0) || (strcmp(usr_list[i].name, nick) == 0))) {
strncpy(usr_list[i].channel, channel, 20);
2005-04-23 15:35:39 +00:00
Syslog('+', "IBC: user %s joined channel %s", nick, channel);
usrchg = TRUE;
2005-08-29 21:03:28 +00:00
snprintf(msg, 81, "* %s@%s has joined %s", nick, server, channel);
2005-04-27 20:54:13 +00:00
chat_msg(channel, NULL, msg);
2005-04-23 15:35:39 +00:00
}
}
2006-03-06 16:34:26 +00:00
p = calloc(512, sizeof(char));
snprintf(p, 512, "JOIN %s@%s %s\r\n", nick, server, channel);
broadcast(hostname, p);
free(p);
2005-04-23 15:35:39 +00:00
chnchg = TRUE;
2005-04-27 18:02:30 +00:00
return 0;
2005-04-23 15:35:39 +00:00
}
2006-05-25 16:37:52 +00:00
int command_part(int slot, char *hostname, char *parameters)
2005-04-23 15:35:39 +00:00
{
2006-03-06 16:34:26 +00:00
char *p, *nick, *server, *channel, *message, msg[81];
2006-05-25 16:37:52 +00:00
int i;
2005-04-23 15:35:39 +00:00
2005-04-23 15:47:48 +00:00
nick = strtok(parameters, "@\0");
2005-04-23 15:35:39 +00:00
server = strtok(NULL, " \0");
2005-04-24 12:14:39 +00:00
channel = strtok(NULL, " \0");
message = strtok(NULL, "\0");
2005-04-23 15:35:39 +00:00
if (channel == NULL) {
2006-05-25 16:37:52 +00:00
send_msg(slot, (char *)"400 PART: Not enough parameters\r\n");
2005-05-01 20:46:30 +00:00
return 400;
2005-04-23 15:35:39 +00:00
}
if (strcasecmp(channel, "#sysop") == 0) {
Syslog('+', "IBC: ignored PART from #sysop channel");
return 0;
}
del_userchannel(channel);
2005-04-23 15:35:39 +00:00
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_USR; i++) {
if ((strcmp(usr_list[i].server, server) == 0) &&
((strcmp(usr_list[i].nick, nick) == 0) || (strcmp(usr_list[i].name, nick) == 0))) {
usr_list[i].channel[0] = '\0';
2005-04-27 20:54:13 +00:00
if (message) {
2005-04-24 12:14:39 +00:00
Syslog('+', "IBC: user %s left channel %s: %s", nick, channel, message);
2006-02-13 19:26:30 +00:00
snprintf(msg, 81, "* %s@%s has left channel %s: %s", nick, server, channel, message);
2005-04-27 20:54:13 +00:00
} else {
2005-04-24 12:14:39 +00:00
Syslog('+', "IBC: user %s left channel %s", nick, channel);
2006-02-13 19:26:30 +00:00
snprintf(msg, 81, "* %s@%s has silently left channel %s", nick, server, channel);
2005-04-27 20:54:13 +00:00
}
chat_msg(channel, NULL, msg);
2005-04-23 15:35:39 +00:00
usrchg = TRUE;
}
}
2005-04-23 15:56:22 +00:00
2006-03-06 16:34:26 +00:00
p = xstrcpy((char *)"PART ");
p = xstrcat(p, nick);
p = xstrcat(p, (char *)"@");
p = xstrcat(p, server);
p = xstrcat(p, (char *)" ");
p = xstrcat(p, channel);
if (message) {
p = xstrcat(p, (char *)" ");
p = xstrcat(p, message);
}
p = xstrcat(p, (char *)"\r\n");
broadcast(hostname, p);
free(p);
2005-04-27 18:02:30 +00:00
return 0;
2005-04-23 15:35:39 +00:00
}
2006-05-25 16:37:52 +00:00
int command_topic(int slot, char *hostname, char *parameters)
2005-04-23 15:35:39 +00:00
{
2006-05-25 16:37:52 +00:00
char *p, *channel, *topic, msg[81];
int i;
2005-04-23 15:35:39 +00:00
channel = strtok(parameters, " \0");
topic = strtok(NULL, "\0");
if (topic == NULL) {
2006-05-25 16:37:52 +00:00
send_msg(slot, (char *)"400 TOPIC: Not enough parameters\r\n");
2005-05-01 20:46:30 +00:00
return 400;
2005-04-23 15:35:39 +00:00
}
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_CHN; i++) {
if (strcmp(chn_list[i].name, channel) == 0) {
2005-04-23 15:35:39 +00:00
chnchg = TRUE;
2006-05-25 16:37:52 +00:00
strncpy(chn_list[i].topic, topic, 54);
2005-04-23 15:35:39 +00:00
Syslog('+', "IBC: channel %s topic: %s", channel, topic);
2006-05-25 16:37:52 +00:00
snprintf(msg, 81, "* Channel topic is now: %s", chn_list[i].topic);
2005-04-27 20:54:13 +00:00
chat_msg(channel, NULL, msg);
2005-04-27 19:52:51 +00:00
break;
2005-04-23 15:35:39 +00:00
}
}
2005-04-23 15:56:22 +00:00
2006-03-06 16:34:26 +00:00
p = xstrcpy((char *)"TOPIC ");
p = xstrcat(p, channel);
p = xstrcat(p, (char *)" ");
p = xstrcat(p, topic);
p = xstrcat(p, (char *)"\r\n");
broadcast(hostname, p);
free(p);
2005-04-27 18:02:30 +00:00
return 0;
}
2005-04-27 19:52:51 +00:00
2006-05-25 16:37:52 +00:00
int command_privmsg(int slot, char *hostname, char *parameters)
2005-04-27 19:52:51 +00:00
{
2006-05-25 16:37:52 +00:00
char *p, *channel, *msg;
int i;
2005-04-27 19:52:51 +00:00
channel = strtok(parameters, " \0");
msg = strtok(NULL, "\0");
if (msg == NULL) {
2006-05-25 16:37:52 +00:00
send_msg(slot, (char *)"412 PRIVMSG: No text to send\r\n");
2005-04-27 19:52:51 +00:00
return 412;
}
if (channel[0] != '#') {
2006-05-25 16:37:52 +00:00
send_msg(slot, (char *)"499 PRIVMSG: Not for a channel\r\n"); // FIXME: also check users
2005-05-01 20:46:30 +00:00
return 499;
2005-04-27 19:52:51 +00:00
}
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_CHN; i++) {
if (strcmp(chn_list[i].name, channel) == 0) {
chn_list[i].lastmsg = now;
2005-04-27 19:52:51 +00:00
chat_msg(channel, NULL, msg);
2006-03-06 16:34:26 +00:00
p = xstrcpy((char *)"PRIVMSG ");
p = xstrcat(p, channel);
p = xstrcat(p, (char *)" ");
p = xstrcat(p, msg);
p = xstrcat(p, (char *)"\r\n");
broadcast(hostname, p);
free(p);
2005-04-27 19:52:51 +00:00
return 0;
}
}
2006-03-06 19:55:10 +00:00
p = calloc(81, sizeof(char));
snprintf(p, 81, "409 %s: Cannot sent to channel\r\n", channel);
2006-05-25 16:37:52 +00:00
send_msg(slot, p);
2006-03-06 19:55:10 +00:00
free(p);
2005-05-01 20:46:30 +00:00
return 409;
2005-04-27 19:52:51 +00:00
}
2005-04-27 18:02:30 +00:00
int do_command(char *hostname, char *command, char *parameters)
{
2006-05-25 16:37:52 +00:00
char *p;
int i, found = FALSE;
2006-03-06 19:55:10 +00:00
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_NCS; i++) {
if (strcmp(ncs_list[i].server, hostname) == 0) {
found = TRUE;
2005-04-27 18:02:30 +00:00
break;
}
}
2006-05-25 16:37:52 +00:00
if (! found) {
Syslog('!', "IBC: got a command from unknown %s", hostname);
return 0;
}
2005-04-27 18:02:30 +00:00
/*
* First the commands that don't have parameters
*/
if (! strcmp(command, (char *)"PING")) {
2006-05-25 16:37:52 +00:00
send_msg(i, (char *)"PONG\r\n");
2005-04-27 18:02:30 +00:00
return 0;
}
2006-05-25 16:37:52 +00:00
2005-04-27 18:02:30 +00:00
if (! strcmp(command, (char *)"PONG")) {
/*
* Just accept, but reset halfdead counter.
2005-04-27 18:02:30 +00:00
*/
2006-05-25 16:37:52 +00:00
if (ncs_list[i].halfdead) {
Syslog('r', "IBC: Reset halfdead counter");
2006-05-25 16:37:52 +00:00
ncs_list[i].halfdead = 0;
srvchg = TRUE;
}
2005-04-27 18:02:30 +00:00
return 0;
}
/*
* Commands with parameters
*/
if (parameters == NULL) {
2006-03-06 19:55:10 +00:00
p = calloc(81, sizeof(char));
snprintf(p, 81, "400 %s: Not enough parameters\r\n", command);
2006-05-25 16:37:52 +00:00
send_msg(i, p);
2006-03-06 19:55:10 +00:00
free(p);
2005-05-01 20:46:30 +00:00
return 400;
2005-04-27 18:02:30 +00:00
}
if (! strcmp(command, (char *)"PASS")) {
2006-05-25 16:37:52 +00:00
return command_pass(i, hostname, parameters);
2005-04-27 18:02:30 +00:00
}
if (! strcmp(command, (char *)"SERVER")) {
return command_server(hostname, parameters);
}
if (! strcmp(command, (char *)"SQUIT")) {
2006-05-25 16:37:52 +00:00
return command_squit(i, hostname, parameters);
2005-04-27 18:02:30 +00:00
}
if (! strcmp(command, (char *)"USER")) {
2006-05-25 16:37:52 +00:00
return command_user(i, hostname, parameters);
2005-04-27 18:02:30 +00:00
}
if (! strcmp(command, (char *)"QUIT")) {
2006-05-25 16:37:52 +00:00
return command_quit(i, hostname, parameters);
2005-04-27 18:02:30 +00:00
}
if (! strcmp(command, (char *)"NICK")) {
2006-05-25 16:37:52 +00:00
return command_nick(i, hostname, parameters);
2005-04-27 20:26:53 +00:00
}
2005-04-27 20:31:54 +00:00
if (! strcmp(command, (char *)"JOIN")) {
2006-05-25 16:37:52 +00:00
return command_join(i, hostname, parameters);
2005-04-27 20:26:53 +00:00
}
2005-04-27 18:02:30 +00:00
if (! strcmp(command, (char *)"PART")) {
2006-05-25 16:37:52 +00:00
return command_part(i, hostname, parameters);
2005-04-27 18:02:30 +00:00
}
if (! strcmp(command, (char *)"TOPIC")) {
2006-05-25 16:37:52 +00:00
return command_topic(i, hostname, parameters);
2005-04-27 18:02:30 +00:00
}
2005-04-27 19:52:51 +00:00
if (! strcmp(command, (char *)"PRIVMSG")) {
2006-05-25 16:37:52 +00:00
return command_privmsg(i, hostname, parameters);
2005-04-27 19:52:51 +00:00
}
2005-04-27 18:02:30 +00:00
2006-03-06 19:55:10 +00:00
p = calloc(81, sizeof(char));
snprintf(p, 81, "413 %s: Unknown command\r\n", command);
2006-05-25 16:37:52 +00:00
send_msg(i, p);
2006-03-06 19:55:10 +00:00
free(p);
2005-05-01 20:46:30 +00:00
return 413;
2005-04-23 15:35:39 +00:00
}
2006-02-13 19:26:30 +00:00
void ibc_receiver(char *crbuf)
2005-04-17 14:14:56 +00:00
{
struct hostent *hp, *tp;
struct in_addr in;
2006-05-25 16:37:52 +00:00
int inlist, i;
char *hostname, *command, *parameters, *ipaddress;
2005-04-17 14:14:56 +00:00
2006-02-13 19:26:30 +00:00
hp = gethostbyaddr((char *)&clientaddr_in.sin_addr, sizeof(struct in_addr), clientaddr_in.sin_family);
if (hp == NULL)
hostname = inet_ntoa(clientaddr_in.sin_addr);
else
hostname = hp->h_name;
2005-04-17 14:14:56 +00:00
2006-02-13 19:26:30 +00:00
if ((crbuf[strlen(crbuf) -2] != '\r') && (crbuf[strlen(crbuf) -1] != '\n')) {
Syslog('!', "IBC: got message not terminated with CR-LF, dropped");
2005-04-17 14:14:56 +00:00
return;
2005-05-08 17:52:53 +00:00
}
2006-02-13 19:26:30 +00:00
/*
2006-05-22 12:09:15 +00:00
* First check for a fixed IP address.
2006-02-13 19:26:30 +00:00
*/
inlist = FALSE;
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_NCS; i++) {
if (strcmp(ncs_list[i].server, hostname) == 0) {
2006-02-13 19:26:30 +00:00
inlist = TRUE;
break;
}
}
if (!inlist) {
/*
* Check for dynamic dns address
*/
ipaddress = xstrcpy(inet_ntoa(clientaddr_in.sin_addr));
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_NCS; i++) {
if (strlen(ncs_list[i].server) && ncs_list[i].dyndns) {
tp = gethostbyname(ncs_list[i].server);
2006-02-13 19:26:30 +00:00
if (tp != NULL) {
memcpy(&in, tp->h_addr, tp->h_length);
if (strcmp(inet_ntoa(in), ipaddress) == 0) {
/*
* Test if the backresolved dynamic DNS name is changed, but exclude the
* initial value which is the same as the real server name.
*/
2006-05-25 16:37:52 +00:00
if (strcmp(ncs_list[i].resolved, hostname) && strcmp(ncs_list[i].resolved, ncs_list[i].server)) {
2006-02-13 19:26:30 +00:00
Syslog('r', "IBC: GrepThiz old resolved %s new resolved %s state %s",
2006-05-25 16:37:52 +00:00
ncs_list[i].resolved, hostname, ncsstate[ncs_list[i].state]);
Syslog('+', "IBC: server %s resolved FQDN changed, restarting", ncs_list[i].server);
ncs_list[i].crc--;
2006-02-13 19:26:30 +00:00
link_reset = TRUE;
/*
* This would be the moment to reset this neighbour
* Double check state: waitpwd or call ?
*/
}
2006-02-13 19:26:30 +00:00
/*
* Store the back resolved IP fqdn for reference and change the
* FQDN to the one from the setup, so we continue to use the
* dynamic FQDN.
*/
2006-05-25 16:37:52 +00:00
if (strcmp(ncs_list[i].resolved, hostname))
Syslog('r', "IBC: setting '%s' to dynamic dns '%s'", hostname, ncs_list[i].server);
strncpy(ncs_list[i].resolved, hostname, 63);
2006-02-13 19:26:30 +00:00
inlist = TRUE;
2006-05-25 16:37:52 +00:00
hostname = ncs_list[i].server;
2006-02-13 19:26:30 +00:00
break;
}
}
2005-04-17 14:14:56 +00:00
}
}
2006-02-13 19:26:30 +00:00
free(ipaddress);
2005-04-17 14:14:56 +00:00
}
2006-02-13 19:26:30 +00:00
if (!inlist) {
Syslog('r', "IBC: message from unknown host (%s), dropped", hostname);
return;
2005-04-16 16:08:32 +00:00
}
2006-05-25 16:37:52 +00:00
if (ncs_list[i].state == NCS_INIT) {
2006-02-13 19:26:30 +00:00
Syslog('r', "IBC: message received from %s while in init state, dropped", hostname);
return;
}
2006-05-25 16:37:52 +00:00
ncs_list[i].last = now;
2006-02-13 19:26:30 +00:00
crbuf[strlen(crbuf) -2] = '\0';
#ifndef PING_PONG_LOG
if (strcmp(crbuf, (char *)"PING") && strcmp(crbuf, (char *)"PONG"))
#endif
Syslog('r', "IBC: < %s: \"%s\"", hostname, printable(crbuf, 0));
2006-02-13 19:26:30 +00:00
/*
* Parse message
*/
command = strtok(crbuf, " \0");
parameters = strtok(NULL, "\0");
2005-04-17 10:32:41 +00:00
2006-02-13 19:26:30 +00:00
if (atoi(command)) {
Syslog('r', "IBC: Got error %d", atoi(command));
} else {
do_command(hostname, command, parameters);
2005-04-17 10:32:41 +00:00
}
2006-02-13 19:26:30 +00:00
}
2005-04-17 10:32:41 +00:00
2005-04-15 21:36:44 +00:00
2006-05-25 16:37:52 +00:00
void ibc_init(void)
{
memset(&ncs_list, 0, sizeof(ncs_list));
memset(&srv_list, 0, sizeof(srv_list));
2006-05-25 19:17:49 +00:00
memset(&usr_list, 0, sizeof(usr_list));
memset(&chn_list, 0, sizeof(chn_list));
2006-05-25 16:37:52 +00:00
}
2006-02-13 19:26:30 +00:00
void ibc_shutdown(void)
{
2006-05-25 16:37:52 +00:00
char *p;
int i;
2005-04-18 15:19:38 +00:00
2006-02-13 19:26:30 +00:00
Syslog('r', "IBC: start shutdown connections");
2005-04-17 10:32:41 +00:00
2006-05-25 19:17:49 +00:00
p = calloc(512, sizeof(char));
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_USR; i++) {
if (strcmp(usr_list[i].server, CFG.myfqdn) == 0) {
2006-02-13 19:26:30 +00:00
/*
* Our user, still connected
*/
2006-05-25 16:37:52 +00:00
if (strlen(usr_list[i].channel) && strcmp(usr_list[i].channel, "#sysop")) {
2006-02-13 19:26:30 +00:00
/*
* In a channel
*/
2006-05-25 16:37:52 +00:00
snprintf(p, 512, "PART %s@%s %s System shutdown\r\n", usr_list[i].nick, usr_list[i].server, usr_list[i].channel);
2006-03-06 16:34:26 +00:00
broadcast((char *)"foobar", p);
2006-02-13 19:26:30 +00:00
}
2006-05-25 16:37:52 +00:00
snprintf(p, 512, "QUIT %s@%s System shutdown\r\n", usr_list[i].nick, usr_list[i].server);
2006-03-06 16:34:26 +00:00
broadcast((char *)"foobar", p);
2006-02-13 19:26:30 +00:00
}
2005-04-15 21:36:44 +00:00
}
2006-05-25 16:37:52 +00:00
for (i = 0; i < MAXIBC_NCS; i++) {
if (strlen(ncs_list[i].server) && ncs_list[i].state == NCS_CONNECT) {
snprintf(p, 512, "SQUIT %s System shutdown\r\n", ncs_list[i].myname);
send_msg(i, p);
2005-04-18 11:43:16 +00:00
}
}
2006-03-06 19:55:10 +00:00
free(p);
2005-04-15 21:36:44 +00:00
}