1
0
mirror of https://github.com/osmarks/ngircd.git synced 2025-10-14 22:27:39 +00:00

Compare commits

..

59 Commits

Author SHA1 Message Date
Florian Westphal
bc3d1f1761 [Parser]: Don't use Client_Type after command has been processed.
This caused a read from already free'd memory, if the processed
command (IRC_QUIT) calls Client_Destroy. (from HEAD)
2008-02-05 13:15:05 +00:00
Alexander Barton
10cc60d1c2 Updated Debian changelog for 0.10.4. 2008-01-07 21:05:37 +00:00
Alexander Barton
928404860b ngIRCd 0.10.4 2008-01-07 20:57:39 +00:00
Florian Westphal
26c65a11cf IRC_PART could reference invalid memory. 2008-01-07 11:41:43 +00:00
Alexander Barton
d64ab2a36d Fixed a compile problem with elder gcc (detected with 2.95.2). [from HEAD] 2007-07-31 20:48:15 +00:00
Alexander Barton
058316059f Ooops, wrong date ... "great". Next try ... 2007-07-31 19:33:51 +00:00
Alexander Barton
c74aa136af New release, fixing a security bug: 0.10.3 2007-07-31 19:07:59 +00:00
Alexander Barton
079e0cf9a4 SECURITY: Fixed a severe bug in handling JOIN commands, which could
cause the server to crash. Thanks to Sebastian Vesper, <net@veoson.net>.
2007-07-31 18:54:26 +00:00
Alexander Barton
1e1cc6d47f Release 0.10.2. 2007-06-08 09:05:23 +00:00
Alexander Barton
c61de8bc0c Updated config.sub and config.guess [from HEAD]. 2007-05-26 10:44:51 +00:00
Alexander Barton
794603bb59 ngIRCd 0.10.2-rc2 2007-05-19 14:22:40 +00:00
Alexander Barton
302bd8ddaf Server links are allowed to use larger write buffers now (up to 50 KB);
removed Z{READ|WRITE}BUFFER_LEN. -- Both from HEAD.
2007-05-18 22:11:18 +00:00
Florian Westphal
cddc7e719d make needlesly global function Conn_Write static. (from HEAD) 2007-05-09 13:21:38 +00:00
Alexander Barton
001c3bb1b4 Version 0.10.2-pre1 2007-05-05 20:43:11 +00:00
Alexander Barton
5cb18415da Updated year of copyright notice. 2007-05-05 20:25:47 +00:00
Alexander Barton
69b595e8d4 Updated documentation. 2007-05-05 20:25:19 +00:00
Florian Westphal
090b596752 fix compressed server links (broken since 0.10.0) 2007-05-02 12:22:43 +00:00
Florian Westphal
f67ad15a36 sync with HEAD. 2007-04-03 22:08:50 +00:00
Florian Westphal
5c3e02393b re-arranged invite and ban list-handling (from HEAD) 2007-04-03 20:23:30 +00:00
Florian Westphal
3f7191db0f revert to last good revision 2006-12-17 23:06:29 +00:00
Florian Westphal
1e29560bac do not call Conn_Close when io_event_create fails [from HEAD] 2006-12-17 23:00:47 +00:00
Florian Westphal
880d4a88b1 fix possibe buffer-off-by one [from HEAD] 2006-12-17 23:00:17 +00:00
Florian Westphal
a915559086 don't call Resolve_Shutdown() when io_event_create fails [from HEAD] 2006-12-17 22:59:56 +00:00
Alexander Barton
52512462a2 ngIRCd 0.10.1. 2006-12-17 14:06:19 +00:00
Alexander Barton
d9323ada46 Updated documentation for release 0.10.1. 2006-12-17 13:55:29 +00:00
Alexander Barton
ec1847f018 Added support for Solaris 11. [from HEAD] 2006-12-17 13:49:49 +00:00
Florian Westphal
0af8fafdfb add PredefChannelsOnly to manpage [from HEAD] 2006-12-11 22:08:14 +00:00
Florian Westphal
c9e26562ce Changed Numerics 265 and 266 to follow ircd 2.11.x "standards". [from HEAD]
Allow PASS syntax defined in RFC 1459 for server links, too. [from HEAD]
Enhanced ISUPPORT message (005 numeric). [from HEAD]
2006-12-02 14:26:52 +00:00
Florian Westphal
a64e33b317 cleanups [from HEAD] 2006-12-02 14:21:26 +00:00
Florian Westphal
7e2e23d12f make several counters unsigned, char *s -> const char *s [from HEAD] 2006-12-02 14:00:00 +00:00
Florian Westphal
ab7bb74581 cleanups [from HEAD] 2006-12-02 13:54:10 +00:00
Florian Westphal
254bf129dc merge Conf_PredefChannelsOnly [from HEAD] 2006-12-02 13:33:52 +00:00
Florian Westphal
14cdb7fdd0 char* -> const char* [from HEAD] 2006-12-02 13:18:22 +00:00
Florian Westphal
740d876c44 backport checks for inline keyword and strcspn() [from HEAD] 2006-12-02 13:13:53 +00:00
Florian Westphal
de9a130bd9 merge Conf_PredefChannelsOnly Config Option [from HEAD] 2006-12-02 13:10:43 +00:00
Florian Westphal
a0e0da74f8 make several counters unsigned [from HEAD] 2006-12-02 13:08:02 +00:00
Florian Westphal
83c14a6383 - whitespace damage [from HEAD] 2006-12-02 13:06:50 +00:00
Florian Westphal
6c12659bcf #define MASK_LEN should use parentheses [from HEAD] 2006-12-02 13:05:38 +00:00
Florian Westphal
83d4d66818 make LogDebug() 'static inline' if DEBUG is not defined [from HEAD] 2006-12-02 13:02:07 +00:00
Florian Westphal
2434e86e14 char *foo -> const char *foo [from HEAD] 2006-12-02 13:01:11 +00:00
Florian Westphal
2b4b416d2f cleanups [from HEAD] 2006-12-02 13:00:25 +00:00
Alexander Barton
62f74db6f6 Fixed validation of server names containing digits. [from HEAD] 2006-11-10 10:06:14 +00:00
Florian Westphal
cf4ae77991 fix Channel_Join() [from HEAD] 2006-10-05 18:30:47 +00:00
Alexander Barton
1f652554dd Update info text of local server after re-reading configuration. [from HEAD] 2006-10-03 11:01:05 +00:00
Alexander Barton
032bf78ed4 ngIRCd 0.10.0 2006-10-01 16:21:55 +00:00
Alexander Barton
ce66aa1028 Removed "~sid" postfix; ooopsa. 2006-10-01 16:13:21 +00:00
Alexander Barton
9296c27cac Added "Provides: ircd" and bumped standards version. 2006-10-01 16:10:47 +00:00
Alexander Barton
921a5434af Updated ChangeLog. 2006-09-16 13:51:35 +00:00
Alexander Barton
7c7d417fd2 Fix file handle leak [from HEAD]. 2006-09-16 13:49:15 +00:00
Alexander Barton
ed71217b31 ngIRCd 0.10.0-pre2 2006-09-09 19:00:06 +00:00
Alexander Barton
57fb95eb1d ngircd 0.10.0-pre2 release. 2006-09-09 18:50:47 +00:00
Alexander Barton
6f2f2ecd3b only test for stack smashing protector if we are using gcc;
use -fstack-protector-all for the test to make sure the guard variable is added.
[from HEAD.]
2006-09-09 18:34:00 +00:00
Alexander Barton
cf824dd8e7 Updated list of supported/tested platforms. [from HEAD] 2006-09-09 18:10:56 +00:00
Alexander Barton
01ba196d7d fix gcc 4.1 -fstack-protector detection. [from HEAD] 2006-08-13 18:21:31 +00:00
Alexander Barton
af6c532007 New release: 0.10.0-pre1 2006-08-02 10:29:11 +00:00
Alexander Barton
1ca10ff590 Updated debian changelog (from HEAD). 2006-08-02 09:54:19 +00:00
Alexander Barton
cd7862cec4 Updated documentation. 2006-08-02 09:04:20 +00:00
Alexander Barton
f9a928451d Updated documentation. 2006-08-02 08:19:38 +00:00
Alexander Barton
2a22629e74 Increased version number to 0.10.x :-) 2006-07-31 20:32:20 +00:00
96 changed files with 3046 additions and 4932 deletions

17
.gitignore vendored
View File

@@ -1,17 +0,0 @@
Makefile
Makefile.in
aclocal.m4
ansi2knr.1
ansi2knr.c
ansi2knr.h
autom4te.cache
config.log
config.status
configure
configure.lineno
depcomp
install-sh
missing
.deps
*.a
*.o

12
AUTHORS
View File

@@ -1,7 +1,7 @@
ngIRCd - Next Generation IRC Server
(c)2001-2007 Alexander Barton,
(c)2001-2005 Alexander Barton,
alex@barton.de, http://www.barton.de/
ngIRCd is free software and published under the
@@ -10,16 +10,9 @@
-- AUTHORS and CONTRIBUTORS --
Note: If you have critics, patches or something else, please feel free to
post a mail to the ngIRCd mailing list: <ngircd-ml@arthur.ath.cx> (please see
<http://ngircd.barton.de/#ml> for details). Don't mail the contributors
directly, if possible!
Main Authors
~~~~~~~~~~~~
Alexander Barton, <alex@barton.de> (alex)
Florian Westphal, <westphal@foo.fh-furtwangen.de> (fw)
Contributors
@@ -28,6 +21,7 @@ Goetz Hoffart, <goetz@hoffart.de> (goetz)
Ilja Osthoff, <i.osthoff@gmx.net> (ilja)
Benjamin Pineau, <ben@zouh.org>
Sean Reifschneider, <jafo-rpms@tummy.com>
Florian Westphal, <westphal@foo.fh-furtwangen.de> (fw)
Code snippets
@@ -38,4 +32,4 @@ Andrew Tridgell & Martin Pool: strl{cpy|cat}()-functions
--
$Id: AUTHORS,v 1.13 2007/10/04 15:18:48 alex Exp $
$Id: AUTHORS,v 1.11 2005/03/19 14:24:52 alex Exp $

101
ChangeLog
View File

@@ -9,103 +9,12 @@
-- ChangeLog --
ngIRCd 0.12.1 (2008-07-09)
- Allow mixed line terminations (CR+LF/CR/LF) in non-RFC-compliant mode
- Don't allow stray \r or \n in command parameters
- --configtest: return non-zero exit code if there are errors
- Update ngIRCd manual pages
- Add option aliases -V (for --version) and -h (for --help).
- Fix 'no-ipv6' compile error.
- Make Listen parameter a comma-seperated list of addresses. This also
obsoletes ListenIPv4 and ListenIPv6 options. If Listen is unset, it
is treated as Listen="::,0.0.0.0".
Note: ListenIPv4 and ListenIPv6 options are still recognized,
but ngircd will print a warning if they are used in the config file.
ngIRCd 0.12.0 (2008-05-13)
- Fix Bug: 85: "WHO #SecretChannel" that user is not a member of now returns
proper RPL_ENDOFWHO_MSG instead of nothing. (Ali Shemiran)
- Fix complie on FreeBSD 5.4 and AIX.
- If bind() fails, also print ip address and not just the port number.
ngIRCd 0.12.0-pre2 (2008-04-29)
- IPv6: Add config options to disabe ipv4/ipv6 support.
- Don't include doc/CVS.txt in distribution archive, use doc/GIT.txt now!
- Documentation: get rid of some more references to CVS, switch to GIT.
- Get rid of cvs-version.* and CVSDATE definition.
- Report ERR_NOTONCHANNEL when trying to part a channel one is not member of.
- Testsuite: remove erroneous ConfUID setting in config file.
ngIRCd 0.12.0-pre1 (2008-04-20)
- Include Mac OS X Xcode project in distribution archives.
- Do not exit on SIGHUP or /REHASH if the config file cannot opened.
- Add IPv6 support.
- Install a LaunchDaemon script to start/stop ngIRCd on Mac OS X.
- Implemented IRC commands INFO, SUMMON (dummy), and USERS (dummy) and
enhanced test suite to check these commands. (Dana Dahlstrom)
- RPL_WHOREPLY messages generated by IRC_WHO didn't include flags (*,@,+).
(Dana Dahlstrom)
- IRC_WHO now supports search patterns and will test this against user
nickname/servername/hostname, etc. as required by RFC 2812, Section 3.6.1.
(reported by Dana Dahlstrom)
- Add test cases for "WHO" command. (Dana Dahlstrom)
- Implement RFC 2812 handling of "0" argument to 'JOIN': must be treated
as if the user had sent PART commands for all channels the user is a
member of. (Dana Dahlstrom)
- Allow NOTICEs to be sent to a channel. (Fabian Schlager)
ngIRCd 0.11.1 (2008-02-26)
- Fix sending of JOIN commands between servers when remote server appended
mode flags. (Rolf Eike Beer) [from HEAD]
- Send "G" instead of "H" flag in WHO replies. (reported by Dana Dahlstrom)
- Under some circumstances ngIRCd issued channel MODE message with a
trailing space. (Dana Dahlstrom) [from HEAD]
ngIRCd 0.11.0 (2008-01-15)
ngIRCd 0.11.0-pre2 (2008-01-07)
- SECURITY: IRC_PART could reference invalid memory, causing
ngircd to crash [from HEAD].
ngIRCd 0.11.0-pre1 (2008-01-02)
- Use dotted-decimal IP address if hostname is >= 64.
- Add support for /STAT u (server uptime) command.
- New [Server] configuration Option "Bind" allows to specify
the source ip adress to use when connecting to remote server.
- New configuration option "MaxNickLength" to specify the allowed maximum
length of user nick names. Note: must be unique in an IRC network!
- Enhanced the IRC+ protocol to support an enhanced "server handshake" and
enable server to recognice numeric 005 (ISUPPORT) and 376 (ENDOFMOTD).
See doc/Protocol.txt for details.
- Re-added doc/SSL.txt to distribution -- got lost somewhere!?
- Fixes the wrong logging output when nested servers are introduced
to the network as well as the wrong output of the LINKS command.
- Update Mac OS X Xcode project file for Xcode 3.
- Adjust test suite to be usable on HP/UX 11.11 :-)
- Fix code to compile using K&R C compiler and ansi2kr again.
- New config option NoDNS: Disables DNS lookups when clients connect.
- Fixed propagation of channel mode 'P' on server links.
- Numeric 317: implemented "signon time" (displayed in WHOIS result).
- Fixed code that prevented GCC 2.95 to compile ngIRCd.
- Adjust path names in manual pages according to "./configure" settings.
- Added new server configuration option "Passive" for "Server" blocks to
disable automatic outgoing connections (similar to -p option to ngircd,
but only for the specified server). (Tassilo Schweyer)
- Don't connect to a server if a connection to another server within the
same group is already in progress.
- Added support for the WALLOPS command. Usage is restricted to IRC
operators.
ngIRCd 0.10.4 (2008-01-07)
- SECURITY: IRC_PART could reference invalid memory, causing
ngircd to crash [from HEAD].
ngIRCd 0.10.3 (2007-08-01)
ngircd to crash.
ngIRCd 0.10.3 (2007-07-31)
- SECURITY: Fixed a severe bug in handling JOIN commands, which could
cause the server to crash. Thanks to Sebastian Vesper, <net@veoson.net>.
@@ -786,3 +695,7 @@ ngIRCd 0.0.2, 06.01.2002
ngIRCd 0.0.1, 31.12.2001
- erste oeffentliche Version von ngIRCd als "public preview" :-)
--
$Id: ChangeLog,v 1.302.2.21 2008/01/07 20:57:39 alex Exp $

12
INSTALL
View File

@@ -1,7 +1,7 @@
ngIRCd - Next Generation IRC Server
(c)2001-2007 Alexander Barton,
(c)2001-2006 by Alexander Barton,
alex@barton.de, http://www.barton.de/
ngIRCd is free software and published under the
@@ -51,9 +51,9 @@ on modern UNIX-like systems that are supported by GNU autoconf and GNU
automake ("configure") should be no problem.
The normal installation procedure after getting (and expanding) the source
files (using a distribution archive or GIT) is as following:
files (using a distribution archive or CVS) is as following:
1) ./autogen.sh [only necessary when using GIT]
1) ./autogen.sh [only necessary when using CVS]
2) ./configure
3) make
4) make install
@@ -77,7 +77,7 @@ doc/ directory: sample-ngircd.conf.
The first step, autogen.sh, is only necessary if the configure-script isn't
already generated. This never happens in official ("stable") releases in
tar.gz-archives, but when using GIT.
tar.gz-archives, but when using CVS.
This step is therefore only interesting for developers.
@@ -244,3 +244,7 @@ These parameters could be passed to the ngIRCd:
Use "--help" to see a short help text describing all available parameters
the server understands, with "--version" the ngIRCd shows its version
number. In both cases the server exits after the output.
--
$Id: INSTALL,v 1.23.2.2 2007/04/03 22:08:50 fw Exp $

View File

@@ -1,6 +1,6 @@
#
# ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
# Copyright (c)2001-2003 by 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
@@ -8,6 +8,8 @@
# (at your option) any later version.
# Please read the file COPYING, README and AUTHORS for more information.
#
# $Id: Makefile.am,v 1.17 2005/07/22 21:01:52 alex Exp $
#
AUTOMAKE_OPTIONS = gnu
@@ -22,9 +24,6 @@ maintainer-clean-local:
rm -f mkinstalldirs missing depcomp install-sh
rm -f config.log debian
testsuite:
make -C src/testsuite check
lint:
make -C src/ngircd lint
@@ -32,10 +31,9 @@ srcdoc:
make -C doc srcdoc
xcode:
@xcodebuild -project contrib/MacOSX/ngIRCd.xcodeproj -list \
>/dev/null 2>&1 \
@xcodebuild -project contrib/MacOSX/ngIRCd.xcode -list >/dev/null 2>&1 \
|| ( echo; echo "Error: \"xcodebuild\" not found!"; echo; exit 1 )
xcodebuild -project contrib/MacOSX/ngIRCd.xcodeproj -alltargets \
xcodebuild -project contrib/MacOSX/ngIRCd.xcode -alltargets \
-buildstyle Development
rpm: distcheck

45
NEWS
View File

@@ -1,7 +1,7 @@
ngIRCd - Next Generation IRC Server
(c)2001-2008 Alexander Barton,
(c)2001-2007 Alexander Barton,
alex@barton.de, http://www.barton.de/
ngIRCd is free software and published under the
@@ -10,47 +10,6 @@
-- NEWS --
ngIRCd 0.12.1 (2008-07-09)
- Add option aliases -V (for --version) and -h (for --help).
- Make Listen parameter a comma-seperated list of addresses. This also
obsoletes ListenIPv4 and ListenIPv6 options. If Listen is unset, it
is treated as Listen="::,0.0.0.0".
Note: ListenIPv4 and ListenIPv6 options are still recognized,
but ngircd will print a warning if they are used in the config file.
ngIRCd 0.12.0 (2008-05-13)
ngIRCd 0.12.0-pre2 (2008-04-29)
- IPv6: Add config options to disabe ipv4/ipv6 support.
ngIRCd 0.12.0-pre1 (2008-04-20)
- Add IPv6 support.
- Install a LaunchDaemon script to start/stop ngIRCd on Mac OS X.
- Implemented IRC commands INFO, SUMMON (dummy), and USERS (dummy) and
enhanced test suite to check these commands. (Dana Dahlstrom)
- IRC_WHO now supports search patterns and will test this against user
nickname/servername/hostname, etc. as required by RFC 2812, Section 3.6.1.
(reported by Dana Dahlstrom)
- Implement RFC 2812 handling of "0" argument to 'JOIN': must be treated
as if the user had sent PART commands for all channels the user is a
member of. (Dana Dahlstrom)
- Allow NOTICEs to be sent to a channel. (Fabian Schlager)
ngIRCd 0.11.0 (2008-01-15)
- Add support for /STAT u (server uptime) command.
- New [Server] configuration Option "Bind" allows to specify
the source ip adress to use when connecting to remote server.
- New configuration option "MaxNickLength" to specify the allowed maximum
length of user nick names. Note: must be unique in an IRC network!
- Numeric 317: implemented "signon time" (displayed in WHOIS result).
- Added new server configuration option "Passive" for "Server" blocks to
disable automatic outgoing connections (similar to -p option to ngircd,
but only for the specified server). (Tassilo Schweyer)
- Added support for the WALLOPS command. Usage is restricted to IRC
operators.
ngIRCd 0.10.2 (2007-06-08)
- Predefined channel configuration now allows specification of channel key
@@ -278,4 +237,4 @@ ngIRCd 0.0.1, 31.12.2001
--
$Id: NEWS,v 1.88 2008/02/26 22:05:42 fw Exp $
$Id: NEWS,v 1.75.2.7 2007/06/08 09:05:23 alex Exp $

16
README
View File

@@ -37,8 +37,7 @@ Implemented IRC-commands are:
ADMIN, AWAY, CHANINFO, CONNECT, DIE, DISCONNECT, ERROR, HELP, INVITE, ISON,
JOIN, KICK, KILL, LINKS, LIST, LUSERS, MODE, MOTD, NAMES, NICK, NJOIN, NOTICE,
OPER, PART, PASS, PING, PONG, PRIVMSG, QUIT, REHASH, RESTART, SERVER, SQUIT,
STATS, TIME, TOPIC, TRACE, USER, USERHOST, VERSION, WALLOPS, WHO, WHOIS,
WHOWAS.
STATS, TIME, TOPIC, TRACE, USER, USERHOST, VERSION, WHO, WHOIS, WHOWAS.
III. Features (or: why use ngIRCd?)
@@ -67,9 +66,9 @@ the newest information about the ngIRCd and the most recent ("stable")
releases there.
If you are interested in the latest development versions (which are not
always stable), then please read the section about "GIT" on the homepage and
the file "doc/GIT.txt" which describes the use of GIT, the version control
system used by ngIRCd (homepage: http://git.or.cz/).
always stable), then please read the section "CVS" on the homepage and
the file "doc/CVS.txt" which describes the use of CVS, the "Concurrent
Versioning System".
VI. Bugs
@@ -83,5 +82,8 @@ 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: <ngircd-ml@arthur.ath.cx> (please see
<http://ngircd.barton.de/#ml> for details).
mail to <alex@barton.de>.
--
$Id: README,v 1.21.2.2 2007/05/05 20:25:20 alex Exp $

View File

@@ -9,7 +9,7 @@
# (at your option) any later version.
# Please read the file COPYING, README and AUTHORS for more information.
#
# $Id: autogen.sh,v 1.15 2007/10/07 13:02:15 alex Exp $
# $Id: autogen.sh,v 1.14 2005/02/21 15:23:23 alex Exp $
#
#
@@ -124,22 +124,17 @@ if [ -z "$EXIST" ]; then
fi
[ "$VERBOSE" = "1" ] && echo "Using \"$EXIST\" to test for tools."
# We want to use GNU automake 1.9, if available (WANT_AUTOMAKE is used by
# We want to use GNU automake 1.7, if available (WANT_AUTOMAKE is used by
# the wrapper scripts of Gentoo Linux, AUTOMAKE_VERSION is used by OpenBSD);
# same applies for GNU autoconf, we want to use version 2.59. -- But only
# set these preferences if not already set!
if [ -z "$AUTOMAKE_VERSION" -a -z "$WANT_AUTOMAKE" ]; then
AUTOMAKE_VERSION=1.9
WANT_AUTOMAKE=1.9
fi
if [ -z "$AUTOCONF_VERSION" -a -z "$WANT_AUTOCONF" ]; then
AUTOCONF_VERSION=2.59
WANT_AUTOCONF=2.59
fi
export AUTOMAKE_VERSION WANT_AUTOMAKE AUTOCONF_VERSION WANT_AUTOCONF
# same applies for GNU autoconf, we want to use version 2.59.
AUTOMAKE_VERSION=1.7
AUTOCONF_VERSION=2.59
export AUTOMAKE_VERSION AUTOCONF_VERSION
WANT_AUTOMAKE=1.7
export WANT_AUTOMAKE
# Try to detect the needed tools when no environment variable already
# specifies one:
# spezifies one:
echo "Searching tools ..."
[ -z "$ACLOCAL" ] && ACLOCAL=`Search aclocal 1`
[ "$VERBOSE" = "1" ] && echo "ACLOCAL=$ACLOCAL"

View File

@@ -8,11 +8,13 @@
# (at your option) any later version.
# Please read the file COPYING, README and AUTHORS for more information.
#
# $Id: configure.in,v 1.118.2.14 2008/01/07 20:57:39 alex Exp $
#
# -- Initialisation --
AC_PREREQ(2.50)
AC_INIT(ngircd, 0.12.1)
AC_INIT(ngircd, 0.10.4)
AC_CONFIG_SRCDIR(src/ngircd/ngircd.c)
AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE(1.6)
@@ -28,7 +30,6 @@ AH_TEMPLATE([SYSLOG], [Define if syslog should be used for logging])
AH_TEMPLATE([ZLIB], [Define if zlib compression should be enabled])
AH_TEMPLATE([TCPWRAP], [Define if TCP wrappers should be used])
AH_TEMPLATE([IRCPLUS], [Define if IRC+ protocol should be used])
AH_TEMPLATE([WANT_IPV6], [Define if IPV6 protocol should be enabled])
AH_TEMPLATE([ZEROCONF], [Define if support for Zeroconf should be included])
AH_TEMPLATE([IDENTAUTH], [Define if the server should do IDENT requests])
@@ -425,19 +426,6 @@ if test "$x_ircplus_on" = "yes"; then
AC_DEFINE(IRCPLUS, 1)
fi
# enable support for IPv6?
x_ipv6_on=no
AC_ARG_ENABLE(ipv6,
[ --enable-ipv6 enable IPv6 protocol support],
if test "$enableval" = "yes"; then x_ipv6_on=yes; fi
)
if test "$x_ipv6_on" = "yes"; then
AC_CHECK_FUNCS([ \
getaddrinfo getnameinfo \
],,AC_MSG_ERROR([required function missing for IPv6 support!]))
AC_DEFINE(WANT_IPV6, 1)
fi
# compile in IRC "sniffer"?
x_sniffer_on=no; x_debug_on=no
@@ -489,7 +477,6 @@ AC_OUTPUT([ \
doc/src/Makefile \
src/Makefile \
src/portab/Makefile \
src/ipaddr/Makefile \
src/tool/Makefile \
src/ngircd/Makefile \
src/testsuite/Makefile \
@@ -497,7 +484,6 @@ AC_OUTPUT([ \
contrib/Makefile \
contrib/Debian/Makefile \
contrib/MacOSX/Makefile \
contrib/MacOSX/ngIRCd.xcodeproj/Makefile \
])
type dpkg >/dev/null 2>&1
@@ -586,8 +572,6 @@ test "$x_identauth_on" = "yes" \
echo $ECHO_N " I/O backend: $ECHO_C"
echo "\"$x_io_backend\""
echo $ECHO_N " IPv6 protocol: $ECHO_C"
echo "$x_ipv6_on"
echo
# -eof-

View File

@@ -1,45 +1,27 @@
ngircd (0.12.1-0ab1) unstable; urgency=low
* New "upstream" release ngIRCd 0.12.1.
-- Alexander Barton <alex@barton.de> Wed, 9 Jul 2008 11:27:00 +0200
ngircd (0.12.0-0ab1) unstable; urgency=low
* New "upstream" release ngIRCd 0.12.0.
-- Alexander Barton <alex@barton.de> Tue, 13 May 2008 12:30:31 +0200
ngircd (0.12.0-0ab0-pre2) unstable; urgency=low
* Second prerelease of upcoming new "upstrem" release 0.12.0-pre1.
-- Alexander Barton <alex@barton.de> Tue, 29 Apr 2008 23:06:14 +0200
ngircd (0.12.0-0ab0-pre1) unstable; urgency=low
* Prereloease of upcoming new "upstrem" release 0.12.0-pre1.
-- Alexander Barton <alex@barton.de> Sun, 20 Apr 2008 15:43:34 +0200
ngircd (0.11.0-0ab0-pre2) unstable; urgency=low
* Second prerelease of upcoming new "upstream release".
-- Alexander Barton <alex@barton.de> Mon, 7 Jan 2008 15:32:42 +0100
ngircd (0.11.0-0ab0-pre1) unstable; urgency=low
* Prerelease of upcoming new "upstream release".
-- Alexander Barton <alex@barton.de> Wed, 2 Jan 2008 21:33:15 +0100
ngircd (0.10.4-0ab1) unstable; urgency=high
* New "upstream" release: 0.10.4 - fixing a security bug.
-- Alexander Barton <alex@barton.de> Mon, 7 Jan 2008 22:04:44 +0100
ngircd (0.10.3-0ab1) unstable; urgency=high
* New "upstream" release: 0.10.3 - fixing a security bug.
-- Alexander Barton <alex@barton.de> Tue, 31 Jul 2007 21:02:52 +0200
ngircd (0.10.2-0ab1) unstable; urgency=low
* New "upstream" release: 0.10.2
-- Alexander Barton <alex@barton.de> Fri, 8 Jun 2007 10:49:36 +0200
ngircd (0.10.1-0ab1) unstable; urgency=low
* New "upstream" release: 0.10.1
-- Alexander Barton <alex@barton.de> Sun, 17 Dec 2006 14:52:06 +0100
ngircd (0.10.0-0ab1) unstable; urgency=low
* New "upstream" release: 0.10.0

View File

@@ -2,7 +2,7 @@
#
# ngIRCd start and stop script for Debian-based systems
#
# $Id: ngircd.init,v 1.7 2006/12/26 14:43:46 alex Exp $
# $Id: ngircd.init,v 1.6.2.1 2007/04/03 22:08:50 fw Exp $
#
### BEGIN INIT INFO

View File

@@ -1,20 +1,13 @@
#!/bin/sh
#
# Debian post-installation script
# $Id: ngircd.postinst,v 1.2 2006/12/26 14:44:40 alex Exp $
# $Id: ngircd.postinst,v 1.1 2003/12/31 17:20:11 alex Exp $
#
set -e
case "$1" in
configure)
if [ -f /etc/ngircd/ngircd.conf ]; then
# make sure that the configuration file is not
# world-readable, it contains passwords!
chmod o= /etc/ngircd/ngircd.conf
fi
;;
esac
if [ -f /etc/ngircd/ngircd.conf ]; then
# make sure that configuration file is not world readable
chmod o= /etc/ngircd/ngircd.conf
fi
#DEBHELPER#

View File

@@ -1 +0,0 @@
build

View File

@@ -1,6 +1,6 @@
#
# ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2008 Alexander Barton <alex@barton.de>
# Copyright (c)2001-2004 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
@@ -8,40 +8,9 @@
# (at your option) any later version.
# Please read the file COPYING, README and AUTHORS for more information.
#
# $Id: Makefile.am,v 1.3 2008/02/17 15:31:15 alex Exp $
# $Id: Makefile.am,v 1.2 2004/05/11 00:34:26 alex Exp $
#
SUBDIRS = ngIRCd.xcodeproj
EXTRA_DIST = de.barton.ngircd.plist.tmpl config.h cvs-version.h
SUFFIXES = .tmpl .
.tmpl:
sed \
-e s@:SBINDIR:@${sbindir}@ \
<$< >$@
install-data-local:
[ `uname -s` != "Darwin" ] || make install-sys-darwin
install-sys-darwin:
@if [ `id -u` -eq 0 ]; then \
make install-sys-darwin-root; \
else \
echo; \
echo " ** NOTE: Not installing with root privileges, so the LaunchDaemon script"; \
echo " ** \"/Library/LaunchDaemons/de.barton.ngircd.plist\" can't be installed/updated!"; \
echo; \
fi
install-sys-darwin-root: de.barton.ngircd.plist
install -c -m 644 -b -o root -g wheel de.barton.ngircd.plist /Library/LaunchDaemons/de.barton.ngircd.plist
@echo
@echo " ** \"/Library/LaunchDaemons/de.barton.ngircd.plist\" has been installed,"
@echo " ** but is disabled. Use launchctl(8) to enable/run ngIRCd on Darwin/Mac OS X."
@echo
clean-local:
rm -rf build

View File

@@ -1,92 +0,0 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2007 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: config.h,v 1.1 2007/11/19 22:11:36 alex Exp $
*
* Static configuration file for Mac OS X Xcode project
*/
#define PACKAGE_NAME "ngircd"
#define VERSION "??"
#define SYSCONFDIR "/etc/ngircd"
/* -- Build options -- */
/* Define if debug-mode should be enabled */
#define DEBUG 1
/* Define if the server should do IDENT requests */
/*#define IDENTAUTH 1*/
/* Define if IRC+ protocol should be used */
#define IRCPLUS 1
/* Define if IRC sniffer should be enabled */
/*#define SNIFFER 1*/
/* Define if syslog should be used for logging */
#define SYSLOG 1
/* Define if TCP wrappers should be used */
/*#define TCPWRAP 1*/
/* Define if support for Zeroconf should be included */
/*#define ZEROCONF 1*/
/* Define if zlib compression should be enabled */
#define ZLIB 1
/* -- Supported features -- */
/* Define if SSP C support is enabled. */
#define ENABLE_SSP_CC 1
/* Define to 1 if the C compiler supports function prototypes. */
#define PROTOTYPES 1
/* Define like PROTOTYPES; this can be used by system headers. */
#define __PROTOTYPES 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the <stddef.h> header file. */
#define HAVE_STDDEF_H 1
/* Define to 1 if you have the <stdbool.h> header file. */
#define HAVE_STDBOOL_H 1
/* Define to 1 if you have the <arpa/inet.h> header file. */
#define HAVE_ARPA_INET_H 1
/* Define to 1 if you have the `kqueue' function. */
#define HAVE_KQUEUE 1
/* Define to 1 if you have the `inet_ntoa' function. */
#define HAVE_INET_NTOA 1
/* Define to 1 if you have the `snprintf' function. */
#define HAVE_SNPRINTF 1
/* Define to 1 if you have the `strlcat' function. */
#define HAVE_STRLCAT 1
/* Define to 1 if you have the `strlcpy' function. */
#define HAVE_STRLCPY 1
/* Define to 1 if you have the `strdup' function. */
#define HAVE_STRDUP 1
/* Define to 1 if you have the `vsnprintf' function. */
#define HAVE_VSNPRINTF 1
/* Define if socklen_t exists */
#define HAVE_socklen_t 1
#ifdef ZEROCONF
/* Define to 1 if you have the <DNSServiceDiscovery/DNSServiceDiscovery.h> header file. */
#define HAVE_DNSSERVICEDISCOVERY_DNSSERVICEDISCOVERY_H 1
/* Define to 1 if you have the `DNSServiceRegistrationCreate' function. */
#define HAVE_DNSSERVICEREGISTRATIONCREATE 1
#endif
/* -eof- */

View File

@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Disabled</key>
<true/>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>de.barton.ngIRCd</string>
<key>ProgramArguments</key>
<array>
<string>:SBINDIR:/ngircd</string>
<string>--nodaemon</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>

View File

@@ -1,2 +0,0 @@
*.mode1v3
*.pbxuser

View File

@@ -1,17 +0,0 @@
#
# ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2008 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.
#
EXTRA_DIST = project.pbxproj
maintainer-clean-local:
rm -f Makefile Makefile.in
# -eof-

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
%define name ngircd
%define version 0.12.1
%define version 0.10.4
%define release 1
%define prefix %{_prefix}

57
doc/CVS.txt Normal file
View File

@@ -0,0 +1,57 @@
ngIRCd - Next Generation IRC Server
(c)2001-2006 Alexander Barton,
alex@barton.de, http://www.barton.de/
ngIRCd is free software and published under the
terms of the GNU General Public License.
-- CVS.txt --
The source code of ngIRCd is maintained using the "Concurrent Versions
System" (CVS). Thereby several developers can work with the source tree at
the same time.
I. Anonymous read-only Access
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To access the source tree anonymously in read-only mode, follow these steps:
Login to the CVS server:
$ cvs -d:pserver:anonymous@ngircd.barton.de:/srv/cvs/ngircd login
Use "anonymous" as user name and no password (just hit Return). Now you can
check out the sources:
$ cvs -d:pserver:anonymous@ngircd.barton.de:/srv/cvs/ngircd checkout ngircd
Thereby a new folder "ngircd" will be created containing all the individual
source files. (Substitute the last "ngircd" with "website" to check out all
the files of the homepage of ngIRCd.)
The newly created folder ("ngircd" or "website") is the "working folder", all
CVS commands will be executed from within this folder in the future.
Please note: When checking out a fresh copy of ngIRCd from CVS, the
configure script doesn't exist; you have to run the autogen.sh shell script
(which is included in the source tree) to generate it. This requires you to
have GNU automake and GNU autoconf installed on your system.
Updating the CVS tree:
$ cvs update -d -P [<filename>]
You can update a single file or the complete source tree.
II. Write Access
~~~~~~~~~~~~~~~~
If you want to contribute a couple of patches and write access to the CVS
repository would be handy, please contact Alex Barton, <alex@barton.de>.
--
$Id: CVS.txt,v 1.8.2.1 2006/08/02 09:04:20 alex Exp $

View File

@@ -62,6 +62,15 @@ A: On Linux/glibc with chroot enabled you need to put some libraries inside
is to either disable chroot support or to link against dietlibc instead
of glibc. (tnx to Sebastian Siewior)
Q: I am running Linux and ngircd dies on startup with the follwing errors:
IO subsystem: epoll (hint size 100, initial maxfd 100, masterfd -1).
Cannot initialize IO routines: Function not implemented
Server isn't listening on a single port!
ngircd exiting due to fatal errors!
A: epoll is only supported on 2.6 Linux kernels. Either use a 2.6 kernel, or
re-run configure with the --without-epoll parameter. After configure
completed, you should see select() being listed as IO backend:
'(I/O backend: "select()"').
IV. Bugs!?
~~~~~~~~~~
@@ -76,4 +85,4 @@ A: Please file a bug report at <http://ngircd.barton.de/bugzilla/index.cgi>!
--
$Id: FAQ.txt,v 1.12 2008/01/02 22:47:58 alex Exp $
$Id: FAQ.txt,v 1.11 2005/12/09 21:14:56 fw Exp $

View File

@@ -1,45 +0,0 @@
ngIRCd - Next Generation IRC Server
-- GIT.txt --
The source code of ngIRCd is maintained using git, the stupid content
tracker.
I. Getting the source code
~~~~~~~~~~~~~~~~~~~~~~~~~~
To access the source tree anonymously, run:
$ git clone git://ngircd.barton.de/ngircd.git
Thereby a new folder "ngircd" will be created containing all the individual
source files.
The newly created directory ("ngircd") is the "working directory", all
git commands will be executed from within this directory in the future.
Please note: When checking out a fresh copy of ngIRCd using git, the
configure script doesn't exist; you have to run the autogen.sh shell script
(which is included in the source tree) to generate it. This requires you to
have GNU automake and GNU autoconf installed on your system.
To update the git tree:
$ git pull
This retrieves all changes and merges them into the current branch.
II. Contributing
~~~~~~~~~~~~~~~~
Patches should be sent to the ngircd mailing list. List homepage:
http://arthur.barton.de/mailman/listinfo/ngircd-ml
If you do not want to send them to the list, you can also mail them
to Alex Barton, <alex@barton.de>.
III. Write Access
~~~~~~~~~~~~~~~~~
If you want to contribute a couple of patches and write access to the git
repository would be handy, please contact Alex Barton, <alex@barton.de>.

View File

@@ -1,6 +1,6 @@
#
# ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2008 by Alexander Barton (alex@barton.de)
# Copyright (c)2001-2003 by Alexander Barton (alex@barton.de)
#
# Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen
# der GNU General Public License (GPL), wie von der Free Software Foundation
@@ -9,11 +9,13 @@
# Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
# der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
#
# $Id: Makefile.am,v 1.21 2005/11/29 20:59:57 alex Exp $
#
SUBDIRS = src
EXTRA_DIST = FAQ.txt GIT.txt Protocol.txt Platforms.txt README-AUX.txt \
README-BeOS.txt RFC.txt SSL.txt Zeroconf.txt sample-ngircd.conf
EXTRA_DIST = CVS.txt FAQ.txt Protocol.txt Platforms.txt README-AUX.txt \
README-BeOS.txt RFC.txt Zeroconf.txt sample-ngircd.conf
maintainer-clean-local:
rm -f Makefile Makefile.in

View File

@@ -74,4 +74,4 @@ Notes
(3) Using the kqueue() IO interface.
--
$Id: Platforms.txt,v 1.18 2006/10/08 14:09:16 alex Exp $
$Id: Platforms.txt,v 1.14.2.2 2007/04/03 22:08:51 fw Exp $

View File

@@ -1,7 +1,7 @@
ngIRCd - Next Generation IRC Server
(c)2001-2007 Alexander Barton,
(c)2001-2003 by Alexander Barton,
alex@barton.de, http://www.barton.de/
ngIRCd is free software and published under the
@@ -79,9 +79,6 @@ The following <serverflags> are defined at the moment:
peer understands this flag, it will send "MODE +I" and "MODE +b"
commands after the server link has been established.
- H: The server supports the "enhanced server handshake", see section II.2
for a detailed description.
- o: IRC operators are allowed to change channel- and channel-user-modes
even if they aren't channel-operator of the affected channel.
@@ -93,50 +90,7 @@ The optional parameter <options> is used to propagate server options as
defined in RFC 2813, section 4.1.1.
II.2 Enhanced Server Handshake
The "enhanced server handshake" is used when both servers support this IRC+
extension, which is indicated by the 'H' flag in the <serverflags> sent with
the PASS command, see section II.1.
It basically means, that after exchanging the PASS and SERVER commands the
server is not registered in the network (as usual), but that IRC numerics
are exchanged until the numeric 376 (ENDOFMOTD) is received. Afterwards the
peer is registered in the network as with the regular IRC protocol.
A server implementing the enhanced server handshake (and indicating this
using 'H' in the <serverflags>) MUST ignore all unknown numerics to it
silently.
In addition, such a server should at least send the numeric 005 (ISUPPORT)
to its peer, containing the following information. Syntax: <key>=<value>,
one token per IRC parameter. If the server has to send more than 12 token
it must send separate ISUPPORT numerics (this is a limitation of the IRC
protocol which allows at max 15 arguments per command).
- NICKLEN: Maximum nickname length. Default: 9.
- CASEMAPPING: Case mapping used for nick- and channel name comparing.
Default: "ascii", the chars [a-z] are lowercase of [A-Z].
- PREFIX: List of channel modes a person can get and the respective prefix
a channel or nickname will get in case the person has it. The order of the
modes goes from most powerful to least powerful. Default: "(ov)@+"
- CHANTYPES: Supported channel prefixes. Default: "#".
- CHANMODES: List of channel modes for 4 types, separated by comma (","):
Mode that adds or removes a nick or address to a list, mode that changes
a setting (both have always has a parameter), mode that changes a setting
and only has a parameter when set, and mode that changes a setting and
never has a parameter. For example "bI,k,l,imnPst".
- CHANLIMIT: Maximum number of channels allowed to join by channel prefix,
for example "#:10".
Please see <http://www.irc.org/tech_docs/005.html> for details.
The information exchanged using ISUPPORT can be used to detect configuration
incompatibilities (different maximum nick name length, for example) and
therefore to disconnect the peer prior to registering it in the network.
II.3 Exchange channel-modes, topics, and persistent channels
II.2 Exchange channel-modes, topics, and persistent channels
Command: CHANINFO
Parameters: <channel> +<modes> <key> <limit> [<topic>]
@@ -161,4 +115,4 @@ channel mode). In this case <limit> should be "0".
--
$Id: Protocol.txt,v 1.14 2007/11/21 12:16:35 alex Exp $
$Id: Protocol.txt,v 1.13 2005/08/27 19:00:06 alex Exp $

