ChangeLog | 42 +++- NEWS | 22 ++- README | 4 +- configure.in | 20 +- contrib/Debian/changelog | 18 ++ contrib/MacOSX/config.h | 2 + contrib/MacOSX/ngIRCd.pmdoc/index.xml | 4 +- contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj | 2 +- contrib/ngircd.spec | 2 +- contrib/platformtest.sh | 2 +- doc/Platforms.txt | 16 +- doc/README-Interix.txt | 37 +++ doc/SSL.txt | 6 +- doc/sample-ngircd.conf | 10 +- man/ngircd.conf.5.tmpl | 9 + src/ngircd/client.c | 41 ++-- src/ngircd/conf.c | 131 ++++++---- src/ngircd/conf.h | 15 +- src/ngircd/conn.c | 327 ++++++++++++++++------- src/ngircd/conn.h | 8 +- src/ngircd/defines.h | 10 +- src/ngircd/irc-channel.c | 84 ++++-- src/ngircd/irc-info.c | 137 ++++++---- src/ngircd/irc-login.c | 27 ++- src/ngircd/irc-login.h | 3 +- src/ngircd/irc-mode.c | 3 +- src/ngircd/irc-oper.c | 21 +- src/ngircd/irc.c | 8 +- src/ngircd/log.c | 4 +- src/ngircd/messages.h | 6 +- src/ngircd/ngircd.c | 8 +- src/ngircd/parse.c | 3 +- src/ngircd/resolve.c | 10 +- 33 files changed, 723 insertions(+), 319 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9b38170..d40a2be 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,7 @@ ngIRCd - Next Generation IRC Server - (c)2001-2009 Alexander Barton, + (c)2001-2010 Alexander Barton, alex@barton.de, http://www.barton.de/ ngIRCd is free software and published under the @@ -10,6 +10,46 @@ -- ChangeLog -- +ngIRCd Release 16 (2010-05-02) + + - doc/SSL: remove line continuation marker + + ngIRCd 16~rc2 (2010-04-25) + - Updated some more copyright notices, it's 2010 already :-) + - Only compile in Get_Error() if really needed + - Fix gcc warning "ignoring return value of ..." + - Include netinet/in_systm.h alongside netinet/ip.h + - Include netinet/{in.h, in_systm.h} when checking for netinet/ip.h + - Only include if it exists + - Updated doc/Platforms.txt + - Enhace connection statistics counters: display total number of served + connections on daemon shutdown and when a new client connects using + the new numeric RPL_STATSCONN (250). + + ngIRCd 16~rc1 (2010-03-25) + - Various fixes to the build system and code cleanups. + - contrib/platformtest.sh: Only show latest commit. + - Updatet doc/Platforms.txt, added new README-Interix.txt documenting + how to tun ngIRCd on Microsoft Services for UNIX (MS SFU, MS SUA). + - Updated links to the ngIRCd homepage (bug tracker, mailing list). + - Added missing modes to USERMODES #define + - Show our name (IRCD=ngIRCd) in ISUPPORT (005) numeric + - Quote received messages of ERROR commands in log output. + - ngircd.conf manual page: document missing "Password" variable. + - Implement WEBIRC command used by some Web-IRC frontends. The password + required to secure this command must be configured using the new + "WebircPassword" variable in the ngircd.conf file. + - Don't use port 6668 as example for both "Ports" and "SSLPorts". + - Remove limit on max number of configured irc operators. + - Only link "nsl" library when really needed. + - A new channel mode "secure connections only" (+z) has been implemented: + Only clients using a SSL encrypted connection to the server are allowed + to join such a channel. + But please note three things: a) already joined clients are not checked + when setting this mode, b) IRC operators are always allowed to join + every channel, and c) remote clients using a server not supporting this + mode are not checked either and therefore always allowed to join. + ngIRCd Release 15 (2009-11-07) - "ngircd --configtest": print SSL configuration options even when unset. diff --git a/NEWS b/NEWS index 5a0a9dd..3d81baf 100644 --- a/NEWS +++ b/NEWS @@ -1,7 +1,7 @@ ngIRCd - Next Generation IRC Server - (c)2001-2009 Alexander Barton, + (c)2001-2010 Alexander Barton, alex@barton.de, http://www.barton.de/ ngIRCd is free software and published under the @@ -10,6 +10,26 @@ -- NEWS -- +ngIRCd Release 16 (2010-05-02) + + ngIRCd 16~rc2 (2010-04-25) + - Enhace connection statistics counters: display total number of served + connections on daemon shutdown and when a new client connects using + the new numeric RPL_STATSCONN (250). + + ngIRCd 16~rc1 (2010-03-25) + - Implement WEBIRC command used by some Web-IRC frontends. The password + required to secure this command must be configured using the new + "WebircPassword" variable in the ngircd.conf file. + - Remove limit on max number of configured irc operators. + - A new channel mode "secure connections only" (+z) has been implemented: + Only clients using a SSL encrypted connection to the server are allowed + to join such a channel. + But please note three things: a) already joined clients are not checked + when setting this mode, b) IRC operators are always allowed to join + every channel, and c) remote clients using a server not supporting this + mode are not checked either and therefore always allowed to join. + ngIRCd Release 15 (2009-11-07) ngIRCd 15~rc1 (2009-10-15) diff --git a/README b/README index 2eff7bc..dc11a9f 100644 --- a/README +++ b/README @@ -78,10 +78,10 @@ VI. Bugs If you find bugs in the ngIRCd (which might be there :-), please report them at the following URL: - + There you can read about known bugs and limitations, too. If you have critics, patches or something else, please feel free to post a mail to the ngIRCd mailing list: (please see - for details). + for details). diff --git a/configure.in b/configure.in index 3d4c640..6d9312d 100644 --- a/configure.in +++ b/configure.in @@ -12,7 +12,7 @@ # -- Initialisation -- AC_PREREQ(2.50) -AC_INIT(ngircd, 15) +AC_INIT(ngircd, 16) AC_CONFIG_SRCDIR(src/ngircd/ngircd.c) AC_CANONICAL_TARGET AM_INIT_AUTOMAKE(1.6) @@ -101,11 +101,19 @@ AC_HEADER_TIME AC_HEADER_SYS_WAIT AC_CHECK_HEADERS([ \ - ctype.h errno.h fcntl.h netdb.h netinet/in.h stdlib.h string.h \ - strings.h sys/socket.h sys/time.h unistd.h \ + ctype.h errno.h fcntl.h netdb.h netinet/in.h netinet/in_systm.h \ + stdlib.h string.h strings.h sys/socket.h sys/time.h unistd.h \ ],,AC_MSG_ERROR([required C header missing!])) -AC_CHECK_HEADERS([arpa/inet.h ctype.h malloc.h stdbool.h stddef.h varargs.h]) +AC_CHECK_HEADERS([ \ + arpa/inet.h ctype.h malloc.h netinet/ip.h stdbool.h stddef.h varargs.h \ + ],[],[],[[ + #include + #ifdef HAVE_NETINET_IN_SYSTM_H + #include + #endif + ]] +) # -- Datatypes -- @@ -130,9 +138,11 @@ AC_CHECK_MEMBER([struct sockaddr_in.sin_len], AC_DEFINE(HAVE_sockaddr_in_len),, # -- Libraries -- +# A/UX needs this. AC_CHECK_LIB(UTIL,memmove) +# needed on solaris. GNU libc also has a libnsl, but we do not need it. +AC_SEARCH_LIBS(gethostbyname,nsl) AC_CHECK_LIB(socket,bind) -AC_CHECK_LIB(nsl,gethostent) # -- Functions -- diff --git a/contrib/Debian/changelog b/contrib/Debian/changelog index 0f76b3d..a337686 100644 --- a/contrib/Debian/changelog +++ b/contrib/Debian/changelog @@ -1,3 +1,21 @@ +ngircd (16-0ab1) unstable; urgency=low + + * New "upstream" release: ngIRCd 16. + + -- Alexander Barton Sun, 02 May 2010 13:32:41 +0200 + +ngircd (16~rc2-0ab1) unstable; urgency=low + + * New "upstream" release candidate 2 for ngIRCd Release 16. + + -- Alexander Barton Sun, 25 Apr 2010 13:12:42 +0200 + +ngircd (16~rc1-0ab1) unstable; urgency=low + + * New "upstream" release candidate 1 for ngIRCd Release 16. + + -- Alexander Barton Thu, 25 Mar 2010 15:56:03 +0200 + ngircd (15-0ab1) unstable; urgency=low * New "upstream" release: ngIRCd 15. diff --git a/contrib/MacOSX/config.h b/contrib/MacOSX/config.h index 60b0618..66465e2 100644 --- a/contrib/MacOSX/config.h +++ b/contrib/MacOSX/config.h @@ -71,6 +71,8 @@ #define HAVE_STDBOOL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_ARPA_INET_H 1 +/* Define to 1 if you have the header file. */ +#define HAVE_NETINET_IP_H 1 /* Define to 1 if you have the `kqueue' function. */ #define HAVE_KQUEUE 1 diff --git a/contrib/MacOSX/ngIRCd.pmdoc/index.xml b/contrib/MacOSX/ngIRCd.pmdoc/index.xml index 2881d58..5d6b8e3 100644 --- a/contrib/MacOSX/ngIRCd.pmdoc/index.xml +++ b/contrib/MacOSX/ngIRCd.pmdoc/index.xml @@ -4,7 +4,7 @@ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\qc\pardirnatural \f0\i\fs24 \cf0 ngIRCd -- The Next Generation IRC Daemon\ -Copyright (c)2001-2009 Alexander Barton and Contributors.\ +Copyright (c)2001-2010 Alexander Barton and Contributors.\ \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural \i0 \cf0 \ @@ -187,4 +187,4 @@ To disable automatic starting of ngIRCd, use this command:\ \ls2\ilvl0 \f1\fs24 \cf0 sudo launchctl unload -w \\\ /Library/LaunchDaemons/de.barton.ngircd.plist\ -}]]>01ngircd.xml02de.xmlproperties.customizeOptionproperties.titledescriptionproperties.anywhereDomainproperties.systemDomain \ No newline at end of file +}]]>01ngircd.xml02de.xmlproperties.customizeOptionproperties.titledescriptionproperties.anywhereDomainproperties.systemDomain diff --git a/contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj b/contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj index a7cc74f..3d9dfe7 100644 --- a/contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj +++ b/contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj @@ -758,7 +758,7 @@ GCC_WARN_SHADOW = YES; GCC_WARN_SIGN_COMPARE = YES; GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNINITIALIZED_AUTOS = NO; GCC_WARN_UNKNOWN_PRAGMAS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_LABEL = YES; diff --git a/contrib/ngircd.spec b/contrib/ngircd.spec index bce620a..4ecc152 100644 --- a/contrib/ngircd.spec +++ b/contrib/ngircd.spec @@ -1,5 +1,5 @@ %define name ngircd -%define version 15 +%define version 16 %define release 1 %define prefix %{_prefix} diff --git a/contrib/platformtest.sh b/contrib/platformtest.sh index aee7f29..0a518b8 100755 --- a/contrib/platformtest.sh +++ b/contrib/platformtest.sh @@ -105,7 +105,7 @@ fi # Get ngIRCd version information if [ -d ".git" ]; then VERSION=`git log --abbrev-commit --pretty=oneline HEAD~1.. \ - | cut -d' ' -f1 | tr -d '.'` + | head -1 | cut -d' ' -f1 | tr -d '.'` elif [ -r "Makefile" ]; then eval $(grep "^VERSION = " Makefile | sed -e 's/ //g') fi diff --git a/doc/Platforms.txt b/doc/Platforms.txt index 8a1282e..7a6e3a8 100644 --- a/doc/Platforms.txt +++ b/doc/Platforms.txt @@ -1,7 +1,7 @@ ngIRCd - Next Generation IRC Server - (c)2001-2009 Alexander Barton + (c)2001-2010 Alexander Barton alex@barton.de, http://www.barton.de/ ngIRCd is free software and published under the @@ -32,22 +32,25 @@ hppa1.1/unknown/linux-gnu gcc 3.3.3 0.8.0 04-05-30 alex Y Y Y Y hppa2.0/unknown/linux-gnu gcc 3.3.5 13~rc1 08-12-02 alex Y Y Y Y hppa2.0w-hp-hpux11.11 gcc 4.2.3 14.1 09-07-22 goetz Y Y Y Y i386/apple/darwin9.7.0 gcc 4.0.1 14.1 09-08-04 alex Y Y Y Y (3) -i386/apple/darwin10.0.0b2 gcc 4.2.1 14.1 09-07-27 alex Y Y Y Y (3) +i386/apple/darwin10.3.0 gcc 4.2.1 16 10-04-23 alex Y Y Y Y (3) i386/pc/solaris2.9 gcc 3.2.2 CVSHEAD 04-02-24 alex Y Y Y Y i386/pc/solaris2.11 gcc 3.4.3 14.1 09-08-03 alex Y Y Y Y (4) i386/unknown/freebsd5.2.1 gcc 3.3.3 0.8.0 04-05-30 alex Y Y Y Y i386/unknown/freebsd6.0 gcc 3.4.4 0.10.0-p1 06-08-04 alex Y Y Y Y (3) i386/unknown/freebsd6.1 gcc 3.4.4 CVSHEAD 06-05-07 fw Y Y Y Y (3) -i386/unknown/freebsd6.2 gcc 3.4.6 14.1 09-07-27 alex Y Y Y Y (3) +i386/unknown/freebsd6.2 gcc 3.4.6 16 10-04-11 alex Y Y Y Y (3) i386/unknown/freebsd7.0 gcc 4.2.1 14.1 09-07-28 alex Y Y Y Y (3) i386/unknown/freebsd7.2 gcc 4.2.1 14.1 09-08-03 alex Y Y Y Y (3) +i386/unknown/freebsd7.3 gcc 4.2.1 16 10-04-11 alex Y Y Y Y (3) i386/unknown/gnu0.3 gcc 3.3.3 0.8.0 04-05-30 alex Y Y n Y i686/unknown/gnu0.3 gcc 4.3.1 14.1 09-07-28 alex Y Y Y Y +i686/unkn./kfreebsd7.2-gnu gcc 4.3.4 15 09-12-02 alex Y Y Y Y (3) i386/unknown/netbsdelf1.6.1 gcc 2.95.3 CVSHEAD 04-02-24 alex Y Y Y Y i386/unknown/netbsdelf3.0.1 gcc 3.3.3 0.10.0-p1 06-08-30 alex Y Y Y Y (3) -i386/unknown/netbsdelf4.0 gcc 4.1.2 14.1 09-07-28 alex Y Y Y Y (3) +i386/unknown/netbsdelf4.0 gcc 4.1.2 16 10-04-11 alex Y Y Y Y (3) i386/unknown/openbsd3.9 gcc 3.3.5 0.10.0-p1 06-08-30 alex Y Y Y Y (3) -i386/unknown/openbsd4.1 gcc 3.3.5 14.1 09-07-28 alex Y Y Y Y (3) +i386/unknown/openbsd4.1 gcc 3.3.5 16 10-04-11 alex Y Y Y Y (3) +i586/pc/interix3.5 gcc 3.3 15 10-01-22 alex Y Y N Y i686/pc/cygwin gcc 3.3.1 0.8.0 04-05-30 alex Y Y n Y i686/pc/linux-gnu gcc 2.95.4 0.8.0 04-05-30 alex Y Y Y Y (1) i686/pc/linux-gnu gcc 3.3.5 14.1 09-08-04 alex Y Y Y Y (1) @@ -65,7 +68,8 @@ powerpc/unknown/openbsd3.6 gcc 2.95.3 0.10.0 06-10-08 alex Y Y n Y sparc/sun/solaris2.6 gcc 2.95.3 0.7.x-CVS 03-04-22 alex Y Y Y Y sparc/sun/solaris2.7 gcc 3.3 0.8.0 04-05-30 alex Y Y Y Y sparc/unkn./netbsdelf1.6.1 gcc 2.95.3 0.8.0 04-05-30 alex Y Y Y Y -x86_64/unknown/linux-gnu gcc 4.3.2 14.1 09-08-04 alex Y Y Y Y (1) +x86_64/unknown/freebsd8.0 gcc 4.2.1 16 10-04-23 alex Y Y Y Y (3) +x86_64/unknown/linux-gnu gcc 4.3.2 16 10-04-23 alex Y Y Y Y (1) Notes diff --git a/doc/README-Interix.txt b/doc/README-Interix.txt new file mode 100644 index 0000000..8f5451f --- /dev/null +++ b/doc/README-Interix.txt @@ -0,0 +1,37 @@ + + ngIRCd - Next Generation IRC Server + + (c)2001-2010 Alexander Barton, + alex@barton.de, http://www.barton.de/ + + ngIRCd is free software and published under the + terms of the GNU General Public License. + + + -- README-Interix.txt -- + + +ngIRCd release 15 has successfully been tested on Microsoft Windows XP +Professional using the Services for UNIX (SFU) version 3.5 and Microsoft +Windows 7 with the bundled Subsystem for UNIX Applications (SUA). + +SFU are supported on Windows 2000, Windows 2000 Server, Windows XP, and +Windows Server 2003. SUA is supported on Windows Server 2003 R2, Windows +Server 2008 & 2008 R2, Windows Vista, and Windows 7 -- so ngIRCd should be +able to run on all of these platforms. + +But please note that the poll() API function is not fully implemented by +SFU/SUA and therefore can't be used by ngIRCd -- which normally would be +the default. Please see section +4.25 for details: + + "If you do try to use the poll() API your program will block on the + API call forever. You must direct your program to build using the + select() API." + +So when running the ./configure script, you HAVE TO DISABLE poll() support: + + ./configure --without-poll + +ngIRCd then defaults to using the select() API function which works fine. + diff --git a/doc/SSL.txt b/doc/SSL.txt index 7207f1b..394894a 100644 --- a/doc/SSL.txt +++ b/doc/SSL.txt @@ -49,8 +49,7 @@ Creating a self-signed certificate OpenSSL: Creating a self-signed certificate and key: - $ openssl req -newkey rsa:2048 -x509 -keyout server-key.pem \ - -out server-cert.pem -days 1461 + $ openssl req -newkey rsa:2048 -x509 -keyout server-key.pem -out server-cert.pem -days 1461 Create DH parameters (optional): $ openssl dhparam -2 -out dhparams.pem 2048 @@ -58,8 +57,7 @@ GnuTLS: Creating a self-signed certificate and key: $ certtool --generate-privkey --bits 2048 --outfile server-key.pem - $ certtool --generate-self-signed --load-privkey server-key.pem \ - --outfile server-cert.pem + $ certtool --generate-self-signed --load-privkey server-key.pem --outfile server-cert.pem Create DH parameters (optional): $ certtool --generate-dh-params --bits 2048 --outfile dhparams.pem diff --git a/doc/sample-ngircd.conf b/doc/sample-ngircd.conf index b945224..daa0801 100644 --- a/doc/sample-ngircd.conf +++ b/doc/sample-ngircd.conf @@ -28,9 +28,15 @@ # LINKS requests for example. Info = Server Info Text - # Global password for all users needed to connect to the server + # Global password for all users needed to connect to the server. + # (Default: not set) ;Password = abc + # Password required for using the WEBIRC command used by some + # Web-to-IRC gateways. If not set/empty, the WEBIRC command can't + # be used. (Default: not set) + ;WebircPassword = xyz + # Information about the server and the administrator, used by the # ADMIN command. Not required by server but by RFC! ;AdminInfo1 = Description @@ -42,7 +48,7 @@ ;Ports = 6667, 6668, 6669 # Additional Listen Ports that expect SSL/TLS encrypted connections - ;SSLPorts = 9999,6668 + ;SSLPorts = 6697, 9999 # SSL Server Key ;SSLKeyFile = /usr/local/etc/ngircd/ssl/server-key.pem diff --git a/man/ngircd.conf.5.tmpl b/man/ngircd.conf.5.tmpl index d9e6f46..46e0308 100644 --- a/man/ngircd.conf.5.tmpl +++ b/man/ngircd.conf.5.tmpl @@ -69,6 +69,15 @@ IRC network and must contain at least one dot (".") character. Info text of the server. This will be shown by WHOIS and LINKS requests for example. .TP +\fBPassword\fR +Global password for all users needed to connect to the server. The default +is empty, so no password is required. +.TP +\fBWebircPassword\fR +Password required for using the WEBIRC command used by some Web-to-IRC +gateways. If not set or empty, the WEBIRC command can't be used. +Default: not set. +.TP \fBAdminInfo1\fR, \fBAdminInfo2\fR, \fBAdminEMail\fR Information about the server and the administrator, used by the ADMIN command. diff --git a/src/ngircd/client.c b/src/ngircd/client.c index 1edc755..c565830 100644 --- a/src/ngircd/client.c +++ b/src/ngircd/client.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2008 Alexander Barton (alex@barton.de) + * Copyright (c)2001-2010 Alexander Barton (alex@barton.de) * * 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 @@ -181,39 +181,46 @@ Client_NewRemoteUser(CLIENT *Introducer, const char *Nick, int Hops, const char */ static CLIENT * Init_New_Client(CONN_ID Idx, CLIENT *Introducer, CLIENT *TopServer, - int Type, const char *ID, const char *User, const char *Hostname, const char *Info, int Hops, - int Token, const char *Modes, bool Idented) + int Type, const char *ID, const char *User, const char *Hostname, + const char *Info, int Hops, int Token, const char *Modes, bool Idented) { CLIENT *client; - assert( Idx >= NONE ); - assert( Introducer != NULL ); - assert( Hostname != NULL ); + assert(Idx >= NONE); + assert(Introducer != NULL); + assert(Hostname != NULL); - client = New_Client_Struct( ); - if( ! client ) return NULL; + client = New_Client_Struct(); + if (!client) + return NULL; client->starttime = time(NULL); client->conn_id = Idx; client->introducer = Introducer; client->topserver = TopServer; client->type = Type; - if( ID ) Client_SetID( client, ID ); - if( User ) Client_SetUser( client, User, Idented ); - if( Hostname ) Client_SetHostname( client, Hostname ); - if( Info ) Client_SetInfo( client, Info ); + if (ID) + Client_SetID(client, ID); + if (User) + Client_SetUser(client, User, Idented); + if (Hostname) + Client_SetHostname(client, Hostname); + if (Info) + Client_SetInfo(client, Info); client->hops = Hops; client->token = Token; - if( Modes ) Client_SetModes( client, Modes ); - if( Type == CLIENT_SERVER ) Generate_MyToken( client ); + if (Modes) + Client_SetModes(client, Modes); + if (Type == CLIENT_SERVER) + Generate_MyToken(client); - if( strchr( client->modes, 'a' )) - strlcpy( client->away, DEFAULT_AWAY_MSG, sizeof( client->away )); + if (strchr(client->modes, 'a')) + strlcpy(client->away, DEFAULT_AWAY_MSG, sizeof(client->away)); client->next = (POINTER *)My_Clients; My_Clients = client; - Adjust_Counters( client ); + Adjust_Counters(client); return client; } /* Init_New_Client */ diff --git a/src/ngircd/conf.c b/src/ngircd/conf.c index 2b592b1..694b5d4 100644 --- a/src/ngircd/conf.c +++ b/src/ngircd/conf.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2009 Alexander Barton (alex@barton.de) + * Copyright (c)2001-2010 Alexander Barton (alex@barton.de) * * 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 @@ -55,6 +55,7 @@ static bool Use_Log = true; static CONF_SERVER New_Server; static int New_Server_Idx; +static size_t Conf_Oper_Count; static size_t Conf_Channel_Count; static void Set_Defaults PARAMS(( bool InitServers )); static bool Read_Config PARAMS(( bool ngircd_starting )); @@ -226,6 +227,41 @@ yesno_to_str(int boolean_value) } +static void +opers_free(void) +{ + struct Conf_Oper *op; + size_t len; + + len = array_length(&Conf_Opers, sizeof(*op)); + op = array_start(&Conf_Opers); + while (len--) { + free(op->mask); + op++; + } + array_free(&Conf_Opers); +} + +static void +opers_puts(void) +{ + struct Conf_Oper *op; + size_t len; + + len = array_length(&Conf_Opers, sizeof(*op)); + op = array_start(&Conf_Opers); + while (len--) { + assert(op->name[0]); + + puts("[OPERATOR]"); + printf(" Name = %s\n", op->name); + printf(" Password = %s\n", op->pwd); + printf(" Mask = %s\n\n", op->mask ? op->mask : ""); + op++; + } +} + + GLOBAL int Conf_Test( void ) { @@ -255,16 +291,17 @@ Conf_Test( void ) } puts( "[GLOBAL]" ); - printf( " Name = %s\n", Conf_ServerName ); - printf( " Info = %s\n", Conf_ServerInfo ); - printf( " Password = %s\n", Conf_ServerPwd ); - printf( " AdminInfo1 = %s\n", Conf_ServerAdmin1 ); - printf( " AdminInfo2 = %s\n", Conf_ServerAdmin2 ); - printf( " AdminEMail = %s\n", Conf_ServerAdminMail ); - printf( " MotdFile = %s\n", Conf_MotdFile ); - printf( " MotdPhrase = %s\n", Conf_MotdPhrase ); - printf( " ChrootDir = %s\n", Conf_Chroot ); - printf( " PidFile = %s\n", Conf_PidFile); + printf(" Name = %s\n", Conf_ServerName); + printf(" Info = %s\n", Conf_ServerInfo); + printf(" Password = %s\n", Conf_ServerPwd); + printf(" WebircPassword = %s\n", Conf_WebircPwd); + printf(" AdminInfo1 = %s\n", Conf_ServerAdmin1); + printf(" AdminInfo2 = %s\n", Conf_ServerAdmin2); + printf(" AdminEMail = %s\n", Conf_ServerAdminMail); + printf(" MotdFile = %s\n", Conf_MotdFile); + printf(" MotdPhrase = %s\n", Conf_MotdPhrase); + printf(" ChrootDir = %s\n", Conf_Chroot); + printf(" PidFile = %s\n", Conf_PidFile); printf(" Listen = %s\n", Conf_ListenAddress); fputs(" Ports = ", stdout); ports_puts(&Conf_ListenPorts); @@ -304,16 +341,7 @@ Conf_Test( void ) printf(" MaxJoins = %d\n", Conf_MaxJoins > 0 ? Conf_MaxJoins : -1); printf(" MaxNickLength = %u\n\n", Conf_MaxNickLength - 1); - for( i = 0; i < Conf_Oper_Count; i++ ) { - if( ! Conf_Oper[i].name[0] ) continue; - - /* Valid "Operator" section */ - puts( "[OPERATOR]" ); - printf( " Name = %s\n", Conf_Oper[i].name ); - printf( " Password = %s\n", Conf_Oper[i].pwd ); - if ( Conf_Oper[i].mask ) printf( " Mask = %s\n", Conf_Oper[i].mask ); - puts( "" ); - } + opers_puts(); for( i = 0; i < MAX_SERVERS; i++ ) { if( ! Conf_Server[i].name[0] ) continue; @@ -609,6 +637,7 @@ Read_Config( bool ngircd_starting ) exit( 1 ); } + opers_free(); Set_Defaults( ngircd_starting ); Config_Error( LOG_INFO, "Reading configuration from \"%s\" ...", NGIRCd_ConfFile ); @@ -667,21 +696,6 @@ Read_Config( bool ngircd_starting ) if( strcasecmp( section, "[GLOBAL]" ) == 0 ) continue; - if( strcasecmp( section, "[OPERATOR]" ) == 0 ) { - if( Conf_Oper_Count + 1 > MAX_OPERATORS ) - Config_Error( LOG_ERR, "Too many operators configured."); - else { - /* Initialize new operator structure */ - Conf_Oper[Conf_Oper_Count].name[0] = '\0'; - Conf_Oper[Conf_Oper_Count].pwd[0] = '\0'; - if (Conf_Oper[Conf_Oper_Count].mask) { - free(Conf_Oper[Conf_Oper_Count].mask ); - Conf_Oper[Conf_Oper_Count].mask = NULL; - } - Conf_Oper_Count++; - } - continue; - } if( strcasecmp( section, "[SERVER]" ) == 0 ) { /* Check if there is already a server to add */ if( New_Server.name[0] ) { @@ -710,6 +724,10 @@ Read_Config( bool ngircd_starting ) Conf_Channel_Count++; continue; } + if (strcasecmp(section, "[OPERATOR]") == 0) { + Conf_Oper_Count++; + continue; + } Config_Error( LOG_ERR, "%s, line %d: Unknown section \"%s\"!", NGIRCd_ConfFile, line, section ); section[0] = 0x1; @@ -828,6 +846,13 @@ Handle_GLOBAL( int Line, char *Var, char *Arg ) Config_Error_TooLong( Line, Var ); return; } + if (strcasecmp(Var, "WebircPassword") == 0) { + /* Password required for WEBIRC command */ + len = strlcpy(Conf_WebircPwd, Arg, sizeof(Conf_WebircPwd)); + if (len >= sizeof(Conf_WebircPwd)) + Config_Error_TooLong(Line, Var); + return; + } if( strcasecmp( Var, "AdminInfo1" ) == 0 ) { /* Administrative info #1 */ len = strlcpy( Conf_ServerAdmin1, Arg, sizeof( Conf_ServerAdmin1 )); @@ -1081,36 +1106,38 @@ Handle_GLOBAL( int Line, char *Var, char *Arg ) static void Handle_OPERATOR( int Line, char *Var, char *Arg ) { - unsigned int opercount; size_t len; + struct Conf_Oper *op; + assert( Line > 0 ); assert( Var != NULL ); assert( Arg != NULL ); assert( Conf_Oper_Count > 0 ); - if ( Conf_Oper_Count == 0 ) + op = array_alloc(&Conf_Opers, sizeof(*op), Conf_Oper_Count - 1); + if (!op) { + Config_Error(LOG_ERR, "Could not allocate memory for operator (%d:%s = %s)", Line, Var, Arg); return; + } - opercount = Conf_Oper_Count - 1; - - if( strcasecmp( Var, "Name" ) == 0 ) { + if (strcasecmp(Var, "Name") == 0) { /* Name of IRC operator */ - len = strlcpy( Conf_Oper[opercount].name, Arg, sizeof( Conf_Oper[opercount].name )); - if (len >= sizeof( Conf_Oper[opercount].name )) - Config_Error_TooLong( Line, Var ); + len = strlcpy(op->name, Arg, sizeof(op->name)); + if (len >= sizeof(op->name)) + Config_Error_TooLong(Line, Var); return; } - if( strcasecmp( Var, "Password" ) == 0 ) { + if (strcasecmp(Var, "Password") == 0) { /* Password of IRC operator */ - len = strlcpy( Conf_Oper[opercount].pwd, Arg, sizeof( Conf_Oper[opercount].pwd )); - if (len >= sizeof( Conf_Oper[opercount].pwd )) - Config_Error_TooLong( Line, Var ); + len = strlcpy(op->pwd, Arg, sizeof(op->pwd)); + if (len >= sizeof(op->pwd)) + Config_Error_TooLong(Line, Var); return; } - if( strcasecmp( Var, "Mask" ) == 0 ) { - if (Conf_Oper[opercount].mask) return; /* Hostname already configured */ - - Conf_Oper[opercount].mask = strdup_warn( Arg ); + if (strcasecmp(Var, "Mask") == 0) { + if (op->mask) + return; /* Hostname already configured */ + op->mask = strdup_warn( Arg ); return; } Config_Error( LOG_ERR, "%s, line %d (section \"Operator\"): Unknown variable \"%s\"!", diff --git a/src/ngircd/conf.h b/src/ngircd/conf.h index 2308e4c..5764d0f 100644 --- a/src/ngircd/conf.h +++ b/src/ngircd/conf.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2008 Alexander Barton (alex@barton.de) + * Copyright (c)2001-2010 Alexander Barton (alex@barton.de) * * 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 @@ -26,12 +26,11 @@ #include "conf-ssl.h" -typedef struct _Conf_Oper -{ +struct Conf_Oper { char name[CLIENT_PASS_LEN]; /* Name (ID) of IRC operator */ char pwd[CLIENT_PASS_LEN]; /* Password */ - char *mask; -} CONF_OPER; + char *mask; /* allowed host mask */ +}; typedef struct _Conf_Server { @@ -125,8 +124,7 @@ GLOBAL int Conf_PongTimeout; GLOBAL int Conf_ConnectRetry; /* Operators */ -GLOBAL CONF_OPER Conf_Oper[MAX_OPERATORS]; -GLOBAL unsigned int Conf_Oper_Count; +GLOBAL array Conf_Opers; /* Servers */ GLOBAL CONF_SERVER Conf_Server[MAX_SERVERS]; @@ -190,6 +188,9 @@ GLOBAL bool Conf_AddServer PARAMS(( const char *Name, UINT16 Port, const char *H GLOBAL bool Conf_IsService PARAMS((int ConfServer, const char *Nick)); +/* Password required by WEBIRC command */ +GLOBAL char Conf_WebircPwd[CLIENT_PASS_LEN]; + #endif diff --git a/src/ngircd/conn.c b/src/ngircd/conn.c index 731647d..4367754 100644 --- a/src/ngircd/conn.c +++ b/src/ngircd/conn.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2009 Alexander Barton (alex@barton.de) + * Copyright (c)2001-2010 Alexander Barton * * 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 @@ -37,6 +37,9 @@ #include #ifdef HAVE_NETINET_IP_H +# ifdef HAVE_NETINET_IN_SYSTM_H +# include +# endif # include #endif @@ -92,10 +95,12 @@ static bool Init_Socket PARAMS(( int Sock )); static void New_Server PARAMS(( int Server, ng_ipaddr_t *dest )); static void Simple_Message PARAMS(( int Sock, const char *Msg )); static int NewListener PARAMS(( const char *listen_addr, UINT16 Port )); +static void Account_Connection PARAMS((void)); + static array My_Listeners; static array My_ConnArray; -static size_t NumConnections; +static size_t NumConnections, NumConnectionsMax, NumConnectionsAccepted; #ifdef TCPWRAP int allow_severity = LOG_INFO; @@ -109,37 +114,51 @@ extern struct SSLOptions Conf_SSLOptions; static void cb_connserver_login_ssl PARAMS((int sock, short what)); static void cb_clientserver_ssl PARAMS((int sock, short what)); #endif -static void cb_Read_Resolver_Result PARAMS(( int sock, UNUSED short what)); -static void cb_Connect_to_Server PARAMS(( int sock, UNUSED short what)); +static void cb_Read_Resolver_Result PARAMS((int sock, UNUSED short what)); +static void cb_Connect_to_Server PARAMS((int sock, UNUSED short what)); static void cb_clientserver PARAMS((int sock, short what)); + +/** + * IO callback for listening sockets: handle new connections. This callback + * gets called when a new non-SSL connection should be accepted. + * @param sock Socket descriptor + * @param irrelevant (ignored IO specification) + */ static void cb_listen(int sock, short irrelevant) { (void) irrelevant; - if (New_Connection( sock ) >= 0) - NumConnections++; - LogDebug("Total number of connections now %ld.", NumConnections); + (void) New_Connection(sock); } #ifdef SSL_SUPPORT +/** + * IO callback for listening SSL sockets: handle new connections. This callback + * gets called when a new SSL-enabled connection should be accepted. + * @param sock Socket descriptor + * @param irrelevant (ignored IO specification) + */ static void cb_listen_ssl(int sock, short irrelevant) { int fd; + (void) irrelevant; fd = New_Connection(sock); if (fd < 0) return; - - NumConnections++; - LogDebug("Total number of connections now %ld.", NumConnections); io_event_setcb(My_Connections[fd].sock, cb_clientserver_ssl); } #endif +/** + * IO callback for new outgoing non-SSL server connections. + * @param sock Socket descriptor + * @param what IO specification (IO_WANTREAD/IO_WANTWRITE/...) + */ static void cb_connserver(int sock, UNUSED short what) { @@ -213,6 +232,10 @@ cb_connserver(int sock, UNUSED short what) } +/** + * Login to a remote server. + * @param idx Connection index + */ static void server_login(CONN_ID idx) { @@ -229,6 +252,11 @@ server_login(CONN_ID idx) #ifdef SSL_SUPPORT +/** + * IO callback for new outgoing SSL-enabled server connections. + * @param sock Socket descriptor + * @param what IO specification (IO_WANTREAD/IO_WANTWRITE/...) + */ static void cb_connserver_login_ssl(int sock, short unused) { @@ -258,6 +286,11 @@ cb_connserver_login_ssl(int sock, short unused) #endif +/** + * IO callback for established non-SSL client and server connections. + * @param sock Socket descriptor + * @param what IO specification (IO_WANTREAD/IO_WANTWRITE/...) + */ static void cb_clientserver(int sock, short what) { @@ -270,18 +303,27 @@ cb_clientserver(int sock, short what) return; } #ifdef SSL_SUPPORT - if (what & IO_WANTREAD || (Conn_OPTION_ISSET(&My_Connections[idx], CONN_SSL_WANT_WRITE))) - Read_Request( idx ); /* if TLS layer needs to write additional data, call Read_Request instead so SSL/TLS can continue */ + if (what & IO_WANTREAD + || (Conn_OPTION_ISSET(&My_Connections[idx], CONN_SSL_WANT_WRITE))) { + /* if TLS layer needs to write additional data, call + * Read_Request() instead so that SSL/TLS can continue */ + Read_Request(idx); + } #else if (what & IO_WANTREAD) - Read_Request( idx ); + Read_Request(idx); #endif if (what & IO_WANTWRITE) - Handle_Write( idx ); + Handle_Write(idx); } #ifdef SSL_SUPPORT +/** + * IO callback for established SSL-enabled client and server connections. + * @param sock Socket descriptor + * @param what IO specification (IO_WANTREAD/IO_WANTWRITE/...) + */ static void cb_clientserver_ssl(int sock, short what) { @@ -295,11 +337,13 @@ cb_clientserver_ssl(int sock, short what) } switch (ConnSSL_Accept(&My_Connections[idx])) { - case 1: break; /* OK */ - case 0: return; /* EAGAIN: this callback will be invoked again by the io layer */ - default: - Conn_Close( idx, "Socket closed!", "SSL accept error", false ); - return; + case 1: + break; /* OK */ + case 0: + return; /* EAGAIN: callback will be invoked again by IO layer */ + default: + Conn_Close(idx, "Socket closed!", "SSL accept error", false); + return; } if (what & IO_WANTREAD) Read_Request(idx); @@ -312,6 +356,9 @@ cb_clientserver_ssl(int sock, short what) #endif +/** + * Initialite connecion module. + */ GLOBAL void Conn_Init( void ) { @@ -324,8 +371,8 @@ Conn_Init( void ) Pool_Size = Conf_MaxConnections; if (!array_alloc(&My_ConnArray, sizeof(CONNECTION), (size_t)Pool_Size)) { - Log( LOG_EMERG, "Can't allocate memory! [Conn_Init]" ); - exit( 1 ); + Log(LOG_EMERG, "Can't allocate memory! [Conn_Init]"); + exit(1); } /* FIXME: My_Connetions/Pool_Size is needed by other parts of the @@ -333,20 +380,21 @@ Conn_Init( void ) My_Connections = (CONNECTION*) array_start(&My_ConnArray); LogDebug("Allocated connection pool for %d items (%ld bytes).", - array_length(&My_ConnArray, sizeof( CONNECTION )), array_bytes(&My_ConnArray)); + array_length(&My_ConnArray, sizeof(CONNECTION)), + array_bytes(&My_ConnArray)); - assert( array_length(&My_ConnArray, sizeof( CONNECTION )) >= (size_t) Pool_Size); + assert(array_length(&My_ConnArray, sizeof(CONNECTION)) >= (size_t)Pool_Size); array_free( &My_Listeners ); - /* Connection-Struktur initialisieren */ - for( i = 0; i < Pool_Size; i++ ) Init_Conn_Struct( i ); - - /* Global write counter */ - WCounter = 0; + for (i = 0; i < Pool_Size; i++) + Init_Conn_Struct(i); } /* Conn_Init */ +/** + * Clean up connection module. + */ GLOBAL void Conn_Exit( void ) { @@ -399,6 +447,10 @@ ports_initlisteners(array *a, const char *listen_addr, void (*func)(int,short)) } +/** + * Initialize all listening sockets. + * @return Number of created listening sockets + */ GLOBAL unsigned int Conn_InitListeners( void ) { @@ -433,13 +485,12 @@ Conn_InitListeners( void ) listen_addr = strtok(NULL, ","); } - /* - * can't free() Conf_ListenAddress here. On /REHASH, if the config file + /* Can't free() Conf_ListenAddress here: on REHASH, if the config file * cannot be re-loaded, we'd end up with a NULL Conf_ListenAddress. * Instead, free() takes place in conf.c, before the config file - * is being parsed. - */ + * is being parsed. */ free(copy); + return created; } /* Conn_InitListeners */ @@ -582,6 +633,7 @@ NewListener(const char *listen_addr, UINT16 Port) return sock; } /* NewListener */ + #ifdef SSL_SUPPORT /* * SSL/TLS connections require extra treatment: @@ -1049,6 +1101,27 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie } /* Conn_Close */ +GLOBAL long +Conn_Count(void) +{ + return NumConnections; +} /* Conn_Count */ + + +GLOBAL long +Conn_CountMax(void) +{ + return NumConnectionsMax; +} /* Conn_CountMax */ + + +GLOBAL long +Conn_CountAccepted(void) +{ + return NumConnectionsAccepted; +} /* Conn_CountAccepted */ + + GLOBAL void Conn_SyncServerStruct( void ) { @@ -1163,12 +1236,14 @@ Count_Connections(ng_ipaddr_t *a) } /* Count_Connections */ +/** + * Initialize new client connection on a listening socket. + * @param Sock Listening socket descriptor + * @return Accepted socket descriptor or -1 on error + */ static int -New_Connection( int Sock ) +New_Connection(int Sock) { - /* Neue Client-Verbindung von Listen-Socket annehmen und - * CLIENT-Struktur anlegen. */ - #ifdef TCPWRAP struct request_info req; #endif @@ -1178,16 +1253,16 @@ New_Connection( int Sock ) CLIENT *c; long cnt; - assert( Sock > NONE ); - /* Connection auf Listen-Socket annehmen */ - new_sock_len = (int)sizeof(new_addr); + assert(Sock > NONE); + new_sock_len = (int)sizeof(new_addr); new_sock = accept(Sock, (struct sockaddr *)&new_addr, (socklen_t *)&new_sock_len); if (new_sock < 0) { Log(LOG_CRIT, "Can't accept connection: %s!", strerror(errno)); return -1; } + NumConnectionsAccepted++; if (!ng_ipaddr_tostr_r(&new_addr, ip_str)) { Log(LOG_CRIT, "fd %d: Can't convert IP address!", new_sock); @@ -1198,49 +1273,56 @@ New_Connection( int Sock ) #ifdef TCPWRAP /* Validate socket using TCP Wrappers */ - request_init( &req, RQ_DAEMON, PACKAGE_NAME, RQ_FILE, new_sock, RQ_CLIENT_SIN, &new_addr, NULL ); + request_init(&req, RQ_DAEMON, PACKAGE_NAME, RQ_FILE, new_sock, + RQ_CLIENT_SIN, &new_addr, NULL); fromhost(&req); if (!hosts_access(&req)) { - Log (deny_severity, "Refused connection from %s (by TCP Wrappers)!", ip_str); - Simple_Message( new_sock, "ERROR :Connection refused" ); - close( new_sock ); + Log(deny_severity, + "Refused connection from %s (by TCP Wrappers)!", ip_str); + Simple_Message(new_sock, "ERROR :Connection refused"); + close(new_sock); return -1; } #endif - /* Socket initialisieren */ - if (!Init_Socket( new_sock )) + if (!Init_Socket(new_sock)) + return -1; + + /* Check global connection limit */ + if ((Conf_MaxConnections > 0) && + (NumConnections >= (size_t) Conf_MaxConnections)) { + Log(LOG_ALERT, "Can't accept connection: limit (%d) reached!", + Conf_MaxConnections); + Simple_Message(new_sock, "ERROR :Connection limit reached"); + close(new_sock); return -1; + } /* Check IP-based connection limit */ cnt = Count_Connections(&new_addr); if ((Conf_MaxConnectionsIP > 0) && (cnt >= Conf_MaxConnectionsIP)) { /* Access denied, too many connections from this IP address! */ - Log( LOG_ERR, "Refused connection from %s: too may connections (%ld) from this IP address!", ip_str, cnt); - Simple_Message( new_sock, "ERROR :Connection refused, too many connections from your IP address!" ); - close( new_sock ); - return -1; - } - - if ((Conf_MaxConnections > 0) && - (NumConnections >= (size_t) Conf_MaxConnections)) - { - Log( LOG_ALERT, "Can't accept connection: limit (%d) reached!", Conf_MaxConnections); - Simple_Message( new_sock, "ERROR :Connection limit reached" ); - close( new_sock ); + Log(LOG_ERR, + "Refused connection from %s: too may connections (%ld) from this IP address!", + ip_str, cnt); + Simple_Message(new_sock, + "ERROR :Connection refused, too many connections from your IP address!"); + close(new_sock); return -1; } - if( new_sock >= Pool_Size ) { + if (new_sock >= Pool_Size) { if (!array_alloc(&My_ConnArray, sizeof(CONNECTION), - (size_t)new_sock)) { - Log( LOG_EMERG, "Can't allocate memory! [New_Connection]" ); - Simple_Message( new_sock, "ERROR: Internal error" ); - close( new_sock ); + (size_t) new_sock)) { + Log(LOG_EMERG, + "Can't allocate memory! [New_Connection]"); + Simple_Message(new_sock, "ERROR: Internal error"); + close(new_sock); return -1; } LogDebug("Bumped connection pool to %ld items (internal: %ld items, %ld bytes)", - new_sock, array_length(&My_ConnArray, sizeof(CONNECTION)), array_bytes(&My_ConnArray)); + new_sock, array_length(&My_ConnArray, + sizeof(CONNECTION)), array_bytes(&My_ConnArray)); /* Adjust pointer to new block */ My_Connections = array_start(&My_ConnArray); @@ -1249,22 +1331,24 @@ New_Connection( int Sock ) } /* register callback */ - if (!io_event_create( new_sock, IO_WANTREAD, cb_clientserver)) { - Log(LOG_ALERT, "Can't accept connection: io_event_create failed!"); + if (!io_event_create(new_sock, IO_WANTREAD, cb_clientserver)) { + Log(LOG_ALERT, + "Can't accept connection: io_event_create failed!"); Simple_Message(new_sock, "ERROR :Internal error"); close(new_sock); return -1; } - c = Client_NewLocal(new_sock, ip_str, CLIENT_UNKNOWN, false ); - if( ! c ) { - Log(LOG_ALERT, "Can't accept connection: can't create client structure!"); + c = Client_NewLocal(new_sock, ip_str, CLIENT_UNKNOWN, false); + if (!c) { + Log(LOG_ALERT, + "Can't accept connection: can't create client structure!"); Simple_Message(new_sock, "ERROR :Internal error"); io_close(new_sock); return -1; } - Init_Conn_Struct( new_sock ); + Init_Conn_Struct(new_sock); My_Connections[new_sock].sock = new_sock; My_Connections[new_sock].addr = new_addr; My_Connections[new_sock].client = c; @@ -1292,11 +1376,28 @@ New_Connection( int Sock ) if (!Conf_NoDNS) Resolve_Addr(&My_Connections[new_sock].res_stat, &new_addr, identsock, cb_Read_Resolver_Result); + + /* ngIRCd waits up to 4 seconds for the result of the asynchronous + * DNS and IDENT resolver subprocess using the "penalty" mechanism. + * If there are results earlier, the delay is aborted. */ Conn_SetPenalty(new_sock, 4); + + Account_Connection(); return new_sock; } /* New_Connection */ +static void +Account_Connection(void) +{ + NumConnections++; + if (NumConnections > NumConnectionsMax) + NumConnectionsMax = NumConnections; + LogDebug("Total number of connections now %lu (max %lu).", + NumConnections, NumConnectionsMax); +} /* Account_Connection */ + + static CONN_ID Socket2Index( int Sock ) { @@ -1736,7 +1837,7 @@ New_Server( int Server , ng_ipaddr_t *dest) } /* Conn_Close() decrements this counter again */ - NumConnections++; + Account_Connection(); Client_SetIntroducer( c, c ); Client_SetToken( c, TOKEN_OUTBOUND ); @@ -1811,12 +1912,13 @@ Init_Socket( int Sock ) } /* Set type of service (TOS) */ -#if defined(IP_TOS) && defined(IPTOS_LOWDELAY) +#if defined(IPPROTO_IP) && defined(IPTOS_LOWDELAY) value = IPTOS_LOWDELAY; - LogDebug("Setting option IP_TOS on socket %d to IPTOS_LOWDELAY (%d).", Sock, value ); - if( setsockopt( Sock, SOL_IP, IP_TOS, &value, (socklen_t)sizeof( value )) != 0 ) - { - Log( LOG_ERR, "Can't set socket option IP_TOS: %s!", strerror( errno )); + LogDebug("Setting IP_TOS on socket %d to IPTOS_LOWDELAY.", Sock); + if (setsockopt(Sock, IPPROTO_IP, IP_TOS, &value, + (socklen_t) sizeof(value))) { + Log(LOG_ERR, "Can't set socket option IP_TOS: %s!", + strerror(errno)); /* ignore this error */ } #endif @@ -1825,7 +1927,6 @@ Init_Socket( int Sock ) } /* Init_Socket */ - static void cb_Connect_to_Server(int fd, UNUSED short events) { @@ -1933,10 +2034,14 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events ) c = Conn_GetClient( i ); assert( c != NULL ); - /* Only update client information of unregistered clients */ - if( Client_Type( c ) == CLIENT_UNKNOWN ) { - strlcpy(My_Connections[i].host, readbuf, sizeof( My_Connections[i].host)); - Client_SetHostname( c, readbuf); + /* Only update client information of unregistered clients. + * Note: user commands (e. g. WEBIRC) are always read _after_ reading + * the resolver results, so we don't have to worry to override settings + * from these commands here. */ + if(Client_Type(c) == CLIENT_UNKNOWN) { + strlcpy(My_Connections[i].host, readbuf, + sizeof(My_Connections[i].host)); + Client_SetHostname(c, readbuf); #ifdef IDENTAUTH ++identptr; if (*identptr) { @@ -1955,41 +2060,63 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events ) } /* cb_Read_Resolver_Result */ +/** + * Write a "simple" (error) message to a socket. + * The message is sent without using the connection write buffers, without + * compression/encryption, and even without any error reporting. It is + * designed for error messages of e.g. New_Connection(). */ static void -Simple_Message( int Sock, const char *Msg ) +Simple_Message(int Sock, const char *Msg) { char buf[COMMAND_LEN]; size_t len; - /* Write "simple" message to socket, without using compression - * or even the connection write buffers. Used e.g. for error - * messages by New_Connection(). */ - assert( Sock > NONE ); - assert( Msg != NULL ); - - strlcpy( buf, Msg, sizeof buf - 2); - len = strlcat( buf, "\r\n", sizeof buf); - (void)write(Sock, buf, len); + + assert(Sock > NONE); + assert(Msg != NULL); + + strlcpy(buf, Msg, sizeof buf - 2); + len = strlcat(buf, "\r\n", sizeof buf); + if (write(Sock, buf, len) < 0) { + /* Because this function most probably got called to log + * an error message, any write error is ignored here to + * avoid an endless loop. But casting the result of write() + * to "void" doesn't satisfy the GNU C code attribute + * "warn_unused_result" which is used by some versions of + * glibc (e.g. 2.11.1), therefore this silly error + * "handling" code here :-( */ + return; + } } /* Simple_Error */ +/** + * Get CLIENT structure that belongs to a local connection identified by its + * index number. Each connection belongs to a client by definition, so it is + * not required that the caller checks for NULL return values. + * @param Idx Connection index number + * @return Pointer to CLIENT structure + */ GLOBAL CLIENT * Conn_GetClient( CONN_ID Idx ) { - /* return Client-Structure that belongs to the local Connection Idx. - * If none is found, return NULL. - */ CONNECTION *c; - assert( Idx >= 0 ); + assert(Idx >= 0); c = array_get(&My_ConnArray, sizeof (CONNECTION), (size_t)Idx); - assert(c != NULL); - return c ? c->client : NULL; } + #ifdef SSL_SUPPORT -/* we cannot access My_Connections in irc-info.c */ + +/** + * Get information about used SSL chiper. + * @param Idx Connection index number + * @param buf Buffer for returned information text + * @param len Size of return buffer "buf" + * @return true on success, false otherwise + */ GLOBAL bool Conn_GetCipherInfo(CONN_ID Idx, char *buf, size_t len) { @@ -2000,6 +2127,11 @@ Conn_GetCipherInfo(CONN_ID Idx, char *buf, size_t len) } +/** + * Check if a connection is SSL-enabled or not. + * @param Idx Connection index number + * @return true if connection is SSL-enabled, false otherwise. + */ GLOBAL bool Conn_UsesSSL(CONN_ID Idx) { @@ -2008,6 +2140,7 @@ Conn_UsesSSL(CONN_ID Idx) assert(Idx < (int) array_length(&My_ConnArray, sizeof(CONNECTION))); return Conn_OPTION_ISSET(&My_Connections[Idx], CONN_SSL); } + #endif diff --git a/src/ngircd/conn.h b/src/ngircd/conn.h index 983c884..f2ec823 100644 --- a/src/ngircd/conn.h +++ b/src/ngircd/conn.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2009 by Alexander Barton (alex@barton.de) + * Copyright (c)2001-2010 Alexander Barton * * 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 @@ -88,7 +88,7 @@ typedef struct _Connection ZIPDATA zip; /* Compression information */ #endif /* ZLIB */ #ifdef SSL_SUPPORT - struct ConnSSL_State ssl_state; /* SSL/GNUTLS state information */ + struct ConnSSL_State ssl_state; /* SSL/GNUTLS state information */ #endif } CONNECTION; @@ -122,5 +122,9 @@ static inline bool Conn_UsesSSL(UNUSED CONN_ID Idx) { return false; } #endif #endif +GLOBAL long Conn_Count PARAMS((void)); +GLOBAL long Conn_CountMax PARAMS((void)); +GLOBAL long Conn_CountAccepted PARAMS((void)); + /* -eof- */ diff --git a/src/ngircd/defines.h b/src/ngircd/defines.h index 905a5a6..94c7dd1 100644 --- a/src/ngircd/defines.h +++ b/src/ngircd/defines.h @@ -1,14 +1,12 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2007 Alexander Barton (alex@barton.de) + * Copyright (c)2001-2010 Alexander Barton (alex@barton.de) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * Please read the file COPYING, README and AUTHORS for more information. - * - * $Id: defines.h,v 1.62 2007/11/21 12:16:36 alex Exp $ */ @@ -30,8 +28,6 @@ #define HOST_LEN 256 /* Max. lenght of fully qualified host names (e. g. "abc.domain.tld") */ -#define MAX_OPERATORS 16 /* Max. count of configurable IRC Ops */ - #define MAX_SERVERS 16 /* Max. count of configurable servers */ #define MAX_WHOWAS 64 /* Max. number of WHOWAS items */ @@ -84,8 +80,8 @@ #define RECONNECT_DELAY 3 /* Time to delay re-connect attempts in seconds. */ -#define USERMODES "aios" /* Supported user modes. */ -#define CHANMODES "biIklmnoPstv" /* Supported channel modes. */ +#define USERMODES "aiorsw" /* Supported user modes. */ +#define CHANMODES "biIklmnoPstvz" /* Supported channel modes. */ #define CONNECTED true /* Internal status codes. */ #define DISCONNECTED false diff --git a/src/ngircd/irc-channel.c b/src/ngircd/irc-channel.c index af0f066..1014d3a 100644 --- a/src/ngircd/irc-channel.c +++ b/src/ngircd/irc-channel.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2008 Alexander Barton (alex@barton.de) + * Copyright (c)2001-2010 Alexander Barton (alex@barton.de) * * 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 @@ -62,9 +62,18 @@ part_from_all_channels(CLIENT* client, CLIENT *target) } +/** + * Check weather a local client is allowed to join an already existing + * channel or not. + * @param Client Client that sent the JOIN command + * @param chan Channel to check + * @param channame Name of the channel + * @param key Provided channel key (or NULL if none has been provided) + * @return true if client is allowed to join channel, false otherwise + */ static bool -join_allowed(CLIENT *Client, CLIENT *target, CHANNEL *chan, - const char *channame, const char *key) +join_allowed(CLIENT *Client, CHANNEL *chan, const char *channame, + const char *key) { bool is_invited, is_banned; const char *channel_modes; @@ -73,32 +82,48 @@ join_allowed(CLIENT *Client, CLIENT *target, CHANNEL *chan, if (strchr(Client_Modes(Client), 'o')) return true; - is_banned = Lists_Check(Channel_GetListBans(chan), target); - is_invited = Lists_Check(Channel_GetListInvites(chan), target); + is_banned = Lists_Check(Channel_GetListBans(chan), Client); + is_invited = Lists_Check(Channel_GetListInvites(chan), Client); if (is_banned && !is_invited) { - IRC_WriteStrClient(Client, ERR_BANNEDFROMCHAN_MSG, Client_ID(Client), channame); + /* Client is banned from channel (and not on invite list) */ + IRC_WriteStrClient(Client, ERR_BANNEDFROMCHAN_MSG, + Client_ID(Client), channame); return false; } channel_modes = Channel_Modes(chan); - if ((strchr(channel_modes, 'i')) && !is_invited) { - /* Channel is "invite-only" (and Client wasn't invited) */ - IRC_WriteStrClient(Client, ERR_INVITEONLYCHAN_MSG, Client_ID(Client), channame); + if (strchr(channel_modes, 'i') && !is_invited) { + /* Channel is "invite-only" and client is not on invite list */ + IRC_WriteStrClient(Client, ERR_INVITEONLYCHAN_MSG, + Client_ID(Client), channame); return false; } - /* Is the channel protected by a key? */ - if (!Channel_CheckKey(chan, target, key ? key : "")) { + if (!Channel_CheckKey(chan, Client, key ? key : "")) { + /* Channel is protected by a channel key and the client + * didn't specify the correct one */ IRC_WriteStrClient(Client, ERR_BADCHANNELKEY_MSG, Client_ID(Client), channame); return false; } - /* Are there already too many members? */ - if ((strchr(channel_modes, 'l')) && (Channel_MaxUsers(chan) <= Channel_MemberCount(chan))) { - IRC_WriteStrClient(Client, ERR_CHANNELISFULL_MSG, Client_ID(Client), channame); + + if (strchr(channel_modes, 'l') && + (Channel_MaxUsers(chan) <= Channel_MemberCount(chan))) { + /* There are more clints joined to this channel than allowed */ + IRC_WriteStrClient(Client, ERR_CHANNELISFULL_MSG, + Client_ID(Client), channame); + return false; + } + + if (strchr(channel_modes, 'z') && !Conn_UsesSSL(Client_Conn(Client))) { + /* Only "secure" clients are allowed, but clients doesn't + * use SSL encryption */ + IRC_WriteStrClient(Client, ERR_SECURECHANNEL_MSG, + Client_ID(Client), channame); return false; } + return true; } @@ -270,20 +295,23 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req ) /* Local client? */ if (Client_Type(Client) == CLIENT_USER) { - /* Test if the user has reached his maximum channel count */ - if ((Conf_MaxJoins > 0) && (Channel_CountForUser(Client) >= Conf_MaxJoins)) - return IRC_WriteStrClient(Client, ERR_TOOMANYCHANNELS_MSG, - Client_ID(Client), channame); - if (!chan) { - /* - * New Channel: first user will be channel operator - * unless this is a modeless channel. - */ + /* Test if the user has reached the channel limit */ + if ((Conf_MaxJoins > 0) && + (Channel_CountForUser(Client) >= Conf_MaxJoins)) + return IRC_WriteStrClient(Client, + ERR_TOOMANYCHANNELS_MSG, + Client_ID(Client), channame); + if (chan) { + /* Already existing channel: check if the + * client is allowed to join */ + if (!join_allowed(Client, chan, channame, key)) + break; + } else { + /* New channel: first user will become channel + * operator unless this is a modeless channel */ if (*channame != '+') flags = "o"; - } else - if (!join_allowed(Client, target, chan, channame, key)) - break; + } /* Local client: update idle time */ Conn_UpdateIdle(Client_Conn(Client)); @@ -293,7 +321,9 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req ) * that the "one shot" entries (generated by INVITE * commands) in this list become deleted when a user * joins a channel this way. */ - if (chan) (void)Lists_Check(Channel_GetListInvites(chan), target); + if (chan) + (void)Lists_Check(Channel_GetListInvites(chan), + target); } /* Join channel (and create channel if it doesn't exist) */ diff --git a/src/ngircd/irc-info.c b/src/ngircd/irc-info.c index 5a8555a..7d7bb88 100644 --- a/src/ngircd/irc-info.c +++ b/src/ngircd/irc-info.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2009 Alexander Barton (alex@barton.de) + * Copyright (c)2001-2010 Alexander Barton * * 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 @@ -465,6 +465,10 @@ uptime_mins(time_t *now) } +/** + * Handler for the IRC command "STATS". + * See RFC 2812 section 3.4.4. + */ GLOBAL bool IRC_STATS( CLIENT *Client, REQUEST *Req ) { @@ -475,11 +479,12 @@ IRC_STATS( CLIENT *Client, REQUEST *Req ) time_t time_now; unsigned int days, hrs, mins; - assert( Client != NULL ); - assert( Req != NULL ); + assert(Client != NULL); + assert(Req != NULL); if (Req->argc > 2) - return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, Client_ID(Client), Req->command); + return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, + Client_ID(Client), Req->command); /* use prefix to determine "From" */ if (Client_Type(Client) == CLIENT_SERVER) @@ -487,18 +492,21 @@ IRC_STATS( CLIENT *Client, REQUEST *Req ) else from = Client; - if (! from) - return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix); + if (!from) + return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, + Client_ID(Client), Req->prefix); if (Req->argc == 2) { /* forward to another server? */ - target = Client_Search( Req->argv[1] ); - if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) - return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[1] ); + target = Client_Search(Req->argv[1]); + if ((!target) || (Client_Type(target) != CLIENT_SERVER)) + return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG, + Client_ID(from), Req->argv[1]); - if( target != Client_ThisServer()) { + if (target != Client_ThisServer()) { /* forward to another server */ - return IRC_WriteStrClientPrefix( target, from, "STATS %s %s", Req->argv[0], Req->argv[1] ); + return IRC_WriteStrClientPrefix(target, from, + "STATS %s %s", Req->argv[0], Req->argv[1]); } } @@ -508,57 +516,70 @@ IRC_STATS( CLIENT *Client, REQUEST *Req ) query = '*'; switch (query) { - case 'l': /* Links */ - case 'L': - time_now = time(NULL); - for (con = Conn_First(); con != NONE ;con = Conn_Next(con)) { - cl = Conn_GetClient(con); - if (!cl) - continue; - if ((Client_Type(cl) == CLIENT_SERVER) || (cl == Client)) { - /* Server link or our own connection */ + case 'l': /* Link status (servers and own link) */ + case 'L': + time_now = time(NULL); + for (con = Conn_First(); con != NONE; con = Conn_Next(con)) { + cl = Conn_GetClient(con); + if (!cl) + continue; + if ((Client_Type(cl) == CLIENT_SERVER) + || (cl == Client)) { + /* Server link or our own connection */ #ifdef ZLIB - if (Conn_Options(con) & CONN_ZIP) { - if (!IRC_WriteStrClient(from, RPL_STATSLINKINFOZIP_MSG, - Client_ID(from), Client_Mask(cl), Conn_SendQ(con), - Conn_SendMsg(con), Zip_SendBytes(con), Conn_SendBytes(con), - Conn_RecvMsg(con), Zip_RecvBytes(con), Conn_RecvBytes(con), (long)(time_now - Conn_StartTime(con)))) - return DISCONNECTED; - continue; - } -#endif - if (!IRC_WriteStrClient(from, RPL_STATSLINKINFO_MSG, Client_ID(from), - Client_Mask(cl), Conn_SendQ(con), Conn_SendMsg(con), Conn_SendBytes(con), - Conn_RecvMsg(con), Conn_RecvBytes(con), (long)(time_now - Conn_StartTime(con)))) - return DISCONNECTED; - } - } - break; - case 'm': /* IRC-Commands */ - case 'M': - cmd = Parse_GetCommandStruct( ); - for (; cmd->name ; cmd++) { - if (cmd->lcount == 0 && cmd->rcount == 0) + if (Conn_Options(con) & CONN_ZIP) { + if (!IRC_WriteStrClient + (from, RPL_STATSLINKINFOZIP_MSG, + Client_ID(from), Client_Mask(cl), + Conn_SendQ(con), Conn_SendMsg(con), + Zip_SendBytes(con), + Conn_SendBytes(con), + Conn_RecvMsg(con), + Zip_RecvBytes(con), + Conn_RecvBytes(con), + (long)(time_now - Conn_StartTime(con)))) + return DISCONNECTED; continue; - if (!IRC_WriteStrClient(from, RPL_STATSCOMMANDS_MSG, Client_ID(from), - cmd->name, cmd->lcount, cmd->bytes, cmd->rcount)) - return DISCONNECTED; + } +#endif + if (!IRC_WriteStrClient + (from, RPL_STATSLINKINFO_MSG, + Client_ID(from), Client_Mask(cl), + Conn_SendQ(con), Conn_SendMsg(con), + Conn_SendBytes(con), Conn_RecvMsg(con), + Conn_RecvBytes(con), + (long)(time_now - Conn_StartTime(con)))) + return DISCONNECTED; } - break; - case 'u': /* server uptime */ - case 'U': - time_now = time(NULL) - NGIRCd_Start; - days = uptime_days(&time_now); - hrs = uptime_hrs(&time_now); - mins = uptime_mins(&time_now); - if (!IRC_WriteStrClient(from, RPL_STATSUPTIME, Client_ID(from), - days, hrs, mins, (unsigned int) time_now)) - return DISCONNECTED; - break; + } + break; + case 'm': /* IRC command status (usage count) */ + case 'M': + cmd = Parse_GetCommandStruct(); + for (; cmd->name; cmd++) { + if (cmd->lcount == 0 && cmd->rcount == 0) + continue; + if (!IRC_WriteStrClient + (from, RPL_STATSCOMMANDS_MSG, Client_ID(from), + cmd->name, cmd->lcount, cmd->bytes, cmd->rcount)) + return DISCONNECTED; + } + break; + case 'u': /* Server uptime */ + case 'U': + time_now = time(NULL) - NGIRCd_Start; + days = uptime_days(&time_now); + hrs = uptime_hrs(&time_now); + mins = uptime_mins(&time_now); + if (!IRC_WriteStrClient(from, RPL_STATSUPTIME, Client_ID(from), + days, hrs, mins, (unsigned int)time_now)) + return DISCONNECTED; + break; } IRC_SetPenalty(from, 2); - return IRC_WriteStrClient(from, RPL_ENDOFSTATS_MSG, Client_ID(from), query); + return IRC_WriteStrClient(from, RPL_ENDOFSTATS_MSG, + Client_ID(from), query); } /* IRC_STATS */ @@ -1155,6 +1176,10 @@ IRC_Send_LUSERS( CLIENT *Client ) if(! IRC_WriteStrClient(Client, RPL_NETUSERS_MSG, Client_ID(Client), cnt, max, cnt, max)) return DISCONNECTED; + /* Connection counters */ + if (! IRC_WriteStrClient(Client, RPL_STATSCONN_MSG, Client_ID(Client), + Conn_CountMax(), Conn_CountAccepted())) + return DISCONNECTED; #endif return CONNECTED; diff --git a/src/ngircd/irc-login.c b/src/ngircd/irc-login.c index 7b73d40..2de4bd5 100644 --- a/src/ngircd/irc-login.c +++ b/src/ngircd/irc-login.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2008 Alexander Barton (alex@barton.de) + * Copyright (c)2001-2010 Alexander Barton (alex@barton.de) * * 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 @@ -557,6 +557,31 @@ IRC_SERVICE(CLIENT *Client, REQUEST *Req) } /* IRC_SERVICE */ +/** + * Handler for the IRC command "WEBIRC". + * Syntax: WEBIRC + */ +GLOBAL bool +IRC_WEBIRC(CLIENT *Client, REQUEST *Req) +{ + /* Exactly 4 parameters are requited */ + if (Req->argc != 4) + return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, + Client_ID(Client), Req->command); + + if (!Conf_WebircPwd[0] || strcmp(Req->argv[0], Conf_WebircPwd) != 0) + return IRC_WriteStrClient(Client, ERR_PASSWDMISMATCH_MSG, + Client_ID(Client)); + + LogDebug("Connection %d: got valid WEBIRC command: user=%s, host=%s, ip=%s", + Client_Conn(Client), Req->argv[1], Req->argv[2], Req->argv[3]); + + Client_SetUser(Client, Req->argv[1], true); + Client_SetHostname(Client, Req->argv[2]); + return CONNECTED; +} /* IRC_WEBIRC */ + + GLOBAL bool IRC_QUIT( CLIENT *Client, REQUEST *Req ) { diff --git a/src/ngircd/irc-login.h b/src/ngircd/irc-login.h index 0b92038..1504e0b 100644 --- a/src/ngircd/irc-login.h +++ b/src/ngircd/irc-login.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2008 Alexander Barton (alex@barton.de) + * Copyright (c)2001-2010 Alexander Barton (alex@barton.de) * * 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 @@ -19,6 +19,7 @@ GLOBAL bool IRC_PASS PARAMS((CLIENT *Client, REQUEST *Req)); GLOBAL bool IRC_NICK PARAMS((CLIENT *Client, REQUEST *Req)); GLOBAL bool IRC_USER PARAMS((CLIENT *Client, REQUEST *Req)); GLOBAL bool IRC_SERVICE PARAMS((CLIENT *Client, REQUEST *Req)); +GLOBAL bool IRC_WEBIRC PARAMS((CLIENT *Client, REQUEST *Req)); GLOBAL bool IRC_PING PARAMS((CLIENT *Client, REQUEST *Req)); GLOBAL bool IRC_PONG PARAMS((CLIENT *Client, REQUEST *Req)); GLOBAL bool IRC_QUIT PARAMS((CLIENT *Client, REQUEST *Req)); diff --git a/src/ngircd/irc-mode.c b/src/ngircd/irc-mode.c index 9509fb0..d22d32f 100644 --- a/src/ngircd/irc-mode.c +++ b/src/ngircd/irc-mode.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2008 Alexander Barton (alex@barton.de) + * Copyright (c)2001-2010 Alexander Barton (alex@barton.de) * * 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 @@ -401,6 +401,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) case 'n': /* Only members can write */ case 's': /* Secret channel */ case 't': /* Topic locked */ + case 'z': /* Secure connections only */ if (modeok) x[0] = *mode_ptr; else diff --git a/src/ngircd/irc-oper.c b/src/ngircd/irc-oper.c index 17b6044..8492603 100644 --- a/src/ngircd/irc-oper.c +++ b/src/ngircd/irc-oper.c @@ -55,25 +55,26 @@ Bad_OperPass(CLIENT *Client, char *errtoken, char *errmsg) GLOBAL bool IRC_OPER( CLIENT *Client, REQUEST *Req ) { - unsigned int i; + struct Conf_Oper *op; + size_t len, i; assert( Client != NULL ); assert( Req != NULL ); if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - for( i = 0; i < Conf_Oper_Count; i++) - { - if( Conf_Oper[i].name[0] && Conf_Oper[i].pwd[0] && ( strcmp( Conf_Oper[i].name, Req->argv[0] ) == 0 )) break; - } - if( i >= Conf_Oper_Count ) + len = array_length(&Conf_Opers, sizeof(*op)); + op = array_start(&Conf_Opers); + for (i = 0; i < len && strcmp(op[i].name, Req->argv[0]); i++) + ; + if (i >= len) return Bad_OperPass(Client, Req->argv[0], "not configured"); - if( strcmp( Conf_Oper[i].pwd, Req->argv[1] ) != 0 ) - return Bad_OperPass(Client, Conf_Oper[i].name, "bad password"); + if (strcmp(op[i].pwd, Req->argv[1]) != 0) + return Bad_OperPass(Client, op[i].name, "bad password"); - if( Conf_Oper[i].mask && (! Match( Conf_Oper[i].mask, Client_Mask( Client ) ))) - return Bad_OperPass(Client, Conf_Oper[i].mask, "hostmask check failed" ); + if (op[i].mask && (!Match(op[i].mask, Client_Mask(Client)))) + return Bad_OperPass(Client, op[i].mask, "hostmask check failed"); if( ! Client_HasMode( Client, 'o' )) { diff --git a/src/ngircd/irc.c b/src/ngircd/irc.c index 2466b6b..67ad2a6 100644 --- a/src/ngircd/irc.c +++ b/src/ngircd/irc.c @@ -53,8 +53,12 @@ IRC_ERROR( CLIENT *Client, REQUEST *Req ) assert( Client != NULL ); assert( Req != NULL ); - if( Req->argc < 1 ) Log( LOG_NOTICE, "Got ERROR from \"%s\"!", Client_Mask( Client )); - else Log( LOG_NOTICE, "Got ERROR from \"%s\": %s!", Client_Mask( Client ), Req->argv[0] ); + if (Req->argc < 1) + Log(LOG_NOTICE, "Got ERROR from \"%s\"!", + Client_Mask(Client)); + else + Log(LOG_NOTICE, "Got ERROR from \"%s\": \"%s\"!", + Client_Mask(Client), Req->argv[0]); return CONNECTED; } /* IRC_ERROR */ diff --git a/src/ngircd/log.c b/src/ngircd/log.c index 5a81b5b..ff81163 100644 --- a/src/ngircd/log.c +++ b/src/ngircd/log.c @@ -146,8 +146,8 @@ GLOBAL void Log_Exit( void ) { /* Good Bye! */ - if( NGIRCd_SignalRestart ) Log( LOG_NOTICE, "%s done (restarting).", PACKAGE_NAME ); - else Log( LOG_NOTICE, "%s done.", PACKAGE_NAME ); + Log(LOG_NOTICE, "%s done%s, served %lu connections.", PACKAGE_NAME, + NGIRCd_SignalRestart ? " (restarting)" : "", Conn_CountAccepted()); #ifdef DEBUG if( Error_File[0] ) diff --git a/src/ngircd/messages.h b/src/ngircd/messages.h index 9e15b81..c356e42 100644 --- a/src/ngircd/messages.h +++ b/src/ngircd/messages.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2008 Alexander Barton + * Copyright (c)2001-2010 Alexander Barton * * 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 @@ -20,7 +20,7 @@ #define RPL_YOURHOST_MSG "002 %s :Your host is %s, running version ngircd-%s (%s/%s/%s)" #define RPL_CREATED_MSG "003 %s :This server has been started %s" #define RPL_MYINFO_MSG "004 %s %s ngircd-%s %s %s" -#define RPL_ISUPPORT1_MSG "005 %s RFC2812 CASEMAPPING=ascii PREFIX=(ov)@+ CHANTYPES=#&+ CHANMODES=bI,k,l,imnPst CHANLIMIT=#&+:%d :are supported on this server" +#define RPL_ISUPPORT1_MSG "005 %s RFC2812 IRCD=ngIRCd CASEMAPPING=ascii PREFIX=(ov)@+ CHANTYPES=#&+ CHANMODES=bI,k,l,imnPst CHANLIMIT=#&+:%d :are supported on this server" #define RPL_ISUPPORT2_MSG "005 %s CHANNELLEN=%d NICKLEN=%d TOPICLEN=%d AWAYLEN=%d KICKLEN=%d PENALTY :are supported on this server" #define RPL_TRACELINK_MSG "200 %s Link %s-%s %s %s V%s %ld %d %d" @@ -46,6 +46,7 @@ #define RPL_TRACEEND_MSG "262 %s %s %s-%s.%s :End of TRACE" #define RPL_LOCALUSERS_MSG "265 %s %lu %lu :Current local users: %lu, Max: %lu" #define RPL_NETUSERS_MSG "266 %s %lu %lu :Current global users: %lu, Max: %lu" +#define RPL_STATSCONN_MSG "250 %s :Highest connection count: %lu (%lu connections received)" #define RPL_AWAY_MSG "301 %s %s :%s" #define RPL_USERHOST_MSG "302 %s :" @@ -113,6 +114,7 @@ #define ERR_ALREADYREGISTRED_MSG "462 %s :Connection already registered" #define ERR_PASSWDMISMATCH_MSG "464 %s :Invalid password" #define ERR_CHANNELISFULL_MSG "471 %s %s :Cannot join channel (+l)" +#define ERR_SECURECHANNEL_MSG "471 %s %s :Cannot join channel (+z)" #define ERR_UNKNOWNMODE_MSG "472 %s: %c :is unknown mode char for %s" #define ERR_INVITEONLYCHAN_MSG "473 %s %s :Cannot join channel (+i)" #define ERR_BANNEDFROMCHAN_MSG "474 %s %s :Cannot join channel (+b)" diff --git a/src/ngircd/ngircd.c b/src/ngircd/ngircd.c index 5fc88c9..b951bad 100644 --- a/src/ngircd/ngircd.c +++ b/src/ngircd/ngircd.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2009 Alexander Barton (alex@barton.de). + * Copyright (c)2001-2010 Alexander Barton (alex@barton.de). * * 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 @@ -562,7 +562,7 @@ static void Show_Version( void ) { puts( NGIRCd_Version ); - puts( "Copyright (c)2001-2009 Alexander Barton () and Contributors." ); + puts( "Copyright (c)2001-2010 Alexander Barton () and Contributors." ); puts( "Homepage: \n" ); puts( "This is free software; see the source for copying conditions. There is NO" ); puts( "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." ); @@ -798,7 +798,9 @@ NGIRCd_Init( bool NGIRCd_NoDaemon ) #else setpgrp(0, getpid()); #endif - chdir( "/" ); + if (chdir( "/" ) != 0) + Log(LOG_ERR, "Can't change directory to '/': %s", + strerror(errno)); /* Detach stdin, stdout and stderr */ Setup_FDStreams( ); diff --git a/src/ngircd/parse.c b/src/ngircd/parse.c index 2c28a30..3710d70 100644 --- a/src/ngircd/parse.c +++ b/src/ngircd/parse.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2008 Alexander Barton (alex@barton.de) + * Copyright (c)2001-2010 Alexander Barton (alex@barton.de) * * 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 @@ -103,6 +103,7 @@ static COMMAND My_Commands[] = { "USERS", IRC_USERS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, { "VERSION", IRC_VERSION, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, { "WALLOPS", IRC_WALLOPS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "WEBIRC", IRC_WEBIRC, CLIENT_UNKNOWN, 0, 0, 0 }, { "WHO", IRC_WHO, CLIENT_USER, 0, 0, 0 }, { "WHOIS", IRC_WHOIS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, { "WHOWAS", IRC_WHOWAS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, diff --git a/src/ngircd/resolve.c b/src/ngircd/resolve.c index b1487be..bccf518 100644 --- a/src/ngircd/resolve.c +++ b/src/ngircd/resolve.c @@ -144,8 +144,8 @@ Resolve_Init(RES_STAT *s) } -#ifndef WANT_IPV6 -#ifdef h_errno +#if !defined(HAVE_GETADDRINFO) || !defined(HAVE_GETNAMEINFO) +#if !defined(WANT_IPV6) && defined(h_errno) static char * Get_Error( int H_Error ) { @@ -162,8 +162,8 @@ Get_Error( int H_Error ) } return "unknown error"; } -#endif /* h_errno */ -#endif /* WANT_IPV6 */ +#endif +#endif /* Do "IDENT" (aka "AUTH") lookup and append result to resolved_addr array */ @@ -203,7 +203,7 @@ Do_IdentQuery(int identsock, array *resolved_addr) * the IP address in resbuf and returns false. * @param IpAddr ip address to resolve * @param resbuf result buffer to store DNS name/string representation of ip address - * @reslen size of result buffer (must be >= NGT_INET_ADDRSTRLEN) + * @param reslen size of result buffer (must be >= NGT_INET_ADDRSTRLEN) * @return true if reverse lookup successful, false otherwise */ static bool