1
0
mirror of https://github.com/osmarks/ngircd.git synced 2025-09-26 22:14:04 +00:00

Compare commits

..

16 Commits

Author SHA1 Message Date
Florian Westphal
3b69da0c52 io.c: fix select FD_SETSIZE check when using epoll as io backend 2008-04-07 13:37:49 +02:00
Alexander Barton
04933f5b8b Fixed indentation ... too late for 0.11.1 :-/ 2008-04-07 13:37:46 +02:00
Alexander Barton
45df522bcb ngIRCd 0.11.1. 2008-02-26 19:37:34 +00:00
Alexander Barton
51260c2e9f Updated NEWS and ChangeLog for 0.11.1. 2008-02-26 19:22:06 +00:00
Florian Westphal
55865d7fc6 From: Rolf Eike Beer <eike@sf-mail.de>
Fix sending of JOINs between servers

I found a bug in "sending join between servers".
This does hit only operators that join a channel with at least 2 servers active in the net
the server the oper connects to sends "channel^Go" to the other servers
the other server first searches for the channel and then strips the modes from the channel name
he has to do the other way round: first strip and then check the channel name.
2008-02-26 12:07:41 +00:00
Florian Westphal
082a92beef send "G" flag in WHOIS replies instead of "H" if client is marked as being away.
(reported by Dana Dahlstrom)
2008-02-26 12:06:57 +00:00
Florian Westphal
e92c889580 From: Dana Dahlstrom <dana+70@cs.ucsd.edu>
Under some circumstances ngIRCd currently issues a channel MODE message
with a trailing space after the last parameter, which isn't permitted by
the grammar in RFC 2812 section 2.3.1:

http://tools.ietf.org/html/rfc2812#section-2.3.1

The following patch modifies mode-test.e to expose this, and modifies
irc-mode.c to correct it. [from HEAD]
2008-02-16 11:26:11 +00:00
Florian Westphal
de4676f066 [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:11:20 +00:00
Florian Westphal
64a98338d5 [LOGIN] irc_login, w CVSDATE defined, used strncpy with overlapping src/dest.
use memmove instead (from HEAD).
2008-02-05 11:48:37 +00:00
Alexander Barton
f4709082fe ngIRCd 0.11.0 2008-01-15 20:45:52 +00:00
Alexander Barton
997abc6889 Documented NoDNS configuration option. [from HEAD] 2008-01-07 23:10:28 +00:00
Alexander Barton
b7047f2e3b Updated ChangeLog to reflect changes from 0.10.x branch. 2008-01-07 23:09:25 +00:00
Alexander Barton
e990d96c61 ngIRCd 0.11.0-pre2 2008-01-07 21:25:35 +00:00
Florian Westphal
d986cd372f IRC_PART could reference invalid memory. 2008-01-07 11:42:13 +00:00
Florian Westphal
762aec0e08 Remove entry about ngircd failing on Linux 2.4: ngircd can now fall back to select. 2008-01-02 22:36:48 +00:00
Alexander Barton
f8cb8e3f20 Fixed year of release (2009 vs. 2008) ... ooops ;-) 2008-01-02 21:39:59 +00:00
74 changed files with 2070 additions and 3274 deletions

7
.cvsignore Normal file
View File

@@ -0,0 +1,7 @@
Makefile
Makefile.in
aclocal.m4
autom4te.cache
config.log
config.status
configure

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

View File

@@ -10,53 +10,6 @@
-- 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
@@ -786,3 +739,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.332.2.11 2008/02/26 20:35:05 alex Exp $

10
INSTALL
View File

@@ -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.26 2007/04/08 11:39:08 alex 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

29
NEWS
View File

@@ -10,33 +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.
@@ -278,4 +251,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.83.2.4 2008/02/26 19:22:07 alex Exp $

10
README
View File

@@ -67,9 +67,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
@@ -85,3 +85,7 @@ 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).
--
$Id: README,v 1.25 2007/10/04 15:18:48 alex Exp $

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.125.2.4 2008/02/26 19:37:34 alex Exp $
#
# -- Initialisation --
AC_PREREQ(2.50)
AC_INIT(ngircd, 0.12.1)
AC_INIT(ngircd, 0.11.1)
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-

2
contrib/.cvsignore Normal file
View File

@@ -0,0 +1,2 @@
Makefile
Makefile.in

View File

@@ -0,0 +1,2 @@
Makefile
Makefile.in

View File

@@ -1,26 +1,14 @@
ngircd (0.12.1-0ab1) unstable; urgency=low
ngircd (0.11.1-0ab1) unstable; urgency=low
* New "upstream" release ngIRCd 0.12.1.
* New "upstream" release 0.11.1.
-- Alexander Barton <alex@barton.de> Wed, 9 Jul 2008 11:27:00 +0200
-- Alexander Barton <alex@barton.de> Tue, 26 Feb 2008 20:24:55 +0100
ngircd (0.12.0-0ab1) unstable; urgency=low
ngircd (0.11.0-0ab1) unstable; urgency=low
* New "upstream" release ngIRCd 0.12.0.
* New "upstream" release 0.11.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
-- Alexander Barton <alex@barton.de> Tue, 15 Jan 2008 21:43:46 +0100
ngircd (0.11.0-0ab0-pre2) unstable; urgency=low