View File

@@ -37,4 +37,4 @@ Links:
--
$Id: Zeroconf.txt,v 1.2 2006/08/03 14:37:29 alex Exp $
$Id: Zeroconf.txt,v 1.1.2.1 2006/08/02 09:04:20 alex Exp $

View File

@@ -1,4 +1,4 @@
# $Id: sample-ngircd.conf,v 1.44 2008/01/07 23:02:29 alex Exp $
# $Id: sample-ngircd.conf,v 1.37.2.2 2007/04/03 22:08:51 fw Exp $
#
# This is a sample configuration file for the ngIRCd, which must be adepted
@@ -6,10 +6,6 @@
#
# Comments are started with "#" or ";".
#
# A lot of configuration options in this file start with a ";". You have
# to remove the ";" in front of each variable to actually set a value!
# The disabled variables are shown with example values for completeness.
#
# Use "ngircd --configtest" (see manual page ngircd(8)) to validate that the
# server interprets the configuration file as expected!
#
@@ -40,11 +36,9 @@
# one port, separated with ",". (Default: 6667)
;Ports = 6667, 6668, 6669
# comma seperated list of IP addresses on which the server should
# listen. Default values are:
# "0.0.0.0" or (if compiled with IPv6 support) "::,0.0.0.0"
# so the server listens on all IP addresses of the system by default.
;Listen = 127.0.0.1,192.168.0.1
# IP address on which the server should listen. (Default: empty,
# so the server listens on all IP addresses of the system)
;Listen = 1.2.3.4
# Text file with the "message of the day" (MOTD). This message will
# be shown to all users connecting to the server:
@@ -102,29 +96,17 @@
# Allow Pre-Defined Channels only (see Section [Channels])
;PredefChannelsOnly = no
# Don't do any DNS lookups when a client connects to the server.
;NoDNS = no
# try to connect to other irc servers using ipv4 and ipv6, if possible
;ConnectIPv6 = yes
;ConnectIPv4 = yes
# Maximum number of simultaneous connection the server is allowed
# to accept (0: unlimited):
;MaxConnections = 0
# to accept (<=0: unlimited):
;MaxConnections = -1
# Maximum number of simultaneous connections from a single IP address
# the server will accept (0: unlimited):
# the server will accept (<=0: unlimited):
;MaxConnectionsIP = 5
# Maximum number of channels a user can be member of (0: no limit):
# Maximum number of channels a user can be member of (<=0: no limit):
;MaxJoins = 10
# Maximum length of an user nick name (Default: 9, as in RFC 2812).
# Please note that all servers in an IRC network MUST use the same
# maximum nick name length!
;MaxNickLength = 9
[Operator]
# [Operator] sections are used to define IRC Operators. There may be
# more than one [Operator] block, one for each local operator.
@@ -163,10 +145,6 @@
# this server should establish the connection).
;Host = connect-to-host.the.net
# IP address to use as _source_ address for the connection. if unspecified,
# ngircd will let the operating system pick an address.
;Bind = 10.0.0.1
# Port of the server to which the ngIRCd should connect. If you
# assign no port the ngIRCd waits for incoming connections.
;Port = 6667
@@ -182,13 +160,6 @@
# Group of this server (optional)
;Group = 123
# Set the "Passive" option to "yes" if you don't want this ngIRCd to
# connect to the configured peer (same as leaving the "Port" variable
# empty). The advantage of this option is that you can actually configure
# a port an use the IRC command CONNECT more easily to manually connect
# this specific server later.
;Passive = no
[Server]
# More [Server] sections, if you like ...

1
doc/src/.gitignore vendored
View File

@@ -1 +0,0 @@
html

View File

@@ -8,7 +8,7 @@
# (at your option) any later version.
# Please read the file COPYING, README and AUTHORS for more information.
#
# $Id: Makefile.am,v 1.3 2006/12/28 14:04:28 alex Exp $
# $Id: Makefile.am,v 1.2.2.1 2007/04/03 22:08:52 fw Exp $
#
maintainer-clean-local:

2
man/.gitignore vendored
View File

@@ -1,2 +0,0 @@
ngircd.8
ngircd.conf.5

View File

@@ -9,25 +9,12 @@
# Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
# der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
#
# $Id: Makefile.am,v 1.6 2006/12/25 16:13:26 alex Exp $
# $Id: Makefile.am,v 1.5 2002/04/04 13:02:41 alex Exp $
#
TEMPLATE_MANS = ngircd.conf.5.tmpl ngircd.8.tmpl
SUFFIXES = .tmpl .
.tmpl:
sed \
-e s@:SBINDIR:@${sbindir}@ \
-e s@:BINDIR:@${bindir}@ \
-e s@:ETCDIR:@${sysconfdir}@ \
<$< >$@
man_MANS = ngircd.conf.5 ngircd.8
CLEANFILES = $(man_MANS)
EXTRA_DIST = $(TEMPLATE_MANS)
EXTRA_DIST = $(man_MANS)
maintainer-clean-local:
rm -f Makefile Makefile.in

View File

@@ -1,7 +1,7 @@
.\"
.\" $Id: ngircd.8.tmpl,v 1.2 2007/11/15 01:03:29 fw Exp $
.\" $Id: ngircd.8,v 1.11 2005/08/12 13:20:54 alex Exp $
.\"
.TH ngircd 8 "May 2008" ngircd "ngIRCd Manual"
.TH ngircd 8 "August 2005" ngircd "ngIRCd Manual"
.SH NAME
ngIRCd \- the next generation IRC daemon
.SH SYNOPSIS
@@ -23,8 +23,7 @@ Linux, Mac OS X, NetBSD, OpenBSD, Solaris, and Windows with Cygwin.
.PP
As ngIRCd relies on UNIX standards and uses GNU automake and GNU autoconf
there are good chances that it also supports other UNIX-based operating
systems as well. By default, ngIRCd writes diagnostic and informational messages using
the syslog mechanism.
systems as well.
.SH OPTIONS
The default behaviour of
.BR ngircd
@@ -50,17 +49,17 @@ CONNECT later on as IRC Operator to link this ngIRCd to other servers.
\fB\-t\fR, \fB\-\-configtest\fR
Read, validate and display the configuration; then exit.
.TP
\fB\-V\fR, \fB\-\-version\fR
\fB\-\-version\fR
Output version information and exit.
.TP
\fB\-h\fR, \fB\-\-help\fR
\fB\-\-help\fR
Display a brief help text and exit.
.SH FILES
.I :ETCDIR:/ngircd.conf
.I /usr/local/etc/ngircd.conf
.RS
The system wide default configuration file.
.RE
.I :ETCDIR:/ngircd.motd
.I /usr/local/etc/ngircd.motd
.RS
Default "message of the day" (MOTD).
.RE

View File

@@ -1,11 +1,11 @@
.\"
.\" $Id: ngircd.conf.5.tmpl,v 1.7 2007/11/23 16:26:03 fw Exp $
.\" $Id: ngircd.conf.5,v 1.20.2.1 2006/12/11 22:08:14 fw Exp $
.\"
.TH ngircd.conf 5 "May 2008" ngircd "ngIRCd Manual"
.TH ngircd.conf 5 "August 2005" ngircd "ngIRCd Manual"
.SH NAME
ngircd.conf \- configuration file of ngIRCd
.SH SYNOPSIS
.B :ETCDIR:/ngircd.conf
.B /usr/local/etc/ngircd.conf
.SH DESCRIPTION
.BR ngircd.conf
is the configuration file of the
@@ -26,20 +26,19 @@ Sections contain parameters of the form
.RE
.PP
Empty lines and any line beginning with a semicolon (';') or a hash ('#')
character are treated as a comment and will be ignored. Leading and trailing
whitespaces are trimmed before any processing takes place.
character is treated as a comment and will be ignored.
.PP
The file format is line-based - that means, each non-empty newline-terminated
line represents either a comment, a section name, or a parameter.
The file format is line-based - that means, each newline-terminated line
represents either a comment, a section name or a parameter.
.PP
Section and parameter names are not case sensitive.
.SH "SECTION OVERVIEW"
The file can contain blocks of four types: [Global], [Operator], [Server],
and [Channel].
.PP
The main configuration of the server is stored in the
In the
.I [Global]
section, like the server name, administrative information and the
section, there is the main configuration like the server name and the
ports on which the server should be listening. IRC operators of this
server are defined in
.I [Operator]
@@ -58,7 +57,7 @@ section is used to define the server main configuration, like the server
name and the ports on which the server should be listening.
.TP
\fBName\fR
Server name in the IRC network, must contain at least one dot (".").
Server name in the IRC network
.TP
\fBInfo\fR
Info text of the server. This will be shown by WHOIS and LINKS requests for
@@ -73,10 +72,8 @@ Ports on which the server should listen. There may be more than one port,
separated with ','. Default: 6667.
.TP
\fBListen\fR
A comma seperated list of IP address on which the server should listen.
If unset, the defaults value is "0.0.0.0", or, if ngircd was compiled
with IPv6 support, "::,0.0.0.0", so the server listens on all configured
IP addresses and interfaces by default.
The IP address on which the server should listen. Default is empty, so
the server listens on all configured IP addresses and interfaces.
.TP
\fBMotdFile\fR
Text file with the "message of the day" (MOTD). This message will be shown
@@ -84,8 +81,7 @@ to all users connecting to the server.
.TP
\fBMotdPhrase\fR
A simple Phrase (<256 chars) if you don't want to use a MOTD file.
If it is set no MotdFile will be read at all which can be handy if the
daemon should run inside a chroot directory.
If it is set no MotdFile will be read at all.
.TP
\fBServerUID\fR
User ID under which the server should run; you can use the name of the user
@@ -154,40 +150,19 @@ by non-chanops as if they were coming from the server. Default: no.
If enabled, no new channels can be created. Useful if
you do not want to have channels other than those defined in
the config file.
Default: No.
.TP
\fBNoDNS\fR
If enabled, ngircd will not make DNS lookups when clients connect.
If you configure ngircd to connect to other servers, ngircd may still
perform a DNS lookup if required.
Default: No.
.TP
\fBConnectIPv4\fR
Set this to no if you do not want ngircd to connect to other irc servers using ipv4.
This allows use of ngircd in ipv6-only setups.
Default: Yes.
.TP
\fBConnectIPv6\fR
Set this to no if you do not want ngircd to connect to other irc servers using ipv6.
Default: Yes.
.TP
\fBMaxConnections\fR
Maximum number of simultaneous connection the server is allowed to accept
(0: unlimited). Default: 0.
(<=0: unlimited). Default: -1.
.TP
\fBMaxConnectionsIP\fR
Maximum number of simultaneous connections from a single IP address that
the server will accept (0: unlimited). This configuration options lowers
the server will accept (<=0: unlimited). This configuration options lowers
the risk of denial of service attacks (DoS). Default: 5.
.TP
\fBMaxJoins\fR
Maximum number of channels a user can be member of (0: no limit).
Maximum number of channels a user can be member of (<=0: no limit).
Default: 10.
.TP
\fBMaxNickLength\fR
Maximum length of an user nick name (Default: 9, as in RFC 2812). Please
note that all servers in an IRC network MUST use the same maximum nick name
length!
.SH [OPERATOR]
.I [Operator]
sections are used to define IRC Operators. There may be more than one
@@ -207,34 +182,27 @@ Example: nick!ident@*.example.com
Other servers are configured in
.I [Server]
sections. If you configure a port for the connection, then this ngIRCd
tries to connect to to the other server on the given port (active);
if not, it waits for the other server to connect (passive).
tries to connect to to the other server on the given port; if not, it waits
for the other server to connect.
.PP
ngIRCd supports "server groups": You can assign an "ID" to every server
with which you want this ngIRCd to link, and the daemon ensures that at
any given time only one direct link exists to servers with the same ID.
So if a server of a group won't answer, ngIRCd tries to connect to the next
server in the given group (="with the same ID"), but never tries to connect
to more than one server of this group simultaneously.
The ngIRCd allows "server groups": You can assign an "ID" to every server
with which you want this ngIRCd to link. If a server of a group won't
answer, the ngIRCd tries to connect to the next server in the given group.
But ngIRCd never tries to connect to two servers with the same group ID.
.PP
There may be more than one
.I [Server]
block.
.TP
\fBName\fR
IRC name of the remote server.
IRC name of the server
.TP
\fBHost\fR
Internet host name (or IP address) of the peer.
.TP
\fBBind\fR
IP address to use as source IP for the outgoing connection. Default ist
to let the operating system decide.
Internet host name of the peer
.TP
\fBPort\fR
Port of the remote server to which ngIRCd should connect (active).
If no port is assigned to a configured server, the daemon only waits for
incoming connections (passive).
Port of the server to which the ngIRCd should connect. If you assign no port
the ngIRCd waits for incoming connections.
.TP
\fBMyPassword\fR
Own password for this connection. This password has to be configured as
@@ -246,10 +214,6 @@ Foreign password for this connection. This password has to be configured as
.TP
\fBGroup\fR
Group of this server (optional).
.TP
\fBPassive\fR
Disable automatic connection even if port value is specified. Default: false.
You can use the IRC Operator command CONNECT later on to create the link.
.SH [CHANNEL]
Pre-defined channels can be configured in
.I [Channel]
@@ -264,19 +228,13 @@ There may be more than one
block.
.TP
\fBName\fR
Name of the channel, including channel prefix ("#").
Name of the channel
.TP
\fBTopic\fR
Topic for this channel.
Topic for this channel
.TP
\fBModes\fR
Initial channel modes.
.TP
\fBKey\fR
Sets initial channel key (only relevant if mode k is set).
.TP
\fBMaxUsers\fR
Set maximum user limit for this channel (only relevant if mode l is set).
.SH HINTS
It's wise to use "ngircd --configtest" to validate the configuration file
after changing it. See

3
src/.gitignore vendored
View File

@@ -1,3 +0,0 @@
config.h
config.h.in
stamp-h1

View File

@@ -8,10 +8,10 @@
# (at your option) any later version.
# Please read the file COPYING, README and AUTHORS for more information.
#
# $Id: Makefile.am,v 1.8 2008/02/26 22:04:15 fw Exp $
# $Id: Makefile.am,v 1.7 2005/07/22 21:01:03 alex Exp $
#
SUBDIRS = portab tool ipaddr ngircd testsuite
SUBDIRS = portab tool ngircd testsuite
maintainer-clean-local:
rm -f Makefile Makefile.in config.h config.h.in stamp-h.in

View File

@@ -1,14 +0,0 @@
AUTOMAKE_OPTIONS = ansi2knr
INCLUDES = -I$(srcdir)/../portab
noinst_LIBRARIES = libngipaddr.a
libngipaddr_a_SOURCES = ng_ipaddr.c
noinst_HEADERS = ng_ipaddr.h
maintainer-clean-local:
rm -f Makefile Makefile.in
# -eof-

View File

@@ -1,167 +0,0 @@
/*
* Functions for AF_ agnostic ipv4/ipv6 handling.
*
* (c) 2008 Florian Westphal <fw@strlen.de>, public domain.
*/
#include "portab.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
#ifdef HAVE_GETADDRINFO
#include <netdb.h>
#include <sys/types.h>
#endif
#include "ng_ipaddr.h"
GLOBAL bool
ng_ipaddr_init(ng_ipaddr_t *addr, const char *ip_str, UINT16 port)
{
#ifdef HAVE_GETADDRINFO
int ret;
char portstr[64];
struct addrinfo *res0;
struct addrinfo hints;
assert(ip_str);
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_NUMERICHOST;
/* some getaddrinfo implementations require that ai_socktype is set. */
hints.ai_socktype = SOCK_STREAM;
/* silly, but ngircd stores UINT16 in server config, not string */
snprintf(portstr, sizeof(portstr), "%u", (unsigned int) port);
ret = getaddrinfo(ip_str, portstr, &hints, &res0);
assert(ret == 0);
if (ret != 0)
return false;
assert(sizeof(*addr) >= res0->ai_addrlen);
if (sizeof(*addr) >= res0->ai_addrlen)
memcpy(addr, res0->ai_addr, res0->ai_addrlen);
else
ret = -1;
freeaddrinfo(res0);
return ret == 0;
#else /* HAVE_GETADDRINFO */
assert(ip_str);
addr->sin4.sin_family = AF_INET;
# ifdef HAVE_INET_ATON
if (inet_aton(ip_str, &addr->sin4.sin_addr) == 0)
return false;
# else
addr->sin4.sin_addr.s_addr = inet_addr(ip_str);
if (addr->sin4.sin_addr.s_addr == (unsigned) -1)
return false;
# endif
ng_ipaddr_setport(addr, port);
return true;
#endif /* HAVE_GETADDRINFO */
}
GLOBAL void
ng_ipaddr_setport(ng_ipaddr_t *a, UINT16 port)
{
#ifdef WANT_IPV6
int af;
assert(a != NULL);
af = a->sa.sa_family;
assert(af == AF_INET || af == AF_INET6);
switch (af) {
case AF_INET:
a->sin4.sin_port = htons(port);
break;
case AF_INET6:
a->sin6.sin6_port = htons(port);
break;
}
#else /* WANT_IPV6 */
assert(a != NULL);
assert(a->sin4.sin_family == AF_INET);
a->sin4.sin_port = htons(port);
#endif /* WANT_IPV6 */
}
GLOBAL bool
ng_ipaddr_ipequal(const ng_ipaddr_t *a, const ng_ipaddr_t *b)
{
assert(a != NULL);
assert(b != NULL);
#ifdef WANT_IPV6
if (a->sa.sa_family != b->sa.sa_family)
return false;
assert(ng_ipaddr_salen(a) == ng_ipaddr_salen(b));
switch (a->sa.sa_family) {
case AF_INET6:
return IN6_ARE_ADDR_EQUAL(&a->sin6.sin6_addr, &b->sin6.sin6_addr);
case AF_INET:
return memcmp(&a->sin4.sin_addr, &b->sin4.sin_addr, sizeof(a->sin4.sin_addr)) == 0;
}
return false;
#else
assert(a->sin4.sin_family == AF_INET);
assert(b->sin4.sin_family == AF_INET);
return memcmp(&a->sin4.sin_addr, &b->sin4.sin_addr, sizeof(a->sin4.sin_addr)) == 0;
#endif
}
#ifdef WANT_IPV6
GLOBAL const char *
ng_ipaddr_tostr(const ng_ipaddr_t *addr)
{
static char strbuf[NG_INET_ADDRSTRLEN];
strbuf[0] = 0;
ng_ipaddr_tostr_r(addr, strbuf);
return strbuf;
}
/* str must be at least NG_INET_ADDRSTRLEN bytes long */
GLOBAL bool
ng_ipaddr_tostr_r(const ng_ipaddr_t *addr, char *str)
{
#ifdef HAVE_GETNAMEINFO
const struct sockaddr *sa = (const struct sockaddr *) addr;
int ret;
*str = 0;
ret = getnameinfo(sa, ng_ipaddr_salen(addr),
str, NG_INET_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST);
/*
* avoid leading ':'.
* causes mis-interpretation of client host in e.g. /WHOIS
*/
if (*str == ':') {
char tmp[NG_INET_ADDRSTRLEN] = "0";
ret = getnameinfo(sa, ng_ipaddr_salen(addr),
tmp+1, sizeof(tmp) -1, NULL, 0, NI_NUMERICHOST);
if (ret == 0)
strlcpy(str, tmp, NG_INET_ADDRSTRLEN);
}
assert (ret == 0);
return ret == 0;
#else
abort(); /* WANT_IPV6 depends on HAVE_GETNAMEINFO */
#endif
}
#endif /* WANT_IPV6 */
/* -eof- */

View File

@@ -1,117 +0,0 @@
/*
* Functions for AF_ agnostic ipv4/ipv6 handling.
*
* (c) 2008 Florian Westphal <fw@strlen.de>, public domain.
*/
#ifndef NG_IPADDR_HDR
#define NG_IPADDR_HDR
#include "portab.h"
#include <sys/socket.h>
#include <netinet/in.h>
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#else
# define PF_INET AF_INET
#endif
#ifdef WANT_IPV6
#define NG_INET_ADDRSTRLEN INET6_ADDRSTRLEN
#else
#define NG_INET_ADDRSTRLEN 16
#endif
#ifdef WANT_IPV6
typedef union {
struct sockaddr sa;
struct sockaddr_in sin4;
struct sockaddr_in6 sin6;
} ng_ipaddr_t;
#else
/* assume compiler can't deal with typedef struct {... */
struct NG_IP_ADDR_DONTUSE {
struct sockaddr_in sin4;
};
typedef struct NG_IP_ADDR_DONTUSE ng_ipaddr_t;
#endif
static inline int
ng_ipaddr_af(const ng_ipaddr_t *a)
{
#ifdef WANT_IPV6
return a->sa.sa_family;
#else
assert(a->sin4.sin_family == 0 || a->sin4.sin_family == AF_INET);
return a->sin4.sin_family;
#endif
}
static inline socklen_t
ng_ipaddr_salen(const ng_ipaddr_t *a)
{
#ifdef WANT_IPV6
assert(a->sa.sa_family == AF_INET || a->sa.sa_family == AF_INET6);
if (a->sa.sa_family == AF_INET6)
return sizeof(a->sin6);
#endif
assert(a->sin4.sin_family == AF_INET);
return sizeof(a->sin4);
}
static inline UINT16
ng_ipaddr_getport(const ng_ipaddr_t *a)
{
#ifdef WANT_IPV6
int af = a->sa.sa_family;
assert(af == AF_INET || af == AF_INET6);
if (af == AF_INET6)
return ntohs(a->sin6.sin6_port);
#endif /* WANT_IPV6 */
assert(a->sin4.sin_family == AF_INET);
return ntohs(a->sin4.sin_port);
}
/*
* init a ng_ipaddr_t object.
* @param addr: pointer to ng_ipaddr_t to initialize.
* @param ip_str: ip address in dotted-decimal (ipv4) or hexadecimal (ipv6) notation
* @param port: transport layer port number to use.
*/
GLOBAL bool ng_ipaddr_init PARAMS((ng_ipaddr_t *addr, const char *ip_str, UINT16 port));
/* set sin4/sin6_port, depending on a->sa_family */
GLOBAL void ng_ipaddr_setport PARAMS((ng_ipaddr_t *a, UINT16 port));
/* return true if a and b have the same IP address. If a and b have different AF, return false. */
GLOBAL bool ng_ipaddr_ipequal PARAMS((const ng_ipaddr_t *a, const ng_ipaddr_t *b));
#ifdef WANT_IPV6
/* convert struct sockaddr to string, returns pointer to static buffer */
GLOBAL const char *ng_ipaddr_tostr PARAMS((const ng_ipaddr_t *addr));
/* convert struct sockaddr to string. dest must be NG_INET_ADDRSTRLEN bytes long */
GLOBAL bool ng_ipaddr_tostr_r PARAMS((const ng_ipaddr_t *addr, char *dest));
#else
static inline const char *
ng_ipaddr_tostr(const ng_ipaddr_t *addr) { return inet_ntoa(addr->sin4.sin_addr); }
static inline bool
ng_ipaddr_tostr_r(const ng_ipaddr_t *addr, char *d)
{
strlcpy(d, inet_ntoa(addr->sin4.sin_addr), NG_INET_ADDRSTRLEN);
return true;
}
#endif
#endif
/* -eof- */

View File

@@ -1,5 +0,0 @@
check-help
check-version
cvs-version.h
cvs-version.new
ngircd

View File

@@ -8,12 +8,12 @@
# (at your option) any later version.
# Please read the file COPYING, README and AUTHORS for more information.
#
# $Id: Makefile.am,v 1.51 2008/02/26 22:04:17 fw Exp $
# $Id: Makefile.am,v 1.49 2006/03/11 01:48:50 alex Exp $
#
AUTOMAKE_OPTIONS = ../portab/ansi2knr
INCLUDES = -I$(srcdir)/../portab -I$(srcdir)/../tool -I$(srcdir)/../ipaddr
INCLUDES = -I$(srcdir)/../portab -I$(srcdir)/../tool
LINTARGS = -weak -warnunixlib +unixlib -booltype BOOLEAN \
-varuse -retvalother -emptyret -unrecog
@@ -23,20 +23,20 @@ sbin_PROGRAMS = ngircd
ngircd_SOURCES = ngircd.c array.c channel.c client.c conf.c conn.c conn-func.c \
conn-zip.c hash.c io.c irc.c irc-channel.c irc-info.c irc-login.c \
irc-mode.c irc-op.c irc-oper.c irc-server.c irc-write.c lists.c log.c \
match.c numeric.c parse.c rendezvous.c resolve.c
match.c parse.c rendezvous.c resolve.c
ngircd_LDFLAGS = -L../portab -L../tool -L../ipaddr
ngircd_LDFLAGS = -L../portab -L../tool
ngircd_LDADD = -lngportab -lngtool -lngipaddr
ngircd_LDADD = -lngportab -lngtool
noinst_HEADERS = ngircd.h array.h channel.h client.h conf.h conn.h conn-func.h \
conn-zip.h hash.h io.h irc.h irc-channel.h irc-info.h irc-login.h \
irc-mode.h irc-op.h irc-oper.h irc-server.h irc-write.h lists.h log.h \
match.h numeric.h parse.h rendezvous.h resolve.h \
match.h parse.h rendezvous.h resolve.h \
defines.h messages.h
clean-local:
rm -f check-version check-help lint.out
rm -f check-version check-help lint.out cvs-version.*
maintainer-clean-local:
rm -f Makefile Makefile.in
@@ -77,6 +77,23 @@ lint:
|| echo "Result: no warnings found."; \
echo; [ $$warnings -gt 0 ] && exit 1
ngircd.c: cvs-version.h
irc-login.c: cvs-version.h
irc-info.c: cvs-version.h
cvs-version.h: cvs-date
cvs-date:
grep VERSION ../config.h | grep "CVS" \
&& echo "#define CVSDATE \"$$( grep "\$$Id" $(srcdir)/*.c \
| $(AWK) "{ print \$$9 }" | sort | tail -1 \
| sed -e "s/\//-/g" )\"" > cvs-version.new \
|| echo "" > cvs-version.new
diff cvs-version.h cvs-version.new 2>/dev/null \
|| cp cvs-version.new cvs-version.h
TESTS = check-version check-help
# -eof-

View File

