init
This commit is contained in:
291
ircd/Makefile
Normal file
291
ircd/Makefile
Normal file
@@ -0,0 +1,291 @@
|
||||
#************************************************************************
|
||||
#* IRC - Internet Relay Chat, ircd/Makefile
|
||||
#* Copyright (C) 1990 Jarkko Oikarinen
|
||||
#*
|
||||
#* This program is free software; you can redistribute it and/or modify
|
||||
#* it under the terms of the GNU General Public License as published by
|
||||
#* the Free Software Foundation; either version 1, or (at your option)
|
||||
#* any later version.
|
||||
#*
|
||||
#* This program is distributed in the hope that it will be useful,
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
#* GNU General Public License for more details.
|
||||
#*
|
||||
#* You should have received a copy of the GNU General Public License
|
||||
#* along with this program; if not, write to the Free Software
|
||||
#* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#*/
|
||||
|
||||
CC=cc
|
||||
RM=/bin/rm
|
||||
CP=/bin/cp
|
||||
TOUCH=touch
|
||||
SHELL=/bin/sh
|
||||
INSTALL=/usr/bin/install
|
||||
|
||||
# IRCDMODE given in top level Makefile, but added here to make sure
|
||||
# compilation works if started in ircd subdirectory
|
||||
|
||||
IRCDMODE=711
|
||||
INCLUDEDIR=../include
|
||||
|
||||
# CFLAGS/IRCDLIBS used in ../Makefile should also be used here. The list
|
||||
# given below is less than complete.
|
||||
# For MIPS, use the following:
|
||||
#CFLAGS= -g -systype bsd43 -DSYSTYPE_BSD43 -I${INCLUDEDIR}
|
||||
# For Irix 4.x (SGI), use the following:
|
||||
#CFLAGS= -g -cckr -I$(INCLUDEDIR)
|
||||
# else just this
|
||||
CFLAGS= -g -I${INCLUDEDIR}
|
||||
#
|
||||
# use the following on SUN OS without nameserver libraries inside libc
|
||||
# NOTE: most dont have the resolver libraries inside libc
|
||||
#IRCDLIBS=-lresolv
|
||||
#
|
||||
#on NeXT other than 2.0:
|
||||
#IRCDLIBS=-lsys_s
|
||||
#
|
||||
# HPUX:
|
||||
#IRCDLIBS=-lBSD
|
||||
#
|
||||
# Solaris 2
|
||||
#IRCDLIBS=-lsocket -lnsl
|
||||
#
|
||||
# ESIX
|
||||
#CFLAGS=-O -I${INCLUDEDIR} -I/usr/ucbinclude
|
||||
#IRCDLIBS=-L/usr/ucblib -L/usr/lib -lsocket -lucb -lns -lnsl
|
||||
#
|
||||
#When profiling:
|
||||
#IRCDLIBS=-lc_p
|
||||
|
||||
LINTFLAGS=-hba
|
||||
#
|
||||
# LDFLAGS - flags to send the loader (ld). SunOS users may want to add
|
||||
# -Bstatic here.
|
||||
#
|
||||
#LDFLAGS=-Bstatic
|
||||
#LDFLAGS=-Wl,-a,archive
|
||||
#
|
||||
# RES - if you are missing the resolv library (man 5 resolv.conf), or you
|
||||
# experience probems with ip# to hostname lookups for local machines or
|
||||
# the server wont compile because _res is missing, uncomment RES.
|
||||
# For those who know what these are, if you normally use the resolv+
|
||||
# libraries and have setup /etc/resolv.conf, these are fromm resolv+ if they
|
||||
# are not part of your system libraries. In all cases you should try your
|
||||
# system libraries before these.
|
||||
#
|
||||
#RES=res_init.o res_comp.o res_mkquery.o
|
||||
|
||||
COMMONOBJS=../common/bsd.o ../common/dbuf.o ../common/packet.o \
|
||||
../common/send.o ../common/match.o ../common/parse.o \
|
||||
../common/support.o
|
||||
|
||||
OBJS=channel.o class.o hash.o ircd.o list.o res.o s_auth.o s_bsd.o s_conf.o \
|
||||
s_debug.o s_err.o s_misc.o s_numeric.o s_serv.o s_user.o whowas.o \
|
||||
note.o userload.o crule.o s_ping.o map.o random.o $(RES) $(COMMONOBJS)
|
||||
|
||||
SRC=$(OBJS:%.o=%.c)
|
||||
|
||||
COMMONSRC=$(COMMONOBJS:%.o=%.c)
|
||||
|
||||
MAKE = make 'CFLAGS=${CFLAGS}' 'CC=${CC}' 'IRCDLIBS=${IRCDLIBS}' \
|
||||
'LDFLAGS=${LDFLAGS}' 'IRCDMODE=${IRCDMODE}'
|
||||
|
||||
|
||||
all: build
|
||||
|
||||
build: ircd chkconf
|
||||
|
||||
ircd: $(OBJS) ../include/patchlevel.h
|
||||
$(SHELL) version.c.SH
|
||||
$(CC) $(CFLAGS) -c version.c
|
||||
$(CC) $(CFLAGS) $(OBJS) version.o $(LDFLAGS) $(IRCDLIBS) -o ircd
|
||||
chmod $(IRCDMODE) ircd
|
||||
|
||||
chkconf: ../include/struct.h ../include/config.h ../include/sys.h \
|
||||
../include/common.h crule.c chkconf.c
|
||||
$(CC) $(CFLAGS) -DCR_CHKCONF -o chkcrule.o -c crule.c
|
||||
$(CC) $(CFLAGS) chkconf.c ../common/match.o chkcrule.o \
|
||||
$(LDFLAGS) $(IRCDLIBS) -o chkconf
|
||||
|
||||
saber: $(SRC)
|
||||
#load -I../include $(SRC) $(COMMONSRC) version.c $(IRCDLIBS)
|
||||
|
||||
lint:
|
||||
lint $(LINTFLAGS) -I../include $(SRC) | egrep -v 'sendto_|debug'
|
||||
|
||||
../common/parse.o: ../common/parse.c ../include/msg.h ../include/config.h\
|
||||
../include/struct.h ../include/sys.h ../include/numeric.h
|
||||
(cd ../common; $(MAKE) build);
|
||||
../common/bsd.o: ../common/bsd.c ../include/config.h ../include/common.h\
|
||||
../include/struct.h ../include/sys.h
|
||||
(cd ../common; $(MAKE) build);
|
||||
../common/dbuf.o: ../common/dbuf.c ../include/config.h ../include/common.h\
|
||||
../include/struct.h ../include/dbuf.h
|
||||
(cd ../common; $(MAKE) build);
|
||||
../common/packet.o: ../common/packet.c ../include/config.h ../include/common.h\
|
||||
../include/struct.h ../include/msg.h
|
||||
(cd ../common; $(MAKE) build);
|
||||
../common/send.o: ../common/send.c ../include/config.h ../include/common.h\
|
||||
../include/struct.h ../include/sys.h
|
||||
(cd ../common; $(MAKE) build);
|
||||
../common/match.o: ../common/match.c ../include/config.h ../include/common.h\
|
||||
../include/sys.h
|
||||
(cd ../common; $(MAKE) build);
|
||||
../common/support.o: ../common/support.c ../include/config.h ../include/sys.h\
|
||||
../include/common.h
|
||||
(cd ../common; $(MAKE) build);
|
||||
|
||||
install: all
|
||||
-if [ ! -d ${IRCDDIR} -a ! -f ${IRCDDIR} ] ; then \
|
||||
mkdir ${IRCDDIR}; \
|
||||
fi
|
||||
../bsdinstall -c -s -m ${IRCDMODE} ircd ${BINDIR}
|
||||
../bsdinstall -c -s -m 700 chkconf ${BINDIR}
|
||||
$(CP) ../doc/example.conf ${IRCDDIR}
|
||||
$(TOUCH) ${IRCDDIR}/ircd.motd
|
||||
$(RM) -f ${IRCDDIR}/ircd.m4
|
||||
$(TOUCH) ${IRCDDIR}/ircd.m4
|
||||
chmod +x buildm4
|
||||
./buildm4 ${IRCDDIR}
|
||||
|
||||
clean:
|
||||
$(RM) -f *.o *~ core ircd version.c \#* *.bak chkconf *.orig
|
||||
|
||||
depend:
|
||||
makedepend -I${INCLUDEDIR} ${SRC}
|
||||
|
||||
channel.o: ../include/struct.h ../include/config.h ../include/dbuf.h \
|
||||
../include/numeric.h ../include/channel.h ../include/sys.h \
|
||||
../include/common.h
|
||||
$(CC) $(CFLAGS) -c channel.c
|
||||
|
||||
class.o: ../include/struct.h ../include/class.h ../include/numeric.h \
|
||||
../include/common.h ../include/config.h ../include/sys.h
|
||||
$(CC) $(CFLAGS) -c class.c
|
||||
|
||||
ircd.o: ircd.c ../include/struct.h ../include/config.h ../include/sys.h \
|
||||
../include/dbuf.h ../include/numeric.h ../include/common.h
|
||||
$(CC) $(CFLAGS) -c ircd.c
|
||||
|
||||
list.o: list.c ../include/struct.h ../include/config.h ../include/dbuf.h \
|
||||
../include/sys.h ../include/common.h
|
||||
$(CC) $(CFLAGS) -c list.c
|
||||
|
||||
res.o: res.c ../include/struct.h ../include/config.h ../include/res.h \
|
||||
../include/sys.h ../include/common.h
|
||||
$(CC) $(CFLAGS) -c res.c
|
||||
|
||||
s_bsd.o: s_bsd.c ../include/struct.h ../include/config.h ../include/dbuf.h \
|
||||
../include/sys.h ../include/common.h
|
||||
$(CC) $(CFLAGS) -c s_bsd.c
|
||||
|
||||
s_auth.o: s_auth.c ../include/struct.h ../include/config.h ../include/dbuf.h \
|
||||
../include/sys.h ../include/common.h
|
||||
$(CC) $(CFLAGS) -c s_auth.c
|
||||
|
||||
s_conf.o: s_conf.c ../include/struct.h ../include/config.h ../include/sys.h \
|
||||
../include/common.h ../include/numeric.h ../include/dbuf.h
|
||||
$(CC) $(CFLAGS) -c s_conf.c
|
||||
|
||||
s_debug.o: ../include/config.h ../include/struct.h ../include/common.h \
|
||||
../include/sys.h s_debug.c
|
||||
$(CC) $(CFLAGS) -c s_debug.c
|
||||
|
||||
s_err.o: ../include/config.h ../include/struct.h ../include/common.h \
|
||||
../include/sys.h ../include/numeric.h ../include/msg.h s_err.c
|
||||
$(CC) $(CFLAGS) -c s_err.c
|
||||
|
||||
s_misc.o: s_misc.c ../include/struct.h ../include/config.h ../include/dbuf.h \
|
||||
../include/common.h ../include/sys.h ../include/numeric.h
|
||||
$(CC) $(CFLAGS) -c s_misc.c
|
||||
|
||||
s_user.o: s_user.c ../include/struct.h ../include/config.h ../include/sys.h \
|
||||
../include/common.h ../include/dbuf.h ../include/channel.h \
|
||||
../include/msg.h ../include/numeric.h ../include/whowas.h
|
||||
$(CC) $(CFLAGS) -c s_user.c
|
||||
|
||||
s_serv.o: s_serv.c ../include/struct.h ../include/config.h ../include/sys.h \
|
||||
../include/common.h ../include/dbuf.h ../include/channel.h \
|
||||
../include/msg.h ../include/numeric.h ../include/whowas.h
|
||||
$(CC) $(CFLAGS) -c s_serv.c
|
||||
|
||||
s_numeric.o: s_numeric.c ../include/config.h ../include/sys.h \
|
||||
../include/common.h ../include/struct.h ../include/dbuf.h \
|
||||
../include/numeric.h
|
||||
$(CC) $(CFLAGS) -c s_numeric.c
|
||||
|
||||
whowas.o: ../include/struct.h ../include/config.h ../include/sys.h \
|
||||
../include/common.h ../include/dbuf.h ../include/numeric.h \
|
||||
../include/whowas.h whowas.c
|
||||
$(CC) $(CFLAGS) -c whowas.c
|
||||
|
||||
hash.o: ../include/struct.h ../include/sys.h ../include/hash.h hash.c \
|
||||
../include/common.h ../include/config.h s_bsd.c s_serv.c s_user.c \
|
||||
channel.c s_misc.c
|
||||
@crypt/sums
|
||||
$(CC) $(CFLAGS) -c hash.c
|
||||
@/bin/rm -f hash.c
|
||||
@/bin/mv -f hash.c.old hash.c
|
||||
@touch hash.o
|
||||
|
||||
note.o: ../include/struct.h ../include/sys.h ../include/common.h \
|
||||
../include/config.h note.c
|
||||
$(CC) $(CFLAGS) -c note.c
|
||||
|
||||
crule.o: ../include/struct.h ../include/sys.h ../include/common.h \
|
||||
../include/config.h crule.c
|
||||
$(CC) $(CFLAGS) -c crule.c
|
||||
|
||||
s_ping.o: ../include/struct.h ../include/sys.h ../include/common.h \
|
||||
../include/config.h s_ping.c
|
||||
$(CC) $(CFLAGS) -c s_ping.c
|
||||
|
||||
random.o: ../include/struct.h ../include/sys.h random.c
|
||||
$(CC) $(CFLAGS) -c random.c
|
||||
|
||||
map.o: ../include/struct.h ../include/sys.h map.c
|
||||
$(CC) $(CFLAGS) -c map.c
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
||||
|
||||
channel.o: ../include/struct.h ../include/config.h ../include/dbuf.h
|
||||
channel.o: ../include/numeric.h ../include/channel.h channel.c
|
||||
s_misc.o: ../include/struct.h ../include/config.h ../include/dbuf.h s_misc.c
|
||||
ircd.o: ../include/struct.h ../include/config.h
|
||||
ircd.o: ../include/dbuf.h ../include/numeric.h ircd.c
|
||||
list.o: ../include/struct.h ../include/config.h ../include/dbuf.h
|
||||
list.o: ../include/sys.h list.c
|
||||
note.o: ../include/config.h note.c
|
||||
res.o: ../include/struct.h ../include/config.h ../include/res.h res.c
|
||||
s_bsd.o: ../include/struct.h ../include/config.h ../include/dbuf.h
|
||||
s_bsd.o: ../include/sys.h s_bsd.c
|
||||
s_auth.o: ../include/struct.h ../include/config.h ../include/dbuf.h
|
||||
s_auth.o: ../include/sys.h s_auth.c
|
||||
s_debug.o: ../include/config.h ../include/struct.h ../include/common.h
|
||||
s_debug.o: ../include/sys.h s_debug.c
|
||||
s_debug.o: ../include/struct.h ../include/common.h ../include/sys.h
|
||||
s_err.o: ../include/struct.h ../include/config.h ../include/numeric.h
|
||||
s_err.o: ../include/dbuf.h ../include/sys.h s_err.c
|
||||
s_conf.o: ../include/struct.h ../include/config.h ../include/numeric.h
|
||||
s_conf.o: ../include/dbuf.h ../include/sys.h s_conf.c
|
||||
s_user.o: ../include/struct.h ../include/config.h
|
||||
s_user.o: ../include/dbuf.h ../include/sys.h ../include/channel.h
|
||||
s_user.o: ../include/msg.h ../include/numeric.h ../include/whowas.h s_user.c
|
||||
s_serv.o: ../include/struct.h ../include/config.h
|
||||
s_serv.o: ../include/dbuf.h ../include/sys.h ../include/channel.h
|
||||
userload.o: ../include/common.h ../include/config.h ../include/userload.h
|
||||
s_serv.o: ../include/msg.h ../include/numeric.h ../include/whowas.h s_serv.c
|
||||
s_numeric.o: ../include/config.h ../include/sys.h ../include/struct.h
|
||||
s_numeric.o: ../include/dbuf.h ../include/numeric.h s_numeric.c
|
||||
whowas.o: ../include/struct.h ../include/config.h ../include/dbuf.h
|
||||
whowas.o: ../include/numeric.h ../include/whowas.h ../include/sys.h whowas.c
|
||||
class.o: ../include/struct.h ../include/class.h ../include/numeric.h
|
||||
class.o: ../include/common.h ../include/config.h class.c
|
||||
hash.o: ../include/config.h ../include/sys.h ../include/hash.h
|
||||
hash.o: ../include/struct.h ../include/common.h s_serv.c s_user.c
|
||||
hash.o: channel.c s_misc.c s_bsd.c ircd.c hash.c version.c.SH
|
||||
version.o: version.c.SH version.c
|
||||
crule.o: ../include/config.h ../include/sys.h ../include/struct.h
|
||||
crule.o: ../include/common.h
|
||||
84
ircd/buildm4
Executable file
84
ircd/buildm4
Executable file
@@ -0,0 +1,84 @@
|
||||
#!/bin/sh
|
||||
# IRC - Internet Relay Chat, ircd/buildm4
|
||||
# Copyright (C) 1993 Darren Reed
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 1, or (at your option)
|
||||
# any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#
|
||||
# If only this was a perl script...*sigh*
|
||||
#
|
||||
IRCDDIR=$1
|
||||
M4=$IRCDDIR/ircd.m4
|
||||
/bin/rm -f $M4
|
||||
egrep "^#def[^P]*PATCHLEVEL" ../include/patchlevel.h | \
|
||||
sed -e 's/[^\"]*\"\([^\"]*\)\"/define(VERSION,\1)/' >>$M4
|
||||
DEBUG=`egrep "^#define[ ]*DEBUGMODE" ../include/config.h`
|
||||
if [ -n "$DEBUG" ] ; then
|
||||
echo "define(DEBUGMODE,1)" >>$M4
|
||||
else
|
||||
echo "undefine(DEBUGMODE)" >>$M4
|
||||
fi
|
||||
echo -n "define(HOSTNAME," >> $M4
|
||||
echo "`hostname`" | sed -e 's/\([a-zA-Z0-9\-]*\).*/\1)/' >> $M4
|
||||
echo "define(USER,$USER)" >>$M4
|
||||
echo -n 'define(PORT,' >>$M4
|
||||
PORT=`egrep '^#define[ ]*PORT[ ]*[0-9]*' ../include/config.h`
|
||||
echo "$PORT" | sed -e 's/[^0-9]*\([0-9]*\).*/\1)/' >> $M4
|
||||
echo -n 'define(PFREQ,' >>$M4
|
||||
PING=`egrep '^#define[ ]*PINGFREQUENCY[ ]*[0-9]*' ../include/config.h`
|
||||
echo "$PING" | sed -e 's/[^0-9]*\([0-9]*\).*/\1)/' >> $M4
|
||||
echo -n 'define(CFREQ,' >>$M4
|
||||
CONT=`egrep '^#define[ ]*CONNECTFREQUENCY[ ]*[0-9]*' ../include/config.h`
|
||||
echo "$CONT" | sed -e 's/[^0-9]*\([0-9]*\).*/\1)/' >> $M4
|
||||
echo -n "define(MAXSENDQ," >>$M4
|
||||
MAXQ=`egrep '^#define[ ]*MAXSENDQLENGTH[ ]*[0-9]*' ../include/config.h`
|
||||
echo "$MAXQ" | sed -e 's/[^0-9]*\([0-9]*\).*/\1)/' >> $M4
|
||||
echo -n "define(MAXLINKS," >>$M4
|
||||
MAXL=`egrep '^#define[ ]*MAXIMUM_LINKS[ ]*[0-9]* | head -1' \
|
||||
../include/config.h`
|
||||
echo "$MAXL" | sed -e 's/[^0-9]*\([0-9]*\).*/\1)/' >> $M4
|
||||
DOM=`egrep '^domain' /etc/resolv.conf | \
|
||||
sed -e 's/^domain[ ]*\([a-zA-Z\-\.0-9]*\).*/\1/'`
|
||||
echo "define(DOMAIN,$DOM)" >> $M4
|
||||
|
||||
cat >>$M4 <<_EOF_
|
||||
define(CL,\`ifelse(len(\$1),0,0,\$1)')
|
||||
define(HOST,\$1)
|
||||
define(HOSTM,\$1)
|
||||
define(ID,*@\$1)
|
||||
define(PASS,\$1)
|
||||
define(PING,\`ifelse(len(\$1),0,PFREQ,\$1)')
|
||||
define(APORT,\`ifelse(len(\$1),0,PORT,\$1)')
|
||||
define(FREQ,\`ifelse(len(\$1),0,CFREQ,\$1)')
|
||||
define(SENDQ,\`ifelse(len(\$1),0,MAXSENDQ,\$1)')
|
||||
define(MAX,\`ifelse(len(\$1),0,MAXLINKS,\$1)')
|
||||
define(CPORT,\$1)
|
||||
define(SERV,\$1)
|
||||
define(ADMIN,A:\$1:\$2:\$3:\$4:\$5)
|
||||
define(ALLOW,N:\`HOST(\$1)':\`PASS(\$2)':\`SERV(\$3)':\`HOSTM(\$4)':\`CL(\$5)')
|
||||
define(BAN,K:\$1:\$2:\$3)
|
||||
define(CLASS,Y:\$1:\`PING(\$2)':\$3:\`MAX(\$4)':\`SENDQ(\$5)')
|
||||
define(CLIENT,I:\`HOST(\$1)':\`PASS(\$2)':\`ifelse(len(HOST(\$3)),0,\$1,\$3)':\
|
||||
\`APORT(\$4)':\`CL(\$5)')
|
||||
define(CONNECT,C:\`HOST(\$1)':\`PASS(\$2)':\`SERV(\$3)':\
|
||||
\`CPORT(\$4)':\`CL(\$5)')
|
||||
define(ME,M:\$1:\$2:\$3:\$4:\$5)
|
||||
define(HUB,H:\`ifelse(len(\$2),0,*,\$2)':*:\$1)
|
||||
define(LEAF,L:\`ifelse(len(\$2),0,*,\$2)':*:\$1:1)
|
||||
define(SERVER,\`
|
||||
CONNECT(\$1,\$2,\$3,\$5,\$6)
|
||||
ALLOW(\$1,\$2,\$3,\$4,\$6)
|
||||
')
|
||||
_EOF_
|
||||
2676
ircd/channel.c
Normal file
2676
ircd/channel.c
Normal file
File diff suppressed because it is too large
Load Diff
755
ircd/chkconf.c
Normal file
755
ircd/chkconf.c
Normal file
@@ -0,0 +1,755 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, ircd/chkconf.c
|
||||
* Copyright (C) 1993 Darren Reed
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)chkconf.c 1.9 1/30/94 (C) 1993 Darren Reed";
|
||||
#endif
|
||||
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "numeric.h"
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#ifdef __hpux
|
||||
#include "inet.h"
|
||||
#endif
|
||||
#ifdef PCS
|
||||
#include <time.h>
|
||||
#endif
|
||||
#ifdef R_LINES
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#ifdef DYNIXPTX
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
/* for the connect rule patch.. these really should be in a header,
|
||||
** but i see h.h isn't included for some reason.. so they're here */
|
||||
char *crule_parse PROTO((char *rule));
|
||||
void crule_free PROTO((char **elem));
|
||||
|
||||
#undef free
|
||||
#define MyMalloc(x) malloc(x)
|
||||
|
||||
static void new_class();
|
||||
static char *getfield(), confchar ();
|
||||
static int openconf(), validate();
|
||||
static aClass *get_class();
|
||||
static aConfItem *initconf();
|
||||
|
||||
static int numclasses = 0, *classarr = (int *)NULL, debugflag = 0;
|
||||
static char *configfile = CONFIGFILE;
|
||||
static char nullfield[] = "";
|
||||
static char maxsendq[12];
|
||||
|
||||
main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
new_class(0);
|
||||
|
||||
if (chdir(DPATH))
|
||||
{
|
||||
perror("chdir");
|
||||
exit(-1);
|
||||
}
|
||||
if (argc > 1 && !strncmp(argv[1], "-d", 2))
|
||||
{
|
||||
debugflag = 1;
|
||||
if (argv[1][2])
|
||||
debugflag = atoi(argv[1]+2);
|
||||
argc--, argv++;
|
||||
}
|
||||
if (argc > 1)
|
||||
configfile = argv[1];
|
||||
return validate(initconf());
|
||||
}
|
||||
|
||||
/*
|
||||
* openconf
|
||||
*
|
||||
* returns -1 on any error or else the fd opened from which to read the
|
||||
* configuration file from. This may either be th4 file direct or one end
|
||||
* of a pipe from m4.
|
||||
*/
|
||||
static int openconf()
|
||||
{
|
||||
#ifdef M4_PREPROC
|
||||
int pi[2];
|
||||
|
||||
if (pipe(pi) == -1)
|
||||
return -1;
|
||||
switch(fork())
|
||||
{
|
||||
case -1 :
|
||||
return -1;
|
||||
case 0 :
|
||||
(void)close(pi[0]);
|
||||
if (pi[1] != 1)
|
||||
{
|
||||
(void)dup2(pi[1], 1);
|
||||
(void)close(pi[1]);
|
||||
}
|
||||
(void)dup2(1,2);
|
||||
/*
|
||||
* m4 maybe anywhere, use execvp to find it. Any error
|
||||
* goes out with report_error. Could be dangerous,
|
||||
* two servers running with the same fd's >:-) -avalon
|
||||
*/
|
||||
(void)execlp("m4", "m4", "ircd.m4", configfile, 0);
|
||||
perror("m4");
|
||||
exit(-1);
|
||||
default :
|
||||
(void)close(pi[1]);
|
||||
return pi[0];
|
||||
}
|
||||
#else
|
||||
return open(configfile, O_RDONLY);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** initconf()
|
||||
** Read configuration file.
|
||||
**
|
||||
** returns -1, if file cannot be opened
|
||||
** 0, if file opened
|
||||
*/
|
||||
|
||||
static aConfItem *initconf(opt)
|
||||
int opt;
|
||||
{
|
||||
int fd;
|
||||
char line[512], *tmp, c[80], *s, *crule;
|
||||
int ccount = 0, ncount = 0, dh, flags = 0;
|
||||
aConfItem *aconf = NULL, *ctop = NULL;
|
||||
|
||||
(void)fprintf(stderr, "initconf(): ircd.conf = %s\n", configfile);
|
||||
if ((fd = openconf()) == -1)
|
||||
{
|
||||
#ifdef M4_PREPROC
|
||||
(void)wait(0);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
(void)dgets(-1, NULL, 0); /* make sure buffer is at empty pos */
|
||||
while ((dh = dgets(fd, line, sizeof(line) - 1)) > 0)
|
||||
{
|
||||
if (aconf)
|
||||
{
|
||||
if (aconf->host)
|
||||
(void)free(aconf->host);
|
||||
if (aconf->passwd)
|
||||
(void)free(aconf->passwd);
|
||||
if (aconf->name)
|
||||
(void)free(aconf->name);
|
||||
}
|
||||
else
|
||||
aconf = (aConfItem *)malloc(sizeof(*aconf));
|
||||
aconf->host = (char *)NULL;
|
||||
aconf->passwd = (char *)NULL;
|
||||
aconf->name = (char *)NULL;
|
||||
aconf->class = (aClass *)NULL;
|
||||
if (tmp = (char *)index(line, '\n'))
|
||||
*tmp = 0;
|
||||
else while(dgets(fd, c, sizeof(c) - 1))
|
||||
if (tmp = (char *)index(c, '\n'))
|
||||
{
|
||||
*tmp = 0;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Do quoting of characters and # detection.
|
||||
*/
|
||||
for (tmp = line; *tmp; tmp++)
|
||||
{
|
||||
if (*tmp == '\\')
|
||||
{
|
||||
switch (*(tmp+1))
|
||||
{
|
||||
case 'n' :
|
||||
*tmp = '\n';
|
||||
break;
|
||||
case 'r' :
|
||||
*tmp = '\r';
|
||||
break;
|
||||
case 't' :
|
||||
*tmp = '\t';
|
||||
break;
|
||||
case '0' :
|
||||
*tmp = '\0';
|
||||
break;
|
||||
default :
|
||||
*tmp = *(tmp+1);
|
||||
break;
|
||||
}
|
||||
if (!*(tmp+1))
|
||||
break;
|
||||
else
|
||||
for (s = tmp; *s = *++s; )
|
||||
;
|
||||
tmp++;
|
||||
}
|
||||
else if (*tmp == '#')
|
||||
*tmp = '\0';
|
||||
}
|
||||
if (!*line || *line == '#' || *line == '\n' ||
|
||||
*line == ' ' || *line == '\t')
|
||||
continue;
|
||||
|
||||
if (line[1] != ':')
|
||||
{
|
||||
(void)fprintf(stderr, "ERROR: Bad config line (%s)\n",
|
||||
line);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (debugflag)
|
||||
(void)printf("\n%s\n",line);
|
||||
(void)fflush(stdout);
|
||||
|
||||
tmp = getfield(line);
|
||||
if (!tmp)
|
||||
{
|
||||
(void)fprintf(stderr, "\tERROR: no fields found\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
aconf->status = CONF_ILLEGAL;
|
||||
|
||||
switch (*tmp)
|
||||
{
|
||||
case 'A': /* Name, e-mail address of administrator */
|
||||
case 'a': /* of this server. */
|
||||
aconf->status = CONF_ADMIN;
|
||||
break;
|
||||
case 'C': /* Server where I should try to connect */
|
||||
case 'c': /* in case of lp failures */
|
||||
ccount++;
|
||||
aconf->status = CONF_CONNECT_SERVER;
|
||||
break;
|
||||
/* Connect rule */
|
||||
case 'D':
|
||||
aconf->status = CONF_CRULEALL;
|
||||
break;
|
||||
/* Connect rule - autos only */
|
||||
case 'd':
|
||||
aconf->status = CONF_CRULEAUTO;
|
||||
break;
|
||||
case 'H': /* Hub server line */
|
||||
case 'h':
|
||||
aconf->status = CONF_HUB;
|
||||
break;
|
||||
case 'I': /* Just plain normal irc client trying */
|
||||
case 'i': /* to connect me */
|
||||
aconf->status = CONF_CLIENT;
|
||||
break;
|
||||
case 'K': /* Kill user line on irc.conf */
|
||||
case 'k':
|
||||
aconf->status = CONF_KILL;
|
||||
break;
|
||||
/* Operator. Line should contain at least */
|
||||
/* password and host where connection is */
|
||||
case 'L': /* guaranteed leaf server */
|
||||
case 'l':
|
||||
aconf->status = CONF_LEAF;
|
||||
break;
|
||||
/* Me. Host field is name used for this host */
|
||||
/* and port number is the number of the port */
|
||||
case 'M':
|
||||
case 'm':
|
||||
aconf->status = CONF_ME;
|
||||
break;
|
||||
case 'N': /* Server where I should NOT try to */
|
||||
case 'n': /* connect in case of lp failures */
|
||||
/* but which tries to connect ME */
|
||||
++ncount;
|
||||
aconf->status = CONF_NOCONNECT_SERVER;
|
||||
break;
|
||||
case 'O':
|
||||
aconf->status = CONF_OPERATOR;
|
||||
break;
|
||||
/* Local Operator, (limited privs --SRB) */
|
||||
case 'o':
|
||||
aconf->status = CONF_LOCOP;
|
||||
break;
|
||||
case 'P': /* listen port line */
|
||||
case 'p':
|
||||
aconf->status = CONF_LISTEN_PORT;
|
||||
break;
|
||||
case 'Q': /* a server that you don't want in your */
|
||||
case 'q': /* network. USE WITH CAUTION! */
|
||||
aconf->status = CONF_QUARANTINED_SERVER;
|
||||
break;
|
||||
#ifdef R_LINES
|
||||
case 'R': /* extended K line */
|
||||
case 'r': /* Offers more options of how to restrict */
|
||||
aconf->status = CONF_RESTRICT;
|
||||
break;
|
||||
#endif
|
||||
case 'S': /* Service. Same semantics as */
|
||||
case 's': /* CONF_OPERATOR */
|
||||
aconf->status = CONF_SERVICE;
|
||||
break;
|
||||
case 'T':
|
||||
case 't':
|
||||
aconf->status = CONF_TLINES;
|
||||
break;
|
||||
case 'U':
|
||||
case 'u':
|
||||
aconf->status = CONF_UWORLD;
|
||||
break;
|
||||
case 'Y':
|
||||
case 'y':
|
||||
aconf->status = CONF_CLASS;
|
||||
break;
|
||||
default:
|
||||
(void)fprintf(stderr,
|
||||
"\tERROR: unknown conf line letter (%c)\n",
|
||||
*tmp);
|
||||
break;
|
||||
}
|
||||
|
||||
if (IsIllegal(aconf))
|
||||
continue;
|
||||
|
||||
for (;;) /* Fake loop, that I can use break here --msa */
|
||||
{
|
||||
if ((tmp = getfield(NULL)) == NULL)
|
||||
break;
|
||||
DupString(aconf->host, tmp);
|
||||
if ((tmp = getfield(NULL)) == NULL)
|
||||
break;
|
||||
DupString(aconf->passwd, tmp);
|
||||
if ((tmp = getfield(NULL)) == NULL)
|
||||
break;
|
||||
DupString(aconf->name, tmp);
|
||||
if ((tmp = getfield(NULL)) == NULL)
|
||||
break;
|
||||
aconf->port = atoi(tmp);
|
||||
if ((tmp = getfield(NULL)) == NULL)
|
||||
break;
|
||||
if (!(aconf->status & CONF_CLASS))
|
||||
aconf->class = get_class(atoi(tmp));
|
||||
break;
|
||||
}
|
||||
if (!aconf->class && (aconf->status & (CONF_CONNECT_SERVER|
|
||||
CONF_NOCONNECT_SERVER|CONF_OPS|CONF_CLIENT)))
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"\tWARNING: No class. Default 0\n");
|
||||
aconf->class = get_class(0);
|
||||
}
|
||||
/*
|
||||
** If conf line is a class definition, create a class entry
|
||||
** for it and make the conf_line illegal and delete it.
|
||||
*/
|
||||
if (aconf->status & CONF_CLASS)
|
||||
{
|
||||
int class = 0;
|
||||
|
||||
if (!aconf->host)
|
||||
{
|
||||
(void)fprintf(stderr,"\tERROR: no class #\n");
|
||||
continue;
|
||||
}
|
||||
if (!tmp)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"\tWARNING: missing sendq field\n");
|
||||
(void)fprintf(stderr, "\t\t default: %d\n",
|
||||
MAXSENDQLENGTH);
|
||||
(void)sprintf(maxsendq, "%d", MAXSENDQLENGTH);
|
||||
}
|
||||
else
|
||||
(void)sprintf(maxsendq, "%d", atoi(tmp));
|
||||
new_class(atoi(aconf->host));
|
||||
aconf->class = get_class(atoi(aconf->host));
|
||||
goto print_confline;
|
||||
}
|
||||
|
||||
if (aconf->status & CONF_LISTEN_PORT)
|
||||
{
|
||||
#ifdef UNIXPORT
|
||||
struct stat sb;
|
||||
|
||||
if (!aconf->host)
|
||||
(void)fprintf(stderr, "\tERROR: %s\n",
|
||||
"null host field in P-line");
|
||||
else if (index(aconf->host, '/'))
|
||||
{
|
||||
if (stat(aconf->host, &sb) == -1)
|
||||
{
|
||||
(void)fprintf(stderr, "\tERROR: (%s) ",
|
||||
aconf->host);
|
||||
perror("stat");
|
||||
}
|
||||
else if ((sb.st_mode & S_IFMT) != S_IFDIR)
|
||||
(void)fprintf(stderr,
|
||||
"\tERROR: %s not directory\n",
|
||||
aconf->host);
|
||||
}
|
||||
#else
|
||||
if (!aconf->host)
|
||||
(void)fprintf(stderr, "\tERROR: %s\n",
|
||||
"null host field in P-line");
|
||||
else if (index(aconf->host, '/'))
|
||||
(void)fprintf(stderr, "\t%s %s\n",
|
||||
"WARNING: / present in P-line",
|
||||
"for non-UNIXPORT configuration");
|
||||
#endif
|
||||
aconf->class = get_class(0);
|
||||
goto print_confline;
|
||||
}
|
||||
|
||||
if (aconf->status & CONF_SERVER_MASK &&
|
||||
(!aconf->host || index(aconf->host, '*') ||
|
||||
index(aconf->host, '?')))
|
||||
{
|
||||
(void)fprintf(stderr, "\tERROR: bad host field\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aconf->status & CONF_SERVER_MASK && BadPtr(aconf->passwd))
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"\tERROR: empty/no password field\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aconf->status & CONF_SERVER_MASK && !aconf->name)
|
||||
{
|
||||
(void)fprintf(stderr, "\tERROR: bad name field\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (aconf->status & (CONF_SERVER_MASK|CONF_OPS))
|
||||
if (!index(aconf->host, '@'))
|
||||
{
|
||||
char *newhost;
|
||||
int len = 3; /* *@\0 = 3 */
|
||||
|
||||
len += strlen(aconf->host);
|
||||
newhost = (char *)MyMalloc(len);
|
||||
(void)sprintf(newhost, "*@%s", aconf->host);
|
||||
(void)free(aconf->host);
|
||||
aconf->host = newhost;
|
||||
}
|
||||
|
||||
/* parse the connect rules to detect errors, but free
|
||||
** any allocated storage immediately -- we're just looking
|
||||
** for errors.. */
|
||||
if (aconf->status & CONF_CRULE)
|
||||
if ((crule =
|
||||
(char *) crule_parse (aconf->name)) != NULL)
|
||||
crule_free (&crule);
|
||||
|
||||
if (!aconf->class)
|
||||
aconf->class = get_class(0);
|
||||
(void)sprintf(maxsendq, "%d", aconf->class->class);
|
||||
|
||||
if (!aconf->name)
|
||||
aconf->name = nullfield;
|
||||
if (!aconf->passwd)
|
||||
aconf->passwd = nullfield;
|
||||
if (!aconf->host)
|
||||
aconf->host = nullfield;
|
||||
if (aconf->status & (CONF_ME|CONF_ADMIN))
|
||||
{
|
||||
if (flags & aconf->status)
|
||||
(void)fprintf(stderr,
|
||||
"ERROR: multiple %c-lines\n",
|
||||
toupper(confchar(aconf->status)));
|
||||
else
|
||||
flags |= aconf->status;
|
||||
}
|
||||
print_confline:
|
||||
if (debugflag > 8)
|
||||
(void)printf("(%d) (%s) (%s) (%s) (%d) (%s)\n",
|
||||
aconf->status, aconf->host, aconf->passwd,
|
||||
aconf->name, aconf->port, maxsendq);
|
||||
(void)fflush(stdout);
|
||||
if (aconf->status & (CONF_SERVER_MASK|CONF_HUB|CONF_LEAF))
|
||||
{
|
||||
aconf->next = ctop;
|
||||
ctop = aconf;
|
||||
aconf = NULL;
|
||||
}
|
||||
}
|
||||
(void)close(fd);
|
||||
#ifdef M4_PREPROC
|
||||
(void)wait(0);
|
||||
#endif
|
||||
return ctop;
|
||||
}
|
||||
|
||||
static aClass *get_class(cn)
|
||||
int cn;
|
||||
{
|
||||
static aClass cls;
|
||||
int i = numclasses - 1;
|
||||
|
||||
cls.class = -1;
|
||||
for (; i >= 0; i--)
|
||||
if (classarr[i] == cn)
|
||||
{
|
||||
cls.class = cn;
|
||||
break;
|
||||
}
|
||||
if (i == -1)
|
||||
(void)fprintf(stderr,"\tWARNING: class %d not found\n", cn);
|
||||
return &cls;
|
||||
}
|
||||
|
||||
static void new_class(cn)
|
||||
int cn;
|
||||
{
|
||||
numclasses++;
|
||||
if (classarr)
|
||||
classarr = (int *)realloc(classarr, sizeof(int) * numclasses);
|
||||
else
|
||||
classarr = (int *)malloc(sizeof(int));
|
||||
classarr[numclasses-1] = cn;
|
||||
}
|
||||
|
||||
/*
|
||||
* field breakup for ircd.conf file.
|
||||
*/
|
||||
static char *getfield(newline)
|
||||
char *newline;
|
||||
{
|
||||
static char *line = NULL;
|
||||
char *end, *field;
|
||||
|
||||
if (newline)
|
||||
line = newline;
|
||||
if (line == NULL)
|
||||
return(NULL);
|
||||
|
||||
field = line;
|
||||
if ((end = (char *)index(line,':')) == NULL)
|
||||
{
|
||||
line = NULL;
|
||||
if ((end = (char *)index(field,'\n')) == NULL)
|
||||
end = field + strlen(field);
|
||||
}
|
||||
else
|
||||
line = end + 1;
|
||||
*end = '\0';
|
||||
return(field);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** read a string terminated by \r or \n in from a fd
|
||||
**
|
||||
** Created: Sat Dec 12 06:29:58 EST 1992 by avalon
|
||||
** Returns:
|
||||
** 0 - EOF
|
||||
** -1 - error on read
|
||||
** >0 - number of bytes returned (<=num)
|
||||
** After opening a fd, it is necessary to init dgets() by calling it as
|
||||
** dgets(x,y,0);
|
||||
** to mark the buffer as being empty.
|
||||
*/
|
||||
int dgets(fd, buf, num)
|
||||
int fd, num;
|
||||
char *buf;
|
||||
{
|
||||
static char dgbuf[8192];
|
||||
static char *head = dgbuf, *tail = dgbuf;
|
||||
register char *s, *t;
|
||||
register int n, nr;
|
||||
|
||||
/*
|
||||
** Sanity checks.
|
||||
*/
|
||||
if (head == tail)
|
||||
*head = '\0';
|
||||
if (!num)
|
||||
{
|
||||
head = tail = dgbuf;
|
||||
*head = '\0';
|
||||
return 0;
|
||||
}
|
||||
if (num > sizeof(dgbuf) - 1)
|
||||
num = sizeof(dgbuf) - 1;
|
||||
dgetsagain:
|
||||
if (head > dgbuf)
|
||||
{
|
||||
for (nr = tail - head, s = head, t = dgbuf; nr > 0; nr--)
|
||||
*t++ = *s++;
|
||||
tail = t;
|
||||
head = dgbuf;
|
||||
}
|
||||
/*
|
||||
** check input buffer for EOL and if present return string.
|
||||
*/
|
||||
if (head < tail &&
|
||||
((s = index(head, '\n')) || (s = index(head, '\r'))) && s < tail)
|
||||
{
|
||||
n = MIN(s - head + 1, num); /* at least 1 byte */
|
||||
dgetsreturnbuf:
|
||||
bcopy(head, buf, n);
|
||||
head += n;
|
||||
if (head == tail)
|
||||
head = tail = dgbuf;
|
||||
return n;
|
||||
}
|
||||
|
||||
if (tail - head >= num) /* dgets buf is big enough */
|
||||
{
|
||||
n = num;
|
||||
goto dgetsreturnbuf;
|
||||
}
|
||||
|
||||
n = sizeof(dgbuf) - (tail - dgbuf) - 1;
|
||||
nr = read(fd, tail, n);
|
||||
if (nr == -1)
|
||||
{
|
||||
head = tail = dgbuf;
|
||||
return -1;
|
||||
}
|
||||
if (!nr)
|
||||
{
|
||||
if (head < tail)
|
||||
{
|
||||
n = MIN(head - tail, num);
|
||||
goto dgetsreturnbuf;
|
||||
}
|
||||
head = tail = dgbuf;
|
||||
return 0;
|
||||
}
|
||||
tail += nr;
|
||||
*tail = '\0';
|
||||
for (t = head; (s = index(t, '\n')); )
|
||||
{
|
||||
if ((s > head) && (s > dgbuf))
|
||||
{
|
||||
t = s-1;
|
||||
for (nr = 0; *t == '\\'; nr++)
|
||||
t--;
|
||||
if (nr & 1)
|
||||
{
|
||||
t = s+1;
|
||||
s--;
|
||||
nr = tail - t;
|
||||
while (nr--)
|
||||
*s++ = *t++;
|
||||
tail -= 2;
|
||||
*tail = '\0';
|
||||
}
|
||||
else
|
||||
s++;
|
||||
}
|
||||
else
|
||||
s++;
|
||||
t = s;
|
||||
}
|
||||
*tail = '\0';
|
||||
goto dgetsagain;
|
||||
}
|
||||
|
||||
|
||||
static int validate(top)
|
||||
aConfItem *top;
|
||||
{
|
||||
Reg1 aConfItem *aconf, *bconf;
|
||||
u_int otype, valid = 0;
|
||||
|
||||
if (!top)
|
||||
return 0;
|
||||
|
||||
for (aconf = top; aconf; aconf = aconf->next)
|
||||
{
|
||||
if (aconf->status & CONF_MATCH)
|
||||
continue;
|
||||
|
||||
if (aconf->status & CONF_SERVER_MASK)
|
||||
{
|
||||
if (aconf->status & CONF_CONNECT_SERVER)
|
||||
otype = CONF_NOCONNECT_SERVER;
|
||||
else if (aconf->status & CONF_NOCONNECT_SERVER)
|
||||
otype = CONF_CONNECT_SERVER;
|
||||
|
||||
for (bconf = top; bconf; bconf = bconf->next)
|
||||
{
|
||||
if (bconf == aconf || !(bconf->status & otype))
|
||||
continue;
|
||||
if (bconf->class == aconf->class &&
|
||||
!mycmp(bconf->name, aconf->name) &&
|
||||
!mycmp(bconf->host, aconf->host))
|
||||
{
|
||||
aconf->status |= CONF_MATCH;
|
||||
bconf->status |= CONF_MATCH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
for (bconf = top; bconf; bconf = bconf->next)
|
||||
{
|
||||
if ((bconf == aconf) ||
|
||||
!(bconf->status & CONF_SERVER_MASK))
|
||||
continue;
|
||||
if (!mycmp(bconf->name, aconf->name))
|
||||
{
|
||||
aconf->status |= CONF_MATCH;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(void) fprintf(stderr, "\n");
|
||||
for (aconf = top; aconf; aconf = aconf->next)
|
||||
if (aconf->status & CONF_MATCH)
|
||||
valid++;
|
||||
else
|
||||
(void)fprintf(stderr, "Unmatched %c:%s:%s:%s\n",
|
||||
confchar(aconf->status), aconf->host,
|
||||
aconf->passwd, aconf->name);
|
||||
return valid ? 0 : -1;
|
||||
}
|
||||
|
||||
static char confchar(status)
|
||||
u_int status;
|
||||
{
|
||||
static char letrs[] = "QICNoOMKARYSLPH";
|
||||
char *s = letrs;
|
||||
|
||||
status &= ~(CONF_MATCH|CONF_ILLEGAL);
|
||||
|
||||
for (; *s; s++, status >>= 1)
|
||||
if (status & 1)
|
||||
return *s;
|
||||
return '-';
|
||||
}
|
||||
|
||||
outofmemory()
|
||||
{
|
||||
(void)write(2, "Out of memory\n", 14);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
236
ircd/class.c
Normal file
236
ircd/class.c
Normal file
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* IRC - Internet Relay Chat, ircd/class.c
|
||||
* Copyright (C) 1990 Darren Reed
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)class.c 1.4 6/28/93 (C) 1990 Darren Reed";
|
||||
#endif
|
||||
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "numeric.h"
|
||||
#include "h.h"
|
||||
|
||||
#define BAD_CONF_CLASS -1
|
||||
#define BAD_PING -2
|
||||
#define BAD_CLIENT_CLASS -3
|
||||
|
||||
aClass *classes;
|
||||
|
||||
int get_conf_class(aconf)
|
||||
aConfItem *aconf;
|
||||
{
|
||||
if ((aconf) && Class(aconf))
|
||||
return (ConfClass(aconf));
|
||||
|
||||
Debug((DEBUG_DEBUG,"No Class For %s",
|
||||
(aconf) ? aconf->name : "*No Conf*"));
|
||||
|
||||
return (BAD_CONF_CLASS);
|
||||
|
||||
}
|
||||
|
||||
static int get_conf_ping(aconf)
|
||||
aConfItem *aconf;
|
||||
{
|
||||
if ((aconf) && Class(aconf))
|
||||
return (ConfPingFreq(aconf));
|
||||
|
||||
Debug((DEBUG_DEBUG,"No Ping For %s",
|
||||
(aconf) ? aconf->name : "*No Conf*"));
|
||||
|
||||
return (BAD_PING);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int get_client_class(acptr)
|
||||
aClient *acptr;
|
||||
{
|
||||
Reg1 Link *tmp;
|
||||
Reg2 aClass *cl;
|
||||
int i = 0, retc = BAD_CLIENT_CLASS;
|
||||
|
||||
if (acptr && !IsMe(acptr) && !IsPing(acptr) && (acptr->confs))
|
||||
for (tmp = acptr->confs; tmp; tmp = tmp->next)
|
||||
{
|
||||
if (!tmp->value.aconf ||
|
||||
!(cl = tmp->value.aconf->class))
|
||||
continue;
|
||||
if (Class(cl) > retc)
|
||||
retc = Class(cl);
|
||||
}
|
||||
|
||||
Debug((DEBUG_DEBUG,"Returning Class %d For %s",retc,acptr->name));
|
||||
|
||||
return (retc);
|
||||
}
|
||||
|
||||
int get_client_ping(acptr)
|
||||
aClient *acptr;
|
||||
{
|
||||
int ping = 0, ping2;
|
||||
aConfItem *aconf;
|
||||
Link *link;
|
||||
|
||||
link = acptr->confs;
|
||||
|
||||
if (link)
|
||||
while (link)
|
||||
{
|
||||
aconf = link->value.aconf;
|
||||
if (aconf->status & (CONF_CLIENT|CONF_CONNECT_SERVER|
|
||||
CONF_NOCONNECT_SERVER))
|
||||
{
|
||||
ping2 = get_conf_ping(aconf);
|
||||
if ((ping2 != BAD_PING) && ((ping > ping2) ||
|
||||
!ping))
|
||||
ping = ping2;
|
||||
}
|
||||
link = link->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
ping = PINGFREQUENCY;
|
||||
Debug((DEBUG_DEBUG,"No Attached Confs"));
|
||||
}
|
||||
if (ping <= 0)
|
||||
ping = PINGFREQUENCY;
|
||||
Debug((DEBUG_DEBUG,"Client %s Ping %d", acptr->name, ping));
|
||||
return (ping);
|
||||
}
|
||||
|
||||
int get_con_freq(clptr)
|
||||
aClass *clptr;
|
||||
{
|
||||
if (clptr)
|
||||
return (ConFreq(clptr));
|
||||
else
|
||||
return (CONNECTFREQUENCY);
|
||||
}
|
||||
|
||||
/*
|
||||
* When adding a class, check to see if it is already present first.
|
||||
* if so, then update the information for that class, rather than create
|
||||
* a new entry for it and later delete the old entry.
|
||||
* if no present entry is found, then create a new one and add it in
|
||||
* immeadiately after the first one (class 0).
|
||||
*/
|
||||
void add_class(class, ping, confreq, maxli, sendq)
|
||||
int class, ping, confreq, maxli;
|
||||
long sendq;
|
||||
{
|
||||
aClass *t, *p;
|
||||
|
||||
t = find_class(class);
|
||||
if ((t == classes) && (class != 0))
|
||||
{
|
||||
p = (aClass *)make_class();
|
||||
NextClass(p) = NextClass(t);
|
||||
NextClass(t) = p;
|
||||
}
|
||||
else
|
||||
p = t;
|
||||
Debug((DEBUG_DEBUG,
|
||||
"Add Class %d: p %x t %x - cf: %d pf: %d ml: %d sq: %l",
|
||||
class, p, t, confreq, ping, maxli, sendq));
|
||||
Class(p) = class;
|
||||
ConFreq(p) = confreq;
|
||||
PingFreq(p) = ping;
|
||||
MaxLinks(p) = maxli;
|
||||
MaxSendq(p) = (sendq > 0) ? sendq : MAXSENDQLENGTH;
|
||||
if (p != t)
|
||||
Links(p) = 0;
|
||||
}
|
||||
|
||||
aClass *find_class(cclass)
|
||||
int cclass;
|
||||
{
|
||||
aClass *cltmp;
|
||||
|
||||
for (cltmp = FirstClass(); cltmp; cltmp = NextClass(cltmp))
|
||||
if (Class(cltmp) == cclass)
|
||||
return cltmp;
|
||||
return classes;
|
||||
}
|
||||
|
||||
void check_class()
|
||||
{
|
||||
Reg1 aClass *cltmp, *cltmp2;
|
||||
|
||||
Debug((DEBUG_DEBUG, "Class check:"));
|
||||
|
||||
for (cltmp2 = cltmp = FirstClass(); cltmp; cltmp = NextClass(cltmp2))
|
||||
{
|
||||
Debug((DEBUG_DEBUG,
|
||||
"Class %d : CF: %d PF: %d ML: %d LI: %d SQ: %ld",
|
||||
Class(cltmp), ConFreq(cltmp), PingFreq(cltmp),
|
||||
MaxLinks(cltmp), Links(cltmp), MaxSendq(cltmp)));
|
||||
if (MaxLinks(cltmp) < 0)
|
||||
{
|
||||
NextClass(cltmp2) = NextClass(cltmp);
|
||||
if (Links(cltmp) <= 0)
|
||||
free_class(cltmp);
|
||||
}
|
||||
else
|
||||
cltmp2 = cltmp;
|
||||
}
|
||||
}
|
||||
|
||||
void initclass()
|
||||
{
|
||||
classes = (aClass *)make_class();
|
||||
|
||||
Class(FirstClass()) = 0;
|
||||
ConFreq(FirstClass()) = CONNECTFREQUENCY;
|
||||
PingFreq(FirstClass()) = PINGFREQUENCY;
|
||||
MaxLinks(FirstClass()) = MAXIMUM_LINKS;
|
||||
MaxSendq(FirstClass()) = MAXSENDQLENGTH;
|
||||
Links(FirstClass()) = 0;
|
||||
NextClass(FirstClass()) = NULL;
|
||||
}
|
||||
|
||||
void report_classes(sptr)
|
||||
aClient *sptr;
|
||||
{
|
||||
Reg1 aClass *cltmp;
|
||||
|
||||
for (cltmp = FirstClass(); cltmp; cltmp = NextClass(cltmp))
|
||||
sendto_one(sptr, rpl_str(RPL_STATSYLINE), me.name, sptr->name,
|
||||
'Y', Class(cltmp), PingFreq(cltmp), ConFreq(cltmp),
|
||||
MaxLinks(cltmp), MaxSendq(cltmp));
|
||||
}
|
||||
|
||||
long get_sendq(cptr)
|
||||
aClient *cptr;
|
||||
{
|
||||
Reg1 int sendq = MAXSENDQLENGTH, retc = BAD_CLIENT_CLASS;
|
||||
Reg2 Link *tmp;
|
||||
Reg2 aClass *cl;
|
||||
|
||||
if (cptr && !IsMe(cptr) && (cptr->confs))
|
||||
for (tmp = cptr->confs; tmp; tmp = tmp->next)
|
||||
{
|
||||
if (!tmp->value.aconf ||
|
||||
!(cl = tmp->value.aconf->class))
|
||||
continue;
|
||||
if (Class(cl) > retc)
|
||||
sendq = MaxSendq(cl);
|
||||
}
|
||||
return sendq;
|
||||
}
|
||||
775
ircd/crule.c
Normal file
775
ircd/crule.c
Normal file
@@ -0,0 +1,775 @@
|
||||
/*
|
||||
* SmartRoute phase 1
|
||||
* connection rule patch
|
||||
* by Tony Vencill (Tonto on IRC) <vencill@bga.com>
|
||||
*
|
||||
* The majority of this file is a recusive descent parser used to convert
|
||||
* connection rules into expression trees when the conf file is read.
|
||||
* All parsing structures and types are hidden in the interest of good
|
||||
* programming style and to make possible future data structure changes
|
||||
* without affecting the interface between this patch and the rest of the
|
||||
* server. The only functions accessible externally are crule_parse,
|
||||
* crule_free, and crule_eval. Prototypes for these functions can be
|
||||
* found in h.h.
|
||||
*
|
||||
* Please direct any connection rule or SmartRoute questions to Tonto on
|
||||
* IRC or by email to vencill@bga.com.
|
||||
*
|
||||
* For parser testing, defining CR_DEBUG generates a stand-alone parser
|
||||
* that takes rules from stdin and prints out memory allocation
|
||||
* information and the parsed rule. This stand alone parser is ignorant
|
||||
* of the irc server and thus cannot do rule evaluation. Do not define
|
||||
* this flag when compiling the server! If you wish to generate the
|
||||
* test parser, compile from the ircd directory with a line similar to
|
||||
* cc -o parser -DCR_DEBUG crule.c
|
||||
*
|
||||
* The define CR_CHKCONF is provided to generate routines needed in
|
||||
* chkconf. These consist of the parser, a different crule_parse that
|
||||
* prints errors to stderr, and crule_free (just for good style and to
|
||||
* more closely simulate the actual ircd environment). crule_eval and
|
||||
* the rule functions are made empty functions as in the stand-alone
|
||||
* test parser.
|
||||
*/
|
||||
|
||||
#ifndef CR_DEBUG
|
||||
/* ircd functions and types we need */
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "h.h"
|
||||
char *collapse PROTO((char *pattern));
|
||||
extern aClient *client, *local[];
|
||||
|
||||
#else
|
||||
/* includes and defines to make the stand-alone test parser */
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#define BadPtr(x) (!(x) || (*(x) == '\0'))
|
||||
#define DupString(x,y) do{x=(char *)MyMalloc(strlen(y)+1);(void)strcpy(x,y);}while(0)
|
||||
#define mycmp strcasecmp
|
||||
#endif
|
||||
|
||||
#ifndef PROTO
|
||||
#if __STDC__
|
||||
# define PROTO(x) x
|
||||
#else
|
||||
# define PROTO(x) ()
|
||||
#endif
|
||||
#endif
|
||||
#if defined(CR_DEBUG) || defined(CR_CHKCONF)
|
||||
#define MyMalloc malloc
|
||||
#undef MyFree
|
||||
#undef free
|
||||
#define MyFree free
|
||||
#endif
|
||||
|
||||
/* some constants and shared data types */
|
||||
#define CR_MAXARGLEN 80 /* why 80? why not? it's > hostname lengths */
|
||||
#define CR_MAXARGS 3 /* there's a better way to do this, but not now */
|
||||
|
||||
/* some symbols for easy reading */
|
||||
enum crule_token
|
||||
{CR_UNKNOWN, CR_END, CR_AND, CR_OR, CR_NOT, CR_OPENPAREN, CR_CLOSEPAREN,
|
||||
CR_COMMA, CR_WORD};
|
||||
enum crule_errcode
|
||||
{CR_NOERR, CR_UNEXPCTTOK, CR_UNKNWTOK, CR_EXPCTAND, CR_EXPCTOR,
|
||||
CR_EXPCTPRIM, CR_EXPCTOPEN, CR_EXPCTCLOSE, CR_UNKNWFUNC, CR_ARGMISMAT};
|
||||
|
||||
/* expression tree structure, function pointer, and tree pointer */
|
||||
/* local! */
|
||||
typedef int (*crule_funcptr) PROTO((int, void **));
|
||||
struct crule_treestruct
|
||||
{
|
||||
crule_funcptr funcptr;
|
||||
int numargs;
|
||||
void *arg[CR_MAXARGS]; /* for operators arg points to a tree element;
|
||||
for functions arg points to a char string */
|
||||
};
|
||||
typedef struct crule_treestruct crule_treeelem;
|
||||
typedef crule_treeelem *crule_treeptr;
|
||||
|
||||
/* rule function prototypes - local! */
|
||||
int crule_connected PROTO((int, void **));
|
||||
int crule_directcon PROTO((int, void **));
|
||||
int crule_via PROTO((int, void **));
|
||||
int crule_directop PROTO((int, void **));
|
||||
int crule__andor PROTO((int, void **));
|
||||
int crule__not PROTO((int, void **));
|
||||
|
||||
/* parsing function prototypes - local! */
|
||||
int crule_gettoken PROTO((int *, char **));
|
||||
void crule_getword PROTO((char *, int *, int, char **));
|
||||
int crule_parseandexpr PROTO((crule_treeptr *, int *, char **));
|
||||
int crule_parseorexpr PROTO((crule_treeptr *, int *, char **));
|
||||
int crule_parseprimary PROTO((crule_treeptr *, int *, char **));
|
||||
int crule_parsefunction PROTO((crule_treeptr *, int *, char **));
|
||||
int crule_parsearglist PROTO((crule_treeptr, int *, char **));
|
||||
|
||||
#if defined(CR_DEBUG) || defined(CR_CHKCONF)
|
||||
/* prototypes for the test parser; if not debugging, these are
|
||||
* defined in h.h */
|
||||
char *crule_parse PROTO((char *));
|
||||
void crule_free PROTO((char **));
|
||||
#ifdef CR_DEBUG
|
||||
void print_tree PROTO((crule_treeptr));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* error messages */
|
||||
char *crule_errstr[] =
|
||||
{
|
||||
"Unknown error", /* NOERR? - for completeness */
|
||||
"Unexpected token", /* UNEXPCTTOK */
|
||||
"Unknown token", /* UNKNWTOK */
|
||||
"And expr expected", /* EXPCTAND */
|
||||
"Or expr expected", /* EXPCTOR */
|
||||
"Primary expected", /* EXPCTPRIM */
|
||||
"( expected", /* EXPCTOPEN */
|
||||
") expected", /* EXPCTCLOSE */
|
||||
"Unknown function", /* UNKNWFUNC */
|
||||
"Argument mismatch" /* ARGMISMAT */
|
||||
};
|
||||
|
||||
/* function table - null terminated */
|
||||
struct crule_funclistent
|
||||
{
|
||||
char name[15]; /* MAXIMUM FUNCTION NAME LENGTH IS 14 CHARS!! */
|
||||
int reqnumargs;
|
||||
crule_funcptr funcptr;
|
||||
};
|
||||
struct crule_funclistent crule_funclist[] =
|
||||
{
|
||||
/* maximum function name length is 14 chars */
|
||||
{"connected", 1, crule_connected},
|
||||
{"directcon", 1, crule_directcon},
|
||||
{"via", 2, crule_via},
|
||||
{"directop", 0, crule_directop},
|
||||
{"", 0, NULL} /* this must be here to mark end of list */
|
||||
};
|
||||
|
||||
int crule_connected (numargs, crulearg)
|
||||
int numargs;
|
||||
void *crulearg[];
|
||||
{
|
||||
#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
|
||||
aClient *acptr;
|
||||
|
||||
/* taken from m_links */
|
||||
for (acptr = client; acptr; acptr = acptr->next)
|
||||
{
|
||||
if (!IsServer(acptr) && !IsMe(acptr))
|
||||
continue;
|
||||
if (match((char *) crulearg[0], acptr->name))
|
||||
continue;
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
int crule_directcon (numargs, crulearg)
|
||||
int numargs;
|
||||
void *crulearg[];
|
||||
{
|
||||
#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
|
||||
int i;
|
||||
aClient *acptr;
|
||||
|
||||
/* adapted from m_trace and exit_one_client */
|
||||
for (i = 0; i <= highest_fd; i++)
|
||||
{
|
||||
if (!(acptr = local[i]) || !IsServer(acptr))
|
||||
continue;
|
||||
if (match((char *) crulearg[0], acptr->name))
|
||||
continue;
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
int crule_via (numargs, crulearg)
|
||||
int numargs;
|
||||
void *crulearg[];
|
||||
{
|
||||
#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
|
||||
aClient *acptr;
|
||||
|
||||
/* adapted from m_links */
|
||||
for (acptr = client; acptr; acptr = acptr->next)
|
||||
{
|
||||
if (!IsServer(acptr) && !IsMe(acptr))
|
||||
continue;
|
||||
if (match((char *) crulearg[1], acptr->name))
|
||||
continue;
|
||||
if (match((char *) crulearg[0], (local[acptr->from->fd])->name))
|
||||
continue;
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
int crule_directop (numargs, crulearg)
|
||||
int numargs;
|
||||
void *crulearg[];
|
||||
{
|
||||
#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
|
||||
int i;
|
||||
aClient *acptr;
|
||||
|
||||
/* adapted from m_trace */
|
||||
for (i = 0; i <= highest_fd; i++)
|
||||
{
|
||||
if (!(acptr = local[i]) || !IsAnOper(acptr))
|
||||
continue;
|
||||
return (1);
|
||||
}
|
||||
return (0);
|
||||
#endif
|
||||
}
|
||||
|
||||
int crule__andor (numargs, crulearg)
|
||||
int numargs;
|
||||
void *crulearg[];
|
||||
{
|
||||
int result1;
|
||||
|
||||
result1 = ((crule_treeptr) crulearg[0])->funcptr
|
||||
(((crule_treeptr) crulearg[0])->numargs,
|
||||
(void *) ((crule_treeptr) crulearg[0])->arg);
|
||||
if (crulearg[2]) /* or */
|
||||
return (result1 ||
|
||||
((crule_treeptr) crulearg[1])->funcptr
|
||||
(((crule_treeptr) crulearg[1])->numargs,
|
||||
(void *) ((crule_treeptr) crulearg[1])->arg));
|
||||
else
|
||||
return (result1 &&
|
||||
((crule_treeptr) crulearg[1])->funcptr
|
||||
(((crule_treeptr) crulearg[1])->numargs,
|
||||
(void *) ((crule_treeptr) crulearg[1])->arg));
|
||||
}
|
||||
|
||||
int crule__not (numargs, crulearg)
|
||||
int numargs;
|
||||
void *crulearg[];
|
||||
{
|
||||
return (!((crule_treeptr) crulearg[0])->funcptr
|
||||
(((crule_treeptr) crulearg[0])->numargs,
|
||||
(void *) ((crule_treeptr) crulearg[0])->arg));
|
||||
}
|
||||
|
||||
#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
|
||||
int crule_eval (rule)
|
||||
char *rule;
|
||||
{
|
||||
return (((crule_treeptr) rule)->funcptr
|
||||
(((crule_treeptr) rule)->numargs,
|
||||
((crule_treeptr) rule)->arg));
|
||||
}
|
||||
#endif
|
||||
|
||||
int crule_gettoken (next_tokp, ruleptr)
|
||||
int *next_tokp;
|
||||
char **ruleptr;
|
||||
{
|
||||
char pending = '\0';
|
||||
|
||||
*next_tokp = CR_UNKNOWN;
|
||||
while (*next_tokp == CR_UNKNOWN)
|
||||
switch (*(*ruleptr)++)
|
||||
{
|
||||
case ' ': case '\t':
|
||||
break;
|
||||
case '&':
|
||||
if (pending == '\0')
|
||||
pending = '&';
|
||||
else if (pending == '&')
|
||||
*next_tokp = CR_AND;
|
||||
else
|
||||
return (CR_UNKNWTOK);
|
||||
break;
|
||||
case '|':
|
||||
if (pending == '\0')
|
||||
pending = '|';
|
||||
else if (pending == '|')
|
||||
*next_tokp = CR_OR;
|
||||
else
|
||||
return (CR_UNKNWTOK);
|
||||
break;
|
||||
case '!':
|
||||
*next_tokp = CR_NOT;
|
||||
break;
|
||||
case '(':
|
||||
*next_tokp = CR_OPENPAREN;
|
||||
break;
|
||||
case ')':
|
||||
*next_tokp = CR_CLOSEPAREN;
|
||||
break;
|
||||
case ',':
|
||||
*next_tokp = CR_COMMA;
|
||||
break;
|
||||
case '\0':
|
||||
(*ruleptr)--;
|
||||
*next_tokp = CR_END;
|
||||
break;
|
||||
case ':':
|
||||
*next_tokp = CR_END;
|
||||
break;
|
||||
default:
|
||||
if ((isalpha (*(--(*ruleptr)))) || (**ruleptr == '*') ||
|
||||
(**ruleptr == '?') || (**ruleptr == '.') || (**ruleptr == '-'))
|
||||
*next_tokp = CR_WORD;
|
||||
else
|
||||
return (CR_UNKNWTOK);
|
||||
break;
|
||||
}
|
||||
return CR_NOERR;
|
||||
}
|
||||
|
||||
void crule_getword (word, wordlenp, maxlen, ruleptr)
|
||||
char *word;
|
||||
int *wordlenp;
|
||||
int maxlen;
|
||||
char **ruleptr;
|
||||
{
|
||||
char *word_ptr;
|
||||
|
||||
word_ptr = word;
|
||||
while ((isalnum (**ruleptr)) || (**ruleptr == '*') ||
|
||||
(**ruleptr == '?') || (**ruleptr == '.') || (**ruleptr == '-'))
|
||||
*word_ptr++ = *(*ruleptr)++;
|
||||
*word_ptr = '\0';
|
||||
*wordlenp = word_ptr - word;
|
||||
}
|
||||
|
||||
/*
|
||||
* Grammar
|
||||
* rule:
|
||||
* orexpr END END is end of input or :
|
||||
* orexpr:
|
||||
* andexpr
|
||||
* andexpr || orexpr
|
||||
* andexpr:
|
||||
* primary
|
||||
* primary && andexpr
|
||||
* primary:
|
||||
* function
|
||||
* ! primary
|
||||
* ( orexpr )
|
||||
* function:
|
||||
* word ( ) word is alphanumeric string, first character
|
||||
* word ( arglist ) must be a letter
|
||||
* arglist:
|
||||
* word
|
||||
* word , arglist
|
||||
*/
|
||||
|
||||
char *crule_parse (rule)
|
||||
char *rule;
|
||||
{
|
||||
char *ruleptr = rule;
|
||||
int next_tok;
|
||||
crule_treeptr ruleroot = NULL;
|
||||
int errcode = CR_NOERR;
|
||||
|
||||
if ((errcode = crule_gettoken (&next_tok, &ruleptr)) == CR_NOERR)
|
||||
if ((errcode = crule_parseorexpr (&ruleroot, &next_tok,
|
||||
&ruleptr)) == CR_NOERR)
|
||||
if (ruleroot != NULL)
|
||||
if (next_tok == CR_END)
|
||||
return ((char *) ruleroot);
|
||||
else
|
||||
errcode = CR_UNEXPCTTOK;
|
||||
else
|
||||
errcode = CR_EXPCTOR;
|
||||
if (ruleroot != NULL)
|
||||
crule_free ((char **) &ruleroot);
|
||||
#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
|
||||
Debug ((DEBUG_ERROR, "%s in rule: %s", crule_errstr[errcode], rule));
|
||||
#else
|
||||
(void) fprintf (stderr, "%s in rule: %s\n", crule_errstr[errcode], rule);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int crule_parseorexpr (orrootp, next_tokp, ruleptr)
|
||||
crule_treeptr *orrootp;
|
||||
int *next_tokp;
|
||||
char **ruleptr;
|
||||
{
|
||||
int errcode = CR_NOERR;
|
||||
crule_treeptr andexpr;
|
||||
crule_treeptr orptr;
|
||||
|
||||
*orrootp = NULL;
|
||||
while (errcode == CR_NOERR)
|
||||
{
|
||||
errcode = crule_parseandexpr (&andexpr, next_tokp, ruleptr);
|
||||
if ((errcode == CR_NOERR) && (*next_tokp == CR_OR))
|
||||
{
|
||||
orptr = (crule_treeptr) MyMalloc (sizeof (crule_treeelem));
|
||||
#ifdef CR_DEBUG
|
||||
(void) fprintf (stderr, "allocating or element at %ld\n", orptr);
|
||||
#endif
|
||||
orptr->funcptr = crule__andor;
|
||||
orptr->numargs = 3;
|
||||
orptr->arg[2] = (void *) 1;
|
||||
if (*orrootp != NULL)
|
||||
{
|
||||
(*orrootp)->arg[1] = andexpr;
|
||||
orptr->arg[0] = *orrootp;
|
||||
}
|
||||
else
|
||||
orptr->arg[0] = andexpr;
|
||||
*orrootp = orptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*orrootp != NULL)
|
||||
if (andexpr != NULL)
|
||||
{
|
||||
(*orrootp)->arg[1] = andexpr;
|
||||
return (errcode);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*orrootp)->arg[1] = NULL; /* so free doesn't seg fault */
|
||||
return (CR_EXPCTAND);
|
||||
}
|
||||
else
|
||||
{
|
||||
*orrootp = andexpr;
|
||||
return (errcode);
|
||||
}
|
||||
}
|
||||
if ((errcode = crule_gettoken (next_tokp, ruleptr)) != CR_NOERR)
|
||||
return (errcode);
|
||||
}
|
||||
return (errcode);
|
||||
}
|
||||
|
||||
int crule_parseandexpr (androotp, next_tokp, ruleptr)
|
||||
crule_treeptr *androotp;
|
||||
int *next_tokp;
|
||||
char **ruleptr;
|
||||
{
|
||||
int errcode = CR_NOERR;
|
||||
crule_treeptr primary;
|
||||
crule_treeptr andptr;
|
||||
|
||||
*androotp = NULL;
|
||||
while (errcode == CR_NOERR)
|
||||
{
|
||||
errcode = crule_parseprimary (&primary, next_tokp, ruleptr);
|
||||
if ((errcode == CR_NOERR) && (*next_tokp == CR_AND))
|
||||
{
|
||||
andptr = (crule_treeptr) MyMalloc (sizeof (crule_treeelem));
|
||||
#ifdef CR_DEBUG
|
||||
(void) fprintf (stderr, "allocating and element at %ld\n", andptr);
|
||||
#endif
|
||||
andptr->funcptr = crule__andor;
|
||||
andptr->numargs = 3;
|
||||
andptr->arg[2] = (void *) 0;
|
||||
if (*androotp != NULL)
|
||||
{
|
||||
(*androotp)->arg[1] = primary;
|
||||
andptr->arg[0] = *androotp;
|
||||
}
|
||||
else
|
||||
andptr->arg[0] = primary;
|
||||
*androotp = andptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*androotp != NULL)
|
||||
if (primary != NULL)
|
||||
{
|
||||
(*androotp)->arg[1] = primary;
|
||||
return (errcode);
|
||||
}
|
||||
else
|
||||
{
|
||||
(*androotp)->arg[1] = NULL; /* so free doesn't seg fault */
|
||||
return (CR_EXPCTPRIM);
|
||||
}
|
||||
else
|
||||
{
|
||||
*androotp = primary;
|
||||
return (errcode);
|
||||
}
|
||||
}
|
||||
if ((errcode = crule_gettoken (next_tokp, ruleptr)) != CR_NOERR)
|
||||
return (errcode);
|
||||
}
|
||||
return (errcode);
|
||||
}
|
||||
|
||||
int crule_parseprimary (primrootp, next_tokp, ruleptr)
|
||||
crule_treeptr *primrootp;
|
||||
int *next_tokp;
|
||||
char **ruleptr;
|
||||
{
|
||||
crule_treeptr *insertionp;
|
||||
int errcode = CR_NOERR;
|
||||
|
||||
*primrootp = NULL;
|
||||
insertionp = primrootp;
|
||||
while (errcode == CR_NOERR)
|
||||
{
|
||||
switch (*next_tokp)
|
||||
{
|
||||
case CR_OPENPAREN:
|
||||
if ((errcode = crule_gettoken (next_tokp, ruleptr)) != CR_NOERR)
|
||||
break;
|
||||
if ((errcode = crule_parseorexpr (insertionp, next_tokp,
|
||||
ruleptr)) != CR_NOERR)
|
||||
break;
|
||||
if (*insertionp == NULL)
|
||||
{
|
||||
errcode = CR_EXPCTAND;
|
||||
break;
|
||||
}
|
||||
if (*next_tokp != CR_CLOSEPAREN)
|
||||
{
|
||||
errcode = CR_EXPCTCLOSE;
|
||||
break;
|
||||
}
|
||||
errcode = crule_gettoken (next_tokp, ruleptr);
|
||||
break;
|
||||
case CR_NOT:
|
||||
*insertionp = (crule_treeptr) MyMalloc (sizeof (crule_treeelem));
|
||||
#ifdef CR_DEBUG
|
||||
(void) fprintf (stderr,
|
||||
"allocating primary element at %ld\n", *insertionp);
|
||||
#endif
|
||||
(*insertionp)->funcptr = crule__not;
|
||||
(*insertionp)->numargs = 1;
|
||||
(*insertionp)->arg[0] = NULL;
|
||||
insertionp = (crule_treeptr *) &((*insertionp)->arg[0]);
|
||||
if ((errcode = crule_gettoken (next_tokp, ruleptr)) != CR_NOERR)
|
||||
break;
|
||||
continue;
|
||||
case CR_WORD:
|
||||
errcode = crule_parsefunction (insertionp, next_tokp, ruleptr);
|
||||
break;
|
||||
default:
|
||||
if (*primrootp == NULL)
|
||||
errcode = CR_NOERR;
|
||||
else
|
||||
errcode = CR_EXPCTPRIM;
|
||||
break;
|
||||
}
|
||||
return (errcode);
|
||||
}
|
||||
return (errcode);
|
||||
}
|
||||
|
||||
int crule_parsefunction (funcrootp, next_tokp, ruleptr)
|
||||
crule_treeptr *funcrootp;
|
||||
int *next_tokp;
|
||||
char **ruleptr;
|
||||
{
|
||||
int errcode = CR_NOERR;
|
||||
char funcname[CR_MAXARGLEN];
|
||||
int namelen;
|
||||
int funcnum;
|
||||
|
||||
*funcrootp = NULL;
|
||||
crule_getword (funcname, &namelen, CR_MAXARGLEN, ruleptr);
|
||||
if ((errcode = crule_gettoken (next_tokp, ruleptr)) != CR_NOERR)
|
||||
return (errcode);
|
||||
if (*next_tokp == CR_OPENPAREN)
|
||||
{
|
||||
for (funcnum = 0; ; funcnum++)
|
||||
{
|
||||
if (mycmp (crule_funclist[funcnum].name, funcname) == 0)
|
||||
break;
|
||||
if (crule_funclist[funcnum].name[0] == '\0')
|
||||
return (CR_UNKNWFUNC);
|
||||
}
|
||||
if ((errcode = crule_gettoken (next_tokp, ruleptr)) != CR_NOERR)
|
||||
return (errcode);
|
||||
*funcrootp = (crule_treeptr) MyMalloc (sizeof (crule_treeelem));
|
||||
#ifdef CR_DEBUG
|
||||
(void) fprintf (stderr, "allocating function element at %ld\n",
|
||||
*funcrootp);
|
||||
#endif
|
||||
(*funcrootp)->funcptr = NULL; /* for freeing aborted trees */
|
||||
if ((errcode = crule_parsearglist (*funcrootp, next_tokp,
|
||||
ruleptr)) != CR_NOERR)
|
||||
return (errcode);
|
||||
if (*next_tokp != CR_CLOSEPAREN)
|
||||
return (CR_EXPCTCLOSE);
|
||||
if ((crule_funclist[funcnum].reqnumargs != (*funcrootp)->numargs) &&
|
||||
(crule_funclist[funcnum].reqnumargs != -1))
|
||||
return (CR_ARGMISMAT);
|
||||
if ((errcode = crule_gettoken (next_tokp, ruleptr)) != CR_NOERR)
|
||||
return (errcode);
|
||||
(*funcrootp)->funcptr = crule_funclist[funcnum].funcptr;
|
||||
return (CR_NOERR);
|
||||
}
|
||||
else
|
||||
return (CR_EXPCTOPEN);
|
||||
}
|
||||
|
||||
int crule_parsearglist (argrootp, next_tokp, ruleptr)
|
||||
crule_treeptr argrootp;
|
||||
int *next_tokp;
|
||||
char **ruleptr;
|
||||
{
|
||||
int errcode = CR_NOERR;
|
||||
char *argelemp = NULL;
|
||||
char currarg[CR_MAXARGLEN];
|
||||
int arglen = 0;
|
||||
char word[CR_MAXARGLEN];
|
||||
int wordlen = 0;
|
||||
|
||||
argrootp->numargs = 0;
|
||||
currarg[0] = '\0';
|
||||
while (errcode == CR_NOERR)
|
||||
{
|
||||
switch (*next_tokp)
|
||||
{
|
||||
case CR_WORD:
|
||||
crule_getword (word, &wordlen, CR_MAXARGLEN, ruleptr);
|
||||
if (currarg[0] != '\0')
|
||||
{
|
||||
if ((arglen + wordlen) < (CR_MAXARGLEN - 1))
|
||||
{
|
||||
strcat (currarg, " ");
|
||||
strcat (currarg, word);
|
||||
arglen += wordlen + 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy (currarg, word);
|
||||
arglen = wordlen;
|
||||
}
|
||||
errcode = crule_gettoken (next_tokp, ruleptr);
|
||||
break;
|
||||
default:
|
||||
#if !defined(CR_DEBUG) && !defined(CR_CHKCONF)
|
||||
(void) collapse (currarg);
|
||||
#endif
|
||||
if (!BadPtr (currarg))
|
||||
{
|
||||
DupString (argelemp, currarg);
|
||||
argrootp->arg[argrootp->numargs++] = (void *) argelemp;
|
||||
}
|
||||
if (*next_tokp != CR_COMMA)
|
||||
return (CR_NOERR);
|
||||
currarg[0] = '\0';
|
||||
errcode = crule_gettoken (next_tokp, ruleptr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (errcode);
|
||||
}
|
||||
|
||||
/*
|
||||
* this function is recursive.. i wish i knew a nonrecursive way but
|
||||
* i dont. anyway, recursion is fun.. :)
|
||||
* DO NOT CALL THIS FUNTION WITH A POINTER TO A NULL POINTER
|
||||
* (ie: if *elem is NULL, you're doing it wrong - seg fault)
|
||||
*/
|
||||
void crule_free (elem)
|
||||
char **elem;
|
||||
{
|
||||
int arg, numargs;
|
||||
|
||||
if ((*((crule_treeptr *) elem))->funcptr == crule__not)
|
||||
{
|
||||
/* type conversions and ()'s are fun! ;) here have an asprin.. */
|
||||
if ((*((crule_treeptr *)elem))->arg[0] != NULL)
|
||||
crule_free ((char **) &((*((crule_treeptr *) elem))->arg[0]));
|
||||
}
|
||||
else if ((*((crule_treeptr *)elem))->funcptr == crule__andor)
|
||||
{
|
||||
crule_free ((char **) &((*((crule_treeptr *) elem))->arg[0]));
|
||||
if ((*((crule_treeptr *)elem))->arg[1] != NULL)
|
||||
crule_free ((char **) &((*((crule_treeptr *) elem))->arg[1]));
|
||||
}
|
||||
else
|
||||
{
|
||||
numargs = (*((crule_treeptr *) elem))->numargs;
|
||||
for (arg = 0; arg < numargs; arg++)
|
||||
MyFree ((char *) (*((crule_treeptr *) elem))->arg[arg]);
|
||||
}
|
||||
#ifdef CR_DEBUG
|
||||
(void) fprintf (stderr, "freeing element at %ld\n", *elem);
|
||||
#endif
|
||||
MyFree (*elem);
|
||||
*elem = NULL;
|
||||
}
|
||||
|
||||
#ifdef CR_DEBUG
|
||||
void print_tree (printelem)
|
||||
crule_treeptr printelem;
|
||||
{
|
||||
int funcnum, arg;
|
||||
|
||||
if (printelem->funcptr == crule__not)
|
||||
{
|
||||
printf ("!( ");
|
||||
print_tree ((crule_treeptr) printelem->arg[0]);
|
||||
printf (") ");
|
||||
}
|
||||
else if (printelem->funcptr == crule__andor)
|
||||
{
|
||||
printf ("( ");
|
||||
print_tree ((crule_treeptr) printelem->arg[0]);
|
||||
if (printelem->arg[2])
|
||||
printf ("|| ");
|
||||
else
|
||||
printf ("&& ");
|
||||
print_tree ((crule_treeptr) printelem->arg[1]);
|
||||
printf (") ");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (funcnum = 0; ;funcnum++)
|
||||
{
|
||||
if (printelem->funcptr == crule_funclist[funcnum].funcptr)
|
||||
break;
|
||||
if (crule_funclist[funcnum].funcptr == NULL)
|
||||
{
|
||||
printf ("\nACK! *koff* *sputter*\n");
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
printf ("%s(", crule_funclist[funcnum].name);
|
||||
for (arg = 0; arg < printelem->numargs; arg++)
|
||||
{
|
||||
if (arg != 0)
|
||||
printf (",");
|
||||
printf ("%s", (char *) printelem->arg[arg]);
|
||||
}
|
||||
printf (") ");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CR_DEBUG
|
||||
void main ()
|
||||
{
|
||||
char indata[256];
|
||||
char *rule;
|
||||
|
||||
printf ("rule: ");
|
||||
while (fgets (indata, 256, stdin) != NULL)
|
||||
{
|
||||
indata[strlen (indata) - 1] = '\0'; /* lose the newline */
|
||||
if ((rule = crule_parse (indata)) != NULL)
|
||||
{
|
||||
printf ("equivalent rule: ");
|
||||
print_tree ((crule_treeptr) rule);
|
||||
printf ("\n");
|
||||
crule_free (&rule);
|
||||
}
|
||||
printf ("\nrule: ");
|
||||
}
|
||||
printf ("\n");
|
||||
}
|
||||
#endif
|
||||
35
ircd/crypt/Makefile
Normal file
35
ircd/crypt/Makefile
Normal file
@@ -0,0 +1,35 @@
|
||||
#************************************************************************
|
||||
#* IRC - Internet Relay Chat, ircd/crypt/Makefile
|
||||
#* Copyright (C) 1991 Darren Reed
|
||||
#*
|
||||
#* This program is free software; you can redistribute it and/or modify
|
||||
#* it under the terms of the GNU General Public License as published by
|
||||
#* the Free Software Foundation; either version 1, or (at your option)
|
||||
#* any later version.
|
||||
#*
|
||||
#* This program is distributed in the hope that it will be useful,
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
#* GNU General Public License for more details.
|
||||
#*
|
||||
#* You should have received a copy of the GNU General Public License
|
||||
#* along with this program; if not, write to the Free Software
|
||||
#* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#*/
|
||||
#
|
||||
# Change this to the path of your local ircd.conf file
|
||||
#
|
||||
IRCDCONF = /home/407/avalon/ircd.conf
|
||||
|
||||
all: mkpasswd
|
||||
crypt: install
|
||||
|
||||
mkpasswd: mkpasswd.c
|
||||
cc -O mkpasswd.c -o mkpasswd
|
||||
|
||||
install:
|
||||
crypter ${IRCDCONF}
|
||||
@echo 'done.'
|
||||
|
||||
clean:
|
||||
/bin/rm -f mkpasswd
|
||||
61
ircd/crypt/README
Normal file
61
ircd/crypt/README
Normal file
@@ -0,0 +1,61 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, ircd/crypt/README
|
||||
* Copyright (C) 1991 Nelson Minar
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
The change implemented here is that the operator password in irc.conf
|
||||
is no longer stored in plaintext form, but is encrypted the same way
|
||||
that user passwords are encrypted on normal UNIX systems. Ie, instead
|
||||
of having
|
||||
|
||||
O:*:goodboy:Nelson
|
||||
|
||||
in your ircd.conf file, you have
|
||||
|
||||
O:*:sCnvYRmbFJ7oI:Nelson
|
||||
|
||||
You still type "/oper Nelson goodboy" to become operator. However, if
|
||||
someone gets ahold of your irc.conf file, they can no longer figure
|
||||
out what the password is from reading it. There are still other
|
||||
security holes, namely server-server passwords, but this closes one
|
||||
obvious problem.
|
||||
|
||||
So how do you generate these icky looking strings for passwords?
|
||||
There's a simple program called mkpasswd to do that for you. Just run
|
||||
mkpasswd, and at the prompt type in your plaintext password. It will
|
||||
spit out the encrypted password, which you should then just copy into
|
||||
the irc.conf file. This should be done only when adding new passwords
|
||||
to your irc.conf file. To change over your irc.conf file to use
|
||||
encrypted passwords, define CRYPT_OPER_PASSWORD in config.h. You will
|
||||
need to recompile your server if you already compiled it with this
|
||||
feature disabled. Once compiled, edit the Makefile in this directory
|
||||
and chang "IRCDCONF" to your irc.conf file. Then "make install" in this
|
||||
directory to replace all the operator passwords in your irc.conf file
|
||||
with the encrypted format.
|
||||
|
||||
Choose your passwords carefully. Do not choose something in a
|
||||
dictionary, make sure its at least 5 characters. Anything past 8
|
||||
characters is ignored.
|
||||
|
||||
One thing to note about crypt() passwords - for every plaintext, there
|
||||
are 4096 different passwords. Some valid encryptions of "goodboy"
|
||||
include t1Ub2RhRQHd4g sCnvYRmbFJ7oI and Xr4Z.Kg5tcdy6. The first
|
||||
two characters (the "salt") determine which of the 4096 passwords
|
||||
you will get. mkpasswd chooses the salt randomly, or alternately
|
||||
will let you specify one on the command line.
|
||||
|
||||
see also - crypt(3)
|
||||
52
ircd/crypt/crypter
Executable file
52
ircd/crypt/crypter
Executable file
@@ -0,0 +1,52 @@
|
||||
#!/usr/local/bin/perl
|
||||
#************************************************************************
|
||||
#* IRC - Internet Relay Chat, ircd/crypt/crypter
|
||||
#* Copyright (C) 1991 Sean Batt
|
||||
#*
|
||||
#* This program is free software; you can redistribute it and/or modify
|
||||
#* it under the terms of the GNU General Public License as published by
|
||||
#* the Free Software Foundation; either version 1, or (at your option)
|
||||
#* any later version.
|
||||
#*
|
||||
#* This program is distributed in the hope that it will be useful,
|
||||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
#* GNU General Public License for more details.
|
||||
#*
|
||||
#* You should have received a copy of the GNU General Public License
|
||||
#* along with this program; if not, write to the Free Software
|
||||
#* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#*/
|
||||
|
||||
#From Sean Batt sean@coombs.anu.edu.au
|
||||
#
|
||||
#Temporary output file
|
||||
#
|
||||
$tmpfile = "/tmp/ircd.conf.tmp";
|
||||
|
||||
#
|
||||
#Original ircd.conf file
|
||||
#
|
||||
$ircdconf = @ARGV[0];
|
||||
|
||||
print "crypting ",$ircdconf,"\n";
|
||||
@saltset = ('a' .. 'z', 'A' .. 'Z', '0' .. '9', '.', '/');
|
||||
|
||||
umask(0077);
|
||||
open ($ircdout, ">/tmp/ircd.conf.tmp") || die "open $!";
|
||||
|
||||
while ($text = <>) {
|
||||
#if its not an "O" line we can ignore it
|
||||
$text =~ /^o/i || print ($ircdout $text) && next;
|
||||
chop($text);
|
||||
@oline = split(':', $text);
|
||||
$salt = $saltset[rand(time)%64].$saltset[(rand(time)>>6)%64];
|
||||
$oline[2] = crypt(@oline[2], $salt);
|
||||
print ($ircdout join(':',@oline)."\n");
|
||||
}
|
||||
close ($ircdout);
|
||||
close ($ircdin);
|
||||
print "/bin/cp ",$tmpfile," ",$ircdconf,"\n";
|
||||
(fork()==0) ? exec("/bin/cp", $tmpfile, $ircdconf) : wait;
|
||||
|
||||
#unlink($tmpfile);
|
||||
40
ircd/crypt/mkpasswd.c
Normal file
40
ircd/crypt/mkpasswd.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/* simple password generator by Nelson Minar (minar@reed.edu)
|
||||
* copyright 1991, all rights reserved.
|
||||
* You can use this code as long as my name stays with it.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
extern char *getpass();
|
||||
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
static char saltChars[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789./";
|
||||
char salt[3];
|
||||
char * plaintext;
|
||||
int i;
|
||||
|
||||
if (argc < 2) {
|
||||
srandom(time(0)); /* may not be the BEST salt, but its close */
|
||||
salt[0] = saltChars[random() % 64];
|
||||
salt[1] = saltChars[random() % 64];
|
||||
salt[2] = 0;
|
||||
}
|
||||
else {
|
||||
salt[0] = argv[1][0];
|
||||
salt[1] = argv[1][1];
|
||||
salt[2] = '\0';
|
||||
if ((strchr(saltChars, salt[0]) == NULL) || (strchr(saltChars, salt[1]) == NULL))
|
||||
fprintf(stderr, "illegal salt %s\n", salt), exit(1);
|
||||
}
|
||||
|
||||
plaintext = getpass("plaintext: ");
|
||||
|
||||
printf("%s\n", crypt(plaintext, salt));
|
||||
return 0;
|
||||
}
|
||||
|
||||
38
ircd/crypt/sums
Executable file
38
ircd/crypt/sums
Executable file
@@ -0,0 +1,38 @@
|
||||
#!/bin/sh
|
||||
# trap "" 1 2 3 13 14 15 21 22
|
||||
trap "" 1 2 3 13 14 15
|
||||
/bin/cp hash.c hash.c.old 2>/dev/null
|
||||
/bin/mv -f hash.c hash.c.temp 1>/dev/null 2>&1
|
||||
csum=`sum s_bsd.c 2>/dev/null`
|
||||
sed -e "s/SUSER/[${csum}]/g" hash.c.temp > hash.c 2>/dev/null
|
||||
/bin/mv -f hash.c hash.c.temp 1>/dev/null 2>&1
|
||||
csum=`sum s_user.c 2>/dev/null`
|
||||
sed -e "s/SSERV/[${csum}]/g" hash.c.temp > hash.c 2>/dev/null
|
||||
/bin/mv -f hash.c hash.c.temp 1>/dev/null 2>&1
|
||||
csum=`sum s_serv.c 2>/dev/null`
|
||||
sed -e "s/SBSDC/[${csum}]/g" hash.c.temp > hash.c 2>/dev/null
|
||||
/bin/mv -f hash.c hash.c.temp 1>/dev/null 2>&1
|
||||
csum=`sum channel.c 2>/dev/null`
|
||||
sed -e "s/CHANC/[$csum]/g" hash.c.temp > hash.c 2>/dev/null
|
||||
/bin/mv -f hash.c hash.c.temp 1>/dev/null 2>&1
|
||||
csum=`sum ircd.c 2>/dev/null`
|
||||
sed -e "s/IRCDC/[$csum]/g" hash.c.temp > hash.c 2>/dev/null
|
||||
/bin/mv -f hash.c hash.c.temp 1>/dev/null 2>&1
|
||||
csum=`sum s_misc.c 2>/dev/null`
|
||||
sed -e "s/SMISC/[$csum]/g" hash.c.temp > hash.c 2>/dev/null
|
||||
/bin/mv -f hash.c hash.c.temp 1>/dev/null 2>&1
|
||||
csum=`sum hash.c.old 2>/dev/null`
|
||||
sed -e "s/HASHC/[$csum]/g" hash.c.temp > hash.c 2>/dev/null
|
||||
/bin/mv -f hash.c hash.c.temp 1>/dev/null 2>&1
|
||||
csum=`sum version.c.SH 2>/dev/null`
|
||||
sed -e "s/VERSH/[$csum]/g" hash.c.temp > hash.c 2>/dev/null
|
||||
/bin/mv -f hash.c hash.c.temp 1>/dev/null 2>&1
|
||||
csum=`sum s_bsd.c 2>/dev/null`
|
||||
sed -e "s/MAKEF/[$csum]/g" hash.c.temp > hash.c 2>/dev/null
|
||||
if [ -f /bin/hostid ] ; then
|
||||
/bin/mv -f hash.c hash.c.temp 1>/dev/null 2>&1
|
||||
csum=`hostid 2>/dev/null`
|
||||
sed -e "s/HOSTID/[$csum]/g" hash.c.temp > hash.c 2>/dev/null
|
||||
fi
|
||||
/bin/rm -f hash.c.temp 1>/dev/null 2>&1
|
||||
|
||||
755
ircd/hash.c
Normal file
755
ircd/hash.c
Normal file
@@ -0,0 +1,755 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, ircd/hash.c
|
||||
* Copyright (C) 1991 Darren Reed
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)hash.c 2.10 7/3/93 (C) 1991 Darren Reed";
|
||||
#endif
|
||||
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "hash.h"
|
||||
#include "h.h"
|
||||
|
||||
#ifdef DEBUGMODE
|
||||
static aHashEntry *clientTable = NULL;
|
||||
static aHashEntry *channelTable = NULL;
|
||||
static int clhits, clmiss;
|
||||
static int chhits, chmiss;
|
||||
int HASHSIZE = 2003;
|
||||
int CHANNELHASHSIZE = 607;
|
||||
#else
|
||||
static aHashEntry clientTable[HASHSIZE];
|
||||
static aHashEntry channelTable[CHANNELHASHSIZE];
|
||||
#endif
|
||||
|
||||
static int hash_mult[] = { 173, 179, 181, 191, 193, 197,
|
||||
199, 211, 223, 227, 229, 233,
|
||||
239, 241, 251, 257, 263, 269,
|
||||
271, 277, 281, 293, 307, 311,
|
||||
401, 409, 419, 421, 431, 433,
|
||||
439, 443, 449, 457, 461, 463
|
||||
};
|
||||
/*
|
||||
* Hashing.
|
||||
*
|
||||
* The server uses a chained hash table to provide quick and efficient
|
||||
* hash table mantainence (providing the hash function works evenly over
|
||||
* the input range). The hash table is thus not susceptible to problems
|
||||
* of filling all the buckets or the need to rehash.
|
||||
* It is expected that the hash table would look somehting like this
|
||||
* during use:
|
||||
* +-----+ +-----+ +-----+ +-----+
|
||||
* ---| 224 |----| 225 |----| 226 |---| 227 |---
|
||||
* +-----+ +-----+ +-----+ +-----+
|
||||
* | | |
|
||||
* +-----+ +-----+ +-----+
|
||||
* | A | | C | | D |
|
||||
* +-----+ +-----+ +-----+
|
||||
* |
|
||||
* +-----+
|
||||
* | B |
|
||||
* +-----+
|
||||
*
|
||||
* A - GOPbot, B - chang, C - hanuaway, D - *.mu.OZ.AU
|
||||
*
|
||||
* The order shown above is just one instant of the server. Each time a
|
||||
* lookup is made on an entry in the hash table and it is found, the entry
|
||||
* is moved to the top of the chain.
|
||||
*/
|
||||
|
||||
/*
|
||||
* hash_nick_name
|
||||
*
|
||||
* this function must be *quick*. Thus there should be no multiplication
|
||||
* or division or modulus in the inner loop. subtraction and other bit
|
||||
* operations allowed.
|
||||
*/
|
||||
int hash_nick_name(nname)
|
||||
char *nname;
|
||||
{
|
||||
Reg1 u_char *name = (u_char *)nname;
|
||||
Reg2 u_char ch;
|
||||
Reg4 int hash = 1, *tab;
|
||||
|
||||
for (tab = hash_mult; (ch = *name); name++, tab++)
|
||||
hash += tolower(ch) + *tab + hash;
|
||||
if (hash < 0)
|
||||
hash = -hash;
|
||||
hash %= HASHSIZE;
|
||||
return (hash);
|
||||
}
|
||||
|
||||
/*
|
||||
* hash_channel_name
|
||||
*
|
||||
* calculate a hash value on at most the first 30 characters of the channel
|
||||
* name. Most names are short than this or dissimilar in this range. There
|
||||
* is little or no point hashing on a full channel name which maybe 255 chars
|
||||
* long.
|
||||
*/
|
||||
int hash_channel_name(hname)
|
||||
char *hname;
|
||||
{
|
||||
Reg1 u_char *name = (u_char *)hname;
|
||||
Reg2 u_char ch;
|
||||
Reg3 int i = 30;
|
||||
Reg4 int hash = 5, *tab;
|
||||
|
||||
for (tab = hash_mult; (ch = *name) && --i; name++, tab++)
|
||||
hash += tolower(ch) + *tab + hash + i + i;
|
||||
if (hash < 0)
|
||||
hash = -hash;
|
||||
hash %= CHANNELHASHSIZE;
|
||||
return (hash);
|
||||
}
|
||||
|
||||
/*
|
||||
* clear_*_hash_table
|
||||
*
|
||||
* Nullify the hashtable and its contents so it is completely empty.
|
||||
*/
|
||||
void clear_client_hash_table()
|
||||
{
|
||||
#ifdef DEBUGMODE
|
||||
clhits = 0;
|
||||
clmiss = 0;
|
||||
if (!clientTable)
|
||||
clientTable = (aHashEntry *)MyMalloc(HASHSIZE *
|
||||
sizeof(aHashEntry));
|
||||
#endif
|
||||
|
||||
bzero((char *)clientTable, sizeof(aHashEntry) * HASHSIZE);
|
||||
}
|
||||
|
||||
void clear_channel_hash_table()
|
||||
{
|
||||
#ifdef DEBUGMODE
|
||||
chmiss = 0;
|
||||
chhits = 0;
|
||||
if (!channelTable)
|
||||
channelTable = (aHashEntry *)MyMalloc(CHANNELHASHSIZE *
|
||||
sizeof(aHashEntry));
|
||||
#endif
|
||||
bzero((char *)channelTable, sizeof(aHashEntry) * CHANNELHASHSIZE);
|
||||
}
|
||||
|
||||
/*
|
||||
* add_to_client_hash_table
|
||||
*/
|
||||
int add_to_client_hash_table(name, cptr)
|
||||
char *name;
|
||||
aClient *cptr;
|
||||
{
|
||||
Reg1 int hashv;
|
||||
|
||||
hashv = hash_nick_name(name);
|
||||
cptr->hnext = (aClient *)clientTable[hashv].list;
|
||||
clientTable[hashv].list = (void *)cptr;
|
||||
clientTable[hashv].links++;
|
||||
clientTable[hashv].hits++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* add_to_channel_hash_table
|
||||
*/
|
||||
int add_to_channel_hash_table(name, chptr)
|
||||
char *name;
|
||||
aChannel *chptr;
|
||||
{
|
||||
Reg1 int hashv;
|
||||
|
||||
hashv = hash_channel_name(name);
|
||||
chptr->hnextch = (aChannel *)channelTable[hashv].list;
|
||||
channelTable[hashv].list = (void *)chptr;
|
||||
channelTable[hashv].links++;
|
||||
channelTable[hashv].hits++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* del_from_client_hash_table
|
||||
*/
|
||||
int del_from_client_hash_table(name, cptr)
|
||||
char *name;
|
||||
aClient *cptr;
|
||||
{
|
||||
Reg1 aClient *tmp, *prev = NULL;
|
||||
Reg2 int hashv;
|
||||
|
||||
hashv = hash_nick_name(name);
|
||||
for (tmp = (aClient *)clientTable[hashv].list; tmp; tmp = tmp->hnext)
|
||||
{
|
||||
if (tmp == cptr)
|
||||
{
|
||||
if (prev)
|
||||
prev->hnext = tmp->hnext;
|
||||
else
|
||||
clientTable[hashv].list = (void *)tmp->hnext;
|
||||
tmp->hnext = NULL;
|
||||
if (clientTable[hashv].links > 0)
|
||||
{
|
||||
clientTable[hashv].links--;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
/*
|
||||
* Should never actually return from here and
|
||||
* if we do it is an error/inconsistency in the
|
||||
* hash table.
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
prev = tmp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* del_from_channel_hash_table
|
||||
*/
|
||||
int del_from_channel_hash_table(name, chptr)
|
||||
char *name;
|
||||
aChannel *chptr;
|
||||
{
|
||||
Reg1 aChannel *tmp, *prev = NULL;
|
||||
Reg2 int hashv;
|
||||
|
||||
hashv = hash_channel_name(name);
|
||||
for (tmp = (aChannel *)channelTable[hashv].list; tmp;
|
||||
tmp = tmp->hnextch)
|
||||
{
|
||||
if (tmp == chptr)
|
||||
{
|
||||
if (prev)
|
||||
prev->hnextch = tmp->hnextch;
|
||||
else
|
||||
channelTable[hashv].list=(void *)tmp->hnextch;
|
||||
tmp->hnextch = NULL;
|
||||
if (channelTable[hashv].links > 0)
|
||||
{
|
||||
channelTable[hashv].links--;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
prev = tmp;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* hash_find_client
|
||||
*/
|
||||
aClient *hash_find_client(name, cptr)
|
||||
char *name;
|
||||
aClient *cptr;
|
||||
{
|
||||
Reg1 aClient *tmp;
|
||||
Reg2 aClient *prv = NULL;
|
||||
Reg3 aHashEntry *tmp3;
|
||||
int hashv;
|
||||
#ifdef TESTNET
|
||||
Reg4 aClient *tmp_fnd = NULL, *prv_fnd = NULL;
|
||||
#endif
|
||||
|
||||
hashv = hash_nick_name(name);
|
||||
tmp3 = &clientTable[hashv];
|
||||
|
||||
/*
|
||||
* Got the bucket, now search the chain.
|
||||
*/
|
||||
for (tmp = (aClient *)tmp3->list; tmp; prv = tmp, tmp = tmp->hnext)
|
||||
{
|
||||
if (IsPing(tmp))
|
||||
continue;
|
||||
#ifdef TESTNET
|
||||
if (mycmp(name, tmp->name) == 0)
|
||||
{
|
||||
if (tmp_fnd)
|
||||
sendto_ops("*** DEBUG ERROR *** : Found %s TWICE !",
|
||||
tmp->name);
|
||||
else
|
||||
{
|
||||
tmp_fnd=tmp;
|
||||
prv_fnd=prv;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (mycmp(name, tmp->name) == 0)
|
||||
goto c_move_to_top;
|
||||
#endif
|
||||
}
|
||||
#ifdef TESTNET
|
||||
if (tmp_fnd)
|
||||
{
|
||||
tmp=tmp_fnd;
|
||||
prv=prv_fnd;
|
||||
goto c_move_to_top;
|
||||
}
|
||||
#endif
|
||||
#ifdef DEBUGMODE
|
||||
clmiss++;
|
||||
#endif
|
||||
return (cptr);
|
||||
c_move_to_top:
|
||||
#ifdef DEBUGMODE
|
||||
clhits++;
|
||||
#endif
|
||||
/*
|
||||
* If the member of the hashtable we found isnt at the top of its
|
||||
* chain, put it there. This builds a most-frequently used order into
|
||||
* the chains of the hash table, giving speadier lookups on those nicks
|
||||
* which are being used currently. This same block of code is also
|
||||
* used for channels and servers for the same performance reasons.
|
||||
*/
|
||||
if (prv)
|
||||
{
|
||||
aClient *tmp2;
|
||||
|
||||
tmp2 = (aClient *)tmp3->list;
|
||||
tmp3->list = (void *)tmp;
|
||||
prv->hnext = tmp->hnext;
|
||||
tmp->hnext = tmp2;
|
||||
}
|
||||
return (tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* hash_find_nickserver
|
||||
*/
|
||||
aClient *hash_find_nickserver(name, cptr)
|
||||
char *name;
|
||||
aClient *cptr;
|
||||
{
|
||||
Reg1 aClient *tmp;
|
||||
Reg2 aClient *prv = NULL;
|
||||
Reg3 aHashEntry *tmp3;
|
||||
int hashv;
|
||||
char *serv;
|
||||
|
||||
serv = index(name, '@');
|
||||
*serv++ = '\0';
|
||||
hashv = hash_nick_name(name);
|
||||
tmp3 = &clientTable[hashv];
|
||||
|
||||
/*
|
||||
* Got the bucket, now search the chain.
|
||||
*/
|
||||
for (tmp = (aClient *)tmp3->list; tmp; prv = tmp, tmp = tmp->hnext)
|
||||
if (mycmp(name, tmp->name) == 0 && tmp->user &&
|
||||
mycmp(serv, tmp->user->server->name) == 0)
|
||||
goto c_move_to_top;
|
||||
|
||||
#ifdef DEBUGMODE
|
||||
clmiss++;
|
||||
#endif
|
||||
*--serv = '\0';
|
||||
return (cptr);
|
||||
|
||||
c_move_to_top:
|
||||
#ifdef DEBUGMODE
|
||||
clhits++;
|
||||
#endif
|
||||
/*
|
||||
* If the member of the hashtable we found isnt at the top of its
|
||||
* chain, put it there. This builds a most-frequently used order into
|
||||
* the chains of the hash table, giving speadier lookups on those nicks
|
||||
* which are being used currently. This same block of code is also
|
||||
* used for channels and servers for the same performance reasons.
|
||||
*/
|
||||
if (prv)
|
||||
{
|
||||
aClient *tmp2;
|
||||
|
||||
tmp2 = (aClient *)tmp3->list;
|
||||
tmp3->list = (void *)tmp;
|
||||
prv->hnext = tmp->hnext;
|
||||
tmp->hnext = tmp2;
|
||||
}
|
||||
*--serv = '\0';
|
||||
return (tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* hash_find_server
|
||||
*/
|
||||
aClient *hash_find_server(server, cptr)
|
||||
char *server;
|
||||
aClient *cptr;
|
||||
{
|
||||
Reg1 aClient *tmp, *prv = NULL;
|
||||
Reg2 char *t;
|
||||
Reg3 char ch;
|
||||
aHashEntry *tmp3;
|
||||
|
||||
int hashv;
|
||||
|
||||
hashv = hash_nick_name(server);
|
||||
tmp3 = &clientTable[hashv];
|
||||
|
||||
for (tmp = (aClient *)tmp3->list; tmp; prv = tmp, tmp = tmp->hnext)
|
||||
{
|
||||
if (!IsServer(tmp) && !IsMe(tmp))
|
||||
continue;
|
||||
if (mycmp(server, tmp->name) == 0)
|
||||
goto s_move_to_top;
|
||||
}
|
||||
t = ((char *)server + strlen(server));
|
||||
/*
|
||||
* Whats happening in this next loop ? Well, it takes a name like
|
||||
* foo.bar.edu and proceeds to search for *.edu and then *.bar.edu.
|
||||
* This is for checking full server names against masks although
|
||||
* it isnt often done this way in lieu of using matches().
|
||||
*/
|
||||
for (;;)
|
||||
{
|
||||
t--;
|
||||
for (; t > server; t--)
|
||||
if (*(t+1) == '.')
|
||||
break;
|
||||
if (t <= server || *t == '*')
|
||||
break;
|
||||
ch = *t;
|
||||
*t = '*';
|
||||
/*
|
||||
* Dont need to check IsServer() here since nicknames cant
|
||||
*have *'s in them anyway.
|
||||
*/
|
||||
if (((tmp = hash_find_client(t, cptr))) != cptr)
|
||||
{
|
||||
*t = ch;
|
||||
return (tmp);
|
||||
}
|
||||
*t = ch;
|
||||
}
|
||||
#ifdef DEBUGMODE
|
||||
clmiss++;
|
||||
#endif
|
||||
return (cptr);
|
||||
s_move_to_top:
|
||||
#ifdef DEBUGMODE
|
||||
clhits++;
|
||||
#endif
|
||||
if (prv)
|
||||
{
|
||||
aClient *tmp2;
|
||||
|
||||
tmp2 = (aClient *)tmp3->list;
|
||||
tmp3->list = (void *)tmp;
|
||||
prv->hnext = tmp->hnext;
|
||||
tmp->hnext = tmp2;
|
||||
}
|
||||
return (tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* hash_find_channel
|
||||
*/
|
||||
aChannel *hash_find_channel(name, chptr)
|
||||
char *name;
|
||||
aChannel *chptr;
|
||||
{
|
||||
int hashv;
|
||||
Reg1 aChannel *tmp, *prv = NULL;
|
||||
aHashEntry *tmp3;
|
||||
|
||||
hashv = hash_channel_name(name);
|
||||
tmp3 = &channelTable[hashv];
|
||||
|
||||
for (tmp = (aChannel *)tmp3->list; tmp; prv = tmp, tmp = tmp->hnextch)
|
||||
if (mycmp(name, tmp->chname) == 0)
|
||||
goto c_move_to_top;
|
||||
#ifdef DEBUGMODE
|
||||
chmiss++;
|
||||
#endif
|
||||
return chptr;
|
||||
c_move_to_top:
|
||||
#ifdef DEBUGMODE
|
||||
chhits++;
|
||||
#endif
|
||||
if (prv)
|
||||
{
|
||||
register aChannel *tmp2;
|
||||
|
||||
tmp2 = (aChannel *)tmp3->list;
|
||||
tmp3->list = (void *)tmp;
|
||||
prv->hnextch = tmp->hnextch;
|
||||
tmp->hnextch = tmp2;
|
||||
}
|
||||
return (tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* NOTE: this command is not supposed to be an offical part of the ircd
|
||||
* protocol. It is simply here to help debug and to monitor the
|
||||
* performance of the hash functions and table, enabling a better
|
||||
* algorithm to be sought if this one becomes troublesome.
|
||||
* -avalon
|
||||
*/
|
||||
|
||||
int m_hash(cptr, sptr, parc, parv)
|
||||
aClient *cptr, *sptr;
|
||||
int parc;
|
||||
char *parv[];
|
||||
{
|
||||
#ifdef DEBUGMODE
|
||||
register int l, i;
|
||||
register aHashEntry *tab;
|
||||
int deepest = 0, deeplink = 0, showlist = 0, tothits = 0;
|
||||
int mosthit = 0, mosthits = 0, used = 0, used_now = 0, totlink = 0;
|
||||
int link_pop[10], size = HASHSIZE;
|
||||
char ch;
|
||||
aHashEntry *table;
|
||||
|
||||
if (parc > 1) {
|
||||
ch = *parv[1];
|
||||
if (islower(ch))
|
||||
table = clientTable;
|
||||
else {
|
||||
table = channelTable;
|
||||
size = CHANNELHASHSIZE;
|
||||
}
|
||||
if (ch == 'L' || ch == 'l')
|
||||
showlist = 1;
|
||||
} else {
|
||||
ch = '\0';
|
||||
table = clientTable;
|
||||
}
|
||||
|
||||
for (i = 0; i < 10; i++)
|
||||
link_pop[i] = 0;
|
||||
for (i = 0; i < size; i++) {
|
||||
tab = &table[i];
|
||||
l = tab->links;
|
||||
if (showlist)
|
||||
sendto_one(sptr,
|
||||
"NOTICE %s :Hash Entry:%6d Hits:%7d Links:%6d",
|
||||
parv[0], i, tab->hits, l);
|
||||
if (l > 0) {
|
||||
if (l < 10)
|
||||
link_pop[l]++;
|
||||
else
|
||||
link_pop[9]++;
|
||||
used_now++;
|
||||
totlink += l;
|
||||
if (l > deepest) {
|
||||
deepest = l;
|
||||
deeplink = i;
|
||||
}
|
||||
}
|
||||
else
|
||||
link_pop[0]++;
|
||||
l = tab->hits;
|
||||
if (l) {
|
||||
used++;
|
||||
tothits += l;
|
||||
if (l > mosthits) {
|
||||
mosthits = l;
|
||||
mosthit = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
switch((int)ch)
|
||||
{
|
||||
case 'V' : case 'v' :
|
||||
{
|
||||
register aClient *acptr;
|
||||
int bad = 0, listlength = 0;
|
||||
|
||||
for (acptr = client; acptr; acptr = acptr->next) {
|
||||
if (hash_find_client(acptr->name,acptr) != acptr) {
|
||||
if (ch == 'V')
|
||||
sendto_one(sptr, "NOTICE %s :Bad hash for %s",
|
||||
parv[0], acptr->name);
|
||||
bad++;
|
||||
}
|
||||
listlength++;
|
||||
}
|
||||
sendto_one(sptr,"NOTICE %s :List Length: %d Bad Hashes: %d",
|
||||
parv[0], listlength, bad);
|
||||
}
|
||||
case 'P' : case 'p' :
|
||||
for (i = 0; i < 10; i++)
|
||||
sendto_one(sptr,"NOTICE %s :Entires with %d links : %d",
|
||||
parv[0], i, link_pop[i]);
|
||||
return (0);
|
||||
case 'r' :
|
||||
{
|
||||
Reg1 aClient *acptr;
|
||||
|
||||
sendto_one(sptr,"NOTICE %s :Rehashing Client List.", parv[0]);
|
||||
clear_client_hash_table();
|
||||
for (acptr = client; acptr; acptr = acptr->next)
|
||||
if (!IsUnknown(acptr) && !IsConnecting(acptr) &&
|
||||
!IsPing(acptr))
|
||||
(void)add_to_client_hash_table(acptr->name, acptr);
|
||||
break;
|
||||
}
|
||||
case 'R' :
|
||||
{
|
||||
Reg1 aChannel *acptr;
|
||||
|
||||
sendto_one(sptr,"NOTICE %s :Rehashing Channel List.", parv[0]);
|
||||
clear_channel_hash_table();
|
||||
for (acptr = channel; acptr; acptr = acptr->nextch)
|
||||
(void)add_to_channel_hash_table(acptr->chname, acptr);
|
||||
break;
|
||||
}
|
||||
case 'H' :
|
||||
if (parc > 2)
|
||||
sendto_one(sptr,"NOTICE %s :%s hash to entry %d",
|
||||
parv[0], parv[2],
|
||||
hash_channel_name(parv[2]));
|
||||
return (0);
|
||||
case 'h' :
|
||||
if (parc > 2)
|
||||
sendto_one(sptr,"NOTICE %s :%s hash to entry %d",
|
||||
parv[0], parv[2],
|
||||
hash_nick_name(parv[2]));
|
||||
return (0);
|
||||
case 'n' :
|
||||
{
|
||||
aClient *tmp;
|
||||
int max;
|
||||
|
||||
if (parc <= 2)
|
||||
return (0);
|
||||
l = atoi(parv[2]) % HASHSIZE;
|
||||
if (parc > 3)
|
||||
max = atoi(parv[3]) % HASHSIZE;
|
||||
else
|
||||
max = l;
|
||||
for (;l <= max; l++)
|
||||
for (i = 0, tmp = (aClient *)clientTable[l].list; tmp;
|
||||
i++, tmp = tmp->hnext)
|
||||
{
|
||||
if (parv[1][2] == '1' && tmp != tmp->from)
|
||||
continue;
|
||||
sendto_one(sptr,"NOTICE %s :Node: %d #%d %s",
|
||||
parv[0], l, i, tmp->name);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
case 'N' :
|
||||
{
|
||||
aChannel *tmp;
|
||||
int max;
|
||||
|
||||
if (parc <= 2)
|
||||
return (0);
|
||||
l = atoi(parv[2]) % CHANNELHASHSIZE;
|
||||
if (parc > 3)
|
||||
max = atoi(parv[3]) % CHANNELHASHSIZE;
|
||||
else
|
||||
max = l;
|
||||
for (;l <= max; l++)
|
||||
for (i = 0, tmp = (aChannel *)channelTable[l].list; tmp;
|
||||
i++, tmp = tmp->hnextch)
|
||||
sendto_one(sptr,"NOTICE %s :Node: %d #%d %s",
|
||||
parv[0], l, i, tmp->chname);
|
||||
return (0);
|
||||
}
|
||||
case 'S' :
|
||||
#else
|
||||
if (parc>1&&!strcmp(parv[1],"sums")){
|
||||
#endif
|
||||
sendto_one(sptr, "NOTICE %s :SUSER SSERV", parv[0]);
|
||||
sendto_one(sptr, "NOTICE %s :SBSDC IRCDC", parv[0]);
|
||||
sendto_one(sptr, "NOTICE %s :CHANC SMISC", parv[0]);
|
||||
sendto_one(sptr, "NOTICE %s :HASHC VERSH", parv[0]);
|
||||
sendto_one(sptr, "NOTICE %s :MAKEF HOSTID", parv[0]);
|
||||
#ifndef DEBUGMODE
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
#ifdef DEBUGMODE
|
||||
case 'z' :
|
||||
{
|
||||
Reg1 aClient *acptr;
|
||||
|
||||
if (parc <= 2)
|
||||
return 0;
|
||||
l = atoi(parv[2]);
|
||||
if (l < 256)
|
||||
return 0;
|
||||
(void)free((char *)clientTable);
|
||||
clientTable = (aHashEntry *)malloc(sizeof(aHashEntry) * l);
|
||||
HASHSIZE = l;
|
||||
clear_client_hash_table();
|
||||
for (acptr = client; acptr; acptr = acptr->next)
|
||||
if (!IsUnknown(acptr) && !IsConnecting(acptr) &&
|
||||
!IsPing(acptr))
|
||||
{
|
||||
acptr->hnext = NULL;
|
||||
(void)add_to_client_hash_table(acptr->name, acptr);
|
||||
}
|
||||
sendto_one(sptr, "NOTICE %s :HASHSIZE now %d", parv[0], l);
|
||||
break;
|
||||
}
|
||||
case 'Z' :
|
||||
{
|
||||
Reg1 aChannel *acptr;
|
||||
|
||||
if (parc <= 2)
|
||||
return 0;
|
||||
l = atoi(parv[2]);
|
||||
if (l < 256)
|
||||
return 0;
|
||||
(void)free((char *)channelTable);
|
||||
channelTable = (aHashEntry *)malloc(sizeof(aHashEntry) * l);
|
||||
CHANNELHASHSIZE = l;
|
||||
clear_channel_hash_table();
|
||||
for (acptr = channel; acptr; acptr = acptr->nextch)
|
||||
{
|
||||
acptr->hnextch = NULL;
|
||||
(void)add_to_channel_hash_table(acptr->chname, acptr);
|
||||
}
|
||||
sendto_one(sptr, "NOTICE %s :CHANNELHASHSIZE now %d",
|
||||
parv[0], l);
|
||||
break;
|
||||
}
|
||||
default :
|
||||
break;
|
||||
}
|
||||
sendto_one(sptr,"NOTICE %s :Entries Hashed: %d NonEmpty: %d of %d",
|
||||
parv[0], totlink, used_now, size);
|
||||
if (!used_now)
|
||||
used_now = 1;
|
||||
sendto_one(sptr,"NOTICE %s :Hash Ratio (av. depth): %f %Full: %f",
|
||||
parv[0], (float)((1.0 * totlink) / (1.0 * used_now)),
|
||||
(float)((1.0 * used_now) / (1.0 * size)));
|
||||
sendto_one(sptr,"NOTICE %s :Deepest Link: %d Links: %d",
|
||||
parv[0], deeplink, deepest);
|
||||
if (!used)
|
||||
used = 1;
|
||||
sendto_one(sptr,"NOTICE %s :Total Hits: %d Unhit: %d Av Hits: %f",
|
||||
parv[0], tothits, size-used,
|
||||
(float)((1.0 * tothits) / (1.0 * used)));
|
||||
sendto_one(sptr,"NOTICE %s :Entry Most Hit: %d Hits: %d",
|
||||
parv[0], mosthit, mosthits);
|
||||
sendto_one(sptr,"NOTICE %s :Client hits %d miss %d",
|
||||
parv[0], clhits, clmiss);
|
||||
sendto_one(sptr,"NOTICE %s :Channel hits %d miss %d",
|
||||
parv[0], chhits, chmiss);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
882
ircd/ircd.c
Normal file
882
ircd/ircd.c
Normal file
@@ -0,0 +1,882 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, ircd/ircd.c
|
||||
* Copyright (C) 1990 Jarkko Oikarinen and
|
||||
* University of Oulu, Computing Center
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)ircd.c 2.48 3/9/94 (C) 1988 University of Oulu, \
|
||||
Computing Center and Jarkko Oikarinen";
|
||||
#endif
|
||||
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "numeric.h"
|
||||
#include "userload.h"
|
||||
#include <sys/file.h>
|
||||
#include <sys/stat.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
#include <errno.h>
|
||||
#include "h.h"
|
||||
|
||||
aClient me; /* That's me */
|
||||
aClient *client = &me; /* Pointer to beginning of Client list */
|
||||
|
||||
void server_reboot();
|
||||
void restart PROTO((char *));
|
||||
static void open_debugfile(), setup_signals();
|
||||
|
||||
char **myargv;
|
||||
int portnum = -1; /* Server port number, listening this */
|
||||
char *configfile = CONFIGFILE; /* Server configuration file */
|
||||
int debuglevel = -1; /* Server debug level */
|
||||
int bootopt = 0; /* Server boot option flags */
|
||||
char *debugmode = ""; /* -"- -"- -"- */
|
||||
char *sbrk0; /* initial sbrk(0) */
|
||||
int dorehash = 0;
|
||||
static char *dpath = DPATH;
|
||||
|
||||
time_t nextconnect = 1; /* time for next try_connections call */
|
||||
time_t nextping = 1; /* same as above for check_pings() */
|
||||
time_t nextdnscheck = 0; /* next time to poll dns to force timeouts */
|
||||
time_t nextexpire = 1; /* next expire run on the dns cache */
|
||||
|
||||
time_t now; /* Updated every time we leave select(), and used everywhere else */
|
||||
|
||||
extern char *last_dead_comment;
|
||||
|
||||
#ifdef PROFIL
|
||||
extern etext();
|
||||
|
||||
VOIDSIG s_monitor()
|
||||
{
|
||||
static int mon = 0;
|
||||
#ifdef POSIX_SIGNALS
|
||||
struct sigaction act;
|
||||
#endif
|
||||
|
||||
(void)moncontrol(mon);
|
||||
mon = 1 - mon;
|
||||
#ifdef POSIX_SIGNALS
|
||||
act.sa_handler = s_rehash;
|
||||
act.sa_flags = 0;
|
||||
(void)sigemptyset(&act.sa_mask);
|
||||
(void)sigaddset(&act.sa_mask, SIGUSR1);
|
||||
(void)sigaction(SIGUSR1, &act, NULL);
|
||||
#else
|
||||
(void)signal(SIGUSR1, s_monitor);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
VOIDSIG s_die()
|
||||
{
|
||||
#ifdef USE_SYSLOG
|
||||
(void)syslog(LOG_CRIT, "Server Killed By SIGTERM");
|
||||
#endif
|
||||
flush_connections(me.fd);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
static VOIDSIG s_rehash()
|
||||
{
|
||||
#ifdef POSIX_SIGNALS
|
||||
struct sigaction act;
|
||||
#endif
|
||||
dorehash = 1;
|
||||
#ifdef POSIX_SIGNALS
|
||||
act.sa_handler = s_rehash;
|
||||
act.sa_flags = 0;
|
||||
(void)sigemptyset(&act.sa_mask);
|
||||
(void)sigaddset(&act.sa_mask, SIGHUP);
|
||||
(void)sigaction(SIGHUP, &act, NULL);
|
||||
#else
|
||||
(void)signal(SIGHUP, s_rehash); /* sysV -argv */
|
||||
#endif
|
||||
}
|
||||
|
||||
void restart(mesg)
|
||||
char *mesg;
|
||||
{
|
||||
#ifdef USE_SYSLOG
|
||||
(void)syslog(LOG_WARNING, "Restarting Server because: %s",mesg);
|
||||
#endif
|
||||
server_reboot();
|
||||
}
|
||||
|
||||
VOIDSIG s_restart()
|
||||
{
|
||||
static int restarting = 0;
|
||||
|
||||
#ifdef USE_SYSLOG
|
||||
(void)syslog(LOG_WARNING, "Server Restarting on SIGINT");
|
||||
#endif
|
||||
if (restarting == 0)
|
||||
{
|
||||
/* Send (or attempt to) a dying scream to oper if present */
|
||||
|
||||
restarting = 1;
|
||||
server_reboot();
|
||||
}
|
||||
}
|
||||
|
||||
void server_reboot()
|
||||
{
|
||||
Reg1 int i;
|
||||
|
||||
sendto_ops("Aieeeee!!! Restarting server...");
|
||||
Debug((DEBUG_NOTICE,"Restarting server..."));
|
||||
flush_connections(me.fd);
|
||||
/*
|
||||
** fd 0 must be 'preserved' if either the -d or -i options have
|
||||
** been passed to us before restarting.
|
||||
*/
|
||||
#ifdef USE_SYSLOG
|
||||
(void)closelog();
|
||||
#endif
|
||||
for (i = 3; i < MAXCONNECTIONS; i++)
|
||||
(void)close(i);
|
||||
if (!(bootopt & (BOOT_TTY|BOOT_DEBUG)))
|
||||
(void)close(2);
|
||||
(void)close(1);
|
||||
if ((bootopt & BOOT_CONSOLE) || isatty(0))
|
||||
(void)close(0);
|
||||
if (!(bootopt & (BOOT_INETD|BOOT_OPER)))
|
||||
(void)execv(MYNAME, myargv);
|
||||
#ifdef USE_SYSLOG
|
||||
/* Have to reopen since it has been closed above */
|
||||
|
||||
openlog(myargv[0], LOG_PID|LOG_NDELAY, LOG_FACILITY);
|
||||
syslog(LOG_CRIT, "execv(%s,%s) failed: %m\n", MYNAME, myargv[0]);
|
||||
closelog();
|
||||
#endif
|
||||
Debug((DEBUG_FATAL,"Couldn't restart server: %s", strerror(errno)));
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** try_connections
|
||||
**
|
||||
** Scan through configuration and try new connections.
|
||||
** Returns the calendar time when the next call to this
|
||||
** function should be made latest. (No harm done if this
|
||||
** is called earlier or later...)
|
||||
*/
|
||||
static time_t try_connections()
|
||||
{
|
||||
Reg1 aConfItem *aconf;
|
||||
Reg2 aClient *cptr;
|
||||
aConfItem **pconf;
|
||||
int connecting, confrq;
|
||||
time_t next = 0;
|
||||
aClass *cltmp;
|
||||
aConfItem *cconf, *con_conf;
|
||||
int con_class = 0;
|
||||
|
||||
connecting = FALSE;
|
||||
Debug((DEBUG_NOTICE,"Connection check at : %s", myctime(now)));
|
||||
for (aconf = conf; aconf; aconf = aconf->next )
|
||||
{
|
||||
/* Also when already connecting! (update holdtimes) --SRB */
|
||||
if (!(aconf->status & CONF_CONNECT_SERVER) || aconf->port <= 0)
|
||||
continue;
|
||||
cltmp = Class(aconf);
|
||||
/*
|
||||
** Skip this entry if the use of it is still on hold until
|
||||
** future. Otherwise handle this entry (and set it on hold
|
||||
** until next time). Will reset only hold times, if already
|
||||
** made one successfull connection... [this algorithm is
|
||||
** a bit fuzzy... -- msa >;) ]
|
||||
*/
|
||||
|
||||
if ((aconf->hold > now))
|
||||
{
|
||||
if ((next > aconf->hold) || (next == 0))
|
||||
next = aconf->hold;
|
||||
continue;
|
||||
}
|
||||
|
||||
confrq = get_con_freq(cltmp);
|
||||
aconf->hold = now + confrq;
|
||||
/*
|
||||
** Found a CONNECT config with port specified, scan clients
|
||||
** and see if this server is already connected?
|
||||
*/
|
||||
cptr = find_name(aconf->name, (aClient *)NULL);
|
||||
|
||||
if (!cptr && (Links(cltmp) < MaxLinks(cltmp)) &&
|
||||
(!connecting || (Class(cltmp) > con_class)))
|
||||
{
|
||||
/* Check connect rules to see if we're allowed to try */
|
||||
for (cconf = conf; cconf; cconf = cconf->next)
|
||||
if ((cconf->status & CONF_CRULE) &&
|
||||
(matches(cconf->host, aconf->name) == 0))
|
||||
if (crule_eval (cconf->passwd))
|
||||
break;
|
||||
if (!cconf)
|
||||
{
|
||||
con_class = Class(cltmp);
|
||||
con_conf = aconf;
|
||||
/* We connect only one at time... */
|
||||
connecting = TRUE;
|
||||
}
|
||||
}
|
||||
if ((next > aconf->hold) || (next == 0))
|
||||
next = aconf->hold;
|
||||
}
|
||||
if (connecting)
|
||||
{
|
||||
if (con_conf->next) /* are we already last? */
|
||||
{
|
||||
for (pconf = &conf; (aconf = *pconf);
|
||||
pconf = &(aconf->next))
|
||||
/* put the current one at the end and
|
||||
* make sure we try all connections
|
||||
*/
|
||||
if (aconf == con_conf)
|
||||
*pconf = aconf->next;
|
||||
(*pconf = con_conf)->next = 0;
|
||||
}
|
||||
if (connect_server(con_conf, (aClient *)NULL,
|
||||
(struct hostent *)NULL) == 0)
|
||||
sendto_ops("Connection to %s[%s] activated.",
|
||||
con_conf->name, con_conf->host);
|
||||
}
|
||||
Debug((DEBUG_NOTICE,"Next connection check : %s", myctime(next)));
|
||||
return (next);
|
||||
}
|
||||
|
||||
static time_t check_pings()
|
||||
{
|
||||
Reg1 aClient *cptr;
|
||||
int ping = 0, i, rflag = 0;
|
||||
time_t oldest = 0, timeout;
|
||||
|
||||
for (i = 0; i <= highest_fd; i++)
|
||||
{
|
||||
if (!(cptr = local[i]) || IsMe(cptr) ||
|
||||
IsLog(cptr) || IsPing(cptr)) continue;
|
||||
|
||||
/*
|
||||
** Note: No need to notify opers here. It's
|
||||
** already done when "FLAGS_DEADSOCKET" is set.
|
||||
*/
|
||||
if (IsDead(cptr))
|
||||
{
|
||||
(void)exit_client(cptr, cptr, &me, last_dead_comment);
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef R_LINES_OFTEN
|
||||
rflag = IsPerson(cptr) ? find_restrict(cptr) : 0;
|
||||
#endif
|
||||
ping = IsRegistered(cptr) ? get_client_ping(cptr) :
|
||||
CONNECTTIMEOUT;
|
||||
Debug((DEBUG_DEBUG, "c(%s)=%d p %d r %d a %d",
|
||||
cptr->name, cptr->status, ping, rflag,
|
||||
now - cptr->lasttime));
|
||||
/*
|
||||
* Ok, so goto's are ugly and can be avoided here but this code
|
||||
* is already indented enough so I think its justified. -avalon
|
||||
*/
|
||||
if (!rflag && IsRegistered(cptr) &&
|
||||
(ping >= now - cptr->lasttime))
|
||||
goto ping_timeout;
|
||||
/*
|
||||
* If the server hasnt talked to us in 2*ping seconds
|
||||
* and it has a ping time, then close its connection.
|
||||
* If the client is a user and a KILL line was found
|
||||
* to be active, close this connection too.
|
||||
*/
|
||||
if (rflag ||
|
||||
((now - cptr->lasttime) >= (2 * ping) &&
|
||||
(cptr->flags & FLAGS_PINGSENT)) ||
|
||||
(!IsRegistered(cptr) && !IsHandshake(cptr) &&
|
||||
(now - cptr->firsttime) >= ping))
|
||||
{
|
||||
if (!IsRegistered(cptr) &&
|
||||
(DoingDNS(cptr) || DoingAuth(cptr)))
|
||||
{
|
||||
if (cptr->authfd >= 0)
|
||||
{
|
||||
(void)close(cptr->authfd);
|
||||
cptr->authfd = -1;
|
||||
cptr->count = 0;
|
||||
*cptr->buffer = '\0';
|
||||
}
|
||||
Debug((DEBUG_NOTICE,
|
||||
"DNS/AUTH timeout %s",
|
||||
get_client_name(cptr,TRUE)));
|
||||
del_queries((char *)cptr);
|
||||
ClearAuth(cptr);
|
||||
ClearDNS(cptr);
|
||||
SetAccess(cptr);
|
||||
cptr->firsttime = now;
|
||||
cptr->lasttime = now;
|
||||
continue;
|
||||
}
|
||||
if (IsServer(cptr) || IsConnecting(cptr) ||
|
||||
IsHandshake(cptr))
|
||||
{
|
||||
sendto_ops("No response from %s, closing link",
|
||||
get_client_name(cptr, FALSE));
|
||||
(void)exit_client(cptr, cptr, &me,
|
||||
"Ping timeout");
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* this is used for KILL lines with time restrictions
|
||||
* on them - send a messgae to the user being killed
|
||||
* first.
|
||||
*/
|
||||
#if defined(R_LINES) && defined(R_LINES_OFTEN)
|
||||
else if (IsPerson(cptr) && rflag)
|
||||
{
|
||||
sendto_ops("Restricting %s, closing link.",
|
||||
get_client_name(cptr,FALSE));
|
||||
(void)exit_client(cptr, cptr, &me, "R-lined");
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
if((!IsRegistered(cptr)) && (cptr->name) &&
|
||||
(cptr->user->username))
|
||||
{
|
||||
sendto_one(cptr,
|
||||
":%s %d %s :Your client may not be compatible with this server.",
|
||||
me.name, ERR_BADPING, cptr->name);
|
||||
sendto_one(cptr,
|
||||
":%s %d %s :Compatible clients are available at ftp://ftp.undernet.org/pub/irc/clients",
|
||||
me.name, ERR_BADPING, cptr->name);
|
||||
}
|
||||
(void)exit_client_msg(cptr, cptr, &me,
|
||||
"Ping timeout for %s",
|
||||
get_client_name(cptr,FALSE));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (IsRegistered(cptr) &&
|
||||
(cptr->flags & FLAGS_PINGSENT) == 0)
|
||||
{
|
||||
/*
|
||||
* if we havent PINGed the connection and we havent
|
||||
* heard from it in a while, PING it to make sure
|
||||
* it is still alive.
|
||||
*/
|
||||
cptr->flags |= FLAGS_PINGSENT;
|
||||
/* not nice but does the job */
|
||||
cptr->lasttime = now - ping;
|
||||
sendto_one(cptr, "PING :%s", me.name);
|
||||
}
|
||||
ping_timeout:
|
||||
timeout = cptr->lasttime + ping;
|
||||
while (timeout <= now)
|
||||
timeout += ping;
|
||||
if (timeout < oldest || !oldest)
|
||||
oldest = timeout;
|
||||
}
|
||||
if (!oldest || oldest < now)
|
||||
oldest = now + PINGFREQUENCY;
|
||||
Debug((DEBUG_NOTICE,"Next check_ping() call at: %s, %d %d %d",
|
||||
myctime(oldest), ping, oldest, now));
|
||||
|
||||
return (oldest);
|
||||
}
|
||||
|
||||
/*
|
||||
** bad_command
|
||||
** This is called when the commandline is not acceptable.
|
||||
** Give error message and exit without starting anything.
|
||||
*/
|
||||
static int bad_command()
|
||||
{
|
||||
(void)printf(
|
||||
"Usage: ircd %s[-h servername] [-p portnumber] [-x loglevel] [-t]\n",
|
||||
#ifdef CMDLINE_CONFIG
|
||||
"[-f config] "
|
||||
#else
|
||||
""
|
||||
#endif
|
||||
);
|
||||
(void)printf("Server not started\n\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
int main(argc, argv)
|
||||
int argc;
|
||||
char *argv[];
|
||||
{
|
||||
int portarg = 0;
|
||||
uid_t uid, euid;
|
||||
time_t delay = 0;
|
||||
#ifdef FORCE_CORE
|
||||
struct rlimit corelim;
|
||||
#endif
|
||||
|
||||
sbrk0 = (char *)sbrk((size_t)0);
|
||||
uid = getuid();
|
||||
euid = geteuid();
|
||||
now = time(NULL);
|
||||
#ifdef PROFIL
|
||||
(void)monstartup(0, etext);
|
||||
(void)moncontrol(1);
|
||||
(void)signal(SIGUSR1, s_monitor);
|
||||
#endif
|
||||
|
||||
#ifdef CHROOTDIR
|
||||
if (chdir(dpath))
|
||||
{
|
||||
perror("chdir");
|
||||
exit(-1);
|
||||
}
|
||||
res_init();
|
||||
if (chroot(DPATH))
|
||||
{
|
||||
(void)fprintf(stderr,"ERROR: Cannot chdir/chroot\n");
|
||||
exit(5);
|
||||
}
|
||||
#endif /*CHROOTDIR*/
|
||||
|
||||
myargv = argv;
|
||||
(void)umask(077); /* better safe than sorry --SRB */
|
||||
bzero((char *)&me, sizeof(me));
|
||||
|
||||
setup_signals();
|
||||
initload();
|
||||
|
||||
#ifdef FORCE_CORE
|
||||
corelim.rlim_cur = corelim.rlim_max = RLIM_INFINITY;
|
||||
if (setrlimit(RLIMIT_CORE, &corelim))
|
||||
printf("unlimit core size failed; errno = %d\n", errno);
|
||||
#endif
|
||||
|
||||
/*
|
||||
** All command line parameters have the syntax "-fstring"
|
||||
** or "-f string" (e.g. the space is optional). String may
|
||||
** be empty. Flag characters cannot be concatenated (like
|
||||
** "-fxyz"), it would conflict with the form "-fstring".
|
||||
*/
|
||||
while (--argc > 0 && (*++argv)[0] == '-')
|
||||
{
|
||||
char *p = argv[0]+1;
|
||||
int flag = *p++;
|
||||
|
||||
if (flag == '\0' || *p == '\0')
|
||||
if (argc > 1 && argv[1][0] != '-')
|
||||
{
|
||||
p = *++argv;
|
||||
argc -= 1;
|
||||
}
|
||||
else
|
||||
p = "";
|
||||
|
||||
switch (flag)
|
||||
{
|
||||
case 'a':
|
||||
bootopt |= BOOT_AUTODIE;
|
||||
break;
|
||||
case 'c':
|
||||
bootopt |= BOOT_CONSOLE;
|
||||
break;
|
||||
case 'q':
|
||||
bootopt |= BOOT_QUICK;
|
||||
break;
|
||||
case 'd' :
|
||||
(void)setuid((uid_t)uid);
|
||||
dpath = p;
|
||||
break;
|
||||
case 'o': /* Per user local daemon... */
|
||||
(void)setuid((uid_t)uid);
|
||||
bootopt |= BOOT_OPER;
|
||||
break;
|
||||
#ifdef CMDLINE_CONFIG
|
||||
case 'f':
|
||||
(void)setuid((uid_t)uid);
|
||||
configfile = p;
|
||||
break;
|
||||
#endif
|
||||
case 'h':
|
||||
strncpyzt(me.name, p, sizeof(me.name));
|
||||
break;
|
||||
case 'i':
|
||||
bootopt |= BOOT_INETD|BOOT_AUTODIE;
|
||||
break;
|
||||
case 'p':
|
||||
if ((portarg = atoi(p)) > 0 )
|
||||
portnum = portarg;
|
||||
break;
|
||||
case 't':
|
||||
(void)setuid((uid_t)uid);
|
||||
bootopt |= BOOT_TTY;
|
||||
break;
|
||||
case 'v':
|
||||
(void)printf("ircd %s\n", version);
|
||||
exit(0);
|
||||
case 'x':
|
||||
#ifdef DEBUGMODE
|
||||
(void)setuid((uid_t)uid);
|
||||
debuglevel = atoi(p);
|
||||
debugmode = *p ? p : "0";
|
||||
bootopt |= BOOT_DEBUG;
|
||||
break;
|
||||
#else
|
||||
(void)fprintf(stderr,
|
||||
"%s: DEBUGMODE must be defined for -x y\n",
|
||||
myargv[0]);
|
||||
exit(0);
|
||||
#endif
|
||||
default:
|
||||
bad_command();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CHROOT
|
||||
if (chdir(dpath))
|
||||
{
|
||||
perror("chdir");
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef IRC_UID
|
||||
if ((uid != euid) && !euid)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"ERROR: do not run ircd setuid root. Make it setuid a\
|
||||
normal user.\n");
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(CHROOTDIR) || (defined(IRC_UID) && defined(IRC_GID))
|
||||
# ifndef AIX
|
||||
(void)setuid((uid_t)uid);
|
||||
(void)setuid((uid_t)euid);
|
||||
# endif
|
||||
|
||||
if ((int)getuid() == 0)
|
||||
{
|
||||
# if defined(IRC_UID) && defined(IRC_GID)
|
||||
|
||||
/* run as a specified user */
|
||||
(void)fprintf(stderr,"WARNING: running ircd with uid = %d\n",
|
||||
IRC_UID);
|
||||
(void)fprintf(stderr," changing to gid %d.\n",IRC_GID);
|
||||
(void)setuid(IRC_UID);
|
||||
(void)setgid(IRC_GID);
|
||||
#else
|
||||
/* check for setuid root as usual */
|
||||
(void)fprintf(stderr,
|
||||
"ERROR: do not run ircd setuid root. Make it setuid a\
|
||||
normal user.\n");
|
||||
exit(-1);
|
||||
# endif
|
||||
}
|
||||
#endif /*CHROOTDIR/UID/GID*/
|
||||
|
||||
/* didn't set debuglevel */
|
||||
/* but asked for debugging output to tty */
|
||||
if ((debuglevel < 0) && (bootopt & BOOT_TTY))
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"you specified -t without -x. use -x <n>\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (argc > 0)
|
||||
return bad_command(); /* This should exit out */
|
||||
|
||||
clear_client_hash_table();
|
||||
clear_channel_hash_table();
|
||||
initlists();
|
||||
initclass();
|
||||
initwhowas();
|
||||
initstats();
|
||||
open_debugfile();
|
||||
if (portnum < 0)
|
||||
portnum = PORTNUM;
|
||||
me.port = portnum;
|
||||
(void)init_sys();
|
||||
me.flags = FLAGS_LISTEN;
|
||||
if (bootopt & BOOT_INETD)
|
||||
{
|
||||
me.fd = 0;
|
||||
local[0] = &me;
|
||||
me.flags = FLAGS_LISTEN;
|
||||
}
|
||||
else
|
||||
me.fd = -1;
|
||||
|
||||
#ifdef USE_SYSLOG
|
||||
openlog(myargv[0], LOG_PID|LOG_NDELAY, LOG_FACILITY);
|
||||
#endif
|
||||
if (initconf(bootopt) == -1)
|
||||
{
|
||||
Debug((DEBUG_FATAL, "Failed in reading configuration file %s",
|
||||
configfile));
|
||||
(void)printf("Couldn't open configuration file %s\n",
|
||||
configfile);
|
||||
exit(-1);
|
||||
}
|
||||
if (!(bootopt & BOOT_INETD))
|
||||
{
|
||||
static char star[] = "*";
|
||||
aConfItem *aconf;
|
||||
|
||||
if ((aconf = find_me()) && portarg <= 0 && aconf->port > 0)
|
||||
portnum = aconf->port;
|
||||
Debug((DEBUG_ERROR, "Port = %d", portnum));
|
||||
if (inetport(&me, star, portnum))
|
||||
exit(1);
|
||||
}
|
||||
else if (inetport(&me, "*", 0))
|
||||
exit(1);
|
||||
|
||||
(void)setup_ping();
|
||||
(void)get_my_name(&me, me.sockhost, sizeof(me.sockhost)-1);
|
||||
if (me.name[0] == '\0')
|
||||
strncpyzt(me.name, "undernet.org", sizeof(me.name));
|
||||
now = time(NULL);
|
||||
me.hopcount = 0;
|
||||
me.authfd = -1;
|
||||
me.confs = NULL;
|
||||
me.next = NULL;
|
||||
me.user = NULL;
|
||||
me.from = &me;
|
||||
SetMe(&me);
|
||||
make_server(&me);
|
||||
/* Abuse own link timestamp as start timestamp: */
|
||||
me.serv->timestamp = TStime();
|
||||
me.serv->prot = atoi(MAJOR_PROTOCOL);
|
||||
me.serv->up = &me;
|
||||
me.serv->down = NULL;
|
||||
me.serv->client = NULL;
|
||||
|
||||
me.lasttime = me.since = me.firsttime = now;
|
||||
(void)add_to_client_hash_table(me.name, &me);
|
||||
|
||||
check_class();
|
||||
if (bootopt & BOOT_OPER)
|
||||
{
|
||||
aClient *tmp = add_connection(&me, 0);
|
||||
|
||||
if (!tmp)
|
||||
exit(1);
|
||||
SetMaster(tmp);
|
||||
}
|
||||
else
|
||||
write_pidfile();
|
||||
|
||||
Debug((DEBUG_NOTICE,"Server ready..."));
|
||||
#ifdef USE_SYSLOG
|
||||
syslog(LOG_NOTICE, "Server Ready");
|
||||
#endif
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/*
|
||||
** We only want to connect if a connection is due,
|
||||
** not every time through. Note, if there are no
|
||||
** active C lines, this call to Tryconnections is
|
||||
** made once only; it will return 0. - avalon
|
||||
*/
|
||||
if (nextconnect && now >= nextconnect)
|
||||
nextconnect = try_connections();
|
||||
/*
|
||||
** DNS checks. One to timeout queries, one for cache expiries.
|
||||
*/
|
||||
if (now >= nextdnscheck)
|
||||
nextdnscheck = timeout_query_list();
|
||||
if (now >= nextexpire)
|
||||
nextexpire = expire_cache();
|
||||
/*
|
||||
** take the smaller of the two 'timed' event times as
|
||||
** the time of next event (stops us being late :) - avalon
|
||||
** WARNING - nextconnect can return 0!
|
||||
*/
|
||||
if (nextconnect)
|
||||
delay = MIN(nextping, nextconnect);
|
||||
else
|
||||
delay = nextping;
|
||||
delay = MIN(nextdnscheck, delay);
|
||||
delay = MIN(nextexpire, delay);
|
||||
delay -= now;
|
||||
/*
|
||||
** Adjust delay to something reasonable [ad hoc values]
|
||||
** (one might think something more clever here... --msa)
|
||||
** We don't really need to check that often and as long
|
||||
** as we don't delay too long, everything should be ok.
|
||||
** waiting too long can cause things to timeout...
|
||||
** i.e. PINGS -> a disconnection :(
|
||||
** - avalon
|
||||
*/
|
||||
if (delay < 1)
|
||||
delay = 1;
|
||||
else
|
||||
delay = MIN(delay, TIMESEC);
|
||||
(void)read_message(delay);
|
||||
|
||||
Debug((DEBUG_DEBUG ,"Got message(s)"));
|
||||
|
||||
/*
|
||||
** ...perhaps should not do these loops every time,
|
||||
** but only if there is some chance of something
|
||||
** happening (but, note that conf->hold times may
|
||||
** be changed elsewhere--so precomputed next event
|
||||
** time might be too far away... (similarly with
|
||||
** ping times) --msa
|
||||
*/
|
||||
if (now >= nextping)
|
||||
nextping = check_pings();
|
||||
|
||||
if (dorehash)
|
||||
{
|
||||
(void)rehash(&me, &me, 1);
|
||||
dorehash = 0;
|
||||
}
|
||||
/*
|
||||
** Flush output buffers on all connections now if they
|
||||
** have data in them (or at least try to flush)
|
||||
** -avalon
|
||||
*/
|
||||
/* What is this doing here ??? Pure cpu waste...
|
||||
flush_connections(me.fd);
|
||||
writes are already done in read_message(), which
|
||||
uses select(). flush_connections doesn't even !!!
|
||||
--Run
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* open_debugfile
|
||||
*
|
||||
* If the -t option is not given on the command line when the server is
|
||||
* started, all debugging output is sent to the file set by LPATH in config.h
|
||||
* Here we just open that file and make sure it is opened to fd 2 so that
|
||||
* any fprintf's to stderr also goto the logfile. If the debuglevel is not
|
||||
* set from the command line by -x, use /dev/null as the dummy logfile as long
|
||||
* as DEBUGMODE has been defined, else dont waste the fd.
|
||||
*/
|
||||
static void open_debugfile()
|
||||
{
|
||||
#ifdef DEBUGMODE
|
||||
int fd;
|
||||
aClient *cptr;
|
||||
|
||||
if (debuglevel >= 0)
|
||||
{
|
||||
cptr = make_client(NULL);
|
||||
cptr->fd = 2;
|
||||
SetLog(cptr);
|
||||
cptr->port = debuglevel;
|
||||
cptr->flags = 0;
|
||||
cptr->acpt = cptr;
|
||||
local[2] = cptr;
|
||||
(void)strcpy(cptr->sockhost, me.sockhost);
|
||||
|
||||
(void)printf("isatty = %d ttyname = %#x\n",
|
||||
isatty(2), (u_int)ttyname(2));
|
||||
if (!(bootopt & BOOT_TTY)) /* leave debugging output on fd 2 */
|
||||
{
|
||||
(void)truncate(LOGFILE, 0);
|
||||
if ((fd = open(LOGFILE, O_WRONLY | O_CREAT, 0600)) < 0)
|
||||
if ((fd = open("/dev/null", O_WRONLY)) < 0)
|
||||
exit(-1);
|
||||
if (fd != 2)
|
||||
{
|
||||
(void)dup2(fd, 2);
|
||||
(void)close(fd);
|
||||
}
|
||||
strncpyzt(cptr->name, LOGFILE, sizeof(cptr->name));
|
||||
}
|
||||
else if (isatty(2) && ttyname(2))
|
||||
strncpyzt(cptr->name, ttyname(2), sizeof(cptr->name));
|
||||
else
|
||||
(void)strcpy(cptr->name, "FD2-Pipe");
|
||||
Debug((DEBUG_FATAL, "Debug: File <%s> Level: %d at %s",
|
||||
cptr->name, cptr->port, myctime(now)));
|
||||
}
|
||||
else
|
||||
local[2] = NULL;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
static void setup_signals()
|
||||
{
|
||||
#ifdef POSIX_SIGNALS
|
||||
struct sigaction act;
|
||||
|
||||
act.sa_handler = SIG_IGN;
|
||||
act.sa_flags = 0;
|
||||
(void)sigemptyset(&act.sa_mask);
|
||||
(void)sigaddset(&act.sa_mask, SIGPIPE);
|
||||
(void)sigaddset(&act.sa_mask, SIGALRM);
|
||||
# ifdef SIGWINCH
|
||||
(void)sigaddset(&act.sa_mask, SIGWINCH);
|
||||
(void)sigaction(SIGWINCH, &act, NULL);
|
||||
# endif
|
||||
(void)sigaction(SIGPIPE, &act, NULL);
|
||||
act.sa_handler = dummy;
|
||||
(void)sigaction(SIGALRM, &act, NULL);
|
||||
act.sa_handler = s_rehash;
|
||||
(void)sigemptyset(&act.sa_mask);
|
||||
(void)sigaddset(&act.sa_mask, SIGHUP);
|
||||
(void)sigaction(SIGHUP, &act, NULL);
|
||||
act.sa_handler = s_restart;
|
||||
(void)sigaddset(&act.sa_mask, SIGINT);
|
||||
(void)sigaction(SIGINT, &act, NULL);
|
||||
act.sa_handler = s_die;
|
||||
(void)sigaddset(&act.sa_mask, SIGTERM);
|
||||
(void)sigaction(SIGTERM, &act, NULL);
|
||||
|
||||
#else
|
||||
# ifndef HAVE_RELIABLE_SIGNALS
|
||||
(void)signal(SIGPIPE, dummy);
|
||||
# ifdef SIGWINCH
|
||||
(void)signal(SIGWINCH, dummy);
|
||||
# endif
|
||||
# else
|
||||
# ifdef SIGWINCH
|
||||
(void)signal(SIGWINCH, SIG_IGN);
|
||||
# endif
|
||||
(void)signal(SIGPIPE, SIG_IGN);
|
||||
# endif
|
||||
(void)signal(SIGALRM, dummy);
|
||||
(void)signal(SIGHUP, s_rehash);
|
||||
(void)signal(SIGTERM, s_die);
|
||||
(void)signal(SIGINT, s_restart);
|
||||
#endif
|
||||
|
||||
#ifdef RESTARTING_SYSTEMCALLS
|
||||
/*
|
||||
** At least on Apollo sr10.1 it seems continuing system calls
|
||||
** after signal is the default. The following 'siginterrupt'
|
||||
** should change that default to interrupting calls.
|
||||
*/
|
||||
(void)siginterrupt(SIGALRM, 1);
|
||||
#endif
|
||||
}
|
||||
543
ircd/list.c
Normal file
543
ircd/list.c
Normal file
@@ -0,0 +1,543 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, ircd/list.c
|
||||
* Copyright (C) 1990 Jarkko Oikarinen and
|
||||
* University of Oulu, Finland
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/* -- Jto -- 20 Jun 1990
|
||||
* extern void free() fixed as suggested by
|
||||
* gruner@informatik.tu-muenchen.de
|
||||
*/
|
||||
|
||||
/* -- Jto -- 03 Jun 1990
|
||||
* Added chname initialization...
|
||||
*/
|
||||
|
||||
/* -- Jto -- 24 May 1990
|
||||
* Moved is_full() to channel.c
|
||||
*/
|
||||
|
||||
/* -- Jto -- 10 May 1990
|
||||
* Added #include <sys.h>
|
||||
* Changed memset(xx,0,yy) into bzero(xx,yy)
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)list.c 2.24 4/20/94 (C) 1988 University of Oulu, \
|
||||
Computing Center and Jarkko Oikarinen";
|
||||
#endif
|
||||
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "h.h"
|
||||
#include "numeric.h"
|
||||
#ifdef DBMALLOC
|
||||
#include "malloc.h"
|
||||
#endif
|
||||
void free_link PROTO((Link *));
|
||||
Link *make_link PROTO(());
|
||||
|
||||
#ifdef DEBUGMODE
|
||||
static struct liststats {
|
||||
int inuse;
|
||||
} cloc, crem, users, servs, links, classs, aconfs;
|
||||
|
||||
#endif
|
||||
|
||||
void outofmemory();
|
||||
|
||||
int numclients = 0;
|
||||
|
||||
void initlists()
|
||||
{
|
||||
#ifdef DEBUGMODE
|
||||
bzero((char *)&cloc, sizeof(cloc));
|
||||
bzero((char *)&crem, sizeof(crem));
|
||||
bzero((char *)&users, sizeof(users));
|
||||
bzero((char *)&servs, sizeof(servs));
|
||||
bzero((char *)&links, sizeof(links));
|
||||
bzero((char *)&classs, sizeof(classs));
|
||||
bzero((char *)&aconfs, sizeof(aconfs));
|
||||
#endif
|
||||
}
|
||||
|
||||
void outofmemory()
|
||||
{
|
||||
Debug((DEBUG_FATAL, "Out of memory: restarting server..."));
|
||||
restart("Out of Memory");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Create a new aClient structure and set it to initial state.
|
||||
**
|
||||
** from == NULL, create local client (a client connected
|
||||
** to a socket).
|
||||
**
|
||||
** from, create remote client (behind a socket
|
||||
** associated with the client defined by
|
||||
** 'from'). ('from' is a local client!!).
|
||||
*/
|
||||
aClient *make_client(from)
|
||||
aClient *from;
|
||||
{
|
||||
Reg1 aClient *cptr = NULL;
|
||||
Reg2 unsigned size = CLIENT_REMOTE_SIZE;
|
||||
|
||||
/*
|
||||
* Check freelists first to see if we can grab a client without
|
||||
* having to call malloc.
|
||||
*/
|
||||
if (!from)
|
||||
size = CLIENT_LOCAL_SIZE;
|
||||
|
||||
if (!(cptr = (aClient *)MyMalloc(size)))
|
||||
outofmemory();
|
||||
bzero((char *)cptr, (int)size);
|
||||
|
||||
#ifdef DEBUGMODE
|
||||
if (size == CLIENT_LOCAL_SIZE)
|
||||
cloc.inuse++;
|
||||
else
|
||||
crem.inuse++;
|
||||
#endif
|
||||
|
||||
/* Note: structure is zero (calloc) */
|
||||
cptr->from = from ? from : cptr; /* 'from' of local client is self! */
|
||||
cptr->next = NULL; /* For machines with NON-ZERO NULL pointers >;) */
|
||||
cptr->prev = NULL;
|
||||
cptr->hnext = NULL;
|
||||
cptr->user = NULL;
|
||||
cptr->serv = NULL;
|
||||
cptr->status = STAT_UNKNOWN;
|
||||
cptr->fd = -1;
|
||||
(void)strcpy(cptr->username, "unknown");
|
||||
if (size == CLIENT_LOCAL_SIZE)
|
||||
{
|
||||
cptr->since = cptr->lasttime = cptr->firsttime = now;
|
||||
cptr->lastnick = TStime();
|
||||
#ifdef NICK_DELAY
|
||||
cptr->nextnick = now - NICK_DELAY;
|
||||
#endif /* NICK_DELAY */
|
||||
cptr->cookie = 0;
|
||||
cptr->confs = NULL;
|
||||
cptr->sockhost[0] = '\0';
|
||||
cptr->buffer[0] = '\0';
|
||||
cptr->authfd = -1;
|
||||
cptr->listing = NULL;
|
||||
}
|
||||
return (cptr);
|
||||
}
|
||||
|
||||
void free_client(cptr)
|
||||
aClient *cptr;
|
||||
{
|
||||
MyFree((char *)cptr);
|
||||
}
|
||||
|
||||
/*
|
||||
** 'make_user' add's an User information block to a client
|
||||
** if it was not previously allocated.
|
||||
*/
|
||||
anUser *make_user(cptr)
|
||||
aClient *cptr;
|
||||
{
|
||||
Reg1 anUser *user;
|
||||
|
||||
user = cptr->user;
|
||||
if (!user)
|
||||
{
|
||||
user = (anUser *)MyMalloc(sizeof(anUser));
|
||||
#ifdef DEBUGMODE
|
||||
users.inuse++;
|
||||
#endif
|
||||
user->away = NULL;
|
||||
user->refcnt = 1;
|
||||
user->joined = 0;
|
||||
user->channel = NULL;
|
||||
user->invited = NULL;
|
||||
user->silence = NULL;
|
||||
cptr->user = user;
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
aServer *make_server(cptr)
|
||||
aClient *cptr;
|
||||
{
|
||||
Reg1 aServer *serv = cptr->serv;
|
||||
|
||||
if (!serv)
|
||||
{
|
||||
serv = (aServer *)MyMalloc(sizeof(aServer));
|
||||
#ifdef DEBUGMODE
|
||||
servs.inuse++;
|
||||
#endif
|
||||
serv->ghost = 0;
|
||||
cptr->serv = serv;
|
||||
serv->user = NULL;
|
||||
serv->nexts = NULL;
|
||||
*serv->by = '\0';
|
||||
serv->up = NULL;
|
||||
serv->down = NULL;
|
||||
serv->client = NULL;
|
||||
}
|
||||
return cptr->serv;
|
||||
}
|
||||
|
||||
/*
|
||||
** free_user
|
||||
** Decrease user reference count by one and realease block,
|
||||
** if count reaches 0
|
||||
*/
|
||||
void free_user(user, cptr)
|
||||
Reg1 anUser *user;
|
||||
aClient *cptr;
|
||||
{
|
||||
if (--user->refcnt <= 0)
|
||||
{
|
||||
if (user->away)
|
||||
MyFree((char *)user->away);
|
||||
/*
|
||||
* sanity check
|
||||
*/
|
||||
if (user->joined || user->refcnt < 0 ||
|
||||
user->invited || user->channel)
|
||||
#ifdef DEBUGMODE
|
||||
dumpcore("%#x user (%s!%s@%s) %#x %#x %#x %d %d",
|
||||
cptr, cptr ? cptr->name : "<noname>",
|
||||
user->username, user->host, user,
|
||||
user->invited, user->channel, user->joined,
|
||||
user->refcnt);
|
||||
#else
|
||||
sendto_ops("* %#x user (%s!%s@%s) %#x %#x %#x %d %d *",
|
||||
cptr, cptr ? cptr->name : "<noname>",
|
||||
user->username, user->host, user,
|
||||
user->invited, user->channel, user->joined,
|
||||
user->refcnt);
|
||||
#endif
|
||||
MyFree((char *)user);
|
||||
#ifdef DEBUGMODE
|
||||
users.inuse--;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* taken the code from ExitOneClient() for this and placed it here.
|
||||
* - avalon
|
||||
*/
|
||||
void remove_client_from_list(cptr)
|
||||
Reg1 aClient *cptr;
|
||||
{
|
||||
checklist();
|
||||
if (cptr->prev)
|
||||
cptr->prev->next = cptr->next;
|
||||
else
|
||||
{
|
||||
client = cptr->next;
|
||||
client->prev = NULL;
|
||||
}
|
||||
if (cptr->next)
|
||||
cptr->next->prev = cptr->prev;
|
||||
if (IsPerson(cptr) && cptr->user)
|
||||
{
|
||||
add_history(cptr);
|
||||
off_history(cptr);
|
||||
}
|
||||
if (cptr->user)
|
||||
{
|
||||
cptr->user->clink = NULL;
|
||||
(void)free_user(cptr->user, cptr);
|
||||
}
|
||||
if (cptr->serv)
|
||||
{
|
||||
if (cptr->serv->user)
|
||||
free_user(cptr->serv->user, cptr);
|
||||
MyFree((char *)cptr->serv);
|
||||
#ifdef DEBUGMODE
|
||||
servs.inuse--;
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUGMODE
|
||||
if (cptr->fd == -2)
|
||||
cloc.inuse--;
|
||||
else
|
||||
crem.inuse--;
|
||||
#endif
|
||||
(void)free_client(cptr);
|
||||
numclients--;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* although only a small routine, it appears in a number of places
|
||||
* as a collection of a few lines...functions like this *should* be
|
||||
* in this file, shouldnt they ? after all, this is list.c, isnt it ?
|
||||
* -avalon
|
||||
*/
|
||||
void add_client_to_list(cptr)
|
||||
aClient *cptr;
|
||||
{
|
||||
/*
|
||||
* since we always insert new clients to the top of the list,
|
||||
* this should mean the "me" is the bottom most item in the list.
|
||||
*/
|
||||
cptr->next = client;
|
||||
client = cptr;
|
||||
if (cptr->next)
|
||||
cptr->next->prev = cptr;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for ptr in the linked listed pointed to by link.
|
||||
*/
|
||||
Link *find_user_link(lp, ptr)
|
||||
Reg1 Link *lp;
|
||||
Reg2 aClient *ptr;
|
||||
{
|
||||
if (ptr)
|
||||
while (lp)
|
||||
{
|
||||
if (lp->value.cptr == ptr)
|
||||
return (lp);
|
||||
lp = lp->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Link *make_link()
|
||||
{
|
||||
Reg1 Link *lp;
|
||||
|
||||
lp = (Link *)MyMalloc(sizeof(Link));
|
||||
#ifdef DEBUGMODE
|
||||
links.inuse++;
|
||||
#endif
|
||||
return lp;
|
||||
}
|
||||
|
||||
void free_link(lp)
|
||||
Reg1 Link *lp;
|
||||
{
|
||||
MyFree((char *)lp);
|
||||
#ifdef DEBUGMODE
|
||||
links.inuse--;
|
||||
#endif
|
||||
}
|
||||
|
||||
Dlink *add_dlink(lpp, cp)
|
||||
Dlink **lpp;
|
||||
aClient *cp;
|
||||
{ register Dlink *lp;
|
||||
lp = (Dlink *)MyMalloc(sizeof(Dlink));
|
||||
lp->value.cptr = cp;
|
||||
lp->prev = NULL;
|
||||
if ((lp->next = *lpp))
|
||||
lp->next->prev = lp;
|
||||
*lpp = lp;
|
||||
return lp;
|
||||
}
|
||||
|
||||
void remove_dlink(lpp, lp)
|
||||
Dlink **lpp, *lp;
|
||||
{
|
||||
if (lp->prev)
|
||||
{ if ((lp->prev->next = lp->next))
|
||||
lp->next->prev = lp->prev; }
|
||||
else if ((*lpp = lp->next))
|
||||
lp->next->prev = NULL;
|
||||
MyFree(lp);
|
||||
}
|
||||
|
||||
aClass *make_class()
|
||||
{
|
||||
Reg1 aClass *tmp;
|
||||
|
||||
tmp = (aClass *)MyMalloc(sizeof(aClass));
|
||||
#ifdef DEBUGMODE
|
||||
classs.inuse++;
|
||||
#endif
|
||||
return tmp;
|
||||
}
|
||||
|
||||
void free_class(tmp)
|
||||
Reg1 aClass *tmp;
|
||||
{
|
||||
MyFree((char *)tmp);
|
||||
#ifdef DEBUGMODE
|
||||
classs.inuse--;
|
||||
#endif
|
||||
}
|
||||
|
||||
aConfItem *make_conf()
|
||||
{
|
||||
Reg1 aConfItem *aconf;
|
||||
|
||||
aconf = (struct ConfItem *)MyMalloc(sizeof(aConfItem));
|
||||
#ifdef DEBUGMODE
|
||||
aconfs.inuse++;
|
||||
#endif
|
||||
bzero((char *)&aconf->ipnum, sizeof(struct in_addr));
|
||||
aconf->next = NULL;
|
||||
aconf->host = aconf->passwd = aconf->name = NULL;
|
||||
aconf->status = CONF_ILLEGAL;
|
||||
aconf->clients = 0;
|
||||
aconf->port = 0;
|
||||
aconf->hold = 0;
|
||||
Class(aconf) = 0;
|
||||
return (aconf);
|
||||
}
|
||||
|
||||
void delist_conf(aconf)
|
||||
aConfItem *aconf;
|
||||
{
|
||||
if (aconf == conf)
|
||||
conf = conf->next;
|
||||
else
|
||||
{
|
||||
aConfItem *bconf;
|
||||
|
||||
for (bconf = conf; aconf != bconf->next; bconf = bconf->next)
|
||||
;
|
||||
bconf->next = aconf->next;
|
||||
}
|
||||
aconf->next = NULL;
|
||||
}
|
||||
|
||||
void free_conf(aconf)
|
||||
aConfItem *aconf;
|
||||
{
|
||||
aClient *cptr = &me;
|
||||
del_queries((char *)aconf);
|
||||
MyFree(aconf->host);
|
||||
if (aconf->passwd)
|
||||
bzero(aconf->passwd, strlen(aconf->passwd));
|
||||
MyFree(aconf->passwd);
|
||||
MyFree(aconf->name);
|
||||
MyFree((char *)aconf);
|
||||
#ifdef DEBUGMODE
|
||||
aconfs.inuse--;
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
aGline *make_gline(host, reason, name, expire)
|
||||
char *host, *reason, *name;
|
||||
time_t expire;
|
||||
{
|
||||
Reg4 aGline *agline;
|
||||
|
||||
agline = (struct Gline *)MyMalloc(sizeof(aGline)); /* alloc memory */
|
||||
DupString(agline->host, host); /* copy vital information */
|
||||
DupString(agline->reason, reason);
|
||||
DupString(agline->name, name);
|
||||
agline->expire = expire;
|
||||
agline->active = GLINE_ACTIVE; /* gline is active */
|
||||
agline->next = gline; /* link it into the list */
|
||||
return (gline = agline);
|
||||
}
|
||||
|
||||
aGline *find_gline(host, name, pgline)
|
||||
Reg1 char *host, *name;
|
||||
aGline **pgline;
|
||||
{
|
||||
Reg3 aGline *agline = gline, *a2gline = NULL;
|
||||
|
||||
while (agline) { /* look through all glines */
|
||||
|
||||
if (agline->expire <= TStime()) { /* handle expired glines */
|
||||
free_gline(agline, a2gline);
|
||||
agline = a2gline ? a2gline->next : gline;
|
||||
if (!agline) break; /* agline == NULL means gline == NULL */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* does gline match? */
|
||||
if (match(agline->host, host) == 0 && match(agline->name, name) == 0) {
|
||||
if (pgline) *pgline = a2gline; /* if they need it, give them the
|
||||
previous gline entry (probably
|
||||
for free_gline, below) */
|
||||
return agline;
|
||||
}
|
||||
|
||||
a2gline = agline;
|
||||
agline = agline->next;
|
||||
}
|
||||
|
||||
return NULL; /* found no glines */
|
||||
}
|
||||
|
||||
void free_gline(agline, pgline)
|
||||
aGline *agline, *pgline;
|
||||
{
|
||||
if (pgline) pgline->next = agline->next; /* squeeze agline out */
|
||||
else gline = agline->next;
|
||||
|
||||
MyFree(agline->host); /* and free up the memory */
|
||||
MyFree(agline->reason);
|
||||
MyFree(agline->name);
|
||||
MyFree((char *)agline);
|
||||
}
|
||||
|
||||
#ifdef DEBUGMODE
|
||||
void send_listinfo(cptr, name)
|
||||
aClient *cptr;
|
||||
char *name;
|
||||
{
|
||||
int inuse = 0, mem = 0, tmp = 0;
|
||||
|
||||
sendto_one(cptr, ":%s %d %s :Local: inuse: %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, name, inuse += cloc.inuse,
|
||||
tmp = cloc.inuse * CLIENT_LOCAL_SIZE);
|
||||
mem += tmp;
|
||||
sendto_one(cptr, ":%s %d %s :Remote: inuse: %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, name,
|
||||
crem.inuse, tmp = crem.inuse * CLIENT_REMOTE_SIZE);
|
||||
mem += tmp;
|
||||
inuse += crem.inuse;
|
||||
sendto_one(cptr, ":%s %d %s :Users: inuse: %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, name, users.inuse,
|
||||
tmp = users.inuse * sizeof(anUser));
|
||||
mem += tmp;
|
||||
inuse += users.inuse,
|
||||
sendto_one(cptr, ":%s %d %s :Servs: inuse: %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, name, servs.inuse,
|
||||
tmp = servs.inuse * sizeof(aServer));
|
||||
mem += tmp;
|
||||
inuse += servs.inuse,
|
||||
sendto_one(cptr, ":%s %d %s :Links: inuse: %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, name, links.inuse,
|
||||
tmp = links.inuse * sizeof(Link));
|
||||
mem += tmp;
|
||||
inuse += links.inuse,
|
||||
sendto_one(cptr, ":%s %d %s :Classes: inuse: %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, name, classs.inuse,
|
||||
tmp = classs.inuse * sizeof(aClass));
|
||||
mem += tmp;
|
||||
inuse += classs.inuse,
|
||||
sendto_one(cptr, ":%s %d %s :Confs: inuse: %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, name, aconfs.inuse,
|
||||
tmp = aconfs.inuse * sizeof(aConfItem));
|
||||
mem += tmp;
|
||||
inuse += aconfs.inuse,
|
||||
sendto_one(cptr, ":%s %d %s :Totals: inuse %d %d",
|
||||
me.name, RPL_STATSDEBUG, name, inuse, mem);
|
||||
}
|
||||
#endif
|
||||
97
ircd/map.c
Normal file
97
ircd/map.c
Normal file
@@ -0,0 +1,97 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, ircd/s_ping.c
|
||||
* Copyright (C) 1994 Carlo K ( Run @ undernet.org )
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)s_ping.c 1.0 9/30/94 (C) 1994 Carlo Kid";
|
||||
#endif
|
||||
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "h.h"
|
||||
#include "numeric.h"
|
||||
|
||||
void dump_map(cptr, server, mask, prompt_length)
|
||||
aClient *cptr, *server;
|
||||
char *mask;
|
||||
register int prompt_length;
|
||||
{
|
||||
static char prompt[64];
|
||||
register Dlink *lp;
|
||||
register char *p = &prompt[prompt_length];
|
||||
register int cnt = 0;
|
||||
|
||||
*p='\0';
|
||||
if (prompt_length > 60)
|
||||
sendto_one(cptr, rpl_str(RPL_MAPMORE), me.name, cptr->name,
|
||||
prompt, server->name);
|
||||
else
|
||||
sendto_one(cptr, rpl_str(RPL_MAP), me.name, cptr->name,
|
||||
prompt, server->name);
|
||||
if (prompt_length > 0)
|
||||
{
|
||||
p[-1] = ' ';
|
||||
if (p[-2] == '`')
|
||||
p[-2] = ' ';
|
||||
}
|
||||
if (prompt_length > 60)
|
||||
return;
|
||||
strcpy(p, "|-");
|
||||
for (lp=server->serv->down; lp; lp=lp->next)
|
||||
if (matches(mask, lp->value.cptr->name))
|
||||
lp->value.cptr->flags &= ~FLAGS_MAP;
|
||||
else
|
||||
{
|
||||
lp->value.cptr->flags |= FLAGS_MAP;
|
||||
cnt++;
|
||||
}
|
||||
for (lp=server->serv->down; lp; lp=lp->next)
|
||||
{
|
||||
if ((lp->value.cptr->flags & FLAGS_MAP) == 0)
|
||||
continue;
|
||||
if (--cnt == 0)
|
||||
*p = '`';
|
||||
dump_map(cptr, lp->value.cptr, mask, prompt_length+2);
|
||||
}
|
||||
if (prompt_length > 0)
|
||||
p[-1] = '-';
|
||||
}
|
||||
|
||||
/*
|
||||
** m_map -- by Run
|
||||
**
|
||||
** parv[0] = sender prefix
|
||||
** parv[1] = server mask
|
||||
**/
|
||||
int m_map(cptr, sptr, parc, parv)
|
||||
aClient *cptr, *sptr;
|
||||
int parc;
|
||||
char *parv[];
|
||||
{
|
||||
if (check_registered_user(sptr))
|
||||
return 0;
|
||||
|
||||
if (parc < 2)
|
||||
parv[1]="*";
|
||||
|
||||
dump_map(sptr, &me, parv[1], 0);
|
||||
sendto_one(sptr, rpl_str(RPL_MAPEND), me.name, parv[0]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
3563
ircd/note.c
Normal file
3563
ircd/note.c
Normal file
File diff suppressed because it is too large
Load Diff
158
ircd/random.c
Normal file
158
ircd/random.c
Normal file
@@ -0,0 +1,158 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, ircd/random.c
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include "config.h"
|
||||
|
||||
char localkey[8] = RANDOM_SEED;
|
||||
|
||||
/*
|
||||
* MD5 transform algorithm, taken from code written by Colin Plumb,
|
||||
* and put into the public domain
|
||||
*
|
||||
* Kev: Taken from Ted T'so's /dev/random random.c code and modified to
|
||||
* be slightly simpler. That code is released under a BSD-style copyright
|
||||
* OR under the terms of the GNU Public License, which should be included
|
||||
* at the top of this source file.
|
||||
*
|
||||
* record: Cleaned up to work with ircd. RANDOM_TOKEN is defined in
|
||||
* setup.h by the make script; if people start to "guess" your cookies,
|
||||
* consider recompiling your server with a different random token.
|
||||
*/
|
||||
|
||||
/* The four core functions - F1 is optimized somewhat */
|
||||
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
/* This is the central step in the MD5 algorithm. */
|
||||
#define MD5STEP(f, w, x, y, z, data, s) \
|
||||
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*
|
||||
* original comment left in; this used to be called MD5Transform and took
|
||||
* two arguments; I've internalized those arguments, creating the character
|
||||
* array "localkey," which should contain 8 bytes of data. The function also
|
||||
* originally returned nothing; now it returns an unsigned long that is the
|
||||
* random number. It appears to be reallyrandom, so... -Kev
|
||||
*
|
||||
* I don't really know what this does. I tried to figure it out and got
|
||||
* a headache. If you know what's good for you, you'll leave this stuff
|
||||
* for the smart people and do something else. -record
|
||||
*/
|
||||
unsigned long ircrandom(void)
|
||||
{
|
||||
unsigned long a, b, c, d;
|
||||
unsigned char in[16];
|
||||
struct timeval tv;
|
||||
|
||||
(void)gettimeofday(&tv, NULL);
|
||||
|
||||
(void)memcpy((void *)in, (void *)localkey, 8);
|
||||
(void)memcpy((void *)(in+8), (void *)&tv.tv_sec, 4);
|
||||
(void)memcpy((void *)(in+12), (void *)&tv.tv_usec, 4);
|
||||
|
||||
a = 0x67452301;
|
||||
b = 0xefcdab89;
|
||||
c = 0x98badcfe;
|
||||
d = 0x10325476;
|
||||
|
||||
MD5STEP(F1, a, b, c, d, (long)in[ 0]+0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, (long)in[ 1]+0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, (long)in[ 2]+0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, (long)in[ 3]+0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, (long)in[ 4]+0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, (long)in[ 5]+0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, (long)in[ 6]+0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, (long)in[ 7]+0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, (long)in[ 8]+0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, (long)in[ 9]+0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, (long)in[10]+0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, (long)in[11]+0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, (long)in[12]+0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, (long)in[13]+0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, (long)in[14]+0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, (long)in[15]+0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, (long)in[ 1]+0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, (long)in[ 6]+0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, (long)in[11]+0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, (long)in[ 0]+0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, (long)in[ 5]+0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, (long)in[10]+0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, (long)in[15]+0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, (long)in[ 4]+0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, (long)in[ 9]+0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, (long)in[14]+0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, (long)in[ 3]+0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, (long)in[ 8]+0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, (long)in[13]+0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, (long)in[ 2]+0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, (long)in[ 7]+0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, (long)in[12]+0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, (long)in[ 5]+0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, (long)in[ 8]+0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, (long)in[11]+0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, (long)in[14]+0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, (long)in[ 1]+0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, (long)in[ 4]+0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, (long)in[ 7]+0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, (long)in[10]+0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, (long)in[13]+0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, (long)in[ 0]+0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, (long)in[ 3]+0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, (long)in[ 6]+0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, (long)in[ 9]+0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, (long)in[12]+0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, (long)in[15]+0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, (long)in[ 2]+0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, (long)in[ 0]+0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, (long)in[ 7]+0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, (long)in[14]+0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, (long)in[ 5]+0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, (long)in[12]+0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, (long)in[ 3]+0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, (long)in[10]+0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, (long)in[ 1]+0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, (long)in[ 8]+0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, (long)in[15]+0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, (long)in[ 6]+0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, (long)in[13]+0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, (long)in[ 4]+0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, (long)in[11]+0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, (long)in[ 2]+0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, (long)in[ 9]+0xeb86d391, 21);
|
||||
|
||||
/*
|
||||
* we have 4 unsigned longs generated by the above sequence; this scrambles
|
||||
* them together so that if there is any pattern, it will be obscured.
|
||||
*/
|
||||
return (a ^ b ^ c ^ d);
|
||||
}
|
||||
|
||||
1417
ircd/res.c
Normal file
1417
ircd/res.c
Normal file
File diff suppressed because it is too large
Load Diff
329
ircd/res_comp.c
Normal file
329
ircd/res_comp.c
Normal file
@@ -0,0 +1,329 @@
|
||||
/*
|
||||
* Copyright (c) 1985 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted provided
|
||||
* that: (1) source distributions retain this entire copyright notice and
|
||||
* comment, and (2) distributions including binaries display the following
|
||||
* acknowledgement: ``This product includes software developed by the
|
||||
* University of California, Berkeley and its contributors'' in the
|
||||
* documentation or other materials provided with the distribution and in
|
||||
* all advertising materials mentioning features or use of this software.
|
||||
* Neither the name of the University nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)res_comp.c 6.18 (Berkeley) 6/27/90";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include "nameser.h"
|
||||
|
||||
static dn_find();
|
||||
|
||||
/*
|
||||
* Expand compressed domain name 'comp_dn' to full domain name.
|
||||
* 'msg' is a pointer to the begining of the message,
|
||||
* 'eomorig' points to the first location after the message,
|
||||
* 'exp_dn' is a pointer to a buffer of size 'length' for the result.
|
||||
* Return size of compressed name or -1 if there was an error.
|
||||
*/
|
||||
dn_expand(msg, eomorig, comp_dn, exp_dn, length)
|
||||
u_char *msg, *eomorig, *comp_dn, *exp_dn;
|
||||
int length;
|
||||
{
|
||||
register u_char *cp, *dn;
|
||||
register int n, c;
|
||||
u_char *eom;
|
||||
int len = -1, checked = 0;
|
||||
|
||||
dn = exp_dn;
|
||||
cp = comp_dn;
|
||||
eom = exp_dn + length;
|
||||
/*
|
||||
* fetch next label in domain name
|
||||
*/
|
||||
while (n = *cp++) {
|
||||
/*
|
||||
* Check for indirection
|
||||
*/
|
||||
switch (n & INDIR_MASK) {
|
||||
case 0:
|
||||
if (dn != exp_dn) {
|
||||
if (dn >= eom)
|
||||
return (-1);
|
||||
*dn++ = '.';
|
||||
}
|
||||
if (dn+n >= eom)
|
||||
return (-1);
|
||||
checked += n + 1;
|
||||
while (--n >= 0) {
|
||||
if ((c = *cp++) == '.') {
|
||||
if (dn + n + 2 >= eom)
|
||||
return (-1);
|
||||
*dn++ = '\\';
|
||||
}
|
||||
*dn++ = c;
|
||||
if (cp >= eomorig) /* out of range */
|
||||
return(-1);
|
||||
}
|
||||
break;
|
||||
|
||||
case INDIR_MASK:
|
||||
if (len < 0)
|
||||
len = cp - comp_dn + 1;
|
||||
cp = msg + (((n & 0x3f) << 8) | (*cp & 0xff));
|
||||
if (cp < msg || cp >= eomorig) /* out of range */
|
||||
return(-1);
|
||||
checked += 2;
|
||||
/*
|
||||
* Check for loops in the compressed name;
|
||||
* if we've looked at the whole message,
|
||||
* there must be a loop.
|
||||
*/
|
||||
if (checked >= eomorig - msg)
|
||||
return (-1);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (-1); /* flag error */
|
||||
}
|
||||
}
|
||||
*dn = '\0';
|
||||
if (len < 0)
|
||||
len = cp - comp_dn;
|
||||
return (len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compress domain name 'exp_dn' into 'comp_dn'.
|
||||
* Return the size of the compressed name or -1.
|
||||
* 'length' is the size of the array pointed to by 'comp_dn'.
|
||||
* 'dnptrs' is a list of pointers to previous compressed names. dnptrs[0]
|
||||
* is a pointer to the beginning of the message. The list ends with NULL.
|
||||
* 'lastdnptr' is a pointer to the end of the arrary pointed to
|
||||
* by 'dnptrs'. Side effect is to update the list of pointers for
|
||||
* labels inserted into the message as we compress the name.
|
||||
* If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
|
||||
* is NULL, we don't update the list.
|
||||
*/
|
||||
dn_comp(exp_dn, comp_dn, length, dnptrs, lastdnptr)
|
||||
u_char *exp_dn, *comp_dn;
|
||||
int length;
|
||||
u_char **dnptrs, **lastdnptr;
|
||||
{
|
||||
register u_char *cp, *dn;
|
||||
register int c, l;
|
||||
u_char **cpp, **lpp, *sp, *eob;
|
||||
u_char *msg;
|
||||
|
||||
dn = exp_dn;
|
||||
cp = comp_dn;
|
||||
eob = cp + length;
|
||||
if (dnptrs != NULL) {
|
||||
if ((msg = *dnptrs++) != NULL) {
|
||||
for (cpp = dnptrs; *cpp != NULL; cpp++)
|
||||
;
|
||||
lpp = cpp; /* end of list to search */
|
||||
}
|
||||
} else
|
||||
msg = NULL;
|
||||
for (c = *dn++; c != '\0'; ) {
|
||||
/* look to see if we can use pointers */
|
||||
if (msg != NULL) {
|
||||
if ((l = dn_find(dn-1, msg, dnptrs, lpp)) >= 0) {
|
||||
if (cp+1 >= eob)
|
||||
return (-1);
|
||||
*cp++ = (l >> 8) | INDIR_MASK;
|
||||
*cp++ = l % 256;
|
||||
return (cp - comp_dn);
|
||||
}
|
||||
/* not found, save it */
|
||||
if (lastdnptr != NULL && cpp < lastdnptr-1) {
|
||||
*cpp++ = cp;
|
||||
*cpp = NULL;
|
||||
}
|
||||
}
|
||||
sp = cp++; /* save ptr to length byte */
|
||||
do {
|
||||
if (c == '.') {
|
||||
c = *dn++;
|
||||
break;
|
||||
}
|
||||
if (c == '\\') {
|
||||
if ((c = *dn++) == '\0')
|
||||
break;
|
||||
}
|
||||
if (cp >= eob) {
|
||||
if (msg != NULL)
|
||||
*lpp = NULL;
|
||||
return (-1);
|
||||
}
|
||||
*cp++ = c;
|
||||
} while ((c = *dn++) != '\0');
|
||||
/* catch trailing '.'s but not '..' */
|
||||
if ((l = cp - sp - 1) == 0 && c == '\0') {
|
||||
cp--;
|
||||
break;
|
||||
}
|
||||
if (l <= 0 || l > MAXLABEL) {
|
||||
if (msg != NULL)
|
||||
*lpp = NULL;
|
||||
return (-1);
|
||||
}
|
||||
*sp = l;
|
||||
}
|
||||
if (cp >= eob) {
|
||||
if (msg != NULL)
|
||||
*lpp = NULL;
|
||||
return (-1);
|
||||
}
|
||||
*cp++ = '\0';
|
||||
return (cp - comp_dn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Skip over a compressed domain name. Return the size or -1.
|
||||
*/
|
||||
dn_skipname(comp_dn, eom)
|
||||
u_char *comp_dn, *eom;
|
||||
{
|
||||
register u_char *cp;
|
||||
register int n;
|
||||
|
||||
cp = comp_dn;
|
||||
while (cp < eom && (n = *cp++)) {
|
||||
/*
|
||||
* check for indirection
|
||||
*/
|
||||
switch (n & INDIR_MASK) {
|
||||
case 0: /* normal case, n == len */
|
||||
cp += n;
|
||||
continue;
|
||||
default: /* illegal type */
|
||||
return (-1);
|
||||
case INDIR_MASK: /* indirection */
|
||||
cp++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return (cp - comp_dn);
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for expanded name from a list of previously compressed names.
|
||||
* Return the offset from msg if found or -1.
|
||||
* dnptrs is the pointer to the first name on the list,
|
||||
* not the pointer to the start of the message.
|
||||
*/
|
||||
static
|
||||
dn_find(exp_dn, msg, dnptrs, lastdnptr)
|
||||
u_char *exp_dn, *msg;
|
||||
u_char **dnptrs, **lastdnptr;
|
||||
{
|
||||
register u_char *dn, *cp, **cpp;
|
||||
register int n;
|
||||
u_char *sp;
|
||||
|
||||
for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
|
||||
dn = exp_dn;
|
||||
sp = cp = *cpp;
|
||||
while (n = *cp++) {
|
||||
/*
|
||||
* check for indirection
|
||||
*/
|
||||
switch (n & INDIR_MASK) {
|
||||
case 0: /* normal case, n == len */
|
||||
while (--n >= 0) {
|
||||
if (*dn == '.')
|
||||
goto next;
|
||||
if (*dn == '\\')
|
||||
dn++;
|
||||
if (*dn++ != *cp++)
|
||||
goto next;
|
||||
}
|
||||
if ((n = *dn++) == '\0' && *cp == '\0')
|
||||
return (sp - msg);
|
||||
if (n == '.')
|
||||
continue;
|
||||
goto next;
|
||||
|
||||
default: /* illegal type */
|
||||
return (-1);
|
||||
|
||||
case INDIR_MASK: /* indirection */
|
||||
cp = msg + (((n & 0x3f) << 8) | *cp);
|
||||
}
|
||||
}
|
||||
if (*dn == '\0')
|
||||
return (sp - msg);
|
||||
next: ;
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Routines to insert/extract short/long's. Must account for byte
|
||||
* order and non-alignment problems. This code at least has the
|
||||
* advantage of being portable.
|
||||
*
|
||||
* used by sendmail.
|
||||
*/
|
||||
|
||||
u_short
|
||||
_getshort(msgp)
|
||||
u_char *msgp;
|
||||
{
|
||||
register u_char *p = (u_char *) msgp;
|
||||
#ifdef vax
|
||||
/*
|
||||
* vax compiler doesn't put shorts in registers
|
||||
*/
|
||||
register u_long u;
|
||||
#else
|
||||
register u_short u;
|
||||
#endif
|
||||
|
||||
u = *p++ << 8;
|
||||
return ((u_short)(u | *p));
|
||||
}
|
||||
|
||||
u_long
|
||||
_getlong(msgp)
|
||||
u_char *msgp;
|
||||
{
|
||||
register u_char *p = (u_char *) msgp;
|
||||
register u_long u;
|
||||
|
||||
u = *p++; u <<= 8;
|
||||
u |= *p++; u <<= 8;
|
||||
u |= *p++; u <<= 8;
|
||||
return (u | *p);
|
||||
}
|
||||
|
||||
|
||||
putshort(s, msgp)
|
||||
register u_short s;
|
||||
register u_char *msgp;
|
||||
{
|
||||
|
||||
msgp[1] = s;
|
||||
msgp[0] = s >> 8;
|
||||
}
|
||||
|
||||
putlong(l, msgp)
|
||||
register u_long l;
|
||||
register u_char *msgp;
|
||||
{
|
||||
|
||||
msgp[3] = l;
|
||||
msgp[2] = (l >>= 8);
|
||||
msgp[1] = (l >>= 8);
|
||||
msgp[0] = l >> 8;
|
||||
}
|
||||
206
ircd/res_init.c
Normal file
206
ircd/res_init.c
Normal file
@@ -0,0 +1,206 @@
|
||||
/*-
|
||||
* Copyright (c) 1985, 1989 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted provided
|
||||
* that: (1) source distributions retain this entire copyright notice and
|
||||
* comment, and (2) distributions including binaries display the following
|
||||
* acknowledgement: ``This product includes software developed by the
|
||||
* University of California, Berkeley and its contributors'' in the
|
||||
* documentation or other materials provided with the distribution and in
|
||||
* all advertising materials mentioning features or use of this software.
|
||||
* Neither the name of the University nor the names of its contributors may
|
||||
* be used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)res_init.c 6.14.1 (Berkeley) 6/27/90";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <stdio.h>
|
||||
#include "config.h" /* To get #define SOL20 Vesa */
|
||||
#include "sys.h"
|
||||
#include "nameser.h"
|
||||
#include "resolv.h"
|
||||
|
||||
/*
|
||||
* Resolver state default settings
|
||||
*/
|
||||
|
||||
struct state _res = {
|
||||
RES_TIMEOUT, /* retransmition time interval */
|
||||
4, /* number of times to retransmit */
|
||||
RES_DEFAULT, /* options flags */
|
||||
1, /* number of name servers */
|
||||
};
|
||||
|
||||
/*
|
||||
* Set up default settings. If the configuration file exist, the values
|
||||
* there will have precedence. Otherwise, the server address is set to
|
||||
* INADDR_ANY and the default domain name comes from the gethostname().
|
||||
*
|
||||
* The configuration file should only be used if you want to redefine your
|
||||
* domain or run without a server on your machine.
|
||||
*
|
||||
* Return 0 if completes successfully, -1 on error
|
||||
*/
|
||||
res_init()
|
||||
{
|
||||
register FILE *fp;
|
||||
register char *cp, *dp, **pp;
|
||||
register int n;
|
||||
char buf[BUFSIZ];
|
||||
extern u_long inet_addr();
|
||||
extern char *getenv();
|
||||
int nserv = 0; /* number of nameserver records read from file */
|
||||
int norder = 0;
|
||||
int haveenv = 0;
|
||||
int havesearch = 0;
|
||||
|
||||
_res.nsaddr.sin_addr.s_addr = INADDR_ANY;
|
||||
_res.nsaddr.sin_family = AF_INET;
|
||||
_res.nsaddr.sin_port = htons(NAMESERVER_PORT);
|
||||
_res.nscount = 1;
|
||||
|
||||
/* Allow user to override the local domain definition */
|
||||
if ((cp = getenv("LOCALDOMAIN")) != NULL) {
|
||||
(void)strncpy(_res.defdname, cp, sizeof(_res.defdname));
|
||||
haveenv++;
|
||||
}
|
||||
|
||||
if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
|
||||
/* read the config file */
|
||||
while (fgets(buf, sizeof(buf), fp) != NULL) {
|
||||
/* read default domain name */
|
||||
if (!strncmp(buf, "domain", sizeof("domain") - 1)) {
|
||||
if (haveenv) /* skip if have from environ */
|
||||
continue;
|
||||
cp = buf + sizeof("domain") - 1;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if ((*cp == '\0') || (*cp == '\n'))
|
||||
continue;
|
||||
(void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
|
||||
if ((cp = index(_res.defdname, '\n')) != NULL)
|
||||
*cp = '\0';
|
||||
havesearch = 0;
|
||||
continue;
|
||||
}
|
||||
/* set search list */
|
||||
if (!strncmp(buf, "search", sizeof("search") - 1)) {
|
||||
if (haveenv) /* skip if have from environ */
|
||||
continue;
|
||||
cp = buf + sizeof("search") - 1;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if ((*cp == '\0') || (*cp == '\n'))
|
||||
continue;
|
||||
(void)strncpy(_res.defdname, cp, sizeof(_res.defdname) - 1);
|
||||
if ((cp = index(_res.defdname, '\n')) != NULL)
|
||||
*cp = '\0';
|
||||
/*
|
||||
* Set search list to be blank-separated strings
|
||||
* on rest of line.
|
||||
*/
|
||||
cp = _res.defdname;
|
||||
pp = _res.dnsrch;
|
||||
*pp++ = cp;
|
||||
for (n = 0; *cp && pp < _res.dnsrch + MAXDNSRCH; cp++) {
|
||||
if (*cp == ' ' || *cp == '\t') {
|
||||
*cp = 0;
|
||||
n = 1;
|
||||
} else if (n) {
|
||||
*pp++ = cp;
|
||||
n = 0;
|
||||
}
|
||||
}
|
||||
/* null terminate last domain if there are excess */
|
||||
while (*cp != '\0' && *cp != ' ' && *cp != '\t')
|
||||
cp++;
|
||||
*cp = '\0';
|
||||
*pp++ = 0;
|
||||
havesearch = 1;
|
||||
continue;
|
||||
}
|
||||
/* read nameservers to query */
|
||||
if (!strncmp(buf, "nameserver", sizeof("nameserver") - 1) &&
|
||||
nserv < MAXNS) {
|
||||
cp = buf + sizeof("nameserver") - 1;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if ((*cp == '\0') || (*cp == '\n'))
|
||||
continue;
|
||||
if ((_res.nsaddr_list[nserv].sin_addr.s_addr =
|
||||
inet_addr(cp)) == (unsigned)-1) {
|
||||
_res.nsaddr_list[nserv].sin_addr.s_addr
|
||||
= INADDR_ANY;
|
||||
continue;
|
||||
}
|
||||
_res.nsaddr_list[nserv].sin_family = AF_INET;
|
||||
_res.nsaddr_list[nserv].sin_port = htons(NAMESERVER_PORT);
|
||||
nserv++;
|
||||
continue;
|
||||
}
|
||||
/* read service order */
|
||||
if (!strncmp(buf, "order", sizeof("order") - 1)) {
|
||||
cp = buf + sizeof("order") - 1;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
if ((*cp == '\0') || (*cp == '\n'))
|
||||
continue;
|
||||
norder = 0;
|
||||
do {
|
||||
if ((dp = index(cp, ',')) != NULL)
|
||||
*dp = '\0';
|
||||
if (norder >= MAXSERVICES)
|
||||
continue;
|
||||
if (!strncmp(cp, "bind", sizeof("bind") - 1))
|
||||
_res.order[norder++] = RES_SERVICE_BIND;
|
||||
else if (!strncmp(cp, "local", sizeof("local") - 1))
|
||||
_res.order[norder++] = RES_SERVICE_LOCAL;
|
||||
cp = dp + 1;
|
||||
} while (dp != NULL);
|
||||
_res.order[norder] = RES_SERVICE_NONE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (nserv > 1)
|
||||
_res.nscount = nserv;
|
||||
(void) fclose(fp);
|
||||
}
|
||||
if (_res.defdname[0] == 0) {
|
||||
if (gethostname(buf, sizeof(_res.defdname)) == 0 &&
|
||||
(cp = index(buf, '.')))
|
||||
(void)strcpy(_res.defdname, cp + 1);
|
||||
}
|
||||
|
||||
/* find components of local domain that might be searched */
|
||||
if (havesearch == 0) {
|
||||
pp = _res.dnsrch;
|
||||
*pp++ = _res.defdname;
|
||||
for (cp = _res.defdname, n = 0; *cp; cp++)
|
||||
if (*cp == '.')
|
||||
n++;
|
||||
cp = _res.defdname;
|
||||
for (; n >= LOCALDOMAINPARTS && pp < _res.dnsrch + MAXDFLSRCH;
|
||||
n--) {
|
||||
cp = index(cp, '.');
|
||||
*pp++ = ++cp;
|
||||
}
|
||||
*pp++ = 0;
|
||||
}
|
||||
/* default search order to bind only */
|
||||
if (norder == 0) {
|
||||
_res.order[0] = RES_SERVICE_BIND;
|
||||
_res.order[1] = RES_SERVICE_NONE;
|
||||
}
|
||||
_res.options |= RES_INIT;
|
||||
return (0);
|
||||
}
|
||||
192
ircd/res_mkquery.c
Normal file
192
ircd/res_mkquery.c
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (c) 1985 Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms are permitted
|
||||
* provided that: (1) source distributions retain this entire copyright
|
||||
* notice and comment, and (2) distributions including binaries display
|
||||
* the following acknowledgement: ``This product includes software
|
||||
* developed by the University of California, Berkeley and its contributors''
|
||||
* in the documentation or other materials provided with the distribution
|
||||
* and in all advertising materials mentioning features or use of this
|
||||
* software. Neither the name of the University nor the names of its
|
||||
* contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)res_mkquery.c 6.12 (Berkeley) 6/1/90";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <netinet/in.h>
|
||||
#include "config.h"
|
||||
#include "sys.h"
|
||||
#include "nameser.h"
|
||||
#include "resolv.h"
|
||||
|
||||
/*
|
||||
* Form all types of queries.
|
||||
* Returns the size of the result or -1.
|
||||
*/
|
||||
res_mkquery(op, dname, class, type, data, datalen, newrr, buf, buflen)
|
||||
int op; /* opcode of query */
|
||||
char *dname; /* domain name */
|
||||
int class, type; /* class and type of query */
|
||||
char *data; /* resource record data */
|
||||
int datalen; /* length of data */
|
||||
struct rrec *newrr; /* new rr for modify or append */
|
||||
char *buf; /* buffer to put query */
|
||||
int buflen; /* size of buffer */
|
||||
{
|
||||
register HEADER *hp;
|
||||
register char *cp;
|
||||
register int n;
|
||||
char *dnptrs[10], **dpp, **lastdnptr;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (_res.options & RES_DEBUG)
|
||||
printf("res_mkquery(%d, %s, %d, %d)\n", op, dname, class, type);
|
||||
#endif /*DEBUG*/
|
||||
/*
|
||||
* Initialize header fields.
|
||||
*/
|
||||
if ((buf == NULL) || (buflen < sizeof(HEADER)))
|
||||
return(-1);
|
||||
bzero(buf, sizeof(HEADER));
|
||||
hp = (HEADER *) buf;
|
||||
hp->id = htons(++_res.id);
|
||||
hp->opcode = op;
|
||||
hp->pr = (_res.options & RES_PRIMARY) != 0;
|
||||
hp->rd = (_res.options & RES_RECURSE) != 0;
|
||||
hp->rcode = NOERROR;
|
||||
cp = buf + sizeof(HEADER);
|
||||
buflen -= sizeof(HEADER);
|
||||
dpp = dnptrs;
|
||||
*dpp++ = buf;
|
||||
*dpp++ = NULL;
|
||||
lastdnptr = dnptrs + sizeof(dnptrs)/sizeof(dnptrs[0]);
|
||||
/*
|
||||
* perform opcode specific processing
|
||||
*/
|
||||
switch (op) {
|
||||
case QUERY:
|
||||
if ((buflen -= QFIXEDSZ) < 0)
|
||||
return(-1);
|
||||
if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
|
||||
return (-1);
|
||||
cp += n;
|
||||
buflen -= n;
|
||||
putshort(type, cp);
|
||||
cp += sizeof(u_short);
|
||||
putshort(class, cp);
|
||||
cp += sizeof(u_short);
|
||||
hp->qdcount = htons(1);
|
||||
if (op == QUERY || data == NULL)
|
||||
break;
|
||||
/*
|
||||
* Make an additional record for completion domain.
|
||||
*/
|
||||
buflen -= RRFIXEDSZ;
|
||||
if ((n = dn_comp(data, cp, buflen, dnptrs, lastdnptr)) < 0)
|
||||
return (-1);
|
||||
cp += n;
|
||||
buflen -= n;
|
||||
putshort(T_NULL, cp);
|
||||
cp += sizeof(u_short);
|
||||
putshort(class, cp);
|
||||
cp += sizeof(u_short);
|
||||
putlong(0, cp);
|
||||
cp += sizeof(u_long);
|
||||
putshort(0, cp);
|
||||
cp += sizeof(u_short);
|
||||
hp->arcount = htons(1);
|
||||
break;
|
||||
|
||||
case IQUERY:
|
||||
/*
|
||||
* Initialize answer section
|
||||
*/
|
||||
if (buflen < 1 + RRFIXEDSZ + datalen)
|
||||
return (-1);
|
||||
*cp++ = '\0'; /* no domain name */
|
||||
putshort(type, cp);
|
||||
cp += sizeof(u_short);
|
||||
putshort(class, cp);
|
||||
cp += sizeof(u_short);
|
||||
putlong(0, cp);
|
||||
cp += sizeof(u_long);
|
||||
putshort(datalen, cp);
|
||||
cp += sizeof(u_short);
|
||||
if (datalen) {
|
||||
bcopy(data, cp, datalen);
|
||||
cp += datalen;
|
||||
}
|
||||
hp->ancount = htons(1);
|
||||
break;
|
||||
|
||||
#ifdef ALLOW_UPDATES
|
||||
/*
|
||||
* For UPDATEM/UPDATEMA, do UPDATED/UPDATEDA followed by UPDATEA
|
||||
* (Record to be modified is followed by its replacement in msg.)
|
||||
*/
|
||||
case UPDATEM:
|
||||
case UPDATEMA:
|
||||
|
||||
case UPDATED:
|
||||
/*
|
||||
* The res code for UPDATED and UPDATEDA is the same; user
|
||||
* calls them differently: specifies data for UPDATED; server
|
||||
* ignores data if specified for UPDATEDA.
|
||||
*/
|
||||
case UPDATEDA:
|
||||
buflen -= RRFIXEDSZ + datalen;
|
||||
if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
|
||||
return (-1);
|
||||
cp += n;
|
||||
putshort(type, cp);
|
||||
cp += sizeof(u_short);
|
||||
putshort(class, cp);
|
||||
cp += sizeof(u_short);
|
||||
putlong(0, cp);
|
||||
cp += sizeof(u_long);
|
||||
putshort(datalen, cp);
|
||||
cp += sizeof(u_short);
|
||||
if (datalen) {
|
||||
bcopy(data, cp, datalen);
|
||||
cp += datalen;
|
||||
}
|
||||
if ( (op == UPDATED) || (op == UPDATEDA) ) {
|
||||
hp->ancount = htons(0);
|
||||
break;
|
||||
}
|
||||
/* Else UPDATEM/UPDATEMA, so drop into code for UPDATEA */
|
||||
|
||||
case UPDATEA: /* Add new resource record */
|
||||
buflen -= RRFIXEDSZ + datalen;
|
||||
if ((n = dn_comp(dname, cp, buflen, dnptrs, lastdnptr)) < 0)
|
||||
return (-1);
|
||||
cp += n;
|
||||
putshort(newrr->r_type, cp);
|
||||
cp += sizeof(u_short);
|
||||
putshort(newrr->r_class, cp);
|
||||
cp += sizeof(u_short);
|
||||
putlong(0, cp);
|
||||
cp += sizeof(u_long);
|
||||
putshort(newrr->r_size, cp);
|
||||
cp += sizeof(u_short);
|
||||
if (newrr->r_size) {
|
||||
bcopy(newrr->r_data, cp, newrr->r_size);
|
||||
cp += newrr->r_size;
|
||||
}
|
||||
hp->ancount = htons(0);
|
||||
break;
|
||||
|
||||
#endif /* ALLOW_UPDATES */
|
||||
}
|
||||
return (cp - buf);
|
||||
}
|
||||
267
ircd/s_auth.c
Normal file
267
ircd/s_auth.c
Normal file
@@ -0,0 +1,267 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, ircd/s_auth.c
|
||||
* Copyright (C) 1992 Darren Reed
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)s_auth.c 1.18 4/18/94 (C) 1992 Darren Reed";
|
||||
#endif
|
||||
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "res.h"
|
||||
#include "numeric.h"
|
||||
#include "patchlevel.h"
|
||||
#include <sys/socket.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/ioctl.h>
|
||||
#ifdef UNIXPORT
|
||||
# include <sys/un.h>
|
||||
#endif
|
||||
#if defined(__hpux)
|
||||
# include "inet.h"
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include "sock.h" /* If FD_ZERO isn't define up to this point, */
|
||||
/* define it (BSD4.2 needs this) */
|
||||
#include "h.h"
|
||||
|
||||
/*
|
||||
* start_auth
|
||||
*
|
||||
* Flag the client to show that an attempt to contact the ident server on
|
||||
* the client's host. The connect and subsequently the socket are all put
|
||||
* into 'non-blocking' mode. Should the connect or any later phase of the
|
||||
* identifing process fail, it is aborted and the user is given a username
|
||||
* of "unknown".
|
||||
*/
|
||||
void start_auth(cptr)
|
||||
Reg1 aClient *cptr;
|
||||
{
|
||||
struct sockaddr_in sock;
|
||||
int err;
|
||||
#ifdef VIRTUAL_HOST
|
||||
extern struct sockaddr_in vserv;
|
||||
#endif
|
||||
|
||||
Debug((DEBUG_NOTICE,"start_auth(%x) fd %d status %d",
|
||||
cptr, cptr->fd, cptr->status));
|
||||
|
||||
(void)alarm(2);
|
||||
cptr->authfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
err = errno;
|
||||
(void)alarm(0);
|
||||
if (cptr->authfd < 0 && err == EAGAIN)
|
||||
sendto_ops(
|
||||
"Can't allocate fd for auth on %s : socket: No more sockets",
|
||||
get_client_name(cptr, TRUE));
|
||||
|
||||
if (cptr->authfd < 0)
|
||||
{
|
||||
#ifdef USE_SYSLOG
|
||||
syslog(LOG_ERR, "Unable to create auth socket for %s:%m",
|
||||
get_client_name(cptr, TRUE));
|
||||
#endif
|
||||
Debug((DEBUG_ERROR, "Unable to create auth socket for %s:%s",
|
||||
get_client_name(cptr, TRUE),
|
||||
strerror(get_sockerr(cptr))));
|
||||
if (!DoingDNS(cptr))
|
||||
SetAccess(cptr);
|
||||
ircstp->is_abad++;
|
||||
return;
|
||||
}
|
||||
if (cptr->authfd >= (MAXCONNECTIONS - 2))
|
||||
{
|
||||
sendto_ops("Can't allocate fd for auth on %s",
|
||||
get_client_name(cptr, TRUE));
|
||||
(void)close(cptr->authfd);
|
||||
return;
|
||||
}
|
||||
|
||||
set_non_blocking(cptr->authfd, cptr);
|
||||
|
||||
#ifdef VIRTUAL_HOST
|
||||
if (bind(cptr->authfd, (struct sockaddr *)&vserv,
|
||||
sizeof(vserv)) == -1)
|
||||
{
|
||||
report_error("binding auth stream socket %s:%s", cptr);
|
||||
(void)close(cptr->fd);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
bcopy((char *)&cptr->ip, (char *)&sock.sin_addr,
|
||||
sizeof(struct in_addr));
|
||||
|
||||
sock.sin_port = htons(113);
|
||||
sock.sin_family = AF_INET;
|
||||
|
||||
(void)alarm((unsigned)4);
|
||||
if (connect(cptr->authfd, (struct sockaddr *)&sock,
|
||||
sizeof(sock)) == -1 && errno != EINPROGRESS)
|
||||
{
|
||||
ircstp->is_abad++;
|
||||
/*
|
||||
* No error report from this...
|
||||
*/
|
||||
(void)alarm((unsigned)0);
|
||||
(void)close(cptr->authfd);
|
||||
cptr->authfd = -1;
|
||||
if (!DoingDNS(cptr))
|
||||
SetAccess(cptr);
|
||||
return;
|
||||
}
|
||||
(void)alarm((unsigned)0);
|
||||
cptr->flags |= (FLAGS_WRAUTH|FLAGS_AUTH);
|
||||
if (cptr->authfd > highest_fd)
|
||||
highest_fd = cptr->authfd;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* send_authports
|
||||
*
|
||||
* Send the ident server a query giving "theirport , ourport".
|
||||
* The write is only attempted *once* so it is deemed to be a fail if the
|
||||
* entire write doesn't write all the data given. This shouldnt be a
|
||||
* problem since the socket should have a write buffer far greater than
|
||||
* this message to store it in should problems arise. -avalon
|
||||
*/
|
||||
void send_authports(cptr)
|
||||
aClient *cptr;
|
||||
{
|
||||
struct sockaddr_in us, them;
|
||||
char authbuf[32];
|
||||
int ulen, tlen;
|
||||
|
||||
Debug((DEBUG_NOTICE,"write_authports(%x) fd %d authfd %d stat %d",
|
||||
cptr, cptr->fd, cptr->authfd, cptr->status));
|
||||
tlen = ulen = sizeof(us);
|
||||
if (getsockname(cptr->fd, (struct sockaddr *)&us, &ulen) ||
|
||||
getpeername(cptr->fd, (struct sockaddr *)&them, &tlen))
|
||||
{
|
||||
#ifdef USE_SYSLOG
|
||||
syslog(LOG_ERR, "auth get{sock,peer}name error for %s:%m",
|
||||
get_client_name(cptr, TRUE));
|
||||
#endif
|
||||
goto authsenderr;
|
||||
}
|
||||
|
||||
(void)sprintf(authbuf, "%u , %u\r\n",
|
||||
(unsigned int)ntohs(them.sin_port),
|
||||
(unsigned int)ntohs(us.sin_port));
|
||||
|
||||
Debug((DEBUG_SEND, "sending [%s] to auth port %s.113",
|
||||
authbuf, inetntoa((char *)&them.sin_addr)));
|
||||
if (write(cptr->authfd, authbuf, strlen(authbuf)) != strlen(authbuf))
|
||||
{
|
||||
authsenderr:
|
||||
ircstp->is_abad++;
|
||||
(void)close(cptr->authfd);
|
||||
if (cptr->authfd == highest_fd)
|
||||
while (!local[highest_fd])
|
||||
highest_fd--;
|
||||
cptr->authfd = -1;
|
||||
cptr->flags &= ~FLAGS_AUTH;
|
||||
if (!DoingDNS(cptr))
|
||||
SetAccess(cptr);
|
||||
}
|
||||
cptr->flags &= ~FLAGS_WRAUTH;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* read_authports
|
||||
*
|
||||
* read the reply (if any) from the ident server we connected to.
|
||||
* The actual read processijng here is pretty weak - no handling of the reply
|
||||
* if it is fragmented by IP.
|
||||
*/
|
||||
void read_authports(cptr)
|
||||
Reg1 aClient *cptr;
|
||||
{
|
||||
Reg1 char *s, *t;
|
||||
Reg2 int len;
|
||||
char ruser[USERLEN+1], system[8];
|
||||
u_short remp = 0, locp = 0;
|
||||
|
||||
*system = *ruser = '\0';
|
||||
Debug((DEBUG_NOTICE,"read_authports(%x) fd %d authfd %d stat %d",
|
||||
cptr, cptr->fd, cptr->authfd, cptr->status));
|
||||
/*
|
||||
* Nasty. Cant allow any other reads from client fd while we're
|
||||
* waiting on the authfd to return a full valid string. Use the
|
||||
* client's input buffer to buffer the authd reply.
|
||||
* Oh. this is needed because an authd reply may come back in more
|
||||
* than 1 read! -avalon
|
||||
*/
|
||||
if ((len = read(cptr->authfd, cptr->buffer + cptr->count,
|
||||
sizeof(cptr->buffer) - 1 - cptr->count)) >= 0)
|
||||
{
|
||||
cptr->count += len;
|
||||
cptr->buffer[cptr->count] = '\0';
|
||||
}
|
||||
|
||||
cptr->lasttime = now;
|
||||
if ((len > 0) && (cptr->count != (sizeof(cptr->buffer) - 1)) &&
|
||||
(sscanf(cptr->buffer, "%hd , %hd : USERID : %*[^:]: %10s",
|
||||
&remp, &locp, ruser) == 3))
|
||||
{
|
||||
s = rindex(cptr->buffer, ':');
|
||||
*s++ = '\0';
|
||||
for (t = (rindex(cptr->buffer, ':') + 1); *t; t++)
|
||||
if (!isspace(*t))
|
||||
break;
|
||||
strncpyzt(system, t, sizeof(system));
|
||||
for (t = ruser; *s && (t < ruser + sizeof(ruser)); s++)
|
||||
if (!isspace(*s) && *s != ':' && *s != '@')
|
||||
*t++ = *s;
|
||||
*t = '\0';
|
||||
Debug((DEBUG_INFO,"auth reply ok [%s] [%s]", system, ruser));
|
||||
}
|
||||
else if (len != 0)
|
||||
{
|
||||
if (!index(cptr->buffer, '\n') && !index(cptr->buffer, '\r'))
|
||||
return;
|
||||
Debug((DEBUG_ERROR,"local %d remote %d", locp, remp));
|
||||
Debug((DEBUG_ERROR,"bad auth reply in [%s]", cptr->buffer));
|
||||
*ruser = '\0';
|
||||
}
|
||||
(void)close(cptr->authfd);
|
||||
if (cptr->authfd == highest_fd)
|
||||
while (!local[highest_fd])
|
||||
highest_fd--;
|
||||
cptr->count = 0;
|
||||
cptr->authfd = -1;
|
||||
ClearAuth(cptr);
|
||||
if (!DoingDNS(cptr))
|
||||
SetAccess(cptr);
|
||||
if (len > 0)
|
||||
Debug((DEBUG_INFO,"ident reply: [%s]", cptr->buffer));
|
||||
|
||||
if (!locp || !remp || !*ruser)
|
||||
{
|
||||
ircstp->is_abad++;
|
||||
return;
|
||||
}
|
||||
ircstp->is_asuc++;
|
||||
strncpyzt(cptr->username, ruser, USERLEN+1);
|
||||
if (strncmp(system, "OTHER", 5))
|
||||
cptr->flags |= FLAGS_GOTID;
|
||||
Debug((DEBUG_INFO, "got username [%s]", ruser));
|
||||
return;
|
||||
}
|
||||
2601
ircd/s_bsd.c
Normal file
2601
ircd/s_bsd.c
Normal file
File diff suppressed because it is too large
Load Diff
1438
ircd/s_conf.c
Normal file
1438
ircd/s_conf.c
Normal file
File diff suppressed because it is too large
Load Diff
475
ircd/s_debug.c
Normal file
475
ircd/s_debug.c
Normal file
@@ -0,0 +1,475 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, ircd/s_debug.c
|
||||
* Copyright (C) 1990 Jarkko Oikarinen and
|
||||
* University of Oulu, Computing Center
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)s_debug.c 2.30 1/3/94 (C) 1988 University of Oulu, \
|
||||
Computing Center and Jarkko Oikarinen";
|
||||
#endif
|
||||
|
||||
#include "struct.h"
|
||||
/*
|
||||
* Option string. Must be before #ifdef DEBUGMODE.
|
||||
*/
|
||||
char serveropts[] = {
|
||||
#ifdef CHROOTDIR
|
||||
'c',
|
||||
#endif
|
||||
#ifdef CMDLINE_CONFIG
|
||||
'C',
|
||||
#endif
|
||||
#ifdef DO_ID
|
||||
'd',
|
||||
#endif
|
||||
#ifdef DEBUGMODE
|
||||
'D',
|
||||
#endif
|
||||
#ifdef LOCOP_REHASH
|
||||
'e',
|
||||
#endif
|
||||
#ifdef OPER_REHASH
|
||||
'E',
|
||||
#endif
|
||||
#ifdef NOTE_FORWARDER
|
||||
'f',
|
||||
#endif
|
||||
#ifdef HUB
|
||||
'H',
|
||||
#endif
|
||||
#ifdef SHOW_INVISIBLE_LUSERS
|
||||
'i',
|
||||
#endif
|
||||
#ifdef OPER_KILL
|
||||
# ifdef LOCAL_KILL_ONLY
|
||||
'k',
|
||||
# else
|
||||
'K',
|
||||
# endif
|
||||
#endif
|
||||
#ifdef LEAST_IDLE
|
||||
'L',
|
||||
#endif
|
||||
#ifdef M4_PREPROC
|
||||
'm',
|
||||
#endif
|
||||
#ifdef IDLE_FROM_MSG
|
||||
'M',
|
||||
#endif
|
||||
#ifdef CRYPT_OPER_PASSWORD
|
||||
'p',
|
||||
#endif
|
||||
#ifdef CRYPT_LINK_PASSWORD
|
||||
'P',
|
||||
#endif
|
||||
#ifdef NPATH
|
||||
'N',
|
||||
#endif
|
||||
#ifdef LOCOP_RESTART
|
||||
'r',
|
||||
#endif
|
||||
#ifdef OPER_RESTART
|
||||
'R',
|
||||
#endif
|
||||
#ifdef ENABLE_SUMMON
|
||||
'S',
|
||||
#endif
|
||||
#ifdef OPER_REMOTE
|
||||
't',
|
||||
#endif
|
||||
#ifdef IRCII_KLUDGE
|
||||
'u',
|
||||
#endif
|
||||
#ifdef ENABLE_USERS
|
||||
'U',
|
||||
#endif
|
||||
#ifdef VALLOC
|
||||
'V',
|
||||
#endif
|
||||
#ifdef UNIXPORT
|
||||
'X',
|
||||
#endif
|
||||
#ifdef USE_SYSLOG
|
||||
'Y',
|
||||
#endif
|
||||
#ifdef V28PlusOnly
|
||||
'8',
|
||||
#endif
|
||||
'\0'};
|
||||
|
||||
#include "numeric.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "whowas.h"
|
||||
#include "hash.h"
|
||||
#include <sys/file.h>
|
||||
#ifdef HPUX
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#if !defined(ULTRIX) && !defined(SGI) && !defined(sequent) && \
|
||||
!defined(__convex__)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
#ifdef HPUX
|
||||
# include <sys/syscall.h>
|
||||
# define getrusage(a,b) syscall(SYS_GETRUSAGE, a, b)
|
||||
#endif
|
||||
#ifdef GETRUSAGE_2
|
||||
# ifdef SOL20
|
||||
# include <sys/time.h>
|
||||
# include <sys/rusage.h>
|
||||
# endif
|
||||
# include <sys/resource.h>
|
||||
#else
|
||||
# ifdef TIMES_2
|
||||
# include <sys/times.h>
|
||||
# endif
|
||||
#endif
|
||||
#ifdef PCS
|
||||
# include <time.h>
|
||||
#endif
|
||||
#ifdef HPUX
|
||||
#include <unistd.h>
|
||||
#ifdef DYNIXPTX
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
#endif
|
||||
#include "h.h"
|
||||
|
||||
#ifndef ssize_t
|
||||
#define ssize_t unsigned int
|
||||
#endif
|
||||
|
||||
#ifdef DEBUGMODE
|
||||
static char debugbuf[1024];
|
||||
|
||||
#ifndef USE_VARARGS
|
||||
/*VARARGS2*/
|
||||
void debug(level, form, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)
|
||||
int level;
|
||||
char *form, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10;
|
||||
{
|
||||
int err = errno;
|
||||
#else
|
||||
void debug(level, form, va_alist)
|
||||
int level;
|
||||
char *form;
|
||||
va_dcl
|
||||
{
|
||||
va_list vl;
|
||||
int err = errno;
|
||||
|
||||
va_start(vl);
|
||||
#endif
|
||||
|
||||
if ((debuglevel >= 0) && (level <= debuglevel))
|
||||
{
|
||||
#ifndef USE_VARARGS
|
||||
(void)sprintf(debugbuf, form,
|
||||
p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
|
||||
#else
|
||||
(void)vsprintf(debugbuf, form, vl);
|
||||
#endif
|
||||
if (local[2])
|
||||
{
|
||||
local[2]->sendM++;
|
||||
local[2]->sendB += strlen(debugbuf);
|
||||
}
|
||||
(void)fprintf(stderr, "%s", debugbuf);
|
||||
(void)fputc('\n', stderr);
|
||||
}
|
||||
errno = err;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is part of the STATS replies. There is no offical numeric for this
|
||||
* since this isnt an official command, in much the same way as HASH isnt.
|
||||
* It is also possible that some systems wont support this call or have
|
||||
* different field names for "struct rusage".
|
||||
* -avalon
|
||||
*/
|
||||
void send_usage(cptr, nick)
|
||||
aClient *cptr;
|
||||
char *nick;
|
||||
{
|
||||
|
||||
#ifdef GETRUSAGE_2
|
||||
struct rusage rus;
|
||||
time_t secs, rup;
|
||||
#ifdef hz
|
||||
# define hzz hz
|
||||
#else
|
||||
# ifdef HZ
|
||||
# define hzz HZ
|
||||
# else
|
||||
int hzz = 1;
|
||||
# ifdef HPUX
|
||||
hzz = (int)sysconf(_SC_CLK_TCK);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
if (getrusage(RUSAGE_SELF, &rus) == -1)
|
||||
{
|
||||
#if !defined(__FreeBSD__) && !defined(__NetBSD__)
|
||||
extern char *sys_errlist[];
|
||||
#endif
|
||||
sendto_one(cptr,":%s NOTICE %s :Getruseage error: %s.",
|
||||
me.name, nick, sys_errlist[errno]);
|
||||
return;
|
||||
}
|
||||
secs = rus.ru_utime.tv_sec + rus.ru_stime.tv_sec;
|
||||
rup = now - me.since;
|
||||
if (secs == 0)
|
||||
secs = 1;
|
||||
|
||||
sendto_one(cptr,
|
||||
":%s %d %s :CPU Secs %d:%d User %d:%d System %d:%d",
|
||||
me.name, RPL_STATSDEBUG, nick, secs/60, secs%60,
|
||||
rus.ru_utime.tv_sec/60, rus.ru_utime.tv_sec%60,
|
||||
rus.ru_stime.tv_sec/60, rus.ru_stime.tv_sec%60);
|
||||
sendto_one(cptr, ":%s %d %s :RSS %d ShMem %d Data %d Stack %d",
|
||||
me.name, RPL_STATSDEBUG, nick, rus.ru_maxrss,
|
||||
rus.ru_ixrss / (rup * hzz), rus.ru_idrss / (rup * hzz),
|
||||
rus.ru_isrss / (rup * hzz));
|
||||
sendto_one(cptr, ":%s %d %s :Swaps %d Reclaims %d Faults %d",
|
||||
me.name, RPL_STATSDEBUG, nick, rus.ru_nswap,
|
||||
rus.ru_minflt, rus.ru_majflt);
|
||||
sendto_one(cptr, ":%s %d %s :Block in %d out %d",
|
||||
me.name, RPL_STATSDEBUG, nick, rus.ru_inblock,
|
||||
rus.ru_oublock);
|
||||
sendto_one(cptr, ":%s %d %s :Msg Rcv %d Send %d",
|
||||
me.name, RPL_STATSDEBUG, nick, rus.ru_msgrcv, rus.ru_msgsnd);
|
||||
sendto_one(cptr, ":%s %d %s :Signals %d Context Vol. %d Invol %d",
|
||||
me.name, RPL_STATSDEBUG, nick, rus.ru_nsignals,
|
||||
rus.ru_nvcsw, rus.ru_nivcsw);
|
||||
#else
|
||||
# ifdef TIMES_2
|
||||
struct tms tmsbuf;
|
||||
time_t secs, mins;
|
||||
int hzz = 1, ticpermin;
|
||||
int umin, smin, usec, ssec;
|
||||
|
||||
# ifdef HPUX
|
||||
hzz = sysconf(_SC_CLK_TCK);
|
||||
# endif
|
||||
ticpermin = hzz * 60;
|
||||
|
||||
umin = tmsbuf.tms_utime / ticpermin;
|
||||
usec = (tmsbuf.tms_utime%ticpermin)/(float)hzz;
|
||||
smin = tmsbuf.tms_stime / ticpermin;
|
||||
ssec = (tmsbuf.tms_stime%ticpermin)/(float)hzz;
|
||||
secs = usec + ssec;
|
||||
mins = (secs/60) + umin + smin;
|
||||
secs %= hzz;
|
||||
|
||||
if (times(&tmsbuf) == -1)
|
||||
{
|
||||
sendto_one(cptr,":%s %d %s :times(2) error: %s.",
|
||||
me.name, RPL_STATSDEBUG, nick, strerror(errno));
|
||||
return;
|
||||
}
|
||||
secs = tmsbuf.tms_utime + tmsbuf.tms_stime;
|
||||
|
||||
sendto_one(cptr,
|
||||
":%s %d %s :CPU Secs %d:%d User %d:%d System %d:%d",
|
||||
me.name, RPL_STATSDEBUG, nick, mins, secs, umin, usec,
|
||||
smin, ssec);
|
||||
# endif
|
||||
#endif
|
||||
sendto_one(cptr, ":%s %d %s :Reads %d Writes %d",
|
||||
me.name, RPL_STATSDEBUG, nick, readcalls, writecalls);
|
||||
sendto_one(cptr, ":%s %d %s :DBUF alloc %d blocks %d",
|
||||
me.name, RPL_STATSDEBUG, nick, dbufalloc, dbufblocks);
|
||||
sendto_one(cptr,
|
||||
":%s %d %s :Writes: <0 %d 0 %d <16 %d <32 %d <64 %d",
|
||||
me.name, RPL_STATSDEBUG, nick,
|
||||
writeb[0], writeb[1], writeb[2], writeb[3], writeb[4]);
|
||||
sendto_one(cptr,
|
||||
":%s %d %s :<128 %d <256 %d <512 %d <1024 %d >1024 %d",
|
||||
me.name, RPL_STATSDEBUG, nick,
|
||||
writeb[5], writeb[6], writeb[7], writeb[8], writeb[9]);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
void count_memory(cptr, nick)
|
||||
aClient *cptr;
|
||||
char *nick;
|
||||
{
|
||||
extern aChannel *channel;
|
||||
extern aClass *classes;
|
||||
extern aConfItem *conf;
|
||||
|
||||
Reg1 aClient *acptr;
|
||||
Reg2 Link *link;
|
||||
Reg3 aChannel *chptr;
|
||||
Reg4 aConfItem *aconf;
|
||||
Reg5 aClass *cltmp;
|
||||
|
||||
int lc = 0, /* local clients */
|
||||
ch = 0, /* channels */
|
||||
lcc = 0, /* local client conf links */
|
||||
rc = 0, /* remote clients */
|
||||
us = 0, /* user structs */
|
||||
chu = 0, /* channel users */
|
||||
chi = 0, /* channel invites */
|
||||
chb = 0, /* channel bans */
|
||||
wwu = 0, /* whowas users */
|
||||
cl = 0, /* classes */
|
||||
co = 0; /* conf lines */
|
||||
|
||||
int usi = 0, /* users invited */
|
||||
usc = 0, /* users in channels */
|
||||
aw = 0, /* aways set */
|
||||
wwa = 0; /* whowas aways */
|
||||
|
||||
u_long chm = 0, /* memory used by channels */
|
||||
chbm = 0, /* memory used by channel bans */
|
||||
lcm = 0, /* memory used by local clients */
|
||||
rcm = 0, /* memory used by remote clients */
|
||||
awm = 0, /* memory used by aways */
|
||||
wwam = 0, /* whowas away memory used */
|
||||
wwm = 0, /* whowas array memory used */
|
||||
com = 0, /* memory used by conf lines */
|
||||
db = 0, /* memory used by dbufs */
|
||||
rm = 0, /* res memory used */
|
||||
totcl = 0,
|
||||
totch = 0,
|
||||
totww = 0,
|
||||
tot = 0;
|
||||
|
||||
count_whowas_memory(&wwu, &wwa, &wwam);
|
||||
wwm = sizeof(aName) * NICKNAMEHISTORYLENGTH;
|
||||
|
||||
for (acptr = client; acptr; acptr = acptr->next)
|
||||
{
|
||||
if (IsPing(acptr))
|
||||
continue;
|
||||
if (MyConnect(acptr))
|
||||
{
|
||||
lc++;
|
||||
for (link = acptr->confs; link; link = link->next)
|
||||
lcc++;
|
||||
}
|
||||
else
|
||||
rc++;
|
||||
if (acptr->user)
|
||||
{
|
||||
us++;
|
||||
for (link = acptr->user->invited; link;
|
||||
link = link->next)
|
||||
usi++;
|
||||
for (link = acptr->user->channel; link;
|
||||
link = link->next)
|
||||
usc++;
|
||||
if (acptr->user->away)
|
||||
{
|
||||
aw++;
|
||||
awm += (strlen(acptr->user->away)+1);
|
||||
}
|
||||
}
|
||||
}
|
||||
lcm = lc * CLIENT_LOCAL_SIZE;
|
||||
rcm = rc * CLIENT_REMOTE_SIZE;
|
||||
|
||||
for (chptr = channel; chptr; chptr = chptr->nextch)
|
||||
{
|
||||
ch++;
|
||||
chm += (strlen(chptr->chname) + sizeof(aChannel));
|
||||
for (link = chptr->members; link; link = link->next)
|
||||
chu++;
|
||||
for (link = chptr->invites; link; link = link->next)
|
||||
chi++;
|
||||
for (link = chptr->banlist; link; link = link->next)
|
||||
{
|
||||
chb++;
|
||||
chbm += (strlen(link->value.cp)+1+sizeof(Link));
|
||||
}
|
||||
}
|
||||
|
||||
for (aconf = conf; aconf; aconf = aconf->next)
|
||||
{
|
||||
co++;
|
||||
com += aconf->host ? strlen(aconf->host)+1 : 0;
|
||||
com += aconf->passwd ? strlen(aconf->passwd)+1 : 0;
|
||||
com += aconf->name ? strlen(aconf->name)+1 : 0;
|
||||
com += sizeof(aConfItem);
|
||||
}
|
||||
|
||||
for (cltmp = classes; cltmp; cltmp = cltmp->next)
|
||||
cl++;
|
||||
|
||||
sendto_one(cptr, ":%s %d %s :Client Local %d(%d) Remote %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, nick, lc, lcm, rc, rcm);
|
||||
sendto_one(cptr, ":%s %d %s :Users %d(%d) Invites %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, nick, us, us*sizeof(anUser), usi,
|
||||
usi * sizeof(Link));
|
||||
sendto_one(cptr, ":%s %d %s :User channels %d(%d) Aways %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, nick, usc, usc*sizeof(Link),
|
||||
aw, awm);
|
||||
sendto_one(cptr, ":%s %d %s :Attached confs %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, nick, lcc, lcc*sizeof(Link));
|
||||
|
||||
totcl = lcm + rcm + us*sizeof(anUser) + usc*sizeof(Link) + awm;
|
||||
totcl += lcc*sizeof(Link) + usi*sizeof(Link);
|
||||
|
||||
sendto_one(cptr, ":%s %d %s :Conflines %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, nick, co, com);
|
||||
|
||||
sendto_one(cptr, ":%s %d %s :Classes %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, nick, cl, cl*sizeof(aClass));
|
||||
|
||||
sendto_one(cptr, ":%s %d %s :Channels %d(%d) Bans %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, nick, ch, chm, chb, chbm);
|
||||
sendto_one(cptr, ":%s %d %s :Channel membrs %d(%d) invite %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, nick, chu, chu*sizeof(Link),
|
||||
chi, chi*sizeof(Link));
|
||||
|
||||
totch = chm + chbm + chu*sizeof(Link) + chi*sizeof(Link);
|
||||
|
||||
sendto_one(cptr, ":%s %d %s :Whowas users %d(%d) away %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, nick, wwu, wwu*sizeof(anUser),
|
||||
wwa, wwam);
|
||||
sendto_one(cptr, ":%s %d %s :Whowas array %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, nick, NICKNAMEHISTORYLENGTH, wwm);
|
||||
|
||||
totww = wwu*sizeof(anUser) + wwam + wwm;
|
||||
|
||||
sendto_one(cptr, ":%s %d %s :Hash: client %d(%d) chan %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, nick, HASHSIZE,
|
||||
sizeof(aHashEntry) * HASHSIZE,
|
||||
CHANNELHASHSIZE, sizeof(aHashEntry) * CHANNELHASHSIZE);
|
||||
db = dbufblocks * sizeof(dbufbuf);
|
||||
sendto_one(cptr, ":%s %d %s :Dbuf blocks %d(%d)",
|
||||
me.name, RPL_STATSDEBUG, nick, dbufblocks, db);
|
||||
|
||||
rm = cres_mem(cptr);
|
||||
|
||||
tot = totww + totch + totcl + com + cl*sizeof(aClass) + db + rm;
|
||||
tot += sizeof(aHashEntry) * HASHSIZE;
|
||||
tot += sizeof(aHashEntry) * CHANNELHASHSIZE;
|
||||
|
||||
sendto_one(cptr, ":%s %d %s :Total: ww %d ch %d cl %d co %d db %d",
|
||||
me.name, RPL_STATSDEBUG, nick, totww, totch, totcl, com, db);
|
||||
sendto_one(cptr, ":%s %d %s :TOTAL: %d sbrk(0)-etext: %u",
|
||||
me.name, RPL_STATSDEBUG, nick, tot,
|
||||
(u_int)sbrk((size_t)0)-(u_int)sbrk0);
|
||||
return;
|
||||
}
|
||||
367
ircd/s_err.c
Normal file
367
ircd/s_err.c
Normal file
@@ -0,0 +1,367 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, ircd/s_err.c
|
||||
* Copyright (C) 1992 Darren Reed
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "struct.h"
|
||||
#include "numeric.h"
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)s_err.c 1.12 11/1/93 (C) 1992 Darren Reed";
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int num_val;
|
||||
char *num_form;
|
||||
} Numeric;
|
||||
|
||||
static char *prepbuf PROTO((char *, int, char *));
|
||||
static char numbuff[512];
|
||||
static char numbers[] = "0123456789";
|
||||
|
||||
static Numeric local_replies[] = {
|
||||
/* 000 */ 0, (char *)NULL,
|
||||
/* 001 */ RPL_WELCOME, ":Welcome to the Internet Relay Network %s",
|
||||
/* 002 */ RPL_YOURHOST, ":Your host is %s, running version %s",
|
||||
/* 003 */ RPL_CREATED, ":This server was created %s",
|
||||
/* 004 */ RPL_MYINFO, "%s %s dioswk biklmnopstv",
|
||||
/* 005 */ RPL_MAP, ":%s%s",
|
||||
/* 006 */ RPL_MAPMORE, ":%s%s --> *more*",
|
||||
/* 007 */ RPL_MAPEND, ":End of /MAP",
|
||||
0, (char *)NULL
|
||||
};
|
||||
|
||||
static Numeric numeric_errors[] = {
|
||||
/* 401 */ ERR_NOSUCHNICK, "%s :No such nick/channel",
|
||||
/* 402 */ ERR_NOSUCHSERVER, "%s :No such server",
|
||||
/* 402 */ ERR_NOSUCHCHANNEL, "%s :No such channel",
|
||||
/* 402 */ ERR_CANNOTSENDTOCHAN, "%s :Cannot send to channel",
|
||||
/* 402 */ ERR_TOOMANYCHANNELS, "%s :You have joined too many channels",
|
||||
/* 402 */ ERR_WASNOSUCHNICK, "%s :There was no such nickname",
|
||||
/* 402 */ ERR_TOOMANYTARGETS,
|
||||
"%s :Duplicate recipients. No message delivered",
|
||||
/* 402 */ ERR_NOSUCHSERVICE, (char *)NULL,
|
||||
/* 402 */ ERR_NOORIGIN, ":No origin specified",
|
||||
0, (char *)NULL,
|
||||
/* 411 */ ERR_NORECIPIENT, ":No recipient given (%s)",
|
||||
/* 411 */ ERR_NOTEXTTOSEND, ":No text to send",
|
||||
/* 411 */ ERR_NOTOPLEVEL, "%s :No toplevel domain specified",
|
||||
/* 411 */ ERR_WILDTOPLEVEL, "%s :Wildcard in toplevel Domain",
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
/* 421 */ ERR_UNKNOWNCOMMAND, "%s :Unknown command",
|
||||
/* 422 */ ERR_NOMOTD, ":MOTD File is missing",
|
||||
/* 422 */ ERR_NOADMININFO,
|
||||
"%s :No administrative info available",
|
||||
/* 422 */ ERR_FILEERROR, ":File error doing %s on %s",
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
/* 431 */ ERR_NONICKNAMEGIVEN, ":No nickname given",
|
||||
/* 432 */ ERR_ERRONEUSNICKNAME, "%s :Erroneus Nickname",
|
||||
/* 433 */ ERR_NICKNAMEINUSE, "%s :Nickname is already in use.",
|
||||
/* 434 */ ERR_SERVICENAMEINUSE, (char *)NULL,
|
||||
/* 435 */ ERR_SERVICECONFUSED, (char *)NULL,
|
||||
/* 436 */ ERR_NICKCOLLISION, "%s :Nickname collision KILL",
|
||||
/* 437 */ ERR_BANNICKCHANGE,
|
||||
"%s :Cannot change nickname while banned on channel",
|
||||
/* 438 */ ERR_NICKTOOFAST, "%s :Nick change too fast. Please wait %d seconds.",
|
||||
0, (char *)NULL, 0, (char *)NULL,
|
||||
/* 441 */ ERR_USERNOTINCHANNEL, "%s %s :They aren't on that channel",
|
||||
/* 442 */ ERR_NOTONCHANNEL, "%s :You're not on that channel",
|
||||
/* 443 */ ERR_USERONCHANNEL, "%s %s :is already on channel",
|
||||
/* 444 */ ERR_NOLOGIN, "%s :User not logged in",
|
||||
#ifndef ENABLE_SUMMON
|
||||
/* 445 */ ERR_SUMMONDISABLED, ":SUMMON has been disabled",
|
||||
#else
|
||||
0, (char *)NULL,
|
||||
#endif
|
||||
#ifndef ENABLE_USERS
|
||||
/* 446 */ ERR_USERSDISABLED, ":USERS has been disabled",
|
||||
#else
|
||||
0, (char *)NULL,
|
||||
#endif
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL,
|
||||
/* 451 */ ERR_NOTREGISTERED, ":You have not registered",
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
/* 461 */ ERR_NEEDMOREPARAMS, "%s :Not enough parameters",
|
||||
/* 462 */ ERR_ALREADYREGISTRED, ":You may not reregister",
|
||||
/* 463 */ ERR_NOPERMFORHOST, ":Your host isn't among the privileged",
|
||||
/* 464 */ ERR_PASSWDMISMATCH, ":Password Incorrect",
|
||||
/* 465 */ ERR_YOUREBANNEDCREEP, ":You are banned from this server",
|
||||
/* 466 */ ERR_YOUWILLBEBANNED, (char *)NULL,
|
||||
/* 467 */ ERR_KEYSET, "%s :Channel key already set",
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
/* 471 */ ERR_CHANNELISFULL, "%s :Cannot join channel (+l)",
|
||||
/* 472 */ ERR_UNKNOWNMODE , "%c :is unknown mode char to me",
|
||||
/* 473 */ ERR_INVITEONLYCHAN, "%s :Cannot join channel (+i)",
|
||||
/* 474 */ ERR_BANNEDFROMCHAN, "%s :Cannot join channel (+b)",
|
||||
/* 475 */ ERR_BADCHANNELKEY, "%s :Cannot join channel (+k)",
|
||||
/* 476 */ ERR_BADCHANMASK, "%s :Bad Channel Mask",
|
||||
0, (char *)NULL,
|
||||
/* 478 */ ERR_BANLISTFULL, "%s %s :Channel ban/ignore list is full",
|
||||
0, (char *)NULL, 0, (char *)NULL,
|
||||
/* 481 */ ERR_NOPRIVILEGES,
|
||||
":Permission Denied- You're not an IRC operator",
|
||||
/* 482 */ ERR_CHANOPRIVSNEEDED, "%s :You're not channel operator",
|
||||
/* 483 */ ERR_CANTKILLSERVER, ":You cant kill a server!",
|
||||
/* 484 */ ERR_ISCHANSERVICE, "%s %s :Cannot kick or deop channel service",
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
/* 491 */ ERR_NOOPERHOST, ":No O-lines for your host",
|
||||
/* 492 */ ERR_NOSERVICEHOST, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL,
|
||||
/* 501 */ ERR_UMODEUNKNOWNFLAG, ":Unknown MODE flag",
|
||||
/* 502 */ ERR_USERSDONTMATCH, ":Cant change mode for other users",
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL,
|
||||
/* 511 */ ERR_SILELISTFULL, "%s :Your silence list is full",
|
||||
/* 512 */ ERR_NOSUCHGLINE, "%s@%s :No such gline",
|
||||
/* 513 */ ERR_BADPING, (char*)NULL
|
||||
};
|
||||
|
||||
static Numeric numeric_replies[] = {
|
||||
/* 300 */ RPL_NONE, (char *)NULL,
|
||||
/* 301 */ RPL_AWAY, "%s :%s",
|
||||
/* 302 */ RPL_USERHOST, ":",
|
||||
/* 303 */ RPL_ISON, ":",
|
||||
/* 304 */ RPL_TEXT, (char *)NULL,
|
||||
/* 305 */ RPL_UNAWAY, ":You are no longer marked as being away",
|
||||
/* 306 */ RPL_NOWAWAY, ":You have been marked as being away",
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL,
|
||||
/* 311 */ RPL_WHOISUSER, "%s %s %s * :%s",
|
||||
/* 312 */ RPL_WHOISSERVER, "%s %s :%s",
|
||||
/* 313 */ RPL_WHOISOPERATOR, "%s :is an IRC Operator",
|
||||
/* 314 */ RPL_WHOWASUSER, "%s %s %s * :%s",
|
||||
/* 315 */ RPL_ENDOFWHO, "%s :End of /WHO list.",
|
||||
/* 316 */ RPL_WHOISCHANOP, (char *)NULL,
|
||||
/* 317 */ RPL_WHOISIDLE, "%s %ld %ld :seconds idle, signon time",
|
||||
/* 318 */ RPL_ENDOFWHOIS, "%s :End of /WHOIS list.",
|
||||
/* 319 */ RPL_WHOISCHANNELS, "%s :%s",
|
||||
0, (char *)NULL,
|
||||
/* 321 */ RPL_LISTSTART, "Channel :Users Name",
|
||||
/* 322 */ RPL_LIST, "%s %d :%s",
|
||||
/* 323 */ RPL_LISTEND, ":End of /LIST",
|
||||
/* 324 */ RPL_CHANNELMODEIS, "%s %s %s",
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL,
|
||||
/* 329 */ RPL_CREATIONTIME, "%s %lu",
|
||||
0, (char *)NULL,
|
||||
/* 331 */ RPL_NOTOPIC, "%s :No topic is set.",
|
||||
/* 332 */ RPL_TOPIC, "%s :%s",
|
||||
/* 333 */ RPL_TOPICWHOTIME, "%s %s %lu",
|
||||
/* 334 */ RPL_LISTUSAGE, ":%s",
|
||||
0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL,
|
||||
/* 341 */ RPL_INVITING, "%s %s",
|
||||
/* 342 */ RPL_SUMMONING, "%s :User summoned to irc",
|
||||
0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
/* 351 */ RPL_VERSION, "%s.%s %s :%s",
|
||||
/* 352 */ RPL_WHOREPLY, "%s %s %s %s %s %s :%d %s",
|
||||
/* 353 */ RPL_NAMREPLY, "%s",
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL,
|
||||
/* 361 */ RPL_KILLDONE, (char *)NULL,
|
||||
/* 362 */ RPL_CLOSING, "%s :Closed. Status = %d",
|
||||
/* 363 */ RPL_CLOSEEND, "%d: Connections Closed",
|
||||
/* 364 */ RPL_LINKS, "%s %s :%d P%u %s",
|
||||
/* 365 */ RPL_ENDOFLINKS, "%s :End of /LINKS list.",
|
||||
/* 366 */ RPL_ENDOFNAMES, "%s :End of /NAMES list.",
|
||||
/* 367 */ RPL_BANLIST, "%s %s %s %lu",
|
||||
/* 368 */ RPL_ENDOFBANLIST, "%s :End of Channel Ban List",
|
||||
/* 369 */ RPL_ENDOFWHOWAS, "%s :End of WHOWAS",
|
||||
0, (char *)NULL,
|
||||
/* 371 */ RPL_INFO, ":%s",
|
||||
/* 372 */ RPL_MOTD, ":- %s",
|
||||
/* 373 */ RPL_INFOSTART, ":Server INFO",
|
||||
/* 374 */ RPL_ENDOFINFO, ":End of /INFO list.",
|
||||
/* 375 */ RPL_MOTDSTART, ":- %s Message of the Day - ",
|
||||
/* 376 */ RPL_ENDOFMOTD, ":End of /MOTD command.",
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL,
|
||||
/* 381 */ RPL_YOUREOPER, ":You are now an IRC Operator",
|
||||
/* 382 */ RPL_REHASHING, "%s :Rehashing",
|
||||
/* 383 */ RPL_YOURESERVICE, (char *)NULL,
|
||||
/* 384 */ RPL_MYPORTIS, "%d :Port to local server is\r\n",
|
||||
/* 385 */ RPL_NOTOPERANYMORE, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL,
|
||||
/* 391 */ RPL_TIME, "%s %lu %ld :%s",
|
||||
#ifdef ENABLE_USERS
|
||||
/* 392 */ RPL_USERSSTART, ":UserID Terminal Host",
|
||||
/* 393 */ RPL_USERS, ":%-8s %-9s %-8s",
|
||||
/* 394 */ RPL_ENDOFUSERS, ":End of Users",
|
||||
/* 395 */ RPL_NOUSERS, ":Nobody logged in.",
|
||||
#else
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL,
|
||||
#endif
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL,
|
||||
/* 200 */ RPL_TRACELINK, "Link %s%s %s %s",
|
||||
/* 201 */ RPL_TRACECONNECTING, "Try. %d %s",
|
||||
/* 202 */ RPL_TRACEHANDSHAKE, "H.S. %d %s",
|
||||
/* 203 */ RPL_TRACEUNKNOWN, "???? %d %s",
|
||||
/* 204 */ RPL_TRACEOPERATOR, "Oper %d %s %ld",
|
||||
/* 205 */ RPL_TRACEUSER, "User %d %s %ld",
|
||||
/* 206 */ RPL_TRACESERVER, "Serv %d %dS %dC %s %s!%s@%s %ld",
|
||||
/* 207 */ RPL_TRACESERVICE, "Service %d %s",
|
||||
/* 208 */ RPL_TRACENEWTYPE, "<newtype> 0 %s",
|
||||
/* 209 */ RPL_TRACECLASS, "Class %d %d",
|
||||
0, (char *)NULL,
|
||||
/* 211 */ RPL_STATSLINKINFO, (char *)NULL,
|
||||
/* 212 */ RPL_STATSCOMMANDS, "%s %u %u",
|
||||
/* 213 */ RPL_STATSCLINE, "%c %s * %s %d %d",
|
||||
/* 214 */ RPL_STATSNLINE, "%c %s * %s %d %d",
|
||||
/* 215 */ RPL_STATSILINE, "%c %s * %s %d %d",
|
||||
/* 216 */ RPL_STATSKLINE, "%c %s %s %s %d %d",
|
||||
/* 217 */ RPL_STATSQLINE, "%c %s * %s %d %d",
|
||||
/* 218 */ RPL_STATSYLINE, "%c %d %d %d %d %ld",
|
||||
/* 219 */ RPL_ENDOFSTATS, "%c :End of /STATS report",
|
||||
0, (char *)NULL,
|
||||
/* 221 */ RPL_UMODEIS, "%s",
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
/* 231 */ RPL_SERVICEINFO, (char *)NULL,
|
||||
/* 232 */ RPL_ENDOFSERVICES, (char *)NULL,
|
||||
/* 233 */ RPL_SERVICE, (char *)NULL,
|
||||
/* 234 */ RPL_SERVLIST, (char *)NULL,
|
||||
/* 235 */ RPL_SERVLISTEND, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL,
|
||||
/* 241 */ RPL_STATSLLINE, "%c %s * %s %d %d",
|
||||
/* 242 */ RPL_STATSUPTIME, ":Server Up %d days, %d:%02d:%02d",
|
||||
/* 243 */ RPL_STATSOLINE, "%c %s * %s %d %d",
|
||||
/* 244 */ RPL_STATSHLINE, "%c %s * %s %d %d",
|
||||
/* 245 */ RPL_STATSSLINE, "%c %s * %s %d %d",
|
||||
/* 246 */ RPL_STATSTLINE, "%c %s %s",
|
||||
/* 247 */ RPL_STATSGLINE, "%c %s@%s %lu :%s",
|
||||
/* 248 */ RPL_STATSULINE, "%c %s * %s %d %d",
|
||||
0, (char *)NULL,
|
||||
/* 250 */ RPL_STATSCONN,
|
||||
":Highest connection count: %d (%d clients)",
|
||||
/* 251 */ RPL_LUSERCLIENT,
|
||||
":There are %d users and %d invisible on %d servers",
|
||||
/* 252 */ RPL_LUSEROP, "%d :operator(s) online",
|
||||
/* 253 */ RPL_LUSERUNKNOWN, "%d :unknown connection(s)",
|
||||
/* 254 */ RPL_LUSERCHANNELS, "%d :channels formed",
|
||||
/* 255 */ RPL_LUSERME, ":I have %d clients and %d servers",
|
||||
/* 256 */ RPL_ADMINME, ":Administrative info about %s",
|
||||
/* 257 */ RPL_ADMINLOC1, ":%s",
|
||||
/* 258 */ RPL_ADMINLOC2, ":%s",
|
||||
/* 259 */ RPL_ADMINEMAIL, ":%s",
|
||||
0, (char *)NULL,
|
||||
/* 261 */ RPL_TRACELOG, "File %s %d",
|
||||
/* 262 */ RPL_TRACEPING, "Ping %s %s",
|
||||
0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
/* 271 */ RPL_SILELIST, "%s %s",
|
||||
/* 272 */ RPL_ENDOFSILELIST, ":End of Silence List",
|
||||
0, (char *)NULL, 0, (char *)NULL,
|
||||
/* 275 */ RPL_STATSDLINE, "%c %s %s",
|
||||
0, (char *)NULL, 0, (char *)NULL, 0, (char *)NULL,
|
||||
0, (char *)NULL,
|
||||
/* 280 */ RPL_GLIST, "%s@%s %lu %s%s",
|
||||
/* 281 */ RPL_ENDOFGLIST, ":End of G-line List"
|
||||
};
|
||||
|
||||
char *err_str(numeric)
|
||||
int numeric;
|
||||
{
|
||||
Reg1 Numeric *nptr;
|
||||
Reg2 int num = numeric;
|
||||
|
||||
num -= numeric_errors[0].num_val;
|
||||
if (num < 0 || num > ERR_USERSDONTMATCH)
|
||||
(void)sprintf(numbuff,
|
||||
":%%s %d %%s :INTERNAL ERROR: BAD NUMERIC! %d",
|
||||
numeric, num);
|
||||
else
|
||||
{
|
||||
nptr = &numeric_errors[num];
|
||||
if (!nptr->num_form || !nptr->num_val)
|
||||
(void)sprintf(numbuff,
|
||||
":%%s %d %%s :NO ERROR FOR NUMERIC ERROR %d",
|
||||
numeric, num);
|
||||
else
|
||||
(void)prepbuf(numbuff, nptr->num_val, nptr->num_form);
|
||||
}
|
||||
return numbuff;
|
||||
}
|
||||
|
||||
|
||||
char *rpl_str(numeric)
|
||||
int numeric;
|
||||
{
|
||||
Reg1 Numeric *nptr;
|
||||
Reg2 int num = numeric;
|
||||
|
||||
if (num > 7)
|
||||
num -= (num > 300) ? 300 : 100;
|
||||
|
||||
if (num < 0 || num > 200)
|
||||
(void)sprintf(numbuff,
|
||||
":%%s %d %%s :INTERNAL REPLY ERROR: BAD NUMERIC! %d",
|
||||
numeric, num);
|
||||
else
|
||||
{
|
||||
if (numeric > 99)
|
||||
nptr = &numeric_replies[num];
|
||||
else
|
||||
nptr = &local_replies[num];
|
||||
Debug((DEBUG_NUM, "rpl_str: numeric %d num %d nptr %x %d %x",
|
||||
numeric, num, nptr, nptr->num_val, nptr->num_form));
|
||||
if (!nptr->num_form || !nptr->num_val)
|
||||
(void)sprintf(numbuff,
|
||||
":%%s %d %%s :NO REPLY FOR NUMERIC ERROR %d",
|
||||
numeric, num);
|
||||
else
|
||||
(void)prepbuf(numbuff, nptr->num_val, nptr->num_form);
|
||||
}
|
||||
return numbuff;
|
||||
}
|
||||
|
||||
static char *prepbuf(buffer, num, tail)
|
||||
char *buffer;
|
||||
Reg1 int num;
|
||||
char *tail;
|
||||
{
|
||||
Reg1 char *s;
|
||||
|
||||
(void)strcpy(buffer, ":%s ");
|
||||
s = buffer + 4;
|
||||
|
||||
*s++ = numbers[num/100];
|
||||
num %= 100;
|
||||
*s++ = numbers[num/10];
|
||||
*s++ = numbers[num%10];
|
||||
(void)strcpy(s, " %s ");
|
||||
(void)strcpy(s+4, tail);
|
||||
return buffer;
|
||||
}
|
||||
777
ircd/s_misc.c
Normal file
777
ircd/s_misc.c
Normal file
@@ -0,0 +1,777 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, ircd/s_misc.c (formerly ircd/date.c)
|
||||
* Copyright (C) 1990 Jarkko Oikarinen and
|
||||
* University of Oulu, Computing Center
|
||||
*
|
||||
* See file AUTHORS in IRC package for additional names of
|
||||
* the programmers.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)s_misc.c 2.42 3/1/94 (C) 1988 University of Oulu, \
|
||||
Computing Center and Jarkko Oikarinen";
|
||||
#endif
|
||||
|
||||
#include <sys/time.h>
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "numeric.h"
|
||||
#include "userload.h"
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#if !defined(ULTRIX) && !defined(SGI) && !defined(sequent) && \
|
||||
!defined(__convex__)
|
||||
# include <sys/param.h>
|
||||
#endif
|
||||
#if defined(PCS) || defined(AIX) || defined(SVR3)
|
||||
# include <time.h>
|
||||
#endif
|
||||
#ifdef HPUX
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#ifdef DYNIXPTX
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#endif
|
||||
#include "h.h"
|
||||
|
||||
static void exit_one_client PROTO((aClient *,aClient *,char *,int));
|
||||
|
||||
static char *months[] = {
|
||||
"January", "February", "March", "April",
|
||||
"May", "June", "July", "August",
|
||||
"September", "October", "November", "December"
|
||||
};
|
||||
|
||||
static char *weekdays[] = {
|
||||
"Sunday", "Monday", "Tuesday", "Wednesday",
|
||||
"Thursday", "Friday", "Saturday"
|
||||
};
|
||||
|
||||
/*
|
||||
* stats stuff
|
||||
*/
|
||||
struct stats ircst, *ircstp = &ircst;
|
||||
|
||||
char *date(clock)
|
||||
time_t clock;
|
||||
{
|
||||
static char buf[80], plus;
|
||||
Reg1 struct tm *lt, *gm;
|
||||
struct tm gmbuf;
|
||||
int minswest;
|
||||
|
||||
if (!clock)
|
||||
clock = now;
|
||||
gm = gmtime(&clock);
|
||||
bcopy((char *)gm, (char *)&gmbuf, sizeof(gmbuf));
|
||||
gm = &gmbuf;
|
||||
lt = localtime(&clock);
|
||||
|
||||
if (lt->tm_yday == gm->tm_yday)
|
||||
minswest = (gm->tm_hour - lt->tm_hour) * 60 +
|
||||
(gm->tm_min - lt->tm_min);
|
||||
else if (lt->tm_yday > gm->tm_yday)
|
||||
minswest = (gm->tm_hour - (lt->tm_hour + 24)) * 60;
|
||||
else
|
||||
minswest = ((gm->tm_hour + 24) - lt->tm_hour) * 60;
|
||||
|
||||
plus = (minswest > 0) ? '-' : '+';
|
||||
if (minswest < 0)
|
||||
minswest = -minswest;
|
||||
|
||||
(void)sprintf(buf, "%s %s %d 19%02d -- %02d:%02d %c%02d:%02d",
|
||||
weekdays[lt->tm_wday], months[lt->tm_mon],lt->tm_mday,
|
||||
lt->tm_year, lt->tm_hour, lt->tm_min,
|
||||
plus, minswest/60, minswest%60);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
** myctime()
|
||||
** This is like standard ctime()-function, but it zaps away
|
||||
** the newline from the end of that string. Also, it takes
|
||||
** the time value as parameter, instead of pointer to it.
|
||||
** Note that it is necessary to copy the string to alternate
|
||||
** buffer (who knows how ctime() implements it, maybe it statically
|
||||
** has newline there and never 'refreshes' it -- zapping that
|
||||
** might break things in other places...)
|
||||
**
|
||||
**/
|
||||
|
||||
char *myctime(value)
|
||||
time_t value;
|
||||
{
|
||||
static char buf[28];
|
||||
Reg1 char *p;
|
||||
|
||||
(void)strcpy(buf, ctime(&value));
|
||||
if ((p = (char *)index(buf, '\n')) != NULL)
|
||||
*p = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
/*
|
||||
** check_registered_user is used to cancel message, if the
|
||||
** originator is a server or not registered yet. In other
|
||||
** words, passing this test, *MUST* guarantee that the
|
||||
** sptr->user exists (not checked after this--let there
|
||||
** be coredumps to catch bugs... this is intentional --msa ;)
|
||||
**
|
||||
** There is this nagging feeling... should this NOT_REGISTERED
|
||||
** error really be sent to remote users? This happening means
|
||||
** that remote servers have this user registered, althout this
|
||||
** one has it not... Not really users fault... Perhaps this
|
||||
** error message should be restricted to local clients and some
|
||||
** other thing generated for remotes...
|
||||
*/
|
||||
int check_registered_user(sptr)
|
||||
aClient *sptr;
|
||||
{
|
||||
if (!IsRegisteredUser(sptr))
|
||||
{
|
||||
sendto_one(sptr, err_str(ERR_NOTREGISTERED), me.name, "*");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** check_registered user cancels message, if 'x' is not
|
||||
** registered (e.g. we don't know yet whether a server
|
||||
** or user)
|
||||
*/
|
||||
int check_registered(sptr)
|
||||
aClient *sptr;
|
||||
{
|
||||
if (!IsRegistered(sptr))
|
||||
{
|
||||
sendto_one(sptr, err_str(ERR_NOTREGISTERED), me.name, "*");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** get_client_name
|
||||
** Return the name of the client for various tracking and
|
||||
** admin purposes. The main purpose of this function is to
|
||||
** return the "socket host" name of the client, if that
|
||||
** differs from the advertised name (other than case).
|
||||
** But, this can be used to any client structure.
|
||||
**
|
||||
** Returns:
|
||||
** "name[user@ip#.port]" if 'showip' is true;
|
||||
** "name[sockethost]", if name and sockhost are different and
|
||||
** showip is false; else
|
||||
** "name".
|
||||
**
|
||||
** NOTE 1:
|
||||
** Watch out the allocation of "nbuf", if either sptr->name
|
||||
** or sptr->sockhost gets changed into pointers instead of
|
||||
** directly allocated within the structure...
|
||||
**
|
||||
** NOTE 2:
|
||||
** Function return either a pointer to the structure (sptr) or
|
||||
** to internal buffer (nbuf). *NEVER* use the returned pointer
|
||||
** to modify what it points!!!
|
||||
*/
|
||||
char *get_client_name(sptr, showip)
|
||||
aClient *sptr;
|
||||
int showip;
|
||||
{
|
||||
static char nbuf[HOSTLEN * 2 + USERLEN + 5];
|
||||
|
||||
if (MyConnect(sptr))
|
||||
{
|
||||
if (IsUnixSocket(sptr))
|
||||
{
|
||||
if (showip)
|
||||
(void) sprintf(nbuf, "%s[%s]",
|
||||
sptr->name, sptr->sockhost);
|
||||
else
|
||||
(void) sprintf(nbuf, "%s[%s]",
|
||||
sptr->name, me.sockhost);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (showip)
|
||||
(void)sprintf(nbuf, "%s[%s@%s]",
|
||||
sptr->name,
|
||||
(!(sptr->flags & FLAGS_GOTID)) ? "" :
|
||||
sptr->username,
|
||||
inetntoa((char *)&sptr->ip));
|
||||
else
|
||||
{
|
||||
if (mycmp(sptr->name, sptr->sockhost))
|
||||
(void)sprintf(nbuf, "%s[%s]",
|
||||
sptr->name, sptr->sockhost);
|
||||
else
|
||||
return sptr->name;
|
||||
}
|
||||
}
|
||||
return nbuf;
|
||||
}
|
||||
return sptr->name;
|
||||
}
|
||||
|
||||
char *get_client_host(cptr)
|
||||
aClient *cptr;
|
||||
{
|
||||
static char nbuf[HOSTLEN * 2 + USERLEN + 5];
|
||||
|
||||
if (!MyConnect(cptr))
|
||||
return cptr->name;
|
||||
if (!cptr->hostp)
|
||||
return get_client_name(cptr, FALSE);
|
||||
if (IsUnixSocket(cptr))
|
||||
(void) sprintf(nbuf, "%s[%s]", cptr->name, me.name);
|
||||
else
|
||||
(void)sprintf(nbuf, "%s[%-.*s@%-.*s]",
|
||||
cptr->name, USERLEN,
|
||||
(!(cptr->flags & FLAGS_GOTID)) ? "" : cptr->username,
|
||||
HOSTLEN, cptr->hostp->h_name);
|
||||
return nbuf;
|
||||
}
|
||||
|
||||
/*
|
||||
* Form sockhost such that if the host is of form user@host, only the host
|
||||
* portion is copied.
|
||||
*/
|
||||
void get_sockhost(cptr, host)
|
||||
Reg1 aClient *cptr;
|
||||
Reg2 char *host;
|
||||
{
|
||||
Reg3 char *s;
|
||||
if ((s = (char *)index(host, '@')))
|
||||
s++;
|
||||
else
|
||||
s = host;
|
||||
strncpyzt(cptr->sockhost, s, sizeof(cptr->sockhost));
|
||||
}
|
||||
|
||||
/*
|
||||
* Return wildcard name of my server name according to given config entry
|
||||
* --Jto
|
||||
*/
|
||||
char *my_name_for_link(name, aconf)
|
||||
char *name;
|
||||
aConfItem *aconf;
|
||||
{
|
||||
static char namebuf[HOSTLEN];
|
||||
register int count = aconf->port;
|
||||
register char *start = name;
|
||||
|
||||
if (count <= 0 || count > 5)
|
||||
return start;
|
||||
|
||||
while (count-- && name)
|
||||
{
|
||||
name++;
|
||||
name = (char *)index(name, '.');
|
||||
}
|
||||
if (!name)
|
||||
return start;
|
||||
|
||||
namebuf[0] = '*';
|
||||
(void)strncpy(&namebuf[1], name, HOSTLEN - 1);
|
||||
namebuf[HOSTLEN - 1] = '\0';
|
||||
|
||||
return namebuf;
|
||||
}
|
||||
|
||||
/*
|
||||
** exit_downlinks - added by Run 25-9-94
|
||||
**
|
||||
** Removes all clients and downlinks (+clients) of any server
|
||||
** QUITs are generated and sent to local users.
|
||||
**
|
||||
** cptr : server that must have all dependents removed
|
||||
** sptr : source who thought that this was a good idea
|
||||
** comment : comment sent as sign off message to local clients
|
||||
*/
|
||||
void exit_downlinks(cptr, sptr, comment)
|
||||
aClient *cptr, *sptr;
|
||||
char *comment;
|
||||
{
|
||||
Reg1 aClient *acptr;
|
||||
Reg2 Dlink *next;
|
||||
Reg3 Dlink *lp;
|
||||
|
||||
/* Run over all its downlinks */
|
||||
for (lp=cptr->serv->down; lp; lp=next)
|
||||
{
|
||||
next=lp->next;
|
||||
acptr=lp->value.cptr;
|
||||
/* Remove the downlinks and client of the downlink */
|
||||
exit_downlinks(acptr, sptr, comment);
|
||||
/* Remove the downlink itself */
|
||||
exit_one_client(acptr, sptr, me.name, 1);
|
||||
}
|
||||
/* Remove all clients of this server */
|
||||
for (lp=cptr->serv->client; lp; lp=next)
|
||||
{
|
||||
next=lp->next;
|
||||
exit_one_client(lp->value.cptr, sptr, comment, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** exit_client, rewritten 25-9-94 by Run
|
||||
**
|
||||
** This function exits a client of *any* type (user, server, etc)
|
||||
** from this server. Also, this generates all necessary prototol
|
||||
** messages that this exit may cause.
|
||||
**
|
||||
** This function implicitly exits all other clients depending on
|
||||
** this connection.
|
||||
**
|
||||
** For convenience, this function returns a suitable value for
|
||||
** m_funtion return value:
|
||||
**
|
||||
** CPTR_KILLED if (cptr == bcptr)
|
||||
** 0 if (cptr != bcptr)
|
||||
**
|
||||
** This function can be called in two ways:
|
||||
** 1) From before or in parse(), exitting the 'cptr', in which case it was
|
||||
** invoked as exit_client(cptr, cptr, &me,...), causing it to always
|
||||
** return CPTR_KILLED.
|
||||
** 2) Via parse from a m_function call, in which case it was invoked as
|
||||
** exit_client(cptr, acptr, sptr, ...). Here 'sptr' is known; the client
|
||||
** that generated the message in a way that we can assume he already
|
||||
** did remove acptr from memory himself (or in other cases we don't mind
|
||||
** because he will be delinked.) Or invoked as:
|
||||
** exit_client(cptr, acptr/sptr, &me, ...) when WE decide this one should
|
||||
** be removed.
|
||||
** In general: No generated SQUIT or QUIT should be sent to source link
|
||||
** sptr->from. And CPTR_KILLED should be returned if cptr got removed (too).
|
||||
**
|
||||
** --Run
|
||||
*/
|
||||
int exit_client(cptr, bcptr, sptr, comment)
|
||||
aClient *cptr; /* Connection being handled by read_message right now */
|
||||
aClient *bcptr; /* Client being killed */
|
||||
aClient *sptr; /* The client that made the decision to remove this
|
||||
one, never NULL */
|
||||
char *comment; /* Reason for the exit */
|
||||
{
|
||||
Reg1 aClient *acptr;
|
||||
Reg2 aClient *next;
|
||||
Reg3 Dlink *dlp;
|
||||
#ifdef FNAME_USERLOG
|
||||
time_t on_for;
|
||||
#endif
|
||||
char comment1[HOSTLEN + HOSTLEN + 2];
|
||||
|
||||
if (MyConnect(bcptr))
|
||||
{
|
||||
bcptr->flags |= FLAGS_CLOSING;
|
||||
current_load_data.conn_count--;
|
||||
if (IsPerson(bcptr))
|
||||
{
|
||||
char mydom_mask[HOSTLEN + 1];
|
||||
mydom_mask[0] = '*';
|
||||
sendto_realops ("Client exiting: %s (%s@%s) [%s]",
|
||||
bcptr->name, bcptr->user->username, bcptr->user->host, comment);
|
||||
strncpy(&mydom_mask[1], DOMAINNAME, HOSTLEN - 1);
|
||||
current_load_data.client_count--;
|
||||
if (matches(mydom_mask, bcptr->sockhost) == 0)
|
||||
current_load_data.local_count--;
|
||||
}
|
||||
update_load();
|
||||
#ifdef FNAME_USERLOG
|
||||
on_for = now - bcptr->firsttime;
|
||||
# if defined(USE_SYSLOG) && defined(SYSLOG_USERS)
|
||||
if (IsPerson(bcptr))
|
||||
syslog(LOG_NOTICE, "%s (%3d:%02d:%02d): %s@%s (%s)\n",
|
||||
myctime(bcptr->firsttime), on_for / 3600, (on_for % 3600)/60,
|
||||
on_for % 60, bcptr->user->username, bcptr->sockhost, bcptr->name);
|
||||
# else
|
||||
{
|
||||
char linebuf[160];
|
||||
int logfile;
|
||||
|
||||
/*
|
||||
* This conditional makes the logfile active only after
|
||||
* it's been created - thus logging can be turned off by
|
||||
* removing the file.
|
||||
*
|
||||
* stop NFS hangs...most systems should be able to open a
|
||||
* file in 3 seconds. -avalon (curtesy of wumpus)
|
||||
*/
|
||||
(void)alarm(3);
|
||||
if (IsPerson(bcptr) &&
|
||||
(logfile = open(FNAME_USERLOG, O_WRONLY|O_APPEND)) != -1)
|
||||
{
|
||||
(void)alarm(0);
|
||||
(void)sprintf(linebuf,
|
||||
"%s (%3d:%02d:%02d): %s@%s [%s]\n",
|
||||
myctime(bcptr->firsttime),
|
||||
on_for / 3600, (on_for % 3600)/60,
|
||||
on_for % 60,
|
||||
bcptr->user->username, bcptr->user->host,
|
||||
bcptr->username);
|
||||
(void)alarm(3);
|
||||
(void)write(logfile, linebuf, strlen(linebuf));
|
||||
(void)alarm(0);
|
||||
(void)close(logfile);
|
||||
}
|
||||
(void)alarm(0);
|
||||
/* Modification by stealth@caen.engin.umich.edu */
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
if (bcptr != sptr->from && bcptr->status >= STAT_MASTER)
|
||||
/* the source knows already --Run */
|
||||
{
|
||||
if (IsServer(bcptr) || IsHandshake(bcptr))
|
||||
{
|
||||
if (IsServer(bcptr) && Protocol(bcptr->from)<9)
|
||||
sendto_one(bcptr, ":%s SQUIT %s :%s", sptr->name,
|
||||
me.name, comment);
|
||||
else /* If we are handshaking, use the newest protocol :/ */
|
||||
sendto_one(bcptr, ":%s SQUIT %s 0 :%s", sptr->name,
|
||||
me.name, comment);
|
||||
}
|
||||
else if (!IsConnecting(bcptr))
|
||||
sendto_one(bcptr, "ERROR :Closing Link: %s by %s (%s)",
|
||||
get_client_name(bcptr,FALSE), sptr->name, comment);
|
||||
if ((IsServer(bcptr) || IsHandshake(bcptr) || IsConnecting(bcptr)) &&
|
||||
(sptr == &me || (IsServer(sptr) &&
|
||||
(strncmp(comment, "Leaf-only link", 14) ||
|
||||
strncmp(comment, "Non-Hub link", 12)))))
|
||||
{
|
||||
if (bcptr->serv->user && (acptr=find_client(bcptr->serv->by, NULL)) &&
|
||||
acptr->user == bcptr->serv->user)
|
||||
sendto_one(acptr,
|
||||
":%s NOTICE %s :Link with %s cancelled: %s",
|
||||
me.name, acptr->name, bcptr->name, comment);
|
||||
else
|
||||
acptr = NULL;
|
||||
if (sptr == &me)
|
||||
sendto_lops_butone(acptr, "Link with %s cancelled: %s",
|
||||
bcptr->name, comment);
|
||||
}
|
||||
}
|
||||
/*
|
||||
** Close the Client connection first.
|
||||
*/
|
||||
close_connection(bcptr);
|
||||
}
|
||||
|
||||
if (IsServer(bcptr))
|
||||
{
|
||||
(void)strcpy(comment1, bcptr->serv->up->name);
|
||||
(void)strcat(comment1," ");
|
||||
(void)strcat(comment1, bcptr->name);
|
||||
if (!IsServer(sptr) || Protocol(sptr)>4)
|
||||
{
|
||||
if (IsPerson(sptr))
|
||||
sendto_lops_butone(sptr, "%s SQUIT by %s [%s]:",
|
||||
(sptr->user->server == bcptr ||
|
||||
sptr->user->server == bcptr->serv->up) ? "Local" : "Remote",
|
||||
get_client_name(sptr,TRUE), sptr->user->server->name);
|
||||
else if (sptr != &me && bcptr->serv->up != sptr)
|
||||
sendto_ops("Received SQUIT %s from %s :", bcptr->name,
|
||||
IsServer(sptr) ? sptr->name : get_client_name(sptr,TRUE));
|
||||
sendto_ops("Net break: %s (%s)", comment1, comment);
|
||||
}
|
||||
exit_downlinks(bcptr, sptr, comment1);
|
||||
}
|
||||
|
||||
/*
|
||||
** Now generate the needed protocol for the other server links
|
||||
** except the source: USE_SERVICES not supported
|
||||
*/
|
||||
for (dlp = me.serv->down; dlp; dlp = dlp->next)
|
||||
if (dlp->value.cptr != sptr->from &&
|
||||
dlp->value.cptr != bcptr)
|
||||
{
|
||||
if (IsServer(bcptr))
|
||||
sendto_one(dlp->value.cptr, ":%s SQUIT %s %lu :%s",
|
||||
sptr->name, bcptr->name, bcptr->serv->timestamp, comment);
|
||||
else if (IsClient(bcptr) && (bcptr->flags & FLAGS_KILLED) == 0)
|
||||
sendto_one(dlp->value.cptr, ":%s QUIT :%s", bcptr->name, comment);
|
||||
}
|
||||
|
||||
exit_one_client(bcptr, sptr, comment, 0);
|
||||
|
||||
/*
|
||||
** cptr can only have been killed if it was cptr itself that got killed here,
|
||||
** because cptr can never have been a dependant of bcptr --Run
|
||||
*/
|
||||
return (cptr == bcptr) ? CPTR_KILLED : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** Exit client with formatted message, added 25-9-94 by Run
|
||||
*/
|
||||
#ifndef USE_VARARGS
|
||||
/*VARARGS*/
|
||||
int exit_client_msg(cptr, bcptr, sptr, pattern, p1, p2, p3, p4, p5, p6)
|
||||
aClient *cptr, *bcptr, *sptr;
|
||||
char *pattern, *p1, *p2, *p3, *p4, *p5, *p6;
|
||||
{
|
||||
#else
|
||||
int exit_client_msg(cptr, bcptr, sptr, pattern, va_alist)
|
||||
aClient *cptr, *bcptr, *sptr;
|
||||
char *pattern;
|
||||
va_dcl
|
||||
{
|
||||
va_list vl;
|
||||
#endif
|
||||
char msgbuf[1024];
|
||||
|
||||
#ifdef USE_VARARGS
|
||||
va_start(vl);
|
||||
(void)vsprintf(msgbuf, pattern, vl);
|
||||
va_end(vl);
|
||||
#else
|
||||
(void)sprintf(msgbuf, pattern, p1, p2, p3, p4, p5, p6);
|
||||
#endif
|
||||
return exit_client(cptr, bcptr, sptr, msgbuf);
|
||||
}
|
||||
|
||||
/*
|
||||
** Exit one client, local or remote. Assuming for local client that
|
||||
** all dependants already have been removed, and socket is closed.
|
||||
**
|
||||
** Rewritten by Run - 24 sept 94
|
||||
**
|
||||
** bcptr : client being (s)quitted
|
||||
** sptr : The source (prefix) of the QUIT or SQUIT
|
||||
**
|
||||
** --Run
|
||||
*/
|
||||
static void exit_one_client(bcptr, sptr, comment, OldProtocolFlag)
|
||||
aClient *bcptr, *sptr;
|
||||
char *comment;
|
||||
int OldProtocolFlag;
|
||||
{
|
||||
Reg1 aClient *acptr;
|
||||
Reg2 int i;
|
||||
Reg3 Link *lp;
|
||||
Reg4 Link *prev;
|
||||
Reg5 Dlink *dlp;
|
||||
|
||||
if (IsClient(bcptr))
|
||||
{
|
||||
/* Stop a running /LIST clean */
|
||||
if (MyClient(bcptr) && bcptr->listing)
|
||||
{
|
||||
bcptr->listing->mode.mode &= ~MODE_LISTED;
|
||||
bcptr->listing = NULL;
|
||||
}
|
||||
|
||||
if (AskedPing(bcptr))
|
||||
cancel_ping(bcptr, NULL);
|
||||
/*
|
||||
** If this exit is generated from "m_kill", then there
|
||||
** is no sense in sending the QUIT--KILL's have been
|
||||
** sent instead.
|
||||
*/
|
||||
/* Old Protocol : */
|
||||
if ((bcptr->flags & FLAGS_KILLED) == 0)
|
||||
{
|
||||
for (dlp = me.serv->down; dlp; dlp = dlp->next)
|
||||
if (Protocol(dlp->value.cptr)<9 && bcptr->from != dlp->value.cptr)
|
||||
sendto_one(dlp->value.cptr,":%s QUIT :%s", bcptr->name, comment);
|
||||
}
|
||||
/*
|
||||
** If a person is on a channel, send a QUIT notice
|
||||
** to every client (person) on the same channel (so
|
||||
** that the client can show the "**signoff" message).
|
||||
** (Note: The notice is to the local clients *only*)
|
||||
*/
|
||||
sendto_common_channels(bcptr, ":%s QUIT :%s", bcptr->name, comment);
|
||||
|
||||
#ifdef NPATH
|
||||
note_signoff(bcptr);
|
||||
#endif
|
||||
|
||||
while ((lp = bcptr->user->channel))
|
||||
remove_user_from_channel(bcptr,lp->value.chptr);
|
||||
|
||||
/* Clean up invitefield */
|
||||
while ((lp = bcptr->user->invited))
|
||||
del_invite(bcptr, lp->value.chptr);
|
||||
|
||||
/* Clean up silencefield */
|
||||
while ((lp = bcptr->user->silence))
|
||||
(void)del_silence(bcptr, lp->value.cp);
|
||||
|
||||
/* Remove from serv->client list */
|
||||
remove_dlink(&bcptr->user->server->serv->client, bcptr->user->clink);
|
||||
}
|
||||
else if (IsServer(bcptr))
|
||||
{
|
||||
/* Old Protocol : */
|
||||
for (dlp = me.serv->down; dlp; dlp = dlp->next)
|
||||
if (Protocol(dlp->value.cptr)<9 && dlp->value.cptr->fd >= 0)
|
||||
{
|
||||
if (bcptr->from != dlp->value.cptr &&
|
||||
(sptr->from != dlp->value.cptr->from || OldProtocolFlag))
|
||||
sendto_one(dlp->value.cptr, "SQUIT %s :%s", bcptr->name, comment);
|
||||
else if (sptr->from != dlp->value.cptr->from && !OldProtocolFlag)
|
||||
sendto_one(dlp->value.cptr, ":%s SQUIT %s :%s", sptr->name,
|
||||
bcptr->name, comment);
|
||||
}
|
||||
|
||||
/* Remove downlink list node of uplink */
|
||||
remove_dlink(&bcptr->serv->up->serv->down, bcptr->serv->updown);
|
||||
}
|
||||
else if (IsPing(bcptr)) /* Apperently, we are closing ALL links */
|
||||
{
|
||||
del_queries((char *)bcptr);
|
||||
end_ping(bcptr);
|
||||
return;
|
||||
}
|
||||
else if (IsService(bcptr))
|
||||
{
|
||||
/* Lame, lamer, Avalon. */
|
||||
sendto_ops("ERROR: exit_one_client: Service? Whaisda?");
|
||||
}
|
||||
else if (IsMe(bcptr))
|
||||
{
|
||||
sendto_ops("ERROR: tried to exit me! : %s", comment);
|
||||
return; /* ...must *never* exit self! */
|
||||
}
|
||||
|
||||
/* Remove bcptr from the client list */
|
||||
if (del_from_client_hash_table(bcptr->name, bcptr) != 1)
|
||||
Debug((DEBUG_ERROR, "%#x !in tab %s[%s] %#x %#x %#x %d %d %#x",
|
||||
bcptr, bcptr->name, bcptr->from ? bcptr->from->sockhost : "??host",
|
||||
bcptr->from, bcptr->next, bcptr->prev, bcptr->fd,
|
||||
bcptr->status, bcptr->user));
|
||||
remove_client_from_list(bcptr);
|
||||
return;
|
||||
}
|
||||
|
||||
void checklist()
|
||||
{
|
||||
Reg1 aClient *acptr;
|
||||
Reg2 int i,j;
|
||||
|
||||
if (!(bootopt & BOOT_AUTODIE))
|
||||
return;
|
||||
for (j = i = 0; i <= highest_fd; i++)
|
||||
if (!(acptr = local[i]))
|
||||
continue;
|
||||
else if (IsClient(acptr))
|
||||
j++;
|
||||
if (!j)
|
||||
{
|
||||
#ifdef USE_SYSLOG
|
||||
syslog(LOG_WARNING,"ircd exiting: autodie");
|
||||
#endif
|
||||
exit(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void initstats()
|
||||
{
|
||||
bzero((char *)&ircst, sizeof(ircst));
|
||||
}
|
||||
|
||||
void tstats(cptr, name)
|
||||
aClient *cptr;
|
||||
char *name;
|
||||
{
|
||||
Reg1 aClient *acptr;
|
||||
Reg2 int i;
|
||||
Reg3 struct stats *sp;
|
||||
struct stats tmp;
|
||||
|
||||
sp = &tmp;
|
||||
bcopy((char *)ircstp, (char *)sp, sizeof(*sp));
|
||||
for (i = 0; i < MAXCONNECTIONS; i++)
|
||||
{
|
||||
if (!(acptr = local[i]))
|
||||
continue;
|
||||
if (IsServer(acptr))
|
||||
{
|
||||
sp->is_sbs += acptr->sendB;
|
||||
sp->is_sbr += acptr->receiveB;
|
||||
sp->is_sks += acptr->sendK;
|
||||
sp->is_skr += acptr->receiveK;
|
||||
sp->is_sti += now - acptr->firsttime;
|
||||
sp->is_sv++;
|
||||
if (sp->is_sbs > 1023)
|
||||
{
|
||||
sp->is_sks += (sp->is_sbs >> 10);
|
||||
sp->is_sbs &= 0x3ff;
|
||||
}
|
||||
if (sp->is_sbr > 1023)
|
||||
{
|
||||
sp->is_skr += (sp->is_sbr >> 10);
|
||||
sp->is_sbr &= 0x3ff;
|
||||
}
|
||||
}
|
||||
else if (IsClient(acptr))
|
||||
{
|
||||
sp->is_cbs += acptr->sendB;
|
||||
sp->is_cbr += acptr->receiveB;
|
||||
sp->is_cks += acptr->sendK;
|
||||
sp->is_ckr += acptr->receiveK;
|
||||
sp->is_cti += now - acptr->firsttime;
|
||||
sp->is_cl++;
|
||||
if (sp->is_cbs > 1023)
|
||||
{
|
||||
sp->is_cks += (sp->is_cbs >> 10);
|
||||
sp->is_cbs &= 0x3ff;
|
||||
}
|
||||
if (sp->is_cbr > 1023)
|
||||
{
|
||||
sp->is_ckr += (sp->is_cbr >> 10);
|
||||
sp->is_cbr &= 0x3ff;
|
||||
}
|
||||
}
|
||||
else if (IsUnknown(acptr))
|
||||
sp->is_ni++;
|
||||
}
|
||||
|
||||
sendto_one(cptr, ":%s %d %s :accepts %u refused %u",
|
||||
me.name, RPL_STATSDEBUG, name, sp->is_ac, sp->is_ref);
|
||||
sendto_one(cptr, ":%s %d %s :unknown commands %u prefixes %u",
|
||||
me.name, RPL_STATSDEBUG, name, sp->is_unco, sp->is_unpf);
|
||||
sendto_one(cptr, ":%s %d %s :nick collisions %u unknown closes %u",
|
||||
me.name, RPL_STATSDEBUG, name, sp->is_kill, sp->is_ni);
|
||||
sendto_one(cptr, ":%s %d %s :wrong direction %u empty %u",
|
||||
me.name, RPL_STATSDEBUG, name, sp->is_wrdi, sp->is_empt);
|
||||
sendto_one(cptr, ":%s %d %s :numerics seen %u mode fakes %u",
|
||||
me.name, RPL_STATSDEBUG, name, sp->is_num, sp->is_fake);
|
||||
sendto_one(cptr, ":%s %d %s :auth successes %u fails %u",
|
||||
me.name, RPL_STATSDEBUG, name, sp->is_asuc, sp->is_abad);
|
||||
sendto_one(cptr, ":%s %d %s :local connections %u udp packets %u",
|
||||
me.name, RPL_STATSDEBUG, name, sp->is_loc, sp->is_udp);
|
||||
sendto_one(cptr, ":%s %d %s :Client Server",
|
||||
me.name, RPL_STATSDEBUG, name);
|
||||
sendto_one(cptr, ":%s %d %s :connected %u %u",
|
||||
me.name, RPL_STATSDEBUG, name, sp->is_cl, sp->is_sv);
|
||||
sendto_one(cptr, ":%s %d %s :bytes sent %u.%uK %u.%uK",
|
||||
me.name, RPL_STATSDEBUG, name,
|
||||
sp->is_cks, sp->is_cbs, sp->is_sks, sp->is_sbs);
|
||||
sendto_one(cptr, ":%s %d %s :bytes recv %u.%uK %u.%uK",
|
||||
me.name, RPL_STATSDEBUG, name,
|
||||
sp->is_ckr, sp->is_cbr, sp->is_skr, sp->is_sbr);
|
||||
sendto_one(cptr, ":%s %d %s :time connected %u %u",
|
||||
me.name, RPL_STATSDEBUG, name, sp->is_cti, sp->is_sti);
|
||||
}
|
||||
129
ircd/s_numeric.c
Normal file
129
ircd/s_numeric.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, ircd/s_numeric.c
|
||||
* Copyright (C) 1990 Jarkko Oikarinen
|
||||
*
|
||||
* Numerous fixes by Markku Savela
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)s_numeric.c 2.14 1/30/94 (C) 1988 University of Oulu, \
|
||||
Computing Center and Jarkko Oikarinen";
|
||||
#endif
|
||||
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "numeric.h"
|
||||
#include "h.h"
|
||||
|
||||
static char buffer[1024];
|
||||
|
||||
/*
|
||||
** DoNumeric (replacement for the old do_numeric)
|
||||
**
|
||||
** parc number of arguments ('sender' counted as one!)
|
||||
** parv[0] pointer to 'sender' (may point to empty string) (not used)
|
||||
** parv[1]..parv[parc-1]
|
||||
** pointers to additional parameters, this is a NULL
|
||||
** terminated list (parv[parc] == NULL).
|
||||
**
|
||||
** *WARNING*
|
||||
** Numerics are mostly error reports. If there is something
|
||||
** wrong with the message, just *DROP* it! Don't even think of
|
||||
** sending back a neat error message -- big danger of creating
|
||||
** a ping pong error message...
|
||||
*/
|
||||
int do_numeric(numeric, cptr, sptr, parc, parv)
|
||||
int numeric;
|
||||
aClient *cptr, *sptr;
|
||||
int parc;
|
||||
char *parv[];
|
||||
{
|
||||
aClient *acptr;
|
||||
aChannel *chptr;
|
||||
char *nick, *p;
|
||||
int i;
|
||||
|
||||
if (parc < 1 || !IsServer(sptr))
|
||||
return 0;
|
||||
/* Remap low number numerics. */
|
||||
if (numeric < 100)
|
||||
numeric += 100;
|
||||
/*
|
||||
** Prepare the parameter portion of the message into 'buffer'.
|
||||
** (Because the buffer is twice as large as the message buffer
|
||||
** for the socket, no overflow can occur here... ...on current
|
||||
** assumptions--bets are off, if these are changed --msa)
|
||||
** Note: if buffer is non-empty, it will begin with SPACE.
|
||||
*/
|
||||
buffer[0] = '\0';
|
||||
if (parc > 1)
|
||||
{
|
||||
for (i = 2; i < (parc - 1); i++)
|
||||
{
|
||||
(void)strcat(buffer, " ");
|
||||
(void)strcat(buffer, parv[i]);
|
||||
}
|
||||
(void)strcat(buffer, " :");
|
||||
(void)strcat(buffer, parv[parc-1]);
|
||||
}
|
||||
for (; (nick = strtoken(&p, parv[1], ",")); parv[1] = NULL)
|
||||
{
|
||||
if ((acptr = find_client(nick, (aClient *)NULL)))
|
||||
{
|
||||
/*
|
||||
** Drop to bit bucket if for me...
|
||||
** ...one might consider sendto_ops
|
||||
** here... --msa
|
||||
** And so it was done. -avalon
|
||||
** And regretted. Dont do it that way. Make sure
|
||||
** it goes only to non-servers. -avalon
|
||||
** Check added to make sure servers don't try to loop
|
||||
** with numerics which can happen with nick collisions.
|
||||
** - Avalon
|
||||
*/
|
||||
if (!IsMe(acptr) && IsPerson(acptr))
|
||||
{
|
||||
/* Added for .U3.2. drop remote 'You are not on
|
||||
** that channel', we should be synced anyway,
|
||||
** and this is an annoying message with TSpre7
|
||||
** still on the net; would result in numeric 442 for
|
||||
** every KICK... Can be removed when TSpre7 is gone.
|
||||
** --Run
|
||||
*/
|
||||
if (numeric==ERR_NOTONCHANNEL) return 0;
|
||||
|
||||
sendto_prefix_one(acptr, sptr,":%s %d %s%s",
|
||||
parv[0], numeric, nick, buffer);
|
||||
}
|
||||
else if (IsServer(acptr) && acptr->from != cptr)
|
||||
sendto_prefix_one(acptr, sptr,":%s %d %s%s",
|
||||
parv[0], numeric, nick, buffer);
|
||||
}
|
||||
else if ((acptr = find_server(nick, (aClient *)NULL)))
|
||||
{
|
||||
if (!IsMe(acptr) && acptr->from != cptr)
|
||||
sendto_prefix_one(acptr, sptr,":%s %d %s%s",
|
||||
parv[0], numeric, nick, buffer);
|
||||
}
|
||||
else if ((chptr = find_channel(nick, (aChannel *)NULL)))
|
||||
sendto_channel_butone(cptr,sptr,chptr,":%s %d %s%s",
|
||||
parv[0],
|
||||
numeric, chptr->chname, buffer);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
500
ircd/s_ping.c
Normal file
500
ircd/s_ping.c
Normal file
@@ -0,0 +1,500 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, ircd/s_ping.c
|
||||
* Copyright (C) 1994 Carlo K ( Run @ undernet.org )
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)s_ping.c 1.0 9/21/94 (C) 1994 Carlo Kid";
|
||||
#endif
|
||||
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "numeric.h"
|
||||
#include "patchlevel.h"
|
||||
#include <sys/socket.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/ioctl.h>
|
||||
#ifdef UNIXPORT
|
||||
# include <sys/un.h>
|
||||
#endif
|
||||
#if defined(__hpux)
|
||||
# include "inet.h"
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include "sock.h" /* If FD_ZERO isn't defined up to this point, */
|
||||
/* define it (BSD4.2 needs this) */
|
||||
#include "h.h"
|
||||
|
||||
#define UPINGBUFSIZE 2000 /* Lot bigger then 1024, bit smaller then 2048 */
|
||||
#define UPINGTIMEOUT 120 /* Timeout waitting for first ping response */
|
||||
|
||||
extern u_long inet_addr();
|
||||
|
||||
/*
|
||||
* start_ping
|
||||
*
|
||||
* As for now, I am abusing the client structure for a ping connection.
|
||||
* Used members are:
|
||||
* These are used by existing routines as well, and do have their own meaning:
|
||||
* fd : The socket file descriptor.
|
||||
* status : To flag that this IS one of these abused ping structures
|
||||
* sockhost : Name of requested server to ping (aconf->host).
|
||||
* name : aconf->name
|
||||
* ip : ip#
|
||||
* These have more or less their own meaning,
|
||||
* but are not used by existing routines:
|
||||
* flags : To flag that a next ping is requested.
|
||||
* port : Requested remote port.
|
||||
* These are only used by the 'uping' routines
|
||||
* and have totally different meanings:
|
||||
* buffer : buffer hold pingtimes of received packets
|
||||
* confs : recv/send (char *) buffer.
|
||||
* hopcount : Total number of requested pings
|
||||
* count : Number of pings left to send.
|
||||
* hashv : Number of pings left to be received.
|
||||
* acpt : client asking for this ping
|
||||
* lasttime : last time a ping was sent
|
||||
* firsttime: recvfrom timeout
|
||||
* since : timeout in seconds to next recvfrom
|
||||
* receiveK : minimum in ms
|
||||
* sendM : average in ms
|
||||
* receiveM : maximum in ms
|
||||
*/
|
||||
int start_ping(cptr)
|
||||
Reg1 aClient *cptr;
|
||||
{
|
||||
struct sockaddr_in remote_addr;
|
||||
|
||||
Debug((DEBUG_NOTICE,"start_ping(%x) status %d", cptr, cptr->status));
|
||||
|
||||
if (!(cptr->acpt)) return -1;
|
||||
|
||||
bcopy((char *)&cptr->ip, (char *)&remote_addr.sin_addr,
|
||||
sizeof(struct in_addr));
|
||||
#ifdef TESTNET
|
||||
remote_addr.sin_port = htons(cptr->port + 10000);
|
||||
#else
|
||||
remote_addr.sin_port = htons(cptr->port);
|
||||
#endif
|
||||
remote_addr.sin_family = AF_INET;
|
||||
|
||||
sendto_one(cptr->acpt,
|
||||
":%s NOTICE %s :Sending %d ping%s to %s[%s] port %d",
|
||||
me.name, cptr->acpt->name, cptr->hopcount,
|
||||
(cptr->hopcount == 1) ? "" : "s", cptr->name,
|
||||
#ifdef TESTNET
|
||||
inetntoa((char *)&remote_addr.sin_addr), ntohs(remote_addr.sin_port)
|
||||
- 10000);
|
||||
#else
|
||||
inetntoa((char *)&remote_addr.sin_addr), ntohs(remote_addr.sin_port));
|
||||
#endif
|
||||
|
||||
cptr->firsttime = now + UPINGTIMEOUT;
|
||||
cptr->since = UPINGTIMEOUT;
|
||||
cptr->flags |= (FLAGS_PING);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* send_ping
|
||||
*
|
||||
*/
|
||||
void send_ping(cptr)
|
||||
aClient *cptr;
|
||||
{
|
||||
struct sockaddr_in remote_addr;
|
||||
struct timeval tv;
|
||||
|
||||
bcopy((char *)&cptr->ip, (char *)&remote_addr.sin_addr,
|
||||
sizeof(struct in_addr));
|
||||
#ifdef TESTNET
|
||||
remote_addr.sin_port = htons(cptr->port + 10000);
|
||||
#else
|
||||
remote_addr.sin_port = htons(cptr->port);
|
||||
#endif
|
||||
remote_addr.sin_family = AF_INET;
|
||||
|
||||
(void) gettimeofday(&tv, NULL);
|
||||
(void)sprintf((char *)cptr->confs, " %10lu%c%6lu",
|
||||
tv.tv_sec, '\0', tv.tv_usec);
|
||||
|
||||
Debug((DEBUG_SEND, "send_ping: sending [%s %s] to %s.%d on %d",
|
||||
(char *)cptr->confs, (char *)cptr->confs + 12,
|
||||
inetntoa((char *)&remote_addr.sin_addr), ntohs(remote_addr.sin_port),
|
||||
cptr->fd));
|
||||
|
||||
if (sendto(cptr->fd, (char *)cptr->confs, 1024, 0,
|
||||
(struct sockaddr *)&remote_addr, sizeof(struct sockaddr_in)) != 1024)
|
||||
{
|
||||
int err=errno;
|
||||
if (cptr->acpt)
|
||||
sendto_one(cptr->acpt, ":%s NOTICE %s :UPING: sendto() failed: %s",
|
||||
me.name, cptr->acpt->name, strerror(get_sockerr(cptr)));
|
||||
Debug((DEBUG_SEND, "send_ping: sendto failed on %d (%d)", cptr->fd, err));
|
||||
end_ping(cptr);
|
||||
}
|
||||
else if (--(cptr->count) <= 0 )
|
||||
{
|
||||
ClearPing(cptr);
|
||||
if (cptr->hashv <= 0) end_ping(cptr);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* read_ping
|
||||
*
|
||||
*/
|
||||
void read_ping(cptr)
|
||||
Reg1 aClient *cptr;
|
||||
{
|
||||
int addr_len = sizeof(struct sockaddr_in);
|
||||
struct sockaddr_in remote_addr;
|
||||
struct timeval tv;
|
||||
int len;
|
||||
unsigned long int pingtime;
|
||||
char *s;
|
||||
|
||||
bcopy((char *)&cptr->ip, (char *)&remote_addr.sin_addr,
|
||||
sizeof(struct in_addr));
|
||||
#ifdef TESTNET
|
||||
remote_addr.sin_port = htons(cptr->port + 10000);
|
||||
#else
|
||||
remote_addr.sin_port = htons(cptr->port);
|
||||
#endif
|
||||
remote_addr.sin_family = AF_INET;
|
||||
|
||||
(void)gettimeofday(&tv, NULL);
|
||||
|
||||
if ((len=recvfrom(cptr->fd, (char *)cptr->confs, UPINGBUFSIZE, 0,
|
||||
(struct sockaddr *)&remote_addr, &addr_len)) == -1)
|
||||
{
|
||||
int err = errno;
|
||||
sendto_one(cptr->acpt,
|
||||
":%s NOTICE %s :UPING: recvfrom: %s",
|
||||
me.name, cptr->acpt->name, strerror(get_sockerr(cptr)));
|
||||
Debug((DEBUG_SEND, "read_ping: recvfrom: %d", err));
|
||||
if (err != EAGAIN) end_ping(cptr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (len<19) return; /* Broken packet */
|
||||
|
||||
pingtime = (tv.tv_sec - atoi((char *)cptr->confs + 1)) * 1000 +
|
||||
(tv.tv_usec - atoi((char *)cptr->confs + strlen((char *)cptr->confs) +
|
||||
1)) / 1000;
|
||||
cptr->sendM += pingtime;
|
||||
if (!(cptr->receiveK) || (cptr->receiveK > pingtime))
|
||||
cptr->receiveK = pingtime;
|
||||
if (pingtime > cptr->receiveM)
|
||||
cptr->receiveM = pingtime;
|
||||
/* Wait at most 10 times the average pingtime for the next one: */
|
||||
if ((cptr->since =
|
||||
cptr->sendM / ( 100 * (cptr->hopcount - cptr->hashv + 1))) < 2)
|
||||
cptr->since = 2;
|
||||
cptr->firsttime = tv.tv_sec + cptr->since;
|
||||
|
||||
Debug(("read_ping: %d bytes, ti %lu: [%s %s] %u ms",
|
||||
len, cptr->since, (char *)cptr->confs,
|
||||
(char *)cptr->confs + strlen((char *)cptr->confs) + 1, pingtime));
|
||||
|
||||
s = cptr->buffer + strlen(cptr->buffer);
|
||||
sprintf(s, " %lu", pingtime);
|
||||
|
||||
if ((--(cptr->hashv) <= 0 && !DoPing(cptr)) || !(cptr->acpt))
|
||||
end_ping(cptr);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int ping_server(cptr, hp)
|
||||
aClient *cptr;
|
||||
struct hostent *hp;
|
||||
{
|
||||
if ( ( !cptr->ip.s_addr )
|
||||
#ifdef UNIXPORT
|
||||
&& ( ( cptr->sockhost[2] ) != '/' )
|
||||
#endif
|
||||
)
|
||||
{
|
||||
struct hostent *hp;
|
||||
char *s;
|
||||
Link lin;
|
||||
|
||||
if (!(cptr->acpt)) return -1; /* Oper left already */
|
||||
|
||||
lin.flags = ASYNC_PING;
|
||||
lin.value.cptr = cptr;
|
||||
nextdnscheck = 1;
|
||||
s = (char *)index(cptr->sockhost, '@');
|
||||
s++; /* should never be NULL; cptr->sockhost is actually a conf->host */
|
||||
if ((cptr->ip.s_addr = inet_addr(s)) == -1)
|
||||
{
|
||||
cptr->ip.s_addr = 0;
|
||||
hp = gethost_byname(s, &lin);
|
||||
Debug((DEBUG_NOTICE, "ping_sv: hp %x ac %x ho %s", hp, cptr, s));
|
||||
if (!hp) return 0;
|
||||
bcopy(hp->h_addr, (char *)&cptr->ip, sizeof(struct in_addr));
|
||||
}
|
||||
}
|
||||
|
||||
return start_ping(cptr);
|
||||
}
|
||||
|
||||
/*
|
||||
** m_uping -- by Run
|
||||
**
|
||||
** parv[0] = sender prefix
|
||||
** parv[1] = pinged server
|
||||
** parv[2] = port
|
||||
** parv[3] = hunted server
|
||||
** parv[4] = number of requested pings
|
||||
*/
|
||||
int m_uping(cptr, sptr, parc, parv)
|
||||
aClient *cptr, *sptr;
|
||||
int parc;
|
||||
char *parv[];
|
||||
{
|
||||
aConfItem *aconf;
|
||||
int port, fd, opt;
|
||||
|
||||
if (!IsPrivileged(sptr))
|
||||
{
|
||||
sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (parc < 2)
|
||||
{
|
||||
sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS),
|
||||
me.name, parv[0], "UPING");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (MyClient(sptr))
|
||||
{
|
||||
if (parc == 2)
|
||||
{
|
||||
parv[parc++]=UDP_PORT;
|
||||
parv[parc++]=me.name;
|
||||
parv[parc++]="5";
|
||||
}
|
||||
else if (parc == 3)
|
||||
{
|
||||
if (isdigit(*parv[2]))
|
||||
{
|
||||
parv[parc++]=me.name;
|
||||
}
|
||||
else
|
||||
{
|
||||
parv[parc++]=parv[2];
|
||||
parv[2]=UDP_PORT;
|
||||
}
|
||||
parv[parc++]="5";
|
||||
}
|
||||
else if (parc == 4)
|
||||
{
|
||||
if (isdigit(*parv[2]))
|
||||
{
|
||||
if (isdigit(*parv[3]))
|
||||
{
|
||||
parv[parc++]=parv[3];
|
||||
parv[3]=me.name;
|
||||
}
|
||||
else
|
||||
parv[parc++]="5";
|
||||
}
|
||||
else
|
||||
{
|
||||
parv[parc++]=parv[3];
|
||||
parv[3]=parv[2];
|
||||
parv[2]=UDP_PORT;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hunt_server(cptr,sptr,":%s UPING %s %s %s %s",3,parc,parv) != HUNTED_ISME)
|
||||
return 0;
|
||||
|
||||
if (BadPtr(parv[4]) || atoi(parv[4])<=0)
|
||||
{
|
||||
sendto_one(sptr,":%s NOTICE %s :UPING: Illegal number of packets: %s",
|
||||
me.name, parv[0], parv[4]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Check if a CONNECT would be possible at all (adapted from m_connect) */
|
||||
for (aconf = conf; aconf; aconf = aconf->next)
|
||||
if (aconf->status == CONF_CONNECT_SERVER &&
|
||||
matches(parv[1], aconf->name) == 0)
|
||||
break;
|
||||
if (!aconf)
|
||||
for (aconf = conf; aconf; aconf = aconf->next)
|
||||
if (aconf->status == CONF_CONNECT_SERVER &&
|
||||
(matches(parv[1], aconf->host) == 0 ||
|
||||
matches(parv[1], index(aconf->host, '@')+1) == 0))
|
||||
break;
|
||||
if (!aconf)
|
||||
{
|
||||
sendto_one(sptr, "NOTICE %s :UPING: Host %s not listed in ircd.conf",
|
||||
parv[0], parv[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (AskedPing(sptr))
|
||||
cancel_ping(sptr, sptr); /* Cancel previous ping request */
|
||||
|
||||
/*
|
||||
* Determine port: First user supplied, then default : 7007
|
||||
*/
|
||||
if (!BadPtr(parv[2]) && (port = atoi(parv[2])) <= 0) port=atoi(UDP_PORT);
|
||||
|
||||
(void)alarm(2);
|
||||
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
|
||||
{
|
||||
int err = errno;
|
||||
(void)alarm(0);
|
||||
sendto_ops("m_uping: socket: %s", (err != EAGAIN) ?
|
||||
strerror(err) : "No more sockets");
|
||||
sendto_one(sptr, ":%s NOTICE %s :UPING: Unable to create udp ping socket",
|
||||
me.name, parv[0]);
|
||||
#ifdef USE_SYSLOG
|
||||
syslog(LOG_ERR, "Unable to create udp ping socket");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
(void)alarm(0);
|
||||
|
||||
if (fcntl(fd, F_SETFL, FNDELAY)==-1)
|
||||
{
|
||||
sendto_ops("m_uping: fcntl FNDELAY: %s", strerror(errno));
|
||||
sendto_one(sptr, ":%s NOTICE %s :UPING: Can't set fd non-blocking",
|
||||
me.name, parv[0]);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
** On some systems, receive and send buffers must be equal in size.
|
||||
** Others block select() when the buffers are too small
|
||||
** (Linux 1.1.50 blocks when < 2048) --Run
|
||||
*/
|
||||
opt = 2048;
|
||||
if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (OPT_TYPE *)&opt, sizeof(opt)) < 0 ||
|
||||
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (OPT_TYPE *)&opt, sizeof(opt)) < 0)
|
||||
{
|
||||
int err=errno;
|
||||
sendto_ops("m_uping: setsockopt SO_SNDBUF|SO_RCVBUF: %s",
|
||||
strerror(err));
|
||||
sendto_one(sptr, ":%s NOTICE %s :UPING: error in setsockopt: %s",
|
||||
me.name, parv[0], strerror(err));
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fd >= MAXCONNECTIONS)
|
||||
{
|
||||
sendto_ops("Can't allocate fd for uping (all connections in use)");
|
||||
sendto_one(sptr, ":%s NOTICE %s :UPING: All connections in use",
|
||||
me.name, parv[0]);
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fd > highest_fd)
|
||||
highest_fd = fd;
|
||||
local[fd] = cptr = make_client(NULL);
|
||||
cptr->confs = (Link *)MyMalloc(UPINGBUFSIZE); /* Really a (char *) */
|
||||
cptr->fd = fd;
|
||||
cptr->port = port;
|
||||
cptr->hopcount = cptr->hashv = cptr->count = MIN(20, atoi(parv[4]));
|
||||
strcpy(cptr->sockhost, aconf->host);
|
||||
cptr->acpt = sptr;
|
||||
SetAskedPing(sptr);
|
||||
bcopy((void *)&aconf->ipnum, (void *)&cptr->ip, sizeof(struct in_addr));
|
||||
strcpy(cptr->name, aconf->name);
|
||||
cptr->firsttime = 0;
|
||||
SetPing(cptr);
|
||||
|
||||
switch (ping_server(cptr, NULL))
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case -1:
|
||||
del_queries((char *)cptr);
|
||||
end_ping(cptr);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void end_ping(cptr)
|
||||
register aClient *cptr;
|
||||
{
|
||||
Debug((DEBUG_DEBUG,"end_ping: %x", cptr));
|
||||
if (cptr->acpt)
|
||||
{
|
||||
if (cptr->firsttime) /* Started at all ? */
|
||||
{
|
||||
if (cptr->hashv != cptr->hopcount) /* Received any pings at all ? */
|
||||
{
|
||||
sendto_one(cptr->acpt, ":%s NOTICE %s :UPING %s%s",
|
||||
me.name, cptr->acpt->name, cptr->name, cptr->buffer);
|
||||
sendto_one(cptr->acpt,
|
||||
":%s NOTICE %s :UPING Stats: sent %d recvd %d ; min/avg/max = %lu/%lu/%lu ms",
|
||||
me.name, cptr->acpt->name, cptr->hopcount - cptr->count,
|
||||
cptr->hopcount - cptr->hashv, cptr->receiveK,
|
||||
(2 * cptr->sendM + cptr->hopcount - cptr->hashv) /
|
||||
(2 * ( cptr->hopcount - cptr->hashv)),
|
||||
cptr->receiveM);
|
||||
}
|
||||
else
|
||||
sendto_one(cptr->acpt,
|
||||
":%s NOTICE %s :UPING: no response from %s within %d seconds",
|
||||
me.name, cptr->acpt->name, cptr->name,
|
||||
now + cptr->since - cptr->firsttime);
|
||||
}
|
||||
else
|
||||
sendto_one(cptr->acpt,
|
||||
":%s NOTICE %s :UPING: Could not start ping to %s %d",
|
||||
me.name, cptr->acpt->name, cptr->name, cptr->port);
|
||||
}
|
||||
(void)close(cptr->fd);
|
||||
local[cptr->fd] = NULL;
|
||||
if (cptr->acpt)
|
||||
ClearAskedPing(cptr->acpt);
|
||||
MyFree((char *)cptr->confs);
|
||||
free_client(cptr);
|
||||
}
|
||||
|
||||
void cancel_ping(sptr, acptr)
|
||||
aClient *sptr, *acptr;
|
||||
{
|
||||
int i;
|
||||
aClient *cptr;
|
||||
|
||||
Debug((DEBUG_DEBUG, "Cancelling uping for %x (%s)", sptr, sptr->name));
|
||||
for (i = highest_fd; i >= 0; i--)
|
||||
if ((cptr = local[i]) && IsPing(cptr) && cptr->acpt == sptr)
|
||||
{ cptr->acpt = acptr;
|
||||
del_queries((char *)cptr);
|
||||
end_ping(cptr);
|
||||
break; }
|
||||
|
||||
ClearAskedPing(sptr);
|
||||
}
|
||||
3017
ircd/s_serv.c
Normal file
3017
ircd/s_serv.c
Normal file
File diff suppressed because it is too large
Load Diff
2802
ircd/s_user.c
Normal file
2802
ircd/s_user.c
Normal file
File diff suppressed because it is too large
Load Diff
251
ircd/userload.c
Normal file
251
ircd/userload.c
Normal file
@@ -0,0 +1,251 @@
|
||||
/****************************************************************************
|
||||
* Userload module by Michael L. VanLoon (mlv) <michaelv@iastate.edu>
|
||||
* Written 2/93. Originally grafted into irc2.7.2g 4/93.
|
||||
*
|
||||
* IRC - Internet Relay Chat, ircd/userload.c
|
||||
* Copyright (C) 1990 University of Oulu, Computing Center
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
****************************************************************************/
|
||||
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "userload.h"
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/errno.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <sys/resource.h>
|
||||
#include "h.h"
|
||||
|
||||
|
||||
struct current_load_struct current_load_data;
|
||||
struct load_entry *load_list_head = NULL, *load_list_tail = NULL,
|
||||
*load_free_head = NULL, *load_free_tail = NULL;
|
||||
|
||||
|
||||
void update_load()
|
||||
{
|
||||
static struct timeval nowt, last;
|
||||
register struct load_entry *cur_load_entry;
|
||||
|
||||
/* This seems to get polluted on startup by an exit_client()
|
||||
* before any connections have been recorded.
|
||||
*/
|
||||
if (current_load_data.local_count > MAXCONNECTIONS ||
|
||||
current_load_data.client_count > MAXCONNECTIONS ||
|
||||
current_load_data.conn_count > MAXCONNECTIONS)
|
||||
bzero((char *)¤t_load_data, sizeof(struct current_load_struct));
|
||||
|
||||
memcpy(&last, &nowt, sizeof(struct timeval));
|
||||
if (gettimeofday(&nowt, NULL) != 0)
|
||||
return; /* error getting time of day--can't calculate time diff */
|
||||
|
||||
if (load_free_tail == NULL) {
|
||||
if ((cur_load_entry =
|
||||
(struct load_entry *) malloc(sizeof(struct load_entry))) == NULL)
|
||||
return;
|
||||
/* printf("malloc pointer: %x\n", cur_load_entry); */
|
||||
} else {
|
||||
cur_load_entry = load_free_tail;
|
||||
load_free_tail = cur_load_entry->prev;
|
||||
if (load_free_tail == NULL)
|
||||
load_free_head = NULL;
|
||||
/* printf("free pointer: %x\n", cur_load_entry); */
|
||||
}
|
||||
if (load_list_tail != NULL) {
|
||||
cur_load_entry->time_incr = ((nowt.tv_sec * 1000 + nowt.tv_usec / 1000 + 5)
|
||||
- (last.tv_sec * 1000 + last.tv_usec / 1000)) / 10;
|
||||
cur_load_entry->local_count = current_load_data.local_count;
|
||||
cur_load_entry->client_count = current_load_data.client_count;
|
||||
cur_load_entry->conn_count = current_load_data.conn_count;
|
||||
} else {
|
||||
load_list_head = cur_load_entry;
|
||||
bzero((char *)cur_load_entry, sizeof(struct load_entry));
|
||||
cur_load_entry->time_incr = 1;
|
||||
}
|
||||
cur_load_entry->prev = load_list_tail;
|
||||
load_list_tail = cur_load_entry;
|
||||
}
|
||||
|
||||
|
||||
void calc_load(sptr, parv)
|
||||
aClient *sptr;
|
||||
char *parv; /* we only get passed the original parv[0] */
|
||||
{
|
||||
register struct load_entry *cur_load_entry;
|
||||
struct load_entry *last;
|
||||
u_long secs = 0, adj_secs, total[3], adj[3];/*[local,client,conn]*/
|
||||
int i, times[5][3]; /* [min,hour,day,Yest,YYest][local,client,conn] */
|
||||
char what[3][HOSTLEN + 1];
|
||||
|
||||
bzero((char *)total, 3 * sizeof(u_long));
|
||||
current_load_data.entries = 0;
|
||||
|
||||
update_load(); /* we want stats accurate as of *now* */
|
||||
|
||||
for (cur_load_entry = load_list_tail; (secs < 6000) &&
|
||||
(cur_load_entry != NULL); cur_load_entry = cur_load_entry->prev) {
|
||||
u_long time_incr = cur_load_entry->time_incr;
|
||||
total[0] += time_incr * cur_load_entry->local_count;
|
||||
total[1] += time_incr * cur_load_entry->client_count;
|
||||
total[2] += time_incr * cur_load_entry->conn_count;
|
||||
last = cur_load_entry;
|
||||
secs += cur_load_entry->time_incr;
|
||||
current_load_data.entries++;
|
||||
}
|
||||
if ((secs > 6000) && (last != NULL)) {
|
||||
adj_secs = secs - 6000;
|
||||
adj[0] = adj_secs * last->local_count;
|
||||
adj[1] = adj_secs * last->client_count;
|
||||
adj[2] = adj_secs * last->conn_count;
|
||||
} else
|
||||
adj_secs = adj[0] = adj[1] = adj[2] = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
times[0][i] = ((total[i] - adj[i]) * 1000 / (secs - adj_secs) + 5) / 10;
|
||||
}
|
||||
|
||||
secs = (secs + 5) / 10;
|
||||
for (i = 0; i < 3; i++)
|
||||
total[i] = (total[i] + 5) / 10;
|
||||
|
||||
for ( ; (secs < 36000) && (cur_load_entry != NULL); secs +=
|
||||
(cur_load_entry->time_incr + 5) / 10, cur_load_entry =
|
||||
cur_load_entry->prev, current_load_data.entries++) {
|
||||
u_long time_incr = (cur_load_entry->time_incr + 5) / 10;
|
||||
total[0] += time_incr * cur_load_entry->local_count;
|
||||
total[1] += time_incr * cur_load_entry->client_count;
|
||||
total[2] += time_incr * cur_load_entry->conn_count;
|
||||
last = cur_load_entry;
|
||||
}
|
||||
if ((secs > 36000) && (last != NULL)) {
|
||||
adj_secs = secs - 36000;
|
||||
adj[0] = adj_secs * last->local_count;
|
||||
adj[1] = adj_secs * last->client_count;
|
||||
adj[2] = adj_secs * last->conn_count;
|
||||
} else
|
||||
adj_secs = adj[0] = adj[1] = adj[2] = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
times[1][i] = ((total[i] - adj[i]) * 100 / (secs - adj_secs) + 5) / 10;
|
||||
}
|
||||
|
||||
secs = (secs + 5) / 10;
|
||||
for (i = 0; i < 3; i++)
|
||||
total[i] = (total[i] + 5) / 10;
|
||||
|
||||
for ( ; (secs < 86400) && (cur_load_entry != NULL); secs +=
|
||||
(cur_load_entry->time_incr + 50) / 100, cur_load_entry =
|
||||
cur_load_entry->prev, current_load_data.entries++) {
|
||||
u_long time_incr = (cur_load_entry->time_incr + 50) / 100;
|
||||
total[0] += time_incr * cur_load_entry->local_count;
|
||||
total[1] += time_incr * cur_load_entry->client_count;
|
||||
total[2] += time_incr * cur_load_entry->conn_count;
|
||||
last = cur_load_entry;
|
||||
}
|
||||
if ((secs > 86400) && (last != NULL)) {
|
||||
adj_secs = secs - 86400;
|
||||
adj[0] = adj_secs * last->local_count;
|
||||
adj[1] = adj_secs * last->client_count;
|
||||
adj[2] = adj_secs * last->conn_count;
|
||||
} else
|
||||
adj_secs = adj[0] = adj[1] = adj[2] = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
times[2][i] = ((total[i] - adj[i]) * 10 / (secs - adj_secs) + 5) / 10;
|
||||
}
|
||||
|
||||
bzero((char *)total, 3 * sizeof(u_long));
|
||||
|
||||
for (secs = 1 ; (secs < 86400) && (cur_load_entry != NULL); secs +=
|
||||
(cur_load_entry->time_incr + 50) / 100, cur_load_entry =
|
||||
cur_load_entry->prev, current_load_data.entries++) {
|
||||
u_long time_incr = (cur_load_entry->time_incr + 50) / 100;
|
||||
total[0] += time_incr * cur_load_entry->local_count;
|
||||
total[1] += time_incr * cur_load_entry->client_count;
|
||||
total[2] += time_incr * cur_load_entry->conn_count;
|
||||
last = cur_load_entry;
|
||||
}
|
||||
if ((secs > 86400) && (last != NULL)) {
|
||||
adj_secs = secs - 86400;
|
||||
adj[0] = adj_secs * last->local_count;
|
||||
adj[1] = adj_secs * last->client_count;
|
||||
adj[2] = adj_secs * last->conn_count;
|
||||
} else
|
||||
adj_secs = adj[0] = adj[1] = adj[2] = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
times[3][i] = ((total[i] - adj[i]) * 10 / (secs - adj_secs) + 5) / 10;
|
||||
}
|
||||
|
||||
bzero((char *)total, 3 * sizeof(u_long));
|
||||
|
||||
for (secs = 1 ; (secs < 86400) && (cur_load_entry != NULL); secs +=
|
||||
(cur_load_entry->time_incr + 50) / 100, cur_load_entry =
|
||||
cur_load_entry->prev, current_load_data.entries++) {
|
||||
u_long time_incr = (cur_load_entry->time_incr + 50) / 100;
|
||||
total[0] += time_incr * cur_load_entry->local_count;
|
||||
total[1] += time_incr * cur_load_entry->client_count;
|
||||
total[2] += time_incr * cur_load_entry->conn_count;
|
||||
last = cur_load_entry;
|
||||
}
|
||||
if ((secs > 86400) && (last != NULL)) {
|
||||
adj_secs = secs - 86400;
|
||||
adj[0] = adj_secs * last->local_count;
|
||||
adj[1] = adj_secs * last->client_count;
|
||||
adj[2] = adj_secs * last->conn_count;
|
||||
} else
|
||||
adj_secs = adj[0] = adj[1] = adj[2] = 0;
|
||||
for (i = 0; i < 3; i++) {
|
||||
times[4][i] = ((total[i] - adj[i]) * 10 / (secs - adj_secs) + 5) / 10;
|
||||
}
|
||||
|
||||
if ((cur_load_entry != NULL) && (cur_load_entry->prev != NULL) &&
|
||||
(secs > 86400)) { /* have nodes to free -- more than 3 days old */
|
||||
struct load_entry *cur_free_entry = load_free_head;
|
||||
|
||||
load_free_head = load_list_head;
|
||||
load_list_head = cur_load_entry;
|
||||
if (cur_free_entry != NULL)
|
||||
cur_free_entry->prev = cur_load_entry->prev;
|
||||
else
|
||||
load_free_tail = cur_load_entry->prev;
|
||||
|
||||
/* printf("freeing: %x (head: %x, tail: %x)\n", cur_load_entry->prev,
|
||||
load_free_head, load_free_tail); */
|
||||
|
||||
cur_load_entry->prev = NULL;
|
||||
}
|
||||
|
||||
strcpy(what[0], DOMAINNAME);
|
||||
strcat(what[0], " clients");
|
||||
strcpy(what[1], "total clients");
|
||||
strcpy(what[2], "total connections");
|
||||
sendto_one(sptr,
|
||||
":%s NOTICE %s :Minute Hour Day Yest. YYest. Userload for:",
|
||||
me.name, parv);
|
||||
for (i = 0; i < 3; i++)
|
||||
sendto_one(sptr,
|
||||
":%s NOTICE %s :%3d.%02d %3d.%01d %3d %3d %3d %s",
|
||||
me.name, parv, times[0][i] / 100, times[0][i] % 100, times[1][i] / 10,
|
||||
times[1][i] % 10, times[2][i], times[3][i], times[4][i], what[i]);
|
||||
}
|
||||
|
||||
|
||||
void initload()
|
||||
{
|
||||
bzero((char *)¤t_load_data, sizeof(struct current_load_struct));
|
||||
update_load(); /* Initialize the load list */
|
||||
}
|
||||
118
ircd/version.c.SH
Executable file
118
ircd/version.c.SH
Executable file
@@ -0,0 +1,118 @@
|
||||
case $CONFIG in
|
||||
'') if test -r ../config.sh
|
||||
then
|
||||
. ../config.sh ;
|
||||
else
|
||||
spitshell=cat
|
||||
package=IRC
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
echo "Extracting $package/ircd/version.c..."
|
||||
|
||||
if test -r version.c
|
||||
then
|
||||
generation=`sed -n 's/^char \*generation = \"\(.*\)\";/\1/p' < version.c`
|
||||
if test ! "$generation" ; then generation=0; fi
|
||||
else
|
||||
generation=0
|
||||
fi
|
||||
|
||||
generation=`expr $generation + 1`
|
||||
|
||||
sumsserv=`sum s_serv.c`;
|
||||
sumsuser=`sum s_user.c`;
|
||||
sumchan=`sum channel.c`;
|
||||
sumsbsd=`sum s_bsd.c`;
|
||||
sumhash=`sum hash.c`;
|
||||
sumsmisc=`sum s_misc.c`;
|
||||
sumircd=`sum ircd.c`;
|
||||
|
||||
creation=`date | \
|
||||
awk '{if (NF == 6) \
|
||||
{ print $1 " " $2 " " $3 " " $6 " at " $4 " " $5 } \
|
||||
else \
|
||||
{ print $1 " " $2 " " $3 " " $7 " at " $4 " " $5 " " $6 }}'`
|
||||
|
||||
$spitshell >version.c <<!SUB!THIS!
|
||||
/*
|
||||
* IRC - Internet Relay Chat, ircd/version.c
|
||||
* Copyright (C) 1990 Chelsea Ashley Dyerman
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is generated by version.c.SH. Any changes made will go away.
|
||||
*/
|
||||
|
||||
#include "struct.h"
|
||||
#include "patchlevel.h"
|
||||
|
||||
char *generation = "$generation";
|
||||
char *creation = "$creation";
|
||||
char *version = BASE_VERSION PATCH1 PATCH2 PATCH3 PATCH4\
|
||||
PATCH5 PATCH6 PATCH7 PATCH8 PATCH9;
|
||||
|
||||
char *infotext[] =
|
||||
{
|
||||
"$package --",
|
||||
"Based on the original code written by Jarkko Oikarinen",
|
||||
"Copyright 1988, 1989, 1990, 1991 University of Oulu, Computing Center",
|
||||
"",
|
||||
"This program is free software; you can redistribute it and/or",
|
||||
"modify it under the terms of the GNU General Public License as",
|
||||
"published by the Free Software Foundation; either version 1, or",
|
||||
"(at your option) any later version.",
|
||||
"",
|
||||
"The following persons have made many changes and enhancements to the",
|
||||
"code and still know how IRC really works if you have questions about it:",
|
||||
"",
|
||||
"Run Carlo Kid carlo@runaway.xs4all.nl",
|
||||
"Avalon Darren Reed avalon@coombs.anu.edu.au",
|
||||
"msa Markku Savela Markku.Savela@vtt.fi",
|
||||
"Wumpus Greg Lindahl gl8f@virginia.edu",
|
||||
"WiZ Jarkko Oikarinen jto@tolsun.oulu.fi",
|
||||
"Argv Armin Gruner Armin.Gruner@Informatik.TU-Muenchen.de",
|
||||
"",
|
||||
"Thanks to the following people for help with preparing 2.8",
|
||||
"",
|
||||
"phone Matthew Green phone@coombs.anu.edu.au",
|
||||
"Sodapop Chuck Kane ckane@ece.uiuc.edu",
|
||||
"Skygod Matt Lyle matt@oc.com",
|
||||
"Vesa Vesa Ruokonen ruokonen@lut.fi",
|
||||
"Nap Nicolas PIOCH pioch@poly.polytechnique.fr",
|
||||
"",
|
||||
"Those who helped in prior versions and continue to be helpful:",
|
||||
"",
|
||||
"Stellan Klebom Dan Goodwin Mike Bolotski",
|
||||
"Ian Frechette Markku Jarvinen Kimmo Suominen",
|
||||
"Jeff Trim Vijay Subramaniam Karl Kleinpaste",
|
||||
"Bill Wisner Tom Davis Hugo Calendar",
|
||||
"Tom Hopkins Stephen van den Berg",
|
||||
"Bo Adler Michael Sandrof Jon Solomon",
|
||||
"Jan Peterson Helen Rose Paul Graham",
|
||||
"",
|
||||
"Thanks also goes to those persons not mentioned here who have added",
|
||||
"their advice, opinions, and code to IRC.",
|
||||
"Thanks also to those who provide the kind sys admins who let me and",
|
||||
"others continue to develop IRC.",
|
||||
"",
|
||||
"[$sumsserv] [$sumchan] [$sumsbsd] [$sumsuser]",
|
||||
"[$sumhash] [$sumsmisc] [$sumircd]",
|
||||
0,
|
||||
};
|
||||
!SUB!THIS!
|
||||
224
ircd/whowas.c
Normal file
224
ircd/whowas.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/************************************************************************
|
||||
* IRC - Internet Relay Chat, ircd/whowas.c
|
||||
* Copyright (C) 1990 Markku Savela
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/*
|
||||
* --- avalon --- 6th April 1992
|
||||
* rewritten to scrap linked lists and use a table of structures which
|
||||
* is referenced like a circular loop. Should be faster and more efficient.
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char sccsid[] = "@(#)whowas.c 2.16 08 Nov 1993 (C) 1988 Markku Savela";
|
||||
#endif
|
||||
|
||||
#include "struct.h"
|
||||
#include "common.h"
|
||||
#include "sys.h"
|
||||
#include "numeric.h"
|
||||
#include "whowas.h"
|
||||
#include "h.h"
|
||||
|
||||
static aName was[NICKNAMEHISTORYLENGTH];
|
||||
static int ww_index = 0;
|
||||
|
||||
void add_history(cptr)
|
||||
Reg1 aClient *cptr;
|
||||
{
|
||||
aName ntmp;
|
||||
Reg2 aName *np = &ntmp, *np2;
|
||||
|
||||
strncpyzt(np->ww_nick, cptr->name, NICKLEN+1);
|
||||
strncpyzt(np->ww_info, cptr->info, REALLEN+1);
|
||||
np->ww_user = cptr->user;
|
||||
np->ww_logout = now;
|
||||
np->ww_online = (cptr->from != NULL) ? cptr : NULL;
|
||||
np->ww_user->refcnt++;
|
||||
np->ww_server = (char *)MyMalloc(strlen(np->ww_user->server->name)+1);
|
||||
strcpy(np->ww_server, np->ww_user->server->name);
|
||||
|
||||
np2 = &was[ww_index];
|
||||
if (np2->ww_user)
|
||||
{
|
||||
free_user(np2->ww_user, np2->ww_online);
|
||||
MyFree(np2->ww_server);
|
||||
}
|
||||
|
||||
bcopy((char *)&ntmp, (char *)np2, sizeof(aName));
|
||||
|
||||
ww_index++;
|
||||
if (ww_index >= NICKNAMEHISTORYLENGTH)
|
||||
ww_index = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** get_history
|
||||
** Return the current client that was using the given
|
||||
** nickname within the timelimit. Returns NULL, if no
|
||||
** one found...
|
||||
*/
|
||||
aClient *get_history(nick, timelimit)
|
||||
char *nick;
|
||||
time_t timelimit;
|
||||
{
|
||||
Reg1 aName *wp, *wp2;
|
||||
Reg2 int i = 0;
|
||||
|
||||
if (ww_index == 0)
|
||||
wp = wp2 = &was[NICKNAMEHISTORYLENGTH - 1];
|
||||
else
|
||||
wp = wp2 = &was[ww_index - 1];
|
||||
timelimit = now-timelimit;
|
||||
|
||||
do {
|
||||
if (!mycmp(nick, wp->ww_nick) && wp->ww_logout >= timelimit)
|
||||
break;
|
||||
if (wp == was)
|
||||
{
|
||||
i = 1;
|
||||
wp = &was[NICKNAMEHISTORYLENGTH - 1];
|
||||
}
|
||||
else
|
||||
wp--;
|
||||
} while (wp != wp2);
|
||||
|
||||
if (wp != wp2 || !i)
|
||||
return (wp->ww_online);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void off_history(cptr)
|
||||
Reg3 aClient *cptr;
|
||||
{
|
||||
Reg1 aName *wp;
|
||||
Reg2 int i;
|
||||
|
||||
for (i = NICKNAMEHISTORYLENGTH, wp = was; i; wp++, i--)
|
||||
if (wp->ww_online == cptr)
|
||||
wp->ww_online = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
void initwhowas()
|
||||
{
|
||||
bzero((char *)was, NICKNAMEHISTORYLENGTH * sizeof(aName));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** m_whowas
|
||||
** parv[0] = sender prefix
|
||||
** parv[1] = nickname queried
|
||||
*/
|
||||
int m_whowas(cptr, sptr, parc, parv)
|
||||
aClient *cptr, *sptr;
|
||||
int parc;
|
||||
char *parv[];
|
||||
{
|
||||
Reg1 aName *wp, *wp2 = NULL;
|
||||
Reg2 int j = 0;
|
||||
Reg3 anUser *up = NULL;
|
||||
int max = -1;
|
||||
char *p, *nick, *s;
|
||||
|
||||
if (parc < 2)
|
||||
{
|
||||
sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN),
|
||||
me.name, parv[0]);
|
||||
return 0;
|
||||
}
|
||||
if (parc > 2)
|
||||
max = atoi(parv[2]);
|
||||
if (parc > 3)
|
||||
if (hunt_server(cptr,sptr,":%s WHOWAS %s %s :%s", 3,parc,parv))
|
||||
return 0;
|
||||
|
||||
for (s = parv[1]; (nick = strtoken(&p, s, ",")); s = NULL)
|
||||
{
|
||||
wp = wp2 = &was[ww_index - 1];
|
||||
|
||||
do {
|
||||
if (wp < was)
|
||||
wp = &was[NICKNAMEHISTORYLENGTH - 1];
|
||||
if (mycmp(nick, wp->ww_nick) == 0)
|
||||
{
|
||||
up = wp->ww_user;
|
||||
sendto_one(sptr, rpl_str(RPL_WHOWASUSER),
|
||||
me.name, parv[0], wp->ww_nick,
|
||||
up->username,
|
||||
up->host, wp->ww_info);
|
||||
sendto_one(sptr, rpl_str(RPL_WHOISSERVER),
|
||||
me.name, parv[0], wp->ww_nick,
|
||||
wp->ww_server,
|
||||
myctime(wp->ww_logout));
|
||||
if (up->away)
|
||||
sendto_one(sptr, rpl_str(RPL_AWAY),
|
||||
me.name, parv[0],
|
||||
wp->ww_nick, up->away);
|
||||
j++;
|
||||
}
|
||||
if (max > 0 && j >= max)
|
||||
break;
|
||||
wp--;
|
||||
} while (wp != wp2);
|
||||
|
||||
if (up == NULL)
|
||||
sendto_one(sptr, err_str(ERR_WASNOSUCHNICK),
|
||||
me.name, parv[0], nick);
|
||||
|
||||
up = NULL;
|
||||
if (p)
|
||||
p[-1] = ',';
|
||||
}
|
||||
sendto_one(sptr, rpl_str(RPL_ENDOFWHOWAS), me.name, parv[0], parv[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void count_whowas_memory(wwu, wwa, wwam)
|
||||
int *wwu, *wwa;
|
||||
u_long *wwam;
|
||||
{
|
||||
Reg1 anUser *tmp;
|
||||
Reg2 int i, j;
|
||||
int u = 0, a = 0;
|
||||
u_long am = 0;
|
||||
|
||||
for (i = 0; i < NICKNAMEHISTORYLENGTH; i++)
|
||||
if ((tmp = was[i].ww_user))
|
||||
if (!was[i].ww_online)
|
||||
{
|
||||
for (j = 0; j < i; j++)
|
||||
if (was[j].ww_user == tmp)
|
||||
break;
|
||||
if (j < i)
|
||||
continue;
|
||||
u++;
|
||||
if (tmp->away)
|
||||
{
|
||||
a++;
|
||||
am += (strlen(tmp->away)+1);
|
||||
}
|
||||
}
|
||||
*wwu = u;
|
||||
*wwa = a;
|
||||
*wwam = am;
|
||||
|
||||
return;
|
||||
}
|
||||
Reference in New Issue
Block a user