View File

@@ -0,0 +1,2 @@
Makefile
Makefile.in

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

@@ -89,4 +89,4 @@
#define HAVE_DNSSERVICEREGISTRATIONCREATE 1
#endif
/* -eof- */
/* -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-

View File

@@ -34,7 +34,6 @@
FA322D4D0CEF74B1001761B3 /* resolve.c in Sources */ = {isa = PBXBuildFile; fileRef = FA322D0C0CEF74B1001761B3 /* resolve.c */; };
FA322DBE0CEF7766001761B3 /* tool.c in Sources */ = {isa = PBXBuildFile; fileRef = FA322D330CEF74B1001761B3 /* tool.c */; };
FA322DC10CEF77CB001761B3 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FA322DC00CEF77CB001761B3 /* libz.dylib */; };
FA407F2E0DB159F400271AF1 /* ng_ipaddr.c in Sources */ = {isa = PBXBuildFile; fileRef = FA407F2C0DB159F400271AF1 /* ng_ipaddr.c */; };
FAE5CC2E0CF2308A007D69B6 /* numeric.c in Sources */ = {isa = PBXBuildFile; fileRef = FAE5CC2D0CF2308A007D69B6 /* numeric.c */; };
/* End PBXBuildFile section */
@@ -51,10 +50,10 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
FA1A6BBC0D6857BB00AA8F71 /* misc-test.e */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = "misc-test.e"; sourceTree = "<group>"; };
FA1A6BBD0D6857D900AA8F71 /* who-test.e */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = "who-test.e"; sourceTree = "<group>"; };
FA322BBA0CEF72E4001761B3 /* ngIRCd */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = ngIRCd; sourceTree = BUILT_PRODUCTS_DIR; };
FA322CD50CEF74B1001761B3 /* .cvsignore */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = .cvsignore; sourceTree = "<group>"; };
FA322CD60CEF74B1001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
FA322CD80CEF74B1001761B3 /* .cvsignore */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = .cvsignore; sourceTree = "<group>"; };
FA322CD90CEF74B1001761B3 /* array.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = array.c; sourceTree = "<group>"; };
FA322CDA0CEF74B1001761B3 /* array.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = array.h; sourceTree = "<group>"; };
FA322CDB0CEF74B1001761B3 /* channel.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = channel.c; sourceTree = "<group>"; };
@@ -108,6 +107,7 @@
FA322D0B0CEF74B1001761B3 /* rendezvous.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = rendezvous.h; sourceTree = "<group>"; };
FA322D0C0CEF74B1001761B3 /* resolve.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = resolve.c; sourceTree = "<group>"; };
FA322D0D0CEF74B1001761B3 /* resolve.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = resolve.h; sourceTree = "<group>"; };
FA322D0F0CEF74B1001761B3 /* .cvsignore */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = .cvsignore; sourceTree = "<group>"; };
FA322D100CEF74B1001761B3 /* ansi2knr.1 */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.man; path = ansi2knr.1; sourceTree = "<group>"; };
FA322D110CEF74B1001761B3 /* ansi2knr.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = ansi2knr.c; sourceTree = "<group>"; };
FA322D120CEF74B1001761B3 /* exp.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = exp.h; sourceTree = "<group>"; };
@@ -119,6 +119,7 @@
FA322D180CEF74B1001761B3 /* strdup.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = strdup.c; sourceTree = "<group>"; };
FA322D190CEF74B1001761B3 /* strlcpy.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = strlcpy.c; sourceTree = "<group>"; };
FA322D1A0CEF74B1001761B3 /* vsnprintf.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = vsnprintf.c; sourceTree = "<group>"; };
FA322D1C0CEF74B1001761B3 /* .cvsignore */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = .cvsignore; sourceTree = "<group>"; };
FA322D1D0CEF74B1001761B3 /* channel-test.e */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = "channel-test.e"; sourceTree = "<group>"; };
FA322D1E0CEF74B1001761B3 /* check-idle.e */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = "check-idle.e"; sourceTree = "<group>"; };
FA322D1F0CEF74B1001761B3 /* connect-test.e */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = "connect-test.e"; sourceTree = "<group>"; };
@@ -136,6 +137,7 @@
FA322D2B0CEF74B1001761B3 /* test-loop.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = "test-loop.sh"; sourceTree = "<group>"; };
FA322D2C0CEF74B1001761B3 /* tests.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = tests.sh; sourceTree = "<group>"; };
FA322D2D0CEF74B1001761B3 /* wait-tests.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = "wait-tests.sh"; sourceTree = "<group>"; };
FA322D2F0CEF74B1001761B3 /* .cvsignore */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = .cvsignore; sourceTree = "<group>"; };
FA322D300CEF74B1001761B3 /* ansi2knr.1 */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.man; path = ansi2knr.1; sourceTree = "<group>"; };
FA322D310CEF74B1001761B3 /* ansi2knr.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = ansi2knr.c; sourceTree = "<group>"; };
FA322D320CEF74B1001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
@@ -152,6 +154,8 @@
FA322D630CEF750F001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = Makefile.am; path = ../../Makefile.am; sourceTree = SOURCE_ROOT; };
FA322D640CEF750F001761B3 /* NEWS */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = NEWS; path = ../../NEWS; sourceTree = SOURCE_ROOT; };
FA322D650CEF750F001761B3 /* README */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = README; path = ../../README; sourceTree = SOURCE_ROOT; };
FA322D670CEF7523001761B3 /* .cvsignore */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = .cvsignore; sourceTree = "<group>"; };
FA322D690CEF7523001761B3 /* .cvsignore */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = .cvsignore; sourceTree = "<group>"; };
FA322D6A0CEF7523001761B3 /* changelog */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = changelog; sourceTree = "<group>"; };
FA322D6B0CEF7523001761B3 /* compat */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = compat; sourceTree = "<group>"; };
FA322D6C0CEF7523001761B3 /* control */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = control; sourceTree = "<group>"; };
@@ -161,6 +165,7 @@
FA322D700CEF7523001761B3 /* ngircd.init */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = ngircd.init; sourceTree = "<group>"; };
FA322D710CEF7523001761B3 /* ngircd.postinst */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = ngircd.postinst; sourceTree = "<group>"; };
FA322D720CEF7523001761B3 /* rules */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = rules; sourceTree = "<group>"; };
FA322D740CEF7523001761B3 /* .cvsignore */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = .cvsignore; sourceTree = "<group>"; };
FA322D8D0CEF7523001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
FA322D8E0CEF7523001761B3 /* ngIRCd.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = ngIRCd.xcodeproj; sourceTree = "<group>"; };
FA322D910CEF7523001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
@@ -169,6 +174,8 @@
FA322D940CEF7523001761B3 /* ngircd.spec */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = ngircd.spec; sourceTree = "<group>"; };
FA322D950CEF7523001761B3 /* README */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
FA322D960CEF7523001761B3 /* systrace.policy */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = systrace.policy; sourceTree = "<group>"; };
FA322D980CEF752C001761B3 /* .cvsignore */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = .cvsignore; sourceTree = "<group>"; };
FA322D990CEF752C001761B3 /* CVS.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = CVS.txt; sourceTree = "<group>"; };
FA322D9A0CEF752C001761B3 /* FAQ.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = FAQ.txt; sourceTree = "<group>"; };
FA322D9B0CEF752C001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
FA322D9C0CEF752C001761B3 /* Platforms.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Platforms.txt; sourceTree = "<group>"; };
@@ -177,6 +184,7 @@
FA322D9F0CEF752C001761B3 /* README-BeOS.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = "README-BeOS.txt"; sourceTree = "<group>"; };
FA322DA00CEF752C001761B3 /* RFC.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = RFC.txt; sourceTree = "<group>"; };
FA322DA10CEF752C001761B3 /* sample-ngircd.conf */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = "sample-ngircd.conf"; sourceTree = "<group>"; };
FA322DA30CEF752C001761B3 /* .cvsignore */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = .cvsignore; sourceTree = "<group>"; };
FA322DA40CEF752C001761B3 /* Doxyfile */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Doxyfile; sourceTree = "<group>"; };
FA322DA50CEF752C001761B3 /* footer.inc.html */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.html; path = footer.inc.html; sourceTree = "<group>"; };
FA322DA60CEF752C001761B3 /* header.inc.html */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.html; path = header.inc.html; sourceTree = "<group>"; };
@@ -184,16 +192,13 @@
FA322DA80CEF752C001761B3 /* ngircd-doc.css */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.css; path = "ngircd-doc.css"; sourceTree = "<group>"; };
FA322DA90CEF752C001761B3 /* SSL.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = SSL.txt; sourceTree = "<group>"; };
FA322DAA0CEF752C001761B3 /* Zeroconf.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Zeroconf.txt; sourceTree = "<group>"; };
FA322DAC0CEF7538001761B3 /* .cvsignore */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = .cvsignore; sourceTree = "<group>"; };
FA322DAD0CEF7538001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
FA322DAE0CEF7538001761B3 /* ngircd.8.tmpl */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = ngircd.8.tmpl; sourceTree = "<group>"; };
FA322DAF0CEF7538001761B3 /* ngircd.conf.5.tmpl */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = ngircd.conf.5.tmpl; sourceTree = "<group>"; };
FA322DB10CEF7565001761B3 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = "<group>"; };
FA322DBB0CEF773C001761B3 /* cvs-version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "cvs-version.h"; sourceTree = "<group>"; };
FA322DC00CEF77CB001761B3 /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = /usr/lib/libz.dylib; sourceTree = "<absolute>"; };
FA407F2B0DB159F400271AF1 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; name = Makefile.am; path = ipaddr/Makefile.am; sourceTree = "<group>"; };
FA407F2C0DB159F400271AF1 /* ng_ipaddr.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = ng_ipaddr.c; path = ipaddr/ng_ipaddr.c; sourceTree = "<group>"; };
FA407F2D0DB159F400271AF1 /* ng_ipaddr.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = ng_ipaddr.h; path = ipaddr/ng_ipaddr.h; sourceTree = "<group>"; };
FA407F380DB15AC700271AF1 /* GIT.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = GIT.txt; sourceTree = "<group>"; };
FAE5CC2C0CF2308A007D69B6 /* numeric.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = numeric.h; sourceTree = "<group>"; };
FAE5CC2D0CF2308A007D69B6 /* numeric.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = numeric.c; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -246,10 +251,10 @@
isa = PBXGroup;
children = (
FA322CD70CEF74B1001761B3 /* ngircd */,
FA407F270DB1598D00271AF1 /* ipaddr */,
FA322D0E0CEF74B1001761B3 /* portab */,
FA322D1B0CEF74B1001761B3 /* testsuite */,
FA322D2E0CEF74B1001761B3 /* tool */,
FA322CD50CEF74B1001761B3 /* .cvsignore */,
FA322CD60CEF74B1001761B3 /* Makefile.am */,
);
name = src;
@@ -259,6 +264,7 @@
FA322CD70CEF74B1001761B3 /* ngircd */ = {
isa = PBXGroup;
children = (
FA322CD80CEF74B1001761B3 /* .cvsignore */,
FA322CD90CEF74B1001761B3 /* array.c */,
FA322CDA0CEF74B1001761B3 /* array.h */,
FA322CDB0CEF74B1001761B3 /* channel.c */,
@@ -321,6 +327,7 @@
FA322D0E0CEF74B1001761B3 /* portab */ = {
isa = PBXGroup;
children = (
FA322D0F0CEF74B1001761B3 /* .cvsignore */,
FA322D100CEF74B1001761B3 /* ansi2knr.1 */,
FA322D110CEF74B1001761B3 /* ansi2knr.c */,
FA322D120CEF74B1001761B3 /* exp.h */,
@@ -339,13 +346,13 @@
FA322D1B0CEF74B1001761B3 /* testsuite */ = {
isa = PBXGroup;
children = (
FA322D1C0CEF74B1001761B3 /* .cvsignore */,
FA322D1D0CEF74B1001761B3 /* channel-test.e */,
FA322D1E0CEF74B1001761B3 /* check-idle.e */,
FA322D1F0CEF74B1001761B3 /* connect-test.e */,
FA322D200CEF74B1001761B3 /* functions.inc */,
FA322D210CEF74B1001761B3 /* getpid.sh */,
FA322D220CEF74B1001761B3 /* Makefile.am */,
FA1A6BBC0D6857BB00AA8F71 /* misc-test.e */,
FA322D230CEF74B1001761B3 /* mode-test.e */,
FA322D240CEF74B1001761B3 /* ngircd-test.conf */,
FA322D250CEF74B1001761B3 /* README */,
@@ -357,7 +364,6 @@
FA322D2B0CEF74B1001761B3 /* test-loop.sh */,
FA322D2C0CEF74B1001761B3 /* tests.sh */,
FA322D2D0CEF74B1001761B3 /* wait-tests.sh */,
FA1A6BBD0D6857D900AA8F71 /* who-test.e */,
);
path = testsuite;
sourceTree = "<group>";
@@ -365,6 +371,7 @@
FA322D2E0CEF74B1001761B3 /* tool */ = {
isa = PBXGroup;
children = (
FA322D2F0CEF74B1001761B3 /* .cvsignore */,
FA322D300CEF74B1001761B3 /* ansi2knr.1 */,
FA322D310CEF74B1001761B3 /* ansi2knr.c */,
FA322D320CEF74B1001761B3 /* Makefile.am */,
@@ -377,6 +384,7 @@
FA322D660CEF7523001761B3 /* contrib */ = {
isa = PBXGroup;
children = (
FA322D670CEF7523001761B3 /* .cvsignore */,
FA322D680CEF7523001761B3 /* Debian */,
FA322D730CEF7523001761B3 /* MacOSX */,
FA322D910CEF7523001761B3 /* Makefile.am */,
@@ -393,6 +401,7 @@
FA322D680CEF7523001761B3 /* Debian */ = {
isa = PBXGroup;
children = (
FA322D690CEF7523001761B3 /* .cvsignore */,
FA322D6A0CEF7523001761B3 /* changelog */,
FA322D6B0CEF7523001761B3 /* compat */,
FA322D6C0CEF7523001761B3 /* control */,
@@ -409,6 +418,7 @@
FA322D730CEF7523001761B3 /* MacOSX */ = {
isa = PBXGroup;
children = (
FA322D740CEF7523001761B3 /* .cvsignore */,
FA322D750CEF7523001761B3 /* build */,
FA322D8D0CEF7523001761B3 /* Makefile.am */,
FA322D8E0CEF7523001761B3 /* ngIRCd.xcodeproj */,
@@ -499,7 +509,8 @@
FA322D970CEF752C001761B3 /* doc */ = {
isa = PBXGroup;
children = (
FA407F380DB15AC700271AF1 /* GIT.txt */,
FA322D980CEF752C001761B3 /* .cvsignore */,
FA322D990CEF752C001761B3 /* CVS.txt */,
FA322D9A0CEF752C001761B3 /* FAQ.txt */,
FA322D9B0CEF752C001761B3 /* Makefile.am */,
FA322D9C0CEF752C001761B3 /* Platforms.txt */,
@@ -519,6 +530,7 @@
FA322DA20CEF752C001761B3 /* src */ = {
isa = PBXGroup;
children = (
FA322DA30CEF752C001761B3 /* .cvsignore */,
FA322DA40CEF752C001761B3 /* Doxyfile */,
FA322DA50CEF752C001761B3 /* footer.inc.html */,
FA322DA60CEF752C001761B3 /* header.inc.html */,
@@ -531,6 +543,7 @@
FA322DAB0CEF7538001761B3 /* man */ = {
isa = PBXGroup;
children = (
FA322DAC0CEF7538001761B3 /* .cvsignore */,
FA322DAD0CEF7538001761B3 /* Makefile.am */,
FA322DAE0CEF7538001761B3 /* ngircd.8.tmpl */,
FA322DAF0CEF7538001761B3 /* ngircd.conf.5.tmpl */,
@@ -539,16 +552,6 @@
path = ../../man;
sourceTree = SOURCE_ROOT;
};
FA407F270DB1598D00271AF1 /* ipaddr */ = {
isa = PBXGroup;
children = (
FA407F2B0DB159F400271AF1 /* Makefile.am */,
FA407F2C0DB159F400271AF1 /* ng_ipaddr.c */,
FA407F2D0DB159F400271AF1 /* ng_ipaddr.h */,
);
name = ipaddr;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -625,7 +628,6 @@
FA322D4D0CEF74B1001761B3 /* resolve.c in Sources */,
FA322DBE0CEF7766001761B3 /* tool.c in Sources */,
FAE5CC2E0CF2308A007D69B6 /* numeric.c in Sources */,
FA407F2E0DB159F400271AF1 /* ng_ipaddr.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -635,24 +637,8 @@
1DEB928708733DD80010E9CD /* Default */ = {
isa = XCBuildConfiguration;
buildSettings = {
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
GCC_WARN_CHECK_SWITCH_STATEMENTS = YES;
GCC_WARN_FOUR_CHARACTER_CONSTANTS = YES;
GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
GCC_WARN_MISSING_PARENTHESES = YES;
GCC_WARN_PEDANTIC = YES;
GCC_WARN_SHADOW = YES;
GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNKNOWN_PRAGMAS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VALUE = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_MODEL_TUNING = G5;
INSTALL_PATH = /usr/local/bin;
PRODUCT_NAME = ngIRCd;
};

View File

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

2
doc/.cvsignore Normal file
View File

@@ -0,0 +1,2 @@
Makefile
Makefile.in

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.9 2006/08/03 14:37:29 alex Exp $

View File

@@ -76,4 +76,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.4.1 2008/01/02 22:36:48 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-2007 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,10 +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.22 2007/11/20 21:39:35 alex Exp $
#
SUBDIRS = src
EXTRA_DIST = FAQ.txt GIT.txt Protocol.txt Platforms.txt README-AUX.txt \
EXTRA_DIST = CVS.txt FAQ.txt Protocol.txt Platforms.txt README-AUX.txt \
README-BeOS.txt RFC.txt SSL.txt Zeroconf.txt sample-ngircd.conf
maintainer-clean-local:

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.43.2.1 2008/01/07 23:10:28 alex Exp $
#
# This is a sample configuration file for the ngIRCd, which must be adepted
@@ -40,11 +40,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:
@@ -105,10 +103,6 @@
# 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

3
doc/src/.cvsignore Normal file
View File

@@ -0,0 +1,3 @@
Makefile
Makefile.in
html

1
doc/src/.gitignore vendored
View File

@@ -1 +0,0 @@
html

View File

@@ -1,2 +1,4 @@
Makefile
Makefile.in
ngircd.8
ngircd.conf.5

View File

@@ -1,7 +1,7 @@
.\"
.\" $Id: ngircd.8.tmpl,v 1.2 2007/11/15 01:03:29 fw 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
@@ -50,10 +50,10 @@ 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

View File

@@ -1,7 +1,7 @@
.\"
.\" $Id: ngircd.conf.5.tmpl,v 1.7 2007/11/23 16:26:03 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
@@ -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
@@ -162,15 +158,6 @@ 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.
@@ -207,34 +194,31 @@ 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.
Internet host name 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.
.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,7 +230,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.
@@ -264,19 +247,19 @@ 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).
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).
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

View File

@@ -1,3 +1,5 @@
Makefile
Makefile.in
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,3 +1,6 @@
Makefile
Makefile.in
.deps
check-help
check-version
cvs-version.h

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.50 2007/11/21 12:16:36 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
@@ -25,9 +25,9 @@ ngircd_SOURCES = ngircd.c array.c channel.c client.c conf.c conn.c conn-func.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
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 \
@@ -36,7 +36,7 @@ noinst_HEADERS = ngircd.h array.h channel.h client.h conf.h conn.h conn-func.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

@@ -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.63 2007/06/11 20:06:46 fw 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.33 2006/12/07 22:23:39 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.97 2007/11/21 12:16:36 alex 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 )
{

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.103 2007/11/23 16:26:04 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,20 +202,10 @@ 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( " 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( " NoDNS = %s\n", Conf_NoDNS ? "yes" : "no");
printf( " MaxConnections = %ld\n", Conf_MaxConnections);
printf( " MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP);
printf( " MaxJoins = %d\n", Conf_MaxJoins>0 ? Conf_MaxJoins : -1);
@@ -282,7 +250,7 @@ Conf_Test( void )
printf( " Topic = %s\n\n", topic ? topic : "");
}
return (config_valid ? 0 : 1);
return 0;
} /* Conf_Test */
@@ -465,8 +433,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;
@@ -482,12 +450,6 @@ Set_Defaults( bool InitServers )
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_MaxConnectionsIP = 5;
Conf_MaxJoins = 10;
@@ -498,8 +460,8 @@ Set_Defaults( bool InitServers )
} /* Set_Defaults */
static bool
Read_Config( bool ngircd_starting )
static void
Read_Config( void )
{
/* Read configuration file. */
@@ -514,14 +476,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 +626,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 */
@@ -873,41 +813,6 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
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 );
@@ -954,24 +859,14 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
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);
}
len = strlcpy( Conf_ListenAddress, Arg, sizeof( Conf_ListenAddress ));
if (len >= sizeof( Conf_ListenAddress ))
Config_Error_TooLong( Line, Var );
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 */
@@ -1043,7 +938,7 @@ Handle_SERVER( int Line, char *Var, char *Arg )
return;
}
if (strcasecmp(Var, "Bind") == 0) {
if (ng_ipaddr_init(&New_Server.bind_addr, Arg, 0))
if (ngt_IPStrToBin(Arg, &New_Server.bind_addr))
return;
Config_Error(LOG_ERR, "%s, line %d (section \"Server\"): Can't parse IP address \"%s\"",
@@ -1167,7 +1062,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 +1070,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 +1088,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 +1101,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 +1115,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 +1147,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 +1213,7 @@ Init_Server_Struct( CONF_SERVER *Server )
Resolve_Init(&Server->res_stat);
Server->conn_id = NONE;
memset(&Server->bind_addr, 0, sizeof(&Server->bind_addr));
Server->bind_addr.s_addr = htonl(INADDR_ANY);
} /* 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.47 2007/11/23 16:28:37 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
{
@@ -44,8 +42,7 @@ 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 */
struct in_addr bind_addr; /* source address to use for outgoing connections */
} 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;
@@ -124,15 +121,6 @@ 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 */
@@ -151,7 +139,7 @@ GLOBAL int Conf_MaxConnectionsIP;
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 ));

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.11 2007/10/04 15:03:56 alex Exp $";
#include "imp.h"
#include <assert.h>
#include <string.h>
#include "log.h"
#include <log.h>
#include "conn.h"
#include "client.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.220 2007/12/13 01:30:16 fw Exp $";
#include "imp.h"
#include <assert.h>
@@ -86,13 +86,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, struct in_addr *dest));
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 +109,7 @@ static void
cb_listen(int sock, short irrelevant)
{
(void) irrelevant;
if (New_Connection( sock ) >= 0)
NumConnections++;
New_Connection( sock );
}
@@ -145,28 +144,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 +197,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 );
@@ -272,7 +255,7 @@ Conn_Exit( void )
static unsigned int
ports_initlisteners(array *a, const char *listen_addr, void (*func)(int,short))
ports_initlisteners(array *a, void (*func)(int,short))
{
unsigned int created = 0;
size_t len;
@@ -281,15 +264,15 @@ ports_initlisteners(array *a, const char *listen_addr, void (*func)(int,short))
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,6 +280,7 @@ ports_initlisteners(array *a, const char *listen_addr, void (*func)(int,short))
created++;
port++;
}
return created;
}
@@ -305,39 +289,16 @@ GLOBAL unsigned int
Conn_InitListeners( void )
{
/* Initialize ports on which the server should accept connections */
unsigned int created = 0;
char *copy, *listen_addr;
unsigned 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 +327,70 @@ Conn_ExitListeners( void )
} /* Conn_ExitListeners */
static bool
InitSinaddrListenAddr(ng_ipaddr_t *addr, const char *listen_addrstr, UINT16 Port)
static void
InitSinaddr(struct sockaddr_in *addr, UINT16 Port)
{
bool ret;
struct in_addr inaddr;
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;
memset(addr, 0, sizeof(*addr));
memset( &inaddr, 0, sizeof(inaddr));
addr->sin_family = AF_INET;
addr->sin_port = htons(Port);
inaddr.s_addr = htonl(INADDR_ANY);
addr->sin_addr = inaddr;
}
static void
set_v6_only(int af, int sock)
static bool
InitSinaddrListenAddr(struct sockaddr_in *addr, UINT16 Port)
{
#if defined(IPV6_V6ONLY) && defined(WANT_IPV6)
int on = 1;
struct in_addr inaddr;
if (af != AF_INET6)
return;
InitSinaddr(addr, Port);
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
if (!Conf_ListenAddress[0])
return true;
if (!ngt_IPStrToBin(Conf_ListenAddress, &inaddr)) {
Log( LOG_CRIT, "Can't bind to %s:%u: can't convert ip address \"%s\"",
Conf_ListenAddress, Port, Conf_ListenAddress);
return false;
}
addr->sin_addr = inaddr;
return true;
}
/* 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;
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);
InitSinaddrListenAddr(&addr, Port);
addr.sin_family = AF_INET;
addr.sin_port = htons( Port );
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 +407,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 +709,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 +736,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 +778,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 +807,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 +816,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 +844,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 +940,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 +949,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 +964,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 +981,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 +1017,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 +1029,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,12 +1043,13 @@ 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,
@@ -1164,10 +1107,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 +1172,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 +1200,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
@@ -1437,44 +1367,37 @@ Check_Servers( void )
static void
New_Server( int Server , ng_ipaddr_t *dest)
New_Server( int Server , struct in_addr *dest)
{
/* Establish new server link */
char ip_str[NG_INET_ADDRSTRLEN];
int af_dest, res, new_sock;
struct sockaddr_in local_addr;
struct sockaddr_in new_addr;
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");
memset(&new_addr, 0, sizeof( new_addr ));
new_addr.sin_family = AF_INET;
new_addr.sin_addr = *dest;
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;
}
Log( LOG_INFO, "Establishing connection to \"%s\", %s, port %d ... ",
Conf_Server[Server].host, ip_str, Conf_Server[Server].port );
if( ! Init_Socket( new_sock )) return;
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 we fail to bind, just continue and let connect() pick a source address */
InitSinaddr(&local_addr, 0);
local_addr.sin_addr = Conf_Server[Server].bind_addr;
if (bind(new_sock, (struct sockaddr *)&local_addr, (socklen_t)sizeof(local_addr)))
Log(LOG_WARNING, "Can't bind socket to %s: %s!", inet_ntoa(Conf_Server[Server].bind_addr), strerror( errno ));
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)))
{
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));
}
ng_ipaddr_setport(dest, Conf_Server[Server].port);
res = connect(new_sock, (struct sockaddr *) dest, ng_ipaddr_salen(dest));
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 );
@@ -1495,9 +1418,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 +1431,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 ));
@@ -1588,9 +1510,8 @@ 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 */
struct in_addr dest_addr;
char readbuf[HOST_LEN + 1];
LogDebug("Resolver: Got forward lookup callback on fd %d, events %d", fd, events);
@@ -1607,28 +1528,23 @@ 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;
assert((len % sizeof(ng_ipaddr_t)) == 0);
readbuf[len] = '\0';
LogDebug("Got result from resolver: \"%s\" (%u bytes read).", readbuf, len);
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);
if (!ngt_IPStrToBin(readbuf, &dest_addr)) {
Log(LOG_ERR, "Can't connect to \"%s\": can't convert ip address %s!",
Conf_Server[i].host, readbuf);
return;
}
Log( LOG_INFO, "Establishing connection to \"%s\", %s, port %d ... ",
Conf_Server[i].host, readbuf, Conf_Server[i].port );
/* connect() */
New_Server(i, dest_addrs);
New_Server(i, &dest_addr);
} /* cb_Read_Forward_Lookup */
@@ -1727,6 +1643,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.45 2007/10/04 15:03:56 alex 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,7 +54,7 @@ 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 */