@@ -12,7 +12,7 @@
#include "array.h"
static char UNUSED id[] = "$Id: array.c,v 1.15 2007/11/18 15:05:35 alex Exp $";
static char UNUSED id[] = "$Id: array.c,v 1.11.2.3 2007/04/03 22:08:52 fw Exp $";
#include <assert.h>
@@ -28,9 +28,9 @@ static char UNUSED id[] = "$Id: array.c,v 1.15 2007/11/18 15:05:35 alex Exp $";
#define array_UNUSABLE(x) ( !(x)->mem || (0 == (x)->allocated) )
#define ALIGN_32U(x) (((x)+(unsigned)31 ) & ~((unsigned)31))
#define ALIGN_1024U(x) (((x)+(unsigned)1023) & ~((unsigned)1023))
#define ALIGN_4096U(x) (((x)+(unsigned)4095) & ~((unsigned)4095))
#define ALIGN_32U(x) (((x)+31U ) & ~(31U))
#define ALIGN_1024U(x) (((x)+1023U) & ~(1023U))
#define ALIGN_4096U(x) (((x)+4095U) & ~(4095U))
static bool

View File

@@ -17,7 +17,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: channel.c,v 1.65 2008/02/05 16:31:35 fw Exp $";
static char UNUSED id[] = "$Id: channel.c,v 1.56.2.4 2007/07/31 20:48:15 alex Exp $";
#include "imp.h"
#include <assert.h>
@@ -56,7 +56,7 @@ static CL2CHAN *My_Cl2Chan;
static CL2CHAN *Get_Cl2Chan PARAMS(( CHANNEL *Chan, CLIENT *Client ));
static CL2CHAN *Add_Client PARAMS(( CHANNEL *Chan, CLIENT *Client ));
static bool Remove_Client PARAMS(( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, const char *Reason, bool InformServer ));
static bool Remove_Client PARAMS(( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, char *Reason, bool InformServer ));
static CL2CHAN *Get_First_Cl2Chan PARAMS(( CLIENT *Client, CHANNEL *Chan ));
static CL2CHAN *Get_Next_Cl2Chan PARAMS(( CL2CHAN *Start, CLIENT *Client, CHANNEL *Chan ));
static bool Delete_Channel PARAMS(( CHANNEL *Chan ));
@@ -201,38 +201,25 @@ Channel_Join( CLIENT *Client, char *Name )
} /* Channel_Join */
/**
* Remove client from channel.
* This function lets a client lead a channel. First, the function checks
* if the channel exists and the client is a member of it and sends out
* appropriate error messages if not. The real work is done by the function
* Remove_Client().
*/
GLOBAL bool
Channel_Part(CLIENT * Client, CLIENT * Origin, const char *Name, const char *Reason)
Channel_Part( CLIENT *Client, CLIENT *Origin, char *Name, char *Reason )
{
CHANNEL *chan;
assert(Client != NULL);
assert(Name != NULL);
assert(Reason != NULL);
assert( Client != NULL );
assert( Name != NULL );
assert( Reason != NULL );
chan = Channel_Search(Name);
if (!chan) {
IRC_WriteStrClient(Client, ERR_NOSUCHCHANNEL_MSG,
Client_ID(Client), Name);
return false;
}
if (!Get_Cl2Chan(chan, Client)) {
IRC_WriteStrClient(Client, ERR_NOTONCHANNEL_MSG,
Client_ID(Client), Name);
chan = Channel_Search( Name );
if(( ! chan ) || ( ! Get_Cl2Chan( chan, Client )))
{
IRC_WriteStrClient( Client, ERR_NOSUCHCHANNEL_MSG, Client_ID( Client ), Name );
return false;
}
if (!Remove_Client(REMOVE_PART, chan, Client, Origin, Reason, true))
return false;
else
return true;
/* User aus Channel entfernen */
if( ! Remove_Client( REMOVE_PART, chan, Client, Origin, Reason, true)) return false;
else return true;
} /* Channel_Part */
@@ -401,7 +388,7 @@ Channel_Next( CHANNEL *Chan )
GLOBAL CHANNEL *
Channel_Search( const char *Name )
Channel_Search( char *Name )
{
/* Channel-Struktur suchen */
@@ -708,66 +695,38 @@ Channel_SetMaxUsers(CHANNEL *Chan, unsigned long Count)
} /* Channel_SetMaxUsers */
static bool
Can_Send_To_Channel(CHANNEL *Chan, CLIENT *From)
GLOBAL bool
Channel_Write( CHANNEL *Chan, CLIENT *From, CLIENT *Client, char *Text )
{
bool is_member, has_voice, is_op;
bool is_member, has_voice, is_op, ok;
/* Okay, target is a channel */
is_member = has_voice = is_op = false;
if (Channel_IsMemberOf(Chan, From)) {
if( Channel_IsMemberOf( Chan, From ))
{
is_member = true;
if (strchr(Channel_UserModes(Chan, From), 'v'))
has_voice = true;
if (strchr(Channel_UserModes(Chan, From), 'o'))
is_op = true;
if( strchr( Channel_UserModes( Chan, From ), 'v' )) has_voice = true;
if( strchr( Channel_UserModes( Chan, From ), 'o' )) is_op = true;
}
/*
* Is the client allowed to write to channel?
*
* If channel mode n set: non-members cannot send to channel.
* If channel mode m set: need voice.
*/
if (strchr(Channel_Modes(Chan), 'n') && !is_member)
return false;
/* Is the client allowed to write to channel? */
ok = true;
if( strchr( Channel_Modes( Chan ), 'n' ) && ( ! is_member )) ok = false;
if( strchr( Channel_Modes( Chan ), 'm' ) && ( ! is_op ) && ( ! has_voice )) ok = false;
if (is_op || has_voice)
return true;
/* Is the client banned? */
if( Lists_Check(&Chan->list_bans, From))
{
/* Client is banned, but is he channel operator or has voice? */
if(( ! has_voice ) && ( ! is_op )) ok = false;
}
if (strchr(Channel_Modes(Chan), 'm'))
return false;
if( ! ok ) return IRC_WriteStrClient( From, ERR_CANNOTSENDTOCHAN_MSG, Client_ID( From ), Channel_Name( Chan ));
return !Lists_Check(&Chan->list_bans, From);
}
GLOBAL bool
Channel_Write(CHANNEL *Chan, CLIENT *From, CLIENT *Client, const char *Text)
{
if (!Can_Send_To_Channel(Chan, From))
return IRC_WriteStrClient(From, ERR_CANNOTSENDTOCHAN_MSG, Client_ID(From), Channel_Name(Chan));
if (Client_Conn(From) > NONE)
Conn_UpdateIdle(Client_Conn(From));
return IRC_WriteStrChannelPrefix(Client, Chan, From, true,
"PRIVMSG %s :%s", Channel_Name(Chan), Text);
}
GLOBAL bool
Channel_Notice(CHANNEL *Chan, CLIENT *From, CLIENT *Client, const char *Text)
{
if (!Can_Send_To_Channel(Chan, From))
return true; /* no error, see RFC 2812 */
if (Client_Conn(From) > NONE)
Conn_UpdateIdle(Client_Conn(From));
return IRC_WriteStrChannelPrefix(Client, Chan, From, true,
"NOTICE %s :%s", Channel_Name(Chan), Text);
}
/* Send text */
if( Client_Conn( From ) > NONE ) Conn_UpdateIdle( Client_Conn( From ));
return IRC_WriteStrChannelPrefix( Client, Chan, From, true, "PRIVMSG %s :%s", Channel_Name( Chan ), Text );
} /* Channel_Write */
GLOBAL CHANNEL *
@@ -842,7 +801,7 @@ Add_Client( CHANNEL *Chan, CLIENT *Client )
static bool
Remove_Client( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, const char *Reason, bool InformServer )
Remove_Client( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, char *Reason, bool InformServer )
{
CL2CHAN *cl2chan, *last_cl2chan;
CHANNEL *c;
@@ -916,7 +875,7 @@ Remove_Client( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, const ch
{
if( ! Get_First_Cl2Chan( NULL, Chan )) Delete_Channel( Chan );
}
return true;
} /* Remove_Client */
@@ -1027,9 +986,9 @@ Delete_Channel( CHANNEL *Chan )
Log( LOG_DEBUG, "Freed channel structure for \"%s\".", Chan->name );
array_free(&chan->topic);
Lists_Free(&chan->list_bans);
Lists_Free(&chan->list_invites);
/* Invite- und Ban-Lists aufraeumen */
Lists_Free( &chan->list_bans );
Lists_Free( &chan->list_invites );
/* Neu verketten und freigeben */
if( last_chan ) last_chan->next = chan->next;

View File

@@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: channel.h,v 1.35 2008/02/05 16:31:35 fw Exp $
* $Id: channel.h,v 1.29.2.2 2007/04/03 20:23:31 fw Exp $
*
* Channel management (header)
*/
@@ -64,7 +64,7 @@ GLOBAL void Channel_InitPredefined PARAMS(( void ));
GLOBAL void Channel_Exit PARAMS(( void ));
GLOBAL bool Channel_Join PARAMS(( CLIENT *Client, char *Name ));
GLOBAL bool Channel_Part PARAMS(( CLIENT *Client, CLIENT *Origin, const char *Name, const char *Reason ));
GLOBAL bool Channel_Part PARAMS(( CLIENT *Client, CLIENT *Origin, char *Name, char *Reason ));
GLOBAL void Channel_Quit PARAMS(( CLIENT *Client, char *Reason ));
@@ -85,7 +85,7 @@ GLOBAL void Channel_SetModes PARAMS(( CHANNEL *Chan, char *Modes ));
GLOBAL void Channel_SetKey PARAMS(( CHANNEL *Chan, char *Key ));
GLOBAL void Channel_SetMaxUsers PARAMS(( CHANNEL *Chan, unsigned long Count ));
GLOBAL CHANNEL *Channel_Search PARAMS(( const char *Name ));
GLOBAL CHANNEL *Channel_Search PARAMS(( char *Name ));
GLOBAL CHANNEL *Channel_First PARAMS(( void ));
GLOBAL CHANNEL *Channel_Next PARAMS(( CHANNEL *Chan ));
@@ -109,8 +109,7 @@ GLOBAL char *Channel_UserModes PARAMS(( CHANNEL *Chan, CLIENT *Client ));
GLOBAL bool Channel_IsMemberOf PARAMS(( CHANNEL *Chan, CLIENT *Client ));
GLOBAL bool Channel_Write PARAMS(( CHANNEL *Chan, CLIENT *From, CLIENT *Client, const char *Text ));
GLOBAL bool Channel_Notice PARAMS(( CHANNEL *Chan, CLIENT *From, CLIENT *Client, const char *Text));
GLOBAL bool Channel_Write PARAMS(( CHANNEL *Chan, CLIENT *From, CLIENT *Client, char *Text ));
GLOBAL CHANNEL *Channel_Create PARAMS(( char *Name ));

View File

@@ -17,7 +17,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: client.c,v 1.98 2008/04/04 19:30:01 fw Exp $";
static char UNUSED id[] = "$Id: client.c,v 1.91.2.2 2007/04/03 22:08:52 fw Exp $";
#include "imp.h"
#include <assert.h>
@@ -55,7 +55,6 @@ static char GetID_Buffer[GETID_LEN];
static WHOWAS My_Whowas[MAX_WHOWAS];
static int Last_Whowas = -1;
static long Max_Users, My_Max_Users;
static unsigned long Count PARAMS(( CLIENT_TYPE Type ));
@@ -70,6 +69,9 @@ static CLIENT *Init_New_Client PARAMS((CONN_ID Idx, CLIENT *Introducer,
char *Info, int Hops, int Token, char *Modes, bool Idented));
long Max_Users = 0, My_Max_Users = 0;
GLOBAL void
Client_Init( void )
{
@@ -92,10 +94,9 @@ Client_Init( void )
This_Server->hops = 0;
gethostname( This_Server->host, CLIENT_HOST_LEN );
if (!Conf_NoDNS) {
h = gethostbyname( This_Server->host );
if (h) strlcpy(This_Server->host, h->h_name, sizeof(This_Server->host));
}
h = gethostbyname( This_Server->host );
if( h ) strlcpy( This_Server->host, h->h_name, sizeof( This_Server->host ));
Client_SetID( This_Server, Conf_ServerName );
Client_SetInfo( This_Server, Conf_ServerInfo );
@@ -607,8 +608,7 @@ Client_ID( CLIENT *Client )
assert( Client != NULL );
#ifdef DEBUG
if(Client->type == CLIENT_USER)
assert(strlen(Client->id) < Conf_MaxNickLength);
if( Client->type == CLIENT_USER ) assert( strlen( Client->id ) < CLIENT_NICK_LEN );
#endif
if( Client->id[0] ) return Client->id;
@@ -951,7 +951,7 @@ Client_IsValidNick( const char *Nick )
if( Nick[0] == '#' ) return false;
if( strchr( goodchars, Nick[0] )) return false;
if( strlen( Nick ) >= Conf_MaxNickLength) return false;
if( strlen( Nick ) >= CLIENT_NICK_LEN ) return false;
ptr = Nick;
while( *ptr )

View File

@@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: client.h,v 1.46 2007/01/23 16:07:19 alex Exp $
* $Id: client.h,v 1.42.2.3 2007/04/03 22:08:52 fw Exp $
*
* Client management (header)
*/

View File

@@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: conf.c,v 1.105 2008/03/18 20:12:47 fw Exp $";
static char UNUSED id[] = "$Id: conf.c,v 1.92.2.4 2007/04/03 22:08:52 fw Exp $";
#include "imp.h"
#include <assert.h>
@@ -56,21 +56,9 @@ static CONF_SERVER New_Server;
static int New_Server_Idx;
#ifdef WANT_IPV6
/*
* these options appeared in ngircd 0.12; they are here
* for backwards compatibility. They should be removed
* in the future. Instead of setting these options,
* the "Listen" option should be set accordingly.
*/
static bool Conf_ListenIPv6;
static bool Conf_ListenIPv4;
#endif
static void Set_Defaults PARAMS(( bool InitServers ));
static bool Read_Config PARAMS(( bool ngircd_starting ));
static bool Validate_Config PARAMS(( bool TestOnly, bool Rehash ));
static void Read_Config PARAMS(( void ));
static void Validate_Config PARAMS(( bool TestOnly, bool Rehash ));
static void Handle_GLOBAL PARAMS(( int Line, char *Var, char *Arg ));
static void Handle_OPERATOR PARAMS(( int Line, char *Var, char *Arg ));
@@ -146,33 +134,24 @@ ports_parse(array *a, int Line, char *Arg)
GLOBAL void
Conf_Init( void )
{
Read_Config( true );
Set_Defaults( true );
Read_Config( );
Validate_Config(false, false);
} /* Config_Init */
GLOBAL bool
GLOBAL void
Conf_Rehash( void )
{
if (!Read_Config(false))
return false;
Set_Defaults( false );
Read_Config( );
Validate_Config(false, true);
/* Update CLIENT structure of local server */
Client_SetInfo(Client_ThisServer(), Conf_ServerInfo);
return true;
} /* Config_Rehash */
static const char*
yesno_to_str(int boolean_value)
{
if (boolean_value)
return "yes";
return "no";
}
GLOBAL int
Conf_Test( void )
{
@@ -182,14 +161,12 @@ Conf_Test( void )
struct group *grp;
unsigned int i;
char *topic;
bool config_valid;
Use_Log = false;
Set_Defaults( true );
if (! Read_Config(true))
return 1;
config_valid = Validate_Config(true, false);
Read_Config( );
Validate_Config(true, false);
/* If stdin and stdout ("you can read our nice message and we can
* read in your keypress") are valid tty's, wait for a key: */
@@ -214,7 +191,8 @@ Conf_Test( void )
fputs(" Ports = ", stdout);
ports_puts(&Conf_ListenPorts);
printf(" Listen = %s\n", Conf_ListenAddress);
printf( " Listen = %s\n", Conf_ListenAddress );
pwd = getpwuid( Conf_UID );
if( pwd ) printf( " ServerUID = %s\n", pwd->pw_name );
else printf( " ServerUID = %ld\n", (long)Conf_UID );
@@ -224,24 +202,12 @@ Conf_Test( void )
printf( " PingTimeout = %d\n", Conf_PingTimeout );
printf( " PongTimeout = %d\n", Conf_PongTimeout );
printf( " ConnectRetry = %d\n", Conf_ConnectRetry );
printf( " OperCanUseMode = %s\n", yesno_to_str(Conf_OperCanMode));
printf( " OperServerMode = %s\n", yesno_to_str(Conf_OperServerMode));
printf( " PredefChannelsOnly = %s\n", yesno_to_str(Conf_PredefChannelsOnly));
printf( " NoDNS = %s\n", yesno_to_str(Conf_NoDNS));
#ifdef WANT_IPV6
/* both are deprecated, only mention them if their default value changed. */
if (!Conf_ListenIPv6)
puts(" ListenIPv6 = no");
if (!Conf_ListenIPv4)
puts(" ListenIPv4 = no");
printf(" ConnectIPv4 = %s\n", yesno_to_str(Conf_ConnectIPv6));
printf(" ConnectIPv6 = %s\n", yesno_to_str(Conf_ConnectIPv4));
#endif
printf( " MaxConnections = %ld\n", Conf_MaxConnections);
printf( " MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP);
printf( " MaxJoins = %d\n", Conf_MaxJoins>0 ? Conf_MaxJoins : -1);
printf( " MaxNickLength = %u\n\n", Conf_MaxNickLength - 1);
printf( " OperCanUseMode = %s\n", Conf_OperCanMode == true ? "yes" : "no" );
printf( " OperServerMode = %s\n", Conf_OperServerMode == true? "yes" : "no" );
printf( " PredefChannelsOnly = %s\n", Conf_PredefChannelsOnly == true ? "yes" : "no" );
printf( " MaxConnections = %ld\n", Conf_MaxConnections>0 ? Conf_MaxConnections : -1);
printf( " MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP>0 ? Conf_MaxConnectionsIP : -1);
printf( " MaxJoins = %d\n\n", Conf_MaxJoins>0 ? Conf_MaxJoins : -1);
for( i = 0; i < Conf_Oper_Count; i++ ) {
if( ! Conf_Oper[i].name[0] ) continue;
@@ -264,8 +230,7 @@ Conf_Test( void )
printf( " Port = %u\n", (unsigned int)Conf_Server[i].port );
printf( " MyPassword = %s\n", Conf_Server[i].pwd_in );
printf( " PeerPassword = %s\n", Conf_Server[i].pwd_out );
printf( " Group = %d\n", Conf_Server[i].group );
printf( " Passive = %s\n\n", Conf_Server[i].flags & CONF_SFLAG_DISABLED ? "yes" : "no");
printf( " Group = %d\n\n", Conf_Server[i].group );
}
for( i = 0; i < Conf_Channel_Count; i++ ) {
@@ -282,7 +247,7 @@ Conf_Test( void )
printf( " Topic = %s\n\n", topic ? topic : "");
}
return (config_valid ? 0 : 1);
return 0;
} /* Conf_Test */
@@ -371,24 +336,6 @@ Conf_EnableServer( char *Name, UINT16 Port )
} /* Conf_EnableServer */
GLOBAL bool
Conf_EnablePassiveServer(const char *Name)
{
/* Enable specified server */
int i;
assert( Name != NULL );
for (i = 0; i < MAX_SERVERS; i++) {
if ((strcasecmp( Conf_Server[i].name, Name ) == 0) && (Conf_Server[i].port > 0)) {
/* BINGO! Enable server */
Conf_Server[i].flags &= ~CONF_SFLAG_DISABLED;
return true;
}
}
return false;
} /* Conf_EnablePassiveServer */
GLOBAL bool
Conf_DisableServer( char *Name )
{
@@ -465,8 +412,8 @@ Set_Defaults( bool InitServers )
strlcpy( Conf_PidFile, PID_FILE, sizeof( Conf_PidFile ));
free(Conf_ListenAddress);
Conf_ListenAddress = NULL;
strcpy( Conf_ListenAddress, "" );
Conf_UID = Conf_GID = 0;
Conf_PingTimeout = 120;
@@ -478,28 +425,20 @@ Set_Defaults( bool InitServers )
Conf_Channel_Count = 0;
Conf_OperCanMode = false;
Conf_NoDNS = false;
Conf_PredefChannelsOnly = false;
Conf_OperServerMode = false;
Conf_ConnectIPv4 = true;
Conf_ConnectIPv6 = true;
#ifdef WANT_IPV6
Conf_ListenIPv4 = true;
Conf_ListenIPv6 = true;
#endif
Conf_MaxConnections = 0;
Conf_MaxConnections = -1;
Conf_MaxConnectionsIP = 5;
Conf_MaxJoins = 10;
Conf_MaxNickLength = CLIENT_NICK_LEN_DEFAULT;
/* Initialize server configuration structures */
if( InitServers ) for( i = 0; i < MAX_SERVERS; Init_Server_Struct( &Conf_Server[i++] ));
} /* Set_Defaults */
static bool
Read_Config( bool ngircd_starting )
static void
Read_Config( void )
{
/* Read configuration file. */
@@ -514,14 +453,10 @@ Read_Config( bool ngircd_starting )
/* No configuration file found! */
Config_Error( LOG_ALERT, "Can't read configuration \"%s\": %s",
NGIRCd_ConfFile, strerror( errno ));
if (!ngircd_starting)
return false;
Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME );
exit( 1 );
}
Set_Defaults( ngircd_starting );
Config_Error( LOG_INFO, "Reading configuration from \"%s\" ...", NGIRCd_ConfFile );
/* Clean up server configuration structure: mark all already
@@ -668,24 +603,6 @@ Read_Config( bool ngircd_starting )
exit( 1 );
}
}
if (!Conf_ListenAddress) {
/* no Listen addresses configured, use default */
#ifdef WANT_IPV6
/* Conf_ListenIPv6/4 should no longer be used */
if (Conf_ListenIPv6 && Conf_ListenIPv4)
Conf_ListenAddress = strdup_warn("::,0.0.0.0");
else if (Conf_ListenIPv6)
Conf_ListenAddress = strdup_warn("::");
else
#endif
Conf_ListenAddress = strdup_warn("0.0.0.0");
}
if (!Conf_ListenAddress) {
Config_Error(LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME);
exit(1);
}
return true;
} /* Read_Config */
@@ -700,27 +617,6 @@ Check_ArgIsTrue( const char *Arg )
} /* Check_ArgIsTrue */
static unsigned int Handle_MaxNickLength(int Line, const char *Arg)
{
unsigned new;
new = (unsigned) atoi(Arg) + 1;
if (new > CLIENT_NICK_LEN) {
Config_Error(LOG_WARNING,
"%s, line %d: Value of \"MaxNickLength\" exceeds %u!",
NGIRCd_ConfFile, Line, CLIENT_NICK_LEN - 1);
return CLIENT_NICK_LEN;
}
if (new < 2) {
Config_Error(LOG_WARNING,
"%s, line %d: Value of \"MaxNickLength\" must be at least 1!",
NGIRCd_ConfFile, Line);
return 2;
}
return new;
} /* Handle_MaxNickLength */
static void
Handle_GLOBAL( int Line, char *Var, char *Arg )
{
@@ -868,46 +764,6 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
Conf_PredefChannelsOnly = Check_ArgIsTrue( Arg );
return;
}
if( strcasecmp( Var, "NoDNS" ) == 0 ) {
/* don't do reverse dns lookups when clients connect? */
Conf_NoDNS = Check_ArgIsTrue( Arg );
return;
}
#ifdef WANT_IPV6
/* the default setting for all the WANT_IPV6 special options is 'true' */
if (strcasecmp(Var, "ListenIPv6") == 0) { /* DEPRECATED, option appeared in 0.12.0 */
/*
* listen on ipv6 sockets, if available?
* Deprecated use "Listen = 0.0.0.0" (or, rather, do not list "::")
*/
Conf_ListenIPv6 = Check_ArgIsTrue( Arg );
Config_Error(LOG_WARNING, "%s, line %d: %s=%s is deprecated, %sinclude '::' in \"Listen =\" option instead",
NGIRCd_ConfFile, Line, Var, yesno_to_str(Conf_ListenIPv6), Conf_ListenIPv6 ? " ":"do not ");
return;
}
if (strcasecmp(Var, "ListenIPv4") == 0) { /* DEPRECATED, option appeared in 0.12.0 */
/*
* listen on ipv4 sockets, if available?
* this allows "ipv6-only" setups
* Deprecated use "Listen = ::" (or, rather, do not list "0.0.0.0")
*/
Conf_ListenIPv4 = Check_ArgIsTrue( Arg );
Config_Error(LOG_WARNING, "%s, line %d: %s=%s is deprecated, %sinclude '0.0.0.0' in \"Listen =\" option instead",
NGIRCd_ConfFile, Line, Var, yesno_to_str(Conf_ListenIPv4), Conf_ListenIPv4 ? " ":"do not ");
return;
}
if( strcasecmp( Var, "ConnectIPv6" ) == 0 ) {
/* connect to other hosts using ipv6, if they have an AAAA record? */
Conf_ConnectIPv6 = Check_ArgIsTrue( Arg );
return;
}
if( strcasecmp( Var, "ConnectIPv4" ) == 0 ) {
/* connect to other hosts using ipv4.
* again, this can be used for ipv6-only setups */
Conf_ConnectIPv4 = Check_ArgIsTrue( Arg );
return;
}
#endif
if( strcasecmp( Var, "OperCanUseMode" ) == 0 ) {
/* Are IRC operators allowed to use MODE in channels they aren't Op in? */
Conf_OperCanMode = Check_ArgIsTrue( Arg );
@@ -919,7 +775,7 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
return;
}
if( strcasecmp( Var, "MaxConnections" ) == 0 ) {
/* Maximum number of connections. 0 -> "no limit". */
/* Maximum number of connections. Values <= 0 are equal to "no limit". */
#ifdef HAVE_ISDIGIT
if( ! isdigit( (int)*Arg )) Config_Error_NaN( Line, Var);
else
@@ -928,7 +784,7 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
return;
}
if( strcasecmp( Var, "MaxConnectionsIP" ) == 0 ) {
/* Maximum number of simultaneous connections from one IP. 0 -> "no limit" */
/* Maximum number of simultaneous connections from one IP. Values <= 0 -> "no limit" */
#ifdef HAVE_ISDIGIT
if( ! isdigit( (int)*Arg )) Config_Error_NaN( Line, Var );
else
@@ -937,7 +793,7 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
return;
}
if( strcasecmp( Var, "MaxJoins" ) == 0 ) {
/* Maximum number of channels a user can join. 0 -> "no limit". */
/* Maximum number of channels a user can join. Values <= 0 are equal to "no limit". */
#ifdef HAVE_ISDIGIT
if( ! isdigit( (int)*Arg )) Config_Error_NaN( Line, Var );
else
@@ -945,33 +801,16 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
Conf_MaxJoins = atoi( Arg );
return;
}
if( strcasecmp( Var, "MaxNickLength" ) == 0 ) {
/* Maximum length of a nick name; must be same on all servers
* within the IRC network! */
Conf_MaxNickLength = Handle_MaxNickLength(Line, Arg);
if( strcasecmp( Var, "Listen" ) == 0 ) {
/* IP-Address to bind sockets */
len = strlcpy( Conf_ListenAddress, Arg, sizeof( Conf_ListenAddress ));
if (len >= sizeof( Conf_ListenAddress ))
Config_Error_TooLong( Line, Var );
return;
}
if( strcasecmp( Var, "Listen" ) == 0 ) {
/* IP-Address to bind sockets */
if (Conf_ListenAddress) {
Config_Error(LOG_ERR, "Multiple Listen= options, ignoring: %s", Arg);
return;
}
Conf_ListenAddress = strdup_warn(Arg);
/*
* if allocation fails, we're in trouble:
* we cannot ignore the error -- otherwise ngircd
* would listen on all interfaces.
*/
if (!Conf_ListenAddress) {
Config_Error(LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME);
exit(1);
}
return;
}
Config_Error(LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!",
NGIRCd_ConfFile, Line, Var);
Config_Error( LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!",
NGIRCd_ConfFile, Line, Var );
} /* Handle_GLOBAL */
@@ -1042,14 +881,6 @@ Handle_SERVER( int Line, char *Var, char *Arg )
Config_Error_TooLong( Line, Var );
return;
}
if (strcasecmp(Var, "Bind") == 0) {
if (ng_ipaddr_init(&New_Server.bind_addr, Arg, 0))
return;
Config_Error(LOG_ERR, "%s, line %d (section \"Server\"): Can't parse IP address \"%s\"",
NGIRCd_ConfFile, Line, Arg);
return;
}
if( strcasecmp( Var, "MyPassword" ) == 0 ) {
/* Password of this server which is sent to the peer */
if (*Arg == ':') {
@@ -1089,11 +920,6 @@ Handle_SERVER( int Line, char *Var, char *Arg )
New_Server.group = atoi( Arg );
return;
}
if( strcasecmp( Var, "Passive" ) == 0 ) {
if (Check_ArgIsTrue(Arg))
New_Server.flags |= CONF_SFLAG_DISABLED;
return;
}
Config_Error( LOG_ERR, "%s, line %d (section \"Server\"): Unknown variable \"%s\"!",
NGIRCd_ConfFile, Line, Var );
@@ -1167,7 +993,7 @@ Handle_CHANNEL( int Line, char *Var, char *Arg )
} /* Handle_CHANNEL */
static bool
static void
Validate_Config(bool Configtest, bool Rehash)
{
/* Validate configuration settings. */
@@ -1175,7 +1001,6 @@ Validate_Config(bool Configtest, bool Rehash)
#ifdef DEBUG
int i, servers, servers_once;
#endif
bool config_valid = true;
char *ptr;
/* Validate configured server name, see RFC 2812 section 2.3.1 */
@@ -1194,7 +1019,6 @@ Validate_Config(bool Configtest, bool Rehash)
if (!Conf_ServerName[0]) {
/* No server name configured! */
config_valid = false;
Config_Error(LOG_ALERT,
"No (valid) server name configured in \"%s\" (section 'Global': 'Name')!",
NGIRCd_ConfFile);
@@ -1208,7 +1032,6 @@ Validate_Config(bool Configtest, bool Rehash)
if (Conf_ServerName[0] && !strchr(Conf_ServerName, '.')) {
/* No dot in server name! */
config_valid = false;
Config_Error(LOG_ALERT,
"Invalid server name configured in \"%s\" (section 'Global': 'Name'): Dot missing!",
NGIRCd_ConfFile);
@@ -1223,7 +1046,6 @@ Validate_Config(bool Configtest, bool Rehash)
#ifdef STRICT_RFC
if (!Conf_ServerAdminMail[0]) {
/* No administrative contact configured! */
config_valid = false;
Config_Error(LOG_ALERT,
"No administrator email address configured in \"%s\" ('AdminEMail')!",
NGIRCd_ConfFile);
@@ -1256,8 +1078,6 @@ Validate_Config(bool Configtest, bool Rehash)
"Configuration: Operators=%d, Servers=%d[%d], Channels=%d",
Conf_Oper_Count, servers, servers_once, Conf_Channel_Count);
#endif
return config_valid;
} /* Validate_Config */
@@ -1324,7 +1144,6 @@ Init_Server_Struct( CONF_SERVER *Server )
Resolve_Init(&Server->res_stat);
Server->conn_id = NONE;
memset(&Server->bind_addr, 0, sizeof(&Server->bind_addr));
} /* Init_Server_Struct */

View File

@@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: conf.h,v 1.49 2008/03/18 20:12:47 fw Exp $
* $Id: conf.h,v 1.40.2.2 2007/04/03 22:08:52 fw Exp $
*
* Configuration management (header)
*/
@@ -22,8 +22,6 @@
#include "defines.h"
#include "array.h"
#include "portab.h"
#include "tool.h"
#include "ng_ipaddr.h"
typedef struct _Conf_Oper
{
@@ -35,6 +33,7 @@ typedef struct _Conf_Oper
typedef struct _Conf_Server
{
char host[HOST_LEN]; /* Hostname */
char ip[16]; /* IP address (Resolver) */
char name[CLIENT_ID_LEN]; /* IRC-Client-ID */
char pwd_in[CLIENT_PASS_LEN]; /* Password which must be received */
char pwd_out[CLIENT_PASS_LEN]; /* Password to send to peer */
@@ -44,8 +43,6 @@ typedef struct _Conf_Server
RES_STAT res_stat; /* Status of the resolver */
int flags; /* Flags */
CONN_ID conn_id; /* ID of server connection or NONE */
ng_ipaddr_t bind_addr; /* source address to use for outgoing connections */
ng_ipaddr_t dst_addr[2]; /* list of addresses to connect to */
} CONF_SERVER;
typedef struct _Conf_Channel
@@ -86,7 +83,7 @@ GLOBAL char Conf_MotdPhrase[LINE_LEN];
GLOBAL array Conf_ListenPorts;
/* Address to which the socket should be bound or empty (=all) */
GLOBAL char *Conf_ListenAddress;
GLOBAL char Conf_ListenAddress[16];
/* User and group ID the server should run with */
GLOBAL uid_t Conf_UID;
@@ -121,18 +118,6 @@ GLOBAL bool Conf_PredefChannelsOnly;
/* Are IRC operators allowed to always use MODE? */
GLOBAL bool Conf_OperCanMode;
/* Disable all DNS functions? */
GLOBAL bool Conf_NoDNS;
/*
* try to connect to remote systems using the ipv6 protocol,
* if they have an ipv6 address? (default yes)
*/
GLOBAL bool Conf_ConnectIPv6;
/* same as above, but for ipv4 hosts, default: yes */
GLOBAL bool Conf_ConnectIPv4;
/* If an IRC op gives chanop privileges without being a chanop,
* ircd2 will ignore the command. This enables a workaround:
* It masks the command as coming from the server */
@@ -147,11 +132,9 @@ GLOBAL int Conf_MaxJoins;
/* Maximum number of connections per IP address */
GLOBAL int Conf_MaxConnectionsIP;
/* Maximum length of a nick name */
GLOBAL unsigned int Conf_MaxNickLength;
GLOBAL void Conf_Init PARAMS((void));
GLOBAL bool Conf_Rehash PARAMS((void));
GLOBAL void Conf_Rehash PARAMS((void));
GLOBAL int Conf_Test PARAMS((void));
GLOBAL void Conf_UnsetServer PARAMS(( CONN_ID Idx ));
@@ -159,7 +142,6 @@ GLOBAL void Conf_SetServer PARAMS(( int ConfServer, CONN_ID Idx ));
GLOBAL int Conf_GetServer PARAMS(( CONN_ID Idx ));
GLOBAL bool Conf_EnableServer PARAMS(( char *Name, UINT16 Port ));
GLOBAL bool Conf_EnablePassiveServer PARAMS((const char *Name));
GLOBAL bool Conf_DisableServer PARAMS(( char *Name ));
GLOBAL bool Conf_AddServer PARAMS(( char *Name, UINT16 Port, char *Host, char *MyPwd, char *PeerPwd ));

View File

@@ -16,12 +16,11 @@
#include "portab.h"
static char UNUSED id[] = "$Id: conn-func.c,v 1.12 2008/03/11 14:05:27 alex Exp $";
static char UNUSED id[] = "$Id: conn-func.c,v 1.10 2006/05/10 21:24:01 alex Exp $";
#include "imp.h"
#include <assert.h>
#include <string.h>
#include "log.h"
#include <log.h>
#include "conn.h"
#include "client.h"
@@ -40,16 +39,6 @@ Conn_UpdateIdle( CONN_ID Idx )
}
/*
* Get signon time of a connection.
*/
GLOBAL time_t
Conn_GetSignon(CONN_ID Idx)
{
assert(Idx > NONE);
return My_Connections[Idx].signon;
}
GLOBAL time_t
Conn_GetIdle( CONN_ID Idx )
{

View File

@@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: conn-func.h,v 1.7 2007/10/04 15:03:56 alex Exp $
* $Id: conn-func.h,v 1.5.2.1 2007/04/03 22:08:52 fw Exp $
*
* Connection management: Global functions (header)
*/
@@ -27,7 +27,6 @@
GLOBAL void Conn_UpdateIdle PARAMS(( CONN_ID Idx ));
GLOBAL time_t Conn_GetSignon PARAMS((CONN_ID Idx));
GLOBAL time_t Conn_GetIdle PARAMS(( CONN_ID Idx ));
GLOBAL time_t Conn_LastPing PARAMS(( CONN_ID Idx ));
GLOBAL time_t Conn_StartTime PARAMS(( CONN_ID Idx ));

View File

@@ -22,7 +22,7 @@
/* enable more zlib related debug messages: */
/* #define DEBUG_ZLIB */
static char UNUSED id[] = "$Id: conn-zip.c,v 1.16 2007/05/17 23:34:24 alex Exp $";
static char UNUSED id[] = "$Id: conn-zip.c,v 1.11.2.1 2007/05/18 22:11:19 alex Exp $";
#include "imp.h"
#include <assert.h>

View File

@@ -17,7 +17,7 @@
#include "portab.h"
#include "io.h"
static char UNUSED id[] = "$Id: conn.c,v 1.221 2008/02/26 22:04:17 fw Exp $";
static char UNUSED id[] = "$Id: conn.c,v 1.198.2.6 2007/05/18 22:11:19 alex Exp $";
#include "imp.h"
#include <assert.h>
@@ -41,6 +41,12 @@ static char UNUSED id[] = "$Id: conn.c,v 1.221 2008/02/26 22:04:17 fw Exp $";
# include <netinet/ip.h>
#endif
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#else
# define PF_INET AF_INET
#endif
#ifdef HAVE_STDINT_H
# include <stdint.h> /* e.g. for Mac OS X */
#endif
@@ -86,13 +92,13 @@ static void Check_Connections PARAMS(( void ));
static void Check_Servers PARAMS(( void ));
static void Init_Conn_Struct PARAMS(( CONN_ID Idx ));
static bool Init_Socket PARAMS(( int Sock ));
static void New_Server PARAMS(( int Server, ng_ipaddr_t *dest ));
static void New_Server PARAMS(( int Server ));
static void Simple_Message PARAMS(( int Sock, const char *Msg ));
static int NewListener PARAMS(( const char *listen_addr, UINT16 Port ));
static int Count_Connections PARAMS(( struct sockaddr_in addr ));
static int NewListener PARAMS(( const UINT16 Port ));
static array My_Listeners;
static array My_ConnArray;
static size_t NumConnections;
#ifdef TCPWRAP
int allow_severity = LOG_INFO;
@@ -109,8 +115,7 @@ static void
cb_listen(int sock, short irrelevant)
{
(void) irrelevant;
if (New_Connection( sock ) >= 0)
NumConnections++;
New_Connection( sock );
}
@@ -145,28 +150,10 @@ cb_connserver(int sock, UNUSED short what)
Conf_Server[Conf_GetServer(idx)].port,
idx, strerror(err));
res = Conf_GetServer(idx);
assert(res >= 0);
Conn_Close(idx, "Can't connect!", NULL, false);
if (res < 0)
return;
if (ng_ipaddr_af(&Conf_Server[res].dst_addr[0])) {
/* more addresses to try... */
New_Server(res, &Conf_Server[res].dst_addr[0]);
/* connection to dst_addr[0] in progress, remove this address... */
Conf_Server[res].dst_addr[0] = Conf_Server[res].dst_addr[1];
memset(&Conf_Server[res].dst_addr[1], 0, sizeof(&Conf_Server[res].dst_addr[1]));
}
return;
}
res = Conf_GetServer(idx);
assert(res >= 0);
if (res >= 0) /* connect succeeded, remove all additional addresses */
memset(&Conf_Server[res].dst_addr, 0, sizeof(&Conf_Server[res].dst_addr));
Conn_OPTION_DEL( &My_Connections[idx], CONN_ISCONNECTING );
server_login(idx);
}
@@ -216,10 +203,12 @@ Conn_Init( void )
/* Speicher fuer Verbindungs-Pool anfordern */
Pool_Size = CONNECTION_POOL;
if ((Conf_MaxConnections > 0) &&
(Pool_Size > Conf_MaxConnections))
Pool_Size = Conf_MaxConnections;
if( Conf_MaxConnections > 0 )
{
/* konfiguriertes Limit beachten */
if( Pool_Size > Conf_MaxConnections ) 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 );
@@ -271,25 +260,25 @@ Conn_Exit( void )
} /* Conn_Exit */
static unsigned int
ports_initlisteners(array *a, const char *listen_addr, void (*func)(int,short))
static int
ports_initlisteners(array *a, void (*func)(int,short))
{
unsigned int created = 0;
int created = 0;
size_t len;
int fd;
UINT16 *port;
len = array_length(a, sizeof (UINT16));
port = array_start(a);
while (len--) {
fd = NewListener(listen_addr, *port);
while(len--) {
fd = NewListener( *port );
if (fd < 0) {
port++;
continue;
}
if (!io_event_create( fd, IO_WANTREAD, func )) {
Log( LOG_ERR, "io_event_create(): Could not add listening fd %d (port %u): %s!",
fd, (unsigned int) *port, strerror(errno));
fd, (unsigned int) *port, strerror(errno));
close(fd);
port++;
continue;
@@ -297,47 +286,25 @@ ports_initlisteners(array *a, const char *listen_addr, void (*func)(int,short))
created++;
port++;
}
return created;
}
GLOBAL unsigned int
GLOBAL int
Conn_InitListeners( void )
{
/* Initialize ports on which the server should accept connections */
unsigned int created = 0;
char *copy, *listen_addr;
int created;
if (!io_library_init(CONNECTION_POOL)) {
Log(LOG_EMERG, "Cannot initialize IO routines: %s", strerror(errno));
return -1;
}
assert(Conf_ListenAddress);
created = ports_initlisteners(&Conf_ListenPorts, cb_listen);
/* can't use Conf_ListenAddress directly, see below */
copy = strdup(Conf_ListenAddress);
if (!copy) {
Log(LOG_CRIT, "Cannot copy %s: %s", Conf_ListenAddress, strerror(errno));
return 0;
}
listen_addr = strtok(copy, ",");
while (listen_addr) {
ngt_TrimStr(listen_addr);
if (*listen_addr)
created += ports_initlisteners(&Conf_ListenPorts, listen_addr, cb_listen);
listen_addr = strtok(NULL, ",");
}
/*
* 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.
*/
free(copy);
return created;
} /* Conn_InitListeners */
@@ -366,68 +333,52 @@ Conn_ExitListeners( void )
} /* Conn_ExitListeners */
static bool
InitSinaddrListenAddr(ng_ipaddr_t *addr, const char *listen_addrstr, UINT16 Port)
{
bool ret;
ret = ng_ipaddr_init(addr, listen_addrstr, Port);
if (!ret) {
assert(listen_addrstr);
Log(LOG_CRIT, "Can't bind to [%s]:%u: can't convert ip address \"%s\"",
listen_addrstr, Port, listen_addrstr);
}
return ret;
}
static void
set_v6_only(int af, int sock)
{
#if defined(IPV6_V6ONLY) && defined(WANT_IPV6)
int on = 1;
if (af != AF_INET6)
return;
if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)))
Log(LOG_ERR, "Could not set IPV6_V6ONLY: %s", strerror(errno));
#else
(void)af;
(void)sock;
#endif
}
/* return new listening port file descriptor or -1 on failure */
static int
NewListener(const char *listen_addr, UINT16 Port)
NewListener( const UINT16 Port )
{
/* Create new listening socket on specified port */
ng_ipaddr_t addr;
int sock, af;
struct sockaddr_in addr;
struct in_addr inaddr;
int sock;
#ifdef ZEROCONF
char name[CLIENT_ID_LEN], *info;
#endif
if (!InitSinaddrListenAddr(&addr, listen_addr, Port))
return -1;
af = ng_ipaddr_af(&addr);
sock = socket(af, SOCK_STREAM, 0);
/* Server-"Listen"-Socket initialisieren */
memset( &addr, 0, sizeof( addr ));
memset( &inaddr, 0, sizeof( inaddr ));
addr.sin_family = (sa_family_t)AF_INET;
addr.sin_port = htons( Port );
if( Conf_ListenAddress[0] )
{
#ifdef HAVE_INET_ATON
if( inet_aton( Conf_ListenAddress, &inaddr ) == 0 )
#else
inaddr.s_addr = inet_addr( Conf_ListenAddress );
if( inaddr.s_addr == (unsigned)-1 )
#endif
{
Log( LOG_CRIT, "Can't listen on %s:%u: can't convert ip address %s!",
Conf_ListenAddress, Port, Conf_ListenAddress );
return -1;
}
}
else inaddr.s_addr = htonl( INADDR_ANY );
addr.sin_addr = inaddr;
sock = socket( PF_INET, SOCK_STREAM, 0);
if( sock < 0 ) {
Log(LOG_CRIT, "Can't create socket (af %d) : %s!", af, strerror(errno));
Log( LOG_CRIT, "Can't create socket: %s!", strerror( errno ));
return -1;
}
set_v6_only(af, sock);
if( ! Init_Socket( sock )) return -1;
if (!Init_Socket(sock))
return -1;
if (bind(sock, (struct sockaddr *)&addr, ng_ipaddr_salen(&addr)) != 0) {
Log(LOG_CRIT, "Can't bind socket to address %s:%d - %s",
ng_ipaddr_tostr(&addr), Port, strerror(errno));
close(sock);
if (bind(sock, (struct sockaddr *)&addr, (socklen_t)sizeof(addr)) != 0) {
Log( LOG_CRIT, "Can't bind socket (port %d) : %s!", Port, strerror( errno ));
close( sock );
return -1;
}
@@ -444,7 +395,8 @@ NewListener(const char *listen_addr, UINT16 Port)
return -1;
}
Log(LOG_INFO, "Now listening on [%s]:%d (socket %d).", ng_ipaddr_tostr(&addr), Port, sock);
if( Conf_ListenAddress[0]) Log( LOG_INFO, "Now listening on %s:%d (socket %d).", Conf_ListenAddress, Port, sock );
else Log( LOG_INFO, "Now listening on 0.0.0.0:%d (socket %d).", Port, sock );
#ifdef ZEROCONF
/* Get best server description text */
@@ -745,7 +697,6 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient )
CLIENT *c;
char *txt;
double in_k, out_k;
UINT16 port;
#ifdef ZLIB
double in_z_k, out_z_k;
int in_p, out_p;
@@ -773,9 +724,9 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient )
if (! txt)
txt = "Reason unknown";
port = ng_ipaddr_getport(&My_Connections[Idx].addr);
Log(LOG_INFO, "Shutting down connection %d (%s) with %s:%d ...", Idx,
LogMsg ? LogMsg : FwdMsg, My_Connections[Idx].host, port);
LogMsg ? LogMsg : FwdMsg, My_Connections[Idx].host,
ntohs(My_Connections[Idx].addr.sin_port));
/* Search client, if any */
c = Conn_GetClient( Idx );
@@ -815,7 +766,7 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient )
Log(LOG_CRIT,
"Error closing connection %d (socket %d) with %s:%d - %s! (ignored)",
Idx, My_Connections[Idx].sock, My_Connections[Idx].host,
port, strerror(errno));
ntohs(My_Connections[Idx].addr.sin_port), strerror(errno));
}
/* Mark socket as invalid: */
@@ -844,7 +795,8 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient )
out_p = (int)(( out_k * 100 ) / out_z_k );
Log(LOG_INFO,
"Connection %d with %s:%d closed (in: %.1fk/%.1fk/%d%%, out: %.1fk/%.1fk/%d%%).",
Idx, My_Connections[Idx].host, port,
Idx, My_Connections[Idx].host,
ntohs(My_Connections[Idx].addr.sin_port),
in_k, in_z_k, in_p, out_k, out_z_k, out_p);
}
else
@@ -852,7 +804,8 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient )
{
Log(LOG_INFO,
"Connection %d with %s:%d closed (in: %.1fk, out: %.1fk).",
Idx, My_Connections[Idx].host, port,
Idx, My_Connections[Idx].host,
ntohs(My_Connections[Idx].addr.sin_port),
in_k, out_k);
}
@@ -879,10 +832,7 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient )
/* Clean up connection structure (=free it) */
Init_Conn_Struct( Idx );
assert(NumConnections > 0);
if (NumConnections)
NumConnections--;
LogDebug("Shutdown of connection %d completed", Idx );
LogDebug("Shutdown of connection %d completed.", Idx );
} /* Conn_Close */
@@ -978,22 +928,6 @@ Handle_Write( CONN_ID Idx )
} /* Handle_Write */
static int
Count_Connections(ng_ipaddr_t *a)
{
int i, cnt;
cnt = 0;
for (i = 0; i < Pool_Size; i++) {
if (My_Connections[i].sock <= NONE)
continue;
if (ng_ipaddr_ipequal(&My_Connections[i].addr, a))
cnt++;
}
return cnt;
} /* Count_Connections */
static int
New_Connection( int Sock )
{
@@ -1003,16 +937,14 @@ New_Connection( int Sock )
#ifdef TCPWRAP
struct request_info req;
#endif
ng_ipaddr_t new_addr;
char ip_str[NG_INET_ADDRSTRLEN];
int new_sock, new_sock_len;
struct sockaddr_in new_addr;
int new_sock, new_sock_len, new_Pool_Size;
CLIENT *c;
long cnt;
assert( Sock > NONE );
/* Connection auf Listen-Socket annehmen */
new_sock_len = (int)sizeof(new_addr);
new_sock_len = (int)sizeof new_addr;
new_sock = accept(Sock, (struct sockaddr *)&new_addr,
(socklen_t *)&new_sock_len);
if (new_sock < 0) {
@@ -1020,19 +952,14 @@ New_Connection( int Sock )
return -1;
}
if (!ng_ipaddr_tostr_r(&new_addr, ip_str)) {
Log(LOG_CRIT, "fd %d: Can't convert IP address!", new_sock);
Simple_Message(new_sock, "ERROR :Internal Server Error");
close(new_sock);
return -1;
}
#ifdef TCPWRAP
/* Validate socket using TCP Wrappers */
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);
if( ! hosts_access( &req ))
{
/* Access denied! */
Log( deny_severity, "Refused connection from %s (by TCP Wrappers)!", inet_ntoa( new_addr.sin_addr ));
Simple_Message( new_sock, "ERROR :Connection refused" );
close( new_sock );
return -1;
@@ -1042,27 +969,30 @@ New_Connection( int Sock )
/* Socket initialisieren */
if (!Init_Socket( new_sock ))
return -1;
/* Check IP-based connection limit */
cnt = Count_Connections(&new_addr);
if ((Conf_MaxConnectionsIP > 0) && (cnt >= Conf_MaxConnectionsIP)) {
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);
Log( LOG_ERR, "Refused connection from %s: too may connections (%ld) from this IP address!", inet_ntoa( new_addr.sin_addr ), 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 );
return -1;
}
if( new_sock >= Pool_Size ) {
new_Pool_Size = new_sock + 1;
/* No free Connection Structures, check if we may accept further connections */
if ((( Conf_MaxConnections > 0) && Pool_Size >= Conf_MaxConnections) ||
(new_Pool_Size < Pool_Size))
{
Log( LOG_ALERT, "Can't accept connection: limit (%d) reached!", Pool_Size );
Simple_Message( new_sock, "ERROR :Connection limit reached" );
close( new_sock );
return -1;
}
if (!array_alloc(&My_ConnArray, sizeof(CONNECTION),
(size_t)new_sock)) {
Log( LOG_EMERG, "Can't allocate memory! [New_Connection]" );
@@ -1075,7 +1005,7 @@ New_Connection( int Sock )
/* Adjust pointer to new block */
My_Connections = array_start(&My_ConnArray);
while (Pool_Size <= new_sock)
while (Pool_Size < new_Pool_Size)
Init_Conn_Struct(Pool_Size++);
}
@@ -1087,7 +1017,7 @@ New_Connection( int Sock )
return -1;
}
c = Client_NewLocal(new_sock, ip_str, CLIENT_UNKNOWN, false );
c = Client_NewLocal( new_sock, inet_ntoa( new_addr.sin_addr ), CLIENT_UNKNOWN, false );
if( ! c ) {
Log(LOG_ALERT, "Can't accept connection: can't create client structure!");
Simple_Message(new_sock, "ERROR :Internal error");
@@ -1101,18 +1031,19 @@ New_Connection( int Sock )
My_Connections[new_sock].client = c;
Log( LOG_INFO, "Accepted connection %d from %s:%d on socket %d.", new_sock,
ip_str, ng_ipaddr_getport(&new_addr), Sock);
inet_ntoa( new_addr.sin_addr ), ntohs( new_addr.sin_port), Sock );
/* Hostnamen ermitteln */
strlcpy(My_Connections[new_sock].host, ip_str, sizeof(My_Connections[new_sock].host));
strlcpy( My_Connections[new_sock].host, inet_ntoa( new_addr.sin_addr ),
sizeof( My_Connections[new_sock].host ));
Client_SetHostname(c, My_Connections[new_sock].host);
Client_SetHostname( c, My_Connections[new_sock].host );
if (!Conf_NoDNS)
Resolve_Addr(&My_Connections[new_sock].res_stat, &new_addr,
My_Connections[new_sock].sock, cb_Read_Resolver_Result);
Resolve_Addr(&My_Connections[new_sock].res_stat, &new_addr,
My_Connections[new_sock].sock, cb_Read_Resolver_Result);
Conn_SetPenalty(new_sock, 4);
/* Penalty-Zeit setzen */
Conn_SetPenalty( new_sock, 4 );
return new_sock;
} /* New_Connection */
@@ -1164,10 +1095,10 @@ Read_Request( CONN_ID Idx )
len = read(My_Connections[Idx].sock, readbuf, sizeof(readbuf));
if (len == 0) {
Log(LOG_INFO, "%s:%u (%s) is closing the connection ...",
My_Connections[Idx].host,
(unsigned int) ng_ipaddr_getport(&My_Connections[Idx].addr),
ng_ipaddr_tostr(&My_Connections[Idx].addr));
Log(LOG_INFO, "%s:%d (%s) is closing the connection ...",
My_Connections[Idx].host,
ntohs(My_Connections[Idx].addr.sin_port),
inet_ntoa( My_Connections[Idx].addr.sin_addr));
Conn_Close(Idx,
"Socket closed!", "Client closed connection",
false);
@@ -1229,7 +1160,7 @@ Handle_Buffer( CONN_ID Idx )
/* Handle Data in Connections Read-Buffer.
* Return true if a reuqest was handled, false otherwise (also returned on errors). */
#ifndef STRICT_RFC
char *ptr1, *ptr2, *first_eol;
char *ptr1, *ptr2;
#endif
char *ptr;
size_t len, delta;
@@ -1257,32 +1188,19 @@ Handle_Buffer( CONN_ID Idx )
return false;
/* A Complete Request end with CR+LF, see RFC 2812. */
delta = 2;
ptr = strstr( array_start(&My_Connections[Idx].rbuf), "\r\n" );
if( ptr ) delta = 2; /* complete request */
#ifndef STRICT_RFC
/* Check for non-RFC-compliant request (only CR or LF)?
* Unfortunately, there are quite a few clients out there
* that do this -- e. g. mIRC, BitchX, and Trillian :-( */
ptr1 = strchr(array_start(&My_Connections[Idx].rbuf), '\r');
ptr2 = strchr(array_start(&My_Connections[Idx].rbuf), '\n');
if (ptr) {
/* Check if there is a single CR or LF _before_ the
* corerct CR+LF line terminator: */
first_eol = ptr1 < ptr2 ? ptr1 : ptr2;
if (first_eol < ptr) {
/* Single CR or LF before CR+LF found */
ptr = first_eol;
delta = 1;
}
} else if (ptr1 || ptr2) {
/* No CR+LF terminated command found, but single
* CR or LF found ... */
if (ptr1 && ptr2)
ptr = ptr1 < ptr2 ? ptr1 : ptr2;
else
ptr = ptr1 ? ptr1 : ptr2;
else {
/* Check for non-RFC-compliant request (only CR or LF)? Unfortunately,
* there are quite a few clients that do this (incl. "mIRC" :-( */
ptr1 = strchr( array_start(&My_Connections[Idx].rbuf), '\r' );
ptr2 = strchr( array_start(&My_Connections[Idx].rbuf), '\n' );
delta = 1;
if( ptr1 && ptr2 ) ptr = ptr1 > ptr2 ? ptr2 : ptr1;
else if( ptr1 ) ptr = ptr1;
else if( ptr2 ) ptr = ptr2;
}
#endif
@@ -1415,7 +1333,7 @@ Check_Servers( void )
if( Conf_Server[i].group > NONE ) {
for (n = 0; n < MAX_SERVERS; n++) {
if (n == i) continue;
if ((Conf_Server[n].conn_id != NONE) &&
if ((Conf_Server[n].conn_id > NONE) &&
(Conf_Server[n].group == Conf_Server[i].group))
break;
}
@@ -1429,7 +1347,6 @@ Check_Servers( void )
/* Okay, try to connect now */
Conf_Server[i].lasttry = time_now;
Conf_Server[i].conn_id = SERVER_WAIT;
assert(Resolve_Getfd(&Conf_Server[i].res_stat) < 0);
Resolve_Name(&Conf_Server[i].res_stat, Conf_Server[i].host, cb_Connect_to_Server);
}
@@ -1437,50 +1354,54 @@ Check_Servers( void )
static void
New_Server( int Server , ng_ipaddr_t *dest)
New_Server( int Server )
{
/* Establish new server link */
char ip_str[NG_INET_ADDRSTRLEN];
int af_dest, res, new_sock;
struct sockaddr_in new_addr;
struct in_addr inaddr;
int res, new_sock;
CLIENT *c;
assert( Server > NONE );
if (!ng_ipaddr_tostr_r(dest, ip_str)) {
Log(LOG_WARNING, "New_Server: Could not convert IP to string");
return;
}
Log( LOG_INFO, "Establishing connection to \"%s\", %s, port %d ... ", Conf_Server[Server].host,
Conf_Server[Server].ip, Conf_Server[Server].port );
Log( LOG_INFO, "Establishing connection to \"%s\", %s, port %d ... ",
Conf_Server[Server].host, ip_str, Conf_Server[Server].port );
af_dest = ng_ipaddr_af(dest);
new_sock = socket(af_dest, SOCK_STREAM, 0);
if (new_sock < 0) {
Log( LOG_CRIT, "Can't create socket (af %d) : %s!", af_dest, strerror( errno ));
return;
}
if (!Init_Socket(new_sock))
return;
/* is a bind address configured? */
res = ng_ipaddr_af(&Conf_Server[Server].bind_addr);
/* if yes, bind now. If it fails, warn and let connect() pick a source address */
if (res && bind(new_sock, (struct sockaddr *) &Conf_Server[Server].bind_addr,
ng_ipaddr_salen(&Conf_Server[Server].bind_addr)))
#ifdef HAVE_INET_ATON
if( inet_aton( Conf_Server[Server].ip, &inaddr ) == 0 )
#else
memset( &inaddr, 0, sizeof( inaddr ));
inaddr.s_addr = inet_addr( Conf_Server[Server].ip );
if( inaddr.s_addr == (unsigned)-1 )
#endif
{
ng_ipaddr_tostr_r(&Conf_Server[Server].bind_addr, ip_str);
Log(LOG_WARNING, "Can't bind socket to %s: %s!", ip_str, strerror(errno));
Log( LOG_ERR, "Can't connect to \"%s\": can't convert ip address %s!",
Conf_Server[Server].host, Conf_Server[Server].ip );
return;
}
ng_ipaddr_setport(dest, Conf_Server[Server].port);
res = connect(new_sock, (struct sockaddr *) dest, ng_ipaddr_salen(dest));
memset( &new_addr, 0, sizeof( new_addr ));
new_addr.sin_family = (sa_family_t)AF_INET;
new_addr.sin_addr = inaddr;
new_addr.sin_port = htons( Conf_Server[Server].port );
new_sock = socket( PF_INET, SOCK_STREAM, 0 );
if ( new_sock < 0 ) {
Log( LOG_CRIT, "Can't create socket: %s!", strerror( errno ));
return;
}
if( ! Init_Socket( new_sock )) return;
res = connect(new_sock, (struct sockaddr *)&new_addr,
(socklen_t)sizeof(new_addr));
if(( res != 0 ) && ( errno != EINPROGRESS )) {
Log( LOG_CRIT, "Can't connect socket: %s!", strerror( errno ));
close( new_sock );
return;
}
if (!array_alloc(&My_ConnArray, sizeof(CONNECTION), (size_t)new_sock)) {
Log(LOG_ALERT,
"Cannot allocate memory for server connection (socket %d)",
@@ -1495,9 +1416,8 @@ New_Server( int Server , ng_ipaddr_t *dest)
Init_Conn_Struct(new_sock);
ng_ipaddr_tostr_r(dest, ip_str);
c = Client_NewLocal(new_sock, ip_str, CLIENT_UNKNOWNSERVER, false);
if (!c) {
c = Client_NewLocal( new_sock, inet_ntoa( new_addr.sin_addr ), CLIENT_UNKNOWNSERVER, false );
if( ! c ) {
Log( LOG_ALERT, "Can't establish connection: can't create client structure!" );
close( new_sock );
return;
@@ -1509,7 +1429,7 @@ New_Server( int Server , ng_ipaddr_t *dest)
/* Register connection */
Conf_Server[Server].conn_id = new_sock;
My_Connections[new_sock].sock = new_sock;
My_Connections[new_sock].addr = *dest;
My_Connections[new_sock].addr = new_addr;
My_Connections[new_sock].client = c;
strlcpy( My_Connections[new_sock].host, Conf_Server[Server].host,
sizeof(My_Connections[new_sock].host ));
@@ -1528,17 +1448,14 @@ New_Server( int Server , ng_ipaddr_t *dest)
} /* New_Server */
/**
* Initialize connection structure.
*/
static void
Init_Conn_Struct(CONN_ID Idx)
Init_Conn_Struct( CONN_ID Idx )
{
time_t now = time(NULL);
time_t now = time( NULL );
/* Connection-Struktur initialisieren */
memset(&My_Connections[Idx], 0, sizeof(CONNECTION));
memset( &My_Connections[Idx], 0, sizeof ( CONNECTION ));
My_Connections[Idx].sock = -1;
My_Connections[Idx].signon = now;
My_Connections[Idx].lastdata = now;
My_Connections[Idx].lastprivmsg = now;
Resolve_Init(&My_Connections[Idx].res_stat);
@@ -1588,9 +1505,7 @@ cb_Connect_to_Server(int fd, UNUSED short events)
/* Read result of resolver sub-process from pipe and start connection */
int i;
size_t len;
ng_ipaddr_t dest_addrs[4]; /* we can handle at most 3; but we read up to
four so we can log the 'more than we can handle'
condition */
char readbuf[HOST_LEN + 1];
LogDebug("Resolver: Got forward lookup callback on fd %d, events %d", fd, events);
@@ -1598,7 +1513,7 @@ cb_Connect_to_Server(int fd, UNUSED short events)
if (Resolve_Getfd(&Conf_Server[i].res_stat) == fd )
break;
}
if( i >= MAX_SERVERS) {
/* Ops, no matching server found?! */
io_close( fd );
@@ -1607,28 +1522,16 @@ cb_Connect_to_Server(int fd, UNUSED short events)
}
/* Read result from pipe */
len = Resolve_Read(&Conf_Server[i].res_stat, dest_addrs, sizeof(dest_addrs));
len = Resolve_Read(&Conf_Server[i].res_stat, readbuf, sizeof readbuf -1);
if (len == 0)
return;
readbuf[len] = '\0';
LogDebug("Got result from resolver: \"%s\" (%u bytes read).", readbuf, len);
strlcpy( Conf_Server[i].ip, readbuf, sizeof( Conf_Server[i].ip ));
assert((len % sizeof(ng_ipaddr_t)) == 0);
LogDebug("Got result from resolver: %u structs (%u bytes).", len/sizeof(ng_ipaddr_t), len);
memset(&Conf_Server[i].dst_addr, 0, sizeof(&Conf_Server[i].dst_addr));
if (len > sizeof(ng_ipaddr_t)) {
/* more than one address for this hostname, remember them
* in case first address is unreachable/not available */
len -= sizeof(ng_ipaddr_t);
if (len > sizeof(&Conf_Server[i].dst_addr)) {
len = sizeof(&Conf_Server[i].dst_addr);
Log(LOG_NOTICE, "Notice: Resolver returned more IP Addresses for host than we can handle,"
" additional addresses dropped");
}
memcpy(&Conf_Server[i].dst_addr, &dest_addrs[1], len);
}
/* connect() */
New_Server(i, dest_addrs);
New_Server(i);
} /* cb_Read_Forward_Lookup */
@@ -1695,10 +1598,10 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
#ifdef IDENTAUTH
++identptr;
if (*identptr) {
Log(LOG_INFO, "IDENT lookup for connection %d: \"%s\".", i, identptr);
Client_SetUser(c, identptr, true);
Log( LOG_INFO, "IDENT lookup for connection %ld: \"%s\".", i, identptr);
Client_SetUser( c, identptr, true );
} else {
Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i);
Log( LOG_INFO, "IDENT lookup for connection %ld: no result.", i );
}
#endif
}
@@ -1727,6 +1630,19 @@ Simple_Message( int Sock, const char *Msg )
} /* Simple_Error */
static int
Count_Connections( struct sockaddr_in addr_in )
{
int i, cnt;
cnt = 0;
for( i = 0; i < Pool_Size; i++ ) {
if(( My_Connections[i].sock > NONE ) && ( My_Connections[i].addr.sin_addr.s_addr == addr_in.sin_addr.s_addr )) cnt++;
}
return cnt;
} /* Count_Connections */
GLOBAL CLIENT *
Conn_GetClient( CONN_ID Idx )
{

View File

@@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: conn.h,v 1.46 2008/02/26 22:04:17 fw Exp $
* $Id: conn.h,v 1.42.2.1 2007/05/09 13:21:38 fw Exp $
*
* Connection management (header)
*/
@@ -38,8 +38,6 @@ typedef int CONN_ID;
#include "defines.h"
#include "resolve.h"
#include "array.h"
#include "tool.h"
#include "ng_ipaddr.h"
#ifdef ZLIB
#include <zlib.h>
@@ -56,12 +54,11 @@ typedef struct _ZipData
typedef struct _Connection
{
int sock; /* Socket handle */
ng_ipaddr_t addr; /* Client address */
struct sockaddr_in addr; /* Client address */
RES_STAT res_stat; /* Status of resolver process */
char host[HOST_LEN]; /* Hostname */
array rbuf; /* Read buffer */
array wbuf; /* Write buffer */
time_t signon; /* Signon ("connect") time */
time_t lastdata; /* Last activity */
time_t lastping; /* Last PING */
time_t lastprivmsg; /* Last PRIVMSG */
@@ -86,7 +83,7 @@ GLOBAL long WCounter;
GLOBAL void Conn_Init PARAMS((void ));
GLOBAL void Conn_Exit PARAMS(( void ));
GLOBAL unsigned int Conn_InitListeners PARAMS(( void ));
GLOBAL int Conn_InitListeners PARAMS(( void ));
GLOBAL void Conn_ExitListeners PARAMS(( void ));
GLOBAL void Conn_Handler PARAMS(( void ));

View File

@@ -8,7 +8,7 @@
* (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 $
* $Id: defines.h,v 1.58.2.1 2007/05/18 22:11:19 alex Exp $
*/
@@ -47,15 +47,14 @@
#define CLIENT_ID_LEN 64 /* Max. length of an IRC ID; see RFC
RFC 2812 section 1.1 and 1.2.1 */
#define CLIENT_NICK_LEN_DEFAULT 10 /* Default nick length, see. RFC 2812
* section 1.2.1 */
#define CLIENT_NICK_LEN 32 /* Maximum nick name length */
#define CLIENT_NICK_LEN 10 /* Max. nick length, see. RFC 2812
section 1.2.1 */
#define CLIENT_PASS_LEN 21 /* Max. password length */
#define CLIENT_USER_LEN 10 /* Max. length of user name ("login")
see RFC 2812, section 1.2.1 */
#define CLIENT_NAME_LEN 32 /* Max. length of "real names" */
#define CLIENT_HOST_LEN 64 /* Max. host name length */
#define CLIENT_MODE_LEN 9 /* Max. lenth of all client modes */
#define CLIENT_MODE_LEN 8 /* Max. lenth of all client modes */
#define CLIENT_INFO_LEN 64 /* Max. length of server info texts */
#define CLIENT_AWAY_LEN 128 /* Max. length of away messages */
#define CLIENT_FLAGS_LEN 100 /* Max. length of client flags */
@@ -82,7 +81,7 @@
protocol, see doc/Protocol.txt */
#ifdef IRCPLUS
# define IRCPLUSFLAGS "CHL" /* Standard IRC+ flags */
# define IRCPLUSFLAGS "CL" /* Standard IRC+ flags */
#endif
#define STARTUP_DELAY 1 /* Delay outgoing connections n seconds

View File

@@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: hash.c,v 1.13 2006/10/06 21:23:47 fw Exp $";
static char UNUSED id[] = "$Id: hash.c,v 1.12.2.1 2006/12/02 13:18:22 fw Exp $";
#include "imp.h"
#include <assert.h>

View File

@@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: hash.h,v 1.6 2006/10/06 21:23:47 fw Exp $
* $Id: hash.h,v 1.5.4.1 2006/12/02 13:18:22 fw Exp $
*
* Hash calculation (header)
*/

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,7 @@
*
* I/O abstraction interface header
*
* $Id: io.h,v 1.4 2006/12/25 22:53:52 alex Exp $
* $Id: io.h,v 1.3.2.1 2007/04/03 22:08:52 fw Exp $
*/
#ifndef io_H_included

View File

@@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: irc-channel.c,v 1.45 2008/02/24 18:57:38 fw Exp $";
static char UNUSED id[] = "$Id: irc-channel.c,v 1.35.2.5 2008/01/07 11:41:44 fw Exp $";
#include "imp.h"
#include <assert.h>
@@ -40,147 +40,14 @@ static char UNUSED id[] = "$Id: irc-channel.c,v 1.45 2008/02/24 18:57:38 fw Exp
#include "irc-channel.h"
/*
* RFC 2812, (3.2.1 Join message Command):
* Note that this message
* accepts a special argument ("0"), which is a special request to leave all
* channels the user is currently a member of. The server will process this
* message as if the user had sent a PART command (See Section 3.2.2) for
* each channel he is a member of.
*/
static bool
part_from_all_channels(CLIENT* client, CLIENT *target)
{
CL2CHAN *cl2chan;
CHANNEL *chan;
while ((cl2chan = Channel_FirstChannelOf(target))) {
chan = Channel_GetChannel(cl2chan);
assert( chan != NULL );
Channel_Part(target, client, Channel_Name(chan), Client_ID(target));
}
return CONNECTED;
}
static bool
join_allowed(CLIENT *Client, CLIENT *target, CHANNEL *chan,
const char *channame, const char *key)
{
bool is_invited, is_banned;
const char *channel_modes;
is_banned = Lists_Check(Channel_GetListBans(chan), target);
is_invited = Lists_Check(Channel_GetListInvites(chan), target);
if (is_banned && !is_invited) {
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);
return false;
}
/* Is the channel protected by a key? */
if (strchr(channel_modes, 'k') &&
strcmp(Channel_Key(chan), key ? key : ""))
{
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);
return false;
}
return true;
}
static void
join_set_channelmodes(CHANNEL *chan, CLIENT *target, const char *flags)
{
if (flags) {
while (*flags) {
Channel_UserModeAdd(chan, target, *flags);
flags++;
}
}
/* If channel persistent and client is ircop: make client chanop */
if (strchr(Channel_Modes(chan), 'P') && strchr(Client_Modes(target), 'o'))
Channel_UserModeAdd(chan, target, 'o');
}
static void
join_forward(CLIENT *Client, CLIENT *target, CHANNEL *chan,
const char *channame)
{
char modes[8];
strlcpy(&modes[1], Channel_UserModes(chan, target), sizeof(modes) - 1);
if (modes[1])
modes[0] = 0x7;
else
modes[0] = '\0';
/* forward to other servers */
IRC_WriteStrServersPrefix(Client, target, "JOIN :%s%s", channame, modes);
/* tell users in this channel about the new client */
IRC_WriteStrChannelPrefix(Client, chan, target, false, "JOIN :%s", channame);
if (modes[1])
IRC_WriteStrChannelPrefix(Client, chan, target, false, "MODE %s +%s %s",
channame, &modes[1], Client_ID(target));
}
static bool
join_send_topic(CLIENT *Client, CLIENT *target, CHANNEL *chan,
const char *channame)
{
const char *topic;
if (Client_Type(Client) != CLIENT_USER)
return true;
/* acknowledge join */
if (!IRC_WriteStrClientPrefix(Client, target, "JOIN :%s", channame))
return false;
/* Send topic to client, if any */
topic = Channel_Topic(chan);
assert(topic != NULL);
if (*topic) {
if (!IRC_WriteStrClient(Client, RPL_TOPIC_MSG,
Client_ID(Client), channame, topic))
return false;
#ifndef STRICT_RFC
if (!IRC_WriteStrClient(Client, RPL_TOPICSETBY_MSG,
Client_ID(Client), channame,
Channel_TopicWho(chan),
Channel_TopicTime(chan)))
return false;
#endif
}
/* send list of channel members to client */
if (!IRC_Send_NAMES(Client, chan))
return false;
return IRC_WriteStrClient(Client, RPL_ENDOFNAMES_MSG, Client_ID(Client), Channel_Name(chan));
}
GLOBAL bool
IRC_JOIN( CLIENT *Client, REQUEST *Req )
{
char *channame, *channame_ptr, *key, *key_ptr, *flags;
char *channame, *channame_ptr, *key, *key_ptr, *flags, *topic, modes[8];
bool is_new_chan, is_invited, is_banned;
CLIENT *target;
CHANNEL *chan;
assert( Client != NULL );
assert( Req != NULL );
@@ -190,83 +57,190 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
Client_ID(Client), Req->command);
/* Who is the sender? */
if (Client_Type(Client) == CLIENT_SERVER)
target = Client_Search(Req->prefix);
else
target = Client;
if (!target)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, Client_ID(Client), Req->prefix);
/* Is argument "0"? */
if (Req->argc == 1 && !strncmp("0", Req->argv[0], 2))
return part_from_all_channels(Client, target);
if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix );
else target = Client;
if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
/* Are channel keys given? */
if (Req->argc > 1) {
key = Req->argv[1];
key_ptr = strchr(key, ',');
if (key_ptr) *key_ptr = '\0';
} else {
key = key_ptr = NULL;
}
else
key = key_ptr = NULL;
channame = Req->argv[0];
channame_ptr = strchr(channame, ',');
if (channame_ptr) *channame_ptr = '\0';
while (channame) {
flags = NULL;
/* Channel-Namen durchgehen */
while (channame)
{
chan = NULL; flags = NULL;
/* Did the server include channel-user-modes? */
if (Client_Type(Client) == CLIENT_SERVER) {
flags = strchr(channame, 0x7);
if (flags) {
/* wird der Channel neu angelegt? */
if( Channel_Search( channame )) {
is_new_chan = false;
} else {
if (Conf_PredefChannelsOnly) { /* this server does not allow creation of channels */
IRC_WriteStrClient( Client, ERR_BANNEDFROMCHAN_MSG, Client_ID( Client ), channame );
/* Try next name, if any */
channame = strchr(channame, ',');
continue;
}
is_new_chan = true;
}
/* Hat ein Server Channel-User-Modes uebergeben? */
if( Client_Type( Client ) == CLIENT_SERVER )
{
/* Channel-Flags extrahieren */
flags = strchr( channame, 0x7 );
if( flags )
{
*flags = '\0';
flags++;
}
}
chan = Channel_Search(channame);
if (!chan && Conf_PredefChannelsOnly) {
/* channel must be created, but server does not allow this */
IRC_WriteStrClient(Client, ERR_BANNEDFROMCHAN_MSG, Client_ID(Client), channame);
break;
}
/* Local client? */
if (Client_Type(Client) == CLIENT_USER) {
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 */
if(( Conf_MaxJoins > 0 ) && ( Channel_CountForUser( Client ) >= Conf_MaxJoins ))
return IRC_WriteStrClient( Client, ERR_TOOMANYCHANNELS_MSG,
Client_ID( Client ), channame );
/* Existiert der Channel bereits, oder wird er im Moment neu erzeugt? */
if( is_new_chan )
{
/* Erster User im Channel: Operator-Flag setzen */
flags = "o";
}
else
if (!join_allowed(Client, target, chan, channame, key))
break;
} else {
{
/* Existierenden Channel suchen */
chan = Channel_Search( channame );
assert( chan != NULL );
is_banned = Lists_Check(Channel_GetListBans(chan), target );
is_invited = Lists_Check(Channel_GetListInvites(chan), target );
/* Testen, ob Client gebanned ist */
if(( is_banned == true) && ( is_invited == false ))
{
/* Client ist gebanned (und nicht invited): */
IRC_WriteStrClient( Client, ERR_BANNEDFROMCHAN_MSG, Client_ID( Client ), channame );
/* Try next name, if any */
channame = strchr(channame, ',');
continue;
}
/* Ist der Channel "invite-only"? */
if(( strchr( Channel_Modes( chan ), 'i' )) && ( is_invited == false ))
{
/* Channel ist "invite-only" und Client wurde nicht invited: */
IRC_WriteStrClient( Client, ERR_INVITEONLYCHAN_MSG, Client_ID( Client ), channame );
/* Try next name, if any */
channame = strchr(channame, ',');
continue;
}
/* Is the channel protected by a key? */
if(( strchr( Channel_Modes( chan ), 'k' )) && ( strcmp( Channel_Key( chan ), key ? key : "" ) != 0 ))
{
/* Bad channel key! */
IRC_WriteStrClient( Client, ERR_BADCHANNELKEY_MSG, Client_ID( Client ), channame );
/* Try next name, if any */
channame = strchr(channame, ',');
continue;
}
/* Are there already too many members? */
if(( strchr( Channel_Modes( chan ), 'l' )) && ( Channel_MaxUsers( chan ) <= Channel_MemberCount( chan )))
{
/* Bad channel key! */
IRC_WriteStrClient( Client, ERR_CHANNELISFULL_MSG, Client_ID( Client ), channame );
/* Try next name, if any */
channame = strchr(channame, ',');
continue;
}
}
}
else
{
/* Remote server: we don't need to know whether the
* client is invited or not, but we have to make sure
* 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);
chan = Channel_Search( channame );
if( chan != NULL ) (void)Lists_Check(Channel_GetListInvites(chan), target);
}
/* Join channel (and create channel if it doesn't exist) */
if (!Channel_Join(target, channame))
break;
/* Channel joinen (und ggf. anlegen) */
if( ! Channel_Join( target, channame ))
{
/* naechsten Namen ermitteln */
channame = strchr(channame, ',');
continue;
}
if( ! chan ) chan = Channel_Search( channame );
assert( chan != NULL );
if (!chan) /* channel is new; it has been created above */
chan = Channel_Search(channame);
assert(chan != NULL);
/* Modes setzen (wenn vorhanden) */
while( flags && *flags )
{
Channel_UserModeAdd( chan, target, *flags );
flags++;
}
join_set_channelmodes(chan, target, flags);
/* Wenn persistenter Channel und IRC-Operator: zum Channel-OP machen */
if(( strchr( Channel_Modes( chan ), 'P' )) && ( strchr( Client_Modes( target ), 'o' ))) Channel_UserModeAdd( chan, target, 'o' );
join_forward(Client, target, chan, channame);
/* Muessen Modes an andere Server gemeldet werden? */
strlcpy( &modes[1], Channel_UserModes( chan, target ), sizeof( modes ) - 1 );
if( modes[1] ) modes[0] = 0x7;
else modes[0] = '\0';
if (!join_send_topic(Client, target, chan, channame))
break; /* write error */
/* An andere Server weiterleiten */
IRC_WriteStrServersPrefix( Client, target, "JOIN :%s%s", channame, modes );
/* im Channel bekannt machen */
IRC_WriteStrChannelPrefix( Client, chan, target, false, "JOIN :%s", channame );
if( modes[1] )
{
/* Modes im Channel bekannt machen */
IRC_WriteStrChannelPrefix( Client, chan, target, false, "MODE %s +%s %s", channame, &modes[1], Client_ID( target ));
}
if( Client_Type( Client ) == CLIENT_USER )
{
/* an Client bestaetigen */
IRC_WriteStrClientPrefix( Client, target, "JOIN :%s", channame );
/* Send topic to client, if any */
topic = Channel_Topic(chan);
if (*topic) {
IRC_WriteStrClient(Client, RPL_TOPIC_MSG,
Client_ID(Client), channame, topic);
#ifndef STRICT_RFC
IRC_WriteStrClient(Client, RPL_TOPICSETBY_MSG,
Client_ID(Client), channame,
Channel_TopicWho(chan),
Channel_TopicTime(chan));
#endif
}
/* Mitglieder an Client Melden */
IRC_Send_NAMES( Client, chan );
IRC_WriteStrClient( Client, RPL_ENDOFNAMES_MSG, Client_ID( Client ), Channel_Name( chan ));
}
/* next channel? */
channame = channame_ptr;
@@ -286,37 +260,38 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
} /* IRC_JOIN */
/**
* Handler for the IRC "PART" command.
*/
GLOBAL bool
IRC_PART(CLIENT * Client, REQUEST * Req)
IRC_PART( CLIENT *Client, REQUEST *Req )
{
CLIENT *target;
char *chan;
assert(Client != NULL);
assert(Req != NULL);
assert( Client != NULL );
assert( Req != NULL );
/* Falsche Anzahl Parameter? */
if (Req->argc < 1 || Req->argc > 2)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
Client_ID(Client), Req->command);
/* Get the sender */
if (Client_Type(Client) == CLIENT_SERVER)
target = Client_Search(Req->prefix);
else
target = Client;
if (!target)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix);
/* Wer ist der Absender? */
if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix );
else target = Client;
if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
/* Loop over all the given channel names */
chan = strtok(Req->argv[0], ",");
while (chan) {
Channel_Part(target, Client, chan,
Req->argc > 1 ? Req->argv[1] : Client_ID(target));
chan = strtok(NULL, ",");
/* Channel-Namen durchgehen */
chan = strtok( Req->argv[0], "," );
while( chan )
{
if( ! Channel_Part( target, Client, chan, Req->argc > 1 ? Req->argv[1] : Client_ID( target )))
{
/* naechsten Namen ermitteln */
chan = strtok( NULL, "," );
continue;
}
/* naechsten Namen ermitteln */
chan = strtok( NULL, "," );
}
return CONNECTED;
} /* IRC_PART */

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
* Copyright (c)2001-2005 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
@@ -14,6 +14,8 @@
#include "portab.h"
static char UNUSED id[] = "$Id: irc-info.c,v 1.33.2.2 2006/12/02 14:26:53 fw Exp $";
#include "imp.h"
#include <assert.h>
#include <errno.h>
@@ -23,6 +25,7 @@
#include <strings.h>
#include "ngircd.h"
#include "cvs-version.h"
#include "conn-func.h"
#include "conn-zip.h"
#include "client.h"
@@ -32,7 +35,6 @@
#include "defines.h"
#include "log.h"
#include "messages.h"
#include "match.h"
#include "tool.h"
#include "parse.h"
#include "irc-write.h"
@@ -82,71 +84,6 @@ IRC_ADMIN(CLIENT *Client, REQUEST *Req )
} /* IRC_ADMIN */
/**
* Handler for the IRC command "INFO".
* See RFC 2812 section 3.4.10.
*/
GLOBAL bool
IRC_INFO(CLIENT * Client, REQUEST * Req)
{
CLIENT *target, *prefix;
char msg[510];
assert(Client != NULL);
assert(Req != NULL);
/* Wrong number of parameters? */
if (Req->argc > 1)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
/* Determine prefix */
if (Client_Type(Client) == CLIENT_SERVER)
prefix = Client_Search(Req->prefix);
else
prefix = Client;
if (!prefix)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix);
/* Look for a target */
if (Req->argc > 0)
target = Client_Search(Req->argv[0]);
else
target = Client_ThisServer();
/* Make sure that the target is a server */
if (target && Client_Type(target) != CLIENT_SERVER)
target = Client_Introducer(target);
if (!target)
return IRC_WriteStrClient(prefix, ERR_NOSUCHSERVER_MSG,
Client_ID(prefix), Req->argv[0]);
/* Pass on to another server? */
if (target != Client_ThisServer()) {
IRC_WriteStrClientPrefix(target, prefix, "INFO %s",
Req->argv[0]);
return CONNECTED;
}
if (!IRC_WriteStrClient(Client, RPL_INFO_MSG, Client_ID(prefix),
NGIRCd_Version))
return DISCONNECTED;
strlcpy(msg, "Server has been started ", sizeof(msg));
strlcat(msg, NGIRCd_StartStr, sizeof(msg));
if (!IRC_WriteStrClient(Client, RPL_INFO_MSG, Client_ID(prefix), msg))
return DISCONNECTED;
if (!IRC_WriteStrClient(Client, RPL_ENDOFINFO_MSG, Client_ID(prefix)))
return DISCONNECTED;
IRC_SetPenalty(Client, 2);
return CONNECTED;
} /* IRC_INFO */
GLOBAL bool
IRC_ISON( CLIENT *Client, REQUEST *Req )
{
@@ -398,41 +335,6 @@ IRC_NAMES( CLIENT *Client, REQUEST *Req )
} /* IRC_NAMES */
static unsigned int
t_diff(time_t *t, const time_t div)
{
time_t diff, remain;
diff = *t / div;
remain = diff * div;
*t -= remain;
return diff;
}
static unsigned int
uptime_days(time_t *now)
{
return t_diff(now, 60 * 60 * 24);
}
static unsigned int
uptime_hrs(time_t *now)
{
return t_diff(now, 60 * 60);
}
static unsigned int
uptime_mins(time_t *now)
{
return t_diff(now, 60);
}
GLOBAL bool
IRC_STATS( CLIENT *Client, REQUEST *Req )
{
@@ -440,110 +342,78 @@ IRC_STATS( CLIENT *Client, REQUEST *Req )
CONN_ID con;
char query;
COMMAND *cmd;
time_t time_now;
unsigned int days, hrs, mins;
assert( Client != NULL );
assert( Req != NULL );
/* Falsche Anzahl Parameter? */
if (Req->argc > 2)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, Client_ID(Client), Req->command);
if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
/* From aus Prefix ermitteln */
if (Client_Type(Client) == CLIENT_SERVER)
from = Client_Search(Req->prefix);
else
from = Client;
if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
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) {
if( Req->argc == 2 )
{
/* an anderen Server forwarden */
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_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( ))
{
/* Ok, anderer Server ist das Ziel: forwarden */
return IRC_WriteStrClientPrefix( target, from, "STATS %s %s", Req->argv[0], Req->argv[1] );
}
}
if (Req->argc > 0)
query = Req->argv[0][0] ? Req->argv[0][0] : '*';
else
query = '*';
if( Req->argc > 0 ) query = Req->argv[0][0] ? Req->argv[0][0] : '*';
else query = '*';
switch (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)) {
con = Conn_First( );
while( con != NONE )
{
cl = Conn_GetClient( con );
if( cl && (( 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;
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( NULL ) - Conn_StartTime( con )))) return DISCONNECTED;
}
else
#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;
{
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( NULL ) - Conn_StartTime( con )))) return DISCONNECTED;
}
}
con = Conn_Next( con );
}
break;
case 'm': /* IRC-Commands */
case 'm': /* IRC-Befehle */
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;
while( cmd->name )
{
if( cmd->lcount > 0 || cmd->rcount > 0 )
{
if( ! IRC_WriteStrClient( from, RPL_STATSCOMMANDS_MSG, Client_ID( from ), cmd->name, cmd->lcount, cmd->bytes, cmd->rcount )) return DISCONNECTED;
}
cmd++;
}
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);
IRC_SetPenalty( from, 2 );
return IRC_WriteStrClient( from, RPL_ENDOFSTATS_MSG, Client_ID( from ), query );
} /* IRC_STATS */
/**
* Handler for the IRC command "SUMMON".
* See RFC 2812 section 4.5. ngIRCd doesn't implement this functionality and
* therefore answers with ERR_SUMMONDISABLED.
*/
GLOBAL bool
IRC_SUMMON(CLIENT * Client, REQUEST * Req)
{
return IRC_WriteStrClient(Client, ERR_SUMMONDISABLED_MSG,
Client_ID(Client), Req->command);
} /* IRC_SUMMON */
GLOBAL bool
IRC_TIME( CLIENT *Client, REQUEST *Req )
{
@@ -621,22 +491,13 @@ IRC_USERHOST( CLIENT *Client, REQUEST *Req )
} /* IRC_USERHOST */
/**
* Handler for the IRC command "USERS".
* See RFC 2812 section 4.6. As suggested there the command is disabled.
*/
GLOBAL bool
IRC_USERS(CLIENT * Client, REQUEST * Req)
{
return IRC_WriteStrClient(Client, ERR_USERSDISABLED_MSG,
Client_ID(Client), Req->command);
} /* IRC_USERS */
GLOBAL bool
IRC_VERSION( CLIENT *Client, REQUEST *Req )
{
CLIENT *target, *prefix;
#ifdef CVSDATE
char ver[12], vertxt[30];
#endif
assert( Client != NULL );
assert( Req != NULL );
@@ -663,110 +524,26 @@ IRC_VERSION( CLIENT *Client, REQUEST *Req )
return CONNECTED;
}
/* send version information */
IRC_SetPenalty(Client, 1);
return IRC_WriteStrClient(Client, RPL_VERSION_MSG, Client_ID(prefix),
PACKAGE_NAME, PACKAGE_VERSION,
NGIRCd_DebugLevel, Conf_ServerName,
NGIRCd_VersionAddition);
/* mit Versionsinfo antworten */
IRC_SetPenalty( Client, 1 );
#ifdef CVSDATE
strlcpy( ver, CVSDATE, sizeof( ver ));
strncpy( ver + 4, ver + 5, 2 );
strncpy( ver + 6, ver + 8, 3 );
snprintf( vertxt, sizeof( vertxt ), "%s(%s)", PACKAGE_VERSION, ver );
return IRC_WriteStrClient( Client, RPL_VERSION_MSG, Client_ID( prefix ), PACKAGE_NAME, vertxt, NGIRCd_DebugLevel, Conf_ServerName, NGIRCd_VersionAddition );
#else
return IRC_WriteStrClient( Client, RPL_VERSION_MSG, Client_ID( prefix ), PACKAGE_NAME, PACKAGE_VERSION, NGIRCd_DebugLevel, Conf_ServerName, NGIRCd_VersionAddition );
#endif
} /* IRC_VERSION */
static bool
write_whoreply(CLIENT *Client, CLIENT *c, const char *channelname, const char *flags)
{
return IRC_WriteStrClient(Client, RPL_WHOREPLY_MSG, Client_ID(Client), channelname,
Client_User(c), Client_Hostname(c), Client_ID(Client_Introducer(c)), Client_ID(c),
flags, Client_Hops(c), Client_Info(c));
}
static const char *
who_flags_status(const char *client_modes)
{
if (strchr(client_modes, 'a'))
return "G"; /* away */
return "H";
}
static const char *
who_flags_qualifier(const char *chan_user_modes)
{
if (strchr(chan_user_modes, 'o'))
return "@";
else if (strchr(chan_user_modes, 'v'))
return "+";
return "";
}
static bool
IRC_Send_WHO(CLIENT *Client, CHANNEL *Chan, bool OnlyOps)
{
bool is_visible, is_member, is_ircop;
CL2CHAN *cl2chan;
const char *client_modes;
const char *chan_user_modes;
char flags[8];
CLIENT *c;
assert( Client != NULL );
assert( Chan != NULL );
is_member = Channel_IsMemberOf(Chan, Client);
/* Secret channel? */
if (!is_member && strchr(Channel_Modes(Chan), 's'))
return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), Channel_Name(Chan));
cl2chan = Channel_FirstMember(Chan);
for (; cl2chan ; cl2chan = Channel_NextMember(Chan, cl2chan)) {
c = Channel_GetClient(cl2chan);
client_modes = Client_Modes(c);
is_ircop = strchr(client_modes, 'o') != NULL;
if (OnlyOps && !is_ircop)
continue;
is_visible = strchr(client_modes, 'i') == NULL;
if (is_member || is_visible) {
strcpy(flags, who_flags_status(client_modes));
if (is_ircop)
strlcat(flags, "*", sizeof(flags));
chan_user_modes = Channel_UserModes(Chan, c);
strlcat(flags, who_flags_qualifier(chan_user_modes), sizeof(flags));
if (!write_whoreply(Client, c, Channel_Name(Chan), flags))
return DISCONNECTED;
}
}
return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), Channel_Name(Chan));
} /* IRC_Send_WHO */
static bool
MatchCaseInsensitive(const char *pattern, const char *searchme)
{
char haystack[COMMAND_LEN];
strlcpy(haystack, searchme, sizeof(haystack));
ngt_LowerStr(haystack);
return Match(pattern, haystack);
}
GLOBAL bool
IRC_WHO( CLIENT *Client, REQUEST *Req )
{
bool only_ops, have_arg, client_match;
const char *channelname, *client_modes, *chan_user_modes;
char pattern[COMMAND_LEN];
char flags[4];
bool ok, only_ops;
char flags[8];
const char *ptr;
CL2CHAN *cl2chan;
CHANNEL *chan, *cn;
CLIENT *c;
@@ -774,102 +551,78 @@ IRC_WHO( CLIENT *Client, REQUEST *Req )
assert( Client != NULL );
assert( Req != NULL );
if (Req->argc > 2)
return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
/* Falsche Anzahl Parameter? */
if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
only_ops = false;
have_arg = false;
chan = NULL;
if (Req->argc == 2) {
if (strcmp(Req->argv[1], "o") == 0)
only_ops = true;
if( Req->argc == 2 )
{
/* Nur OPs anzeigen? */
if( strcmp( Req->argv[1], "o" ) == 0 ) only_ops = true;
#ifdef STRICT_RFC
else return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, Client_ID(Client), Req->command);
else return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
#endif
}
IRC_SetPenalty(Client, 1);
if (Req->argc >= 1) { /* Channel or Mask. */
chan = Channel_Search(Req->argv[0]);
if (chan)
return IRC_Send_WHO(Client, chan, only_ops);
if (strcmp(Req->argv[0], "0") != 0) { /* RFC stupidity, same as no arguments */
have_arg = true;
strlcpy(pattern, Req->argv[0], sizeof(pattern));
ngt_LowerStr(pattern);
IRC_SetPenalty(Client, 3);
}
if( Req->argc >= 1 )
{
/* wurde ein Channel oder Nick-Mask angegeben? */
chan = Channel_Search( Req->argv[0] );
}
for (c = Client_First(); c != NULL; c = Client_Next(c)) {
if (Client_Type(c) != CLIENT_USER)
continue;
/*
* RFC 2812, 3.6.1:
* In the absence of the parameter, all visible (users who aren't
* invisible (user mode +i) and who don't have a common channel
* with the requesting client) are listed.
*
* The same result can be achieved by using a [sic] of "0"
* or any wildcard which will end up matching every visible user.
*
* The [sic] passed to WHO is matched against users' host, server, real name and
* nickname if the channel cannot be found.
*/
client_modes = Client_Modes(c);
if (strchr(client_modes, 'i'))
continue;
if( chan )
{
/* User eines Channels ausgeben */
if( ! IRC_Send_WHO( Client, chan, only_ops )) return DISCONNECTED;
}
if (only_ops && !strchr(client_modes, 'o'))
continue;
if (have_arg) { /* match pattern against user host/server/name/nick */
client_match = MatchCaseInsensitive(pattern, Client_Hostname(c)); /* user's host */
if (!client_match)
client_match = MatchCaseInsensitive(pattern, Client_ID(Client_Introducer(c))); /* server */
if (!client_match)
client_match = Match(Req->argv[0], Client_Info(c)); /* realname */
if (!client_match)
client_match = MatchCaseInsensitive(pattern, Client_ID(c)); /* nick name */
if (!client_match) /* This isn't the client you're looking for */
continue;
}
strcpy(flags, who_flags_status(client_modes));
if (strchr(client_modes, 'o')) /* this client is an operator */
strlcat(flags, "*", sizeof(flags));
/* Search suitable channel */
cl2chan = Channel_FirstChannelOf(c);
while (cl2chan) {
cn = Channel_GetChannel(cl2chan);
if (Channel_IsMemberOf(cn, Client) ||
!strchr(Channel_Modes(cn), 's'))
c = Client_First( );
while( c )
{
if(( Client_Type( c ) == CLIENT_USER ) && ( ! strchr( Client_Modes( c ), 'i' )))
{
ok = false;
if( Req->argc == 0 ) ok = true;
else
{
channelname = Channel_Name(cn);
break;
if( strcasecmp( Req->argv[0], Client_ID( c )) == 0 ) ok = true;
else if( strcmp( Req->argv[0], "0" ) == 0 ) ok = true;
}
cl2chan = Channel_NextChannelOf(c, cl2chan);
}
if (cl2chan) {
chan = Channel_GetChannel(cl2chan);
chan_user_modes = Channel_UserModes(chan, c);
strlcat(flags, who_flags_qualifier(chan_user_modes), sizeof(flags));
} else
channelname = "*";
if (!write_whoreply(Client, c, channelname, flags))
return DISCONNECTED;
if( ok && (( ! only_ops ) || ( strchr( Client_Modes( c ), 'o' ))))
{
/* Get flags */
strcpy( flags, "H" );
if( strchr( Client_Modes( c ), 'o' )) strlcat( flags, "*", sizeof( flags ));
/* Search suitable channel */
cl2chan = Channel_FirstChannelOf( c );
while( cl2chan )
{
cn = Channel_GetChannel( cl2chan );
if( Channel_IsMemberOf( cn, Client ) ||
! strchr( Channel_Modes( cn ), 's' ))
{
ptr = Channel_Name( cn );
break;
}
cl2chan = Channel_NextChannelOf( c, cl2chan );
}
if( ! cl2chan ) ptr = "*";
if( ! IRC_WriteStrClient( Client, RPL_WHOREPLY_MSG, Client_ID( Client ), ptr, Client_User( c ), Client_Hostname( c ), Client_ID( Client_Introducer( c )), Client_ID( c ), flags, Client_Hops( c ), Client_Info( c ))) return DISCONNECTED;
}
}
/* naechster Client */
c = Client_Next( c );
}
if (Req->argc > 0)
channelname = Req->argv[0];
else
channelname = "*";
return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), channelname);
if( chan ) return IRC_WriteStrClient( Client, RPL_ENDOFWHO_MSG, Client_ID( Client ), Channel_Name( chan ));
else if( Req->argc == 0 ) return IRC_WriteStrClient( Client, RPL_ENDOFWHO_MSG, Client_ID( Client ), "*" );
else return IRC_WriteStrClient( Client, RPL_ENDOFWHO_MSG, Client_ID( Client ), Req->argv[0] );
} /* IRC_WHO */
@@ -954,13 +707,10 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req )
if( ! IRC_WriteStrClient( from, RPL_WHOISOPERATOR_MSG, Client_ID( from ), Client_ID( c ))) return DISCONNECTED;
}
/* Idle and signon time (local clients only!) */
if (Client_Conn(c) > NONE ) {
if (! IRC_WriteStrClient(from, RPL_WHOISIDLE_MSG,
Client_ID(from), Client_ID(c),
(unsigned long)Conn_GetIdle(Client_Conn(c)),
(unsigned long)Conn_GetSignon(Client_Conn(c))))
return DISCONNECTED;
/* Idle (only local clients) */
if( Client_Conn( c ) > NONE )
{
if( ! IRC_WriteStrClient( from, RPL_WHOISIDLE_MSG, Client_ID( from ), Client_ID( c ), Conn_GetIdle( Client_Conn ( c )))) return DISCONNECTED;
}
/* Away? */
@@ -1132,21 +882,18 @@ IRC_Send_LUSERS( CLIENT *Client )
} /* IRC_Send_LUSERS */
static bool
Show_MOTD_Start(CLIENT *Client)
static bool Show_MOTD_Start(CLIENT *Client)
{
return IRC_WriteStrClient(Client, RPL_MOTDSTART_MSG,
Client_ID( Client ), Client_ID( Client_ThisServer( )));
}
static bool
Show_MOTD_Sendline(CLIENT *Client, const char *msg)
static bool Show_MOTD_Sendline(CLIENT *Client, const char *msg)
{
return IRC_WriteStrClient(Client, RPL_MOTD_MSG, Client_ID( Client ), msg);
}
static bool
Show_MOTD_End(CLIENT *Client)
static bool Show_MOTD_End(CLIENT *Client)
{
return IRC_WriteStrClient( Client, RPL_ENDOFMOTD_MSG, Client_ID( Client ));
}
@@ -1249,23 +996,52 @@ IRC_Send_NAMES( CLIENT *Client, CHANNEL *Chan )
} /* IRC_Send_NAMES */
/**
* Send the ISUPPORT numeric (005).
* This numeric indicates the features that are supported by this server.
* See <http://www.irc.org/tech_docs/005.html> for details.
*/
GLOBAL bool
IRC_Send_ISUPPORT PARAMS((CLIENT * Client))
IRC_Send_WHO( CLIENT *Client, CHANNEL *Chan, bool OnlyOps )
{
if (!IRC_WriteStrClient(Client, RPL_ISUPPORT1_MSG, Client_ID(Client),
Conf_MaxJoins))
return DISCONNECTED;
return IRC_WriteStrClient(Client, RPL_ISUPPORT2_MSG, Client_ID(Client),
CHANNEL_NAME_LEN - 1, Conf_MaxNickLength - 1,
COMMAND_LEN - 23, CLIENT_AWAY_LEN - 1,
COMMAND_LEN - 113);
} /* IRC_Send_ISUPPORT */
bool is_visible, is_member;
CL2CHAN *cl2chan;
char flags[8];
CLIENT *c;
assert( Client != NULL );
assert( Chan != NULL );
if( Channel_IsMemberOf( Chan, Client )) is_member = true;
else is_member = false;
/* Secret channel? */
if( ! is_member && strchr( Channel_Modes( Chan ), 's' )) return CONNECTED;
/* Alle Mitglieder suchen */
cl2chan = Channel_FirstMember( Chan );
while( cl2chan )
{
c = Channel_GetClient( cl2chan );
if( strchr( Client_Modes( c ), 'i' )) is_visible = false;
else is_visible = true;
if( is_member || is_visible )
{
/* Flags zusammenbasteln */
strcpy( flags, "H" );
if( strchr( Client_Modes( c ), 'o' )) strlcat( flags, "*", sizeof( flags ));
if( strchr( Channel_UserModes( Chan, c ), 'o' )) strlcat( flags, "@", sizeof( flags ));
else if( strchr( Channel_UserModes( Chan, c ), 'v' )) strlcat( flags, "+", sizeof( flags ));
/* ausgeben */
if(( ! OnlyOps ) || ( strchr( Client_Modes( c ), 'o' )))
{
if( ! IRC_WriteStrClient( Client, RPL_WHOREPLY_MSG, Client_ID( Client ), Channel_Name( Chan ), Client_User( c ), Client_Hostname( c ), Client_ID( Client_Introducer( c )), Client_ID( c ), flags, Client_Hops( c ), Client_Info( c ))) return DISCONNECTED;
}
}
/* naechstes Mitglied suchen */
cl2chan = Channel_NextMember( Chan, cl2chan );
}
return CONNECTED;
} /* IRC_Send_WHO */
/* -eof- */

