mirror of
https://github.com/osmarks/ngircd.git
synced 2025-09-26 22:14:04 +00:00
Compare commits
16 Commits
branch-0-1
...
branch-0-1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
3b69da0c52 | ||
![]() |
04933f5b8b | ||
![]() |
45df522bcb | ||
![]() |
51260c2e9f | ||
![]() |
55865d7fc6 | ||
![]() |
082a92beef | ||
![]() |
e92c889580 | ||
![]() |
de4676f066 | ||
![]() |
64a98338d5 | ||
![]() |
f4709082fe | ||
![]() |
997abc6889 | ||
![]() |
b7047f2e3b | ||
![]() |
e990d96c61 | ||
![]() |
d986cd372f | ||
![]() |
762aec0e08 | ||
![]() |
f8cb8e3f20 |
7
.cvsignore
Normal file
7
.cvsignore
Normal file
@@ -0,0 +1,7 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
config.log
|
||||
config.status
|
||||
configure
|
17
.gitignore
vendored
17
.gitignore
vendored
@@ -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
|
51
ChangeLog
51
ChangeLog
@@ -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
10
INSTALL
@@ -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 $
|
||||
|
12
Makefile.am
12
Makefile.am
@@ -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
29
NEWS
@@ -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
10
README
@@ -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 $
|
||||
|
22
configure.in
22
configure.in
@@ -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
2
contrib/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
Makefile.in
|
2
contrib/Debian/.cvsignore
Normal file
2
contrib/Debian/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
Makefile.in
|
@@ -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
|
||||
|
||||
|
2
contrib/MacOSX/.cvsignore
Normal file
2
contrib/MacOSX/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
Makefile.in
|
1
contrib/MacOSX/.gitignore
vendored
1
contrib/MacOSX/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
build
|
@@ -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
|
||||
|
||||
|
@@ -89,4 +89,4 @@
|
||||
#define HAVE_DNSSERVICEREGISTRATIONCREATE 1
|
||||
#endif
|
||||
|
||||
/* -eof- */
|
||||
/* -eof- */
|
@@ -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>
|
2
contrib/MacOSX/ngIRCd.xcodeproj/.gitignore
vendored
2
contrib/MacOSX/ngIRCd.xcodeproj/.gitignore
vendored
@@ -1,2 +0,0 @@
|
||||
*.mode1v3
|
||||
*.pbxuser
|
@@ -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-
|
@@ -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;
|
||||
};
|
||||
|
@@ -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
2
doc/.cvsignore
Normal file
@@ -0,0 +1,2 @@
|
||||
Makefile
|
||||
Makefile.in
|
57
doc/CVS.txt
Normal file
57
doc/CVS.txt
Normal 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 $
|
@@ -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 $
|
||||
|
45
doc/GIT.txt
45
doc/GIT.txt
@@ -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>.
|
||||
|
@@ -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:
|
||||
|
@@ -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
3
doc/src/.cvsignore
Normal file
@@ -0,0 +1,3 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
html
|
1
doc/src/.gitignore
vendored
1
doc/src/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
html
|
@@ -1,2 +1,4 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
ngircd.8
|
||||
ngircd.conf.5
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -1,3 +1,5 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
config.h
|
||||
config.h.in
|
||||
stamp-h1
|
@@ -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
|
||||
|
@@ -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-
|
@@ -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- */
|
@@ -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- */
|
@@ -1,3 +1,6 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
.deps
|
||||
check-help
|
||||
check-version
|
||||
cvs-version.h
|
@@ -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-
|
||||
|
@@ -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;
|
||||
|
@@ -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 ));
|
||||
|
||||
|
@@ -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 )
|
||||
{
|
||||
|
@@ -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 */
|
||||
|
||||
|
||||
|
@@ -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 ));
|
||||
|
@@ -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"
|
||||
|
@@ -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 )
|
||||
{
|
||||
|
@@ -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 */
|
||||
|
1115
src/ngircd/io.c
1115
src/ngircd/io.c
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
|
@@ -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).
|
||||
|
@@ -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 ));
|
||||
|
||||
|
||||
|
@@ -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 */
|
||||
|
@@ -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 */
|
||||
|
||||
|
@@ -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 */
|
||||
|
||||
|
||||
|
@@ -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(),
|
||||
|
@@ -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
|
||||
|
@@ -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"
|
||||
|
@@ -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 */
|
||||
|
||||
|
||||
|
@@ -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 */
|
||||
|
||||
|
||||
|
@@ -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
|
||||
|
||||
|
||||
|
@@ -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))
|
||||
{
|
||||
|
@@ -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
4
src/portab/.cvsignore
Normal file
@@ -0,0 +1,4 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
.deps
|
||||
portabtest
|
1
src/portab/.gitignore
vendored
1
src/portab/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
portabtest
|
7
src/testsuite/.cvsignore
Normal file
7
src/testsuite/.cvsignore
Normal file
@@ -0,0 +1,7 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
T-ngircd
|
||||
logs
|
||||
ngircd-test.log
|
||||
ngircd-test.motd
|
||||
tests
|
10
src/testsuite/.gitignore
vendored
10
src/testsuite/.gitignore
vendored
@@ -1,10 +0,0 @@
|
||||
T-ngircd
|
||||
channel-test
|
||||
connect-test
|
||||
misc-test
|
||||
mode-test
|
||||
who-test
|
||||
ngircd-test.log
|
||||
ngircd-test.motd
|
||||
logs
|
||||
tests
|
@@ -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
|
||||
|
||||
|
@@ -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 }
|
||||
|
@@ -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-
|
@@ -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 {
|
||||
|
@@ -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
|
||||
|
@@ -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
3
src/tool/.cvsignore
Normal file
@@ -0,0 +1,3 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
.deps
|
@@ -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- */
|
||||
|
@@ -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
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user