File diff suppressed because it is too large Load Diff

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.40.2.2 2008/02/26 12:07:41 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,186 @@ 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) {
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;
/* 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;
}
/* 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,36 +256,29 @@ 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 );
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 */
/* Channel-Namen durchgehen */
chan = strtok(Req->argv[0], ",");
while (chan) {
Channel_Part(target, Client, chan,
Req->argc > 1 ? Req->argv[1] : Client_ID(target));
Channel_Part(target, Client, chan, Req->argc > 1 ? Req->argv[1] : Client_ID(target));
chan = strtok(NULL, ",");
}
return CONNECTED;

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.41.2.1 2008/02/26 12:06:57 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 )
{
@@ -531,19 +468,6 @@ IRC_STATS( CLIENT *Client, REQUEST *Req )
} /* 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 +545,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 +578,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 +605,82 @@ 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 */
if (strchr(Client_Modes( c ), 'a'))
strcpy(flags, "G"); /* away */
else
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 */
@@ -1249,6 +1060,55 @@ IRC_Send_NAMES( CLIENT *Client, CHANNEL *Chan )
} /* IRC_Send_NAMES */
GLOBAL bool
IRC_Send_WHO( CLIENT *Client, CHANNEL *Chan, bool OnlyOps )
{
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 ) {
if (strchr(Client_Modes( c ), 'a'))
strcpy(flags, "G"); /* away */
else
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 */
/**
* Send the ISUPPORT numeric (005).

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.4 2007/11/21 12:16:36 alex 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,6 +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_WHO PARAMS(( CLIENT *Client, CHANNEL *Chan, bool OnlyOps ));
GLOBAL bool IRC_Send_ISUPPORT PARAMS(( CLIENT *Client ));

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.54.2.1 2008/02/05 11:48:37 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,61 @@ 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 ));
memmove( ver + 4, ver + 5, 2 );
memmove( 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_Send_ISUPPORT(Client))
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.50.2.1 2008/02/16 11:26:12 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
@@ -237,140 +242,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 ? "+" : "-");
if( set ) strcpy( the_modes, "+" );
else strcpy( the_modes, "-" );
the_args[0] = '\0';
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 +368,241 @@ 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) {
/* 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 */
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, " ", 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 ));
}
}
} 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, " ", 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 ));
}
}
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] )
{
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';
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 +635,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.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.21 2007/01/29 21:13:26 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.13 2006/12/07 17:57:20 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

@@ -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.74 2007/12/11 11:29:44 fw Exp $
*
* IRC numerics (Header)
*/
@@ -77,8 +77,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 +100,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.117 2007/11/21 12:16:36 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 */
/**
@@ -431,16 +427,15 @@ NGIRCd_Rehash( void )
Log( LOG_NOTICE|LOG_snotice, "Re-reading configuration NOW!" );
NGIRCd_SignalRehash = false;
/* Close down all listening sockets */
Conn_ExitListeners( );
/* 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( );
Conf_Rehash( );
/* Recover old server name and nick name length: these values can't
* be changed during run-time */
@@ -557,7 +552,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 +577,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 */

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.69.2.1 2008/02/05 13:11:20 fw Exp $";
/**
* @file
* IRC command parser and validator.
@@ -49,13 +52,8 @@
#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 +62,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,13 +88,11 @@ 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 },
@@ -109,6 +104,14 @@ static COMMAND My_Commands[] =
{ NULL, NULL, 0x0, 0, 0, 0 } /* Ende-Marke */
};
NUMERIC My_Numerics[] =
{
{ 005, IRC_Num_ISUPPORT },
{ 376, IRC_Num_ENDOFMOTD },
{ 0, NULL } /* end marker */
};
static void Init_Request PARAMS(( REQUEST *Req ));
static bool Validate_Prefix PARAMS(( CONN_ID Idx, REQUEST *Req, bool *Closed ));
@@ -117,7 +120,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 +337,28 @@ 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;
NUMERIC *num;
int i, client_type;
assert( Idx >= 0 );
assert( Req != NULL );
@@ -455,43 +368,110 @@ Handle_Request( CONN_ID Idx, REQUEST *Req )
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);
if ((Client_Type(client) == CLIENT_SERVER ||
Client_Type(client) == CLIENT_UNKNOWNSERVER)
&& strlen(Req->command) == 3 && atoi(Req->command) > 1) {
/* Command is a status code ("numeric") 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 of the numeric */
i = atoi(Req->command);
num = My_Numerics;
while (num->numeric > 0) {
if (i != num->numeric) {
num++;
continue;
}
result = (num->function)(client, Req);
return result;
}
LogDebug("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 +480,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.12 2007/11/21 12:16:36 alex Exp $
*
* IRC command parser and validator (header)
*/
@@ -38,10 +38,18 @@ typedef struct _COMMAND
} COMMAND;
typedef struct _NUMERIC
{
int numeric; /* numeric */
bool (*function) PARAMS(( CLIENT *Client, REQUEST *Request ));
} NUMERIC;
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.28 2008/01/02 11:03:29 fw Exp $";
#include "imp.h"
#include <assert.h>
@@ -35,19 +35,19 @@ static char UNUSED id[] = "$Id: resolve.c,v 1.29 2008/02/26 22:04:17 fw Exp $";
#include "conn.h"
#include "defines.h"
#include "log.h"
#include "tool.h"
#include "exp.h"
#include "resolve.h"
#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 ipstr[CLIENT_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 || strlen(h->h_name) >= sizeof(hostname)) {
#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));

4
src/portab/.cvsignore Normal file
View File

@@ -0,0 +1,4 @@
Makefile
Makefile.in
.deps
portabtest

View File

@@ -1 +0,0 @@
portabtest

7
src/testsuite/.cvsignore Normal file
View File

@@ -0,0 +1,7 @@
Makefile
Makefile.in
T-ngircd
logs
ngircd-test.log
ngircd-test.motd
tests

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.15 2007/11/18 15:07:16 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:
@@ -47,14 +47,6 @@ 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
@@ -62,9 +54,7 @@ mode-test: tests.sh
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,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.8.1 2008/02/16 11:26:13 fw Exp $
spawn telnet localhost 6789
expect {

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.5 2007/11/18 15:07:16 alex Exp $
[Global]
Name = ngircd.test.server
@@ -7,7 +7,8 @@
MotdFile = ngircd-test.motd
AdminEMail = admin@irc.server
MaxConnectionsIP = 0
OperCanUseMode = yes
ServerUID = 1
ServerGID = 1
[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-

3
src/tool/.cvsignore Normal file
View File

@@ -0,0 +1,3 @@
Makefile
Makefile.in
.deps

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.8 2007/11/25 18:42:38 fw Exp $";
#include "imp.h"
#include <assert.h>
@@ -106,4 +106,23 @@ ngt_TrimLastChr( char *String, const char Chr)
if( String[len] == Chr ) String[len] = '\0';
} /* ngt_TrimLastChr */
GLOBAL bool
ngt_IPStrToBin(const char *ip_str, struct in_addr *inaddr)
{
/* AF is always AF_INET for now */
#ifdef HAVE_INET_ATON
if (inet_aton(ip_str, inaddr) == 0)
return false;
#else
inaddr->s_addr = inet_addr(ip_str);
if (inaddr->s_addr == (unsigned)-1)
return false;
#endif
return true;
}
/* -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.5 2007/11/25 18:42:38 fw Exp $
*
* Tool functions (Header)
*/
@@ -29,6 +29,8 @@ GLOBAL void ngt_TrimLastChr PARAMS((char *String, const char Chr ));
GLOBAL void ngt_TrimStr PARAMS((char *String ));
GLOBAL char *ngt_LowerStr PARAMS((char *String ));
GLOBAL bool ngt_IPStrToBin PARAMS((const char *ip_str, struct in_addr *inaddr));
#endif