View File

@@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: irc-info.h,v 1.6 2008/02/17 13:26:42 alex Exp $
* $Id: irc-info.h,v 1.3 2005/03/19 18:43:48 fw Exp $
*
* IRC info commands (header)
*/
@@ -19,17 +19,14 @@
GLOBAL bool IRC_ADMIN PARAMS(( CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_INFO PARAMS(( CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_ISON PARAMS(( CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_LINKS PARAMS(( CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_LUSERS PARAMS(( CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_MOTD PARAMS(( CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_NAMES PARAMS(( CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_STATS PARAMS(( CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_SUMMON PARAMS(( CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_TIME PARAMS(( CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_USERHOST PARAMS(( CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_USERS PARAMS(( CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_VERSION PARAMS(( CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_WHO PARAMS(( CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_WHOIS PARAMS(( CLIENT *Client, REQUEST *Req ));
@@ -38,7 +35,7 @@ GLOBAL bool IRC_WHOWAS PARAMS(( CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_Send_LUSERS PARAMS(( CLIENT *Client ));
GLOBAL bool IRC_Send_NAMES PARAMS(( CLIENT *Client, CHANNEL *Chan ));
GLOBAL bool IRC_Show_MOTD PARAMS(( CLIENT *Client ));
GLOBAL bool IRC_Send_ISUPPORT PARAMS(( CLIENT *Client ));
GLOBAL bool IRC_Send_WHO PARAMS(( CLIENT *Client, CHANNEL *Chan, bool OnlyOps ));
#endif

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
* Copyright (c)2001,2002 by 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
@@ -14,6 +14,8 @@
#include "portab.h"
static char UNUSED id[] = "$Id: irc-login.c,v 1.49.2.2 2006/12/02 14:26:53 fw Exp $";
#include "imp.h"
#include <assert.h>
#include <stdio.h>
@@ -33,6 +35,7 @@
#include "irc.h"
#include "irc-info.h"
#include "irc-write.h"
#include "cvs-version.h"
#include "exp.h"
#include "irc-login.h"
@@ -504,7 +507,7 @@ IRC_PING(CLIENT *Client, REQUEST *Req)
Client_ID(from), Client_ID(Client));
#else
/* Some clients depend on the argument being returned in the PONG
* reply (not mentioned in any RFC, though) */
* reply (not mentioned in any RFC, though) */
return IRC_WriteStrClient(Client, "PONG %s :%s",
Client_ID(from), Req->argv[0]);
#endif
@@ -570,60 +573,66 @@ IRC_PONG(CLIENT *Client, REQUEST *Req)
static bool
Hello_User(CLIENT * Client)
Hello_User( CLIENT *Client )
{
assert(Client != NULL);
#ifdef CVSDATE
char ver[12], vertxt[30];
#endif
assert( Client != NULL );
/* Check password ... */
if (strcmp(Client_Password(Client), Conf_ServerPwd) != 0) {
if( strcmp( Client_Password( Client ), Conf_ServerPwd ) != 0 )
{
/* Bad password! */
Log(LOG_ERR,
"User \"%s\" rejected (connection %d): Bad password!",
Client_Mask(Client), Client_Conn(Client));
Conn_Close(Client_Conn(Client), NULL, "Bad password", true);
Log( LOG_ERR, "User \"%s\" rejected (connection %d): Bad password!", Client_Mask( Client ), Client_Conn( Client ));
Conn_Close( Client_Conn( Client ), NULL, "Bad password", true);
return DISCONNECTED;
}
Log(LOG_NOTICE, "User \"%s\" registered (connection %d).",
Client_Mask(Client), Client_Conn(Client));
Log( LOG_NOTICE, "User \"%s\" registered (connection %d).", Client_Mask( Client ), Client_Conn( Client ));
/* Inform other servers */
IRC_WriteStrServers(NULL, "NICK %s 1 %s %s 1 +%s :%s",
Client_ID(Client), Client_User(Client),
Client_Hostname(Client), Client_Modes(Client),
Client_Info(Client));
IRC_WriteStrServers( NULL, "NICK %s 1 %s %s 1 +%s :%s", Client_ID( Client ), Client_User( Client ), Client_Hostname( Client ), Client_Modes( Client ), Client_Info( Client ));
if (!IRC_WriteStrClient
(Client, RPL_WELCOME_MSG, Client_ID(Client), Client_Mask(Client)))
return false;
if (!IRC_WriteStrClient
(Client, RPL_YOURHOST_MSG, Client_ID(Client),
Client_ID(Client_ThisServer()), PACKAGE_VERSION, TARGET_CPU,
TARGET_VENDOR, TARGET_OS))
return false;
if (!IRC_WriteStrClient
(Client, RPL_CREATED_MSG, Client_ID(Client), NGIRCd_StartStr))
return false;
if (!IRC_WriteStrClient
(Client, RPL_MYINFO_MSG, Client_ID(Client),
Client_ID(Client_ThisServer()), PACKAGE_VERSION, USERMODES,
CHANMODES))
return false;
/* Welcome :-) */
if( ! IRC_WriteStrClient( Client, RPL_WELCOME_MSG, Client_ID( Client ), Client_Mask( Client ))) return false;
/* Version and system type */
#ifdef CVSDATE
strlcpy( ver, CVSDATE, sizeof( ver ));
strncpy( ver + 4, ver + 5, 2 );
strncpy( ver + 6, ver + 8, 3 );
snprintf( vertxt, sizeof( vertxt ), "%s(%s)", PACKAGE_VERSION, ver );
if( ! IRC_WriteStrClient( Client, RPL_YOURHOST_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), vertxt, TARGET_CPU, TARGET_VENDOR, TARGET_OS )) return false;
#else
if( ! IRC_WriteStrClient( Client, RPL_YOURHOST_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), PACKAGE_VERSION, TARGET_CPU, TARGET_VENDOR, TARGET_OS )) return false;
#endif
if( ! IRC_WriteStrClient( Client, RPL_CREATED_MSG, Client_ID( Client ), NGIRCd_StartStr )) return false;
#ifdef CVSDATE
if( ! IRC_WriteStrClient( Client, RPL_MYINFO_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), vertxt, USERMODES, CHANMODES )) return false;
#else
if( ! IRC_WriteStrClient( Client, RPL_MYINFO_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), PACKAGE_VERSION, USERMODES, CHANMODES )) return false;
#endif
/* Features supported by this server (005 numeric, ISUPPORT),
* see <http://www.irc.org/tech_docs/005.html> for details. */
if (!IRC_Send_ISUPPORT(Client))
if (! IRC_WriteStrClient(Client, RPL_ISUPPORT1_MSG, Client_ID(Client),
Conf_MaxJoins))
return DISCONNECTED;
if (! IRC_WriteStrClient(Client, RPL_ISUPPORT2_MSG, Client_ID(Client),
CHANNEL_NAME_LEN-1, CLIENT_NICK_LEN-1, COMMAND_LEN-23,
CLIENT_AWAY_LEN-1, COMMAND_LEN-113))
return DISCONNECTED;
Client_SetType(Client, CLIENT_USER);
Client_SetType( Client, CLIENT_USER );
if (!IRC_Send_LUSERS(Client))
return DISCONNECTED;
if (!IRC_Show_MOTD(Client))
return DISCONNECTED;
if( ! IRC_Send_LUSERS( Client )) return DISCONNECTED;
if( ! IRC_Show_MOTD( Client )) return DISCONNECTED;
/* Suspend the client for a second ... */
IRC_SetPenalty(Client, 1);
IRC_SetPenalty( Client, 1 );
return CONNECTED;
} /* Hello_User */

View File

@@ -14,6 +14,8 @@
#include "portab.h"
static char UNUSED id[] = "$Id: irc-mode.c,v 1.45.2.2 2007/04/03 20:23:31 fw Exp $";
#include "imp.h"
#include <assert.h>
#include <stdio.h>
@@ -39,10 +41,13 @@
static bool Client_Mode PARAMS(( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ));
static bool Channel_Mode PARAMS(( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ));
static bool Add_Ban_Invite PARAMS((int what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Pattern));
static bool Del_Ban_Invite PARAMS((int what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Pattern));
static bool Add_Invite PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ));
static bool Add_Ban PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ));
static bool Send_ListChange PARAMS(( char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Mask ));
static bool Del_Invite PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ));
static bool Del_Ban PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ));
static bool Send_ListChange PARAMS(( char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Mask ));
GLOBAL bool
@@ -159,7 +164,6 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
{
case 'i': /* Invisible */
case 's': /* Server messages */
case 'w': /* Wallops messages */
x[0] = *mode_ptr;
break;
@@ -237,140 +241,123 @@ client_exit:
} /* Client_Mode */
static bool
Channel_Mode_Answer_Request(CLIENT *Origin, CHANNEL *Channel)
{
char the_modes[COMMAND_LEN], the_args[COMMAND_LEN], argadd[CLIENT_PASS_LEN];
const char *mode_ptr;
/* Member or not? -- That's the question! */
if (!Channel_IsMemberOf(Channel, Origin))
return IRC_WriteStrClient(Origin, RPL_CHANNELMODEIS_MSG,
Client_ID(Origin), Channel_Name(Channel), Channel_Modes(Channel));
/* The sender is a member: generate extended reply */
strlcpy(the_modes, Channel_Modes(Channel), sizeof(the_modes));
mode_ptr = the_modes;
the_args[0] = '\0';
while(*mode_ptr) {
switch(*mode_ptr) {
case 'l':
snprintf(argadd, sizeof(argadd), " %lu", Channel_MaxUsers(Channel));
strlcat(the_args, argadd, sizeof(the_args));
break;
case 'k':
strlcat(the_args, " ", sizeof(the_args));
strlcat(the_args, Channel_Key(Channel), sizeof(the_args));
break;
}
mode_ptr++;
}
if (the_args[0])
strlcat(the_modes, the_args, sizeof(the_modes));
return IRC_WriteStrClient(Origin, RPL_CHANNELMODEIS_MSG,
Client_ID(Origin), Channel_Name(Channel), the_modes);
}
static bool
Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel )
{
/* Handle channel and channel-user modes */
char the_modes[COMMAND_LEN], the_args[COMMAND_LEN], x[2], argadd[CLIENT_PASS_LEN], *mode_ptr;
bool ok, set, modeok = true, skiponce, use_servermode = false, retval;
bool ok, set, modeok = false, skiponce, use_servermode = false;
int mode_arg, arg_arg;
CLIENT *client;
long l;
size_t len;
/* Mode request: let's answer it :-) */
if (Req->argc <= 1)
return Channel_Mode_Answer_Request(Origin, Channel);
if( Req->argc == 1 )
{
/* Member or not? -- That's the question! */
if( ! Channel_IsMemberOf( Channel, Origin )) return IRC_WriteStrClient( Origin, RPL_CHANNELMODEIS_MSG, Client_ID( Origin ), Channel_Name( Channel ), Channel_Modes( Channel ));
/* The sender is a member: generate extended reply */
strlcpy( the_modes, Channel_Modes( Channel ), sizeof( the_modes ));
mode_ptr = the_modes;
the_args[0] = '\0';
while( *mode_ptr )
{
switch( *mode_ptr )
{
case 'l':
snprintf( argadd, sizeof( argadd ), " %lu", Channel_MaxUsers( Channel ));
strlcat( the_args, argadd, sizeof( the_args ));
break;
case 'k':
strlcat( the_args, " ", sizeof( the_args ));
strlcat( the_args, Channel_Key( Channel ), sizeof( the_args ));
break;
}
mode_ptr++;
}
if( the_args[0] ) strlcat( the_modes, the_args, sizeof( the_modes ));
return IRC_WriteStrClient( Origin, RPL_CHANNELMODEIS_MSG, Client_ID( Origin ), Channel_Name( Channel ), the_modes );
}
/* Is the user allowed to change modes? */
if (Client_Type(Client) == CLIENT_USER) {
if( Client_Type( Client ) == CLIENT_USER )
{
/* Is the originating user on that channel? */
if (!Channel_IsMemberOf(Channel, Origin))
return IRC_WriteStrClient(Origin, ERR_NOTONCHANNEL_MSG,
Client_ID(Origin), Channel_Name(Channel));
modeok = false;
/* channel operator? */
if (strchr(Channel_UserModes(Channel, Origin), 'o'))
modeok = true;
else if(Conf_OperCanMode) {
if( ! Channel_IsMemberOf( Channel, Origin )) return IRC_WriteStrClient( Origin, ERR_NOTONCHANNEL_MSG, Client_ID( Origin ), Channel_Name( Channel ));
/* Is he channel operator? */
if( strchr( Channel_UserModes( Channel, Origin ), 'o' )) modeok = true;
else if( Conf_OperCanMode )
{
/* IRC-Operators can use MODE as well */
if (Client_OperByMe(Origin)) {
if( Client_OperByMe( Origin )) {
modeok = true;
if (Conf_OperServerMode)
use_servermode = true; /* Change Origin to Server */
if ( Conf_OperServerMode ) use_servermode = true; /* Change Origin to Server */
}
}
}
else modeok = true;
mode_arg = 1;
mode_ptr = Req->argv[mode_arg];
if (Req->argc > mode_arg + 1)
arg_arg = mode_arg + 1;
else
arg_arg = -1;
if( Req->argc > mode_arg + 1 ) arg_arg = mode_arg + 1;
else arg_arg = -1;
/* Initial state: set or unset modes? */
skiponce = false;
switch (*mode_ptr) {
case '-': set = false; break;
case '+': set = true; break;
default:
set = true;
skiponce = true;
}
if( *mode_ptr == '-' ) set = false;
else if( *mode_ptr == '+' ) set = true;
else set = skiponce = true;
/* Prepare reply string */
strcpy(the_modes, set ? "+" : "-");
the_args[0] = '\0';
if( set ) strcpy( the_modes, "+" );
else strcpy( the_modes, "-" );
strcpy( the_args, " " );
x[1] = '\0';
ok = CONNECTED;
while (mode_ptr) {
if (! skiponce)
mode_ptr++;
if (!*mode_ptr) {
while( mode_ptr )
{
if( ! skiponce ) mode_ptr++;
if( ! *mode_ptr )
{
/* Try next argument if there's any */
if (arg_arg > mode_arg)
mode_arg = arg_arg;
else
mode_arg++;
if (mode_arg >= Req->argc)
break;
mode_ptr = Req->argv[mode_arg];
if (Req->argc > mode_arg + 1)
arg_arg = mode_arg + 1;
else
arg_arg = -1;
if( arg_arg > mode_arg ) mode_arg = arg_arg;
else mode_arg++;
if( mode_arg < Req->argc ) mode_ptr = Req->argv[mode_arg];
else break;
if( Req->argc > mode_arg + 1 ) arg_arg = mode_arg + 1;
else arg_arg = -1;
}
skiponce = false;
switch (*mode_ptr) {
case '+':
case '-':
if (((*mode_ptr == '+') && !set) || ((*mode_ptr == '-') && set)) {
/* Action modifier ("+"/"-") must be changed ... */
len = strlen( the_modes ) - 1;
if ((the_modes[len] == '+') || (the_modes[len] == '-')) {
/* Adjust last action modifier in result */
the_modes[len] = *mode_ptr;
} else {
/* Append modifier character to result string */
x[0] = *mode_ptr;
strlcat(the_modes, x, sizeof(the_modes));
switch( *mode_ptr )
{
case '+':
case '-':
if((( *mode_ptr == '+' ) && ( ! set )) || (( *mode_ptr == '-' ) && ( set )))
{
/* Action modifier ("+"/"-") must be changed ... */
len = strlen( the_modes ) - 1;
if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' ))
{
/* Adjust last action modifier in result */
the_modes[len] = *mode_ptr;
}
else
{
/* Append modifier character to result string */
x[0] = *mode_ptr;
strlcat( the_modes, x, sizeof( the_modes ));
}
if( *mode_ptr == '+' ) set = true;
else set = false;
}
set = *mode_ptr == '+';
}
continue;
continue;
}
/* Are there arguments left? */
@@ -380,194 +367,240 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel )
x[0] = '\0';
argadd[0] = '\0';
client = NULL;
switch (*mode_ptr) {
/* --- Channel modes --- */
case 'i': /* Invite only */
case 'm': /* Moderated */
case 'n': /* Only members can write */
case 's': /* Secret channel */
case 't': /* Topic locked */
if (modeok)
x[0] = *mode_ptr;
else
ok = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(Origin), Channel_Name(Channel));
break;
case 'k': /* Channel key */
if (! set) {
if (modeok)
x[0] = *mode_ptr;
else
ok = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(Origin), Channel_Name(Channel));
switch( *mode_ptr )
{
/* --- Channel modes --- */
case 'i': /* Invite only */
case 'm': /* Moderated */
case 'n': /* Only members can write */
case 's': /* Secret channel */
case 't': /* Topic locked */
if( modeok ) x[0] = *mode_ptr;
else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
break;
}
if (arg_arg > mode_arg) {
if (modeok) {
Channel_ModeDel(Channel, 'k');
Channel_SetKey(Channel, Req->argv[arg_arg]);
strlcpy(argadd, Channel_Key(Channel), sizeof(argadd));
x[0] = *mode_ptr;
} else {
ok = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(Origin), Channel_Name(Channel));
case 'k': /* Channel key */
if( ! set )
{
if( modeok ) x[0] = *mode_ptr;
else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
break;
}
Req->argv[arg_arg][0] = '\0';
arg_arg++;
} else {
ok = IRC_WriteStrClient(Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID(Origin), Req->command);
}
break;
case 'l': /* Member limit */
if (!set) {
if (modeok)
x[0] = *mode_ptr;
else
ok = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(Origin), Channel_Name(Channel));
break;
}
if (arg_arg > mode_arg) {
if (modeok) {
l = atol(Req->argv[arg_arg]);
if (l > 0 && l < 0xFFFF) {
Channel_ModeDel(Channel, 'l');
Channel_SetMaxUsers(Channel, l);
snprintf(argadd, sizeof(argadd), "%ld", l);
if( arg_arg > mode_arg )
{
if( modeok )
{
Channel_ModeDel( Channel, 'k' );
Channel_SetKey( Channel, Req->argv[arg_arg] );
strlcpy( argadd, Channel_Key( Channel ), sizeof( argadd ));
x[0] = *mode_ptr;
}
} else {
ok = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(Origin), Channel_Name(Channel));
else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
Req->argv[arg_arg][0] = '\0';
arg_arg++;
}
Req->argv[arg_arg][0] = '\0';
arg_arg++;
} else {
ok = IRC_WriteStrClient(Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID(Origin), Req->command);
}
break;
case 'P': /* Persistent channel */
if (modeok) {
/* Only IRC operators are allowed to
* set the 'P' channel mode! */
if (set && !(Client_OperByMe(Client) || Client_Type(Client) == CLIENT_SERVER))
ok = IRC_WriteStrClient(Origin, ERR_NOPRIVILEGES_MSG, Client_ID(Origin));
else
x[0] = 'P';
} else
ok = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(Origin), Channel_Name(Channel));
break;
/* --- Channel user modes --- */
case 'o': /* Channel operator */
case 'v': /* Voice */
if (arg_arg > mode_arg) {
if (modeok) {
client = Client_Search(Req->argv[arg_arg]);
if (client)
x[0] = *mode_ptr;
else
ok = IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, Client_ID(Client), Req->argv[arg_arg]);
} else {
ok = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(Origin), Channel_Name(Channel));
}
Req->argv[arg_arg][0] = '\0';
arg_arg++;
} else {
ok = IRC_WriteStrClient(Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID(Origin), Req->command);
}
break;
/* --- Channel lists --- */
case 'I': /* Invite lists */
case 'b': /* Ban lists */
if (arg_arg > mode_arg) {
/* modify list */
if (modeok) {
ok = set ? Add_Ban_Invite(*mode_ptr, Origin, Client, Channel, Req->argv[arg_arg])
: Del_Ban_Invite(*mode_ptr, Origin, Client, Channel, Req->argv[arg_arg]);
} else {
ok = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(Origin), Channel_Name(Channel));
}
Req->argv[arg_arg][0] = '\0';
arg_arg++;
} else {
if (*mode_ptr == 'I')
Channel_ShowInvites(Origin, Channel);
else
Channel_ShowBans(Origin, Channel);
}
break;
default:
Log(LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\" on %s!?",
set ? '+' : '-', *mode_ptr, Client_ID(Origin), Channel_Name(Channel));
if (Client_Type(Client) != CLIENT_SERVER)
ok = IRC_WriteStrClient(Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID(Origin), set ? '+' : '-', *mode_ptr);
x[0] = '\0';
goto chan_exit;
} /* switch() */
else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command );
break;
if (!ok)
break;
case 'l': /* Member limit */
if( ! set )
{
if( modeok ) x[0] = *mode_ptr;
else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
break;
}
if( arg_arg > mode_arg )
{
if( modeok )
{
l = atol( Req->argv[arg_arg] );
if( l > 0 && l < 0xFFFF )
{
Channel_ModeDel( Channel, 'l' );
Channel_SetMaxUsers( Channel, l );
snprintf( argadd, sizeof( argadd ), "%ld", l );
x[0] = *mode_ptr;
}
}
else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
Req->argv[arg_arg][0] = '\0';
arg_arg++;
}
else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command );
break;
case 'P': /* Persistent channel */
if( modeok )
{
if( set && ( ! Client_OperByMe( Client )))
{
/* Only IRC operators are allowed to set P mode */
ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin ));
}
else x[0] = 'P';
}
else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
break;
/* --- Channel user modes --- */
case 'o': /* Channel operator */
case 'v': /* Voice */
if( arg_arg > mode_arg )
{
if( modeok )
{
client = Client_Search( Req->argv[arg_arg] );
if( client ) x[0] = *mode_ptr;
else ok = IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[arg_arg] );
}
else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
Req->argv[arg_arg][0] = '\0';
arg_arg++;
}
else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command );
break;
/* --- Channel lists --- */
case 'I': /* Invite lists */
if( arg_arg > mode_arg )
{
/* modify list */
if( modeok )
{
if( set ) Add_Invite( Origin, Client, Channel, Req->argv[arg_arg] );
else Del_Invite( Origin, Client, Channel, Req->argv[arg_arg] );
}
else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
Req->argv[arg_arg][0] = '\0';
arg_arg++;
}
else Channel_ShowInvites( Origin, Channel );
break;
case 'b': /* Ban lists */
if( arg_arg > mode_arg )
{
/* modify list */
if( modeok )
{
if( set ) Add_Ban( Origin, Client, Channel, Req->argv[arg_arg] );
else Del_Ban( Origin, Client, Channel, Req->argv[arg_arg] );
}
else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel ));
Req->argv[arg_arg][0] = '\0';
arg_arg++;
}
else Channel_ShowBans( Origin, Channel );
break;
default:
Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\" on %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Origin ), Channel_Name( Channel ));
if( Client_Type( Client ) != CLIENT_SERVER ) ok = IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Origin ), set ? '+' : '-', *mode_ptr );
x[0] = '\0';
goto chan_exit;
}
if( ! ok ) break;
/* Is there a valid mode change? */
if (!x[0])
continue;
if( ! x[0] ) continue;
/* Validate target client */
if (client && (!Channel_IsMemberOf(Channel, client))) {
if (!IRC_WriteStrClient(Origin, ERR_USERNOTINCHANNEL_MSG,
Client_ID(Origin), Client_ID(client), Channel_Name(Channel)))
break;
if( client && ( ! Channel_IsMemberOf( Channel, client )))
{
if( ! IRC_WriteStrClient( Origin, ERR_USERNOTINCHANNEL_MSG, Client_ID( Origin ), Client_ID( client ), Channel_Name( Channel ))) break;
continue;
}
if (client) {
/* Channel-User-Mode */
retval = set ? Channel_UserModeAdd(Channel, client, x[0]) : Channel_UserModeDel(Channel, client, x[0]);
if (retval) {
strlcat(the_args, " ", sizeof(the_args));
strlcat(the_args, Client_ID(client), sizeof(the_args));
strlcat(the_modes, x, sizeof(the_modes));
Log(LOG_DEBUG, "User \"%s\": Mode change on %s, now \"%s\"",
Client_Mask(client), Channel_Name(Channel), Channel_UserModes(Channel, client));
if( set )
{
/* Set mode */
if( client )
{
/* Channel-User-Mode */
if( Channel_UserModeAdd( Channel, client, x[0] ))
{
strlcat( the_args, Client_ID( client ), sizeof( the_args ));
strlcat( the_args, " ", sizeof( the_args ));
strlcat( the_modes, x, sizeof( the_modes ));
Log( LOG_DEBUG, "User \"%s\": Mode change on %s, now \"%s\"", Client_Mask( client ), Channel_Name( Channel ), Channel_UserModes( Channel, client ));
}
}
} else {
/* Channel-Mode */
retval = set ? Channel_ModeAdd(Channel, x[0]) : Channel_ModeDel(Channel, x[0]);
if (retval) {
strlcat(the_modes, x, sizeof(the_modes));
Log(LOG_DEBUG, "Channel %s: Mode change, now \"%s\".", Channel_Name(Channel), Channel_Modes(Channel));
else
{
/* Channel-Mode */
if( Channel_ModeAdd( Channel, x[0] ))
{
strlcat( the_modes, x, sizeof( the_modes ));
Log( LOG_DEBUG, "Channel %s: Mode change, now \"%s\".", Channel_Name( Channel ), Channel_Modes( Channel ));
}
}
}
else
{
/* Unset mode */
if( client )
{
/* Channel-User-Mode */
if( Channel_UserModeDel( Channel, client, x[0] ))
{
strlcat( the_args, Client_ID( client ), sizeof( the_args ));
strlcat( the_args, " ", sizeof( the_args ));
strlcat( the_modes, x, sizeof( the_modes ));
Log( LOG_DEBUG, "User \"%s\": Mode change on %s, now \"%s\"", Client_Mask( client ), Channel_Name( Channel ), Channel_UserModes( Channel, client ));
}
}
else
{
/* Channel-Mode */
if( Channel_ModeDel( Channel, x[0] ))
{
strlcat( the_modes, x, sizeof( the_modes ));
Log( LOG_DEBUG, "Channel %s: Mode change, now \"%s\".", Channel_Name( Channel ), Channel_Modes( Channel ));
}
}
}
/* Are there additional arguments to add? */
if (argadd[0]) {
strlcat(the_args, " ", sizeof(the_args));
strlcat(the_args, argadd, sizeof(the_args));
if( argadd[0] )
{
len = strlen( the_args ) - 1;
if( the_args[len] != ' ' ) strlcat( the_args, " ", sizeof( the_args ));
strlcat( the_args, argadd, sizeof( the_args ));
}
}
chan_exit:
/* Are there changed modes? */
if (the_modes[1]) {
/* Clean up mode string */
len = strlen(the_modes) - 1;
if ((the_modes[len] == '+') || (the_modes[len] == '-'))
the_modes[len] = '\0';
if (Client_Type(Client) == CLIENT_SERVER) {
/* Are there changed modes? */
if( the_modes[1] )
{
/* Clean up mode string */
len = strlen( the_modes ) - 1;
if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' )) the_modes[len] = '\0';
/* Clean up argument string if there are none */
if( ! the_args[1] ) the_args[0] = '\0';
if( Client_Type( Client ) == CLIENT_SERVER )
{
/* Forward mode changes to channel users and other servers */
IRC_WriteStrServersPrefix(Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args);
IRC_WriteStrChannelPrefix(Client, Channel, Origin, false, "MODE %s %s%s", Channel_Name(Channel), the_modes, the_args);
} else {
if (use_servermode)
Origin = Client_ThisServer();
IRC_WriteStrServersPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
IRC_WriteStrChannelPrefix( Client, Channel, Origin, false, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
}
else
{
if ( use_servermode ) Origin = Client_ThisServer();
/* Send reply to client and inform other servers and channel users */
ok = IRC_WriteStrClientPrefix(Client, Origin, "MODE %s %s%s",
Channel_Name(Channel), the_modes, the_args);
IRC_WriteStrServersPrefix(Client, Origin, "MODE %s %s%s",
Channel_Name(Channel), the_modes, the_args);
IRC_WriteStrChannelPrefix(Client, Channel, Origin, false, "MODE %s %s%s",
Channel_Name(Channel), the_modes, the_args);
ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
IRC_WriteStrServersPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
IRC_WriteStrChannelPrefix( Client, Channel, Origin, false, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args );
}
}
IRC_SetPenalty(Client, 1);
IRC_SetPenalty( Client, 1 );
return CONNECTED;
} /* Channel_Mode */
@@ -600,64 +633,85 @@ IRC_AWAY( CLIENT *Client, REQUEST *Req )
static bool
Add_Ban_Invite(int what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Pattern)
Add_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
{
const char *mask;
char *mask;
bool already;
bool ret;
assert( Client != NULL );
assert( Channel != NULL );
assert( Pattern != NULL );
assert(what == 'I' || what == 'b');
mask = Lists_MakeMask(Pattern);
already = Lists_CheckDupeMask(Channel_GetListInvites(Channel), mask);
if (!already) {
if (what == 'I')
ret = Channel_AddInvite(Channel, mask, false);
else
ret = Channel_AddBan(Channel, mask);
if (!ret)
return CONNECTED;
}
if (already && (Client_Type(Prefix) == CLIENT_SERVER))
return CONNECTED;
if (what == 'I')
return Send_ListChange("+I", Prefix, Client, Channel, mask);
return Send_ListChange("+b", Prefix, Client, Channel, mask);
}
static bool
Del_Ban_Invite(int what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Pattern)
{
const char *mask;
struct list_head *list;
assert( Client != NULL );
assert( Channel != NULL );
assert( Pattern != NULL );
assert(what == 'I' || what == 'b');
mask = Lists_MakeMask( Pattern );
if (what == 'I')
list = Channel_GetListInvites(Channel);
else
list = Channel_GetListBans(Channel);
already = Lists_CheckDupeMask(Channel_GetListInvites(Channel), mask );
if (!already) {
if( ! Channel_AddInvite(Channel, mask, false ))
return CONNECTED;
}
if ( already && ( Client_Type( Prefix ) == CLIENT_SERVER ))
return CONNECTED;
Lists_Del(list, mask);
if (what == 'I')
return Send_ListChange( "-I", Prefix, Client, Channel, mask );
return Send_ListChange( "-b", Prefix, Client, Channel, mask );
}
return Send_ListChange( "+I", Prefix, Client, Channel, mask );
} /* Add_Invite */
static bool
Send_ListChange( char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Mask )
Add_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
{
char *mask;
bool already;
assert( Client != NULL );
assert( Channel != NULL );
assert( Pattern != NULL );
mask = Lists_MakeMask( Pattern );
already = Lists_CheckDupeMask(Channel_GetListBans(Channel), mask );
if (!already) {
if( ! Channel_AddBan(Channel, mask))
return CONNECTED;
}
if ( already && ( Client_Type( Prefix ) == CLIENT_SERVER ))
return CONNECTED;
return Send_ListChange( "+b", Prefix, Client, Channel, mask );
} /* Add_Ban */
static bool
Del_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
{
char *mask;
assert( Client != NULL );
assert( Channel != NULL );
assert( Pattern != NULL );
mask = Lists_MakeMask( Pattern );
Lists_Del(Channel_GetListInvites(Channel), mask);
return Send_ListChange( "-I", Prefix, Client, Channel, mask );
} /* Del_Invite */
static bool
Del_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
{
char *mask;
assert( Client != NULL );
assert( Channel != NULL );
assert( Pattern != NULL );
mask = Lists_MakeMask( Pattern );
Lists_Del(Channel_GetListBans(Channel), mask);
return Send_ListChange( "-b", Prefix, Client, Channel, mask );
} /* Del_Ban */
static bool
Send_ListChange( char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Mask )
{
/* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */

View File

@@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: irc-op.c,v 1.17 2006/12/07 17:57:20 fw Exp $";
static char UNUSED id[] = "$Id: irc-op.c,v 1.15.4.2 2007/04/03 20:23:31 fw Exp $";
#include "imp.h"
#include <assert.h>

View File

@@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: irc-oper.c,v 1.29 2007/08/02 10:14:26 fw Exp $";
static char UNUSED id[] = "$Id: irc-oper.c,v 1.27 2006/07/23 15:43:18 alex Exp $";
#include "imp.h"
#include <assert.h>
@@ -191,12 +191,12 @@ IRC_CONNECT(CLIENT * Client, REQUEST * Req)
Client_ID(Client));
/* Bad number of parameters? */
if ((Req->argc != 1) && (Req->argc != 2) && (Req->argc != 5))
if ((Req->argc != 2) && (Req->argc != 5))
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
/* Invalid port number? */
if ((Req->argc > 1) && atoi(Req->argv[1]) < 1)
if (atoi(Req->argv[1]) < 1)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
@@ -204,22 +204,14 @@ IRC_CONNECT(CLIENT * Client, REQUEST * Req)
"Got CONNECT command from \"%s\" for \"%s\".", Client_Mask(Client),
Req->argv[0]);
switch (Req->argc) {
case 1:
if (!Conf_EnablePassiveServer(Req->argv[0]))
return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
Client_ID(Client),
Req->argv[0]);
break;
case 2:
if (Req->argc == 2) {
/* Connect configured server */
if (!Conf_EnableServer
(Req->argv[0], (UINT16) atoi(Req->argv[1])))
return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
Client_ID(Client),
Req->argv[0]);
break;
default:
} else {
/* Add server */
if (!Conf_AddServer
(Req->argv[0], (UINT16) atoi(Req->argv[1]), Req->argv[2],
@@ -263,54 +255,4 @@ IRC_DISCONNECT(CLIENT *Client, REQUEST *Req )
} /* IRC_CONNECT */
GLOBAL bool
IRC_WALLOPS( CLIENT *Client, REQUEST *Req )
{
CLIENT *to, *from;
int client_type;
assert( Client != NULL );
assert( Req != NULL );
if (Req->argc != 1)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, Client_ID(Client), Req->command);
client_type = Client_Type(Client);
switch (client_type) {
case CLIENT_USER:
if (!Client_OperByMe(Client))
return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG, Client_ID(Client));
from = Client;
break;
case CLIENT_SERVER:
from = Client_Search(Req->prefix);
break;
default:
return CONNECTED;
}
if (!from)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, Client_ID(Client), Req->prefix);
for (to=Client_First(); to != NULL; to=Client_Next(to)) {
if (Client_Conn(to) < 0) /* no local connection or WALLOPS origin */
continue;
client_type = Client_Type(to);
switch (client_type) {
case CLIENT_USER:
if (Client_HasMode(to, 'w'))
IRC_WriteStrClientPrefix(to, from, "WALLOPS :%s", Req->argv[0]);
break;
case CLIENT_SERVER:
if (to != Client)
IRC_WriteStrClientPrefix(to, from, "WALLOPS :%s", Req->argv[0]);
break;
}
}
return CONNECTED;
}
/* -eof- */

View File

@@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: irc-oper.h,v 1.12 2007/08/02 10:14:26 fw Exp $
* $Id: irc-oper.h,v 1.11 2005/03/19 18:43:48 fw Exp $
*
* IRC operator commands (header)
*/
@@ -24,7 +24,6 @@ GLOBAL bool IRC_REHASH PARAMS((CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_RESTART PARAMS((CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_CONNECT PARAMS((CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_DISCONNECT PARAMS((CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_WALLOPS PARAMS(( CLIENT *Client, REQUEST *Req ));
#endif

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2007 Alexander Barton (alex@barton.de)
* Copyright (c)2001-2006 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
@@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: irc-server.c,v 1.46 2007/11/21 12:16:36 alex Exp $";
static char UNUSED id[] = "$Id: irc-server.c,v 1.39.2.3 2007/04/03 20:23:31 fw Exp $";
#include "imp.h"
#include <assert.h>
@@ -35,14 +35,56 @@ static char UNUSED id[] = "$Id: irc-server.c,v 1.46 2007/11/21 12:16:36 alex Exp
#include "log.h"
#include "messages.h"
#include "parse.h"
#include "numeric.h"
#include "ngircd.h"
#include "irc-info.h"
#include "exp.h"
#include "irc-server.h"
#ifdef IRCPLUS
static bool
Synchronize_Lists( CLIENT *Client )
{
CHANNEL *c;
struct list_head *head;
struct list_elem *elem;
assert( Client != NULL );
c = Channel_First();
while (c) {
head = Channel_GetListBans(c);
elem = Lists_GetFirst(head);
while (elem) {
if( ! IRC_WriteStrClient( Client, "MODE %s +b %s",
Channel_Name(c), Lists_GetMask(elem)))
{
return false;
}
elem = Lists_GetNext(elem);
}
head = Channel_GetListInvites(c);
elem = Lists_GetFirst(head);
while (elem) {
if( ! IRC_WriteStrClient( Client, "MODE %s +I %s",
Channel_Name( c ), Lists_GetMask(elem)))
{
return false;
}
elem = Lists_GetNext(elem);
}
c = Channel_Next(c);
}
return true;
}
#endif
/**
* Handler for the IRC command "SERVER".
* See RFC 2813 section 4.1.2.
@@ -50,10 +92,12 @@ static char UNUSED id[] = "$Id: irc-server.c,v 1.46 2007/11/21 12:16:36 alex Exp
GLOBAL bool
IRC_SERVER( CLIENT *Client, REQUEST *Req )
{
char str[LINE_LEN], *ptr;
CLIENT *from, *c;
char str[LINE_LEN], *ptr, *modes, *topic;
CLIENT *from, *c, *cl;
CL2CHAN *cl2chan;
int max_hops, i;
CHANNEL *chan;
bool ok;
int i;
CONN_ID con;
assert( Client != NULL );
@@ -122,10 +166,10 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req )
Client_SetToken( Client, atoi( Req->argv[1] ));
}
/* Mark this connection as belonging to an configured server */
Conf_SetServer(i, con);
Client_SetType(Client, CLIENT_UNKNOWNSERVER);
Log( LOG_NOTICE|LOG_snotice, "Server \"%s\" registered (connection %d, 1 hop - direct link).", Client_ID( Client ), con );
Client_SetType( Client, CLIENT_SERVER );
Conf_SetServer( i, con );
#ifdef ZLIB
/* Kompression initialisieren, wenn erforderlich */
@@ -140,23 +184,140 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req )
}
#endif
/* maximalen Hop Count ermitteln */
max_hops = 0;
c = Client_First( );
while( c )
{
if( Client_Hops( c ) > max_hops ) max_hops = Client_Hops( c );
c = Client_Next( c );
}
/* Alle bisherigen Server dem neuen Server bekannt machen,
* die bisherigen Server ueber den neuen informierenn */
for( i = 0; i < ( max_hops + 1 ); i++ )
{
c = Client_First( );
while( c )
{
if(( Client_Type( c ) == CLIENT_SERVER ) && ( c != Client ) && ( c != Client_ThisServer( )) && ( Client_Hops( c ) == i ))
{
if( Client_Conn( c ) > NONE )
{
/* Dem gefundenen Server gleich den neuen
* Server bekannt machen */
if( ! IRC_WriteStrClient( c, "SERVER %s %d %d :%s", Client_ID( Client ), Client_Hops( Client ) + 1, Client_MyToken( Client ), Client_Info( Client ))) return DISCONNECTED;
}
/* Den neuen Server ueber den alten informieren */
if( ! IRC_WriteStrClientPrefix( Client, Client_Hops( c ) == 1 ? Client_ThisServer( ) : Client_Introducer( c ), "SERVER %s %d %d :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_MyToken( c ), Client_Info( c ))) return DISCONNECTED;
}
c = Client_Next( c );
}
}
/* alle User dem neuen Server bekannt machen */
c = Client_First( );
while( c )
{
if( Client_Type( c ) == CLIENT_USER )
{
/* User an neuen Server melden */
if( ! IRC_WriteStrClient( Client, "NICK %s %d %s %s %d +%s :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_User( c ), Client_Hostname( c ), Client_MyToken( Client_Introducer( c )), Client_Modes( c ), Client_Info( c ))) return DISCONNECTED;
}
c = Client_Next( c );
}
/* Channels dem neuen Server bekannt machen */
chan = Channel_First( );
while( chan )
{
#ifdef IRCPLUS
if (strchr(Client_Flags(Client), 'H')) {
LogDebug("Peer supports IRC+ extended server handshake ...");
if (!IRC_Send_ISUPPORT(Client))
return DISCONNECTED;
return IRC_WriteStrClient(Client, RPL_ENDOFMOTD_MSG,
Client_ID(Client));
} else {
/* Send CHANINFO if the peer supports it */
if( strchr( Client_Flags( Client ), 'C' ))
{
#ifdef DEBUG
Log( LOG_DEBUG, "Sending CHANINFO commands ..." );
#endif
if (Conf_MaxNickLength != CLIENT_NICK_LEN_DEFAULT)
Log(LOG_CRIT,
"Attention: this server uses a non-standard nick length, but the peer doesn't support the IRC+ extended server handshake!");
modes = Channel_Modes( chan );
topic = Channel_Topic( chan );
if( *modes || *topic )
{
/* send CHANINFO */
if(( ! strchr( Channel_Modes( chan ), 'k' )) && ( ! strchr( Channel_Modes( chan ), 'l' )) && ( ! *topic ))
{
/* "CHANINFO <chan> +<modes>" */
if( ! IRC_WriteStrClient( Client, "CHANINFO %s +%s", Channel_Name( chan ), modes )) return DISCONNECTED;
}
else if(( ! strchr( Channel_Modes( chan ), 'k' )) && ( ! strchr( Channel_Modes( chan ), 'l' )))
{
/* "CHANINFO <chan> +<modes> :<topic>" */
if( ! IRC_WriteStrClient( Client, "CHANINFO %s +%s :%s", Channel_Name( chan ), modes, topic )) return DISCONNECTED;
}
else
{
/* "CHANINFO <chan> +<modes> <key> <limit> :<topic>" */
if( ! IRC_WriteStrClient( Client, "CHANINFO %s +%s %s %lu :%s",
Channel_Name( chan ), modes,
strchr( Channel_Modes( chan ), 'k' ) ? Channel_Key( chan ) : "*",
strchr( Channel_Modes( chan ), 'l' ) ? Channel_MaxUsers( chan ) : 0UL, topic ))
{
return DISCONNECTED;
}
}
}
}
#endif
/* alle Member suchen */
cl2chan = Channel_FirstMember( chan );
snprintf( str, sizeof( str ), "NJOIN %s :", Channel_Name( chan ));
while( cl2chan )
{
cl = Channel_GetClient( cl2chan );
assert( cl != NULL );
/* Nick, ggf. mit Modes, anhaengen */
if( str[strlen( str ) - 1] != ':' ) strlcat( str, ",", sizeof( str ));
if( strchr( Channel_UserModes( chan, cl ), 'v' )) strlcat( str, "+", sizeof( str ));
if( strchr( Channel_UserModes( chan, cl ), 'o' )) strlcat( str, "@", sizeof( str ));
strlcat( str, Client_ID( cl ), sizeof( str ));
if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 8 ))
{
/* Zeile senden */
if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED;
snprintf( str, sizeof( str ), "NJOIN %s :", Channel_Name( chan ));
}
cl2chan = Channel_NextMember( chan, cl2chan );
}
/* noch Daten da? */
if( str[strlen( str ) - 1] != ':')
{
/* Ja; Also senden ... */
if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED;
}
/* Get next channel ... */
chan = Channel_Next(chan);
}
#ifdef IRCPLUS
if (strchr(Client_Flags(Client), 'L')) {
#ifdef DEBUG
Log(LOG_DEBUG,
"Synchronizing INVITE- and BAN-lists ...");
#endif
/* Synchronize INVITE- and BAN-lists */
if (!Synchronize_Lists(Client))
return DISCONNECTED;
}
#endif
return IRC_Num_ENDOFMOTD(Client, Req);
return CONNECTED;
}
else if( Client_Type( Client ) == CLIENT_SERVER )
{
@@ -200,9 +361,8 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req )
IRC_WriteStrServersPrefix( Client, from, "SERVER %s %d %d :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_MyToken( c ), Client_Info( c ));
return CONNECTED;
} else
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
}
else return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
} /* IRC_SERVER */

View File

@@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: irc-server.h,v 1.6 2007/11/21 12:16:36 alex Exp $
* $Id: irc-server.h,v 1.5 2005/03/19 18:43:49 fw Exp $
*
* IRC commands for server links (header)
*/
@@ -22,8 +22,6 @@ GLOBAL bool IRC_SERVER PARAMS((CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_NJOIN PARAMS((CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_SQUIT PARAMS((CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_ENDOFMOTD_Server PARAMS((CLIENT *Client));
#endif

View File

@@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: irc-write.c,v 1.21 2006/08/12 11:56:24 fw Exp $";
static char UNUSED id[] = "$Id: irc-write.c,v 1.20.2.1 2006/12/02 13:06:50 fw Exp $";
#include "imp.h"
#include <assert.h>

View File

@@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: irc.c,v 1.132 2008/01/15 22:28:14 fw Exp $";
static char UNUSED id[] = "$Id: irc.c,v 1.131 2006/07/23 14:55:40 alex Exp $";
#include "imp.h"
#include <assert.h>
@@ -170,7 +170,6 @@ GLOBAL bool
IRC_NOTICE( CLIENT *Client, REQUEST *Req )
{
CLIENT *to, *from;
CHANNEL *chan;
assert( Client != NULL );
assert( Req != NULL );
@@ -190,14 +189,7 @@ IRC_NOTICE( CLIENT *Client, REQUEST *Req )
/* Okay, Ziel ist ein User */
return IRC_WriteStrClientPrefix( to, from, "NOTICE %s :%s", Client_ID( to ), Req->argv[1] );
}
else
{
chan = Channel_Search(Req->argv[0]);
if (chan)
return Channel_Notice(chan, from, Client, Req->argv[1]);
}
return CONNECTED;
else return CONNECTED;
} /* IRC_NOTICE */

View File

@@ -14,6 +14,8 @@
#include "portab.h"
static char UNUSED id[] = "$Id: lists.c,v 1.18.2.3 2007/04/03 22:08:52 fw Exp $";
#include "imp.h"
#include <assert.h>
@@ -160,8 +162,8 @@ Lists_CheckDupeMask(const struct list_head *h, const char *Mask )
}
GLOBAL const char *
Lists_MakeMask(const char *Pattern)
GLOBAL char *
Lists_MakeMask( char *Pattern )
{
/* This function generats a valid IRC mask of "any" string. This
* mask is only valid until the next call to Lists_MakeMask(),

View File

@@ -8,6 +8,8 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: lists.h,v 1.12.4.1 2007/04/03 20:23:31 fw Exp $
*
* Management of IRC lists: ban, invite, ... (header)
*/
@@ -37,7 +39,7 @@ GLOBAL bool Lists_AlreadyRegistered PARAMS(( const struct list_head *head, const
GLOBAL void Lists_Free PARAMS(( struct list_head *head ));
GLOBAL const char *Lists_MakeMask PARAMS((const char *Pattern));
GLOBAL char *Lists_MakeMask PARAMS(( char *Pattern ));
GLOBAL const char *Lists_GetMask PARAMS(( const struct list_elem *e ));
#endif

View File

@@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: log.c,v 1.62 2006/08/05 09:16:21 fw Exp $";
static char UNUSED id[] = "$Id: log.c,v 1.61.2.1 2006/12/02 13:02:07 fw Exp $";
#include "imp.h"
#include <assert.h>

View File

@@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: log.h,v 1.20 2006/08/05 09:16:21 fw Exp $
* $Id: log.h,v 1.19.2.1 2006/12/02 13:02:07 fw Exp $
*
* Logging functions (header)
*/

View File

@@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: match.c,v 1.5 2006/10/06 21:23:47 fw Exp $";
static char UNUSED id[] = "$Id: match.c,v 1.4.2.1 2006/12/02 13:01:11 fw Exp $";
#include "imp.h"
#include <assert.h>

View File

@@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: match.h,v 1.4 2006/10/06 21:23:47 fw Exp $
* $Id: match.h,v 1.3.4.1 2006/12/02 13:01:11 fw Exp $
*
* Wildcard pattern matching (header)
*/

View File

@@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: messages.h,v 1.75 2008/02/17 13:26:42 alex Exp $
* $Id: messages.h,v 1.67.2.2 2006/12/02 14:26:53 fw Exp $
*
* IRC numerics (Header)
*/
@@ -32,7 +32,6 @@
#define RPL_STATSCOMMANDS_MSG "212 %s %s %ld %ld %ld"
#define RPL_ENDOFSTATS_MSG "219 %s %c :End of STATS report"
#define RPL_UMODEIS_MSG "221 %s +%s"
#define RPL_STATSUPTIME "242 %s :Server Up %u days %u:%02u:%02u"
#define RPL_LUSERCLIENT_MSG "251 %s :There are %ld users and %ld services on %ld servers"
#define RPL_LUSEROP_MSG "252 %s %lu :operator(s) online"
#define RPL_LUSERUNKNOWN_MSG "253 %s %lu :unknown connection(s)"
@@ -56,7 +55,7 @@
#define RPL_WHOISOPERATOR_MSG "313 %s %s :is an IRC operator"
#define RPL_WHOWASUSER_MSG "314 %s %s %s %s * :%s"
#define RPL_ENDOFWHO_MSG "315 %s %s :End of WHO list"
#define RPL_WHOISIDLE_MSG "317 %s %s %lu %lu :seconds idle, signon time"
#define RPL_WHOISIDLE_MSG "317 %s %s %ld :seconds idle"
#define RPL_ENDOFWHOIS_MSG "318 %s %s :End of WHOIS list"
#define RPL_WHOISCHANNELS_MSG "319 %s %s :"
#define RPL_LIST_MSG "322 %s %s %ld :%s"
@@ -77,8 +76,6 @@
#define RPL_BANLIST_MSG "367 %s %s %s"
#define RPL_ENDOFBANLIST_MSG "368 %s %s :End of channel ban list"
#define RPL_ENDOFWHOWAS_MSG "369 %s %s :End of WHOWAS list"
#define RPL_INFO_MSG "371 %s :%s"
#define RPL_ENDOFINFO_MSG "374 %s :End of INFO list"
#define RPL_MOTD_MSG "372 %s :- %s"
#define RPL_MOTDSTART_MSG "375 %s :- %s message of the day"
#define RPL_ENDOFMOTD_MSG "376 %s :End of MOTD command"
@@ -102,8 +99,6 @@
#define ERR_USERNOTINCHANNEL_MSG "441 %s %s %s :They aren't on that channel"
#define ERR_NOTONCHANNEL_MSG "442 %s %s :You are not on that channel"
#define ERR_USERONCHANNEL_MSG "443 %s %s %s :is already on channel"
#define ERR_SUMMONDISABLED_MSG "445 %s %s :SUMMON has been disabled"
#define ERR_USERSDISABLED_MSG "446 %s %s :USERS has been disabled"
#define ERR_NOTREGISTERED_MSG "451 %s :Connection not registered"
#define ERR_NOTREGISTEREDSERVER_MSG "451 %s :Connection not registered as server link"
#define ERR_NEEDMOREPARAMS_MSG "461 %s %s :Syntax error"

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2008 Alexander Barton (alex@barton.de).
* Copyright (c)2001-2007 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
@@ -12,6 +12,8 @@
#include "portab.h"
static char UNUSED id[] = "$Id: ngircd.c,v 1.113.2.2 2007/05/05 20:25:47 alex Exp $";
/**
* @file
* The main program, including the C function main() which is called
@@ -40,6 +42,7 @@
#include "client.h"
#include "channel.h"
#include "conf.h"
#include "cvs-version.h"
#include "lists.h"
#include "log.h"
#include "parse.h"
@@ -166,12 +169,14 @@ main( int argc, const char *argv[] )
{
ok = false;
#ifdef DEBUG
if (argv[i][n] == 'd') {
if( argv[i][n] == 'd' )
{
NGIRCd_Debug = true;
ok = true;
}
#endif
if (argv[i][n] == 'f') {
if( argv[i][n] == 'f' )
{
if(( ! argv[i][n + 1] ) && ( i + 1 < argc ))
{
/* Ok, next character is a blank */
@@ -183,38 +188,31 @@ main( int argc, const char *argv[] )
ok = true;
}
}
if (argv[i][n] == 'h') {
Show_Version();
puts(""); Show_Help(); puts("");
exit(1);
}
if (argv[i][n] == 'n') {
if( argv[i][n] == 'n' )
{
NGIRCd_NoDaemon = true;
ok = true;
}
if (argv[i][n] == 'p') {
if( argv[i][n] == 'p' )
{
NGIRCd_Passive = true;
ok = true;
}
#ifdef SNIFFER
if (argv[i][n] == 's') {
if( argv[i][n] == 's' )
{
NGIRCd_Sniffer = true;
ok = true;
}
#endif
if (argv[i][n] == 't') {
if( argv[i][n] == 't' )
{
configtest = true;
ok = true;
}
if (argv[i][n] == 'V') {
Show_Version();
exit(1);
}
if (! ok) {
if( ! ok )
{
printf( "%s: invalid option \"-%c\"!\n", PACKAGE_NAME, argv[i][n] );
printf( "Try \"%s --help\" for more information.\n", PACKAGE_NAME );
exit( 1 );
@@ -399,12 +397,7 @@ Fill_Version( void )
strlcat( NGIRCd_VersionAddition, "IRCPLUS", sizeof NGIRCd_VersionAddition );
#endif
#ifdef WANT_IPV6
if (NGIRCd_VersionAddition[0])
strlcat(NGIRCd_VersionAddition, "+", sizeof(NGIRCd_VersionAddition));
strlcat(NGIRCd_VersionAddition, "IPv6", sizeof(NGIRCd_VersionAddition));
#endif
if( NGIRCd_VersionAddition[0] )
strlcat( NGIRCd_VersionAddition, "-", sizeof( NGIRCd_VersionAddition ));
@@ -414,9 +407,12 @@ Fill_Version( void )
strlcat( NGIRCd_VersionAddition, "/", sizeof( NGIRCd_VersionAddition ));
strlcat( NGIRCd_VersionAddition, TARGET_OS, sizeof( NGIRCd_VersionAddition ));
snprintf(NGIRCd_Version, sizeof NGIRCd_Version, "%s %s-%s",
PACKAGE_NAME, PACKAGE_VERSION, NGIRCd_VersionAddition);
} /* Fill_Version */
#ifdef CVSDATE
snprintf( NGIRCd_Version, sizeof NGIRCd_Version,"%s %s(%s)-%s", PACKAGE_NAME, PACKAGE_VERSION, CVSDATE, NGIRCd_VersionAddition);
#else
snprintf( NGIRCd_Version, sizeof NGIRCd_Version, "%s %s-%s", PACKAGE_NAME, PACKAGE_VERSION, NGIRCd_VersionAddition);
#endif
} /* Fill_Version */
/**
@@ -426,31 +422,24 @@ GLOBAL void
NGIRCd_Rehash( void )
{
char old_name[CLIENT_ID_LEN];
unsigned old_nicklen;
Log( LOG_NOTICE|LOG_snotice, "Re-reading configuration NOW!" );
NGIRCd_SignalRehash = false;
/* Remember old server name and nick name length */
strlcpy( old_name, Conf_ServerName, sizeof old_name );
old_nicklen = Conf_MaxNickLength;
/* Re-read configuration ... */
if (!Conf_Rehash( ))
return;
/* Close down all listening sockets */
Conn_ExitListeners( );
/* Recover old server name and nick name length: these values can't
* be changed during run-time */
if (strcmp(old_name, Conf_ServerName) != 0 ) {
strlcpy(Conf_ServerName, old_name, sizeof Conf_ServerName);
Log(LOG_ERR, "Can't change \"ServerName\" on runtime! Ignored new name.");
}
if (old_nicklen != Conf_MaxNickLength) {
Conf_MaxNickLength = old_nicklen;
Log(LOG_ERR, "Can't change \"MaxNickLength\" on runtime! Ignored new value.");
/* Remember old server name */
strlcpy( old_name, Conf_ServerName, sizeof old_name );
/* Re-read configuration ... */
Conf_Rehash( );
/* Recover old server name: it can't be changed during run-time */
if( strcmp( old_name, Conf_ServerName ) != 0 )
{
strlcpy( Conf_ServerName, old_name, sizeof Conf_ServerName );
Log( LOG_ERR, "Can't change \"ServerName\" on runtime! Ignored new name." );
}
/* Create new pre-defined channels */
@@ -557,7 +546,7 @@ static void
Show_Version( void )
{
puts( NGIRCd_Version );
puts( "Copyright (c)2001-2008 Alexander Barton (<alex@barton.de>) and Contributors." );
puts( "Copyright (c)2001-2007 Alexander Barton (<alex@barton.de>) and Contributors." );
puts( "Homepage: <http://ngircd.barton.de/>\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." );
@@ -582,8 +571,8 @@ Show_Help( void )
puts( " -s, --sniffer enable network sniffer and display all IRC traffic" );
#endif
puts( " -t, --configtest read, validate and display configuration; then exit" );
puts( " -V, --version output version information and exit" );
puts( " -h, --help display this help and exit" );
puts( " --version output version information and exit" );
puts( " --help display this help and exit" );
} /* Show_Help */
@@ -808,7 +797,7 @@ NGIRCd_Init( bool NGIRCd_NoDaemon )
if( chdir( pwd->pw_dir ) == 0 )
Log( LOG_DEBUG, "Changed working directory to \"%s\" ...", pwd->pw_dir );
else
Log( LOG_INFO, "Notice: Can't change working directory to \"%s\": %s",
Log( LOG_ERR, "Can't change working directory to \"%s\": %s",
pwd->pw_dir, strerror( errno ));
}
} else {

View File

@@ -1,334 +0,0 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2007 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.
*
* Handlers for IRC numerics sent to the server
*/
#include "portab.h"
static char UNUSED id[] = "$Id: numeric.c,v 1.1 2007/11/21 12:20:32 alex Exp $";
#include "imp.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "defines.h"
#include "resolve.h"
#include "conn.h"
#include "conf.h"
#include "conn.h"
#include "client.h"
#include "channel.h"
#include "irc-write.h"
#include "lists.h"
#include "log.h"
#include "messages.h"
#include "parse.h"
#include "exp.h"
#include "numeric.h"
/**
* Announce new server in the network
* @param Client New server
* @param Server Existing server in the network
*/
static bool
Announce_Server(CLIENT * Client, CLIENT * Server)
{
CLIENT *c;
if (Client_Conn(Server) > NONE) {
/* Announce the new server to the one already registered
* which is directly connected to the local server */
if (!IRC_WriteStrClient
(Server, "SERVER %s %d %d :%s", Client_ID(Client),
Client_Hops(Client) + 1, Client_MyToken(Client),
Client_Info(Client)))
return DISCONNECTED;
}
if (Client_Hops(Server) == 1)
c = Client_ThisServer();
else
c = Client_Introducer(Server);
/* Inform new server about the one already registered in the network */
return IRC_WriteStrClientPrefix(Client, c, "SERVER %s %d %d :%s",
Client_ID(Server), Client_Hops(Server) + 1,
Client_MyToken(Server), Client_Info(Server));
} /* Announce_Server */
/**
* Announce existing user to a new server
* @param Client New server
* @param User Existing user in the network
*/
static bool
Announce_User(CLIENT * Client, CLIENT * User)
{
return IRC_WriteStrClient(Client, "NICK %s %d %s %s %d +%s :%s",
Client_ID(User), Client_Hops(User) + 1, Client_User(User),
Client_Hostname(User), Client_MyToken(Client_Introducer(User)),
Client_Modes(User), Client_Info(User));
} /* Announce_User */
#ifdef IRCPLUS
/**
* Synchronize invite and ban lists between servers
* @param Client New server
*/
static bool
Synchronize_Lists(CLIENT * Client)
{
CHANNEL *c;
struct list_head *head;
struct list_elem *elem;
assert(Client != NULL);
c = Channel_First();
while (c) {
/* ban list */
head = Channel_GetListBans(c);
elem = Lists_GetFirst(head);
while (elem) {
if (!IRC_WriteStrClient(Client, "MODE %s +b %s",
Channel_Name(c),
Lists_GetMask(elem))) {
return DISCONNECTED;
}
elem = Lists_GetNext(elem);
}
/* invite list */
head = Channel_GetListInvites(c);
elem = Lists_GetFirst(head);
while (elem) {
if (!IRC_WriteStrClient(Client, "MODE %s +I %s",
Channel_Name(c),
Lists_GetMask(elem))) {
return DISCONNECTED;
}
elem = Lists_GetNext(elem);
}
c = Channel_Next(c);
}
return CONNECTED;
}
/**
* Send CHANINFO commands to a new server (inform it about existing channels).
* @param Client New server
* @param Chan Channel
*/
static bool
Send_CHANINFO(CLIENT * Client, CHANNEL * Chan)
{
char *modes, *topic;
bool has_k, has_l;
#ifdef DEBUG
Log(LOG_DEBUG, "Sending CHANINFO commands ...");
#endif
modes = Channel_Modes(Chan);
topic = Channel_Topic(Chan);
if (!*modes && !*topic)
return CONNECTED;
has_k = strchr(modes, 'k') != NULL;
has_l = strchr(modes, 'l') != NULL;
/* send CHANINFO */
if (!has_k && !has_l) {
if (!*topic) {
/* "CHANINFO <chan> +<modes>" */
return IRC_WriteStrClient(Client, "CHANINFO %s +%s",
Channel_Name(Chan), modes);
}
/* "CHANINFO <chan> +<modes> :<topic>" */
return IRC_WriteStrClient(Client, "CHANINFO %s +%s :%s",
Channel_Name(Chan), modes, topic);
}
/* "CHANINFO <chan> +<modes> <key> <limit> :<topic>" */
return IRC_WriteStrClient(Client, "CHANINFO %s +%s %s %lu :%s",
Channel_Name(Chan), modes,
has_k ? Channel_Key(Chan) : "*",
has_l ? Channel_MaxUsers(Chan) : 0, topic);
} /* Send_CHANINFO */
#endif /* IRCPLUS */
/**
* Handle ENDOFMOTD (376) numeric and login remote server.
* The peer is either an IRC server (no IRC+ protocol), or we got the
* ENDOFMOTD numeric from an IRC+ server. We have to register the new server.
*/
GLOBAL bool
IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req)
{
char str[LINE_LEN];
int max_hops, i;
CLIENT *c, *cl;
CHANNEL *chan;
CL2CHAN *cl2chan;
Client_SetType(Client, CLIENT_SERVER);
Log(LOG_NOTICE | LOG_snotice,
"Server \"%s\" registered (connection %d, 1 hop - direct link).",
Client_ID(Client), Client_Conn(Client));
/* Get highest hop count */
max_hops = 0;
c = Client_First();
while (c) {
if (Client_Hops(c) > max_hops)
max_hops = Client_Hops(c);
c = Client_Next(c);
}
/* Inform the new server about all other servers, and announce the
* new server to all the already registered ones. Important: we have
* to do this "in order" and can't introduce servers of which the
* "toplevel server" isn't known already. */
for (i = 0; i < (max_hops + 1); i++) {
for (c = Client_First(); c != NULL; c = Client_Next(c)) {
if (Client_Type(c) != CLIENT_SERVER)
continue; /* not a server */
if (Client_Hops(c) != i)
continue; /* not actual "nesting level" */
if (c == Client || c == Client_ThisServer())
continue; /* that's us or the peer! */
if (!Announce_Server(Client, c))
return DISCONNECTED;
}
}
/* Announce all the users to the new server */
c = Client_First();
while (c) {
if (Client_Type(c) == CLIENT_USER) {
if (!Announce_User(Client, c))
return DISCONNECTED;
}
c = Client_Next(c);
}
/* Announce all channels to the new server */
chan = Channel_First();
while (chan) {
#ifdef IRCPLUS
/* Send CHANINFO if the peer supports it */
if (strchr(Client_Flags(Client), 'C')) {
if (!Send_CHANINFO(Client, chan))
return DISCONNECTED;
}
#endif
/* Get all the members of this channel */
cl2chan = Channel_FirstMember(chan);
snprintf(str, sizeof(str), "NJOIN %s :", Channel_Name(chan));
while (cl2chan) {
cl = Channel_GetClient(cl2chan);
assert(cl != NULL);
/* Nick name, with modes (if applicable) */
if (str[strlen(str) - 1] != ':')
strlcat(str, ",", sizeof(str));
if (strchr(Channel_UserModes(chan, cl), 'v'))
strlcat(str, "+", sizeof(str));
if (strchr(Channel_UserModes(chan, cl), 'o'))
strlcat(str, "@", sizeof(str));
strlcat(str, Client_ID(cl), sizeof(str));
/* Send the data if the buffer is "full" */
if (strlen(str) > (LINE_LEN - CLIENT_NICK_LEN - 8)) {
if (!IRC_WriteStrClient(Client, "%s", str))
return DISCONNECTED;
snprintf(str, sizeof(str), "NJOIN %s :",
Channel_Name(chan));
}
cl2chan = Channel_NextMember(chan, cl2chan);
}
/* Data left in the buffer? */
if (str[strlen(str) - 1] != ':') {
/* Yes, send it ... */
if (!IRC_WriteStrClient(Client, "%s", str))
return DISCONNECTED;
}
/* Get next channel ... */
chan = Channel_Next(chan);
}
#ifdef IRCPLUS
if (strchr(Client_Flags(Client), 'L')) {
LogDebug("Synchronizing INVITE- and BAN-lists ...");
if (!Synchronize_Lists(Client))
return DISCONNECTED;
}
#endif
return CONNECTED;
} /* IRC_Num_ENDOFMOTD */
/**
* Handle ISUPPORT (005) numeric.
*/
GLOBAL bool
IRC_Num_ISUPPORT(CLIENT * Client, REQUEST * Req)
{
int i;
char *key, *value;
for (i = 1; i < Req->argc - 1; i++) {
key = Req->argv[i];
value = strchr(key, '=');
if (value)
*value++ = '\0';
else
value = "";
if (strcmp("NICKLEN", key) == 0) {
if ((unsigned int)atol(value) == Conf_MaxNickLength - 1)
continue;
/* Nick name length settings are different! */
Log(LOG_ERR,
"Peer uses incompatible nick name length (%d/%d)! Disconnecting ...",
Conf_MaxNickLength - 1, atoi(value));
Conn_Close(Client_Conn(Client),
"Incompatible nick name length",
NULL, false);
return DISCONNECTED;
}
}
return CONNECTED;
} /* IRC_Num_ISUPPORT */
/* -eof- */

View File

@@ -1,24 +0,0 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2007 by 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: numeric.h,v 1.1 2007/11/21 12:20:32 alex Exp $
*
* Handlers for IRC numerics sent to the server (header)
*/
#ifndef __numeric_h__
#define __numeric_h__
GLOBAL bool IRC_Num_ENDOFMOTD PARAMS((CLIENT *Client, UNUSED REQUEST *Req));
GLOBAL bool IRC_Num_ISUPPORT PARAMS((CLIENT *Client, REQUEST *Req));
#endif
/* -eof- */

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
* Copyright (c)2001,2002 by 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
@@ -9,8 +9,11 @@
* Please read the file COPYING, README and AUTHORS for more information.
*/
#include "portab.h"
static char UNUSED id[] = "$Id: parse.c,v 1.67.2.1 2008/02/05 13:15:05 fw Exp $";
/**
* @file
* IRC command parser and validator.
@@ -45,17 +48,11 @@
#include "irc-oper.h"
#include "irc-server.h"
#include "irc-write.h"
#include "numeric.h"
#include "exp.h"
struct _NUMERIC {
int numeric;
bool (*function) PARAMS(( CLIENT *Client, REQUEST *Request ));
};
static COMMAND My_Commands[] =
COMMAND My_Commands[] =
{
{ "ADMIN", IRC_ADMIN, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "AWAY", IRC_AWAY, CLIENT_USER, 0, 0, 0 },
@@ -64,7 +61,6 @@ static COMMAND My_Commands[] =
{ "DISCONNECT", IRC_DISCONNECT, CLIENT_USER, 0, 0, 0 },
{ "ERROR", IRC_ERROR, 0xFFFF, 0, 0, 0 },
{ "HELP", IRC_HELP, CLIENT_USER, 0, 0, 0 },
{ "INFO", IRC_INFO, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "INVITE", IRC_INVITE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "ISON", IRC_ISON, CLIENT_USER, 0, 0, 0 },
{ "JOIN", IRC_JOIN, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
@@ -91,15 +87,12 @@ static COMMAND My_Commands[] =
{ "SERVER", IRC_SERVER, 0xFFFF, 0, 0, 0 },
{ "SQUIT", IRC_SQUIT, CLIENT_SERVER, 0, 0, 0 },
{ "STATS", IRC_STATS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "SUMMON", IRC_SUMMON, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "TIME", IRC_TIME, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "TOPIC", IRC_TOPIC, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "TRACE", IRC_TRACE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "USER", IRC_USER, 0xFFFF, 0, 0, 0 },
{ "USERHOST", IRC_USERHOST, CLIENT_USER, 0, 0, 0 },
{ "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 },
{ "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 },
@@ -109,6 +102,7 @@ static COMMAND My_Commands[] =
{ NULL, NULL, 0x0, 0, 0, 0 } /* Ende-Marke */
};
static void Init_Request PARAMS(( REQUEST *Req ));
static bool Validate_Prefix PARAMS(( CONN_ID Idx, REQUEST *Req, bool *Closed ));
@@ -117,7 +111,6 @@ static bool Validate_Args PARAMS(( CONN_ID Idx, REQUEST *Req, bool *Closed ));
static bool Handle_Request PARAMS(( CONN_ID Idx, REQUEST *Req ));
#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0]))
/**
* Return the pointer to the global "IRC command structure".
@@ -335,117 +328,27 @@ Validate_Command( UNUSED CONN_ID Idx, UNUSED REQUEST *Req, bool *Closed )
static bool
Validate_Args(CONN_ID Idx, REQUEST *Req, bool *Closed)
Validate_Args( UNUSED CONN_ID Idx, UNUSED REQUEST *Req, bool *Closed )
{
#ifdef STRICT_RFC
int i;
#endif
assert( Idx >= 0 );
assert( Req != NULL );
*Closed = false;
#ifdef STRICT_RFC
/* CR and LF are never allowed in command parameters.
* But since we do accept lines terminated only with CR or LF in
* "non-RFC-compliant mode" (besides the correct CR+LF combination),
* this check can only trigger in "strict RFC" mode; therefore we
* optimize it away otherwise ... */
for (i = 0; i < Req->argc; i++) {
if (strchr(Req->argv[i], '\r') || strchr(Req->argv[i], '\n')) {
Log(LOG_ERR,
"Invalid character(s) in parameter (connection %d, command %s)!?",
Idx, Req->command);
if (!Conn_WriteStr(Idx,
"ERROR :Invalid character(s) in parameter!"))
*Closed = true;
return false;
}
}
#endif
return true;
} /* Validate_Args */
/* Command is a status code ("numeric") from another server */
static bool
Handle_Numeric(CLIENT *client, REQUEST *Req)
{
static const struct _NUMERIC Numerics[] = {
{ 005, IRC_Num_ISUPPORT },
{ 376, IRC_Num_ENDOFMOTD }
};
int i, num;
char str[LINE_LEN];
CLIENT *prefix, *target = NULL;
/* Determine target */
if (Req->argc > 0)
target = Client_Search(Req->argv[0]);
if (!target) {
/* Status code without target!? */
if (Req->argc > 0)
Log(LOG_WARNING,
"Unknown target for status code %s: \"%s\"",
Req->command, Req->argv[0]);
else
Log(LOG_WARNING,
"Unknown target for status code %s!",
Req->command);
return true;
}
if (target == Client_ThisServer()) {
/* This server is the target of the numeric */
num = atoi(Req->command);
for (i = 0; i < (int) ARRAY_SIZE(Numerics); i++) {
if (num == Numerics[i].numeric)
return Numerics[i].function(client, Req);
}
LogDebug("Ignored status code %s from \"%s\".",
Req->command, Client_ID(client));
return true;
}
/* Determine source */
if (! Req->prefix[0]) {
/* Oops, no prefix!? */
Log(LOG_WARNING, "Got status code %s from \"%s\" without prefix!?",
Req->command, Client_ID(client));
return true;
}
prefix = Client_Search(Req->prefix);
if (! prefix) { /* Oops, unknown prefix!? */
Log(LOG_WARNING, "Got status code %s from unknown source: \"%s\"", Req->command, Req->prefix);
return true;
}
/* Forward status code */
strlcpy(str, Req->command, sizeof(str));
for (i = 0; i < Req->argc; i++) {
if (i < Req->argc - 1)
strlcat(str, " ", sizeof(str));
else
strlcat(str, " :", sizeof(str));
strlcat(str, Req->argv[i], sizeof(str));
}
return IRC_WriteStrClientPrefix(target, prefix, "%s", str);
}
static bool
Handle_Request( CONN_ID Idx, REQUEST *Req )
{
/* Client-Request verarbeiten. Bei einem schwerwiegenden Fehler
* wird die Verbindung geschlossen und false geliefert. */
CLIENT *client;
bool result = true;
int client_type;
CLIENT *client, *target, *prefix;
char str[LINE_LEN];
bool result;
COMMAND *cmd;
int i, client_type;
assert( Idx >= 0 );
assert( Req != NULL );
@@ -454,44 +357,91 @@ Handle_Request( CONN_ID Idx, REQUEST *Req )
client = Conn_GetClient( Idx );
assert( client != NULL );
/* Numeric? */
client_type = Client_Type(client);
if ((client_type == CLIENT_SERVER ||
client_type == CLIENT_UNKNOWNSERVER)
&& strlen(Req->command) == 3 && atoi(Req->command) > 1)
return Handle_Numeric(client, Req);
/* Statuscode? */
if(( Client_Type( client ) == CLIENT_SERVER ) && ( strlen( Req->command ) == 3 ) && ( atoi( Req->command ) > 100 ))
{
/* Command is a status code from an other server */
cmd = My_Commands;
while (cmd->name) {
/* Befehl suchen */
if (strcasecmp(Req->command, cmd->name) != 0) {
cmd++;
continue;
/* Determine target */
if( Req->argc > 0 ) target = Client_Search( Req->argv[0] );
else target = NULL;
if( ! target )
{
/* Status code without target!? */
if( Req->argc > 0 ) Log( LOG_WARNING, "Unknown target for status code %s: \"%s\"", Req->command, Req->argv[0] );
else Log( LOG_WARNING, "Unknown target for status code %s!", Req->command );
return true;
}
if( target == Client_ThisServer( ))
{
/* This server is the target, ignore it */
Log( LOG_DEBUG, "Ignored status code %s from \"%s\".", Req->command, Client_ID( client ));
return true;
}
if (!(client_type & cmd->type))
return IRC_WriteStrClient(client, ERR_NOTREGISTERED_MSG, Client_ID(client));
/* Determine source */
if( ! Req->prefix[0] )
{
/* Oops, no prefix!? */
Log( LOG_WARNING, "Got status code %s from \"%s\" without prefix!?", Req->command, Client_ID( client ));
return true;
}
else prefix = Client_Search( Req->prefix );
if( ! prefix )
{
/* Oops, unknown prefix!? */
Log( LOG_WARNING, "Got status code %s from unknown source: \"%s\"", Req->command, Req->prefix );
return true;
}
/* Command is allowed for this client: call it and count produced bytes */
Conn_ResetWCounter();
result = (cmd->function)(client, Req);
cmd->bytes += Conn_WCounter();
/* Adjust counters */
if (client_type != CLIENT_SERVER)
cmd->lcount++;
else
cmd->rcount++;
return result;
/* Forward status code */
strlcpy( str, Req->command, sizeof( str ));
for( i = 0; i < Req->argc; i++ )
{
if( i < Req->argc - 1 ) strlcat( str, " ", sizeof( str ));
else strlcat( str, " :", sizeof( str ));
strlcat( str, Req->argv[i], sizeof( str ));
}
return IRC_WriteStrClientPrefix( target, prefix, "%s", str );
}
if (client_type != CLIENT_USER &&
client_type != CLIENT_SERVER &&
client_type != CLIENT_SERVICE )
return true;
cmd = My_Commands;
client_type = Client_Type( client );
while( cmd->name )
{
/* Befehl suchen */
if( strcasecmp( Req->command, cmd->name ) != 0 )
{
cmd++; continue;
}
if( client_type & cmd->type )
{
/* Command is allowed for this client: call it and count produced bytes */
Conn_ResetWCounter( );
result = (cmd->function)( client, Req );
cmd->bytes += Conn_WCounter( );
/* Adjust counters */
if( client_type != CLIENT_SERVER ) cmd->lcount++;
else cmd->rcount++;
return result;
}
else
{
/* Befehl ist fuer diesen Client-Typ nicht erlaubt! */
return IRC_WriteStrClient( client, ERR_NOTREGISTERED_MSG, Client_ID( client ));
}
}
if( Client_Type( client ) != CLIENT_USER &&
Client_Type( client ) != CLIENT_SERVER &&
Client_Type( client ) != CLIENT_SERVICE )
return true;
/* Unknown command and registered connection: generate error: */
LogDebug("Connection %d: Unknown command \"%s\", %d %s,%s prefix.",
Log( LOG_DEBUG, "Connection %d: Unknown command \"%s\", %d %s,%s prefix.",
Client_Conn( client ), Req->command, Req->argc,
Req->argc == 1 ? "parameter" : "parameters",
Req->prefix ? "" : " no" );
@@ -500,8 +450,10 @@ Handle_Request( CONN_ID Idx, REQUEST *Req )
result = IRC_WriteStrClient(client, ERR_UNKNOWNCOMMAND_MSG,
Client_ID(client), Req->command);
Conn_SetPenalty(Idx, 1);
return result;
}
return result;
return true;
} /* Handle_Request */

View File

@@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: parse.h,v 1.13 2008/01/13 16:12:49 fw Exp $
* $Id: parse.h,v 1.11 2005/03/19 18:43:49 fw Exp $
*
* IRC command parser and validator (header)
*/
@@ -33,8 +33,8 @@ typedef struct _COMMAND
char *name; /* command name */
bool (*function) PARAMS(( CLIENT *Client, REQUEST *Request ));
CLIENT_TYPE type; /* valid client types (bit mask) */
long lcount, rcount; /* number of local and remote calls */
long bytes; /* number of bytes created */
long lcount, rcount; /* number of local and remote calls */
long bytes; /* number of bytes created */
} COMMAND;
@@ -42,6 +42,7 @@ GLOBAL bool Parse_Request PARAMS((CONN_ID Idx, char *Request ));
GLOBAL COMMAND *Parse_GetCommandStruct PARAMS(( void ));
#endif

View File

@@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: resolve.c,v 1.29 2008/02/26 22:04:17 fw Exp $";
static char UNUSED id[] = "$Id: resolve.c,v 1.24.2.2 2006/12/17 22:59:56 fw Exp $";
#include "imp.h"
#include <assert.h>
@@ -24,6 +24,7 @@ static char UNUSED id[] = "$Id: resolve.c,v 1.29 2008/02/26 22:04:17 fw Exp $";
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#ifdef IDENTAUTH
@@ -41,13 +42,12 @@ static char UNUSED id[] = "$Id: resolve.c,v 1.29 2008/02/26 22:04:17 fw Exp $";
#include "io.h"
static void Do_ResolveAddr PARAMS(( const ng_ipaddr_t *Addr, int Sock, int w_fd ));
static void Do_ResolveAddr PARAMS(( struct sockaddr_in *Addr, int Sock, int w_fd ));
static void Do_ResolveName PARAMS(( const char *Host, int w_fd ));
static bool register_callback PARAMS((RES_STAT *s, void (*cbfunc)(int, short)));
#ifdef WANT_IPV6
extern bool Conf_ConnectIPv4;
extern bool Conf_ConnectIPv6;
#ifdef h_errno
static char *Get_Error PARAMS(( int H_Error ));
#endif
static pid_t
@@ -82,7 +82,7 @@ Resolver_fork(int *pipefds)
* Resolve IP (asynchronous!).
*/
GLOBAL bool
Resolve_Addr(RES_STAT * s, const ng_ipaddr_t *Addr, int identsock,
Resolve_Addr(RES_STAT * s, struct sockaddr_in *Addr, int identsock,
void (*cbfunc) (int, short))
{
int pipefd[2];
@@ -92,8 +92,9 @@ Resolve_Addr(RES_STAT * s, const ng_ipaddr_t *Addr, int identsock,
pid = Resolver_fork(pipefd);
if (pid > 0) {
Log(LOG_DEBUG, "Resolver for %s created (PID %d).", ng_ipaddr_tostr(Addr), pid);
#ifdef DEBUG
Log( LOG_DEBUG, "Resolver for %s created (PID %d).", inet_ntoa( Addr->sin_addr ), pid );
#endif
s->pid = pid;
s->resolver_fd = pipefd[0];
return register_callback(s, cbfunc);
@@ -146,302 +147,92 @@ Resolve_Init(RES_STAT *s)
}
#ifndef WANT_IPV6
#ifdef h_errno
static char *
Get_Error( int H_Error )
{
/* Get error message for H_Error */
switch( H_Error ) {
case HOST_NOT_FOUND:
return "host not found";
case NO_DATA:
return "name valid but no IP address defined";
case NO_RECOVERY:
return "name server error";
case TRY_AGAIN:
return "name server temporary not available";
}
return "unknown error";
}
#endif /* h_errno */
#endif /* WANT_IPV6 */
/* Do "IDENT" (aka "AUTH") lookup and append result to resolved_addr array */
static void
Do_IdentQuery(int identsock, array *resolved_addr)
{
#ifdef IDENTAUTH
char *res;
assert(identsock >= 0);
#ifdef DEBUG
Log_Resolver(LOG_DEBUG, "Doing IDENT lookup on socket %d ...", identsock);
#endif
if (identsock < 0)
return;
res = ident_id( identsock, 10 );
#ifdef DEBUG
Log_Resolver(LOG_DEBUG, "Ok, IDENT lookup on socket %d done: \"%s\"",
identsock, res ? res : "(NULL)" );
#endif
if (!res) /* no result */
return;
if (!array_cats(resolved_addr, res))
Log_Resolver(LOG_WARNING, "Resolver: Cannot copy IDENT result: %s!", strerror(errno));
free(res);
#else
(void) identsock;
(void) resolved_addr;
#endif
}
/**
* perform reverse DNS lookup and put result string into resbuf.
* If no hostname could be obtained, this function stores the string representation of
* 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)
* @return true if reverse lookup successful, false otherwise
*/
static bool
ReverseLookup(const ng_ipaddr_t *IpAddr, char *resbuf, size_t reslen)
{
char tmp_ip_str[NG_INET_ADDRSTRLEN];
const char *errmsg;
#ifdef HAVE_GETNAMEINFO
static const char funcname[]="getnameinfo";
int res;
*resbuf = 0;
res = getnameinfo((struct sockaddr *) IpAddr, ng_ipaddr_salen(IpAddr),
resbuf, reslen, NULL, 0, NI_NAMEREQD);
if (res == 0)
return true;
if (res == EAI_SYSTEM)
errmsg = strerror(errno);
else
errmsg = gai_strerror(res);
#else
const struct sockaddr_in *Addr = (const struct sockaddr_in *) IpAddr;
struct hostent *h;
static const char funcname[]="gethostbyaddr";
h = gethostbyaddr((char *)&Addr->sin_addr, sizeof(Addr->sin_addr), AF_INET);
if (h) {
if (strlcpy(resbuf, h->h_name, reslen) < reslen)
return true;
errmsg = "hostname too long";
} else {
# ifdef h_errno
errmsg = Get_Error(h_errno);
# else
errmsg = "unknown error";
# endif /* h_errno */
}
#endif /* HAVE_GETNAMEINFO */
assert(errmsg);
assert(reslen >= NG_INET_ADDRSTRLEN);
ng_ipaddr_tostr_r(IpAddr, tmp_ip_str);
Log_Resolver(LOG_WARNING, "%s: Can't resolve address \"%s\": %s",
funcname, tmp_ip_str, errmsg);
strlcpy(resbuf, tmp_ip_str, reslen);
return false;
}
/**
* perform DNS lookup of given host name and fill IpAddr with a list of
* ip addresses associated with that name.
* ip addresses found are stored in the "array *IpAddr" argument (type ng_ipaddr_t)
* @param hostname The domain name to look up.
* @param IpAddr pointer to empty and initialized array to store results
* @return true if lookup successful, false if domain name not found
*/
static bool
ForwardLookup(const char *hostname, array *IpAddr)
{
ng_ipaddr_t addr;
#ifdef HAVE_GETADDRINFO
int res;
struct addrinfo *a, *ai_results;
static struct addrinfo hints = {
#ifndef WANT_IPV6
.ai_family = AF_INET,
#endif
#ifdef AI_ADDRCONFIG /* glibc has this, but not e.g. netbsd 4.0 */
.ai_flags = AI_ADDRCONFIG,
#endif
.ai_socktype = SOCK_STREAM,
.ai_protocol = IPPROTO_TCP
};
#ifdef WANT_IPV6
assert(Conf_ConnectIPv6 || Conf_ConnectIPv4);
if (!Conf_ConnectIPv6)
hints.ai_family = AF_INET;
if (!Conf_ConnectIPv4)
hints.ai_family = AF_INET6;
#endif
res = getaddrinfo(hostname, NULL, &hints, &ai_results);
switch (res) {
case 0: break;
case EAI_SYSTEM:
Log_Resolver(LOG_WARNING, "Can't resolve \"%s\": %s", hostname, strerror(errno));
return false;
default:
Log_Resolver(LOG_WARNING, "Can't resolve \"%s\": %s", hostname, gai_strerror(res));
return false;
}
for (a = ai_results; a != NULL; a = a->ai_next) {
assert(a->ai_addrlen <= sizeof(addr));
if (a->ai_addrlen > sizeof(addr))
continue;
memcpy(&addr, a->ai_addr, a->ai_addrlen);
if (!array_catb(IpAddr, (char *)&addr, sizeof(addr)))
break;
}
freeaddrinfo(ai_results);
return a == NULL;
#else
struct hostent *h = gethostbyname(hostname);
if (!h) {
#ifdef h_errno
Log_Resolver(LOG_WARNING, "Can't resolve \"%s\": %s", hostname, Get_Error(h_errno));
#else
Log_Resolver(LOG_WARNING, "Can't resolve \"%s\"", hostname);
#endif
return false;
}
memset(&addr, 0, sizeof(addr));
addr.sin4.sin_family = AF_INET;
memcpy(&addr.sin4.sin_addr, h->h_addr, sizeof(struct in_addr));
return array_copyb(IpAddr, (char *)&addr, sizeof(addr));
#endif /* HAVE_GETADDRINFO */
}
static bool
Addr_in_list(const array *resolved_addr, const ng_ipaddr_t *Addr)
{
char tmp_ip_str[NG_INET_ADDRSTRLEN];
const ng_ipaddr_t *tmpAddrs = array_start(resolved_addr);
size_t len = array_length(resolved_addr, sizeof(*tmpAddrs));
assert(len > 0);
assert(tmpAddrs);
while (len > 0) {
if (ng_ipaddr_ipequal(Addr, tmpAddrs))
return true;
tmpAddrs++;
len--;
}
/* failed; print list of addresses */
ng_ipaddr_tostr_r(Addr, tmp_ip_str);
len = array_length(resolved_addr, sizeof(*tmpAddrs));
tmpAddrs = array_start(resolved_addr);
while (len > 0) {
Log_Resolver(LOG_WARNING, "Address mismatch: %s != %s",
tmp_ip_str, ng_ipaddr_tostr(tmpAddrs));
tmpAddrs++;
len--;
}
return false;
}
static void
Log_Forgery_NoIP(const char *ip, const char *host)
{
Log_Resolver(LOG_WARNING, "Possible forgery: %s resolved to %s "
"(which has no ip address)", ip, host);
}
static void
Log_Forgery_WrongIP(const char *ip, const char *host)
{
Log_Resolver(LOG_WARNING,"Possible forgery: %s resolved to %s "
"(which points to different address)", ip, host);
}
static void
ArrayWrite(int fd, const array *a)
{
size_t len = array_bytes(a);
const char *data = array_start(a);
assert(data);
if( (size_t)write(fd, data, len) != len )
Log_Resolver( LOG_CRIT, "Resolver: Can't write to parent: %s!",
strerror(errno));
}
static void
Do_ResolveAddr(const ng_ipaddr_t *Addr, int identsock, int w_fd)
Do_ResolveAddr( struct sockaddr_in *Addr, int identsock, int w_fd )
{
/* Resolver sub-process: resolve IP address and write result into
* pipe to parent. */
char hostname[CLIENT_HOST_LEN];
char tmp_ip_str[NG_INET_ADDRSTRLEN];
char hostname[HOST_LEN];
char ipstr[HOST_LEN];
struct hostent *h;
size_t len;
struct in_addr *addr;
char *ntoaptr;
array resolved_addr;
#ifdef IDENTAUTH
char *res;
#endif
array_init(&resolved_addr);
ng_ipaddr_tostr_r(Addr, tmp_ip_str);
/* Resolve IP address */
#ifdef DEBUG
Log_Resolver(LOG_DEBUG, "Now resolving %s ...", tmp_ip_str);
Log_Resolver( LOG_DEBUG, "Now resolving %s ...", inet_ntoa( Addr->sin_addr ));
#endif
if (!ReverseLookup(Addr, hostname, sizeof(hostname)))
goto dns_done;
if (ForwardLookup(hostname, &resolved_addr)) {
if (!Addr_in_list(&resolved_addr, Addr)) {
Log_Forgery_WrongIP(tmp_ip_str, hostname);
strlcpy(hostname, tmp_ip_str, sizeof(hostname));
}
h = gethostbyaddr( (char *)&Addr->sin_addr, sizeof( Addr->sin_addr ), AF_INET );
if (!h) {
#ifdef h_errno
Log_Resolver( LOG_WARNING, "Can't resolve address \"%s\": %s!", inet_ntoa( Addr->sin_addr ), Get_Error( h_errno ));
#else
Log_Resolver( LOG_WARNING, "Can't resolve address \"%s\"!", inet_ntoa( Addr->sin_addr ));
#endif
strlcpy( hostname, inet_ntoa( Addr->sin_addr ), sizeof( hostname ));
} else {
Log_Forgery_NoIP(tmp_ip_str, hostname);
strlcpy(hostname, tmp_ip_str, sizeof(hostname));
strlcpy( hostname, h->h_name, sizeof( hostname ));
h = gethostbyname( hostname );
if ( h ) {
if (memcmp(h->h_addr, &Addr->sin_addr, sizeof (struct in_addr))) {
addr = (struct in_addr*) h->h_addr;
strlcpy(ipstr, inet_ntoa(*addr), sizeof ipstr);
ntoaptr = inet_ntoa( Addr->sin_addr );
Log(LOG_WARNING,"Possible forgery: %s resolved to %s (which is at ip %s!)",
ntoaptr, hostname, ipstr);
strlcpy( hostname, ntoaptr, sizeof hostname);
}
} else {
ntoaptr = inet_ntoa( Addr->sin_addr );
Log(LOG_WARNING, "Possible forgery: %s resolved to %s (which has no ip address)",
ntoaptr, hostname);
strlcpy( hostname, ntoaptr, sizeof hostname);
}
}
#ifdef DEBUG
Log_Resolver(LOG_DEBUG, "Ok, translated %s to \"%s\".", tmp_ip_str, hostname);
#endif
dns_done:
len = strlen(hostname);
hostname[len] = '\n';
if (!array_copyb(&resolved_addr, hostname, ++len)) {
Log_Resolver(LOG_CRIT, "Resolver: Can't copy resolved name: %s!", strerror(errno));
array_free(&resolved_addr);
Log_Resolver( LOG_DEBUG, "Ok, translated %s to \"%s\".", inet_ntoa( Addr->sin_addr ), hostname );
len = strlen( hostname );
hostname[len] = '\n'; len++;
if (!array_copyb(&resolved_addr, hostname, len )) {
Log_Resolver( LOG_CRIT, "Resolver: Can't copy resolved name: %s!", strerror( errno ));
close( w_fd );
return;
}
Do_IdentQuery(identsock, &resolved_addr);
#ifdef IDENTAUTH
assert(identsock >= 0);
if (identsock >= 0) {
/* Do "IDENT" (aka "AUTH") lookup and append result to resolved_addr array */
#ifdef DEBUG
Log_Resolver( LOG_DEBUG, "Doing IDENT lookup on socket %d ...", identsock );
#endif
res = ident_id( identsock, 10 );
#ifdef DEBUG
Log_Resolver(LOG_DEBUG, "Ok, IDENT lookup on socket %d done: \"%s\"",
identsock, res ? res : "(NULL)" );
#endif
if (res && !array_cats(&resolved_addr, res)) {
Log_Resolver(LOG_WARNING, "Resolver: Cannot copy IDENT result: %s!", strerror(errno));
/* omit ident and return hostname only */
}
ArrayWrite(w_fd, &resolved_addr);
if (res) free(res);
}
#else
(void)identsock;
#endif
len = array_bytes(&resolved_addr);
if( (size_t)write( w_fd, array_start(&resolved_addr), len) != len )
Log_Resolver( LOG_CRIT, "Resolver: Can't write result to parent: %s!", strerror( errno ));
close(w_fd);
array_free(&resolved_addr);
} /* Do_ResolveAddr */
@@ -451,36 +242,65 @@ Do_ResolveName( const char *Host, int w_fd )
{
/* Resolver sub-process: resolve name and write result into pipe
* to parent. */
array IpAddrs;
#ifdef DEBUG
ng_ipaddr_t *addr;
size_t len;
#endif
Log_Resolver(LOG_DEBUG, "Now resolving \"%s\" ...", Host);
array_init(&IpAddrs);
char ip[16];
struct hostent *h;
struct in_addr *addr;
size_t len;
Log_Resolver( LOG_DEBUG, "Now resolving \"%s\" ...", Host );
/* Resolve hostname */
if (!ForwardLookup(Host, &IpAddrs)) {
h = gethostbyname( Host );
if( h ) {
addr = (struct in_addr *)h->h_addr;
strlcpy( ip, inet_ntoa( *addr ), sizeof( ip ));
} else {
#ifdef h_errno
Log_Resolver( LOG_WARNING, "Can't resolve \"%s\": %s!", Host, Get_Error( h_errno ));
#else
Log_Resolver( LOG_WARNING, "Can't resolve \"%s\"!", Host );
#endif
close(w_fd);
return;
}
#ifdef DEBUG
len = array_length(&IpAddrs, sizeof(*addr));
assert(len > 0);
addr = array_start(&IpAddrs);
assert(addr);
for (; len > 0; --len,addr++) {
Log_Resolver(LOG_DEBUG, "translated \"%s\" to %s.",
Host, ng_ipaddr_tostr(addr));
}
Log_Resolver( LOG_DEBUG, "Ok, translated \"%s\" to %s.", Host, ip );
#endif
/* Write result into pipe to parent */
ArrayWrite(w_fd, &IpAddrs);
array_free(&IpAddrs);
len = strlen( ip );
if ((size_t)write( w_fd, ip, len ) != len) {
Log_Resolver( LOG_CRIT, "Resolver: Can't write to parent: %s!", strerror( errno ));
close( w_fd );
}
} /* Do_ResolveName */
#ifdef h_errno
static char *
Get_Error( int H_Error )
{
/* Get error message for H_Error */
switch( H_Error )
{
case HOST_NOT_FOUND:
return "host not found";
case NO_DATA:
return "name valid but no IP address defined";
case NO_RECOVERY:
return "name server error";
case TRY_AGAIN:
return "name server temporary not available";
default:
return "unknown error";
}
} /* Get_Error */
#endif
static bool
register_callback( RES_STAT *s, void (*cbfunc)(int, short))
{

View File

@@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: resolve.h,v 1.14 2008/02/26 22:04:17 fw Exp $
* $Id: resolve.h,v 1.13 2006/05/10 21:24:02 alex Exp $
*
* Asynchronous resolver (header)
*/
@@ -18,8 +18,6 @@
#define __resolve_h__
#include "array.h"
#include "tool.h"
#include "ng_ipaddr.h"
#include <netinet/in.h>
/* This struct must not be accessed directly */
@@ -32,7 +30,7 @@ typedef struct _Res_Stat {
#define Resolve_Getfd(x) ((x)->resolver_fd)
#define Resolve_INPROGRESS(x) ((x)->resolver_fd >= 0)
GLOBAL bool Resolve_Addr PARAMS(( RES_STAT *s, const ng_ipaddr_t *Addr, int identsock, void (*cbfunc)(int, short)));
GLOBAL bool Resolve_Addr PARAMS(( RES_STAT *s, struct sockaddr_in *Addr, int identsock, void (*cbfunc)(int, short)));
GLOBAL bool Resolve_Name PARAMS(( RES_STAT *s, const char *Host, void (*cbfunc)(int, short) ));
GLOBAL size_t Resolve_Read PARAMS(( RES_STAT *s, void *buf, size_t buflen));
GLOBAL void Resolve_Init PARAMS(( RES_STAT *s));

View File

@@ -1 +0,0 @@
portabtest

View File

@@ -1,10 +0,0 @@
T-ngircd
channel-test
connect-test
misc-test
mode-test
who-test
ngircd-test.log
ngircd-test.motd
logs
tests

View File

@@ -9,7 +9,7 @@
# Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
# der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
#
# $Id: Makefile.am,v 1.18 2008/02/17 13:26:42 alex Exp $
# $Id: Makefile.am,v 1.14 2004/09/08 09:40:51 alex Exp $
#
AUTOMAKE_OPTIONS = ../portab/ansi2knr
@@ -20,8 +20,8 @@ EXTRA_DIST = \
README functions.inc getpid.sh \
start-server.sh stop-server.sh tests.sh stress-server.sh \
test-loop.sh wait-tests.sh \
channel-test.e connect-test.e check-idle.e misc-test.e mode-test.e \
who-test.e stress-A.e stress-B.e \
connect-test.e channel-test.e mode-test.e \
stress-A.e stress-B.e check-idle.e \
ngircd-test.conf
all:
@@ -40,31 +40,18 @@ ngircd-TEST-Binary:
[ -f getpid.sh ] || ln -s $(srcdir)/getpid.sh .
connect-test: tests.sh
rm -f connect-test
ln -s $(srcdir)/tests.sh connect-test
channel-test: tests.sh
rm -f channel-test
ln -s $(srcdir)/tests.sh channel-test
who-test: tests.sh
rm -f who-test
ln -s $(srcdir)/tests.sh who-test
misc-test: tests.sh
rm -f misc-test
ln -s $(srcdir)/tests.sh misc-test
mode-test: tests.sh
rm -f mode-test
ln -s $(srcdir)/tests.sh mode-test
TESTS = start-server.sh \
connect-test \
channel-test \
misc-test \
mode-test \
who-test \
stress-server.sh \
stop-server.sh

View File

@@ -1,4 +1,4 @@
# $Id: channel-test.e,v 1.4 2008/02/05 13:31:51 fw Exp $
# $Id: channel-test.e,v 1.3 2003/12/27 13:01:12 alex Exp $
spawn telnet localhost 6789
expect {
@@ -69,36 +69,6 @@ expect {
"@* PART #channel :nick"
}
send "join #channel\r"
expect {
timeout { exit 1 }
"@* JOIN :#channel"
}
expect {
timeout { exit 1 }
"366"
}
send "join #channel2\r"
expect {
timeout { exit 1 }
"@* JOIN :#channel2"
}
expect {
timeout { exit 1 }
"366"
}
send "join 0\r"
expect {
timeout { exit 1 }
"@* PART #channel2 :nick"
}
expect {
timeout { exit 1 }
"@* PART #channel :nick"
}
send "quit\r"
expect {
timeout { exit 1 }

View File

@@ -1,6 +1,6 @@
#!/bin/sh
# ngIRCd Test Suite
# $Id: getpid.sh,v 1.5 2006/08/05 00:15:28 alex Exp $
# $Id: getpid.sh,v 1.4.6.1 2006/12/17 13:49:49 alex Exp $
# did we get a name?
[ $# -ne 1 ] && exit 1

View File

@@ -1,44 +0,0 @@
# $Id: misc-test.e,v 1.2 2008/02/17 13:51:00 alex Exp $
spawn telnet localhost 6789
expect {
timeout { exit 1 }
"Connected"
}
send "nick nick\r"
send "user user . . :User\r"
expect {
timeout { exit 1 }
"376"
}
send "summon\r"
expect {
timeout { exit 1 }
"445"
}
send "users\r"
expect {
timeout { exit 1 }
"446"
}
send "info\r"
expect {
timeout { exit 1 }
"371"
}
expect {
timeout { exit 1 }
"374"
}
send "quit\r"
expect {
timeout { exit 1 }
"ERROR"
}
# -eof-

View File

@@ -1,4 +1,4 @@
# $Id: mode-test.e,v 1.7 2008/02/16 11:27:49 fw Exp $
# $Id: mode-test.e,v 1.6 2004/03/10 20:40:06 alex Exp $
spawn telnet localhost 6789
expect {
@@ -72,7 +72,7 @@ expect {
send "mode #channel +v nick\r"
expect {
timeout { exit 1 }
"@* MODE #channel +v nick\r"
"@* MODE #channel +v nick"
}
send "mode #channel +I nick1\r"
@@ -96,7 +96,7 @@ expect {
send "mode #channel -vo nick nick\r"
expect {
timeout { exit 1 }
"@* MODE #channel -vo nick nick\r"
"@* MODE #channel -vo nick nick"
}
send "quit\r"

View File

@@ -1,4 +1,4 @@
# $Id: ngircd-test.conf,v 1.6 2008/02/17 00:00:13 fw Exp $
# $Id: ngircd-test.conf,v 1.4 2003/11/05 23:31:43 alex Exp $
[Global]
Name = ngircd.test.server
@@ -7,7 +7,6 @@
MotdFile = ngircd-test.motd
AdminEMail = admin@irc.server
MaxConnectionsIP = 0
OperCanUseMode = yes
[Operator]
Name = TestOp

View File

@@ -1,162 +0,0 @@
spawn telnet localhost 6789
expect {
timeout { exit 1 }
"Connected"
}
send "nick nick\r"
send "user user . . :Real Name\r"
expect {
timeout { exit 1 }
"376"
}
send "who\r"
expect {
timeout { exit 1 }
":ngircd.test.server 352 nick \* ~user localhost ngircd.test.server nick H :0 Real Name"
}
send "join #channel\r"
expect {
timeout { exit 1 }
"@* JOIN :#channel"
}
send "who 0\r"
expect {
timeout { exit 1 }
":ngircd.test.server 352 nick #channel ~user localhost ngircd.test.server nick H@ :0 Real Name"
}
send "away :testing\r"
expect {
timeout { exit 1 }
"306 nick"
}
send "who *\r"
expect {
timeout { exit 1 }
":ngircd.test.server 352 nick #channel ~user localhost ngircd.test.server nick G@ :0 Real Name"
}
send "mode #channel +v nick\r"
expect {
timeout { exit 1 }
"@* MODE #channel +v nick\r"
}
send "who localhost\r"
expect {
timeout { exit 1 }
":ngircd.test.server 352 nick #channel ~user localhost ngircd.test.server nick G@ :0 Real Name"
}
send "mode #channel -o nick\r"
expect {
timeout { exit 1 }
"@* MODE #channel -o nick\r"
}
send "who ngircd.test.server\r"
expect {
timeout { exit 1 }
":ngircd.test.server 352 nick #channel ~user localhost ngircd.test.server nick G+ :0 Real Name"
}
send "part #channel\r"
expect {
timeout { exit 1 }
"@* PART #channel :nick"
}
send "who Real?Name\r"
expect {
timeout { exit 1 }
":ngircd.test.server 352 nick \* ~user localhost ngircd.test.server nick G :0 Real Name"
}
send "oper TestOp 123\r"
expect {
timeout { exit 1 }
"MODE nick :+o"
}
expect {
timeout { exit 1 }
"381 nick"
}
send "who 0 o\r"
expect {
timeout { exit 1 }
":ngircd.test.server 352 nick \* ~user localhost ngircd.test.server nick G* :0 Real Name"
}
send "away\r"
expect {
timeout { exit 1 }
"305 nick"
}
send "who *cal*ho??\r"
expect {
timeout { exit 1 }
":ngircd.test.server 352 nick \* ~user localhost ngircd.test.server nick H* :0 Real Name"
}
send "join #opers\r"
expect {
timeout { exit 1 }
"@* JOIN :#opers"
}
send "who #opers\r"
expect {
timeout { exit 1 }
":ngircd.test.server 352 nick #opers ~user localhost ngircd.test.server nick H*@ :0 Real Name"
}
send "mode #opers -o nick\r"
expect {
timeout { exit 1 }
"@* MODE #opers -o nick\r"
}
send "who *.server\r"
expect {
timeout { exit 1 }
":ngircd.test.server 352 nick #opers ~user localhost ngircd.test.server nick H* :0 Real Name"
}
send "mode #opers +v nick\r"
expect {
timeout { exit 1 }
"@* MODE #opers +v nick\r"
}
send "who Real*me\r"
expect {
timeout { exit 1 }
":ngircd.test.server 352 nick #opers ~user localhost ngircd.test.server nick H*+ :0 Real Name"
}
send "mode #opers +s\r"
expect {
timeout { exit 1 }
"@* MODE #opers +s\r"
}
send "who n?c?\r"
expect {
timeout { exit 1 }
":ngircd.test.server 352 nick \* ~user localhost ngircd.test.server nick H* :0 Real Name"
}
send "quit\r"
expect {
timeout { exit 1 }
"Connection closed"
}
# -eof-

View File

@@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: tool.c,v 1.9 2008/02/26 22:04:18 fw Exp $";
static char UNUSED id[] = "$Id: tool.c,v 1.6 2006/04/09 12:53:07 alex Exp $";
#include "imp.h"
#include <assert.h>
@@ -22,8 +22,6 @@ static char UNUSED id[] = "$Id: tool.c,v 1.9 2008/02/26 22:04:18 fw Exp $";
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include "exp.h"
#include "tool.h"
@@ -106,4 +104,5 @@ ngt_TrimLastChr( char *String, const char Chr)
if( String[len] == Chr ) String[len] = '\0';
} /* ngt_TrimLastChr */
/* -eof- */

View File

@@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: tool.h,v 1.6 2008/02/26 22:04:18 fw Exp $
* $Id: tool.h,v 1.3 2005/03/19 18:43:53 fw Exp $
*
* Tool functions (Header)
*/
@@ -16,19 +16,15 @@
#ifndef __tool_h__
#define __tool_h__
#include "portab.h"
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#else
# define PF_INET AF_INET
#endif
GLOBAL void ngt_TrimLastChr PARAMS((char *String, const char Chr ));
GLOBAL void ngt_TrimStr PARAMS((char *String ));
GLOBAL char *ngt_LowerStr PARAMS((char *String ));
#endif