.gitignore | 2 + ChangeLog | 171 ++++- INSTALL | 20 +- Makefile.am | 14 +- NEWS | 95 ++- README | 15 +- autogen.sh | 68 +- config.guess | 17 +- config.sub | 23 +- configure.in | 651 ------------------ configure.ng | 722 ++++++++++++++++++++ contrib/Anope/0001-Revert-Removed-ngircd.patch | 496 -------------- contrib/Anope/0002-ngircd-whitespace-fixes.patch | 60 -- ...RCd-protocol-module-for-current-Anope-1.9.patch | 128 ---- ...PING-PONG-on-server-burst-to-sync-servers.patch | 93 --- ...ircd-always-prefix-modes-in-CHANINFO-with.patch | 29 - ...cd-support-user-mode-R-and-channel-mode-R.patch | 47 -- ...0007-ngircd-Fix-handling-of-JOIN-commands.patch | 96 --- ...d-Allow-setting-modes-by-clients-on-burst.patch | 38 -- ...ate-protocol-module-for-current-Anope-1.9.patch | 143 ---- contrib/Anope/0010-ngircd-Add-ProtongIRCd.patch | 57 -- ...ate-protocol-module-for-current-Anope-1.9.patch | 29 - ...12-ngircd-Channel-mode-r-is-supported-now.patch | 25 - .../0013-ngircd-Update-copyright-notice.patch | 28 - ...gircd-set-unset-GLINE-s-on-AKILL-commands.patch | 35 - ...ngircd-ngIRCd-supports-channel-mode-e-now.patch | 27 - .../Anope/0016-ngircd-support-SQUERY-command.patch | 35 - contrib/Anope/Makefile.am | 34 - contrib/Anope/README | 35 - contrib/Debian/changelog | 18 + contrib/Debian/control | 32 +- contrib/Debian/rules | 8 +- contrib/MacOSX/config.h | 12 +- contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj | 47 +- contrib/Makefile.am | 15 +- contrib/README | 3 - contrib/ngircd.service | 11 + contrib/ngircd.spec | 12 +- contrib/platformtest.sh | 12 +- doc/HowToRelease.txt | 2 +- doc/Makefile.am | 27 +- doc/Modes.txt | 13 +- doc/Platforms.txt | 13 +- doc/Protocol.txt | 79 ++- doc/Services.txt | 99 +-- doc/sample-ngircd.conf.tmpl | 34 +- man/Makefile.am | 2 +- man/ngircd.8.tmpl | 29 +- man/ngircd.conf.5.tmpl | 47 +- src/ipaddr/.gitignore | 1 + src/ipaddr/Makefile.am | 14 - src/ipaddr/Makefile.ng | 21 + src/ngircd/.gitignore | 1 + src/ngircd/Makefile.am | 144 ---- src/ngircd/Makefile.ng | 152 +++++ src/ngircd/channel.c | 166 ++--- src/ngircd/client.c | 131 +++- src/ngircd/client.h | 13 +- src/ngircd/conf-ssl.h | 12 +- src/ngircd/conf.c | 102 ++- src/ngircd/conf.h | 24 +- src/ngircd/conn-encoding.c | 192 ++++++ src/ngircd/conn-encoding.h | 30 + src/ngircd/conn-ssl.c | 28 +- src/ngircd/conn.c | 144 +++- src/ngircd/conn.h | 19 +- src/ngircd/defines.h | 26 +- src/ngircd/io.c | 14 + src/ngircd/irc-cap.c | 4 +- src/ngircd/irc-channel.c | 47 +- src/ngircd/irc-encoding.c | 68 ++ src/ngircd/irc-encoding.h | 24 + src/ngircd/irc-info.c | 132 ++-- src/ngircd/irc-login.c | 152 +++-- src/ngircd/irc-login.h | 3 +- src/ngircd/irc-metadata.c | 109 +++ src/ngircd/irc-metadata.h | 24 + src/ngircd/irc-mode.c | 189 +++-- src/ngircd/irc-op.c | 12 +- src/ngircd/irc-oper.c | 2 + src/ngircd/irc-server.c | 95 ++- src/ngircd/irc.c | 38 +- src/ngircd/lists.c | 2 +- src/ngircd/log.c | 8 +- src/ngircd/login.c | 11 +- src/ngircd/match.c | 49 +- src/ngircd/match.h | 12 +- src/ngircd/messages.h | 38 +- src/ngircd/ngircd.c | 139 ++-- src/ngircd/numeric.c | 74 +- src/ngircd/pam.c | 4 +- src/ngircd/parse.c | 11 +- src/ngircd/sighandlers.c | 5 +- src/portab/.gitignore | 1 + src/portab/Makefile.am | 34 - src/portab/Makefile.ng | 35 + src/portab/portab.h | 18 +- src/testsuite/.gitignore | 1 + src/testsuite/Makefile.am | 110 --- src/testsuite/Makefile.ng | 109 +++ src/testsuite/getpid.sh | 2 +- src/testsuite/message-test.e | 16 + src/testsuite/mode-test.e | 68 ++ src/testsuite/start-server.sh | 2 +- src/testsuite/stop-server.sh | 2 +- src/testsuite/stress-server.sh | 19 +- src/testsuite/tests.sh | 33 +- src/testsuite/whois-test.e | 26 + src/tool/.gitignore | 1 + src/tool/Makefile.am | 27 - src/tool/Makefile.ng | 27 + src/tool/tool.c | 30 +- src/tool/tool.h | 8 +- 113 files changed, 3642 insertions(+), 3161 deletions(-) diff --git a/.gitignore b/.gitignore index 1990041..e7ab758 100644 --- a/.gitignore +++ b/.gitignore @@ -4,11 +4,13 @@ aclocal.m4 ansi2knr.1 ansi2knr.c ansi2knr.h +ar-lib autom4te.cache build-stamp-ngircd* config.log config.status configure +configure.ac configure.lineno cscope.out debian diff --git a/ChangeLog b/ChangeLog index 1745ea4..9e2a042 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,165 @@ -- ChangeLog -- +ngIRCd 20 (2012-12-17) + + - Allow user names ("INDENT") up to 20 characters when ngIRCd has not + been configured for "strict RFC mode". This is useful if you are using + external (PAM) authenticaion mechanisms that require longer user names. + Patch suggested by Brett Smith , see + . + + ngIRCd 20~rc2 (2012-12-02) + - Rework cloaked hostname handling and implement the "METADATA cloakhost" + subcommand: Now ngIRCd uses two fields internally, one to store the + "real" hostname and one to save the "cloaked" hostname. This allows + "foreign servers" (aka "IRC services") to alter the real and cloaked + hostnames of clients without problems, even when the user itself issues + additional "MODE +x" and "MODE -x" commands. + - RPL_UMODEIS: send correct target name, even on server links. + - Update platformtest.sh to follow autoconf changes and only generate + the "configure" script when it is missing. + - Fix the test suite to correctly execute test scripts even when stdout + is redirected. + - Fix some compiler warnings on NetBSD and OpenBSD. + + ngIRCd 20~rc1 (2012-11-11) + - Update doc/Services.txt: describe the upcoming version of Anope 1.9.8, + then including a protocol module for ngIRCd. And remove our own patches + in ./contrib/Anope because they aren't supported any more ... + - Implement new "METADATA" command which can be used by remote servers + and IRC services to update client metadata like the client info text + ("real name"), user name, and hostname, and use this command to + configure an cloaked hostname (user mode "+x") on remote servers: + This prevents "double cloaking" of hostnames and even cloaked + hostnames are in sync on all servers supporting "METADATA" now. + - Fix error message when trying to join non-predefined channels and the + "PredefChannelsOnly" configuration option is set. + - Implement new IRC "SVSNICK" command to allow remote servers (and IRC + services) to change nicknames of already registered users. The SVSNICK + command itself doesn't change the nickname, but it becomes forwarded + to the server to which the user is connected to. And then this server + initiates the real nickname changing using regular NICK commands. + This allows to run mixed networks with old servers not supporting the + SVSNICK command, because SVSNICK commands for nicknames on such servers + are silently ignored and don't cause a desynchronization of the network. + - Make server reconnect time a little bit more random, so that two + servers trying to connect to each other asynchronously don't try this + in exactly the same time periods and kick each other off ... + - Don't accept connections for servers already being linked: there was a + time frame that could result in one connection overwriting the other, + e. g. the incoming connection overwriting the status of the outgoing + one. And this could lead to all kind of weirdness (even crashes!) later + on: now such incoming connections are dropped. + - New configuration option "MaxListSize" to configure the maximum number + of channels returned by a LIST command. The default is 100, as before. + - Implement user mode "b", "block messages": when a user has set mode "b", + all private messages and notices to this user are blocked if they don't + originate from a registered user, an IRC Op, server or service. The + originator gets an error numeric sent back in this case, + ERR_NONONREG_MSG (486), which is used by UnrealIRCd, too. (Closes #144) + - WHOIS: Not only show RPL_WHOISHOST_MSG to local IRC operators, but show + it to all IRC operators in the network. And don't show it to anybody if + the "more privacy" configuration option is enabled. (Closes #134) + - Test suite: make expect scripts more verbose displaying dots for each + reply of the server that it is waiting for. + - WHOIS: Implement numeric RPL_WHOISMODES_MSG (379) and show user modes in + the reply of the WHOIS command for the user himself or, if MorePrivacy + isn't set, for request initiated by an IRC operator. (Closes #129) + - Implement channel mode "V" (invite disallow): If the new channel mode + "V" is set, the INVITE command becomes invalid and all clients get the + new ERR_NOINVITE_MSG (518) reply. (Closes #143) + - KICK-protect IRC services. + - Implement channel mode "Q" and user mode "q": Both modes protect users + from channel kicks: only IRC operators and servers can kick users having + mode "q" or in channels with mode "Q". (Closes #141) + - Debian: require "telnet" or "telnet-ssl" for building and enable + CHARCONV in ngircd-full[-dbg] variants. + - Send RPL_REHASHING (382) numeric if a REHASH command was accepted. + - Fix spelling and variable names in some log messages. + - Allow users to "cloak" their hostname only when the configuration + variable "CloakHostModeX" (introduced in 19.2) is set. Otherwise, only + IRC operators, other servers, and services are allowed to set the user + mode "+x": this prevents regular users from changing their hostmask to + the name of the IRC server itself, which confused quite a few people ;-) + (Closes #133) + - New configuration option "OperChanPAutoOp": If disabled, IRC operators + don't become channel operators in persistent channels when joining. + Enabled by default, which has been the behavior of ngIRCd up to this + patch. (Closes #135) + - Allow IRC operators to see secret (+s) channels in LIST command as long + as the "MorePrivacy" configuration option isn't enabled in the + configuration file. (Closes #136) + - Enhance build system: Support new (>=1.12) and old (<=1.11) GNU automake + versions, update checks for required and optional features, enable + colored test output of automake (if available), rename configure.in to + more modern configure.ac, include .mailmap and all build-system files in + distribution archives and no longer require a GIT tree to detect the + correct version string. + - Update documentation: add doc/Contributing.txt and include version + numbers in doc/Modes.txt. + - Free all listen ports on initialization: now listen ports can be + reconfigured on runtime using a configuration reload. + - Initialize SSL when needed only, and disable SSL on errors. + - Implement new (optional) IRC+ "CHARCONV" command to set a client + character set that the server translates all messages to/from UTF-8. + This feature requires the "libiconv" library and must be enabled using + the new "--with-iconv" option of the ./configure script. See + doc/Protocol.txt for details. (Closes #109) + - Allow limited punctuation in usernames, for better PAM integration. + - Correctly re-initialize signal handlers on RESTART commands. + - Show a warning on startup if the configuration file is not a full path: + ngIRCd is a long-running process and changes its working directory to + "/" to not block mounted filesystems and the like when running as daemon + ("not in the foreground"); therefore the path to the configuration file + must be relative to "/" (or the chroot() directory), which basically is + "not relative", to ensure that "kill -HUP" and the "REHASH" command work + as expected later on. (Closes #127) + - Make the "&SERVER" channel definable in a [Channel] configuration block, + which enables server operators to overwrite the built-in topic and + channel modes. (Closes #131) + - Don't limit list size of "WHO #channel" commands, because it makes no + sense to not return all the users in that channel, so I removed the + check. But if there are more than MAX_RPL_WHO(25) replies, the client + requesting the list will be "penalized" one second more, then 2 in + total. (Closes #125) + - Make ngIRCd buildable using the kqueue() IO interface on FreeBSD 4.x. + - Fix the "NoticeAuth" configuration option when using SSL connections and + enhance the message to show the hostname and IDENT reply of the client. + - Introduce numeric RPL_HOSTHIDDEN_MSG (396): This numeric is sent to the + client each time it changes its displayed hostname using "MODE +/-x", + and if "CloakHost" is set right after the MOTD has been sent. + - Fix USERHOST not displaying the correctly cloaked hostname. + - Implement user mode "B" ("Bot flag"): it is settable and unsettable by + every (non-restricted) client. This is how Unreal and InspIRCd do + behave, and so do we :-) + - Dynamically allocate memory for connection passwords: This a) saves + memory for clients not using passwords at all and b) allows for + "arbitrarily" long passwords. + - Implement channel mode "M": Only the server, identified users and IRC + operators are able to talk in such a channel. + - Block nicknames that are reserved for services and are defined using the + configuration variable "ServiceMask" in "Server" blocks; And this + variable now can handle more than one mask separated by commas. + - Now "make uninstall" removes the installed "ngircd.conf" file, if it is + still equal to our "sample-ngircd.conf" file and therefore hasn't been + modified by the user. If it has been modified, it isn't removed and a + notice is displayed to the user. And "make install" now displays a + message when no ngircd.conf file exists and the "sample-ngircd.conf" + file will be installed as a starting point. + - Add contrib/ngircd.service, a systemd service file for ngircd. + - Implemented XOP channel user modes: "Half Op" ("+h", prefix "%") can set + the channel modes +imntvIbek and kick all +v and normal users; "Admin" + ("+a", prefix "&") can set channel modes +imntvIbekoRsz and kick all +o, + +h, +v and normal users; and "Owner" ("+q", prefix "~") can set channel + modes +imntvIbekoRsz and kick all +a, +o, +h, +v and normal users. + - Implement hashed cloaked hostnames for both the "CloakHost" and + "CloakHostModeX" configuration options: now the admin can use the new + '%x' placeholder to insert a hashed version of the clients hostname, + and the new configuration option "CloakHostSalt" defines the salt for + the hash function. When "CloakHostSalt" is not set (the default), a + random salt will be generated after each server restart. (Closes #133) + ngIRCd Release 19.2 (2012-06-19) - doc/Capabilities.txt: document "multi-prefix" capability @@ -82,7 +241,7 @@ ngIRCd Release 19 (2012-02-29) and receiver are on the same channel. This prevents private flooding by completely unknown clients. - New RPL_WHOISREGNICK_MSG(307) numeric in WHOIS command replies: it - indicates if a nick name is registered (if user mode 'R' set). + indicates if a nickname is registered (if user mode 'R' set). - Limit channel invite, ban, and exception lists to 50 entries and fix duplicate check and error messages when adding already listed entries or deleting no (longer) existing ones. @@ -123,7 +282,7 @@ ngIRCd Release 19 (2012-02-29) limit reached), but report an error and continue. And don't check the channel limit and don't report with "too many channels" when trying to join a channel that the client already is a member of. - - ISON command: reply with the correct upper-/lowercase nick names. + - ISON command: reply with the correct upper-/lowercase nicknames. - New configuration option "PAMIsOptional": when set, clients not sending a password are still allowed to connect: they won't become "identified" and keep the "~" character prepended to their supplied @@ -170,7 +329,7 @@ ngIRCd Release 19 (2012-02-29) The bug has been introduced starting with ngIRCd 17 ... :-( (commit ID 6ebb31ab35e) - Added doc/Modes.txt: document modes supported by ngIRCd. - - Implement user mode "R": indicates that the nick name of this user + - Implement user mode "R": indicates that the nickname of this user is "registered". This mode isn't handled by ngIRCd itself, but must be set and unset by IRC services like Anope. - Implement channel mode "R": only registered users (having the user @@ -188,7 +347,7 @@ ngIRCd Release 19 (2012-02-29) - Handle channel user modes 'a', 'h', and 'q' from remote servers. These channel user modes aren't used for anything at the moment, but ngIRCd knows that these three modes are "channel user modes" - and not "channel modes", that is that these modes take an "nick name" + and not "channel modes", that is that these modes take an "nickname" argument. Like unknown user and channel modes, these modes are saved and forwarded to other servers, but ignored otherwise. - Correctly inform clients when other servers change their user modes. @@ -275,7 +434,7 @@ ngIRCd Release 18 (2011-07-10) - New configuration option "CloakHost": when set, this host name is used for every client instead of the real DNS host name (or IP address). - New configuration option "CloakUserToNick": when enabled, ngIRCd sets - every clients' user name to their nick name and hides the user name + every clients' user name to their nickname and hides the user name supplied by the IRC client. - doc/Protocol.txt: Update description of the CHANINFO and WEBIRC commands. - Doxygen'ify (document) much more source files; code cleanup ... @@ -607,7 +766,7 @@ ngIRCd 0.11.0 (2008-01-15) - New [Server] configuration Option "Bind" allows to specify the source IP address to use when connecting to remote server. - New configuration option "MaxNickLength" to specify the allowed maximum - length of user nick names. Note: must be unique in an IRC network! + length of user nicknames. Note: must be unique in an IRC network! - Enhanced the IRC+ protocol to support an enhanced "server handshake" and enable server to recognize numeric 005 (ISUPPORT) and 376 (ENDOFMOTD). See doc/Protocol.txt for details. diff --git a/INSTALL b/INSTALL index 4e1cd2f..b445958 100644 --- a/INSTALL +++ b/INSTALL @@ -12,6 +12,14 @@ I. Upgrade Information ~~~~~~~~~~~~~~~~~~~~~~ +Differences to version 19.x + +- Starting with ngIRCd 20, users can "cloak" their hostname only when the + configuration variable "CloakHostModeX" (introduced in 19.2) is set. + Otherwise, only IRC opertators, other servers, and services are allowed to + set mode +x. This prevents regular users from changing their hostmask to + the name of the IRC server itself, which confused quite a few people ;-) + Differences to version 17 - Support for ZeroConf/Bonjour/Rendezvous service registration has been @@ -149,10 +157,14 @@ This step is therefore only interesting for developers. autogen.sh produces the Makefile.in's, which are necessary for the configure script itself, and some more files for make. To run autogen.sh you'll need -GNU autoconf and GNU automake (use recent versions! autoconf 2.53 and -automake 1.6.1 are known to work). - -Again: "end users" do not need this step! +GNU autoconf and GNU automake: at least autoconf 2.61 and automake 1.10 are +requird, newer is better. But don't use automake 1.12 or newer for creating +distribution archives: it will work but lack "de-ANSI-fucation" support in the +generated Makefile's! Stick with automake 1.11.x for this purpose ... +So automake 1.11.x and autoconf 2.67+ is recommended. + +Again: "end users" do not need this step and neither need GNU autoconf nor GNU +automake at all! 2): "./configure" diff --git a/Makefile.am b/Makefile.am index 58f202c..f6a97ce 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ # # ngIRCd -- The Next Generation IRC Daemon -# Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors +# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors # # 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 @@ -13,24 +13,26 @@ AUTOMAKE_OPTIONS = gnu SUBDIRS = doc src man contrib +EXTRA_DIST = autogen.sh configure.ng .mailmap + clean-local: rm -f build-stamp* rm -rf ngircd.dest maintainer-clean-local: rm -rf autom4te.cache - rm -f Makefile.in Makefile aclocal.m4 configure - rm -f mkinstalldirs missing depcomp install-sh + rm -f Makefile.in Makefile aclocal.m4 configure configure.ac + rm -f ar-lib mkinstalldirs missing depcomp install-sh rm -f config.log debian testsuite: - make -C src/testsuite check + cd src/testsuite && make check lint: - make -C src/ngircd lint + cd src/ngircd && make lint srcdoc: - make -C doc srcdoc + cd doc && make srcdoc have-xcodebuild: @xcodebuild -project contrib/MacOSX/ngIRCd.xcodeproj -list \ diff --git a/NEWS b/NEWS index ab0ac19..96ecdc8 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,91 @@ -- NEWS -- +ngIRCd 20 (2012-12-17) + + - Allow user names ("INDENT") up to 20 characters when ngIRCd has not + been configured for "strict RFC mode". This is useful if you are using + external (PAM) authenticaion mechanisms that require longer user names. + Patch suggested by Brett Smith , see + . + + ngIRCd 20~rc2 (2012-12-02) + - Rework cloaked hostname handling and implement the "METADATA cloakhost" + subcommand: Now ngIRCd uses two fields internally, one to store the + "real" hostname and one to save the "cloaked" hostname. This allows + "foreign servers" (aka "IRC services") to alter the real and cloaked + hostnames of clients without problems, even when the user itself issues + additional "MODE +x" and "MODE -x" commands. + + ngIRCd 20~rc1 (2012-11-11) + - Update doc/Services.txt: describe the upcoming version of Anope 1.9.8, + then including a protocol module for ngIRCd. And remove our own patches + in ./contrib/Anope because they aren't supported any more ... + - Implement new "METADATA" command which can be used by remote servers + and IRC services to update client metadata like the client info text + ("real name"), user name, and hostname, and use this command to + configure an cloaked hostname (user mode "+x") on remote servers: + This prevents "double cloaking" of hostnames and even cloaked + hostnames are in sync on all servers supporting "METADATA" now. + - Implement new IRC "SVSNICK" command to allow remote servers (and IRC + services) to change nicknames of already registered users. The SVSNICK + command itself doesn't change the nickname, but it becomes forwarded + to the server to which the user is connected to. And then this server + initiates the real nickname changing using regular NICK commands. + This allows to run mixed networks with old servers not supporting the + SVSNICK command, because SVSNICK commands for nicknames on such servers + are silently ignored and don't cause a desynchronization of the network. + - New configuration option "MaxListSize" to configure the maximum number + of channels returned by a LIST command. The default is 100, as before. + - Implement user mode "b", "block messages": when a user has set mode "b", + all private messages and notices to this user are blocked if they don't + originate from a registered user, an IRC Op, server or service. The + originator gets an error numeric sent back in this case, + ERR_NONONREG_MSG (486), which is used by UnrealIRCd, too. (Closes #144) + - Implement channel mode "V" (invite disallow): If the new channel mode + "V" is set, the INVITE command becomes invalid and all clients get the + new ERR_NOINVITE_MSG (518) reply. (Closes #143) + - Implement channel mode "Q" and user mode "q": Both modes protect users + from channel kicks: only IRC operators and servers can kick users having + mode "q" or in channels with mode "Q". (Closes #141) + - Allow users to "cloak" their hostname only when the configuration + variable "CloakHostModeX" (introduced in 19.2) is set. Otherwise, only + IRC operators, other servers, and services are allowed to set the user + mode "+x": this prevents regular users from changing their hostmask to + the name of the IRC server itself, which confused quite a few people ;-) + (Closes #133) + - New configuration option "OperChanPAutoOp": If disabled, IRC operators + don't become channel operators in persistent channels when joining. + Enabled by default, which has been the behavior of ngIRCd up to this + patch. (Closes #135) + - Allow IRC operators to see secret (+s) channels in LIST command as long + as the "MorePrivacy" configuration option isn't enabled in the + configuration file. (Closes #136) + - Implement new (optional) IRC+ "CHARCONV" command to set a client + character set that the server translates all messages to/from UTF-8. + This feature requires the "libiconv" library and must be enabled using + the new "--with-iconv" option of the ./configure script. See + doc/Protocol.txt for details. (Closes #109) + - Implement user mode "B" ("Bot flag"): it is settable and unsettable by + every (non-restricted) client. This is how Unreal and InspIRCd do + behave, and so do we :-) + - Implement channel mode "M": Only the server, identified users and IRC + operators are able to talk in such a channel. + - Block nicknames that are reserved for services and are defined using the + configuration variable "ServiceMask" in "Server" blocks; And this + variable now can handle more than one mask separated by commas. + - Implemented XOP channel user modes: "Half Op" ("+h", prefix "%") can set + the channel modes +imntvIbek and kick all +v and normal users; "Admin" + ("+a", prefix "&") can set channel modes +imntvIbekoRsz and kick all +o, + +h, +v and normal users; and "Owner" ("+q", prefix "~") can set channel + modes +imntvIbekoRsz and kick all +a, +o, +h, +v and normal users. + - Implement hashed cloaked hostnames for both the "CloakHost" and + "CloakHostModeX" configuration options: now the admin can use the new + '%x' placeholder to insert a hashed version of the clients hostname, + and the new configuration option "CloakHostSalt" defines the salt for + the hash function. When "CloakHostSalt" is not set (the default), a + random salt will be generated after each server restart. + ngIRCd Release 19.2 (2012-06-19) ngIRCd 19.2~rc1 (2012-06-13) @@ -43,7 +128,7 @@ ngIRCd Release 19 (2012-02-29) and receiver are on the same channel. This prevents private flooding by completely unknown clients. - New RPL_WHOISREGNICK_MSG(307) numeric in WHOIS command replies: it - indicates if a nick name is registered (if user mode 'R' set). + indicates if a nickname is registered (if user mode 'R' set). - Limit channel invite, ban, and exception lists to 50 entries and fix duplicate check and error messages when adding already listed entries or deleting no (longer) existing ones. @@ -79,7 +164,7 @@ ngIRCd Release 19 (2012-02-29) NICK, and USER commands have been processed) and before the child processes for authentication are forked, so resource usage is smaller. - Added doc/Modes.txt: document modes supported by ngIRCd. - - Implement user mode "R": indicates that the nick name of this user + - Implement user mode "R": indicates that the nickname of this user is "registered". This mode isn't handled by ngIRCd itself, but must be set and unset by IRC services like Anope. - Implement channel mode "R": only registered users (having the user @@ -90,7 +175,7 @@ ngIRCd Release 19 (2012-02-29) - Handle channel user modes 'a', 'h', and 'q' from remote servers. These channel user modes aren't used for anything at the moment, but ngIRCd knows that these three modes are "channel user modes" - and not "channel modes", that is that these modes take an "nick name" + and not "channel modes", that is that these modes take an "nickname" argument. Like unknown user and channel modes, these modes are saved and forwarded to other servers, but ignored otherwise. @@ -149,7 +234,7 @@ ngIRCd Release 18 (2011-07-10) - New configuration option "CloakHost": when set, this host name is used for every client instead of the real DNS host name (or IP address). - New configuration option "CloakUserToNick": when enabled, ngIRCd sets - every clients' user name to their nick name and hides the user name + every clients' user name to their nickname and hides the user name supplied by the IRC client. - Make write buffers bigger, but flush early. Before this change, a client got disconnected if the buffer flushing at 4k failed, now regular clients @@ -317,7 +402,7 @@ ngIRCd 0.11.0 (2008-01-15) - New [Server] configuration Option "Bind" allows to specify the source IP address to use when connecting to remote server. - New configuration option "MaxNickLength" to specify the allowed maximum - length of user nick names. Note: must be unique in an IRC network! + length of user nicknames. Note: must be unique in an IRC network! - Numeric 317: implemented "signon time" (displayed in WHOIS result). - Added new server configuration option "Passive" for "Server" blocks to disable automatic outgoing connections (similar to -p option to ngircd, diff --git a/README b/README index 2e19d83..11d140d 100644 --- a/README +++ b/README @@ -12,12 +12,15 @@ I. Introduction ~~~~~~~~~~~~~~~ -ngIRCd is an Open Source server for the Internet Relay Chat (IRC), which -is developed and published under the terms of the GNU General Public -Licence, see the file COPYING for details. ngIRCd means "next generation -IRC daemon" (which is a little bit exaggerated, "lightweight Internet Relay -Chat server" would be better), it's written from scratch and not deduced -from the "grandfather of IRC daemons", the daemon of the IRCNet. +ngIRCd is a free, portable and lightweight Internet Relay Chat server for +small or private networks, developed under the GNU General Public License +(GPL; please see the file COPYING for details). It is simple to configure, +can cope with dynamic IP addresses, and supports IPv6 as well as SSL. It is +written from scratch and not based on the original IRCd. + +The name ngIRCd means next generation IRC daemon, which is a little bit +exaggerated: lightweight Internet Relay Chat server most probably would be a +better name :-) Please see the INSTALL document for installation and upgrade information! diff --git a/autogen.sh b/autogen.sh index c87085a..6c2a8dd 100755 --- a/autogen.sh +++ b/autogen.sh @@ -1,7 +1,7 @@ #!/bin/sh # # ngIRCd -- The Next Generation IRC Daemon -# Copyright (c)2001-2008 Alexander Barton +# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors # # 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 @@ -16,6 +16,11 @@ # GNU autoconf. It tries to be smart in finding the correct/usable/available # installed versions of these tools on your system. # +# In addition, it enables or disables the "de-ANSI-fication" support of GNU +# automake, which is supported up to autoconf 1.11.x an has been removed +# in automake 1.12 -- make sure to use a version of automake supporting it +# when generating distribution archives! +# # The following strategy is used for each of aclocal, autoheader, automake, # and autoconf: first, "tool" (the regular name of the tool, e. g. "autoconf" # or "automake") is checked. If this fails, "tool" (for example @@ -98,6 +103,12 @@ Notfound() exit 1 } +Run() +{ + [ "$VERBOSE" = "1" ] && echo " - running \"$@\" ..." + $@ +} + # Reset locale settings to suppress warning messages of Perl unset LC_ALL unset LANG @@ -123,19 +134,18 @@ fi # Try to detect the needed tools when no environment variable already # specifies one: -echo "Searching tools ..." +echo "Searching for required tools ..." [ -z "$ACLOCAL" ] && ACLOCAL=`Search aclocal 1` -[ "$VERBOSE" = "1" ] && echo "ACLOCAL=$ACLOCAL" +[ "$VERBOSE" = "1" ] && echo " - ACLOCAL=$ACLOCAL" [ -z "$AUTOHEADER" ] && AUTOHEADER=`Search autoheader 2` -[ "$VERBOSE" = "1" ] && echo "AUTOHEADER=$AUTOHEADER" +[ "$VERBOSE" = "1" ] && echo " - AUTOHEADER=$AUTOHEADER" [ -z "$AUTOMAKE" ] && AUTOMAKE=`Search automake 1` -[ "$VERBOSE" = "1" ] && echo "AUTOMAKE=$AUTOMAKE" +[ "$VERBOSE" = "1" ] && echo " - AUTOMAKE=$AUTOMAKE" [ -z "$AUTOCONF" ] && AUTOCONF=`Search autoconf 2` -[ "$VERBOSE" = "1" ] && echo "AUTOCONF=$AUTOCONF" +[ "$VERBOSE" = "1" ] && echo " - AUTOCONF=$AUTOCONF" -# Call ./configure when parameters have been passed to this script and -# GO isn't already defined. -[ -z "$GO" -a $# -gt 0 ] && GO=1 +[ $# -gt 0 ] && CONFIGURE_ARGS=" $@" || CONFIGURE_ARGS="" +[ -z "$GO" -a -n "$CONFIGURE_ARGS" ] && GO=1 # Verify that all tools have been found [ -z "$ACLOCAL" ] && Notfound aclocal @@ -143,14 +153,41 @@ echo "Searching tools ..." [ -z "$AUTOMAKE" ] && Notfound automake [ -z "$AUTOCONF" ] && Notfound autoconf +AM_VERSION=`$AUTOMAKE --version|head -n 1|egrep -o "([1-9]\.[0-9]+(\.[0-9]+)*)"` +ifs=$IFS; IFS="."; set $AM_VERSION; IFS=$ifs +AM_MAJOR="$1"; AM_MINOR="$2"; AM_PATCHLEVEL="$3" + +AM_MAKEFILES="src/ipaddr/Makefile.ng src/ngircd/Makefile.ng src/testsuite/Makefile.ng src/tool/Makefile.ng" + +if [ "$AM_MAJOR" -eq "1" -a "$AM_MINOR" -lt "12" ]; then + # automake < 1.12 => automatic de-ANSI-fication support available + echo "Enabling de-ANSI-fication support (automake $AM_VERSION) ..." + sed -e "s|^__ng_PROTOTYPES__|AM_C_PROTOTYPES|g" configure.ng >configure.ac + DEANSI_START="" + DEANSI_END="" +else + # automake >= 1.12 => no de-ANSI-fication support available + echo "Disabling de-ANSI-fication support (automake $AM_VERSION) ..." + sed -e "s|^__ng_PROTOTYPES__|AC_C_PROTOTYPES|g" configure.ng >configure.ac + DEANSI_START="#" + DEANSI_END=" # disabled by ./autogen.sh script" +fi +sed -e "s|^__ng_Makefile_am_template__|${DEANSI_START}AUTOMAKE_OPTIONS = ansi2knr${DEANSI_END}|g" \ + src/portab/Makefile.ng >src/portab/Makefile.am +for makefile_ng in $AM_MAKEFILES; do + makefile_am=`echo "$makefile_ng" | sed -e "s|\.ng\$|\.am|g"` + sed -e "s|^__ng_Makefile_am_template__|${DEANSI_START}AUTOMAKE_OPTIONS = ../portab/ansi2knr${DEANSI_END}|g" \ + $makefile_ng >$makefile_am +done + export ACLOCAL AUTOHEADER AUTOMAKE AUTOCONF # Generate files -echo "Generating files ..." -$ACLOCAL && \ - $AUTOHEADER && \ - $AUTOMAKE --add-missing && \ - $AUTOCONF --force +echo "Generating files using GNU $AUTOCONF and $AUTOMAKE ..." +Run $ACLOCAL && \ + Run $AUTOCONF && \ + Run $AUTOHEADER && \ + Run $AUTOMAKE --add-missing --no-force if [ $? -eq 0 -a -x ./configure ]; then # Success: if we got some parameters we call ./configure and pass @@ -158,8 +195,7 @@ if [ $? -eq 0 -a -x ./configure ]; then NAME=`grep PACKAGE_STRING= configure | cut -d"'" -f2` if [ "$GO" = "1" ]; then [ -n "$PREFIX" ] && p=" --prefix=$PREFIX" || p="" - [ -n "$*" ] && a=" $*" || a="" - c="./configure${p}${a}" + c="./configure${p}${CONFIGURE_ARGS}" echo "Okay, autogen.sh for $NAME done." echo "Calling \"$c\" ..." $c diff --git a/config.guess b/config.guess index d622a44..137bedf 100644 --- a/config.guess +++ b/config.guess @@ -4,7 +4,7 @@ # 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, # 2011, 2012 Free Software Foundation, Inc. -timestamp='2012-02-10' +timestamp='2012-08-14' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -200,6 +200,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. echo "${machine}-${os}${release}" exit ;; + *:Bitrig:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE} + exit ;; *:OpenBSD:*:*) UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} @@ -801,6 +805,9 @@ EOF i*:CYGWIN*:*) echo ${UNAME_MACHINE}-pc-cygwin exit ;; + *:MINGW64*:*) + echo ${UNAME_MACHINE}-pc-mingw64 + exit ;; *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; @@ -1201,6 +1208,9 @@ EOF BePC:Haiku:*:*) # Haiku running on Intel PC compatible. echo i586-pc-haiku exit ;; + x86_64:Haiku:*:*) + echo x86_64-unknown-haiku + exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; @@ -1256,7 +1266,7 @@ EOF NEO-?:NONSTOP_KERNEL:*:*) echo neo-tandem-nsk${UNAME_RELEASE} exit ;; - NSE-?:NONSTOP_KERNEL:*:*) + NSE-*:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; NSR-?:NONSTOP_KERNEL:*:*) @@ -1330,9 +1340,6 @@ EOF exit ;; esac -#echo '(No uname command or uname output not recognized.)' 1>&2 -#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 - eval $set_cc_for_build cat >$dummy.c < - #endif - #ifdef HAVE_SYS_SOCKET_H - #include - #endif - #ifdef HAVE_NETINET_IN_H - #include - #endif - ]] -) - -# -- Datatypes -- - -AC_MSG_CHECKING(whether socklen_t exists) -AC_TRY_COMPILE([ -#include -#include - ],[ - socklen_t a, b; - a = 2; b = 4; a += b; - ],[ - AC_DEFINE(HAVE_socklen_t) AC_MSG_RESULT(yes) - ],[ - AC_MSG_RESULT(no) -]) - -AC_TYPE_SIGNAL -AC_TYPE_SIZE_T - -AC_CHECK_MEMBER([struct sockaddr_in.sin_len], AC_DEFINE(HAVE_sockaddr_in_len),, - [#include ]) - -# -- Libraries -- - -# A/UX needs this. -AC_CHECK_LIB(UTIL,memmove) -# needed on solaris. GNU libc also has a libnsl, but we do not need it. -AC_SEARCH_LIBS(gethostbyname,nsl) -AC_CHECK_LIB(socket,bind) - -# -- Functions -- - -AC_FUNC_FORK -AC_FUNC_STRFTIME - -AC_CHECK_FUNCS([ \ - bind gethostbyaddr gethostbyname gethostname inet_ntoa \ - setsid setsockopt socket strcasecmp waitpid],, - AC_MSG_ERROR([required function missing!])) - -AC_CHECK_FUNCS([ \ - gai_strerror getaddrinfo getnameinfo inet_aton sigaction \ - sigprocmask snprintf vsnprintf strdup strlcpy strlcat strtok_r]) - -# -- Configuration options -- - -# use syslog? - -x_syslog_on=no -AC_ARG_WITH(syslog, - [ --without-syslog disable syslog (autodetected by default)], - [ if test "$withval" != "no"; then - if test "$withval" != "yes"; then - CFLAGS="-I$withval/include $CFLAGS" - CPPFLAGS="-I$withval/include $CPPFLAGS" - LDFLAGS="-L$withval/lib $LDFLAGS" - fi - AC_CHECK_LIB(be, syslog) - AC_CHECK_FUNCS(syslog, x_syslog_on=yes, - AC_MSG_ERROR([Can't enable syslog!]) - ) - fi - ], - [ - AC_CHECK_LIB(be, syslog) - AC_CHECK_FUNCS(syslog, x_syslog_on=yes) - ] -) -if test "$x_syslog_on" = "yes"; then - AC_DEFINE(SYSLOG, 1) - AC_CHECK_HEADERS(syslog.h,,AC_MSG_ERROR([required C header missing!])) -fi - -# use zlib compression? - -x_zlib_on=no -AC_ARG_WITH(zlib, - [ --without-zlib disable zlib compression (autodetected by default)], - [ if test "$withval" != "no"; then - if test "$withval" != "yes"; then - CFLAGS="-I$withval/include $CFLAGS" - CPPFLAGS="-I$withval/include $CPPFLAGS" - LDFLAGS="-L$withval/lib $LDFLAGS" - fi - AC_CHECK_LIB(z, deflate) - AC_CHECK_FUNCS(deflate, x_zlib_on=yes, - AC_MSG_ERROR([Can't enable zlib!]) - ) - fi - ], - [ AC_CHECK_LIB(z, deflate) - AC_CHECK_FUNCS(deflate, x_zlib_on=yes) - ] -) -if test "$x_zlib_on" = "yes"; then - AC_DEFINE(ZLIB, 1) - AC_CHECK_HEADERS(zlib.h,,AC_MSG_ERROR([required C header missing!])) -fi - -# detect which IO API to use: - -x_io_backend=none - -AC_ARG_WITH(select, - [ --without-select disable select IO support (autodetected by default)], - [ if test "$withval" != "no"; then - if test "$withval" != "yes"; then - CFLAGS="-I$withval/include $CFLAGS" - CPPFLAGS="-I$withval/include $CPPFLAGS" - LDFLAGS="-L$withval/lib $LDFLAGS" - fi - AC_CHECK_FUNCS(select, x_io_select=yes, - AC_MSG_ERROR([Can't enable select IO support!]) - ) - fi - ], - [ - AC_CHECK_FUNCS(select, x_io_select=yes) - ] -) - -AC_ARG_WITH(poll, - [ --without-poll disable poll support (autodetected by default)], - [ if test "$withval" != "no"; then - if test "$withval" != "yes"; then - CFLAGS="-I$withval/include $CFLAGS" - CPPFLAGS="-I$withval/include $CPPFLAGS" - LDFLAGS="-L$withval/lib $LDFLAGS" - fi - AC_CHECK_FUNCS(poll, [ - AC_CHECK_HEADERS(poll.h, - x_io_backend=poll\(\), - AC_MSG_ERROR( - [Can't enable poll IO support!]) - ) - ], [ - AC_MSG_ERROR([Can't enable poll IO support!]) - ]) - fi - ], - [ - AC_CHECK_FUNCS(poll, [ - AC_CHECK_HEADERS(poll.h, x_io_backend=poll\(\)) - ]) - ] -) - -AC_ARG_WITH(devpoll, - [ --without-devpoll disable /dev/poll IO support (autodetected by default)], - [ if test "$withval" != "no"; then - if test "$withval" != "yes"; then - CFLAGS="-I$withval/include $CFLAGS" - CPPFLAGS="-I$withval/include $CPPFLAGS" - LDFLAGS="-L$withval/lib $LDFLAGS" - fi - - AC_CHECK_HEADERS(sys/devpoll.h,,AC_MSG_ERROR([required C header missing!])) - fi - ], - [ - AC_CHECK_HEADERS(sys/devpoll.h, x_io_backend=/dev/poll) - ] -) - -AC_ARG_WITH(epoll, - [ --without-epoll disable epoll IO support (autodetected by default)], - [ if test "$withval" != "no"; then - if test "$withval" != "yes"; then - CFLAGS="-I$withval/include $CFLAGS" - CPPFLAGS="-I$withval/include $CPPFLAGS" - LDFLAGS="-L$withval/lib $LDFLAGS" - fi - AC_CHECK_FUNCS(epoll_create, x_io_epoll=yes, - AC_MSG_ERROR([Can't enable epoll IO support!]) - ) - fi - ], - [ - AC_CHECK_FUNCS(epoll_create, x_io_epoll=yes) - ] -) - -AC_ARG_WITH(kqueue, - [ --without-kqueue disable kqueue IO support (autodetected by default)], - [ if test "$withval" != "no"; then - if test "$withval" != "yes"; then - CFLAGS="-I$withval/include $CFLAGS" - CPPFLAGS="-I$withval/include $CPPFLAGS" - LDFLAGS="-L$withval/lib $LDFLAGS" - fi - AC_CHECK_FUNCS(kqueue, x_io_backend=kqueue\(\), - AC_MSG_ERROR([Can't enable kqueue IO support!]) - ) - fi - ], - [ - AC_CHECK_FUNCS(kqueue, x_io_backend=kqueue\(\)) - ] -) - -if test "$x_io_epoll" = "yes" -a "$x_io_select" = "yes"; then - # when epoll() and select() are available, we'll use both! - x_io_backend="epoll(), select()" -else - if test "$x_io_epoll" = "yes"; then - # we prefere epoll() if it is available - x_io_backend="epoll()" - else - if test "$x_io_select" = "yes" -a "$x_io_backend" = "none"; then - # we'll use select, when available and no "better" - # interface has been detected ... - x_io_backend="select()" - fi - fi -fi - -if test "$x_io_backend" = "none"; then - AC_MSG_ERROR([No useable IO API activated/found!?]) -fi - -# use SSL? - -AC_ARG_WITH(openssl, - [ --with-openssl enable SSL support using OpenSSL], - [ if test "$withval" != "no"; then - if test "$withval" != "yes"; then - CFLAGS="-I$withval/include $CFLAGS" - CPPFLAGS="-I$withval/include $CPPFLAGS" - LDFLAGS="-L$withval/lib $LDFLAGS" - fi - AC_CHECK_LIB(crypto, BIO_s_mem) - AC_CHECK_LIB(ssl, SSL_library_init) - AC_CHECK_FUNCS(SSL_library_init, x_ssl_openssl=yes, - AC_MSG_ERROR([Can't enable openssl]) - ) - fi - ] -) - -AC_ARG_WITH(gnutls, - [ --with-gnutls enable SSL support using gnutls], - [ if test "$withval" != "no"; then - if test "$withval" != "yes"; then - CFLAGS="-I$withval/include $CFLAGS" - CPPFLAGS="-I$withval/include $CPPFLAGS" - LDFLAGS="-L$withval/lib $LDFLAGS" - fi - AC_CHECK_LIB(gnutls, gnutls_global_init) - AC_CHECK_FUNCS(gnutls_global_init, x_ssl_gnutls=yes, - AC_MSG_ERROR([Can't enable gnutls]) - ) - fi - ] -) - -x_ssl_lib="no" -if test "$x_ssl_gnutls" = "yes"; then - if test "$x_ssl_openssl" = "yes";then - AC_MSG_ERROR([Cannot enable both gnutls and openssl]) - fi - x_ssl_lib=gnutls -fi -if test "$x_ssl_openssl" = "yes"; then - x_ssl_lib=openssl -fi - -# use TCP wrappers? - -x_tcpwrap_on=no -AC_ARG_WITH(tcp-wrappers, - [ --with-tcp-wrappers enable TCP wrappers support], - [ if test "$withval" != "no"; then - if test "$withval" != "yes"; then - CFLAGS="-I$withval/include $CFLAGS" - CPPFLAGS="-I$withval/include $CPPFLAGS" - LDFLAGS="-L$withval/lib $LDFLAGS" - fi - AC_MSG_CHECKING(for hosts_access) - LIBS="-lwrap $LIBS" - AC_TRY_LINK([ -#include -int allow_severity = 0; -int deny_severity = 0; - ],[ - tcpd_warn("link test"); - ],[ - AC_MSG_RESULT(yes) - AC_DEFINE(TCPWRAP, 1) - x_tcpwrap_on=yes - ],[ - AC_MSG_RESULT(no) - AC_MSG_ERROR([Can't enable TCP wrappers!]) - ]) - fi - ] -) - -# do IDENT requests using libident? - -x_identauth_on=no -AC_ARG_WITH(ident, - [ --with-ident enable "IDENT" ("AUTH") protocol support], - [ if test "$withval" != "no"; then - if test "$withval" != "yes"; then - CFLAGS="-I$withval/include $CFLAGS" - CPPFLAGS="-I$withval/include $CPPFLAGS" - LDFLAGS="-L$withval/lib $LDFLAGS" - fi - AC_CHECK_LIB(ident, ident_id) - AC_CHECK_FUNCS(ident_id, x_identauth_on=yes, - AC_MSG_ERROR([Can't enable IDENT support!]) - ) - fi - ] -) -if test "$x_identauth_on" = "yes"; then - AC_DEFINE(IDENTAUTH, 1) - AC_CHECK_HEADERS(ident.h,,AC_MSG_ERROR([required C header missing!])) -fi - -# compile in PAM support? - -x_pam_on=no -AC_ARG_WITH(pam, - [ --with-pam enable user authentication using PAM], - [ if test "$withval" != "no"; then - if test "$withval" != "yes"; then - CFLAGS="-I$withval/include $CFLAGS" - CPPFLAGS="-I$withval/include $CPPFLAGS" - LDFLAGS="-L$withval/lib $LDFLAGS" - fi - AC_CHECK_LIB(pam, pam_authenticate) - AC_CHECK_FUNCS(pam_authenticate, x_pam_on=yes, - AC_MSG_ERROR([Can't enable PAM support!]) - ) - fi - ] -) -if test "$x_pam_on" = "yes"; then - AC_DEFINE(PAM, 1) - AC_CHECK_HEADERS(security/pam_appl.h,pam_ok=yes) - if test "$pam_ok" != "yes"; then - AC_CHECK_HEADERS(pam/pam_appl.h,pam_ok=yes, - AC_MSG_ERROR([required C header missing!])) - fi -fi - -# compile in IRC+ protocol support? - -x_ircplus_on=yes -AC_ARG_ENABLE(ircplus, - [ --disable-ircplus disable IRC+ protocol], - if test "$enableval" = "no"; then x_ircplus_on=no; fi -) -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 - # getaddrinfo() and getnameinfo() are optional when not compiling - # with IPv6 support, but are required for IPv6 to work! - 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 -AC_ARG_ENABLE(sniffer, - [ --enable-sniffer enable IRC traffic sniffer (enables debug mode)], - if test "$enableval" = "yes"; then - AC_DEFINE(SNIFFER, 1) - x_sniffer_on=yes; x_debug_on=yes - fi -) - -# enable additional debugging code? - -AC_ARG_ENABLE(debug, - [ --enable-debug show additional debug output], - if test "$enableval" = "yes"; then x_debug_on=yes; fi -) -if test "$x_debug_on" = "yes"; then - AC_DEFINE(DEBUG, 1) - test "$GCC" = "yes" && CFLAGS="-pedantic $CFLAGS" - AC_CHECK_FUNCS(mtrace) -fi - -# enable "strict RFC rules"? - -x_strict_rfc_on=no -AC_ARG_ENABLE(strict-rfc, - [ --enable-strict-rfc strict RFC conformance -- may break clients!], - if test "$enableval" = "yes"; then - AC_DEFINE(STRICT_RFC, 1) - x_strict_rfc_on=yes - fi -) - -# -- Definitions -- - -AC_DEFINE_UNQUOTED(TARGET_CPU, "$target_cpu" ) -AC_DEFINE_UNQUOTED(TARGET_VENDOR, "$target_vendor" ) -AC_DEFINE_UNQUOTED(TARGET_OS, "$target_os" ) - -# Add additional CFLAGS, eventually specified on the command line, but after -# running this configure script. Useful for "-Werror" for example. -test -n "$CFLAGS_END" && CFLAGS="$CFLAGS $CFLAGS_END" - -# -- Generate files -- - -AC_OUTPUT([ \ - Makefile \ - doc/Makefile \ - doc/src/Makefile \ - src/Makefile \ - src/portab/Makefile \ - src/ipaddr/Makefile \ - src/tool/Makefile \ - src/ngircd/Makefile \ - src/testsuite/Makefile \ - man/Makefile \ - contrib/Makefile \ - contrib/Anope/Makefile \ - contrib/Debian/Makefile \ - contrib/MacOSX/Makefile \ - contrib/MacOSX/ngIRCd.xcodeproj/Makefile \ - contrib/MacOSX/ngIRCd.pmdoc/Makefile \ -]) - -type dpkg >/dev/null 2>&1 -if test $? -eq 0; then - # Generate debian/ link if the dpkg command exists - # (read: if we are running on a debian compatible system) - echo "creating Debian-specific links ..." - test -f debian/rules || ln -s contrib/Debian debian -fi - -# -- Result -- - -echo -echo "ngIRCd $PACKAGE_VERSION has been configured with the following options:" -echo - -# Someone please show me a better way :) [borrowed by OpenSSH] -B=`eval echo ${bindir}` ; B=`eval echo ${B}` -S=`eval echo ${sbindir}` ; S=`eval echo ${S}` -C=`eval echo ${sysconfdir}` ; C=`eval echo ${C}` -M=`eval echo ${mandir}` ; M=`eval echo ${M}` -D=`eval echo ${docdir}` ; D=`eval echo ${D}` - -echo " Target: ${target}" -test "$target" != "$host" && echo " Host: ${host}" -echo " Compiler: ${CC}" -test -n "$CFLAGS" && echo " Compiler flags: ${CFLAGS}" -test -n "$CPPFLAGS" && echo " Preprocessor flags: ${CPPFLAGS}" -test -n "$LDFLAGS" && echo " Linker flags: ${LDFLAGS}" -test -n "$LIBS" && echo " Libraries: ${LIBS}" -echo -echo " 'ngircd' binary: $S" -echo " Configuration file: $C" -echo " Manual pages: $M" -echo " Documentation: $D" -echo - -echo $ECHO_N " Syslog support: $ECHO_C" -test "$x_syslog_on" = "yes" \ - && echo $ECHO_N "yes $ECHO_C" \ - || echo $ECHO_N "no $ECHO_C" -echo $ECHO_N " Enable debug code: $ECHO_C" -test "$x_debug_on" = "yes" \ - && echo "yes" \ - || echo "no" - -echo $ECHO_N " zlib compression: $ECHO_C" -test "$x_zlib_on" = "yes" \ - && echo $ECHO_N "yes $ECHO_C" \ - || echo $ECHO_N "no $ECHO_C" -echo $ECHO_N " IRC sniffer: $ECHO_C" -test "$x_sniffer_on" = "yes" \ - && echo "yes" \ - || echo "no" - -echo $ECHO_N " Use TCP Wrappers: $ECHO_C" -test "$x_tcpwrap_on" = "yes" \ - && echo $ECHO_N "yes $ECHO_C" \ - || echo $ECHO_N "no $ECHO_C" -echo $ECHO_N " Strict RFC mode: $ECHO_C" -test "$x_strict_rfc_on" = "yes" \ - && echo "yes" \ - || echo "no" - -echo $ECHO_N " IDENT support: $ECHO_C" -test "$x_identauth_on" = "yes" \ - && echo $ECHO_N "yes $ECHO_C" \ - || echo $ECHO_N "no $ECHO_C" -echo $ECHO_N " IRC+ protocol: $ECHO_C" -test "$x_ircplus_on" = "yes" \ - && echo "yes" \ - || echo "no" - -echo $ECHO_N " IPv6 protocol: $ECHO_C" -test "$x_ipv6_on" = "yes" \ - && echo $ECHO_N "yes $ECHO_C" \ - || echo $ECHO_N "no $ECHO_C" -echo $ECHO_N " I/O backend: $ECHO_C" - echo "\"$x_io_backend\"" - -echo $ECHO_N " PAM support: $ECHO_C" -test "$x_pam_on" = "yes" \ - && echo $ECHO_N "yes $ECHO_C" \ - || echo $ECHO_N "no $ECHO_C" -echo $ECHO_N " SSL support: $ECHO_C" -echo "$x_ssl_lib" - -echo - -# -eof- diff --git a/configure.ng b/configure.ng new file mode 100644 index 0000000..84e2750 --- /dev/null +++ b/configure.ng @@ -0,0 +1,722 @@ +# +# ngIRCd -- The Next Generation IRC Daemon +# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors +# +# 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. +# + +define(VERSION_ID,esyscmd([ + V=`git describe 2>/dev/null | sed -e 's/rel-//g' | sed -e 's/-/~/'`; + [ -z "$V" -a -r configure ] \ + && V=`grep "PACKAGE_STRING=" configure | cut -d"'" -f2 | cut -d' ' -f2` + ( [ -n "$V" ] && echo "$V" || echo "??" ) | tr -d '\n'; +])) + +m4_ifdef([AM_SILENT_RULES], + [m4_define([ng_color_tests], [color-tests])], + [m4_define([ng_color_tests], [])]) + +# -- Initialisation -- + +AC_PREREQ([2.61]) +AC_INIT([ngIRCd], VERSION_ID, + [ngircd-ml@ngircd.barton.de], [ngircd], [http://ngircd.barton.de/]) + +AC_CONFIG_SRCDIR([src/ngircd/ngircd.c]) +AC_CONFIG_HEADER([src/config.h]) +AC_CANONICAL_HOST + +AM_INIT_AUTOMAKE([-Wall 1.10 ]ng_color_tests) + +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +# -- Templates for config.h -- + +AH_TEMPLATE([DEBUG], [Define if debug-mode should be enabled]) +AH_TEMPLATE([HAVE_sockaddr_in_len], [Define if sockaddr_in.sin_len exists]) +AH_TEMPLATE([HAVE_socklen_t], [Define if socklen_t exists]) +AH_TEMPLATE([ICONV], [Define if libiconv can be used, e.g. for CHARCONV]) +AH_TEMPLATE([IDENTAUTH], [Define if the server should do IDENT requests]) +AH_TEMPLATE([IRCPLUS], [Define if IRC+ protocol should be used]) +AH_TEMPLATE([PAM], [Define if PAM should be used]) +AH_TEMPLATE([SNIFFER], [Define if IRC sniffer should be enabled]) +AH_TEMPLATE([STRICT_RFC], [Define if ngIRCd should behave strict RFC compliant]) +AH_TEMPLATE([SYSLOG], [Define if syslog should be used for logging]) +AH_TEMPLATE([TCPWRAP], [Define if TCP wrappers should be used]) +AH_TEMPLATE([WANT_IPV6], [Define if IPV6 protocol should be enabled]) +AH_TEMPLATE([ZLIB], [Define if zlib compression should be enabled]) + +AH_TEMPLATE([HOST_OS], [Target operating system name]) +AH_TEMPLATE([HOST_VENDOR], [Target system vendor]) +AH_TEMPLATE([HOST_CPU], [Target CPU name]) + +# -- C Compiler -- + +AC_PROG_CC +AC_PROG_CC_STDC + +# -- Helper programs -- + +m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) + +AC_PROG_AWK +AC_PROG_INSTALL +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_RANLIB + +# -- Compiler Features -- + +AC_C_CONST +AC_C_INLINE +__ng_PROTOTYPES__ + +# -- Hard coded system and compiler dependencies/features/options ... -- + +AC_DEFUN([GCC_STACK_PROTECT_CC],[ + ssp_cc=yes + # we use -fstack-protector-all for the test to enfoce the use of the guard variable + AC_MSG_CHECKING([whether ${CC} accepts -fstack-protector]) + ssp_old_cflags="$CFLAGS" + CFLAGS="$CFLAGS -fstack-protector-all" + AC_TRY_LINK(,,, ssp_cc=no) + echo $ssp_cc + CFLAGS="$ssp_old_cflags" + if test "X$ssp_cc" = "Xyes"; then + CFLAGS="$CFLAGS -fstack-protector" + AC_DEFINE([ENABLE_SSP_CC], 1, [Define if SSP C support is enabled.]) + fi +]) + +if test "$GCC" = "yes"; then + # We are using the GNU C compiler. Good! + CFLAGS="$CFLAGS -pipe -W -Wall -Wpointer-arith -Wstrict-prototypes" + + GCC_STACK_PROTECT_CC +fi + +case "$host_os" in + hpux*) + # This is HP/UX, we need to define _XOPEN_SOURCE_EXTENDED + # (tested with HP/UX 11.11) + CFLAGS="$CFLAGS -D_XOPEN_SOURCE_EXTENDED" + ;; +esac + +# Add additional CFLAGS, eventually specified on the command line: +test -n "$CFLAGS_ADD" && CFLAGS="$CFLAGS $CFLAGS_ADD" + +CFLAGS="$CFLAGS -DSYSCONFDIR='\"\$(sysconfdir)\"'" + +# -- Headers -- + +AC_HEADER_STDC +AC_HEADER_SYS_WAIT +AC_HEADER_TIME + +# Required header files +AC_CHECK_HEADERS([ \ + fcntl.h netdb.h netinet/in.h netinet/in_systm.h stdlib.h string.h \ + strings.h sys/socket.h sys/time.h unistd.h \ + ],,AC_MSG_ERROR([required C header missing!])) + +# Optional header files +AC_CHECK_HEADERS_ONCE([ \ + arpa/inet.h inttypes.h malloc.h netinet/ip.h stdbool.h stddef.h \ + stdint.h varargs.h \ + ]) + +# -- Datatypes -- + +AC_MSG_CHECKING(whether socklen_t exists) +AC_TRY_COMPILE([ +#include +#include + ],[ + socklen_t a, b; + a = 2; b = 4; a += b; + ],[ + AC_DEFINE(HAVE_socklen_t) AC_MSG_RESULT(yes) + ],[ + AC_MSG_RESULT(no) +]) + +AC_TYPE_PID_T +AC_TYPE_SIGNAL +AC_TYPE_SIZE_T +AC_TYPE_SSIZE_T +AC_TYPE_UID_T +AC_TYPE_UINT16_T +AC_TYPE_UINT32_T +AC_TYPE_UINT8_T + +AC_CHECK_MEMBER([struct sockaddr_in.sin_len], AC_DEFINE(HAVE_sockaddr_in_len),, + [#include ]) + +# -- Libraries -- + +# memmove: A/UX libUTIL +AC_SEARCH_LIBS([memmove], [UTIL], [], [ + AC_MSG_ERROR([unable to find the memmove() function]) +]) +# gethostbyname: Solaris libnsl +AC_SEARCH_LIBS([gethostbyname], [bind nsl network], [], [ + AC_MSG_ERROR([unable to find the gethostbyname() function]) +]) +# bind: SVR4 libsocket +AC_SEARCH_LIBS([bind], [socket network], [], [ + AC_MSG_ERROR([unable to find the bind() function]) +]) + +# -- Functions -- + +AC_FUNC_FORK +AC_FUNC_STRFTIME + +# Required functions +AC_CHECK_FUNCS([ \ + alarm dup2 endpwent gethostbyaddr gethostbyname gethostname \ + gettimeofday inet_ntoa memmove memset setsid socket strcasecmp \ + strchr strcspn strerror strncasecmp strrchr strspn strstr \ + ],, + AC_MSG_ERROR([required function missing!])) + +# Optional functions +AC_CHECK_FUNCS_ONCE([ \ + gai_strerror getaddrinfo getnameinfo inet_aton sigaction sigprocmask \ + snprintf vsnprintf strdup strlcpy strlcat strtok_r waitpid]) + +# -- Configuration options -- + +# use syslog? + +x_syslog_on=no +AC_ARG_WITH(syslog, + AS_HELP_STRING([--without-syslog], + [disable syslog (autodetected by default)]), + [ if test "$withval" != "no"; then + if test "$withval" != "yes"; then + CFLAGS="-I$withval/include $CFLAGS" + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + fi + AC_SEARCH_LIBS([syslog], [be], [x_syslog_on=yes], [ + AC_MSG_ERROR([Can't enable syslog!]) + ]) + fi + ], + [ AC_SEARCH_LIBS([syslog], [be], [x_syslog_on=yes]) + ] +) +if test "$x_syslog_on" = "yes"; then + AC_DEFINE(SYSLOG, 1) + AC_CHECK_HEADERS(syslog.h,,AC_MSG_ERROR([required C header missing!])) +fi + +# use zlib compression? + +x_zlib_on=no +AC_ARG_WITH(zlib, + AS_HELP_STRING([--without-zlib], + [disable zlib compression (autodetected by default)]), + [ if test "$withval" != "no"; then + if test "$withval" != "yes"; then + CFLAGS="-I$withval/include $CFLAGS" + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + fi + AC_CHECK_LIB(z, deflate) + AC_CHECK_FUNCS(deflate, x_zlib_on=yes, + AC_MSG_ERROR([Can't enable zlib!]) + ) + fi + ], + [ AC_CHECK_LIB(z, deflate) + AC_CHECK_FUNCS(deflate, x_zlib_on=yes) + ] +) +if test "$x_zlib_on" = "yes"; then + AC_DEFINE(ZLIB, 1) + AC_CHECK_HEADERS(zlib.h,,AC_MSG_ERROR([required C header missing!])) +fi + +# detect which IO API to use: + +x_io_backend=none + +AC_ARG_WITH(select, + AS_HELP_STRING([--without-select], + [disable select IO support (autodetected by default)]), + [ if test "$withval" != "no"; then + if test "$withval" != "yes"; then + CFLAGS="-I$withval/include $CFLAGS" + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + fi + AC_CHECK_FUNCS(select, x_io_select=yes, + AC_MSG_ERROR([Can't enable select IO support!]) + ) + fi + ], + [ + AC_CHECK_FUNCS(select, x_io_select=yes) + ] +) + +AC_ARG_WITH(poll, + AS_HELP_STRING([--without-poll], + [disable poll support (autodetected by default)]), + [ if test "$withval" != "no"; then + if test "$withval" != "yes"; then + CFLAGS="-I$withval/include $CFLAGS" + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + fi + AC_CHECK_FUNCS(poll, [ + AC_CHECK_HEADERS(poll.h, + x_io_backend=poll\(\), + AC_MSG_ERROR( + [Can't enable poll IO support!]) + ) + ], [ + AC_MSG_ERROR([Can't enable poll IO support!]) + ]) + fi + ], + [ + AC_CHECK_FUNCS(poll, [ + AC_CHECK_HEADERS(poll.h, x_io_backend=poll\(\)) + ]) + ] +) + +AC_ARG_WITH(devpoll, + AS_HELP_STRING([--without-devpoll], + [disable /dev/poll IO support (autodetected by default)]), + [ if test "$withval" != "no"; then + if test "$withval" != "yes"; then + CFLAGS="-I$withval/include $CFLAGS" + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + fi + + AC_CHECK_HEADERS(sys/devpoll.h,,AC_MSG_ERROR([required C header missing!])) + fi + ], + [ + AC_CHECK_HEADERS(sys/devpoll.h, x_io_backend=/dev/poll) + ] +) + +AC_ARG_WITH(epoll, + AS_HELP_STRING([--without-epoll], + [disable epoll IO support (autodetected by default)]), + [ if test "$withval" != "no"; then + if test "$withval" != "yes"; then + CFLAGS="-I$withval/include $CFLAGS" + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + fi + AC_CHECK_FUNCS(epoll_create, x_io_epoll=yes, + AC_MSG_ERROR([Can't enable epoll IO support!]) + ) + fi + ], + [ + AC_CHECK_FUNCS(epoll_create, x_io_epoll=yes) + ] +) + +AC_ARG_WITH(kqueue, + AS_HELP_STRING([--without-kqueue], + [disable kqueue IO support (autodetected by default)]), + [ if test "$withval" != "no"; then + if test "$withval" != "yes"; then + CFLAGS="-I$withval/include $CFLAGS" + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + fi + AC_CHECK_FUNCS(kqueue, x_io_backend=kqueue\(\), + AC_MSG_ERROR([Can't enable kqueue IO support!]) + ) + fi + ], + [ + AC_CHECK_FUNCS(kqueue, x_io_backend=kqueue\(\)) + ] +) + +if test "$x_io_epoll" = "yes" -a "$x_io_select" = "yes"; then + # when epoll() and select() are available, we'll use both! + x_io_backend="epoll(), select()" +else + if test "$x_io_epoll" = "yes"; then + # we prefere epoll() if it is available + x_io_backend="epoll()" + else + if test "$x_io_select" = "yes" -a "$x_io_backend" = "none"; then + # we'll use select, when available and no "better" + # interface has been detected ... + x_io_backend="select()" + fi + fi +fi + +if test "$x_io_backend" = "none"; then + AC_MSG_ERROR([No useable IO API activated/found!?]) +fi + +# use SSL? + +AC_ARG_WITH(openssl, + AS_HELP_STRING([--with-openssl], + [enable SSL support using OpenSSL]), + [ if test "$withval" != "no"; then + if test "$withval" != "yes"; then + CFLAGS="-I$withval/include $CFLAGS" + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + fi + AC_CHECK_LIB(crypto, BIO_s_mem) + AC_CHECK_LIB(ssl, SSL_library_init) + AC_CHECK_FUNCS(SSL_library_init, x_ssl_openssl=yes, + AC_MSG_ERROR([Can't enable openssl]) + ) + fi + ] +) + +AC_ARG_WITH(gnutls, + AS_HELP_STRING([--with-gnutls], + [enable SSL support using gnutls]), + [ if test "$withval" != "no"; then + if test "$withval" != "yes"; then + CFLAGS="-I$withval/include $CFLAGS" + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + fi + AC_CHECK_LIB(gnutls, gnutls_global_init) + AC_CHECK_FUNCS(gnutls_global_init, x_ssl_gnutls=yes, + AC_MSG_ERROR([Can't enable gnutls]) + ) + fi + ] +) + +x_ssl_lib="no" +if test "$x_ssl_gnutls" = "yes"; then + if test "$x_ssl_openssl" = "yes";then + AC_MSG_ERROR([Cannot enable both gnutls and openssl]) + fi + x_ssl_lib=gnutls +fi +if test "$x_ssl_openssl" = "yes"; then + x_ssl_lib=openssl +fi + +# use TCP wrappers? + +x_tcpwrap_on=no +AC_ARG_WITH(tcp-wrappers, + AS_HELP_STRING([--with-tcp-wrappers], + [enable TCP wrappers support]), + [ if test "$withval" != "no"; then + if test "$withval" != "yes"; then + CFLAGS="-I$withval/include $CFLAGS" + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + fi + AC_MSG_CHECKING(for hosts_access) + LIBS="-lwrap $LIBS" + AC_TRY_LINK([ +#include +int allow_severity = 0; +int deny_severity = 0; + ],[ + tcpd_warn("link test"); + ],[ + AC_MSG_RESULT(yes) + AC_DEFINE(TCPWRAP, 1) + x_tcpwrap_on=yes + ],[ + AC_MSG_RESULT(no) + AC_MSG_ERROR([Can't enable TCP wrappers!]) + ]) + fi + ] +) + +# do IDENT requests using libident? + +x_identauth_on=no +AC_ARG_WITH(ident, + AS_HELP_STRING([--with-ident], + [enable "IDENT" ("AUTH") protocol support]), + [ if test "$withval" != "no"; then + if test "$withval" != "yes"; then + CFLAGS="-I$withval/include $CFLAGS" + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + fi + AC_CHECK_LIB(ident, ident_id) + AC_CHECK_FUNCS(ident_id, x_identauth_on=yes, + AC_MSG_ERROR([Can't enable IDENT support!]) + ) + fi + ] +) +if test "$x_identauth_on" = "yes"; then + AC_DEFINE(IDENTAUTH, 1) + AC_CHECK_HEADERS(ident.h,,AC_MSG_ERROR([required C header missing!])) +fi + +# compile in PAM support? + +x_pam_on=no +AC_ARG_WITH(pam, + AS_HELP_STRING([--with-pam], + [enable user authentication using PAM]), + [ if test "$withval" != "no"; then + if test "$withval" != "yes"; then + CFLAGS="-I$withval/include $CFLAGS" + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + fi + AC_CHECK_LIB(pam, pam_authenticate) + AC_CHECK_FUNCS(pam_authenticate, x_pam_on=yes, + AC_MSG_ERROR([Can't enable PAM support!]) + ) + fi + ] +) +if test "$x_pam_on" = "yes"; then + AC_DEFINE(PAM, 1) + AC_CHECK_HEADERS(security/pam_appl.h,pam_ok=yes) + if test "$pam_ok" != "yes"; then + AC_CHECK_HEADERS(pam/pam_appl.h,pam_ok=yes, + AC_MSG_ERROR([required C header missing!])) + fi +fi + +# compile in IRC+ protocol support? + +x_ircplus_on=yes +AC_ARG_ENABLE(ircplus, + AS_HELP_STRING([--disable-ircplus], + [disable IRC+ protocol]), + if test "$enableval" = "no"; then x_ircplus_on=no; fi +) +if test "$x_ircplus_on" = "yes"; then + AC_DEFINE(IRCPLUS, 1) + + # Compile in iconv support? + # We only check for it when IRC+ is enabled, because the IRC+ command + # CHARCONV is the only function depending on it. + x_iconv_on=no + AC_ARG_WITH(iconv, + [ --with-iconv enable character conversation using libiconv], + [ if test "$withval" != "no"; then + if test "$withval" != "yes"; then + CFLAGS="-I$withval/include $CFLAGS" + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + fi + AC_CHECK_LIB(iconv, iconv_open) + AC_CHECK_FUNCS(iconv_open, x_iconv_on=yes, + AC_MSG_ERROR([Can't enable libiconv support!]) + ) + fi + ] + ) + if test "$x_iconv_on" = "yes"; then + AC_DEFINE(ICONV, 1) + fi +fi + +# enable support for IPv6? +x_ipv6_on=no +AC_ARG_ENABLE(ipv6, + AS_HELP_STRING([--enable-ipv6], + [enable IPv6 protocol support]), + if test "$enableval" = "yes"; then x_ipv6_on=yes; fi +) +if test "$x_ipv6_on" = "yes"; then + # getaddrinfo() and getnameinfo() are optional when not compiling + # with IPv6 support, but are required for IPv6 to work! + 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 +AC_ARG_ENABLE(sniffer, + AS_HELP_STRING([--enable-sniffer], + [enable IRC traffic sniffer (enables debug mode)]), + if test "$enableval" = "yes"; then + AC_DEFINE(SNIFFER, 1) + x_sniffer_on=yes; x_debug_on=yes + fi +) + +# enable additional debugging code? + +AC_ARG_ENABLE(debug, + AS_HELP_STRING([--enable-debug], + [show additional debug output]), + if test "$enableval" = "yes"; then x_debug_on=yes; fi +) +if test "$x_debug_on" = "yes"; then + AC_DEFINE(DEBUG, 1) + test "$GCC" = "yes" && CFLAGS="-pedantic $CFLAGS" + AC_CHECK_FUNCS(mtrace) +fi + +# enable "strict RFC rules"? + +x_strict_rfc_on=no +AC_ARG_ENABLE(strict-rfc, + AS_HELP_STRING([--enable-strict-rfc], + [strict RFC conformance -- may break clients!]), + if test "$enableval" = "yes"; then + AC_DEFINE(STRICT_RFC, 1) + x_strict_rfc_on=yes + fi +) + +# -- Definitions -- + +AC_DEFINE_UNQUOTED(HOST_CPU, "$host_cpu" ) +AC_DEFINE_UNQUOTED(HOST_VENDOR, "$host_vendor" ) +AC_DEFINE_UNQUOTED(HOST_OS, "$host_os" ) + +# Add additional CFLAGS, eventually specified on the command line, but after +# running this configure script. Useful for "-Werror" for example. +test -n "$CFLAGS_END" && CFLAGS="$CFLAGS $CFLAGS_END" + +# -- Generate files -- + +AC_CONFIG_FILES([ \ + Makefile \ + contrib/Debian/Makefile \ + contrib/MacOSX/Makefile \ + contrib/MacOSX/ngIRCd.pmdoc/Makefile \ + contrib/MacOSX/ngIRCd.xcodeproj/Makefile \ + contrib/Makefile \ + doc/Makefile \ + doc/src/Makefile \ + man/Makefile \ + src/ipaddr/Makefile \ + src/Makefile \ + src/ngircd/Makefile \ + src/portab/Makefile \ + src/testsuite/Makefile \ + src/tool/Makefile \ +]) + +AC_OUTPUT + +type dpkg >/dev/null 2>&1 +if test $? -eq 0; then + # Generate debian/ link if the dpkg command exists + # (read: if we are running on a debian compatible system) + echo "creating Debian-specific links ..." + test -f debian/rules || ln -s contrib/Debian debian +fi + +# -- Result -- + +echo +echo "ngIRCd $PACKAGE_VERSION has been configured with the following options:" +echo + +# Someone please show me a better way :) [borrowed by OpenSSH] +B=`eval echo ${bindir}` ; B=`eval echo ${B}` +S=`eval echo ${sbindir}` ; S=`eval echo ${S}` +C=`eval echo ${sysconfdir}` ; C=`eval echo ${C}` +M=`eval echo ${mandir}` ; M=`eval echo ${M}` +D=`eval echo ${docdir}` ; D=`eval echo ${D}` + +echo " Host: ${host}" +echo " Compiler: ${CC}" +test -n "$CFLAGS" && echo " Compiler flags: ${CFLAGS}" +test -n "$CPPFLAGS" && echo " Preprocessor flags: ${CPPFLAGS}" +test -n "$LDFLAGS" && echo " Linker flags: ${LDFLAGS}" +test -n "$LIBS" && echo " Libraries: ${LIBS}" +echo +echo " 'ngircd' binary: $S" +echo " Configuration file: $C" +echo " Manual pages: $M" +echo " Documentation: $D" +echo + +echo $ECHO_N " Syslog support: $ECHO_C" +test "$x_syslog_on" = "yes" \ + && echo $ECHO_N "yes $ECHO_C" \ + || echo $ECHO_N "no $ECHO_C" +echo $ECHO_N " Enable debug code: $ECHO_C" +test "$x_debug_on" = "yes" \ + && echo "yes" \ + || echo "no" + +echo $ECHO_N " zlib compression: $ECHO_C" +test "$x_zlib_on" = "yes" \ + && echo $ECHO_N "yes $ECHO_C" \ + || echo $ECHO_N "no $ECHO_C" +echo $ECHO_N " IRC sniffer: $ECHO_C" +test "$x_sniffer_on" = "yes" \ + && echo "yes" \ + || echo "no" + +echo $ECHO_N " Use TCP Wrappers: $ECHO_C" +test "$x_tcpwrap_on" = "yes" \ + && echo $ECHO_N "yes $ECHO_C" \ + || echo $ECHO_N "no $ECHO_C" +echo $ECHO_N " Strict RFC mode: $ECHO_C" +test "$x_strict_rfc_on" = "yes" \ + && echo "yes" \ + || echo "no" + +echo $ECHO_N " IDENT support: $ECHO_C" +test "$x_identauth_on" = "yes" \ + && echo $ECHO_N "yes $ECHO_C" \ + || echo $ECHO_N "no $ECHO_C" +echo $ECHO_N " IRC+ protocol: $ECHO_C" +test "$x_ircplus_on" = "yes" \ + && echo "yes" \ + || echo "no" + +echo $ECHO_N " IPv6 protocol: $ECHO_C" +test "$x_ipv6_on" = "yes" \ + && echo $ECHO_N "yes $ECHO_C" \ + || echo $ECHO_N "no $ECHO_C" +echo $ECHO_N " I/O backend: $ECHO_C" + echo "\"$x_io_backend\"" + +echo $ECHO_N " PAM support: $ECHO_C" +test "$x_pam_on" = "yes" \ + && echo $ECHO_N "yes $ECHO_C" \ + || echo $ECHO_N "no $ECHO_C" +echo $ECHO_N " SSL support: $ECHO_C" +echo "$x_ssl_lib" + +echo $ECHO_N " libiconv support: $ECHO_C" + echo "$x_iconv_on" + +echo + +if ! grep "^AUTOMAKE_OPTIONS = ../portab/ansi2knr" src/ngircd/Makefile.am >/dev/null 2>&1; then + echo "WARNING:" + echo "This GNU automake generated build system does not support \"de-ANSI-fication\"," + echo "therefore don't use it to generate \"official\" distribution archives!" + echo "(Most probably you want to use GNU automake 1.11.x for this purpose ...)" + echo +fi + +# -eof- diff --git a/contrib/Anope/0001-Revert-Removed-ngircd.patch b/contrib/Anope/0001-Revert-Removed-ngircd.patch deleted file mode 100644 index efed0ad..0000000 --- a/contrib/Anope/0001-Revert-Removed-ngircd.patch +++ /dev/null @@ -1,496 +0,0 @@ -From bc5023fdba8091ab7eee29fe0deeca6843159743 Mon Sep 17 00:00:00 2001 -From: Alexander Barton -Date: Mon, 16 May 2011 18:23:01 +0200 -Subject: [PATCH 1/2] Revert "Removed ngircd as we've decided not to support it at this time" - -This reverts commit 605b5d57171d2f0fac56ee2ee3e1b1bbdadeb24f and re-enables -the ngIRCd protocol module for Anope. ---- - modules/protocol/ngircd.cpp | 475 +++++++++++++++++++++++++++++++++++++++++++ - 1 files changed, 475 insertions(+), 0 deletions(-) - create mode 100644 modules/protocol/ngircd.cpp - -diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp -new file mode 100644 -index 0000000..6e1f21f ---- /dev/null -+++ b/modules/protocol/ngircd.cpp -@@ -0,0 +1,475 @@ -+/* ngIRCd IRCD functions -+ * -+ * (C) 2003-2011 Anope Team -+ * Contact us at team@anope.org -+ * -+ * Please read COPYING and README for further details. -+ * -+ * Based on the original code of Epona by Lara. -+ * Based on the original code of Services by Andy Church. -+ */ -+ -+#include "services.h" -+#include "modules.h" -+ -+IRCDVar myIrcd[] = { -+ {"ngIRCd", /* ircd name */ -+ "+oi", /* Modes used by pseudoclients */ -+ 0, /* SVSNICK */ -+ 0, /* Vhost */ -+ 0, /* Supports SNlines */ -+ 0, /* Supports SQlines */ -+ 0, /* Supports SZlines */ -+ 0, /* Join 2 Message */ -+ 0, /* Chan SQlines */ -+ 1, /* Quit on Kill */ -+ 0, /* vidents */ -+ 0, /* svshold */ -+ 0, /* time stamp on mode */ -+ 0, /* UMODE */ -+ 0, /* O:LINE */ -+ 0, /* No Knock requires +i */ -+ 0, /* Can remove User Channel Modes with SVSMODE */ -+ 0, /* Sglines are not enforced until user reconnects */ -+ 0, /* ts6 */ -+ "$", /* TLD Prefix for Global */ -+ 20, /* Max number of modes we can send per line */ -+ 0, /* IRCd sends a SSL users certificate fingerprint */ -+ } -+ , -+ {NULL} -+}; -+ -+/* PASS */ -+class ngIRCdProto : public IRCDProto -+{ -+ void SendAkill(User *u, const XLine *x) -+ { -+ if (SGLine && u == NULL) -+ for (Anope::insensitive_map::iterator it = UserListByNick.begin(); it != UserListByNick.end();) -+ { -+ u = it->second; -+ ++it; -+ if (SGLine->Check(u) != NULL) -+ break; -+ } -+ } -+ -+ void SendAkillDel(const XLine*) { } -+ -+ void SendGlobopsInternal(const BotInfo *source, const Anope::string &buf) -+ { -+ send_cmd(source ? source->nick : Config->ServerName, "WALLOPS :%s", buf.c_str()); -+ } -+ -+ void SendJoin(BotInfo *user, Channel *c, const ChannelStatus *status) -+ { -+ send_cmd(user->nick, "JOIN %s", c->name.c_str()); -+ if (status) -+ for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) -+ if (status->HasFlag(ModeManager::ChannelModes[i]->Name)) -+ c->SetMode(user, ModeManager::ChannelModes[i], user->nick, false); -+ } -+ -+ void SendSVSKillInternal(const BotInfo *source, const User *user, const Anope::string &buf) -+ { -+ send_cmd(source ? source->nick : Config->ServerName, "KILL %s :%s", user->nick.c_str(), buf.c_str()); -+ } -+ -+ /* SERVER name hop descript */ -+ void SendServer(const Server *server) -+ { -+ send_cmd("", "SERVER %s %d :%s", server->GetName().c_str(), server->GetHops(), server->GetDescription().c_str()); -+ } -+ -+ void SendConnect() -+ { -+ send_cmd("", "PASS %s 0210-IRC+ Anope|%s:CLHSo P", uplink_server->password.c_str(), Anope::VersionShort().c_str()); -+ /* Make myself known to myself in the serverlist */ -+ SendServer(Me); -+ /* finish the enhanced server handshake and register the connection */ -+ this->SendNumeric(Config->ServerName, 376, "*", ":End of MOTD command"); -+ } -+ -+ // Received: :dev.anope.de NICK DukeP 1 ~DukePyro p57ABF9C9.dip.t-dialin.net 1 +i :DukePyrolator -+ void SendClientIntroduction(const User *u, const Anope::string &modes) -+ { -+ EnforceQlinedNick(u->nick, ""); -+ send_cmd(Config->ServerName, "NICK %s 1 %s %s 1 %s :%s", u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str(), modes.c_str(), u->realname.c_str()); -+ } -+ -+ void SendPartInternal(const BotInfo *bi, const Channel *chan, const Anope::string &buf) -+ { -+ if (!buf.empty()) -+ send_cmd(bi->nick, "PART %s :%s", chan->name.c_str(), buf.c_str()); -+ else -+ send_cmd(bi->nick, "PART %s", chan->name.c_str()); -+ } -+ -+ void SendModeInternal(const BotInfo *bi, const Channel *dest, const Anope::string &buf) -+ { -+ send_cmd(bi ? bi->nick : Config->ServerName, "MODE %s %s", dest->name.c_str(), buf.c_str()); -+ } -+ -+ void SendModeInternal(const BotInfo *bi, const User *u, const Anope::string &buf) -+ { -+ send_cmd(bi ? bi->nick : Config->ServerName, "MODE %s %s", u->nick.c_str(), buf.c_str()); -+ } -+ -+ void SendKickInternal(const BotInfo *bi, const Channel *chan, const User *user, const Anope::string &buf) -+ { -+ if (!buf.empty()) -+ send_cmd(bi->nick, "KICK %s %s :%s", chan->name.c_str(), user->nick.c_str(), buf.c_str()); -+ else -+ send_cmd(bi->nick, "KICK %s %s", chan->name.c_str(), user->nick.c_str()); -+ } -+ -+ void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) -+ { -+ send_cmd(source ? source->nick : Config->s_ChanServ, "NOTICE @%s :%s", dest->name.c_str(), buf.c_str()); -+ } -+ -+ /* INVITE */ -+ void SendInvite(BotInfo *source, const Anope::string &chan, const Anope::string &nick) -+ { -+ send_cmd(source->nick, "INVITE %s %s", nick.c_str(), chan.c_str()); -+ } -+ -+ void SendChannel(Channel *c) -+ { -+ Anope::string mlock_modes = get_mlock_modes(c->ci, true); -+ if (mlock_modes.empty()) -+ mlock_modes = "+"; -+ send_cmd(Config->ServerName, "CHANINFO %s %s", c->name.c_str(), mlock_modes.c_str()); -+ } -+ void SendTopic(BotInfo *bi, Channel *c) -+ { -+ send_cmd(bi->nick, "TOPIC %s :%s", c->name.c_str(), c->topic.c_str()); -+ } -+}; -+ -+class ngIRCdIRCdMessage : public IRCdMessage -+{ -+ public: -+ bool OnSJoin(const Anope::string&, const std::vector&) { return false; } -+ -+ /* -+ * Received: :dev.anope.de MODE #anope +b *!*@*aol* -+ */ -+ bool OnMode(const Anope::string &source, const std::vector ¶ms) -+ { -+ if (params.size() < 2) -+ return true; -+ -+ Anope::string modes = params[1]; -+ for (unsigned i = 2; i < params.size(); ++i) -+ modes += " " + params[i]; -+ -+ if (params[0][0] == '#' || params[0][0] == '&') -+ do_cmode(source, params[0], modes, ""); -+ else -+ do_umode(params[0], params[1]); -+ -+ return true; -+ } -+ -+ /* -+ Received: :DukeP_ NICK :test2 -+ Received: :dev.anope.de NICK DukeP_ 1 ~DukePyro ip-2-201-236-154.web.vodafone.de 1 + :DukePyrolator -+ source = nickname on nickchange, servername on newuser -+ params[0] = nick -+ params[1] = -+ params[2] = username -+ params[3] = host -+ params[4] = -+ params[5] = modes -+ params[6] = info -+ */ -+ bool OnNick(const Anope::string &source, const std::vector ¶ms) -+ { -+ if (params.size() == 1) -+ { -+ // we have a nickchange -+ do_nick(source, params[0], "", "", "", "", Anope::CurTime, "", "", "", ""); -+ } -+ else if (params.size() == 7) -+ { -+ // a new user is connecting to the network -+ User *user = do_nick("", params[0], params[2], params[3], source, params[6], Anope::CurTime, "", "", "", params[5]); -+ if (user) -+ validate_user(user); -+ } -+ else -+ { -+ Log() << "Received NICK with invalid number of parameters. source = " << source << "param[0] = " << params[0] << "params.size() = " << params.size(); -+ } -+ return true; -+ } -+ -+ bool OnServer(const Anope::string &source, const std::vector ¶ms) -+ { -+ if (params.size() == 3) -+ do_server("", params[0], 0, params[2], params[1]); -+ else -+ do_server(source, params[0], params[1].is_pos_number_only() ? convertTo(params[1]) : 0, params[3], params[2]); -+ return true; -+ } -+ -+ bool OnTopic(const Anope::string &source, const std::vector ¶ms) -+ { -+ Channel *c = findchan(params[0]); -+ if (!c) -+ { -+ Log() << "TOPIC for nonexistant channel " << params[0]; -+ return true; -+ } -+ -+ c->ChangeTopicInternal(source, params[1]); -+ return true; -+ } -+ -+ /* -+ * <@po||ux> DukeP: RFC 2813, 4.2.1: the JOIN command on server-server links -+ * separates the modes ("o") with ASCII 7, not space. And you can't see ASCII 7. -+ * -+ * if a user joins a new channel, the ircd sends \7 -+ */ -+ bool OnJoin (const Anope::string &source, const std::vector ¶ms) -+ { -+ if (!params.empty()) -+ { -+ size_t pos = params[0].find('\7'); -+ if (pos != Anope::string::npos) -+ { -+ Anope::string channel = params[0].substr(0, pos); -+ Anope::string mode = '+' + params[0].substr(pos, params[0].length()) + " " + source; -+ do_join(source, channel, ""); -+ do_cmode(source, channel, mode, ""); -+ } -+ else -+ do_join(source, params[0], ""); -+ } -+ return true; -+ } -+}; -+ -+/* -+ * CHANINFO + -+ * CHANINFO + : -+ * CHANINFO + : -+ */ -+bool event_chaninfo(const Anope::string &source, const std::vector ¶ms) -+{ -+ -+ Channel *c = findchan(params[0]); -+ if (!c) -+ c = new Channel(params[0]); -+ -+ Anope::string modes = params[1]; -+ -+ if (params.size() == 3) -+ { -+ c->ChangeTopicInternal(source, params[2], Anope::CurTime); -+ } -+ else if (params.size() == 5) -+ { -+ for (size_t i = 0, end = params[1].length(); i < end; ++i) -+ { -+ switch(params[1][i]) -+ { -+ case 'k': -+ modes += " " + params[2]; -+ continue; -+ case 'l': -+ modes += " " + params[3]; -+ continue; -+ } -+ } -+ c->ChangeTopicInternal(source, params[4], Anope::CurTime); -+ } -+ -+ c->SetModesInternal(NULL, modes); -+ -+ return true; -+} -+ -+/* -+ * Received: :dev.anope.de NJOIN #test :DukeP2,@DukeP -+ */ -+bool event_njoin(const Anope::string &source, const std::vector ¶ms) -+{ -+ Channel *c = findchan(params[0]); -+ commasepstream sep(params[1]); -+ Anope::string buf; -+ -+ if (!c) -+ { -+ c = new Channel(params[0], Anope::CurTime); -+ c->SetFlag(CH_SYNCING); -+ } -+ -+ while (sep.GetToken(buf)) -+ { -+ std::list Status; -+ char ch; -+ -+ /* Get prefixes from the nick */ -+ while ((ch = ModeManager::GetStatusChar(buf[0]))) -+ { -+ buf.erase(buf.begin()); -+ ChannelMode *cm = ModeManager::FindChannelModeByChar(ch); -+ if (!cm) -+ { -+ Log() << "Received unknown mode prefix " << ch << " in NJOIN string."; -+ continue; -+ } -+ Status.push_back(cm); -+ } -+ User *u = finduser(buf); -+ if (!u) -+ { -+ Log(LOG_DEBUG) << "NJOIN for nonexistant user " << buf << " on " << c->name; -+ continue; -+ } -+ -+ EventReturn MOD_RESULT; -+ FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); -+ -+ /* Add the user to the Channel */ -+ c->JoinUser(u); -+ -+ /* Update their status internally on the channel -+ * This will enforce secureops etc on the user -+ */ -+ for (std::list::iterator it = Status.begin(), it_end = Status.end(); it != it_end; ++it) -+ c->SetModeInternal(*it, buf); -+ /* Now set whatever modes this user is allowed to have on the channel */ -+ chan_set_correct_modes(u, c, 1); -+ -+ /* Check to see if modules want the user to join, if they do -+ * check to see if they are allowed to join (CheckKick will kick/ban them) -+ * Don't trigger OnJoinChannel event then as the user will be destroyed -+ */ -+ if (MOD_RESULT != EVENT_STOP && c->ci && c->ci->CheckKick(u)) -+ continue; -+ -+ FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); -+ } /* while */ -+ -+ if (c->HasFlag(CH_SYNCING)) -+ { -+ c->UnsetFlag(CH_SYNCING); -+ c->Sync(); -+ } -+ -+ return true; -+} -+ -+bool event_kick(const Anope::string &source, const std::vector ¶ms) -+{ -+ if (params.size() > 2) -+ do_kick(source, params[0], params[1], params[2]); -+ return true; -+} -+ -+bool event_pass(const Anope::string &source, const std::vector ¶ms) -+{ -+ return true; -+} -+ -+bool event_005(const Anope::string &source, const std::vector ¶ms) -+{ -+ size_t pos; -+ Anope::string name, data; -+ for (unsigned i = 0, end = params.size(); i < end; ++i) -+ { -+ pos = params[i].find('='); -+ if (pos != Anope::string::npos) -+ { -+ name = params[i].substr(0, pos); -+ data = params[i].substr(pos+1, params[i].length()); -+ if (name == "NICKLEN") -+ { -+ unsigned newlen = convertTo(data); -+ if (Config->NickLen != newlen) -+ { -+ Log() << "Config->NickLen changed from " << Config->NickLen << " to " << newlen; -+ Config->NickLen = newlen; -+ } -+ } -+ } -+ } -+ return true; -+} -+ -+bool event_442(const Anope::string &source, const std::vector ¶ms) -+{ -+ return true; -+} -+ -+bool event_376(const Anope::string &source, const std::vector ¶ms) -+{ -+ return true; -+} -+ -+ -+class ProtongIRCd : public Module -+{ -+ Message message_kick, message_pass, message_njoin, message_chaninfo, message_005, -+ message_442, message_376; -+ -+ ngIRCdProto ircd_proto; -+ ngIRCdIRCdMessage ircd_message; -+ -+ void AddModes() -+ { -+ /* Add user modes */ -+ ModeManager::AddUserMode(new UserMode(UMODE_ADMIN, 'a')); -+ ModeManager::AddUserMode(new UserMode(UMODE_INVIS, 'i')); -+ ModeManager::AddUserMode(new UserMode(UMODE_OPER, 'o')); -+ ModeManager::AddUserMode(new UserMode(UMODE_RESTRICTED, 'r')); -+ ModeManager::AddUserMode(new UserMode(UMODE_SNOMASK, 's')); -+ ModeManager::AddUserMode(new UserMode(UMODE_WALLOPS, 'w')); -+ ModeManager::AddUserMode(new UserMode(UMODE_CLOAK, 'x')); -+ -+ /* b/e/I */ -+ ModeManager::AddChannelMode(new ChannelModeBan(CMODE_BAN, 'b')); -+ ModeManager::AddChannelMode(new ChannelModeList(CMODE_INVITEOVERRIDE, 'I')); -+ -+ /* v/h/o/a/q */ -+ ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', '+')); -+ ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, 'o', '@')); -+ -+ /* Add channel modes */ -+ // channel modes: biIklmnoPstvz -+ ModeManager::AddChannelMode(new ChannelMode(CMODE_INVITE, 'i')); -+ ModeManager::AddChannelMode(new ChannelModeKey('k')); -+ ModeManager::AddChannelMode(new ChannelModeParam(CMODE_LIMIT, 'l')); -+ ModeManager::AddChannelMode(new ChannelMode(CMODE_MODERATED, 'm')); -+ ModeManager::AddChannelMode(new ChannelMode(CMODE_NOEXTERNAL, 'n')); -+ ModeManager::AddChannelMode(new ChannelMode(CMODE_PERM, 'P')); -+ ModeManager::AddChannelMode(new ChannelMode(CMODE_SECRET, 's')); -+ ModeManager::AddChannelMode(new ChannelMode(CMODE_TOPIC, 't')); -+ ModeManager::AddChannelMode(new ChannelMode(CMODE_SSL, 'z')); -+ } -+ -+ public: -+ ProtongIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), -+ message_kick("KICK", event_kick), message_pass("PASS", event_pass), -+ message_njoin("NJOIN", event_njoin), message_chaninfo("CHANINFO", event_chaninfo), -+ message_005("005", event_005), message_442("442", event_442), message_376("376", event_376) -+ { -+ this->SetAuthor("Anope"); -+ this->SetType(PROTOCOL); -+ -+ Capab.SetFlag(CAPAB_QS); -+ -+ pmodule_ircd_var(myIrcd); -+ pmodule_ircd_proto(&this->ircd_proto); -+ pmodule_ircd_message(&this->ircd_message); -+ -+ this->AddModes(); -+ } -+}; -+ -+MODULE_INIT(ProtongIRCd) --- -1.7.2.5 - diff --git a/contrib/Anope/0002-ngircd-whitespace-fixes.patch b/contrib/Anope/0002-ngircd-whitespace-fixes.patch deleted file mode 100644 index 60356a8..0000000 --- a/contrib/Anope/0002-ngircd-whitespace-fixes.patch +++ /dev/null @@ -1,60 +0,0 @@ -From 1ea1dd2095e63cef34edbebb729edc687f410a96 Mon Sep 17 00:00:00 2001 -From: Alexander Barton -Date: Mon, 16 May 2011 18:26:56 +0200 -Subject: [PATCH 2/2] ngircd: whitespace fixes - ---- - modules/protocol/ngircd.cpp | 12 ++++++------ - 1 files changed, 6 insertions(+), 6 deletions(-) - -diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp -index 6e1f21f..e546d05 100644 ---- a/modules/protocol/ngircd.cpp -+++ b/modules/protocol/ngircd.cpp -@@ -266,11 +266,11 @@ bool event_chaninfo(const Anope::string &source, const std::vectorChangeTopicInternal(source, params[2], Anope::CurTime); -- } -+ } - else if (params.size() == 5) - { - for (size_t i = 0, end = params[1].length(); i < end; ++i) -@@ -307,7 +307,7 @@ bool event_njoin(const Anope::string &source, const std::vector & - c = new Channel(params[0], Anope::CurTime); - c->SetFlag(CH_SYNCING); - } -- -+ - while (sep.GetToken(buf)) - { - std::list Status; -@@ -415,9 +415,9 @@ bool event_376(const Anope::string &source, const std::vector &pa - - class ProtongIRCd : public Module - { -- Message message_kick, message_pass, message_njoin, message_chaninfo, message_005, -+ Message message_kick, message_pass, message_njoin, message_chaninfo, message_005, - message_442, message_376; -- -+ - ngIRCdProto ircd_proto; - ngIRCdIRCdMessage ircd_message; - -@@ -461,7 +461,7 @@ class ProtongIRCd : public Module - { - this->SetAuthor("Anope"); - this->SetType(PROTOCOL); -- -+ - Capab.SetFlag(CAPAB_QS); - - pmodule_ircd_var(myIrcd); --- -1.7.2.5 - diff --git a/contrib/Anope/0003-Update-ngIRCd-protocol-module-for-current-Anope-1.9.patch b/contrib/Anope/0003-Update-ngIRCd-protocol-module-for-current-Anope-1.9.patch deleted file mode 100644 index c4ea0e6..0000000 --- a/contrib/Anope/0003-Update-ngIRCd-protocol-module-for-current-Anope-1.9.patch +++ /dev/null @@ -1,128 +0,0 @@ -From d8eddbeaadc7d161865b5342d59748b80266533c Mon Sep 17 00:00:00 2001 -From: DukePyrolator -Date: Mon, 22 Aug 2011 14:53:37 +0200 -Subject: [PATCH 03/16] Update ngIRCd protocol module for current Anope 1.9 - GIT - ---- - modules/protocol/ngircd.cpp | 37 ++++++++++++++++++------------------- - 1 files changed, 18 insertions(+), 19 deletions(-) - -diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp -index e546d05..790b8f4 100644 ---- a/modules/protocol/ngircd.cpp -+++ b/modules/protocol/ngircd.cpp -@@ -11,6 +11,8 @@ - - #include "services.h" - #include "modules.h" -+#include "nickserv.h" -+#include "oper.h" - - IRCDVar myIrcd[] = { - {"ngIRCd", /* ircd name */ -@@ -45,14 +47,7 @@ class ngIRCdProto : public IRCDProto - { - void SendAkill(User *u, const XLine *x) - { -- if (SGLine && u == NULL) -- for (Anope::insensitive_map::iterator it = UserListByNick.begin(); it != UserListByNick.end();) -- { -- u = it->second; -- ++it; -- if (SGLine->Check(u) != NULL) -- break; -- } -+ // TODO: ADD SOME CODE - } - - void SendAkillDel(const XLine*) { } -@@ -62,13 +57,16 @@ class ngIRCdProto : public IRCDProto - send_cmd(source ? source->nick : Config->ServerName, "WALLOPS :%s", buf.c_str()); - } - -- void SendJoin(BotInfo *user, Channel *c, const ChannelStatus *status) -+ void SendJoin(User *user, Channel *c, const ChannelStatus *status) - { - send_cmd(user->nick, "JOIN %s", c->name.c_str()); - if (status) -+ { -+ BotInfo *setter = findbot(user->nick); - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) - if (status->HasFlag(ModeManager::ChannelModes[i]->Name)) -- c->SetMode(user, ModeManager::ChannelModes[i], user->nick, false); -+ c->SetMode(setter, ModeManager::ChannelModes[i], user->nick, false); -+ } - } - - void SendSVSKillInternal(const BotInfo *source, const User *user, const Anope::string &buf) -@@ -84,7 +82,7 @@ class ngIRCdProto : public IRCDProto - - void SendConnect() - { -- send_cmd("", "PASS %s 0210-IRC+ Anope|%s:CLHSo P", uplink_server->password.c_str(), Anope::VersionShort().c_str()); -+ send_cmd("", "PASS %s 0210-IRC+ Anope|%s:CLHSo P", Config->Uplinks[CurrentUplink]->password.c_str(), Anope::VersionShort().c_str()); - /* Make myself known to myself in the serverlist */ - SendServer(Me); - /* finish the enhanced server handshake and register the connection */ -@@ -92,9 +90,11 @@ class ngIRCdProto : public IRCDProto - } - - // Received: :dev.anope.de NICK DukeP 1 ~DukePyro p57ABF9C9.dip.t-dialin.net 1 +i :DukePyrolator -- void SendClientIntroduction(const User *u, const Anope::string &modes) -+ void SendClientIntroduction(const User *u) - { -- EnforceQlinedNick(u->nick, ""); -+ Anope::string modes = "+" + u->GetModes(); -+ XLine x(u->nick, "Reserved for services"); -+ ircdproto->SendSQLine(NULL, &x); - send_cmd(Config->ServerName, "NICK %s 1 %s %s 1 %s :%s", u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str(), modes.c_str(), u->realname.c_str()); - } - -@@ -126,7 +126,7 @@ class ngIRCdProto : public IRCDProto - - void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) - { -- send_cmd(source ? source->nick : Config->s_ChanServ, "NOTICE @%s :%s", dest->name.c_str(), buf.c_str()); -+ send_cmd(source->nick, "NOTICE @%s :%s", dest->name.c_str(), buf.c_str()); - } - - /* INVITE */ -@@ -196,8 +196,8 @@ class ngIRCdIRCdMessage : public IRCdMessage - { - // a new user is connecting to the network - User *user = do_nick("", params[0], params[2], params[3], source, params[6], Anope::CurTime, "", "", "", params[5]); -- if (user) -- validate_user(user); -+ if (user && nickserv) -+ nickserv->Validate(user); - } - else - { -@@ -433,7 +433,7 @@ class ProtongIRCd : public Module - ModeManager::AddUserMode(new UserMode(UMODE_CLOAK, 'x')); - - /* b/e/I */ -- ModeManager::AddChannelMode(new ChannelModeBan(CMODE_BAN, 'b')); -+ ModeManager::AddChannelMode(new ChannelModeList(CMODE_BAN, 'b')); - ModeManager::AddChannelMode(new ChannelModeList(CMODE_INVITEOVERRIDE, 'I')); - - /* v/h/o/a/q */ -@@ -454,13 +454,12 @@ class ProtongIRCd : public Module - } - - public: -- ProtongIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator), -+ ProtongIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_kick("KICK", event_kick), message_pass("PASS", event_pass), - message_njoin("NJOIN", event_njoin), message_chaninfo("CHANINFO", event_chaninfo), - message_005("005", event_005), message_442("442", event_442), message_376("376", event_376) - { - this->SetAuthor("Anope"); -- this->SetType(PROTOCOL); - - Capab.SetFlag(CAPAB_QS); - --- -1.7.8.3 - diff --git a/contrib/Anope/0004-ngircd-Do-PING-PONG-on-server-burst-to-sync-servers.patch b/contrib/Anope/0004-ngircd-Do-PING-PONG-on-server-burst-to-sync-servers.patch deleted file mode 100644 index 0aec3e9..0000000 --- a/contrib/Anope/0004-ngircd-Do-PING-PONG-on-server-burst-to-sync-servers.patch +++ /dev/null @@ -1,93 +0,0 @@ -From 88b2b14a76b8ee053b1f6ea64139350260590043 Mon Sep 17 00:00:00 2001 -From: DukePyrolator -Date: Mon, 22 Aug 2011 14:55:07 +0200 -Subject: [PATCH 04/16] ngircd: Do PING-PONG on server burst to "sync servers" - -Imagine we had three servers, A, B & C linked like so: A<->B<->C: - -If Anope is linked to A and B splits from A and then reconnects B -introduces itself, introduces C, sends EOS for C, introduces B's clients -introduces C's clients, sends EOS for B. This causes all of C's clients -to be introduced with their server "not syncing". - -We now send a PING immediately when receiving a new server and then -finish sync once we get a pong back from that server. ---- - modules/protocol/ngircd.cpp | 28 ++++++++++++++++++++++++++-- - 1 files changed, 26 insertions(+), 2 deletions(-) - -diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp -index 790b8f4..89aecfd 100644 ---- a/modules/protocol/ngircd.cpp -+++ b/modules/protocol/ngircd.cpp -@@ -108,11 +108,13 @@ class ngIRCdProto : public IRCDProto - - void SendModeInternal(const BotInfo *bi, const Channel *dest, const Anope::string &buf) - { -+Log(LOG_DEBUG) << "SendModeInternal 1"; - send_cmd(bi ? bi->nick : Config->ServerName, "MODE %s %s", dest->name.c_str(), buf.c_str()); - } - - void SendModeInternal(const BotInfo *bi, const User *u, const Anope::string &buf) - { -+Log(LOG_DEBUG) << "SendModeInternal 2"; - send_cmd(bi ? bi->nick : Config->ServerName, "MODE %s %s", u->nick.c_str(), buf.c_str()); - } - -@@ -212,6 +214,8 @@ class ngIRCdIRCdMessage : public IRCdMessage - do_server("", params[0], 0, params[2], params[1]); - else - do_server(source, params[0], params[1].is_pos_number_only() ? convertTo(params[1]) : 0, params[3], params[2]); -+ -+ ircdproto->SendPing(Config->ServerName, params[0]); - return true; - } - -@@ -253,6 +257,25 @@ class ngIRCdIRCdMessage : public IRCdMessage - } - }; - -+/** This is here because: -+ * -+ * If we had three servers, A, B & C linked like so: A<->B<->C -+ * If Anope is linked to A and B splits from A and then reconnects -+ * B introduces itself, introduces C, sends EOS for C, introduces Bs clients -+ * introduces Cs clients, sends EOS for B. This causes all of Cs clients to be introduced -+ * with their server "not syncing". We now send a PING immediately when receiving a new server -+ * and then finish sync once we get a pong back from that server. -+ */ -+bool event_pong(const Anope::string &source, const std::vector ¶ms) -+{ -+ Server *s = Server::Find(source); -+ if (s && !s->IsSynced()) -+ s->Sync(false); -+ return true; -+} -+ -+ -+ - /* - * CHANINFO + - * CHANINFO + : -@@ -416,7 +439,7 @@ bool event_376(const Anope::string &source, const std::vector &pa - class ProtongIRCd : public Module - { - Message message_kick, message_pass, message_njoin, message_chaninfo, message_005, -- message_442, message_376; -+ message_442, message_376, message_pong; - - ngIRCdProto ircd_proto; - ngIRCdIRCdMessage ircd_message; -@@ -457,7 +480,8 @@ class ProtongIRCd : public Module - ProtongIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL), - message_kick("KICK", event_kick), message_pass("PASS", event_pass), - message_njoin("NJOIN", event_njoin), message_chaninfo("CHANINFO", event_chaninfo), -- message_005("005", event_005), message_442("442", event_442), message_376("376", event_376) -+ message_005("005", event_005), message_442("442", event_442), message_376("376", event_376), -+ message_pong("PONG", event_pong) - { - this->SetAuthor("Anope"); - --- -1.7.8.3 - diff --git a/contrib/Anope/0005-ngircd-always-prefix-modes-in-CHANINFO-with.patch b/contrib/Anope/0005-ngircd-always-prefix-modes-in-CHANINFO-with.patch deleted file mode 100644 index 27b7163..0000000 --- a/contrib/Anope/0005-ngircd-always-prefix-modes-in-CHANINFO-with.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 0d83f8f9ca0de651d664eca6f467f36df0417f7d Mon Sep 17 00:00:00 2001 -From: Alexander Barton -Date: Mon, 22 Aug 2011 14:59:49 +0200 -Subject: [PATCH 05/16] ngircd: always prefix modes in CHANINFO with "+" - ---- - modules/protocol/ngircd.cpp | 6 ++---- - 1 files changed, 2 insertions(+), 4 deletions(-) - -diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp -index 89aecfd..3e5beb3 100644 ---- a/modules/protocol/ngircd.cpp -+++ b/modules/protocol/ngircd.cpp -@@ -139,10 +139,8 @@ Log(LOG_DEBUG) << "SendModeInternal 2"; - - void SendChannel(Channel *c) - { -- Anope::string mlock_modes = get_mlock_modes(c->ci, true); -- if (mlock_modes.empty()) -- mlock_modes = "+"; -- send_cmd(Config->ServerName, "CHANINFO %s %s", c->name.c_str(), mlock_modes.c_str()); -+ Anope::string modes = c->GetModes(true, true); -+ send_cmd(Config->ServerName, "CHANINFO %s +%s", c->name.c_str(), modes.c_str()); - } - void SendTopic(BotInfo *bi, Channel *c) - { --- -1.7.8.3 - diff --git a/contrib/Anope/0006-ngircd-support-user-mode-R-and-channel-mode-R.patch b/contrib/Anope/0006-ngircd-support-user-mode-R-and-channel-mode-R.patch deleted file mode 100644 index 8038555..0000000 --- a/contrib/Anope/0006-ngircd-support-user-mode-R-and-channel-mode-R.patch +++ /dev/null @@ -1,47 +0,0 @@ -From 1914a36b83b1fc6b4678ef261a1a06eefab9a0ca Mon Sep 17 00:00:00 2001 -From: Alexander Barton -Date: Fri, 26 Aug 2011 17:51:37 +0200 -Subject: [PATCH 06/16] ngircd: support user mode "R" and channel mode "R" - ---- - modules/protocol/ngircd.cpp | 7 ++++--- - 1 files changed, 4 insertions(+), 3 deletions(-) - -diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp -index 3e5beb3..7f4186e 100644 ---- a/modules/protocol/ngircd.cpp -+++ b/modules/protocol/ngircd.cpp -@@ -449,26 +449,27 @@ class ProtongIRCd : public Module - ModeManager::AddUserMode(new UserMode(UMODE_INVIS, 'i')); - ModeManager::AddUserMode(new UserMode(UMODE_OPER, 'o')); - ModeManager::AddUserMode(new UserMode(UMODE_RESTRICTED, 'r')); -+ ModeManager::AddUserMode(new UserMode(UMODE_REGISTERED, 'R')); - ModeManager::AddUserMode(new UserMode(UMODE_SNOMASK, 's')); - ModeManager::AddUserMode(new UserMode(UMODE_WALLOPS, 'w')); - ModeManager::AddUserMode(new UserMode(UMODE_CLOAK, 'x')); - -- /* b/e/I */ -+ /* Add modes for ban and invite lists */ - ModeManager::AddChannelMode(new ChannelModeList(CMODE_BAN, 'b')); - ModeManager::AddChannelMode(new ChannelModeList(CMODE_INVITEOVERRIDE, 'I')); - -- /* v/h/o/a/q */ -+ /* Add channel user modes */ - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', '+')); - ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, 'o', '@')); - - /* Add channel modes */ -- // channel modes: biIklmnoPstvz - ModeManager::AddChannelMode(new ChannelMode(CMODE_INVITE, 'i')); - ModeManager::AddChannelMode(new ChannelModeKey('k')); - ModeManager::AddChannelMode(new ChannelModeParam(CMODE_LIMIT, 'l')); - ModeManager::AddChannelMode(new ChannelMode(CMODE_MODERATED, 'm')); - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOEXTERNAL, 'n')); - ModeManager::AddChannelMode(new ChannelMode(CMODE_PERM, 'P')); -+ ModeManager::AddChannelMode(new ChannelMode(CMODE_REGISTEREDONLY, 'R')); - ModeManager::AddChannelMode(new ChannelMode(CMODE_SECRET, 's')); - ModeManager::AddChannelMode(new ChannelMode(CMODE_TOPIC, 't')); - ModeManager::AddChannelMode(new ChannelMode(CMODE_SSL, 'z')); --- -1.7.8.3 - diff --git a/contrib/Anope/0007-ngircd-Fix-handling-of-JOIN-commands.patch b/contrib/Anope/0007-ngircd-Fix-handling-of-JOIN-commands.patch deleted file mode 100644 index f507499..0000000 --- a/contrib/Anope/0007-ngircd-Fix-handling-of-JOIN-commands.patch +++ /dev/null @@ -1,96 +0,0 @@ -From 4c9300ede35310ee5642f34e5ac227bd96fc7384 Mon Sep 17 00:00:00 2001 -From: DukePyrolator -Date: Sun, 4 Sep 2011 15:08:55 +0200 -Subject: [PATCH 07/16] ngircd: Fix handling of JOIN commands - ---- - modules/protocol/ngircd.cpp | 60 +++++++++++++++++++++++++++++++++++++++--- - 1 files changed, 55 insertions(+), 5 deletions(-) - -diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp -index 7f4186e..3024fdd 100644 ---- a/modules/protocol/ngircd.cpp -+++ b/modules/protocol/ngircd.cpp -@@ -240,16 +240,58 @@ class ngIRCdIRCdMessage : public IRCdMessage - { - if (!params.empty()) - { -+ Anope::string channel, mode; - size_t pos = params[0].find('\7'); - if (pos != Anope::string::npos) - { -- Anope::string channel = params[0].substr(0, pos); -- Anope::string mode = '+' + params[0].substr(pos, params[0].length()) + " " + source; -- do_join(source, channel, ""); -- do_cmode(source, channel, mode, ""); -+ channel = params[0].substr(0, pos); -+ mode = '+' + params[0].substr(pos+1, params[0].length()) + " " + source; - } - else -- do_join(source, params[0], ""); -+ channel = params[0]; -+ -+ Channel *c = findchan(channel); -+ -+ if (!c) -+ { -+ c = new Channel(channel, Anope::CurTime); -+ c->SetFlag(CH_SYNCING); -+ } -+ -+ User *u = finduser(source); -+ -+ if (!u) -+ { -+ Log(LOG_DEBUG) << "JOIN for nonexistant user " << source << " on " << channel; -+ return false; -+ } -+ -+ EventReturn MOD_RESULT; -+ FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c)); -+ -+ /* Add the user to the channel */ -+ c->JoinUser(u); -+ -+ /* set the usermodes to the channel */ -+ do_cmode(source, channel, mode, ""); -+ -+ /* Now set whatever modes this user is allowed to have on the channel */ -+ chan_set_correct_modes(u, c, 1); -+ -+ /* Check to see if modules want the user to join, if they do -+ * check to see if they are allowed to join (CheckKick will kick/ban them) -+ * Don't trigger OnJoinChannel event then as the user will be destroyed -+ */ -+ if (MOD_RESULT != EVENT_STOP && c->ci && c->ci->CheckKick(u)) -+ return false; -+ -+ FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c)); -+ -+ if (c->HasFlag(CH_SYNCING)) -+ { -+ c->UnsetFlag(CH_SYNCING); -+ c->Sync(); -+ } - } - return true; - } -@@ -491,7 +533,15 @@ class ProtongIRCd : public Module - pmodule_ircd_message(&this->ircd_message); - - this->AddModes(); -+ -+ ModuleManager::Attach(I_OnUserNickChange, this); - } -+ -+ void OnUserNickChange(User *u, const Anope::string &) -+ { -+ u->RemoveModeInternal(ModeManager::FindUserModeByName(UMODE_REGISTERED)); -+ } -+ - }; - - MODULE_INIT(ProtongIRCd) --- -1.7.8.3 - diff --git a/contrib/Anope/0008-ngircd-Allow-setting-modes-by-clients-on-burst.patch b/contrib/Anope/0008-ngircd-Allow-setting-modes-by-clients-on-burst.patch deleted file mode 100644 index eb2c214..0000000 --- a/contrib/Anope/0008-ngircd-Allow-setting-modes-by-clients-on-burst.patch +++ /dev/null @@ -1,38 +0,0 @@ -From d363ebd841ea7e1db3c62730023759d69520e0d8 Mon Sep 17 00:00:00 2001 -From: Alexander Barton -Date: Tue, 27 Sep 2011 15:08:09 +0200 -Subject: [PATCH 08/16] ngircd: Allow setting modes by clients on burst - -This change is required by commit 43201ead9575a for the ngIRCd protocol -module as well. ---- - modules/protocol/ngircd.cpp | 7 +++++-- - 1 files changed, 5 insertions(+), 2 deletions(-) - -diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp -index 3024fdd..2774168 100644 ---- a/modules/protocol/ngircd.cpp -+++ b/modules/protocol/ngircd.cpp -@@ -57,14 +57,17 @@ class ngIRCdProto : public IRCDProto - send_cmd(source ? source->nick : Config->ServerName, "WALLOPS :%s", buf.c_str()); - } - -- void SendJoin(User *user, Channel *c, const ChannelStatus *status) -+ void SendJoin(User *user, Channel *c, ChannelStatus *status) - { - send_cmd(user->nick, "JOIN %s", c->name.c_str()); - if (status) - { -+ ChannelStatus cs = *status; -+ status->ClearFlags(); -+ - BotInfo *setter = findbot(user->nick); - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) -- if (status->HasFlag(ModeManager::ChannelModes[i]->Name)) -+ if (cs.HasFlag(ModeManager::ChannelModes[i]->Name)) - c->SetMode(setter, ModeManager::ChannelModes[i], user->nick, false); - } - } --- -1.7.8.3 - diff --git a/contrib/Anope/0009-ngircd-Update-protocol-module-for-current-Anope-1.9.patch b/contrib/Anope/0009-ngircd-Update-protocol-module-for-current-Anope-1.9.patch deleted file mode 100644 index b6a003a..0000000 --- a/contrib/Anope/0009-ngircd-Update-protocol-module-for-current-Anope-1.9.patch +++ /dev/null @@ -1,143 +0,0 @@ -From e74a5303f2357f4a9915bb91038a2e326323db3c Mon Sep 17 00:00:00 2001 -From: Alexander Barton -Date: Fri, 25 Nov 2011 19:16:37 +0100 -Subject: [PATCH 09/16] ngircd: Update protocol module for current Anope 1.9 - GIT - -This changes are rquired by: - - - b14f5ea88: Fixed accidentally clearing botmodes when joins are sent - - cef3eb78d: Remove send_cmd and replace it with a stringstream - - ddc3c2f38: Added options:nonicknameownership config option ---- - modules/protocol/ngircd.cpp | 54 ++++++++++++++++++++++-------------------- - 1 files changed, 28 insertions(+), 26 deletions(-) - -diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp -index 2774168..55cb8d7 100644 ---- a/modules/protocol/ngircd.cpp -+++ b/modules/protocol/ngircd.cpp -@@ -54,16 +54,22 @@ class ngIRCdProto : public IRCDProto - - void SendGlobopsInternal(const BotInfo *source, const Anope::string &buf) - { -- send_cmd(source ? source->nick : Config->ServerName, "WALLOPS :%s", buf.c_str()); -+ UplinkSocket::Message(source ? source->nick : Config->ServerName) << "WALLOPS :" << buf; - } - -- void SendJoin(User *user, Channel *c, ChannelStatus *status) -+ void SendJoin(User *user, Channel *c, const ChannelStatus *status) - { -- send_cmd(user->nick, "JOIN %s", c->name.c_str()); -+ UplinkSocket::Message(user->nick) << "JOIN " << c->name; - if (status) - { -+ /* First save the channel status incase uc->Status == status */ - ChannelStatus cs = *status; -- status->ClearFlags(); -+ /* If the user is internally on the channel with flags, kill them so that -+ * the stacker will allow this. -+ */ -+ UserContainer *uc = c->FindUser(user); -+ if (uc != NULL) -+ uc->Status->ClearFlags(); - - BotInfo *setter = findbot(user->nick); - for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i) -@@ -74,18 +80,18 @@ class ngIRCdProto : public IRCDProto - - void SendSVSKillInternal(const BotInfo *source, const User *user, const Anope::string &buf) - { -- send_cmd(source ? source->nick : Config->ServerName, "KILL %s :%s", user->nick.c_str(), buf.c_str()); -+ UplinkSocket::Message(source ? source->nick : Config->ServerName) << "KILL " << user->nick << " :" << buf; - } - - /* SERVER name hop descript */ - void SendServer(const Server *server) - { -- send_cmd("", "SERVER %s %d :%s", server->GetName().c_str(), server->GetHops(), server->GetDescription().c_str()); -+ UplinkSocket::Message() << "SERVER " << server->GetName() << " " << server->GetHops() << " :" << server->GetDescription(); - } - - void SendConnect() - { -- send_cmd("", "PASS %s 0210-IRC+ Anope|%s:CLHSo P", Config->Uplinks[CurrentUplink]->password.c_str(), Anope::VersionShort().c_str()); -+ UplinkSocket::Message() << "PASS " << Config->Uplinks[CurrentUplink]->password << " 0210-IRC+ Anope|" << Anope::VersionShort() << ":CLHSo P"; - /* Make myself known to myself in the serverlist */ - SendServer(Me); - /* finish the enhanced server handshake and register the connection */ -@@ -98,56 +104,52 @@ class ngIRCdProto : public IRCDProto - Anope::string modes = "+" + u->GetModes(); - XLine x(u->nick, "Reserved for services"); - ircdproto->SendSQLine(NULL, &x); -- send_cmd(Config->ServerName, "NICK %s 1 %s %s 1 %s :%s", u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str(), modes.c_str(), u->realname.c_str()); -+ UplinkSocket::Message(Config->ServerName) << "NICK " << u->nick << " 1 " << u->GetIdent() << " " << u->host << " 1 " << modes << " :" << u->realname; - } - - void SendPartInternal(const BotInfo *bi, const Channel *chan, const Anope::string &buf) - { - if (!buf.empty()) -- send_cmd(bi->nick, "PART %s :%s", chan->name.c_str(), buf.c_str()); -+ UplinkSocket::Message(bi->nick) << "PART " << chan->name << " :" << buf; - else -- send_cmd(bi->nick, "PART %s", chan->name.c_str()); -+ UplinkSocket::Message(bi->nick) << "PART " << chan->name; - } - - void SendModeInternal(const BotInfo *bi, const Channel *dest, const Anope::string &buf) - { --Log(LOG_DEBUG) << "SendModeInternal 1"; -- send_cmd(bi ? bi->nick : Config->ServerName, "MODE %s %s", dest->name.c_str(), buf.c_str()); -+ UplinkSocket::Message(bi ? bi->nick : Config->ServerName) << "MODE " << dest->name << " " << buf; - } - - void SendModeInternal(const BotInfo *bi, const User *u, const Anope::string &buf) - { --Log(LOG_DEBUG) << "SendModeInternal 2"; -- send_cmd(bi ? bi->nick : Config->ServerName, "MODE %s %s", u->nick.c_str(), buf.c_str()); -+ UplinkSocket::Message(bi ? bi->nick : Config->ServerName) << "MODE " << u->nick << " " << buf; - } - - void SendKickInternal(const BotInfo *bi, const Channel *chan, const User *user, const Anope::string &buf) - { - if (!buf.empty()) -- send_cmd(bi->nick, "KICK %s %s :%s", chan->name.c_str(), user->nick.c_str(), buf.c_str()); -+ UplinkSocket::Message(bi->nick) << "KICK " << chan->name << " " << user->nick << " :" << buf; - else -- send_cmd(bi->nick, "KICK %s %s", chan->name.c_str(), user->nick.c_str()); -+ UplinkSocket::Message(bi->nick) << "KICK " << chan->name << " " << user->nick; - } - -- void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf) -+ void SendChannel(Channel *c) - { -- send_cmd(source->nick, "NOTICE @%s :%s", dest->name.c_str(), buf.c_str()); -+ Anope::string modes = c->GetModes(true, true); -+ UplinkSocket::Message(Config->ServerName) << "CHANINFO " << c->name << " +" << modes; - } - -- /* INVITE */ -- void SendInvite(BotInfo *source, const Anope::string &chan, const Anope::string &nick) -+ void SendTopic(BotInfo *bi, Channel *c) - { -- send_cmd(source->nick, "INVITE %s %s", nick.c_str(), chan.c_str()); -+ UplinkSocket::Message(bi->nick) << "TOPIC " << c->name << " :" << c->topic; - } - -- void SendChannel(Channel *c) -+ void SendLogin(User *u) - { -- Anope::string modes = c->GetModes(true, true); -- send_cmd(Config->ServerName, "CHANINFO %s +%s", c->name.c_str(), modes.c_str()); - } -- void SendTopic(BotInfo *bi, Channel *c) -+ -+ void SendLogout(User *u) - { -- send_cmd(bi->nick, "TOPIC %s :%s", c->name.c_str(), c->topic.c_str()); - } - }; - --- -1.7.8.3 - diff --git a/contrib/Anope/0010-ngircd-Add-ProtongIRCd.patch b/contrib/Anope/0010-ngircd-Add-ProtongIRCd.patch deleted file mode 100644 index 42cd4a5..0000000 --- a/contrib/Anope/0010-ngircd-Add-ProtongIRCd.patch +++ /dev/null @@ -1,57 +0,0 @@ -From d2c45d7c578ec684d3b471020f631847316de196 Mon Sep 17 00:00:00 2001 -From: Alexander Barton -Date: Fri, 25 Nov 2011 19:17:19 +0100 -Subject: [PATCH 10/16] ngircd: Add ~ProtongIRCd() - ---- - modules/protocol/ngircd.cpp | 13 ++++++++----- - 1 files changed, 8 insertions(+), 5 deletions(-) - -diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp -index 55cb8d7..5fd62db 100644 ---- a/modules/protocol/ngircd.cpp -+++ b/modules/protocol/ngircd.cpp -@@ -302,8 +302,7 @@ class ngIRCdIRCdMessage : public IRCdMessage - } - }; - --/** This is here because: -- * -+/* - * If we had three servers, A, B & C linked like so: A<->B<->C - * If Anope is linked to A and B splits from A and then reconnects - * B introduces itself, introduces C, sends EOS for C, introduces Bs clients -@@ -319,8 +318,6 @@ bool event_pong(const Anope::string &source, const std::vector &p - return true; - } - -- -- - /* - * CHANINFO + - * CHANINFO + : -@@ -480,7 +477,6 @@ bool event_376(const Anope::string &source, const std::vector &pa - return true; - } - -- - class ProtongIRCd : public Module - { - Message message_kick, message_pass, message_njoin, message_chaninfo, message_005, -@@ -542,6 +538,13 @@ class ProtongIRCd : public Module - ModuleManager::Attach(I_OnUserNickChange, this); - } - -+ ~ProtongIRCd() -+ { -+ pmodule_ircd_var(NULL); -+ pmodule_ircd_proto(NULL); -+ pmodule_ircd_message(NULL); -+ } -+ - void OnUserNickChange(User *u, const Anope::string &) - { - u->RemoveModeInternal(ModeManager::FindUserModeByName(UMODE_REGISTERED)); --- -1.7.8.3 - diff --git a/contrib/Anope/0011-ngircd-Update-protocol-module-for-current-Anope-1.9.patch b/contrib/Anope/0011-ngircd-Update-protocol-module-for-current-Anope-1.9.patch deleted file mode 100644 index bbf2b63..0000000 --- a/contrib/Anope/0011-ngircd-Update-protocol-module-for-current-Anope-1.9.patch +++ /dev/null @@ -1,29 +0,0 @@ -From 4dc5a3d3e2fbb218461d9459bff1c0a392a75881 Mon Sep 17 00:00:00 2001 -From: Alexander Barton -Date: Sat, 31 Dec 2011 16:12:52 +0100 -Subject: [PATCH 11/16] ngircd: Update protocol module for current Anope 1.9 - GIT - -This changes are rquired by: - - - 150831c1a: Made capab management a bit simplier ---- - modules/protocol/ngircd.cpp | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - -diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp -index 5fd62db..9c26ec8 100644 ---- a/modules/protocol/ngircd.cpp -+++ b/modules/protocol/ngircd.cpp -@@ -527,7 +527,7 @@ class ProtongIRCd : public Module - { - this->SetAuthor("Anope"); - -- Capab.SetFlag(CAPAB_QS); -+ Capab.insert("QS"); - - pmodule_ircd_var(myIrcd); - pmodule_ircd_proto(&this->ircd_proto); --- -1.7.8.3 - diff --git a/contrib/Anope/0012-ngircd-Channel-mode-r-is-supported-now.patch b/contrib/Anope/0012-ngircd-Channel-mode-r-is-supported-now.patch deleted file mode 100644 index 2127c26..0000000 --- a/contrib/Anope/0012-ngircd-Channel-mode-r-is-supported-now.patch +++ /dev/null @@ -1,25 +0,0 @@ -From 99c18cafdee28bfb17fad5f0526b3ed5d1f5f312 Mon Sep 17 00:00:00 2001 -From: Alexander Barton -Date: Sat, 31 Dec 2011 16:17:50 +0100 -Subject: [PATCH 12/16] ngircd: let Anope know that channel mode "r" is - supported - ---- - modules/protocol/ngircd.cpp | 1 + - 1 files changed, 1 insertions(+), 0 deletions(-) - -diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp -index 9c26ec8..6155667 100644 ---- a/modules/protocol/ngircd.cpp -+++ b/modules/protocol/ngircd.cpp -@@ -512,6 +512,7 @@ class ProtongIRCd : public Module - ModeManager::AddChannelMode(new ChannelMode(CMODE_MODERATED, 'm')); - ModeManager::AddChannelMode(new ChannelMode(CMODE_NOEXTERNAL, 'n')); - ModeManager::AddChannelMode(new ChannelMode(CMODE_PERM, 'P')); -+ ModeManager::AddChannelMode(new ChannelModeRegistered('r')); - ModeManager::AddChannelMode(new ChannelMode(CMODE_REGISTEREDONLY, 'R')); - ModeManager::AddChannelMode(new ChannelMode(CMODE_SECRET, 's')); - ModeManager::AddChannelMode(new ChannelMode(CMODE_TOPIC, 't')); --- -1.7.8.3 - diff --git a/contrib/Anope/0013-ngircd-Update-copyright-notice.patch b/contrib/Anope/0013-ngircd-Update-copyright-notice.patch deleted file mode 100644 index 759076d..0000000 --- a/contrib/Anope/0013-ngircd-Update-copyright-notice.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 5a19b69f0daceb5b12ec751bc919519a7f712f2d Mon Sep 17 00:00:00 2001 -From: Alexander Barton -Date: Sun, 15 Jan 2012 13:36:14 +0100 -Subject: [PATCH 13/16] ngircd: Update copyright notice - ---- - modules/protocol/ngircd.cpp | 7 ++++--- - 1 files changed, 4 insertions(+), 3 deletions(-) - -diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp -index 6155667..024c61d 100644 ---- a/modules/protocol/ngircd.cpp -+++ b/modules/protocol/ngircd.cpp -@@ -1,7 +1,8 @@ --/* ngIRCd IRCD functions -+/* -+ * ngIRCd Protocol module for Anope IRC Services - * -- * (C) 2003-2011 Anope Team -- * Contact us at team@anope.org -+ * (C) 2011-2012 Alexander Barton -+ * (C) 2011 Anope Team - * - * Please read COPYING and README for further details. - * --- -1.7.8.3 - diff --git a/contrib/Anope/0014-ngircd-set-unset-GLINE-s-on-AKILL-commands.patch b/contrib/Anope/0014-ngircd-set-unset-GLINE-s-on-AKILL-commands.patch deleted file mode 100644 index c02ac6e..0000000 --- a/contrib/Anope/0014-ngircd-set-unset-GLINE-s-on-AKILL-commands.patch +++ /dev/null @@ -1,35 +0,0 @@ -From acc24a7f4488f6ef0fb240a76766db4220b62d53 Mon Sep 17 00:00:00 2001 -From: Alexander Barton -Date: Sun, 22 Jan 2012 19:05:28 +0100 -Subject: [PATCH 14/16] ngircd: set/unset GLINE's on AKILL commands - ---- - modules/protocol/ngircd.cpp | 10 ++++++++-- - 1 files changed, 8 insertions(+), 2 deletions(-) - -diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp -index 024c61d..3bc3812 100644 ---- a/modules/protocol/ngircd.cpp -+++ b/modules/protocol/ngircd.cpp -@@ -48,10 +48,16 @@ class ngIRCdProto : public IRCDProto - { - void SendAkill(User *u, const XLine *x) - { -- // TODO: ADD SOME CODE -+ // Calculate the time left before this would expire, capping it at 2 days -+ time_t timeleft = x->Expires - Anope::CurTime; -+ if (timeleft > 172800 || !x->Expires) -+ timeleft = 172800; -+ UplinkSocket::Message(Config->ServerName) << "GLINE " << x->Mask << " " << timeleft << " :" << x->Reason << " (" << x->By << ")"; - } - -- void SendAkillDel(const XLine*) { } -+ void SendAkillDel(const XLine *x) { -+ UplinkSocket::Message(Config->ServerName) << "GLINE " << x->Mask; -+ } - - void SendGlobopsInternal(const BotInfo *source, const Anope::string &buf) - { --- -1.7.8.3 - diff --git a/contrib/Anope/0015-ngircd-ngIRCd-supports-channel-mode-e-now.patch b/contrib/Anope/0015-ngircd-ngIRCd-supports-channel-mode-e-now.patch deleted file mode 100644 index 7a25c9a..0000000 --- a/contrib/Anope/0015-ngircd-ngIRCd-supports-channel-mode-e-now.patch +++ /dev/null @@ -1,27 +0,0 @@ -From 3a61b190db79848d4519296432ebb2ab714c42b7 Mon Sep 17 00:00:00 2001 -From: Alexander Barton -Date: Sun, 22 Jan 2012 19:06:34 +0100 -Subject: [PATCH 15/16] ngircd: ngIRCd supports channel mode 'e' now - ---- - modules/protocol/ngircd.cpp | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - -diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp -index 3bc3812..0f87cbd 100644 ---- a/modules/protocol/ngircd.cpp -+++ b/modules/protocol/ngircd.cpp -@@ -504,8 +504,9 @@ class ProtongIRCd : public Module - ModeManager::AddUserMode(new UserMode(UMODE_WALLOPS, 'w')); - ModeManager::AddUserMode(new UserMode(UMODE_CLOAK, 'x')); - -- /* Add modes for ban and invite lists */ -+ /* Add modes for ban, exception, and invite lists */ - ModeManager::AddChannelMode(new ChannelModeList(CMODE_BAN, 'b')); -+ ModeManager::AddChannelMode(new ChannelModeList(CMODE_EXCEPT, 'e')); - ModeManager::AddChannelMode(new ChannelModeList(CMODE_INVITEOVERRIDE, 'I')); - - /* Add channel user modes */ --- -1.7.8.3 - diff --git a/contrib/Anope/0016-ngircd-support-SQUERY-command.patch b/contrib/Anope/0016-ngircd-support-SQUERY-command.patch deleted file mode 100644 index a3346a4..0000000 --- a/contrib/Anope/0016-ngircd-support-SQUERY-command.patch +++ /dev/null @@ -1,35 +0,0 @@ -From a7c48fcf47af757cf1b4eeaa6bcc96f4ae1f7410 Mon Sep 17 00:00:00 2001 -From: Alexander Barton -Date: Sat, 4 Feb 2012 11:13:36 +0100 -Subject: [PATCH 16/16] ngircd: support SQUERY command - -Thanks to DukePyrolator for explaining these changes to me. ---- - modules/protocol/ngircd.cpp | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - -diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp -index 0f87cbd..530686e 100644 ---- a/modules/protocol/ngircd.cpp -+++ b/modules/protocol/ngircd.cpp -@@ -487,7 +487,7 @@ bool event_376(const Anope::string &source, const std::vector &pa - class ProtongIRCd : public Module - { - Message message_kick, message_pass, message_njoin, message_chaninfo, message_005, -- message_442, message_376, message_pong; -+ message_442, message_376, message_pong, message_squery; - - ngIRCdProto ircd_proto; - ngIRCdIRCdMessage ircd_message; -@@ -532,7 +532,7 @@ class ProtongIRCd : public Module - message_kick("KICK", event_kick), message_pass("PASS", event_pass), - message_njoin("NJOIN", event_njoin), message_chaninfo("CHANINFO", event_chaninfo), - message_005("005", event_005), message_442("442", event_442), message_376("376", event_376), -- message_pong("PONG", event_pong) -+ message_pong("PONG", event_pong), message_squery("SQUERY", ::OnPrivmsg) - { - this->SetAuthor("Anope"); - --- -1.7.8.3 - diff --git a/contrib/Anope/Makefile.am b/contrib/Anope/Makefile.am deleted file mode 100644 index 607f0bc..0000000 --- a/contrib/Anope/Makefile.am +++ /dev/null @@ -1,34 +0,0 @@ -# -# ngIRCd -- The Next Generation IRC Daemon -# Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors -# -# 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 = \ - README \ - 0001-Revert-Removed-ngircd.patch \ - 0002-ngircd-whitespace-fixes.patch \ - 0003-Update-ngIRCd-protocol-module-for-current-Anope-1.9.patch \ - 0004-ngircd-Do-PING-PONG-on-server-burst-to-sync-servers.patch \ - 0005-ngircd-always-prefix-modes-in-CHANINFO-with.patch \ - 0006-ngircd-support-user-mode-R-and-channel-mode-R.patch \ - 0007-ngircd-Fix-handling-of-JOIN-commands.patch \ - 0008-ngircd-Allow-setting-modes-by-clients-on-burst.patch \ - 0009-ngircd-Update-protocol-module-for-current-Anope-1.9.patch \ - 0010-ngircd-Add-ProtongIRCd.patch \ - 0011-ngircd-Update-protocol-module-for-current-Anope-1.9.patch \ - 0012-ngircd-Channel-mode-r-is-supported-now.patch \ - 0013-ngircd-Update-copyright-notice.patch \ - 0014-ngircd-set-unset-GLINE-s-on-AKILL-commands.patch \ - 0015-ngircd-ngIRCd-supports-channel-mode-e-now.patch \ - 0016-ngircd-support-SQUERY-command.patch - -maintainer-clean-local: - rm -f Makefile Makefile.in - -# -eof- diff --git a/contrib/Anope/README b/contrib/Anope/README deleted file mode 100644 index 50f025c..0000000 --- a/contrib/Anope/README +++ /dev/null @@ -1,35 +0,0 @@ - - ngIRCd - Next Generation IRC Server - http://ngircd.barton.de/ - - (c)2001-2012 Alexander Barton and Contributors. - ngIRCd is free software and published under the - terms of the GNU General Public License. - - -- contrib/Anope/README -- - - -This directory contains two preliminary patches that (re-) add a ngIRCd -protocol module to the Anope 1.9 development branch. It has been tested -with Anope 1.9.6, there is no guarantee that it will work with other -versions as Anope 1.9.x is under heavy development ... - -To build this Anope protocol module, you have to - - - Download the Anope 1.9.x sources (only tested with 1.9.6!), - - Patch in the ngIRCd protocol module, - - Build and install Anope as usual, - - Configure Anope as usual, use "ngircd" as protocol module. - -So the command sequence can be something like this: - - $ tar xzf anope-1.9.6-source.tar.gz - $ cd anope-1.9.6-source - $ for p in .../ngircd/contrib/Anope/*.patch ; do patch -p1 < $p ; done - $ ./Config - $ cd build - $ make - $ make install - -Please have a look at the file doc/Services.txt for more information about -how to set up ngIRCd and Anope. diff --git a/contrib/Debian/changelog b/contrib/Debian/changelog index d1438c8..2a9c2df 100644 --- a/contrib/Debian/changelog +++ b/contrib/Debian/changelog @@ -1,3 +1,21 @@ +ngircd (20-0ab1) unstable; urgency=low + + * New "upstream" release: ngIRCd 20. + + -- Alexander Barton Mon, 17 Dec 2012 13:04:15 +0100 + +ngircd (20~rc2-0ab1) unstable; urgency=low + + * New "upstream" release candidate 2 for ngIRCd Release 20. + + -- Alexander Barton Sun, 02 Dec 2012 18:51:06 +0100 + +ngircd (20~rc1-0ab1) unstable; urgency=low + + * New "upstream" release candidate 1 for ngIRCd Release 20. + + -- Alexander Barton Sun, 11 Nov 2012 16:03:32 +0100 + ngircd (19.2-0ab1) unstable; urgency=low * New "upstream" release: ngIRCd 19.2. diff --git a/contrib/Debian/control b/contrib/Debian/control index 0ac6d22..59a74ab 100644 --- a/contrib/Debian/control +++ b/contrib/Debian/control @@ -10,7 +10,7 @@ Build-Depends: debhelper (>> 4.0.0), libident-dev, libgnutls-dev, libpam0g-dev, - telnet, + telnet | telnet-ssl, Standards-Version: 3.9.1 Package: ngircd @@ -18,11 +18,11 @@ Architecture: any Depends: ${shlibs:Depends}, ${misc:Depends} Provides: ircd Description: lightweight Internet Relay Chat server - This package provides ngIRCd, a lightweight Internet Relay Chat - server for small or private networks. It is simple to configure, can - cope with dynamic IP addresses, and supports IPv6 as well as SSL. It - is written from scratch, not based on the original IRCd and quite - portable. + This package provides ngIRCd, a portable and lightweight Internet Relay + Chat server for small or private networks, developed under the GNU + General Public License (GPL). It is simple to configure, can cope with + dynamic IP addresses, and supports IPv6 as well as SSL. It is written + from scratch and not based on the original IRCd. . This package contains the "standard distribution", including support for syslog logging and compressed server-links using zlib. Please have a look @@ -35,11 +35,11 @@ Depends: ${shlibs:Depends}, ${misc:Depends} Provides: ircd Conflicts: ngircd, ngircd-dbg Description: lightweight Internet Relay Chat server - This package provides ngIRCd, a lightweight Internet Relay Chat - server for small or private networks. It is simple to configure, can - cope with dynamic IP addresses, and supports IPv6 as well as SSL. It - is written from scratch, not based on the original IRCd and quite - portable. + This package provides ngIRCd, a portable and lightweight Internet Relay + Chat server for small or private networks, developed under the GNU + General Public License (GPL). It is simple to configure, can cope with + dynamic IP addresses, and supports IPv6 as well as SSL. It is written + from scratch and not based on the original IRCd. . In addition to the features of the "standard package", this package includes support for TCP wrappers, IDENT requests, the IPv6 protocol and @@ -51,11 +51,11 @@ Depends: ${shlibs:Depends}, ${misc:Depends} Provides: ircd Conflicts: ngircd, ngircd-full Description: lightweight Internet Relay Chat server - This package provides ngIRCd, a lightweight Internet Relay Chat - server for small or private networks. It is simple to configure, can - cope with dynamic IP addresses, and supports IPv6 as well as SSL. It - is written from scratch, not based on the original IRCd and quite - portable. + This package provides ngIRCd, a portable and lightweight Internet Relay + Chat server for small or private networks, developed under the GNU + General Public License (GPL). It is simple to configure, can cope with + dynamic IP addresses, and supports IPv6 as well as SSL. It is written + from scratch and not based on the original IRCd. . In addition to the features of the "standard package", this package includes support for TCP wrappers, IDENT requests, the IPv6 protocol and diff --git a/contrib/Debian/rules b/contrib/Debian/rules index 868a042..0aecde5 100755 --- a/contrib/Debian/rules +++ b/contrib/Debian/rules @@ -1,7 +1,7 @@ #!/usr/bin/make -f # # ngIRCd -- The Next Generation IRC Daemon -# Copyright (c)2001-2009 Alexander Barton +# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors # # 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 @@ -53,7 +53,8 @@ configure-ngircd-full: configure --sysconfdir=/etc/ngircd \ --mandir=\$${prefix}/share/man \ --with-syslog --with-zlib \ - --with-gnutls --with-ident --with-tcp-wrappers --with-pam \ + --with-gnutls --with-iconv --with-ident --with-tcp-wrappers \ + --with-pam \ --enable-ipv6 configure-ngircd-full-dbg: configure @@ -66,7 +67,8 @@ configure-ngircd-full-dbg: configure --mandir=\$${prefix}/share/man \ --enable-debug --enable-sniffer \ --with-syslog --with-zlib \ - --with-gnutls --with-ident --with-tcp-wrappers --with-pam \ + --with-gnutls --with-iconv --with-ident --with-tcp-wrappers \ + --with-pam \ --enable-ipv6 build: diff --git a/contrib/MacOSX/config.h b/contrib/MacOSX/config.h index 5b47e9d..6da7496 100644 --- a/contrib/MacOSX/config.h +++ b/contrib/MacOSX/config.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors. + * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors. * * 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 @@ -11,7 +11,8 @@ * Static configuration file for Mac OS X Xcode project */ -#define PACKAGE_NAME "ngircd" +#define PACKAGE_NAME "ngIRCd" +#define PACKAGE "ngircd" #ifndef VERSION #define VERSION "??("__DATE__")" #endif @@ -51,6 +52,9 @@ /* Define if PAM should be used */ #define PAM 1 +/* Define if libiconv can be used, e.g. for CHARCONV */ +#define ICONV 1 + /* -- Supported features -- */ /* Define if SSP C support is enabled. */ @@ -76,6 +80,8 @@ /* Define to 1 if you have the `gai_strerror' function. */ #define HAVE_GAI_STRERROR 1 +/* Define to 1 if you have the `iconv_open' function. */ +#define HAVE_ICONV_OPEN 1 /* Define to 1 if you have the `kqueue' function. */ #define HAVE_KQUEUE 1 /* Define to 1 if you have the `inet_ntoa' function. */ @@ -98,6 +104,8 @@ #define HAVE_GETNAMEINFO 1 /* Define to 1 if you have the `sigaction' function. */ #define HAVE_SIGACTION 1 +/* Define to 1 if you have the `setsid' function. */ +#define HAVE_SETSID 1 /* Define if socklen_t exists */ #define HAVE_socklen_t 1 diff --git a/contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj b/contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj index 6da1cb3..a2cad27 100644 --- a/contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj +++ b/contrib/MacOSX/ngIRCd.xcodeproj/project.pbxproj @@ -36,6 +36,10 @@ 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 */; }; + FA4F165A164836B100DBD011 /* irc-metadata.c in Sources */ = {isa = PBXBuildFile; fileRef = FA4F1659164836B100DBD011 /* irc-metadata.c */; }; + FA6BBC631605F0AC0004247A /* conn-encoding.c in Sources */ = {isa = PBXBuildFile; fileRef = FA6BBC5F1605F0AB0004247A /* conn-encoding.c */; }; + FA6BBC641605F0AC0004247A /* irc-encoding.c in Sources */ = {isa = PBXBuildFile; fileRef = FA6BBC611605F0AC0004247A /* irc-encoding.c */; }; + FA6BBC661605F6D60004247A /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FA6BBC651605F6D60004247A /* libiconv.dylib */; }; FA85178C0FA061EC006A1F5A /* op.c in Sources */ = {isa = PBXBuildFile; fileRef = FA85178B0FA061EC006A1F5A /* op.c */; }; FA99428C10E82A27007F27ED /* proc.c in Sources */ = {isa = PBXBuildFile; fileRef = FA99428B10E82A27007F27ED /* proc.c */; }; FAA3D27B0F139CDC00B2447E /* conn-ssl.c in Sources */ = {isa = PBXBuildFile; fileRef = FAA3D2790F139CDC00B2447E /* conn-ssl.c */; }; @@ -203,6 +207,13 @@ FA4B08E613E7F91700765BA3 /* ngIRCd-Logo.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = "ngIRCd-Logo.gif"; sourceTree = ""; }; FA4B08E713E7F91700765BA3 /* ngircd-redhat.init */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "ngircd-redhat.init"; sourceTree = ""; }; FA4B08E813E7F91C00765BA3 /* platformtest.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = platformtest.sh; sourceTree = ""; }; + FA4F1659164836B100DBD011 /* irc-metadata.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "irc-metadata.c"; sourceTree = ""; }; + FA4F165C164836BF00DBD011 /* irc-metadata.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "irc-metadata.h"; sourceTree = ""; }; + FA6BBC5F1605F0AB0004247A /* conn-encoding.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "conn-encoding.c"; sourceTree = ""; }; + FA6BBC601605F0AC0004247A /* conn-encoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "conn-encoding.h"; sourceTree = ""; }; + FA6BBC611605F0AC0004247A /* irc-encoding.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "irc-encoding.c"; sourceTree = ""; }; + FA6BBC621605F0AC0004247A /* irc-encoding.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "irc-encoding.h"; sourceTree = ""; }; + FA6BBC651605F6D60004247A /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = ../../../../../../../usr/lib/libiconv.dylib; sourceTree = ""; }; FA77849A133FB9FF00740057 /* sample-ngircd.conf.tmpl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "sample-ngircd.conf.tmpl"; sourceTree = ""; }; FA85178A0FA061EC006A1F5A /* op.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = op.h; sourceTree = ""; }; FA85178B0FA061EC006A1F5A /* op.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = op.c; sourceTree = ""; }; @@ -258,6 +269,7 @@ files = ( FA322DC10CEF77CB001761B3 /* libz.dylib in Frameworks */, FA2D567B11EA1AB300D37A35 /* libpam.dylib in Frameworks */, + FA6BBC661605F6D60004247A /* libiconv.dylib in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -283,8 +295,9 @@ FA322D600CEF750F001761B3 /* configure.in */, FA322D630CEF750F001761B3 /* Makefile.am */, 1AB674ADFE9D54B511CA2CBB /* Products */, - FA322DC00CEF77CB001761B3 /* libz.dylib */, + FA6BBC651605F6D60004247A /* libiconv.dylib */, FA2D567A11EA1AB300D37A35 /* libpam.dylib */, + FA322DC00CEF77CB001761B3 /* libz.dylib */, ); name = ngIRCd; sourceTree = ""; @@ -328,12 +341,14 @@ FA322CDF0CEF74B1001761B3 /* conf.c */, FA322CE00CEF74B1001761B3 /* conf.h */, FAA3D2780F139CDC00B2447E /* conf-ssl.h */, + FA322CE50CEF74B1001761B3 /* conn.c */, + FA322CE60CEF74B1001761B3 /* conn.h */, + FA6BBC5F1605F0AB0004247A /* conn-encoding.c */, + FA6BBC601605F0AC0004247A /* conn-encoding.h */, FA322CE10CEF74B1001761B3 /* conn-func.c */, FA322CE20CEF74B1001761B3 /* conn-func.h */, FA322CE30CEF74B1001761B3 /* conn-zip.c */, FA322CE40CEF74B1001761B3 /* conn-zip.h */, - FA322CE50CEF74B1001761B3 /* conn.c */, - FA322CE60CEF74B1001761B3 /* conn.h */, FAA3D2790F139CDC00B2447E /* conn-ssl.c */, FAA3D27A0F139CDC00B2447E /* conn-ssl.h */, FA322CE70CEF74B1001761B3 /* defines.h */, @@ -341,14 +356,20 @@ FA322CE90CEF74B1001761B3 /* hash.h */, FA322CEA0CEF74B1001761B3 /* io.c */, FA322CEB0CEF74B1001761B3 /* io.h */, + FA322CFC0CEF74B1001761B3 /* irc.c */, + FA322CFD0CEF74B1001761B3 /* irc.h */, FAD5853315271AB800328741 /* irc-cap.c */, FAD5853415271AB800328741 /* irc-cap.h */, FA322CEC0CEF74B1001761B3 /* irc-channel.c */, FA322CED0CEF74B1001761B3 /* irc-channel.h */, + FA6BBC611605F0AC0004247A /* irc-encoding.c */, + FA6BBC621605F0AC0004247A /* irc-encoding.h */, FA322CEE0CEF74B1001761B3 /* irc-info.c */, FA322CEF0CEF74B1001761B3 /* irc-info.h */, FA322CF00CEF74B1001761B3 /* irc-login.c */, FA322CF10CEF74B1001761B3 /* irc-login.h */, + FA4F1659164836B100DBD011 /* irc-metadata.c */, + FA4F165C164836BF00DBD011 /* irc-metadata.h */, FA322CF20CEF74B1001761B3 /* irc-mode.c */, FA322CF30CEF74B1001761B3 /* irc-mode.h */, FA322CF40CEF74B1001761B3 /* irc-op.c */, @@ -359,8 +380,6 @@ FA322CF90CEF74B1001761B3 /* irc-server.h */, FA322CFA0CEF74B1001761B3 /* irc-write.c */, FA322CFB0CEF74B1001761B3 /* irc-write.h */, - FA322CFC0CEF74B1001761B3 /* irc.c */, - FA322CFD0CEF74B1001761B3 /* irc.h */, FA322CFE0CEF74B1001761B3 /* lists.c */, FA322CFF0CEF74B1001761B3 /* lists.h */, FA322D000CEF74B1001761B3 /* log.c */, @@ -750,6 +769,9 @@ FAD5853215271AAB00328741 /* client-cap.c in Sources */, FAD5853515271AB800328741 /* irc-cap.c in Sources */, FAD5853815272C2600328741 /* login.c in Sources */, + FA6BBC631605F0AC0004247A /* conn-encoding.c in Sources */, + FA6BBC641605F0AC0004247A /* irc-encoding.c in Sources */, + FA4F165A164836B100DBD011 /* irc-metadata.c in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -779,7 +801,7 @@ GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VALUE = YES; INSTALL_PATH = /usr/local/bin; - PRODUCT_NAME = ngIRCd; + PRODUCT_NAME = ngircd; }; name = Default; }; @@ -787,10 +809,12 @@ isa = XCBuildConfiguration; buildSettings = { ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; - GCC_VERSION = 4.2; + CODE_SIGN_IDENTITY = ""; + GCC_VERSION = ""; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - SDKROOT = macosx10.6; + MACOSX_DEPLOYMENT_TARGET = 10.6; + SDKROOT = ""; }; name = Default; }; @@ -800,11 +824,12 @@ ARCHS = "$(NATIVE_ARCH_ACTUAL)"; GCC_DEBUGGING_SYMBOLS = full; GCC_OPTIMIZATION_LEVEL = 0; - GCC_VERSION = 4.2; + GCC_VERSION = ""; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; + SDKROOT = ""; }; name = Debug; }; @@ -831,7 +856,7 @@ GCC_WARN_UNUSED_PARAMETER = YES; GCC_WARN_UNUSED_VALUE = YES; INSTALL_PATH = /usr/local/bin; - PRODUCT_NAME = ngIRCd; + PRODUCT_NAME = ngircd; }; name = Debug; }; diff --git a/contrib/Makefile.am b/contrib/Makefile.am index 36ba245..09b43a6 100644 --- a/contrib/Makefile.am +++ b/contrib/Makefile.am @@ -1,6 +1,6 @@ # # ngIRCd -- The Next Generation IRC Daemon -# Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors +# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors # # 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,10 +9,17 @@ # Please read the file COPYING, README and AUTHORS for more information. # -SUBDIRS = Anope Debian MacOSX +SUBDIRS = Debian MacOSX -EXTRA_DIST = README ngircd.spec systrace.policy ngindent ngircd-bsd.sh \ - ngIRCd-Logo.gif ngircd-redhat.init platformtest.sh +EXTRA_DIST = README \ + ngindent \ + ngircd-bsd.sh \ + ngIRCd-Logo.gif \ + ngircd-redhat.init \ + ngircd.service \ + ngircd.spec \ + platformtest.sh \ + systrace.policy maintainer-clean-local: rm -f Makefile Makefile.in diff --git a/contrib/README b/contrib/README index 6097bae..1aebd1e 100644 --- a/contrib/README +++ b/contrib/README @@ -9,9 +9,6 @@ -- Contributions -- -Anope/ - - A preliminary patch that adds a ngIRCd protocol module to Anope 1.9. - Debian/ - Various files for building Debian GNU/Linux packages (".deb's"). diff --git a/contrib/ngircd.service b/contrib/ngircd.service new file mode 100644 index 0000000..b5bab06 --- /dev/null +++ b/contrib/ngircd.service @@ -0,0 +1,11 @@ +[Unit] +Description=Next Generation IRC Daemon +After=network.target + +[Service] +# don't daemonize to simplify stuff +ExecStart=/usr/sbin/ngircd -n +ExecReload=/bin/kill -HUP $MAINPID + +[Install] +WantedBy=multi-user.target diff --git a/contrib/ngircd.spec b/contrib/ngircd.spec index 2041aa0..9632bc0 100644 --- a/contrib/ngircd.spec +++ b/contrib/ngircd.spec @@ -1,5 +1,5 @@ %define name ngircd -%define version 19.2 +%define version 20 %define release 1 %define prefix %{_prefix} @@ -15,11 +15,11 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: zlib-devel, openssl-devel %description -This package provides ngIRCd, a lightweight Internet Relay Chat -server for small or private networks. It is simple to configure, can -cope with dynamic IP addresses, and supports IPv6 as well as SSL. It -is written from scratch, not based on the original IRCd and quite -portable. +This package provides ngIRCd, a portable and lightweight Internet Relay +Chat server for small or private networks, developed under the GNU +General Public License (GPL). It is simple to configure, can cope with +dynamic IP addresses, and supports IPv6 as well as SSL. It is written +from scratch and not based on the original IRCd. Advantages: - well arranged (lean) configuration file diff --git a/contrib/platformtest.sh b/contrib/platformtest.sh index afe9420..cfa1ecc 100755 --- a/contrib/platformtest.sh +++ b/contrib/platformtest.sh @@ -54,8 +54,8 @@ if [ $? -ne 0 ]; then cd .. fi -echo "$NAME: Checking for \"./autogen.sh\" script ..." -if [ -r ./autogen.sh ]; then +echo "$NAME: Checking for \"./configure\" script ..." +if [ ! -e ./configure ]; then echo "$NAME: Running \"./autogen.sh\" ..." [ -n "$VERBOSE" ] && ./autogen.sh || ./autogen.sh >/dev/null fi @@ -76,7 +76,7 @@ if [ -r ./configure ]; then R_RUN=$R_CHECK else ./src/ngircd/ngircd --help 2>/dev/null \ - | grep "^ngircd" >/dev/null + | grep "^ngIRCd" >/dev/null [ $? -eq 0 ] && R_RUN=1 fi fi @@ -85,9 +85,9 @@ fi # Get target platform information if [ -r "src/config.h" ]; then - CPU=`grep "TARGET_CPU" "src/config.h" | cut -d'"' -f2` - OS=`grep "TARGET_OS" "src/config.h" | cut -d'"' -f2` - VENDOR=`grep "TARGET_VENDOR" "src/config.h" | cut -d'"' -f2` + CPU=`grep "HOST_CPU" "src/config.h" | cut -d'"' -f2` + OS=`grep "HOST_OS" "src/config.h" | cut -d'"' -f2` + VENDOR=`grep "HOST_VENDOR" "src/config.h" | cut -d'"' -f2` PLATFORM="$CPU/$VENDOR/$OS" fi if [ -z "$PLATFORM" ]; then diff --git a/doc/HowToRelease.txt b/doc/HowToRelease.txt index d4d82bc..429c3d8 100644 --- a/doc/HowToRelease.txt +++ b/doc/HowToRelease.txt @@ -40,7 +40,7 @@ a) Make sure the source tree is in a releasable state ;-) b) Make sure you have working versions of GNU autoconf and GNU automake installed on the system you use for generating the release: - as of October 2010 we are using GNU autoconf 2.61 and GNU automake 1.10.1 + as of October 2010 we are using GNU autoconf 2.67 and GNU automake 1.11.1 which seem to work just fine. c) Update the files describing the new release: diff --git a/doc/Makefile.am b/doc/Makefile.am index 92e019b..cd51d7f 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -10,7 +10,7 @@ # .tmpl: - sed \ + $(AM_V_GEN)sed \ -e s@:ETCDIR:@${sysconfdir}@ \ <$< >$@ @@ -19,6 +19,7 @@ SUFFIXES = .tmpl static_docs = \ Bopm.txt \ Capabilities.txt \ + Contributing.txt \ FAQ.txt \ GIT.txt \ HowToRelease.txt \ @@ -52,8 +53,8 @@ all: $(generated_docs) install-data-hook: $(static_docs) $(toplevel_docs) $(generated_docs) $(mkinstalldirs) $(DESTDIR)$(sysconfdir) - if [ ! -f $(DESTDIR)$(sysconfdir)/ngircd.conf ]; then \ - $(INSTALL) -m 600 -c sample-ngircd.conf $(DESTDIR)$(sysconfdir)/ngircd.conf; \ + @if [ ! -f $(DESTDIR)$(sysconfdir)/ngircd.conf ]; then \ + make install-config; \ fi $(mkinstalldirs) $(DESTDIR)$(docdir) for f in $(static_docs) $(toplevel_docs); do \ @@ -63,10 +64,30 @@ install-data-hook: $(static_docs) $(toplevel_docs) $(generated_docs) $(INSTALL) -m 644 -c $$f $(DESTDIR)$(docdir)/; \ done +install-config: + $(INSTALL) -m 600 -c sample-ngircd.conf $(DESTDIR)$(sysconfdir)/ngircd.conf + @echo; \ + echo " ** NOTE: Installed sample configuration file:"; \ + echo " ** \"$(DESTDIR)$(sysconfdir)/ngircd.conf\""; \ + echo + uninstall-hook: rm -rf $(DESTDIR)$(docdir) + @if cmp --silent sample-ngircd.conf $(DESTDIR)$(sysconfdir)/ngircd.conf; then \ + make uninstall-config; \ + else \ + echo; \ + echo " ** NOTE: Not uninstalling changed configuration file:"; \ + echo " ** \"$(DESTDIR)$(sysconfdir)/ngircd.conf\""; \ + echo; \ + fi + +uninstall-config: + rm -f $(DESTDIR)$(sysconfdir)/ngircd.conf srcdoc: make -C src srcdoc +.PHONY: install-config uninstall-config srcdoc + # -eof- diff --git a/doc/Modes.txt b/doc/Modes.txt index e47e270..aee7491 100644 --- a/doc/Modes.txt +++ b/doc/Modes.txt @@ -2,7 +2,7 @@ ngIRCd - Next Generation IRC Server http://ngircd.barton.de/ - (c)2001-2011 Alexander Barton and Contributors. + (c)2001-2012 Alexander Barton and Contributors. ngIRCd is free software and published under the terms of the GNU General Public License. @@ -22,10 +22,13 @@ channels he is using at the moment. mode since description a 0.3.0 User is away. + b 20 User blocks private messages and notices. + B 20 User is flagged as a "bot". c 17 IRC operator wants to receive connect/disconnect NOTICEs. C 19 Only users that share a channel are allowed to send messages. i 0.0.1 User is "invisible". o 0.0.1 User is IRC operator. + q 20 User is protected, can not be kicked from a channel. r 0.0.1 User is restricted. R (1) 19 User is registered (e.g. by NickServ). s 0.4.0 User wants to receive server notices. @@ -49,13 +52,16 @@ users to lists (e.g. "invite list", "ban list"), others have parameters k 0.6.0 Channel has a "key" (a password). l 0.6.0 Channel has a user limit. m 0.3.0 Channel is moderated, only "voiced" users can send messages. + M 20 Only registered users (and IRC Ops) can send messages. n 0.3.0 Channel doesn't allow messages of users not being members. O 18 Only IRC operators are allowed to join this channel. P 0.5.0 Channel is "persistent". + Q 20 Nobody can be kicked from the channel. r (1) 19 Channel is "registered" (e.g. by ChanServ). R 19 Only registered users are allowed to join this channel. s 0.9.0 Channel is "secret". t 0.3.0 Only ChanOps are allowed to modify the channel topic. + V 20 Channel doesn't allow invites. z 16 Only users connected via SSL are allowed to join the channel. III. Channel User Modes @@ -66,7 +72,12 @@ channel of which he is a member. mode since description + q 20 User is channel owner can only be set by a service, other + owner and irc op. Can promote other users to q, a, o, h, v. + a 20 User is channel admin and can promote other users to v, h, o o 0.2.0 User is channel operator and can op/kick/... other members. + h 20 User is half op and can set channel modes imntvIbek and kick + voiced and normal users. v 0.2.0 User is "voiced" and can speak even if channel is moderated. diff --git a/doc/Platforms.txt b/doc/Platforms.txt index b8e33b5..9ff3b6c 100644 --- a/doc/Platforms.txt +++ b/doc/Platforms.txt @@ -39,8 +39,8 @@ i386/pc/solaris2.9 gcc 3.2.2 CVSHEAD 04-02-24 alex Y Y Y Y i386/pc/solaris2.11 gcc 3.4.3 19 12-02-26 alex Y Y N Y (4) i386/pc/solaris2.11 gcc 4.2.3 19.1 12-05-29 goetz Y Y Y Y (4) i386/unknown/freebsd5.2.1 gcc 3.3.3 0.8.0 04-05-30 alex Y Y Y Y -i386/unknown/freebsd6.2 gcc 3.4.6 19 12-02-26 alex Y Y Y Y (3) -i386/unknown/freebsd7.3 gcc 4.2.1 19 12-02-26 alex Y Y Y Y (3) +i386/unknown/freebsd6.2 gcc 3.4.6 20~rc1 12-11-13 alex Y Y Y Y (3) +i386/unknown/freebsd7.3 gcc 4.2.1 20~rc1 12-11-13 alex Y Y Y Y (3) i686/unknown/gnu0.3 gcc 4.4.5 19 12-02-29 alex Y Y Y Y i686/unkn./kfreebsd7.2-gnu gcc 4.3.4 15 09-12-02 alex Y Y Y Y (3) i386/unknown/netbsdelf1.6.2 gcc 2.95.3 18 11-07-10 goetz Y Y Y Y @@ -49,6 +49,7 @@ i386/unknown/netbsdelf4.0 gcc 4.1.2 19 12-02-29 alex Y Y Y Y (3) i386/unknown/netbsdelf5.0.2 gcc 4.1.3 19 12-02-26 alex Y Y Y Y (3) i386/unknown/openbsd3.9 gcc 3.3.5 0.10.0-p1 06-08-30 alex Y Y Y Y (3) i386/unknown/openbsd4.1 gcc 3.3.5 16 10-04-11 alex Y Y Y Y (3) +i586/pc/haiku gcc 2.95.3 19.2~138 12-10-11 user Y Y N N i586/pc/interix3.5 gcc 3.3 19 12-02-29 alex Y Y N Y i686/pc/cygwin gcc 3.3.1 0.8.0 04-05-30 alex Y Y N Y i686/pc/linux-gnu gcc 2.7.2 19.1 12-05-30 goetz Y Y Y Y (1) @@ -72,10 +73,12 @@ powerpc/unknown/openbsd3.6 gcc 2.95.3 0.10.0 06-10-08 alex Y Y N Y sparc/sun/solaris2.6 gcc 2.95.3 0.7.x-CVS 03-04-22 alex Y Y Y Y sparc/sun/solaris2.7 gcc 3.3 0.8.0 04-05-30 alex Y Y Y Y sparc/unkn./netbsdelf1.6.1 gcc 2.95.3 0.8.0 04-05-30 alex Y Y Y Y -x86_64/unknown/freebsd8.1 gcc 4.2.1 19 12-02-26 alex Y Y Y Y (3) +x86_64/apple/darwin12.2.0 gcc 4.2.1 20~rc1 12-11-13 alex Y Y Y Y (3) +x86_64/unknown/freebsd8.1 gcc 4.2.1 20~rc1 12-11-13 alex Y Y Y Y (3) x86_64/unkn./freebsd8.1-gnu gcc 4.4.5 19 12-02-26 alex Y Y Y Y (3) -x86_64/unknown/linux-gnu gcc 4.4.5 19 12-02-26 alex Y Y Y Y (1) -x86_64/unknown/openbsd4.7 gcc 3.3.5 19 12-02-26 alex Y Y Y Y (3) +x86_64/unknown/linux-gnu gcc 4.4.5 20~rc1 12-02-26 alex Y Y Y Y (1) +x86_64/unknown/openbsd4.7 gcc 3.3.5 20~rc1 12-02-26 alex Y Y Y Y (3) +x86_64/unknown/openbsd4.8 gcc 4.2.1 20~rc1 12-11-13 alex Y Y Y Y (3) Notes diff --git a/doc/Protocol.txt b/doc/Protocol.txt index 5093eea..39c5730 100644 --- a/doc/Protocol.txt +++ b/doc/Protocol.txt @@ -1,9 +1,8 @@ ngIRCd - Next Generation IRC Server + http://ngircd.barton.de/ - (c)2001-2008 Alexander Barton, - alex@barton.de, http://www.barton.de/ - + (c)2001-2012 Alexander Barton and Contributors. ngIRCd is free software and published under the terms of the GNU General Public License. @@ -82,11 +81,17 @@ The following are defined at the moment: - H: The server supports the "enhanced server handshake", see section II.2 for a detailed description. +- M: Changing client "metadata" (hostname, real name, ...) using the + METADATA command is supported. + - o: IRC operators are allowed to change channel- and channel-user-modes even if they aren't channel-operator of the affected channel. - S: The server supports the SERVICE command (on this link). +- X: Server supports XOP channel modes (owner, admin, halfop) and supports + these user prefixes in CHANINFO commands, for example. + - Z: Compressed server links are supported by the server. Example for a complete string: "ngircd|0.7.5:CZ". @@ -134,7 +139,7 @@ protocol which allows at max 15 arguments per command). Please see for details. The information exchanged using ISUPPORT can be used to detect configuration -incompatibilities (different maximum nick name length, for example) and +incompatibilities (different maximum nickname length, for example) and therefore to disconnect the peer prior to registering it in the network. @@ -181,3 +186,69 @@ first command sent to the server, even before USER and NICK commands! The must be set in the server configuration file to prevent unauthorized clients to fake their identity; it is an arbitrary string. + +II.5 Client character encoding conversion + + Command: CHARCONV + Parameters: + Used by: registered clients + Replies: RPL_IP_CHARCONV, ERR_IP_CHARCONV + +A client can set its character set encoding using the CHARCONV command: +after receiving such a command, the server translates all message data +received from the client using the set to the server +encoding (UTF-8), and all message data which is to be sent to the client +from the server encoding (UTF-8) to . + +The list of supported client character sets is implementation dependent. + +If a client sets its to the server encoding (UTF-8), +it disables all conversions; the connection behaves as if no CHARCONV +command has been sent at all in this session. + + +II.6 Update client "metadata" + + Command: METADATA + Parameters: + Used by: servers only + +The METADATA command is used on server-links to update "metadata" information +of clients, like the hostname, the info text ("real name"), or the user name. + +The server updates its client database according to the received and + parameters, and passes the METADATA command on to all the other +servers in the network that support this command (see section II.1 "Register +new server link", "M"), even if it doesn't support the given + itself: unknown names are ignored silently! + +The following names are defined: + + - "host": the hostname of a client (can't be empty) + - "cloakhost": the cloaked hostname of a client + - "info": info text ("real name") of a client + - "user": the user name of a client (can't be empty) + + +III. Numerics used by IRC+ Protocol +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The IRC+ protocol uses numerics in the range 800-899 which aren't used by +RFC 2812 and hopefully don't clash with other implementations ... + +Numerics 800-849 are used for status and success messages, and numerics +850-899 are failure and error messages. + + +III.1 IRC+ status and success numerics + +801 - RPL_IP_CHARCONV + %1 :Client encoding set" + + %1 client character set + + +III.2 IRC+ failure and error numerics + +851 - ERR_IP_CHARCONV + :Can't initialize client encoding diff --git a/doc/Services.txt b/doc/Services.txt index 944afd4..f51bd48 100644 --- a/doc/Services.txt +++ b/doc/Services.txt @@ -9,17 +9,20 @@ -- Services.txt -- -At the moment, ngIRCd doesn't implement a "special IRC services interface". -But services acting as a "regular server" are supported, either using the IRC -protocol defined in RFC 1459 or RFC 2812. +ngIRCd doesn't implement a "special IRC services interface", but services +acting as a "regular servers" ("pseudo servers") are supported, either +using the IRC protocol as defined in RFC 1459 or RFC 2812. -Support for Services has been tested using "IRC Services" version 5.x by -Andrew Church (), Anope 1.9 using a -preliminary protocol module for ngIRCd (), and -Atheme 7.0.2 or later. +Support for Services has been tested using + - Anope 1.9.8 or later (; unreleased!) + - Atheme 7.0.2 or later () + - "IRC Services" 5.1.x by Andrew Church () This document describes setting up ngIRCd and these services. +Please let us know if you are successfully using other IRC service packages or +which problems you encounter -- thanks! + Setting up ngIRCd ~~~~~~~~~~~~~~~~~ @@ -41,13 +44,21 @@ Example: Setting up Anope 1.9.x ~~~~~~~~~~~~~~~~~~~~~~ -Anope 1.9.4 (and above) can be used with ngIRCd using a preliminary "ngircd" -protocol module contained in our contrib/Anope/ directory. Please see the -file contrib/Anope/README for installation instructions! +Anope 1.9.8 or later (; unreleased as of 2012-11-10) +may be used with ngIRCd using the "ngircd" protocol module. +Until Anope 1.9.8 is released, you have to use the sources from the Anope +development GIT tree, see ! + +At least the following settings have to be tweaked, in addition to all the +settings marked as required by Anope: -After patching and installing Anope, at least the following configuration -variables have to be adjusted in data/services.conf, in addition to all the -settings marked as required: +In conf/services.conf: + + define + { + name = "services.host" + value = "services.irc.net" + } uplink { @@ -56,13 +67,46 @@ settings marked as required: password = "123abc" } - serverinfo + # Load ngIRCd protocol module + module { name = "ngircd" } + + networkinfo + { + # Must be set to the "MaxNickLength" setting of ngIRCd! + nicklen = 9 + + chanlen = 50 + } + +In conf/nickserv.conf: + + nickserv { - name = "services.irc.net" - type = "ngircd" + # not required if you are running ngIRCd with a higher nickname limit + # ("MaxNickLength") than 11 characters, but REQUIRED by default! + guestnickprefix = "G-" } +Setting up Atheme 7.0.2 or later +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Atheme 7.0.2 or later () may be used with ngIRCd using +the "ngircd" protocol module. + +The following settings need to be in atheme.conf: + + loadmodule "modules/protocol/ngircd"; + + uplink "server.irc.net" { + password = "123abc"; + port = 6667; + }; + +The documentation of Atheme can be found in the doc/ directory of the +Atheme source distribution. + + Setting up IRC Services 5.1.x ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -92,26 +136,3 @@ In modules.conf: The documentation of IRC Services can be found here: - - -Setting up Atheme 7.0.2 or later -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Atheme 7.0.2 or later may be used with ngIRCd using the "ngircd" protocol -module. - -The following settings need to be in atheme.conf: - -loadmodule "modules/protocol/ngircd"; - -uplink "server.irc.net" { - password = "123abc"; - port = 6667; -}; - -The documentation of Atheme can be found in the doc/ directory of the -Atheme source distribution. - - -Please let us know if you are successfully using other IRC service packages or -which problems you encounter, thanks! diff --git a/doc/sample-ngircd.conf.tmpl b/doc/sample-ngircd.conf.tmpl index e8b2fb0..997a983 100644 --- a/doc/sample-ngircd.conf.tmpl +++ b/doc/sample-ngircd.conf.tmpl @@ -95,11 +95,15 @@ # Maximum number of channels a user can be member of (0: no limit): ;MaxJoins = 10 - # Maximum length of an user nick name (Default: 9, as in RFC 2812). + # Maximum length of an user nickname (Default: 9, as in RFC 2812). # Please note that all servers in an IRC network MUST use the same - # maximum nick name length! + # maximum nickname length! ;MaxNickLength = 9 + # Maximum number of channels returned in response to a /list + # command (0: unlimited): + ;MaxListSize = 100 + # After seconds of inactivity the server will send a # PING to the peer to test whether it is alive or not. ;PingTimeout = 120 @@ -125,17 +129,19 @@ ;ChrootDir = /var/empty # Set this hostname for every client instead of the real one. - # Please note: don't use the percentage sign ("%"), it is reserved for - # future extensions! + # Use %x to add the hashed value of the original hostname. ;CloakHost = cloaked.host # Use this hostname for hostname cloaking on clients that have the # user mode "+x" set, instead of the name of the server. - # Please note: don't use the percentage sign ("%"), it is reserved for - # future extensions! + # Use %x to add the hashed value of the original hostname. ;CloakHostModeX = cloaked.user - # Set every clients' user name to their nick name + # The Salt for cloaked hostname hashing. When undefined a random + # hash is generated after each server start. + ;CloakHostSalt = abcdefghijklmnopqrstuvwxyz + + # Set every clients' user name to their nickname ;CloakUserToNick = yes # Try to connect to other IRC servers using IPv4 and IPv6, if possible. @@ -163,6 +169,9 @@ # they are not(!) channel-operators? ;OperCanUseMode = no + # Should IRC Operators get AutoOp (+o) in persistent (+P) channels? + ;OperChanPAutoOp = yes + # Mask IRC Operator mode requests as if they were coming from the # server? (This is a compatibility hack for ircd-irc2 servers) ;OperServerMode = no @@ -232,7 +241,7 @@ # [Operator] sections are used to define IRC Operators. There may be # more than one [Operator] block, one for each local operator. - # ID of the operator (may be different of the nick name) + # ID of the operator (may be different of the nickname) ;Name = TheOper # Password of the IRC operator @@ -295,15 +304,16 @@ # Connect to the remote server using TLS/SSL (Default: false) ;SSLConnect = yes - # Define a (case insensitive) mask matching nick names that should be - # treated as IRC services when introduced via this remote server. + # Define a (case insensitive) list of masks matching nicknames that + # should be treated as IRC services when introduced via this remote + # server, separated by commas (","). # REGULAR SERVERS DON'T NEED this parameter, so leave it empty # (which is the default). # When you are connecting IRC services which mask as a IRC server # and which use "virtual users" to communicate with, for example # "NickServ" and "ChanServ", you should set this parameter to - # something like "*Serv". - ;ServiceMask = *Serv + # something like "*Serv" or "NickServ,ChanServ,XyzServ". + ;ServiceMask = *Serv,Global [Server] # More [Server] sections, if you like ... diff --git a/man/Makefile.am b/man/Makefile.am index ebe9fce..5624e2a 100644 --- a/man/Makefile.am +++ b/man/Makefile.am @@ -17,7 +17,7 @@ TEMPLATE_MANS = ngircd.conf.5.tmpl ngircd.8.tmpl SUFFIXES = .tmpl . .tmpl: - sed \ + $(AM_V_GEN)sed \ -e s@:SBINDIR:@${sbindir}@ \ -e s@:BINDIR:@${bindir}@ \ -e s@:ETCDIR:@${sysconfdir}@ \ diff --git a/man/ngircd.8.tmpl b/man/ngircd.8.tmpl index f0703f3..318c045 100644 --- a/man/ngircd.8.tmpl +++ b/man/ngircd.8.tmpl @@ -1,30 +1,35 @@ .\" .\" ngircd(8) manual page template .\" -.TH ngircd 8 "Mar 2012" ngircd "ngIRCd Manual" +.TH ngircd 8 "Oct 2012" ngIRCd "ngIRCd Manual" .SH NAME -ngIRCd \- the next generation IRC daemon +ngIRCd \- the "next generation" IRC daemon .SH SYNOPSIS -.B ngircd [ +.B ngircd +[ .I Options -.B ] +] .SH DESCRIPTION .BR ngIRCd -is a free open source daemon for the Internet Relay Chat (IRC), -developed under the GNU General Public License (GPL). +is a free, portable and lightweight Internet Relay Chat server for small +or private networks, developed under the GNU General Public License (GPL). +It is easy to configure, can cope with dynamic IP addresses, and supports +IPv6, SSL-protected connections as well as PAM for authentication. +It is written from scratch and not based on the original IRCd. .PP -It's written from scratch and is not based upon the original IRCd like -many others. It is easy to configure, supports server links (even with -original ircd's) and runs on hosts with changing IP addresses (such as -dial-in networks). +The name ngIRCd means +.IR "next generation IRC daemon", +which is a little bit exaggerated: +.IR "lightweight Internet Relay Chat server" +most probably would have been a better name :-) .PP Currently supported platforms include AIX, A/UX, FreeBSD, HP-UX, IRIX, Linux, Mac OS X, NetBSD, OpenBSD, Solaris, and Windows with Cygwin. .PP As ngIRCd relies on UNIX standards and uses GNU automake and GNU autoconf there are good chances that it also supports other UNIX-based operating -systems as well. By default, ngIRCd writes diagnostic and informational messages using -the syslog mechanism. +systems as well. By default, ngIRCd writes diagnostic and informational +messages using the syslog mechanism. .SH OPTIONS The default behavior of .BR ngircd diff --git a/man/ngircd.conf.5.tmpl b/man/ngircd.conf.5.tmpl index 0473206..e3f62c8 100644 --- a/man/ngircd.conf.5.tmpl +++ b/man/ngircd.conf.5.tmpl @@ -1,7 +1,7 @@ .\" .\" ngircd.conf(5) manual page template .\" -.TH ngircd.conf 5 "Mar 2012" ngircd "ngIRCd Manual" +.TH ngircd.conf 5 "Nov 2012" ngIRCd "ngIRCd Manual" .SH NAME ngircd.conf \- configuration file of ngIRCd .SH SYNOPSIS @@ -178,10 +178,13 @@ Maximum number of channels a user can be member of (0: no limit). Default: 10. .TP \fBMaxNickLength\fR (number) -Maximum length of an user nick name (Default: 9, as in RFC 2812). Please -note that all servers in an IRC network MUST use the same maximum nick name +Maximum length of an user nickname (Default: 9, as in RFC 2812). Please +note that all servers in an IRC network MUST use the same maximum nickname length! .TP +\fBMaxListSize\fR (number) +Maximum number of channels returned in response to a LIST command. Default: 100. +.TP \fBPingTimeout\fR (number) After seconds of inactivity the server will send a PING to the peer to test whether it is alive or not. Default: 120. @@ -212,27 +215,19 @@ For this to work the server must have been started with root privileges! .TP \fBCloakHost\fR (string) Set this hostname for every client instead of the real one. Default: empty, -don't change. -.PP -.RS -.B Please note: -.br -Don't use the percentage sign ("%"), it is reserved for future extensions! -.RE +don't change. Use %x to add the hashed value of the original hostname. .TP \fBCloakHostModeX\fR (string) Use this hostname for hostname cloaking on clients that have the user mode "+x" set, instead of the name of the server. Default: empty, use the name -of the server. -.PP -.RS -.B Please note: -.br -Don't use the percentage sign ("%"), it is reserved for future extensions! -.RE +of the server. Use %x to add the hashed value of the original hostname +.TP +\fBCloakHostSalt\fR (string) +The Salt for cloaked hostname hashing. When undefined a random hash is +generated after each server start. .TP \fBCloakUserToNick\fR (boolean) -Set every clients' user name to their nick name and hide the one supplied +Set every clients' user name to their nickname and hide the one supplied by the IRC client. Default: no. .TP \fBConnectIPv4\fR (boolean) @@ -276,6 +271,10 @@ while connecting. Default: no. Should IRC Operators be allowed to use the MODE command even if they are not(!) channel-operators? Default: no. .TP +\fBOperChanPAutoOp\fR (boolean) +Should IRC Operators get AutoOp (+o) in persistent (+P) channels? +Default: yes. +.TP \fBOperServerMode\fR (boolean) If \fBOperCanUseMode\fR is enabled, this may lead the compatibility problems with Servers that run the ircd-irc2 Software. This Option "masks" mode @@ -370,7 +369,7 @@ sections are used to define IRC Operators. There may be more than one block, one for each local operator. .TP \fBName\fR (string) -ID of the operator (may be different of the nick name). +ID of the operator (may be different of the nickname). .TP \fBPassword\fR (string) Password of the IRC operator. @@ -430,14 +429,16 @@ You can use the IRC Operator command CONNECT later on to create the link. Connect to the remote server using TLS/SSL. Default: false. .TP \fBServiceMask\fR (string) -Define a (case insensitive) mask matching nick names that should be treated as -IRC services when introduced via this remote server. REGULAR SERVERS DON'T NEED -this parameter, so leave it empty (which is the default). +Define a (case insensitive) list of masks matching nicknames that should be +treated as IRC services when introduced via this remote server, separated +by commas (","). REGULAR SERVERS DON'T NEED this parameter, so leave it empty +(which is the default). .PP .RS When you are connecting IRC services which mask as a IRC server and which use "virtual users" to communicate with, for example "NickServ" and "ChanServ", -you should set this parameter to something like "*Serv". +you should set this parameter to something like "*Serv", "*Serv,OtherNick", +or "NickServ,ChanServ,XyzServ". .SH [CHANNEL] Pre-defined channels can be configured in .I [Channel] diff --git a/src/ipaddr/.gitignore b/src/ipaddr/.gitignore new file mode 100644 index 0000000..08a6d72 --- /dev/null +++ b/src/ipaddr/.gitignore @@ -0,0 +1 @@ +Makefile.am diff --git a/src/ipaddr/Makefile.am b/src/ipaddr/Makefile.am deleted file mode 100644 index fcbb7cf..0000000 --- a/src/ipaddr/Makefile.am +++ /dev/null @@ -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- diff --git a/src/ipaddr/Makefile.ng b/src/ipaddr/Makefile.ng new file mode 100644 index 0000000..ecfce29 --- /dev/null +++ b/src/ipaddr/Makefile.ng @@ -0,0 +1,21 @@ +# +# ipaddr/Makefile.am +# (c) 2008 Florian Westphal , public domain. +# + +__ng_Makefile_am_template__ + +EXTRA_DIST = Makefile.ng + +AM_CPPFLAGS = -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 Makefile.am + +# -eof- diff --git a/src/ngircd/.gitignore b/src/ngircd/.gitignore index c25ba5e..d1148bf 100644 --- a/src/ngircd/.gitignore +++ b/src/ngircd/.gitignore @@ -1,3 +1,4 @@ +Makefile.am check-help check-version ngircd diff --git a/src/ngircd/Makefile.am b/src/ngircd/Makefile.am deleted file mode 100644 index 3a411a9..0000000 --- a/src/ngircd/Makefile.am +++ /dev/null @@ -1,144 +0,0 @@ -# -# ngIRCd -- The Next Generation IRC Daemon -# Copyright (c)2001-2012 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. -# - -AUTOMAKE_OPTIONS = ../portab/ansi2knr - -INCLUDES = -I$(srcdir)/../portab -I$(srcdir)/../tool -I$(srcdir)/../ipaddr - -LINTARGS = -weak -warnunixlib +unixlib -booltype BOOLEAN \ - -varuse -retvalother -emptyret -unrecog - -sbin_PROGRAMS = ngircd - -ngircd_SOURCES = \ - ngircd.c \ - array.c \ - channel.c \ - class.c \ - client.c \ - client-cap.c \ - conf.c \ - conn.c \ - conn-func.c \ - conn-ssl.c \ - conn-zip.c \ - hash.c \ - io.c \ - irc.c \ - irc-cap.c \ - irc-channel.c \ - irc-info.c \ - irc-login.c \ - irc-mode.c \ - irc-op.c \ - irc-oper.c \ - irc-server.c \ - irc-write.c \ - lists.c \ - log.c \ - login.c \ - match.c \ - numeric.c \ - op.c \ - pam.c \ - parse.c \ - proc.c \ - resolve.c \ - sighandlers.c - -ngircd_LDFLAGS = -L../portab -L../tool -L../ipaddr - -ngircd_LDADD = -lngportab -lngtool -lngipaddr - -noinst_HEADERS = \ - ngircd.h \ - array.h \ - channel.h \ - class.h \ - client.h \ - client-cap.h \ - conf.h \ - conf-ssl.h \ - conn.h \ - conn-func.h \ - conn-ssl.h \ - conn-zip.h \ - defines.h \ - hash.h \ - io.h \ - irc.h \ - irc-cap.h \ - irc-channel.h \ - irc-info.h \ - irc-login.h \ - irc-mode.h \ - irc-op.h \ - irc-oper.h \ - irc-server.h \ - irc-write.h \ - lists.h \ - log.h \ - login.h \ - match.h \ - messages.h \ - numeric.h \ - op.h \ - pam.h \ - parse.h \ - proc.h \ - resolve.h \ - sighandlers.h - -clean-local: - rm -f check-version check-help lint.out - -maintainer-clean-local: - rm -f Makefile Makefile.in - -check-version: Makefile - echo "#!/bin/sh" > check-version - echo "./ngircd --version | grep ngircd >/dev/null 2>&1" >>check-version - chmod 755 check-version - -check-help: Makefile - echo "#!/bin/sh" > check-help - echo "./ngircd --help | grep help >/dev/null 2>&1" >>check-help - chmod 755 check-help - -lint: - @splint --version >/dev/null 2>&1 \ - || ( echo; echo "Error: \"splint\" not found!"; echo; exit 1 ) - @echo; warnings=0; files=0; \ - for f in *.c; do \ - echo "checking $$f ..."; \ - splint $$f $(LINTARGS) -I$(srcdir) -I$(srcdir)/.. \ - $(INCLUDES) $(AM_CFLAGS) >lint.out 2>&1; \ - grep "no warnings" lint.out > /dev/null 2>&1; \ - if [ $$? -ne 0 ]; then \ - waswarning=1; \ - echo; grep -v "^Command Line: " lint.out; echo; \ - w=$$( grep "code warning" lint.out | $(AWK) "{ print \$$4 }" ); \ - [ "$$w" -gt 0 ] && warnings=`expr $$warnings + $$w`; \ - files=`expr $$files + 1`; \ - else \ - waswarning=0; \ - fi; \ - rm -f lint.out; \ - done; \ - [ $$waswarning -eq 0 ] && echo; \ - [ $$warnings -gt 0 ] \ - && echo "Result: $$warnings warning(s) in $$files file(s)!" \ - || echo "Result: no warnings found."; \ - echo; [ $$warnings -gt 0 ] && exit 1 - -TESTS = check-version check-help - -# -eof- diff --git a/src/ngircd/Makefile.ng b/src/ngircd/Makefile.ng new file mode 100644 index 0000000..cdbd27c --- /dev/null +++ b/src/ngircd/Makefile.ng @@ -0,0 +1,152 @@ +# +# ngIRCd -- The Next Generation IRC Daemon +# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors +# +# 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. +# + +__ng_Makefile_am_template__ + +EXTRA_DIST = Makefile.ng + +AM_CPPFLAGS = -I$(srcdir)/../portab -I$(srcdir)/../tool -I$(srcdir)/../ipaddr + +LINTARGS = -weak -warnunixlib +unixlib -booltype BOOLEAN \ + -varuse -retvalother -emptyret -unrecog + +sbin_PROGRAMS = ngircd + +ngircd_SOURCES = \ + ngircd.c \ + array.c \ + channel.c \ + class.c \ + client.c \ + client-cap.c \ + conf.c \ + conn.c \ + conn-encoding.c \ + conn-func.c \ + conn-ssl.c \ + conn-zip.c \ + hash.c \ + io.c \ + irc.c \ + irc-cap.c \ + irc-channel.c \ + irc-encoding.c \ + irc-info.c \ + irc-login.c \ + irc-metadata.c \ + irc-mode.c \ + irc-op.c \ + irc-oper.c \ + irc-server.c \ + irc-write.c \ + lists.c \ + log.c \ + login.c \ + match.c \ + numeric.c \ + op.c \ + pam.c \ + parse.c \ + proc.c \ + resolve.c \ + sighandlers.c + +ngircd_LDFLAGS = -L../portab -L../tool -L../ipaddr + +ngircd_LDADD = -lngportab -lngtool -lngipaddr + +noinst_HEADERS = \ + ngircd.h \ + array.h \ + channel.h \ + class.h \ + client.h \ + client-cap.h \ + conf.h \ + conf-ssl.h \ + conn.h \ + conn-encoding.h \ + conn-func.h \ + conn-ssl.h \ + conn-zip.h \ + defines.h \ + hash.h \ + io.h \ + irc.h \ + irc-cap.h \ + irc-channel.h \ + irc-encoding.h \ + irc-info.h \ + irc-login.h \ + irc-metadata.h \ + irc-mode.h \ + irc-op.h \ + irc-oper.h \ + irc-server.h \ + irc-write.h \ + lists.h \ + log.h \ + login.h \ + match.h \ + messages.h \ + numeric.h \ + op.h \ + pam.h \ + parse.h \ + proc.h \ + resolve.h \ + sighandlers.h + +clean-local: + rm -f check-version check-help lint.out + +maintainer-clean-local: + rm -f Makefile Makefile.in Makefile.am + +check-version: Makefile + echo "#!/bin/sh" > check-version + echo "./ngircd --version | grep ngircd >/dev/null 2>&1" >>check-version + chmod 755 check-version + +check-help: Makefile + echo "#!/bin/sh" > check-help + echo "./ngircd --help | grep help >/dev/null 2>&1" >>check-help + chmod 755 check-help + +lint: + @splint --version >/dev/null 2>&1 \ + || ( echo; echo "Error: \"splint\" not found!"; echo; exit 1 ) + @echo; warnings=0; files=0; \ + for f in *.c; do \ + echo "checking $$f ..."; \ + splint $$f $(LINTARGS) -I$(srcdir) -I$(srcdir)/.. \ + $(AM_CPPFLAGS) $(AM_CFLAGS) >lint.out 2>&1; \ + grep "no warnings" lint.out > /dev/null 2>&1; \ + if [ $$? -ne 0 ]; then \ + waswarning=1; \ + echo; grep -v "^Command Line: " lint.out; echo; \ + w=$$( grep "code warning" lint.out | $(AWK) "{ print \$$4 }" ); \ + [ "$$w" -gt 0 ] && warnings=`expr $$warnings + $$w`; \ + files=`expr $$files + 1`; \ + else \ + waswarning=0; \ + fi; \ + rm -f lint.out; \ + done; \ + [ $$waswarning -eq 0 ] && echo; \ + [ $$warnings -gt 0 ] \ + && echo "Result: $$warnings warning(s) in $$files file(s)!" \ + || echo "Result: no warnings found."; \ + echo; [ $$warnings -gt 0 ] && exit 1 + +TESTS = check-version check-help + +# -eof- diff --git a/src/ngircd/channel.c b/src/ngircd/channel.c index ff47024..00aafe0 100644 --- a/src/ngircd/channel.c +++ b/src/ngircd/channel.c @@ -66,16 +66,8 @@ static void Set_KeyFile PARAMS((CHANNEL *Chan, const char *KeyFile)); GLOBAL void Channel_Init( void ) { - CHANNEL *sc; - My_Channels = NULL; My_Cl2Chan = NULL; - - sc = Channel_Create("&SERVER"); - if (sc) { - Channel_SetModes(sc, "mnPt"); - Channel_SetTopic(sc, Client_ThisServer(), "Server Messages"); - } } /* Channel_Init */ @@ -103,11 +95,12 @@ Channel_GetListInvites(CHANNEL *c) } +/** + * Generate predefined persistent channels and &SERVER + */ GLOBAL void Channel_InitPredefined( void ) { - /* Generate predefined persistent channels */ - CHANNEL *new_chan; const struct Conf_Channel *conf_chan; const char *c; @@ -160,6 +153,18 @@ Channel_InitPredefined( void ) } if (channel_count) array_free(&Conf_Channels); + + /* Make sure the local &SERVER channel exists */ + if (!Channel_Search("&SERVER")) { + new_chan = Channel_Create("&SERVER"); + if (new_chan) { + Channel_SetModes(new_chan, "mnPt"); + Channel_SetTopic(new_chan, Client_ThisServer(), + "Server Messages"); + } else + Log(LOG_ERR, "Failed to create \"&SERVER\" channel!"); + } else + LogDebug("Required channel \"&SERVER\" already exists, ok."); } /* Channel_InitPredefined */ @@ -294,6 +299,8 @@ Channel_Kick(CLIENT *Peer, CLIENT *Target, CLIENT *Origin, const char *Name, const char *Reason ) { CHANNEL *chan; + char *ptr, *target_modes; + bool can_kick = false; assert(Peer != NULL); assert(Target != NULL); @@ -314,14 +321,63 @@ Channel_Kick(CLIENT *Peer, CLIENT *Target, CLIENT *Origin, const char *Name, /* Check that user is on the specified channel */ if (!Channel_IsMemberOf(chan, Origin)) { IRC_WriteStrClient( Origin, ERR_NOTONCHANNEL_MSG, - Client_ID(Origin), Name); + Client_ID(Origin), Name); return; } + } + + if(Client_Type(Peer) == CLIENT_USER) { + /* Channel mode 'Q' and user mode 'q' on target: nobody but + * IRC Operators and servers can kick the target user */ + if ((strchr(Channel_Modes(chan), 'Q') + || Client_HasMode(Target, 'q') + || Client_Type(Target) == CLIENT_SERVICE) + && !Client_HasMode(Origin, 'o')) { + IRC_WriteStrClient(Origin, ERR_KICKDENY_MSG, + Client_ID(Origin), Name, + Client_ID(Target)); + return; + } + + /* Check if client has the rights to kick target */ + ptr = Channel_UserModes(chan, Peer); + target_modes = Channel_UserModes(chan, Target); + while(*ptr) { + /* Owner can kick everyone */ + if ( *ptr == 'q') { + can_kick = true; + break; + } + /* Admin can't kick owner */ + if ( *ptr == 'a' ) { + if (!strchr(target_modes, 'q')) { + can_kick = true; + break; + } + } + /* Op can't kick owner | admin */ + if ( *ptr == 'o' ) { + if (!strchr(target_modes, 'q') && + !strchr(target_modes, 'a')) { + can_kick = true; + break; + } + } + /* Half Op can't kick owner | admin | op */ + if ( *ptr == 'h' ) { + if (!strchr(target_modes, 'q') && + !strchr(target_modes, 'a') && + !strchr(target_modes, 'o')) { + can_kick = true; + break; + } + } + ptr++; + } - /* Check if user has operator status */ - if (!strchr(Channel_UserModes(chan, Origin), 'o')) { - IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, - Client_ID(Origin), Name); + if(!can_kick) { + IRC_WriteStrClient(Origin, ERR_CHANOPPRIVTOOLOW_MSG, + Client_ID(Origin), Name); return; } } @@ -807,9 +863,9 @@ Channel_SetMaxUsers(CHANNEL *Chan, unsigned long Count) static bool Can_Send_To_Channel(CHANNEL *Chan, CLIENT *From) { - bool is_member, has_voice, is_op; + bool is_member, has_voice, is_halfop, is_op, is_chanadmin, is_owner; - is_member = has_voice = is_op = false; + is_member = has_voice = is_halfop = is_op = is_chanadmin = is_owner = false; /* The server itself always can send messages :-) */ if (Client_ThisServer() == From) @@ -819,8 +875,14 @@ Can_Send_To_Channel(CHANNEL *Chan, CLIENT *From) is_member = true; if (strchr(Channel_UserModes(Chan, From), 'v')) has_voice = true; + if (strchr(Channel_UserModes(Chan, From), 'h')) + is_halfop = true; if (strchr(Channel_UserModes(Chan, From), 'o')) is_op = true; + if (strchr(Channel_UserModes(Chan, From), 'a')) + is_chanadmin = true; + if (strchr(Channel_UserModes(Chan, From), 'q')) + is_owner = true; } /* @@ -832,7 +894,11 @@ Can_Send_To_Channel(CHANNEL *Chan, CLIENT *From) if (strchr(Channel_Modes(Chan), 'n') && !is_member) return false; - if (is_op || has_voice) + if (strchr(Channel_Modes(Chan), 'M') && !Client_HasMode(From, 'R') + && !Client_HasMode(From, 'o')) + return false; + + if (has_voice || is_halfop || is_op || is_chanadmin || is_owner) return true; if (strchr(Channel_Modes(Chan), 'm')) @@ -852,7 +918,11 @@ Channel_Write(CHANNEL *Chan, CLIENT *From, CLIENT *Client, const char *Command, if (!Can_Send_To_Channel(Chan, From)) { if (! SendErrors) return CONNECTED; /* no error, see RFC 2812 */ - return IRC_WriteStrClient(From, ERR_CANNOTSENDTOCHAN_MSG, + if (strchr(Channel_Modes(Chan), 'M')) + return IRC_WriteStrClient(From, ERR_NEEDREGGEDNICK_MSG, + Client_ID(From), Channel_Name(Chan)); + else + return IRC_WriteStrClient(From, ERR_CANNOTSENDTOCHAN_MSG, Client_ID(From), Channel_Name(Chan)); } @@ -1187,64 +1257,6 @@ Channel_CheckKey(CHANNEL *Chan, CLIENT *Client, const char *Key) } /* Channel_CheckKey */ -/** - * Check wether a client is allowed to administer a channel or not. - * - * @param Chan The channel to test. - * @param Client The client from which the command has been received. - * @param Origin The originator of the command (or NULL). - * @param OnChannel Set to true if the originator is member of the channel. - * @param AdminOk Set to true if the client is allowed to do - * administrative tasks on this channel. - * @param UseServerMode Set to true if ngIRCd should emulate "server mode", - * that is send commands as if originating from a server - * and not the originator of the command. - */ -GLOBAL void -Channel_CheckAdminRights(CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, - bool *OnChannel, bool *AdminOk, bool *UseServerMode) -{ - assert (Chan != NULL); - assert (Client != NULL); - assert (OnChannel != NULL); - assert (AdminOk != NULL); - assert (UseServerMode != NULL); - - /* Use the client as origin, if no origin has been given (no prefix?) */ - if (!Origin) - Origin = Client; - - *OnChannel = false; - *AdminOk = false; - *UseServerMode = false; - - if (Client_Type(Client) != CLIENT_USER - && Client_Type(Client) != CLIENT_SERVER - && Client_Type(Client) != CLIENT_SERVICE) - return; - - /* Allow channel administration if the client is a server or service */ - if (Client_Type(Client) != CLIENT_USER) { - *AdminOk = true; - return; - } - - *OnChannel = Channel_IsMemberOf(Chan, Origin); - - if (*OnChannel && strchr(Channel_UserModes(Chan, Origin), 'o')) { - /* User is a channel operator */ - *AdminOk = true; - } else if (Conf_OperCanMode) { - /* IRC operators are allowed to administer channels as well */ - if (Client_OperByMe(Origin)) { - *AdminOk = true; - if (Conf_OperServerMode) - *UseServerMode = true; - } - } -} /* Channel_CheckAdminRights */ - - static CL2CHAN * Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan ) { diff --git a/src/ngircd/client.c b/src/ngircd/client.c index e203cdd..2114f84 100644 --- a/src/ngircd/client.c +++ b/src/ngircd/client.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2010 Alexander Barton (alex@barton.de) + * Copyright (c)2001-2012 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 @@ -331,9 +331,15 @@ Client_SetHostname( CLIENT *Client, const char *Hostname ) assert(Hostname != NULL); if (strlen(Conf_CloakHost)) { + char cloak[GETID_LEN]; + + strlcpy(cloak, Hostname, GETID_LEN); + strlcat(cloak, Conf_CloakHostSalt, GETID_LEN); + snprintf(cloak, GETID_LEN, Conf_CloakHost, Hash(cloak)); + LogDebug("Updating hostname of \"%s\": \"%s\" -> \"%s\"", - Client_ID(Client), Client->host, Conf_CloakHost); - strlcpy(Client->host, Conf_CloakHost, sizeof(Client->host)); + Client_ID(Client), Client->host, cloak); + strlcpy(Client->host, cloak, sizeof(Client->host)); } else { LogDebug("Updating hostname of \"%s\": \"%s\" -> \"%s\"", Client_ID(Client), Client->host, Hostname); @@ -435,18 +441,6 @@ Client_SetFlags( CLIENT *Client, const char *Flags ) GLOBAL void -Client_SetPassword( CLIENT *Client, const char *Pwd ) -{ - /* set password sent by client */ - - assert( Client != NULL ); - assert( Pwd != NULL ); - - strlcpy(Client->pwd, Pwd, sizeof(Client->pwd)); -} /* Client_SetPassword */ - - -GLOBAL void Client_SetAway( CLIENT *Client, const char *Txt ) { /* Set AWAY reason of client */ @@ -677,7 +671,6 @@ Client_OrigUser(CLIENT *Client) { #endif - /** * Return the hostname of a client. * @param Client Pointer to client structure @@ -688,33 +681,88 @@ Client_Hostname(CLIENT *Client) { assert (Client != NULL); return Client->host; -} /* Client_Hostname */ +} +/** + * Return the cloaked hostname of a client, if set. + * @param Client Pointer to the client structure. + * @return Pointer to the cloaked hostname or NULL if not set. + */ +GLOBAL char * +Client_HostnameCloaked(CLIENT *Client) +{ + assert(Client != NULL); + return Client->cloaked; +} /** - * Get potentially cloaked hostname of a client. + * Get (potentially cloaked) hostname of a client to display it to other users. + * * If the client has not enabled cloaking, the real hostname is used. + * Please note that this function uses a global static buffer, so you can't + * nest invocations without overwriting earlier results! + * * @param Client Pointer to client structure * @return Pointer to client hostname */ GLOBAL char * -Client_HostnameCloaked(CLIENT *Client) +Client_HostnameDisplayed(CLIENT *Client) { assert(Client != NULL); - if (Client_HasMode(Client, 'x')) - return Client_ID(Client->introducer); - else + + /* Client isn't cloaked at all, return real hostname: */ + if (!Client_HasMode(Client, 'x')) return Client_Hostname(Client); -} /* Client_HostnameCloaked */ + /* Use an already saved cloaked hostname, if there is one */ + if (Client->cloaked[0]) + return Client->cloaked; -GLOBAL char * -Client_Password( CLIENT *Client ) + Client_UpdateCloakedHostname(Client, NULL, NULL); + return Client->cloaked; +} + +/** + * Update (and generate, if necessary) the cloaked hostname of a client. + * + * The newly set cloaked hostname is announced in the network using METADATA + * commands to peers that support this feature. + * + * @param Client The client of which the cloaked hostname should be updated. + * @param Origin The originator of the hostname change, or NULL if this server. + * @param Hostname The new cloaked hostname, or NULL if it should be generated. + */ +GLOBAL void +Client_UpdateCloakedHostname(CLIENT *Client, CLIENT *Origin, + const char *Hostname) { - assert( Client != NULL ); - return Client->pwd; -} /* Client_Password */ + static char Cloak_Buffer[CLIENT_HOST_LEN]; + assert(Client != NULL); + if (!Origin) + Origin = Client_ThisServer(); + + if (!Hostname) { + /* Generate new cloaked hostname */ + if (*Conf_CloakHostModeX) { + strlcpy(Cloak_Buffer, Client->host, CLIENT_HOST_LEN); + strlcat(Cloak_Buffer, Conf_CloakHostSalt, + CLIENT_HOST_LEN); + snprintf(Client->cloaked, sizeof(Client->cloaked), + Conf_CloakHostModeX, Hash(Cloak_Buffer)); + } else + strlcpy(Client->cloaked, Client_ID(Client->introducer), + sizeof(Client->cloaked)); + } else + strlcpy(Client->cloaked, Hostname, sizeof(Client->cloaked)); + LogDebug("Cloaked hostname of \"%s\" updated to \"%s\"", + Client_ID(Client), Client->cloaked); + + /* Inform other servers in the network */ + IRC_WriteStrServersPrefixFlag(Client_NextHop(Origin), Origin, 'M', + "METADATA %s cloakhost :%s", + Client_ID(Client), Client->cloaked); +} GLOBAL char * Client_Modes( CLIENT *Client ) @@ -806,10 +854,12 @@ Client_Mask( CLIENT *Client ) /** * Return ID of a client with cloaked hostname: "client!user@server-name" + * * This client ID is used for IRC prefixes, for example. * Please note that this function uses a global static buffer, so you can't * nest invocations without overwriting earlier results! * If the client has not enabled cloaking, the real hostname is used. + * * @param Client Pointer to client structure * @return Pointer to global buffer containing the client ID */ @@ -822,12 +872,11 @@ Client_MaskCloaked(CLIENT *Client) /* Is the client using cloaking at all? */ if (!Client_HasMode(Client, 'x')) - return Client_Mask(Client); + return Client_Mask(Client); + + snprintf(Mask_Buffer, GETID_LEN, "%s!%s@%s", Client->id, Client->user, + Client_HostnameDisplayed(Client)); - snprintf(Mask_Buffer, GETID_LEN, "%s!%s@%s", - Client->id, Client->user, - *Conf_CloakHostModeX ? Conf_CloakHostModeX - : Client_ID(Client->introducer)); return Mask_Buffer; } /* Client_MaskCloaked */ @@ -871,7 +920,7 @@ Client_Away( CLIENT *Client ) * the appropriate error messages. * * @param Client Client that wants to change the nickname. - * @param Nick New nick name. + * @param Nick New nickname. * @returns true if nickname is valid, false otherwise. */ GLOBAL bool @@ -891,6 +940,16 @@ Client_CheckNick(CLIENT *Client, char *Nick) return false; } + if (Client_Type(Client) != CLIENT_SERVER + && Client_Type(Client) != CLIENT_SERVICE) { + /* Make sure that this isn't a restricted/forbidden nickname */ + if (Conf_NickIsBlocked(Nick)) { + IRC_WriteStrClient(Client, ERR_FORBIDDENNICKNAME_MSG, + Client_ID(Client), Nick); + return false; + } + } + /* Nickname already registered? */ if (Client_Search(Nick)) { IRC_WriteStrClient(Client, ERR_NICKNAMEINUSE_MSG, @@ -1161,7 +1220,7 @@ Client_Introduce(CLIENT *From, CLIENT *Client, int Type) Client_SetType(Client, Type); if (From) { - if (Conf_IsService(Conf_GetServer(Client_Conn(From)), + if (Conf_NickIsService(Conf_GetServer(Client_Conn(From)), Client_ID(Client))) Client_SetType(Client, CLIENT_SERVICE); LogDebug("%s \"%s\" (+%s) registered (via %s, on %s, %d hop%s).", @@ -1325,7 +1384,7 @@ Client_RegisterWhowas( CLIENT *Client ) sizeof( My_Whowas[slot].id )); strlcpy( My_Whowas[slot].user, Client_User( Client ), sizeof( My_Whowas[slot].user )); - strlcpy( My_Whowas[slot].host, Client_HostnameCloaked( Client ), + strlcpy( My_Whowas[slot].host, Client_HostnameDisplayed( Client ), sizeof( My_Whowas[slot].host )); strlcpy( My_Whowas[slot].info, Client_Info( Client ), sizeof( My_Whowas[slot].info )); diff --git a/src/ngircd/client.h b/src/ngircd/client.h index 4dbcc7a..ebbd06c 100644 --- a/src/ngircd/client.h +++ b/src/ngircd/client.h @@ -47,8 +47,8 @@ typedef struct _CLIENT CONN_ID conn_id; /* ID of the connection (if local) or NONE (remote) */ struct _CLIENT *introducer; /* ID of the servers which the client is connected to */ struct _CLIENT *topserver; /* toplevel servers (only valid if client is a server) */ - char pwd[CLIENT_PASS_LEN]; /* password received of the client */ char host[CLIENT_HOST_LEN]; /* hostname of the client */ + char cloaked[CLIENT_HOST_LEN]; /* cloaked hostname of the client */ char user[CLIENT_USER_LEN]; /* user name ("login") */ #if defined(PAM) && defined(IDENTAUTH) char orig_user[CLIENT_USER_LEN];/* user name supplied by USER command */ @@ -72,7 +72,7 @@ typedef POINTER CLIENT; typedef struct _WHOWAS { time_t time; /* time stamp of entry or 0 if unused */ - char id[CLIENT_NICK_LEN]; /* client nick name */ + char id[CLIENT_NICK_LEN]; /* client nickname */ char host[CLIENT_HOST_LEN]; /* hostname of the client */ char user[CLIENT_USER_LEN]; /* user name ("login") */ char info[CLIENT_INFO_LEN]; /* long user name */ @@ -108,8 +108,8 @@ GLOBAL char *Client_User PARAMS(( CLIENT *Client )); GLOBAL char *Client_OrigUser PARAMS(( CLIENT *Client )); #endif GLOBAL char *Client_Hostname PARAMS(( CLIENT *Client )); -GLOBAL char *Client_HostnameCloaked PARAMS(( CLIENT *Client )); -GLOBAL char *Client_Password PARAMS(( CLIENT *Client )); +GLOBAL char *Client_HostnameCloaked PARAMS((CLIENT *Client)); +GLOBAL char *Client_HostnameDisplayed PARAMS(( CLIENT *Client )); GLOBAL char *Client_Modes PARAMS(( CLIENT *Client )); GLOBAL char *Client_Flags PARAMS(( CLIENT *Client )); GLOBAL CLIENT *Client_Introducer PARAMS(( CLIENT *Client )); @@ -129,7 +129,6 @@ GLOBAL void Client_SetID PARAMS(( CLIENT *Client, const char *Nick )); GLOBAL void Client_SetUser PARAMS(( CLIENT *Client, const char *User, bool Idented )); GLOBAL void Client_SetOrigUser PARAMS(( CLIENT *Client, const char *User )); GLOBAL void Client_SetInfo PARAMS(( CLIENT *Client, const char *Info )); -GLOBAL void Client_SetPassword PARAMS(( CLIENT *Client, const char *Pwd )); GLOBAL void Client_SetType PARAMS(( CLIENT *Client, int Type )); GLOBAL void Client_SetHops PARAMS(( CLIENT *Client, int Hops )); GLOBAL void Client_SetToken PARAMS(( CLIENT *Client, int Token )); @@ -169,6 +168,10 @@ GLOBAL void Client_Reject PARAMS((CLIENT *Client, const char *Reason, bool InformClient)); GLOBAL void Client_Introduce PARAMS((CLIENT *From, CLIENT *Client, int Type)); +GLOBAL void Client_UpdateCloakedHostname PARAMS((CLIENT *Client, + CLIENT *Originator, + const char *hostname)); + #ifdef DEBUG GLOBAL void Client_DebugDump PARAMS((void)); diff --git a/src/ngircd/conf-ssl.h b/src/ngircd/conf-ssl.h index 3fab579..22897ef 100644 --- a/src/ngircd/conf-ssl.h +++ b/src/ngircd/conf-ssl.h @@ -33,19 +33,15 @@ struct ConnSSL_State { SSL *ssl; #endif #ifdef HAVE_LIBGNUTLS - gnutls_session gnutls_session; + gnutls_session_t gnutls_session; void *cookie; /* pointer to server configuration structure (for outgoing connections), or NULL. */ #endif }; -bool -ConnSSL_InitLibrary(void); -#else -static inline bool -ConnSSL_InitLibrary(void) -{ return true; } -#endif /* SSL_SUPPORT */ +#endif + +bool ConnSSL_InitLibrary(void); #endif /* conf_ssl_h */ diff --git a/src/ngircd/conf.c b/src/ngircd/conf.c index 5f7b24f..bea4d61 100644 --- a/src/ngircd/conf.c +++ b/src/ngircd/conf.c @@ -18,6 +18,7 @@ #include "imp.h" #include +#include #include #ifdef PROTOTYPES # include @@ -34,9 +35,6 @@ #include #include -#ifdef HAVE_CTYPE_H -# include -#endif #include "array.h" #include "ngircd.h" @@ -106,6 +104,8 @@ ConfSSL_Init(void) free(Conf_SSLOptions.DHFile); Conf_SSLOptions.DHFile = NULL; array_free_wipe(&Conf_SSLOptions.KeyFilePassword); + + array_free(&Conf_SSLOptions.ListenPorts); } /** @@ -346,10 +346,11 @@ Conf_Test( void ) puts("[LIMITS]"); printf(" ConnectRetry = %d\n", Conf_ConnectRetry); - printf(" MaxConnections = %ld\n", Conf_MaxConnections); + printf(" MaxConnections = %d\n", Conf_MaxConnections); printf(" MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP); printf(" MaxJoins = %d\n", Conf_MaxJoins > 0 ? Conf_MaxJoins : -1); printf(" MaxNickLength = %u\n", Conf_MaxNickLength - 1); + printf(" MaxListSize = %d\n", Conf_MaxListSize); printf(" PingTimeout = %d\n", Conf_PingTimeout); printf(" PongTimeout = %d\n", Conf_PongTimeout); puts(""); @@ -359,6 +360,7 @@ Conf_Test( void ) printf(" ChrootDir = %s\n", Conf_Chroot); printf(" CloakHost = %s\n", Conf_CloakHost); printf(" CloakHostModeX = %s\n", Conf_CloakHostModeX); + printf(" CloakHostSalt = %s\n", Conf_CloakHostSalt); printf(" CloakUserToNick = %s\n", yesno_to_str(Conf_CloakUserToNick)); #ifdef WANT_IPV6 printf(" ConnectIPv4 = %s\n", yesno_to_str(Conf_ConnectIPv6)); @@ -371,6 +373,7 @@ Conf_Test( void ) printf(" MorePrivacy = %s\n", yesno_to_str(Conf_MorePrivacy)); printf(" NoticeAuth = %s\n", yesno_to_str(Conf_NoticeAuth)); printf(" OperCanUseMode = %s\n", yesno_to_str(Conf_OperCanMode)); + printf(" OperChanPAutoOp = %s\n", yesno_to_str(Conf_OperChanPAutoOp)); printf(" OperServerMode = %s\n", yesno_to_str(Conf_OperServerMode)); #ifdef PAM printf(" PAM = %s\n", yesno_to_str(Conf_PAM)); @@ -478,8 +481,12 @@ Conf_UnsetServer( CONN_ID Idx ) * require the next attempt to be delayed. */ Conf_Server[i].lasttry = t - Conf_ConnectRetry + RECONNECT_DELAY; - } else - Conf_Server[i].lasttry = t; + } else { + /* "Short" connection, enforce "ConnectRetry" + * but randomize it a little bit: 15 seconds. */ + Conf_Server[i].lasttry = + t + rand() / (RAND_MAX / 15); + } } } } @@ -487,7 +494,7 @@ Conf_UnsetServer( CONN_ID Idx ) /** * Set connection information for specified configured server. */ -GLOBAL void +GLOBAL bool Conf_SetServer( int ConfServer, CONN_ID Idx ) { assert( ConfServer > NONE ); @@ -495,13 +502,15 @@ Conf_SetServer( int ConfServer, CONN_ID Idx ) if (Conf_Server[ConfServer].conn_id > NONE && Conf_Server[ConfServer].conn_id != Idx) { - Log(LOG_ALERT, - "Trying to update connection index for already registered server \"%s\": %d/%d - ignored.", - Conf_Server[ConfServer].name, - Conf_Server[ConfServer].conn_id, Idx); - return; + Log(LOG_ERR, + "Connection %d: Server configuration of \"%s\" already in use by connection %d!", + Idx, Conf_Server[ConfServer].name, + Conf_Server[ConfServer].conn_id); + Conn_Close(Idx, NULL, "Server configuration already in use", true); + return false; } Conf_Server[ConfServer].conn_id = Idx; + return true; } /** @@ -635,14 +644,41 @@ Conf_AddServer(const char *Name, UINT16 Port, const char *Host, } /** - * Check if the given nick name is an service. + * Check if the given nickname is reserved for services on a particular server. * - * @returns true if the given nick name belongs to an "IRC service". + * @param ConfServer The server index to check. + * @param Nick The nickname to check. + * @returns true if the given nickname belongs to an "IRC service". */ GLOBAL bool -Conf_IsService(int ConfServer, const char *Nick) +Conf_NickIsService(int ConfServer, const char *Nick) { - return MatchCaseInsensitive(Conf_Server[ConfServer].svs_mask, Nick); + assert (ConfServer >= 0); + assert (ConfServer < MAX_SERVERS); + + return MatchCaseInsensitiveList(Conf_Server[ConfServer].svs_mask, + Nick, ","); +} + +/** + * Check if the given nickname is blocked for "normal client" use. + * + * @param ConfServer The server index or NONE to check all configured servers. + * @param Nick The nickname to check. + * @returns true if the given nickname belongs to an "IRC service". + */ +GLOBAL bool +Conf_NickIsBlocked(const char *Nick) +{ + int i; + + for(i = 0; i < MAX_SERVERS; i++) { + if (!Conf_Server[i].name[0]) + continue; + if (Conf_NickIsService(i, Nick)) + return true; + } + return false; } /** @@ -652,6 +688,7 @@ static void Set_Defaults(bool InitServers) { int i; + char random[RANDOM_SALT_LEN + 1]; /* Global */ strcpy(Conf_ServerName, ""); @@ -662,6 +699,7 @@ Set_Defaults(bool InitServers) PACKAGE_NAME, PACKAGE_VERSION); free(Conf_ListenAddress); Conf_ListenAddress = NULL; + array_free(&Conf_ListenPorts); array_free(&Conf_Motd); strlcpy(Conf_MotdFile, SYSCONFDIR, sizeof(Conf_MotdFile)); strlcat(Conf_MotdFile, MOTD_FILE, sizeof(Conf_MotdFile)); @@ -675,6 +713,7 @@ Set_Defaults(bool InitServers) Conf_MaxConnectionsIP = 5; Conf_MaxJoins = 10; Conf_MaxNickLength = CLIENT_NICK_LEN_DEFAULT; + Conf_MaxListSize = 100; Conf_PingTimeout = 120; Conf_PongTimeout = 20; @@ -686,6 +725,8 @@ Set_Defaults(bool InitServers) strlcpy(Conf_Chroot, CHROOT_DIR, sizeof(Conf_Chroot)); strcpy(Conf_CloakHost, ""); strcpy(Conf_CloakHostModeX, ""); + strlcpy(Conf_CloakHostSalt, ngt_RandomStr(random, RANDOM_SALT_LEN), + sizeof(Conf_CloakHostSalt)); Conf_CloakUserToNick = false; Conf_ConnectIPv4 = true; #ifdef WANT_IPV6 @@ -702,6 +743,7 @@ Set_Defaults(bool InitServers) Conf_MorePrivacy = false; Conf_NoticeAuth = false; Conf_OperCanMode = false; + Conf_OperChanPAutoOp = true; Conf_OperServerMode = false; #ifdef PAM Conf_PAM = true; @@ -1033,7 +1075,7 @@ Check_ArgIsTrue(const char *Arg) * * @param Line Line number in configuration file. * @raram Arg Input string. - * @returns New configured maximum nick name length. + * @returns New configured maximum nickname length. */ static unsigned int Handle_MaxNickLength(int Line, const char *Arg) @@ -1150,6 +1192,7 @@ CheckLegacyGlobalOption(int Line, char *Var, char *Arg) || strcasecmp(Var, "ConnectIPv4") == 0 || strcasecmp(Var, "ConnectIPv6") == 0 || strcasecmp(Var, "OperCanUseMode") == 0 + || strcasecmp(Var, "OperChanPAutoOp") == 0 || strcasecmp(Var, "OperServerMode") == 0 || strcasecmp(Var, "PredefChannelsOnly") == 0 || strcasecmp(Var, "SyslogFacility") == 0 @@ -1402,7 +1445,7 @@ Handle_LIMITS(int Line, char *Var, char *Arg) return; } if (strcasecmp(Var, "MaxConnections") == 0) { - Conf_MaxConnections = atol(Arg); + Conf_MaxConnections = atoi(Arg); if (!Conf_MaxConnections && strcmp(Arg, "0")) Config_Error_NaN(Line, Var); return; @@ -1423,6 +1466,12 @@ Handle_LIMITS(int Line, char *Var, char *Arg) Conf_MaxNickLength = Handle_MaxNickLength(Line, Arg); return; } + if (strcasecmp(Var, "MaxListSize") == 0) { + Conf_MaxListSize = atoi(Arg); + if (!Conf_MaxListSize && strcmp(Arg, "0")) + Config_Error_NaN(Line, Var); + return; + } if (strcasecmp(Var, "PingTimeout") == 0) { Conf_PingTimeout = atoi(Arg); if (Conf_PingTimeout < 5) { @@ -1485,6 +1534,12 @@ Handle_OPTIONS(int Line, char *Var, char *Arg) Config_Error_TooLong(Line, Var); return; } + if (strcasecmp(Var, "CloakHostSalt") == 0) { + len = strlcpy(Conf_CloakHostSalt, Arg, sizeof(Conf_CloakHostSalt)); + if (len >= sizeof(Conf_CloakHostSalt)) + Config_Error_TooLong(Line, Var); + return; + } if (strcasecmp(Var, "CloakUserToNick") == 0) { Conf_CloakUserToNick = Check_ArgIsTrue(Arg); return; @@ -1519,6 +1574,10 @@ Handle_OPTIONS(int Line, char *Var, char *Arg) Conf_OperCanMode = Check_ArgIsTrue(Arg); return; } + if (strcasecmp(Var, "OperChanPAutoOp") == 0) { + Conf_OperChanPAutoOp = Check_ArgIsTrue(Arg); + return; + } if (strcasecmp(Var, "OperServerMode") == 0) { Conf_OperServerMode = Check_ArgIsTrue(Arg); return; @@ -1875,6 +1934,13 @@ Validate_Config(bool Configtest, bool Rehash) bool config_valid = true; char *ptr; + /* Emit a warning when the config file is not a full path name */ + if (NGIRCd_ConfFile[0] && NGIRCd_ConfFile[0] != '/') { + Config_Error(LOG_WARNING, + "Not specifying a full path name to \"%s\" can cause problems when rehashing the server!", + NGIRCd_ConfFile); + } + /* Validate configured server name, see RFC 2812 section 2.3.1 */ ptr = Conf_ServerName; do { diff --git a/src/ngircd/conf.h b/src/ngircd/conf.h index 86f00fe..f85a25f 100644 --- a/src/ngircd/conf.h +++ b/src/ngircd/conf.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors. + * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -62,7 +62,7 @@ typedef struct _Conf_Server #ifdef SSL_SUPPORT bool SSLConnect; /**< Establish connection using SSL? */ #endif - char svs_mask[CLIENT_ID_LEN]; /**< Mask of nick names that should be + char svs_mask[CLIENT_ID_LEN]; /**< Mask of nicknames that should be treated and counted as services */ } CONF_SERVER; @@ -151,6 +151,9 @@ GLOBAL bool Conf_PredefChannelsOnly; /** Flag indicating if IRC operators are allowed to always use MODE (true) */ GLOBAL bool Conf_OperCanMode; +/** Flag indicating if IRC operators get AutoOp in persistent (+P) channels */ +GLOBAL bool Conf_OperChanPAutoOp; + /** * If true, mask channel MODE commands of IRC operators to the server. * Background: ircd2 will ignore channel MODE commands if an IRC operator @@ -169,7 +172,10 @@ GLOBAL char Conf_CloakHost[CLIENT_ID_LEN]; /** Cloaked hostname for clients that did +x */ GLOBAL char Conf_CloakHostModeX[CLIENT_ID_LEN]; -/** Use nick name as user name? */ +/** Salt for hostname hash for cloaked hostnames */ +GLOBAL char Conf_CloakHostSalt[CLIENT_ID_LEN]; + +/** Use nickname as user name? */ GLOBAL bool Conf_CloakUserToNick; /** Enable all DNS functions? */ @@ -203,7 +209,7 @@ GLOBAL bool Conf_ConnectIPv6; GLOBAL bool Conf_ConnectIPv4; /** Maximum number of simultaneous connections to this server */ -GLOBAL long Conf_MaxConnections; +GLOBAL int Conf_MaxConnections; /** Maximum number of channels a user can join */ GLOBAL int Conf_MaxJoins; @@ -211,9 +217,12 @@ GLOBAL int Conf_MaxJoins; /** Maximum number of connections per IP address */ GLOBAL int Conf_MaxConnectionsIP; -/** Maximum length of a nick name */ +/** Maximum length of a nickname */ GLOBAL unsigned int Conf_MaxNickLength; +/** Maximum number of channels returned to /list */ +GLOBAL int Conf_MaxListSize; + #ifndef STRICT_RFC /** Require "AUTH PING-PONG" on login */ @@ -233,7 +242,7 @@ GLOBAL bool Conf_Rehash PARAMS((void)); GLOBAL int Conf_Test PARAMS((void)); GLOBAL void Conf_UnsetServer PARAMS(( CONN_ID Idx )); -GLOBAL void Conf_SetServer PARAMS(( int ConfServer, CONN_ID Idx )); +GLOBAL bool Conf_SetServer PARAMS(( int ConfServer, CONN_ID Idx )); GLOBAL int Conf_GetServer PARAMS(( CONN_ID Idx )); GLOBAL bool Conf_EnableServer PARAMS(( const char *Name, UINT16 Port )); @@ -241,7 +250,8 @@ GLOBAL bool Conf_EnablePassiveServer PARAMS((const char *Name)); GLOBAL bool Conf_DisableServer PARAMS(( const char *Name )); GLOBAL bool Conf_AddServer PARAMS(( const char *Name, UINT16 Port, const char *Host, const char *MyPwd, const char *PeerPwd )); -GLOBAL bool Conf_IsService PARAMS((int ConfServer, const char *Nick)); +GLOBAL bool Conf_NickIsService PARAMS((int ConfServer, const char *Nick)); +GLOBAL bool Conf_NickIsBlocked PARAMS((const char *Nick)); /* Password required by WEBIRC command */ GLOBAL char Conf_WebircPwd[CLIENT_PASS_LEN]; diff --git a/src/ngircd/conn-encoding.c b/src/ngircd/conn-encoding.c new file mode 100644 index 0000000..71ab588 --- /dev/null +++ b/src/ngircd/conn-encoding.c @@ -0,0 +1,192 @@ +/* + * ngIRCd -- The Next Generation IRC Daemon + * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors. + * + * 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. + */ + +#define __conn_encoding_c__ + +#define CONN_MODULE + +#include "portab.h" + +/** + * @file + * Functions to deal with character encodings and conversions + */ + +#include "imp.h" +#include +#include +#include + +#include "defines.h" +#include "conn.h" +#include "log.h" + +#include "exp.h" +#include "conn-encoding.h" + +#ifdef ICONV + +char Encoding_Buffer[COMMAND_LEN]; + +char *Convert_Message PARAMS((iconv_t Handle, char *Message)); + + +/** + * Set client character encoding on a connection. + * + * @param Conn Connection identifier. + * @param ClientEnc Client encoding (for example "ASCII", "MacRoman", ...). + * @return true on success, false otherwise. + */ +GLOBAL bool +Conn_SetEncoding(CONN_ID Conn, const char *ClientEnc) +{ + char client_enc[25], server_enc[25]; + + assert(Conn > NONE); + assert(ClientEnc != NULL); + + Conn_UnsetEncoding(Conn); + + /* Is the client character set identical to server character set? */ + if (strcasecmp(ClientEnc, "UTF-8") == 0) + return true; + + snprintf(client_enc, sizeof(client_enc), "%s//TRANSLIT", ClientEnc); + snprintf(server_enc, sizeof(server_enc), "%s//TRANSLIT", "UTF-8"); + + My_Connections[Conn].iconv_from = iconv_open(server_enc, client_enc); + if (My_Connections[Conn].iconv_from == (iconv_t)(-1)) { + Conn_UnsetEncoding(Conn); + return false; + } + My_Connections[Conn].iconv_to = iconv_open(client_enc, server_enc); + if (My_Connections[Conn].iconv_to == (iconv_t)(-1)) { + Conn_UnsetEncoding(Conn); + return false; + } + + LogDebug("Set client character set of connection \"%d\" to \"%s\".", + Conn, client_enc); + return true; +} + +/** + * Remove client character encoding conversion on a connection. + * + * @param Conn Connection identifier. + */ +GLOBAL void +Conn_UnsetEncoding(CONN_ID Conn) +{ + assert(Conn > NONE); + + if (My_Connections[Conn].iconv_from != (iconv_t)(-1)) + iconv_close(My_Connections[Conn].iconv_from); + if (My_Connections[Conn].iconv_to != (iconv_t)(-1)) + iconv_close(My_Connections[Conn].iconv_to); + + My_Connections[Conn].iconv_from = (iconv_t)(-1); + My_Connections[Conn].iconv_to = (iconv_t)(-1); + + LogDebug("Unset character conversion of connection %d.", Conn); +} + +/** + * Convert the encoding of a given message. + * + * This function uses a static buffer for the result of the encoding + * conversion which is overwritten by subsequent calls to this function! + * + * @param Handle libiconv handle. + * @param Message The message to convert. + * @return Pointer to the result. + */ +char * +Convert_Message(iconv_t Handle, char *Message) +{ + size_t in_left, out_left; + char *out = Encoding_Buffer; + + assert (Handle != (iconv_t)(-1)); + assert (Message != NULL); + + in_left = strlen(Message); + out_left = sizeof(Encoding_Buffer) - 1; + + if (iconv(Handle, &Message, &in_left, &out, &out_left) == (size_t)(-1)) { + /* An error occured! */ + LogDebug("Error converting message encoding!"); + strlcpy(Encoding_Buffer, Message, sizeof(Encoding_Buffer)); + iconv(Handle, NULL, NULL, NULL, NULL); + } else + *out = '\0'; + + return Encoding_Buffer; +} + +#endif + +/** + * Convert encoding of a message received from a connection. + * + * Note 1: If no conversion is required, this function returns the original + * pointer to the message. + * + * Note 2: This function uses Convert_Message(), so subsequent calls to this + * function will overwrite the earlier results. + * + * @param Conn Connection identifier. + * @param Message The message to convert. + * @return Pointer to the result. + * @see Convert_Message + */ +GLOBAL char * +Conn_EncodingFrom(UNUSED CONN_ID Conn, char *Message) +{ + assert(Conn > NONE); + assert (Message != NULL); + +#ifdef ICONV + if (My_Connections[Conn].iconv_from != (iconv_t)(-1)) + return Convert_Message(My_Connections[Conn].iconv_from, Message); +#endif + return Message; +} + +/** + * Convert encoding of a message for sending on a connection. + * + * Note 1: If no conversion is required, this function returns the original + * pointer to the message. + * + * Note 2: This function uses Convert_Message(), so subsequent calls to this + * function will overwrite the earlier results. + * + * @param Conn Connection identifier. + * @param Message The message to convert. + * @return Pointer to the result. + * @see Convert_Message + */ +GLOBAL char * +Conn_EncodingTo(UNUSED CONN_ID Conn, char *Message) +{ + assert(Conn > NONE); + assert (Message != NULL); + +#ifdef ICONV + if (My_Connections[Conn].iconv_to != (iconv_t)(-1)) + return Convert_Message(My_Connections[Conn].iconv_to, Message); +#endif + return Message; +} + +/* -eof- */ diff --git a/src/ngircd/conn-encoding.h b/src/ngircd/conn-encoding.h new file mode 100644 index 0000000..7b50ed6 --- /dev/null +++ b/src/ngircd/conn-encoding.h @@ -0,0 +1,30 @@ +/* + * ngIRCd -- The Next Generation IRC Daemon + * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors. + * + * 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. + */ + +#ifndef __conn_encoding_h__ +#define __conn_encoding_h__ + +/** + * @file + * Functions to deal with character encodings and conversions (header) + */ + +#ifdef ICONV + +GLOBAL bool Conn_SetEncoding PARAMS((CONN_ID Idx, const char *ClientEnc)); +GLOBAL void Conn_UnsetEncoding PARAMS((CONN_ID Idx)); + +#endif /* ICONV */ + +GLOBAL char* Conn_EncodingFrom PARAMS((CONN_ID Idx, char *Message)); +GLOBAL char* Conn_EncodingTo PARAMS((CONN_ID Idx, char *Message)); + +#endif diff --git a/src/ngircd/conn-ssl.c b/src/ngircd/conn-ssl.c index 5d44b30..59729e0 100644 --- a/src/ngircd/conn-ssl.c +++ b/src/ngircd/conn-ssl.c @@ -156,7 +156,7 @@ Load_DH_params(void) bool ret = true; if (!Conf_SSLOptions.DHFile) { - Log(LOG_NOTICE, "Configuration option \"SSLDHFile\" not set!"); + Log(LOG_NOTICE, "Configuration option \"DHFile\" not set!"); return false; } fp = fopen(Conf_SSLOptions.DHFile, "r"); @@ -201,7 +201,7 @@ Load_DH_params(void) } if (need_dhgenerate) { Log(LOG_WARNING, - "SSLDHFile not set, generating %u bit DH parameters. This may take a while ...", + "DHFile not set, generating %u bit DH parameters. This may take a while ...", DH_BITS); err = gnutls_dh_params_generate2(tmp_dh_params, DH_BITS); if (err < 0) { @@ -241,6 +241,9 @@ void ConnSSL_Free(CONNECTION *c) bool ConnSSL_InitLibrary( void ) { + if (!array_bytes(&Conf_SSLOptions.ListenPorts)) + return true; + #ifdef HAVE_LIBSSL SSL_CTX *newctx; @@ -256,12 +259,14 @@ ConnSSL_InitLibrary( void ) * According to OpenSSL RAND_egd(3): "The automatic query of /var/run/egd-pool et al was added in OpenSSL 0.9.7"; * so it makes little sense to deal with PRNGD seeding ourselves. */ + array_free(&Conf_SSLOptions.ListenPorts); return false; } newctx = SSL_CTX_new(SSLv23_method()); if (!newctx) { LogOpenSSLError("SSL_CTX_new()", NULL); + array_free(&Conf_SSLOptions.ListenPorts); return false; } @@ -276,6 +281,7 @@ ConnSSL_InitLibrary( void ) return true; out: SSL_CTX_free(newctx); + array_free(&Conf_SSLOptions.ListenPorts); return false; #endif #ifdef HAVE_LIBGNUTLS @@ -287,10 +293,13 @@ out: err = gnutls_global_init(); if (err) { Log(LOG_ERR, "gnutls_global_init(): %s", gnutls_strerror(err)); + array_free(&Conf_SSLOptions.ListenPorts); return false; } - if (!ConnSSL_LoadServerKey_gnutls()) + if (!ConnSSL_LoadServerKey_gnutls()) { + array_free(&Conf_SSLOptions.ListenPorts); return false; + } Log(LOG_INFO, "gnutls %s initialized.", gnutls_check_version(NULL)); initialized = true; return true; @@ -313,7 +322,7 @@ ConnSSL_LoadServerKey_gnutls(void) cert_file = Conf_SSLOptions.CertFile ? Conf_SSLOptions.CertFile:Conf_SSLOptions.KeyFile; if (!cert_file) { - Log(LOG_NOTICE, "No SSL server key configured, SSL disabled."); + Log(LOG_ERR, "No SSL server key configured!"); return false; } @@ -344,7 +353,7 @@ ConnSSL_LoadServerKey_openssl(SSL_CTX *ctx) assert(ctx); if (!Conf_SSLOptions.KeyFile) { - Log(LOG_NOTICE, "No SSL server key configured, SSL disabled."); + Log(LOG_ERR, "No SSL server key configured!"); return false; } @@ -625,6 +634,8 @@ ConnectAccept( CONNECTION *c, bool connect) #endif /* _GNUTLS */ Conn_OPTION_DEL(c, (CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ|CONN_SSL_CONNECT)); ConnSSL_LogCertInfo(c); + + Conn_StartLogin(CONNECTION2ID(c)); return 1; } @@ -712,6 +723,13 @@ ConnSSL_GetCipherInfo(CONNECTION *c, char *buf, size_t len) #endif } +#else + +bool +ConnSSL_InitLibrary(void) +{ + return true; +} #endif /* SSL_SUPPORT */ /* -eof- */ diff --git a/src/ngircd/conn.c b/src/ngircd/conn.c index 06236fd..80b085a 100644 --- a/src/ngircd/conn.c +++ b/src/ngircd/conn.c @@ -47,10 +47,6 @@ # include #endif -#ifdef HAVE_STDINT_H -# include /* e.g. for Mac OS X */ -#endif - #ifdef TCPWRAP # include /* for TCP Wrappers */ #endif @@ -67,6 +63,7 @@ #include "client.h" #include "class.h" #include "conf.h" +#include "conn-encoding.h" #include "conn-ssl.h" #include "conn-zip.h" #include "conn-func.h" @@ -88,7 +85,7 @@ static bool Handle_Write PARAMS(( CONN_ID Idx )); static bool Conn_Write PARAMS(( CONN_ID Idx, char *Data, size_t Len )); -static int New_Connection PARAMS(( int Sock )); +static int New_Connection PARAMS(( int Sock, bool IsSSL )); static CONN_ID Socket2Index PARAMS(( int Sock )); static void Read_Request PARAMS(( CONN_ID Idx )); static unsigned int Handle_Buffer PARAMS(( CONN_ID Idx )); @@ -134,7 +131,7 @@ static void cb_listen(int sock, short irrelevant) { (void) irrelevant; - (void) New_Connection(sock); + (void) New_Connection(sock, false); } @@ -152,7 +149,7 @@ cb_listen_ssl(int sock, short irrelevant) int fd; (void) irrelevant; - fd = New_Connection(sock); + fd = New_Connection(sock, true); if (fd < 0) return; io_event_setcb(My_Connections[fd].sock, cb_clientserver_ssl); @@ -865,6 +862,9 @@ va_dcl #endif { char buffer[COMMAND_LEN]; +#ifdef ICONV + char *ptr, *message; +#endif size_t len; bool ok; va_list ap; @@ -905,6 +905,16 @@ va_dcl CUT_TXTSUFFIX); } +#ifdef ICONV + ptr = strchr(buffer + 1, ':'); + if (ptr) { + ptr++; + message = Conn_EncodingTo(Idx, ptr); + if (message != ptr) + strlcpy(ptr, message, sizeof(buffer) - (ptr - buffer)); + } +#endif + #ifdef SNIFFER if (NGIRCd_Sniffer) Log(LOG_DEBUG, " -> connection %d: '%s'.", Idx, buffer); @@ -918,6 +928,30 @@ va_dcl return ok; } /* Conn_WriteStr */ +GLOBAL char* +Conn_Password( CONN_ID Idx ) +{ + assert( Idx > NONE ); + if (My_Connections[Idx].pwd == NULL) + return (char*)"\0"; + else + return My_Connections[Idx].pwd; +} /* Conn_Password */ + +GLOBAL void +Conn_SetPassword( CONN_ID Idx, const char *Pwd ) +{ + assert( Idx > NONE ); + + if (My_Connections[Idx].pwd) + free(My_Connections[Idx].pwd); + + My_Connections[Idx].pwd = strdup(Pwd); + if (My_Connections[Idx].pwd == NULL) { + Log(LOG_EMERG, "Can't allocate memory! [Conn_SetPassword]"); + exit(1); + } +} /* Conn_SetPassword */ /** * Append Data to the outbound write buffer of a connection. @@ -1146,6 +1180,8 @@ Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClie array_free(&My_Connections[Idx].rbuf); array_free(&My_Connections[Idx].wbuf); + if (My_Connections[Idx].pwd != NULL) + free(My_Connections[Idx].pwd); /* Clean up connection structure (=free it) */ Init_Conn_Struct( Idx ); @@ -1336,17 +1372,18 @@ Count_Connections(ng_ipaddr_t *a) * Initialize new client connection on a listening socket. * * @param Sock Listening socket descriptor. + * @param IsSSL true if this socket expects SSL-encrypted data. * @returns Accepted socket descriptor or -1 on error. */ static int -New_Connection(int Sock) +New_Connection(int Sock, UNUSED bool IsSSL) { #ifdef TCPWRAP struct request_info req; #endif ng_ipaddr_t new_addr; char ip_str[NG_INET_ADDRSTRLEN]; - int new_sock, new_sock_len, identsock; + int new_sock, new_sock_len; CLIENT *c; long cnt; @@ -1466,30 +1503,56 @@ New_Connection(int Sock) Log(LOG_INFO, "Accepted connection %d from %s:%d on socket %d.", new_sock, My_Connections[new_sock].host, ng_ipaddr_getport(&new_addr), Sock); + Account_Connection(); + +#ifdef SSL_SUPPORT + /* Delay connection initalization until SSL handshake is finished */ + if (!IsSSL) +#endif + Conn_StartLogin(new_sock); + + return new_sock; +} /* New_Connection */ + + +/** + * Finish connection initialization, start resolver subprocess. + * + * @param Idx Connection index. + */ +GLOBAL void +Conn_StartLogin(CONN_ID Idx) +{ + int ident_sock = -1; + + assert(Idx >= 0); + + /* Nothing to do if DNS (and resolver subprocess) is disabled */ + if (!Conf_DNS) + return; - identsock = new_sock; #ifdef IDENTAUTH - if (!Conf_Ident) - identsock = -1; + /* Should we make an IDENT request? */ + if (Conf_Ident) + ident_sock = My_Connections[Idx].sock; #endif - if (Conf_DNS) { - if (Conf_NoticeAuth) { + + if (Conf_NoticeAuth) { + /* Send "NOTICE AUTH" messages to the client */ #ifdef IDENTAUTH - if (Conf_Ident) - (void)Conn_WriteStr(new_sock, - "NOTICE AUTH :*** Looking up your hostname and checking ident"); - else + if (Conf_Ident) + (void)Conn_WriteStr(Idx, + "NOTICE AUTH :*** Looking up your hostname and checking ident"); + else #endif - (void)Conn_WriteStr(new_sock, - "NOTICE AUTH :*** Looking up your hostname"); - } - Resolve_Addr(&My_Connections[new_sock].proc_stat, &new_addr, - identsock, cb_Read_Resolver_Result); + (void)Conn_WriteStr(Idx, + "NOTICE AUTH :*** Looking up your hostname"); + (void)Handle_Write(Idx); } - Account_Connection(); - return new_sock; -} /* New_Connection */ + Resolve_Addr(&My_Connections[Idx].proc_stat, &My_Connections[Idx].addr, + ident_sock, cb_Read_Resolver_Result); +} /** @@ -1839,10 +1902,10 @@ Check_Connections(void) if (My_Connections[i].lastping < time(NULL) - Conf_PongTimeout) { /* Timeout */ - LogDebug - ("Connection %d: Ping timeout: %d seconds.", - i, Conf_PongTimeout); - snprintf(msg, sizeof(msg), "Ping timeout: %d seconds", Conf_PongTimeout); + snprintf(msg, sizeof(msg), + "Ping timeout: %d seconds", + Conf_PongTimeout); + LogDebug("Connection %d: %s.", i, msg); Conn_Close(i, NULL, msg, true); } } else if (My_Connections[i].lastdata < @@ -2016,7 +2079,8 @@ New_Server( int Server , ng_ipaddr_t *dest) Client_SetToken( c, TOKEN_OUTBOUND ); /* Register connection */ - Conf_SetServer(Server, new_sock); + if (!Conf_SetServer(Server, new_sock)) + return; My_Connections[new_sock].sock = new_sock; My_Connections[new_sock].addr = *dest; My_Connections[new_sock].client = c; @@ -2056,6 +2120,11 @@ Init_Conn_Struct(CONN_ID Idx) My_Connections[Idx].lastdata = now; My_Connections[Idx].lastprivmsg = now; Proc_InitStruct(&My_Connections[Idx].proc_stat); + +#ifdef ICONV + My_Connections[Idx].iconv_from = (iconv_t)(-1); + My_Connections[Idx].iconv_to = (iconv_t)(-1); +#endif } /* Init_Conn_Struct */ @@ -2231,7 +2300,8 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events ) Client_SetHostname(c, readbuf); if (Conf_NoticeAuth) (void)Conn_WriteStr(i, - "NOTICE AUTH :*** Found your hostname"); + "NOTICE AUTH :*** Found your hostname: %s", + My_Connections[i].host); #ifdef IDENTAUTH ++identptr; if (*identptr) { @@ -2256,8 +2326,10 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events ) } if (Conf_NoticeAuth) { (void)Conn_WriteStr(i, - "NOTICE AUTH :*** Got %sident response", - *ptr ? "invalid " : ""); + "NOTICE AUTH :*** Got %sident response%s%s", + *ptr ? "invalid " : "", + *ptr ? "" : ": ", + *ptr ? "" : identptr); } } else { Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i); @@ -2266,6 +2338,10 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events ) "NOTICE AUTH :*** No ident response"); } #endif + + if (Conf_NoticeAuth) + (void)Handle_Write(i); + Class_HandleServerBans(c); } #ifdef DEBUG diff --git a/src/ngircd/conn.h b/src/ngircd/conn.h index 4752ec1..9236c58 100644 --- a/src/ngircd/conn.h +++ b/src/ngircd/conn.h @@ -42,7 +42,7 @@ #define CONN_SSL_WANT_READ 128 /* SSL/TLS library needs to read protocol data */ #define CONN_SSL_FLAGS_ALL (CONN_SSL_CONNECT|CONN_SSL|CONN_SSL_WANT_WRITE|CONN_SSL_WANT_READ) #endif -typedef long CONN_ID; +typedef int CONN_ID; #include "client.h" #include "proc.h" @@ -54,6 +54,10 @@ typedef long CONN_ID; #include "tool.h" #include "ng_ipaddr.h" +#ifdef ICONV +# include +#endif + #ifdef ZLIB #include typedef struct _ZipData @@ -72,6 +76,7 @@ typedef struct _Connection ng_ipaddr_t addr; /* Client address */ PROC_STAT proc_stat; /* Status of resolver process */ char host[HOST_LEN]; /* Hostname */ + char *pwd; /* password received of the client */ array rbuf; /* Read buffer */ array wbuf; /* Write buffer */ time_t signon; /* Signon ("connect") time */ @@ -94,12 +99,18 @@ typedef struct _Connection #ifndef STRICT_RFC long auth_ping; /** PING response expected on login */ #endif +#ifdef ICONV + iconv_t iconv_from; /** iconv: convert from client to server */ + iconv_t iconv_to; /** iconv: convert from server to client */ +#endif } CONNECTION; GLOBAL CONNECTION *My_Connections; GLOBAL CONN_ID Pool_Size; GLOBAL long WCounter; +#define CONNECTION2ID(x) (long)(x - My_Connections) + #endif /* CONN_MODULE */ @@ -111,10 +122,15 @@ GLOBAL void Conn_CloseAllSockets PARAMS((int ExceptOf)); GLOBAL unsigned int Conn_InitListeners PARAMS(( void )); GLOBAL void Conn_ExitListeners PARAMS(( void )); +GLOBAL void Conn_StartLogin PARAMS((CONN_ID Idx)); + GLOBAL void Conn_Handler PARAMS(( void )); GLOBAL bool Conn_WriteStr PARAMS(( CONN_ID Idx, const char *Format, ... )); +GLOBAL char* Conn_Password PARAMS(( CONN_ID Idx )); +GLOBAL void Conn_SetPassword PARAMS(( CONN_ID Idx, const char *Pwd )); + GLOBAL void Conn_Close PARAMS(( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClient )); GLOBAL void Conn_SyncServerStruct PARAMS(( void )); @@ -122,6 +138,7 @@ GLOBAL void Conn_SyncServerStruct PARAMS(( void )); GLOBAL CONN_ID Conn_GetFromProc PARAMS((int fd)); GLOBAL CLIENT* Conn_GetClient PARAMS((CONN_ID i)); GLOBAL PROC_STAT* Conn_GetProcStat PARAMS((CONN_ID i)); + #ifdef SSL_SUPPORT GLOBAL bool Conn_GetCipherInfo PARAMS((CONN_ID Idx, char *buf, size_t len)); GLOBAL bool Conn_UsesSSL PARAMS((CONN_ID Idx)); diff --git a/src/ngircd/defines.h b/src/ngircd/defines.h index 953eac3..ad9716f 100644 --- a/src/ngircd/defines.h +++ b/src/ngircd/defines.h @@ -44,9 +44,12 @@ /** Max. length of file name. */ #define FNAME_LEN 256 -/** Max. lenght of fully qualified host names (e. g. "abc.domain.tld"). */ +/** Max. length of fully qualified host names (e. g. "abc.domain.tld"). */ #define HOST_LEN 256 +/** Max. length of random salt */ +#define RANDOM_SALT_LEN 32 + /* Size of structures */ @@ -89,14 +92,18 @@ /** Default nick length (including NULL), see. RFC 2812 section 1.2.1. */ #define CLIENT_NICK_LEN_DEFAULT 10 -/** Maximum nick name length (including NULL). */ +/** Maximum nickname length (including NULL). */ #define CLIENT_NICK_LEN 32 /** Max. password length (including NULL). */ #define CLIENT_PASS_LEN 21 /** Max. length of user name ("login"; incl. NULL), RFC 2812, section 1.2.1. */ -#define CLIENT_USER_LEN 10 +#ifndef STRICT_RFC +# define CLIENT_USER_LEN 20 +#else +# define CLIENT_USER_LEN 10 +#endif /** Max. length of "real names" (including NULL). */ #define CLIENT_NAME_LEN 32 @@ -105,7 +112,7 @@ #define CLIENT_HOST_LEN 64 /** Max. length of all client modes (including NULL). */ -#define CLIENT_MODE_LEN 16 +#define CLIENT_MODE_LEN 21 /** Max. length of server info texts (including NULL). */ #define CLIENT_INFO_LEN 64 @@ -120,7 +127,7 @@ #define CHANNEL_NAME_LEN 51 /** Max. length of channel modes (including NULL). */ -#define CHANNEL_MODE_LEN 9 +#define CHANNEL_MODE_LEN 21 /** Max. IRC command length (including NULL), see. RFC 2812 section 3.2. */ #define COMMAND_LEN 513 @@ -154,14 +161,14 @@ #ifdef IRCPLUS /** Standard IRC+ flags. */ -# define IRCPLUSFLAGS "CHLS" +# define IRCPLUSFLAGS "CHLMSX" #endif /** Supported user modes. */ -#define USERMODES "acCiorRswx" +#define USERMODES "abBcCioqrRswx" /** Supported channel modes. */ -#define CHANMODES "beiIklmnoOPrRstvz" +#define CHANMODES "abehiIklmMnoOPqQrRstvVz" /** Away message for users connected to linked servers. */ #define DEFAULT_AWAY_MSG "Away" @@ -178,9 +185,6 @@ /* Defaults and limits for IRC commands */ -/** Max. number of LIST replies. */ -#define MAX_RPL_LIST 100 - /** Max. number of elemets allowed in channel invite and ban lists. */ #define MAX_HNDL_CHANNEL_LISTS 50 diff --git a/src/ngircd/io.c b/src/ngircd/io.c index 9ffdfd6..cce6ef5 100644 --- a/src/ngircd/io.c +++ b/src/ngircd/io.c @@ -86,6 +86,20 @@ static int io_masterfd; static int io_dispatch_kqueue(struct timeval *tv); static bool io_event_change_kqueue(int, short, const int action); + +#ifndef EV_SET +/* Taken from /usr/include/sys/event.h of FreeBSD 8.1 and required by all + * platforms that have kqueue but lack EV_SET() -- for example FreeBSD 4. */ +#define EV_SET(kevp, a, b, c, d, e, f) do { \ + struct kevent *__kevp__ = (kevp); \ + __kevp__->ident = (a); \ + __kevp__->filter = (b); \ + __kevp__->flags = (c); \ + __kevp__->fflags = (d); \ + __kevp__->data = (e); \ + __kevp__->udata = (f); \ +} while(0) +#endif #endif #ifdef IO_USE_POLL diff --git a/src/ngircd/irc-cap.c b/src/ngircd/irc-cap.c index 2ea4c9a..af34c38 100644 --- a/src/ngircd/irc-cap.c +++ b/src/ngircd/irc-cap.c @@ -275,8 +275,8 @@ Parse_CAP(int Capabilities, char *Args) * @param Capabilities Capability flags (bitmask). * @return Pointer to textual representation. */ -char -*Get_CAP_String(int Capabilities) +char * +Get_CAP_String(int Capabilities) { static char txt[COMMAND_LEN]; diff --git a/src/ngircd/irc-channel.c b/src/ngircd/irc-channel.c index d714b48..41947a8 100644 --- a/src/ngircd/irc-channel.c +++ b/src/ngircd/irc-channel.c @@ -167,8 +167,10 @@ join_set_channelmodes(CHANNEL *chan, CLIENT *target, const char *flags) } } - /* If channel persistent and client is ircop: make client chanop */ - if (strchr(Channel_Modes(chan), 'P') && strchr(Client_Modes(target), 'o')) + /* If the channel is persistent (+P) and client is an IRC op: + * make client chanop, if not disabled in configuration. */ + if (strchr(Channel_Modes(chan), 'P') && Conf_OperChanPAutoOp + && strchr(Client_Modes(target), 'o')) Channel_UserModeAdd(chan, target, 'o'); } /* join_set_channelmodes */ @@ -363,7 +365,7 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req ) chan = Channel_Search(channame); if (!chan && Conf_PredefChannelsOnly) { /* channel must be created, but forbidden by config */ - IRC_WriteStrClient(Client, ERR_BANNEDFROMCHAN_MSG, + IRC_WriteStrClient(Client, ERR_NOSUCHCHANNEL_MSG, Client_ID(Client), channame); goto join_next; } @@ -510,7 +512,7 @@ IRC_TOPIC( CLIENT *Client, REQUEST *Req ) CHANNEL *chan; CLIENT *from; char *topic; - bool onchannel, topicok, use_servermode, r; + bool r, topic_power; assert( Client != NULL ); assert( Req != NULL ); @@ -533,12 +535,17 @@ IRC_TOPIC( CLIENT *Client, REQUEST *Req ) return IRC_WriteStrClient(from, ERR_NOSUCHCHANNEL_MSG, Client_ID(from), Req->argv[0]); - Channel_CheckAdminRights(chan, Client, from, - &onchannel, &topicok, &use_servermode); - - if (!onchannel && !topicok) - return IRC_WriteStrClient(from, ERR_NOTONCHANNEL_MSG, - Client_ID(from), Req->argv[0]); + /* Only remote servers and channel members are allowed to change the + * channel topic, and IRC opreators when the Conf_OperCanMode option + * is set in the server configuration. */ + if (Client_Type(Client) != CLIENT_SERVER) { + topic_power = Client_HasMode(from, 'o'); + if (!Channel_IsMemberOf(chan, from) + && !(Conf_OperCanMode && topic_power)) + return IRC_WriteStrClient(from, ERR_NOTONCHANNEL_MSG, + Client_ID(from), Req->argv[0]); + } else + topic_power = true; if (Req->argc == 1) { /* Request actual topic */ @@ -565,8 +572,12 @@ IRC_TOPIC( CLIENT *Client, REQUEST *Req ) } if (strchr(Channel_Modes(chan), 't')) { - /* Topic Lock. Is the user a channel or IRC operator? */ - if (!topicok) + /* Topic Lock. Is the user a channel op or IRC operator? */ + if(!topic_power && + !strchr(Channel_UserModes(chan, from), 'h') && + !strchr(Channel_UserModes(chan, from), 'o') && + !strchr(Channel_UserModes(chan, from), 'a') && + !strchr(Channel_UserModes(chan, from), 'q')) return IRC_WriteStrClient(from, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(from), Channel_Name(chan)); @@ -578,7 +589,7 @@ IRC_TOPIC( CLIENT *Client, REQUEST *Req ) Client_TypeText(from), Client_Mask(from), Channel_Name(chan), Req->argv[1][0] ? Req->argv[1] : ""); - if (use_servermode) + if (Conf_OperServerMode) from = Client_ThisServer(); /* Update channel and forward new topic to other servers */ @@ -666,10 +677,12 @@ IRC_LIST( CLIENT *Client, REQUEST *Req ) if (MatchCaseInsensitive(pattern, Channel_Name(chan))) { /* Gotcha! */ if (!strchr(Channel_Modes(chan), 's') - || Channel_IsMemberOf(chan, from)) { - if (IRC_CheckListTooBig(from, count, - MAX_RPL_LIST, - "LIST")) + || Channel_IsMemberOf(chan, from) + || (!Conf_MorePrivacy && Client_OperByMe(Client))) { + if ((Conf_MaxListSize > 0) + && IRC_CheckListTooBig(from, count, + Conf_MaxListSize, + "LIST")) break; if (!IRC_WriteStrClient(from, RPL_LIST_MSG, Client_ID(from), diff --git a/src/ngircd/irc-encoding.c b/src/ngircd/irc-encoding.c new file mode 100644 index 0000000..b1d3a69 --- /dev/null +++ b/src/ngircd/irc-encoding.c @@ -0,0 +1,68 @@ +/* + * ngIRCd -- The Next Generation IRC Daemon + * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors. + * + * 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. + */ + +#include "portab.h" + +/** + * @file + * IRC encoding commands + */ + +#include "imp.h" +#include +#include + +#include "conn-func.h" +#include "channel.h" +#include "conn-encoding.h" +#include "irc-write.h" +#include "messages.h" +#include "parse.h" +#include "tool.h" + +#include "exp.h" +#include "irc-encoding.h" + +#ifdef ICONV + +/** + * Handler for the IRC+ "CHARCONV" command. + * + * @param Client The client from which this command has been received. + * @param Req Request structure with prefix and all parameters. + * @returns CONNECTED or DISCONNECTED. + */ +GLOBAL bool +IRC_CHARCONV(CLIENT *Client, REQUEST *Req) +{ + char encoding[20]; + + assert (Client != NULL); + assert (Req != NULL); + + if (Req->argc != 1) + return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, + Client_ID(Client), Req->command); + + strlcpy(encoding, Req->argv[0], sizeof(encoding)); + ngt_UpperStr(encoding); + + if (!Conn_SetEncoding(Client_Conn(Client), encoding)) + return IRC_WriteStrClient(Client, ERR_IP_CHARCONV_MSG, + Client_ID(Client), encoding); + + return IRC_WriteStrClient(Client, RPL_IP_CHARCONV_MSG, + Client_ID(Client), encoding); +} /* IRC_CHARCONV */ + +#endif + +/* -eof- */ diff --git a/src/ngircd/irc-encoding.h b/src/ngircd/irc-encoding.h new file mode 100644 index 0000000..4349c91 --- /dev/null +++ b/src/ngircd/irc-encoding.h @@ -0,0 +1,24 @@ +/* + * ngIRCd -- The Next Generation IRC Daemon + * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors. + * + * 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. + */ + +#ifndef __irc_encoding_h__ +#define __irc_encoding_h__ + +/** + * @file + * IRC encoding commands (header) + */ + +GLOBAL bool IRC_CHARCONV PARAMS((CLIENT *Client, REQUEST *Req)); + +#endif + +/* -eof- */ diff --git a/src/ngircd/irc-info.c b/src/ngircd/irc-info.c index 0ea8587..57d6e1a 100644 --- a/src/ngircd/irc-info.c +++ b/src/ngircd/irc-info.c @@ -117,7 +117,7 @@ IRC_INFO(CLIENT * Client, REQUEST * Req) 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); @@ -727,7 +727,7 @@ IRC_USERHOST(CLIENT *Client, REQUEST *Req) strlcat(rpl, "+", sizeof(rpl)); strlcat(rpl, Client_User(c), sizeof(rpl)); strlcat(rpl, "@", sizeof(rpl)); - strlcat(rpl, Client_HostnameCloaked(c), sizeof(rpl)); + strlcat(rpl, Client_HostnameDisplayed(c), sizeof(rpl)); strlcat(rpl, " ", sizeof(rpl)); } } @@ -792,7 +792,7 @@ write_whoreply(CLIENT *Client, CLIENT *c, const char *channelname, const char *f { return IRC_WriteStrClient(Client, RPL_WHOREPLY_MSG, Client_ID(Client), channelname, Client_User(c), - Client_HostnameCloaked(c), + Client_HostnameDisplayed(c), Client_ID(Client_Introducer(c)), Client_ID(c), flags, Client_Hops(c), Client_Info(c)); } @@ -807,22 +807,48 @@ who_flags_status(const char *client_modes) } -static const char * -who_flags_qualifier(CLIENT *Client, const char *chan_user_modes) +/** + * Return channel user mode prefix(es). + * + * @param Client The client requesting the mode prefixes. + * @param chan_user_modes String with channel user modes. + * @param str String buffer to which the prefix(es) will be appended. + * @param len Size of "str" buffer. + * @return Pointer to "str". + */ +static char * +who_flags_qualifier(CLIENT *Client, const char *chan_user_modes, + char *str, size_t len) { assert(Client != NULL); if (Client_Cap(Client) & CLIENT_CAP_MULTI_PREFIX) { - if (strchr(chan_user_modes, 'o') && - strchr(chan_user_modes, 'v')) - return "@+"; + if (strchr(chan_user_modes, 'q')) + strlcat(str, "~", len); + if (strchr(chan_user_modes, 'a')) + strlcat(str, "&", len); + if (strchr(chan_user_modes, 'o')) + strlcat(str, "@", len); + if (strchr(chan_user_modes, 'h')) + strlcat(str, "%", len); + if (strchr(chan_user_modes, 'v')) + strlcat(str, "+", len); + + return str; } - if (strchr(chan_user_modes, 'o')) - return "@"; + if (strchr(chan_user_modes, 'q')) + strlcat(str, "~", len); + else if (strchr(chan_user_modes, 'a')) + strlcat(str, "&", len); + else if (strchr(chan_user_modes, 'o')) + strlcat(str, "@", len); + else if (strchr(chan_user_modes, 'h')) + strlcat(str, "%", len); else if (strchr(chan_user_modes, 'v')) - return "+"; - return ""; + strlcat(str, "+", len); + + return str; } @@ -840,14 +866,15 @@ IRC_WHO_Channel(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]; + char flags[10]; CLIENT *c; int count = 0; assert( Client != NULL ); assert( Chan != NULL ); + IRC_SetPenalty(Client, 1); + is_member = Channel_IsMemberOf(Chan, Client); /* Secret channel? */ @@ -866,16 +893,12 @@ IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps) is_visible = strchr(client_modes, 'i') == NULL; if (is_member || is_visible) { - if (IRC_CheckListTooBig(Client, count, MAX_RPL_WHO, "WHO")) - break; - 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(c, chan_user_modes), - sizeof(flags)); + who_flags_qualifier(Client, Channel_UserModes(Chan, c), + flags, sizeof(flags)); if (!write_whoreply(Client, c, Channel_Name(Chan), flags)) @@ -883,6 +906,11 @@ IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps) count++; } } + + /* If there are a lot of clients, augment penalty a bit */ + if (count > MAX_RPL_WHO) + IRC_SetPenalty(Client, 1); + return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), Channel_Name(Chan)); } @@ -911,6 +939,7 @@ IRC_WHO_Mask(CLIENT *Client, char *Mask, bool OnlyOps) if (Mask) ngt_LowerStr(Mask); + IRC_SetPenalty(Client, 3); for (c = Client_First(); c != NULL; c = Client_Next(c)) { if (Client_Type(c) != CLIENT_USER) continue; @@ -958,7 +987,7 @@ IRC_WHO_Mask(CLIENT *Client, char *Mask, bool OnlyOps) if (IRC_CheckListTooBig(Client, count, MAX_RPL_WHO, "WHO")) break; - strcpy(flags, who_flags_status(Client_Modes(c))); + strlcpy(flags, who_flags_status(Client_Modes(c)), sizeof(flags)); if (strchr(Client_Modes(c), 'o')) strlcat(flags, "*", sizeof(flags)); @@ -1014,13 +1043,11 @@ IRC_WHO(CLIENT *Client, REQUEST *Req) chan = Channel_Search(Req->argv[0]); if (chan) { /* Members of a channel have been requested */ - IRC_SetPenalty(Client, 1); return IRC_WHO_Channel(Client, chan, only_ops); } if (strcmp(Req->argv[0], "0") != 0) { /* A mask has been given. But please note this RFC * stupidity: "0" is same as no arguments ... */ - IRC_SetPenalty(Client, 3); return IRC_WHO_Mask(Client, Req->argv[0], only_ops); } } @@ -1053,7 +1080,7 @@ IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c) /* Nick, user, hostname and client info */ if (!IRC_WriteStrClient(from, RPL_WHOISUSER_MSG, Client_ID(from), Client_ID(c), Client_User(c), - Client_HostnameCloaked(c), Client_Info(c))) + Client_HostnameDisplayed(c), Client_Info(c))) return DISCONNECTED; /* Server */ @@ -1087,8 +1114,8 @@ IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c) if (str[strlen(str) - 1] != ':') strlcat(str, " ", sizeof(str)); - strlcat(str, who_flags_qualifier(c, Channel_UserModes(chan, c)), - sizeof(str)); + who_flags_qualifier(Client, Channel_UserModes(chan, c), + str, sizeof(str)); strlcat(str, Channel_Name(chan), sizeof(str)); if (strlen(str) > (LINE_LEN - CHANNEL_NAME_LEN - 4)) { @@ -1111,23 +1138,37 @@ IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c) Client_ID(from), Client_ID(c))) return DISCONNECTED; + /* IRC-Bot? */ + if (Client_HasMode(c, 'B') && + !IRC_WriteStrClient(from, RPL_WHOISBOT_MSG, + Client_ID(from), Client_ID(c))) + return DISCONNECTED; + /* Connected using SSL? */ if (Conn_UsesSSL(Client_Conn(c)) && !IRC_WriteStrClient(from, RPL_WHOISSSL_MSG, Client_ID(from), Client_ID(c))) return DISCONNECTED; - /* Registered nick name? */ + /* Registered nickname? */ if (Client_HasMode(c, 'R') && !IRC_WriteStrClient(from, RPL_WHOISREGNICK_MSG, Client_ID(from), Client_ID(c))) return DISCONNECTED; - if (Client_Conn(c) > NONE && (Client_OperByMe(from) || from == c) && - !IRC_WriteStrClient(from, RPL_WHOISHOST_MSG, Client_ID(from), - Client_ID(c), Client_Hostname(c), - Conn_GetIPAInfo(Client_Conn(c)))) - return DISCONNECTED; + /* Local client and requester is the user itself or an IRC Op? */ + if (Client_Conn(c) > NONE && + (from == c || (!Conf_MorePrivacy && Client_HasMode(from, 'o')))) { + /* Client hostname */ + if (!IRC_WriteStrClient(from, RPL_WHOISHOST_MSG, + Client_ID(from), Client_ID(c), Client_Hostname(c), + Conn_GetIPAInfo(Client_Conn(c)))) + return DISCONNECTED; + /* Client modes */ + if (!IRC_WriteStrClient(from, RPL_WHOISMODES_MSG, + Client_ID(from), Client_ID(c), Client_Modes(c))) + return DISCONNECTED; + } /* Idle and signon time (local clients only!) */ if (!Conf_MorePrivacy && Client_Conn(c) > NONE && @@ -1187,7 +1228,7 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req ) /* Get target server for this command */ if (Req->argc > 1) { /* Search the target server, which can be specified as a - * nick name on that server as well: */ + * nickname on that server as well: */ target = Client_Search(Req->argv[0]); if (!target) return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG, @@ -1456,7 +1497,7 @@ IRC_Send_LUSERS(CLIENT *Client) Conn_CountMax(), Conn_CountAccepted())) return DISCONNECTED; #endif - + return CONNECTED; } /* IRC_Send_LUSERS */ @@ -1477,7 +1518,15 @@ Show_MOTD_Sendline(CLIENT *Client, const char *msg) static bool Show_MOTD_End(CLIENT *Client) { - return IRC_WriteStrClient( Client, RPL_ENDOFMOTD_MSG, Client_ID( Client )); + if (!IRC_WriteStrClient(Client, RPL_ENDOFMOTD_MSG, Client_ID(Client))) + return DISCONNECTED; + + if (*Conf_CloakHost) + return IRC_WriteStrClient(Client, RPL_HOSTHIDDEN_MSG, + Client_ID(Client), + Client_Hostname(Client)); + + return CONNECTED; } #ifdef SSL_SUPPORT @@ -1578,16 +1627,9 @@ IRC_Send_NAMES(CLIENT * Client, CHANNEL * Chan) if (is_member || is_visible) { if (str[strlen(str) - 1] != ':') strlcat(str, " ", sizeof(str)); - if (Client_Cap(cl) & CLIENT_CAP_MULTI_PREFIX) { - if (strchr(Channel_UserModes(Chan, cl), 'o') && - strchr(Channel_UserModes(Chan, cl), 'v')) - strlcat(str, "@+", sizeof(str)); - } else { - if (strchr(Channel_UserModes(Chan, cl), 'o')) - strlcat(str, "@", sizeof(str)); - else if (strchr(Channel_UserModes(Chan, cl), 'v')) - strlcat(str, "+", sizeof(str)); - } + + who_flags_qualifier(Client, Channel_UserModes(Chan, cl), + str, sizeof(str)); strlcat(str, Client_ID(cl), sizeof(str)); if (strlen(str) > (LINE_LEN - CLIENT_NICK_LEN - 4)) { diff --git a/src/ngircd/irc-login.c b/src/ngircd/irc-login.c index 3fb1b90..80a6627 100644 --- a/src/ngircd/irc-login.c +++ b/src/ngircd/irc-login.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors. + * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors. * * 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 @@ -18,6 +18,7 @@ #include "imp.h" #include +#include #include #include #include @@ -37,7 +38,10 @@ #include "exp.h" #include "irc-login.h" -static void Kill_Nick PARAMS(( char *Nick, char *Reason )); +static void Kill_Nick PARAMS((char *Nick, char *Reason)); +static void Change_Nick PARAMS((CLIENT * Origin, CLIENT * Target, char *NewNick, + bool InformClient)); + /** * Handler for the IRC "PASS" command. @@ -87,7 +91,7 @@ IRC_PASS( CLIENT *Client, REQUEST *Req ) Client_ID(Client)); } - Client_SetPassword(Client, Req->argv[0]); + Conn_SetPassword(Client_Conn(Client), Req->argv[0]); /* Protocol version */ if (Req->argc >= 2 && strlen(Req->argv[1]) >= 4) { @@ -274,40 +278,9 @@ IRC_NICK( CLIENT *Client, REQUEST *Req ) Client_SetType( Client, CLIENT_GOTNICK ); } else { /* Nickname change */ - if (Client_Conn(target) > NONE) { - /* Local client */ - Log(LOG_INFO, - "%s \"%s\" changed nick (connection %d): \"%s\" -> \"%s\".", - Client_TypeText(target), Client_Mask(target), - Client_Conn(target), Client_ID(target), - Req->argv[0]); - Conn_UpdateIdle(Client_Conn(target)); - } else { - /* Remote client */ - LogDebug("%s \"%s\" changed nick: \"%s\" -> \"%s\".", - Client_TypeText(target), - Client_Mask(target), Client_ID(target), - Req->argv[0]); - } - - /* Inform all users and servers (which have to know) - * of this nickname change */ - if( Client_Type( Client ) == CLIENT_USER ) - IRC_WriteStrClientPrefix( Client, Client, - "NICK :%s", - Req->argv[0] ); - IRC_WriteStrServersPrefix( Client, target, - "NICK :%s", Req->argv[0] ); - IRC_WriteStrRelatedPrefix( target, target, false, - "NICK :%s", Req->argv[0] ); - - /* Register old nickname for WHOWAS queries */ - Client_RegisterWhowas( target ); - - /* Save new nickname */ - Client_SetID( target, Req->argv[0] ); - - IRC_SetPenalty( target, 2 ); + Change_Nick(Client, target, Req->argv[0], + Client_Type(Client) == CLIENT_USER ? true : false); + IRC_SetPenalty(target, 2); } return CONNECTED; @@ -388,6 +361,54 @@ IRC_NICK( CLIENT *Client, REQUEST *Req ) /** + * Handler for the IRC "SVSNICK" command. + * + * @param Client The client from which this command has been received. + * @param Req Request structure with prefix and all parameters. + * @return CONNECTED or DISCONNECTED. + */ +GLOBAL bool +IRC_SVSNICK(CLIENT *Client, REQUEST *Req) +{ + CLIENT *from, *target; + + assert(Client != NULL); + assert(Req != NULL); + + if (Req->argc != 2) + return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, + Client_ID(Client), Req->command); + + /* Search the originator */ + from = Client_Search(Req->prefix); + if (!from) + from = Client; + + /* Search the target */ + target = Client_Search(Req->argv[0]); + if (!target || Client_Type(target) != CLIENT_USER) { + return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, + Client_ID(Client), Req->argv[0]); + } + + if (Client_Conn(target) <= NONE) { + /* We have to forward the message to the server handling + * this user; this is required to make sure all servers + * in the network do follow the nick name change! */ + return IRC_WriteStrClientPrefix(Client_NextHop(target), from, + "SVSNICK %s %s", + Req->argv[0], Req->argv[1]); + } + + /* Make sure that the new nickname is valid */ + if (!Client_CheckNick(from, Req->argv[1])) + return CONNECTED; + + Change_Nick(from, target, Req->argv[1], true); + return CONNECTED; +} + +/** * Handler for the IRC "USER" command. * * See RFC 2812, 3.1.3 "User message". @@ -418,12 +439,13 @@ IRC_USER(CLIENT * Client, REQUEST * Req) Client_ID(Client), Req->command); - /* User name: only alphanumeric characters are allowed! */ + /* User name: only alphanumeric characters and limited + punctuation is allowed.*/ ptr = Req->argv[0]; while (*ptr) { - if ((*ptr < '0' || *ptr > '9') && - (*ptr < 'A' || *ptr > 'Z') && - (*ptr < 'a' || *ptr > 'z')) { + if (!isalnum((int)*ptr) && + *ptr != '+' && *ptr != '-' && + *ptr != '.' && *ptr != '_') { Conn_Close(Client_Conn(Client), NULL, "Invalid user name", true); return DISCONNECTED; @@ -544,10 +566,10 @@ IRC_SERVICE(CLIENT *Client, REQUEST *Req) hops = atoi(Req->argv[4]); info = Req->argv[5]; - /* Validate service name ("nick name") */ + /* Validate service name ("nickname") */ c = Client_Search(nick); if(c) { - /* Nick name collission: disconnect (KILL) both clients! */ + /* Nickname collission: disconnect (KILL) both clients! */ Log(LOG_ERR, "Server %s introduces already registered service \"%s\"!", Client_ID(Client), nick); Kill_Nick(nick, "Nick collision"); @@ -898,9 +920,9 @@ IRC_PONG(CLIENT *Client, REQUEST *Req) /** - * Kill all users with a specific nick name in the network. + * Kill all users with a specific nickname in the network. * - * @param Nick Nick name. + * @param Nick Nickname. * @param Reason Reason for the KILL. */ static void @@ -923,4 +945,44 @@ Kill_Nick(char *Nick, char *Reason) } /* Kill_Nick */ +/** + * Change the nickname of a client. + * + * @param Origin The client which caused the nickname change. + * @param Target The client of which the nickname should be changed. + * @param NewNick The new nickname. + */ +static void +Change_Nick(CLIENT *Origin, CLIENT *Target, char *NewNick, bool InformClient) +{ + if (Client_Conn(Target) > NONE) { + /* Local client */ + Log(LOG_INFO, + "%s \"%s\" changed nick (connection %d): \"%s\" -> \"%s\".", + Client_TypeText(Target), Client_Mask(Target), + Client_Conn(Target), Client_ID(Target), NewNick); + Conn_UpdateIdle(Client_Conn(Target)); + } else { + /* Remote client */ + LogDebug("%s \"%s\" changed nick: \"%s\" -> \"%s\".", + Client_TypeText(Target), + Client_Mask(Target), Client_ID(Target), NewNick); + } + + /* Inform all servers and users (which have to know) of the new name */ + if (InformClient) { + IRC_WriteStrClientPrefix(Target, Target, "NICK :%s", NewNick); + IRC_WriteStrServersPrefix(NULL, Target, "NICK :%s", NewNick); + } else + IRC_WriteStrServersPrefix(Origin, Target, "NICK :%s", NewNick); + IRC_WriteStrRelatedPrefix(Target, Target, false, "NICK :%s", NewNick); + + /* Register old nickname for WHOWAS queries */ + Client_RegisterWhowas(Target); + + /* Save new nickname */ + Client_SetID(Target, NewNick); +} + + /* -eof- */ diff --git a/src/ngircd/irc-login.h b/src/ngircd/irc-login.h index f3138f6..15be7b4 100644 --- a/src/ngircd/irc-login.h +++ b/src/ngircd/irc-login.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2010 Alexander Barton (alex@barton.de) + * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,6 +26,7 @@ GLOBAL bool IRC_PING PARAMS((CLIENT *Client, REQUEST *Req)); GLOBAL bool IRC_PONG PARAMS((CLIENT *Client, REQUEST *Req)); GLOBAL bool IRC_QUIT PARAMS((CLIENT *Client, REQUEST *Req)); GLOBAL bool IRC_QUIT_HTTP PARAMS((CLIENT *Client, REQUEST *Req)); +GLOBAL bool IRC_SVSNICK PARAMS(( CLIENT *Client, REQUEST *Req )); #endif diff --git a/src/ngircd/irc-metadata.c b/src/ngircd/irc-metadata.c new file mode 100644 index 0000000..308a715 --- /dev/null +++ b/src/ngircd/irc-metadata.c @@ -0,0 +1,109 @@ +/* + * ngIRCd -- The Next Generation IRC Daemon + * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors. + * + * 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. + */ + +#define __irc_metadata_c__ + +#include "portab.h" + +/** + * @file + * IRC metadata commands + */ + +#include "imp.h" +#include +#include +#include + +#include "conn-func.h" +#include "channel.h" +#include "conn-encoding.h" +#include "irc-write.h" +#include "log.h" +#include "messages.h" +#include "parse.h" +#include "tool.h" + +#include "exp.h" +#include "irc-metadata.h" + +/** + * Handler for the IRC+ "METADATA" command. + * + * @param Client The client from which this command has been received. + * @param Req Request structure with prefix and all parameters. + * @returns CONNECTED or DISCONNECTED. + */ +GLOBAL bool +IRC_METADATA(CLIENT *Client, REQUEST *Req) +{ + CLIENT *prefix, *target; + char new_flags[COMMAND_LEN]; + + assert(Client != NULL); + assert(Req != NULL); + + if (Req->argc != 3) + return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, + Client_ID(Client), Req->command); + + prefix = Client_Search(Req->prefix); + if (!prefix) + return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, + Client_ID(Client), Req->prefix); + + target = Client_Search(Req->argv[0]); + if (!target) + return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, + Client_ID(Client), Req->argv[0]); + + LogDebug("Got \"METADATA\" command from \"%s\" for client \"%s\": \"%s=%s\".", + Client_ID(prefix), Client_ID(target), + Req->argv[1], Req->argv[2]); + + /* Mark client: it has receiveda a METADATA command */ + if (!strchr(Client_Flags(target), 'M')) { + snprintf(new_flags, sizeof new_flags, "%sM", + Client_Flags(target)); + Client_SetFlags(target, new_flags); + } + + if (strcasecmp(Req->argv[1], "cloakhost") == 0) { + Client_UpdateCloakedHostname(target, prefix, Req->argv[2]); + if (Client_Conn(target) > NONE && Client_HasMode(target, 'x')) + IRC_WriteStrClientPrefix(target, prefix, + RPL_HOSTHIDDEN_MSG, Client_ID(target), + Client_HostnameDisplayed(target)); + /* The Client_UpdateCloakedHostname() function already + * forwarded the METADATA command, don't do it twice: */ + return CONNECTED; + } + else if (*Req->argv[2] && strcasecmp(Req->argv[1], "host") == 0) { + Client_SetHostname(target, Req->argv[2]); + if (Client_Conn(target) > NONE && !Client_HasMode(target, 'x')) + IRC_WriteStrClientPrefix(target, prefix, + RPL_HOSTHIDDEN_MSG, Client_ID(target), + Client_HostnameDisplayed(target)); + } else if (strcasecmp(Req->argv[1], "info") == 0) + Client_SetInfo(target, Req->argv[2]); + else if (*Req->argv[2] && strcasecmp(Req->argv[1], "user") == 0) + Client_SetUser(target, Req->argv[2], true); + else + Log(LOG_WARNING, + "Ignored metadata update from \"%s\" for client \"%s\": \"%s=%s\" - unknown key!", + Client_ID(Client), Client_ID(target), + Req->argv[1], Req->argv[2]); + + /* Forward the METADATA command to peers that support it: */ + IRC_WriteStrServersPrefixFlag(Client, prefix, 'M', "METADATA %s %s :%s", + Client_ID(target), Req->argv[1], Req->argv[2]); + return CONNECTED; +} diff --git a/src/ngircd/irc-metadata.h b/src/ngircd/irc-metadata.h new file mode 100644 index 0000000..3a2f0bb --- /dev/null +++ b/src/ngircd/irc-metadata.h @@ -0,0 +1,24 @@ +/* + * ngIRCd -- The Next Generation IRC Daemon + * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors. + * + * 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. + */ + +#ifndef __irc_metadata_h__ +#define __irc_metadata_h__ + +/** + * @file + * IRC metadata commands (header) + */ + +GLOBAL bool IRC_METADATA PARAMS((CLIENT *Client, REQUEST *Req)); + +#endif + +/* -eof- */ diff --git a/src/ngircd/irc-mode.c b/src/ngircd/irc-mode.c index fa35cdd..3221997 100644 --- a/src/ngircd/irc-mode.c +++ b/src/ngircd/irc-mode.c @@ -138,6 +138,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) { char the_modes[COMMAND_LEN], x[2], *mode_ptr; bool ok, set; + bool send_RPL_HOSTHIDDEN_MSG = false; int mode_arg; size_t len; @@ -153,7 +154,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) /* Mode request: let's answer it :-) */ if (Req->argc == 1) return IRC_WriteStrClient(Origin, RPL_UMODEIS_MSG, - Client_ID(Origin), + Client_ID(Target), Client_Modes(Target)); mode_arg = 1; @@ -214,6 +215,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) /* Validate modes */ x[0] = '\0'; switch (*mode_ptr) { + case 'b': /* Block private msgs */ case 'C': /* Only messages from clients sharing a channel */ case 'i': /* Invisible */ case 's': /* Server messages */ @@ -229,6 +231,14 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) ERR_NOPRIVILEGES_MSG, Client_ID(Origin)); break; + case 'B': /* Bot */ + if (Client_HasMode(Client, 'r')) + ok = IRC_WriteStrClient(Origin, + ERR_RESTRICTED_MSG, + Client_ID(Origin)); + else + x[0] = 'B'; + break; case 'c': /* Receive connect notices * (only settable by IRC operators!) */ if (!set || Client_Type(Client) == CLIENT_SERVER @@ -248,6 +258,15 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) ERR_NOPRIVILEGES_MSG, Client_ID(Origin)); break; + case 'q': /* KICK-protected user */ + if (!set || Client_Type(Client) == CLIENT_SERVER + || Client_OperByMe(Origin)) + x[0] = 'q'; + else + ok = IRC_WriteStrClient(Origin, + ERR_NOPRIVILEGES_MSG, + Client_ID(Origin)); + break; case 'r': /* Restricted (only settable) */ if (set || Client_Type(Client) == CLIENT_SERVER) x[0] = 'r'; @@ -256,13 +275,28 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) ERR_RESTRICTED_MSG, Client_ID(Origin)); break; + case 'R': /* Registered (not [un]settable by clients) */ + if (Client_Type(Client) == CLIENT_SERVER) + x[0] = 'R'; + else + ok = IRC_WriteStrClient(Origin, + ERR_NICKREGISTER_MSG, + Client_ID(Origin)); + break; case 'x': /* Cloak hostname */ if (Client_HasMode(Client, 'r')) ok = IRC_WriteStrClient(Origin, ERR_RESTRICTED_MSG, Client_ID(Origin)); - else + else if (!set || Conf_CloakHostModeX[0] + || Client_Type(Client) == CLIENT_SERVER + || Client_OperByMe(Client)) { x[0] = 'x'; + send_RPL_HOSTHIDDEN_MSG = true; + } else + ok = IRC_WriteStrClient(Origin, + ERR_NOPRIVILEGES_MSG, + Client_ID(Origin)); break; default: if (Client_Type(Client) != CLIENT_SERVER) { @@ -333,6 +367,16 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) Client_ID(Target), the_modes); } + + if (send_RPL_HOSTHIDDEN_MSG && Client_Conn(Target) > NONE) { + /* A new (cloaked) hostname must be annoucned */ + IRC_WriteStrClientPrefix(Target, Origin, + RPL_HOSTHIDDEN_MSG, + Client_ID(Target), + Client_HostnameDisplayed(Target)); + + } + LogDebug("%s \"%s\": Mode change, now \"%s\".", Client_TypeText(Target), Client_Mask(Target), Client_Modes(Target)); @@ -396,13 +440,16 @@ static bool Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) { char the_modes[COMMAND_LEN], the_args[COMMAND_LEN], x[2], - argadd[CLIENT_PASS_LEN], *mode_ptr; - bool connected, set, skiponce, retval, onchannel, modeok, use_servermode; + argadd[CLIENT_PASS_LEN], *mode_ptr, *o_mode_ptr; + bool connected, set, skiponce, retval, use_servermode, + is_halfop, is_op, is_admin, is_owner, is_machine, is_oper; int mode_arg, arg_arg, mode_arg_count = 0; CLIENT *client; long l; size_t len; + is_halfop = is_op = is_admin = is_owner = is_machine = is_oper = false; + if (Channel_IsModeless(Channel)) return IRC_WriteStrClient(Client, ERR_NOCHANMODES_MSG, Client_ID(Client), Channel_Name(Channel)); @@ -411,10 +458,20 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) if (Req->argc <= 1) return Channel_Mode_Answer_Request(Origin, Channel); - Channel_CheckAdminRights(Channel, Client, Origin, - &onchannel, &modeok, &use_servermode); + /* Check if origin is oper and opers can use mode */ + use_servermode = Conf_OperServerMode; + if(Client_OperByMe(Client) && Conf_OperCanMode) { + is_oper = true; + } + + /* Check if client is a server/service */ + if(Client_Type(Client) == CLIENT_SERVER || + Client_Type(Client) == CLIENT_SERVICE) { + is_machine = true; + } - if (!onchannel && !modeok) + /* Check if client is member of channel or an oper or an server/service */ + if(!Channel_IsMemberOf(Channel, Client) && !is_oper && !is_machine) return IRC_WriteStrClient(Origin, ERR_NOTONCHANNEL_MSG, Client_ID(Origin), Channel_Name(Channel)); @@ -493,20 +550,46 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) if (arg_arg >= Req->argc) arg_arg = -1; + if(!is_machine) { + o_mode_ptr = Channel_UserModes(Channel, Client); + while( *o_mode_ptr ) { + if ( *o_mode_ptr == 'q') + is_owner = true; + if ( *o_mode_ptr == 'a') + is_admin = true; + if ( *o_mode_ptr == 'o') + is_op = true; + if ( *o_mode_ptr == 'h') + is_halfop = true; + o_mode_ptr++; + } + } + /* Validate modes */ x[0] = '\0'; argadd[0] = '\0'; client = NULL; switch (*mode_ptr) { /* --- Channel modes --- */ + case 'R': /* Registered users only */ + case 's': /* Secret channel */ + case 'z': /* Secure connections only */ + if(!is_oper && !is_machine && !is_owner && + !is_admin && !is_op) { + connected = IRC_WriteStrClient(Origin, + ERR_CHANOPRIVSNEEDED_MSG, + Client_ID(Origin), Channel_Name(Channel)); + goto chan_exit; + } case 'i': /* Invite only */ + case 'V': /* Invite disallow */ + case 'M': /* Only identified nicks can write */ case 'm': /* Moderated */ case 'n': /* Only members can write */ - case 'R': /* Registered users only */ - case 's': /* Secret channel */ + case 'Q': /* No kicks */ case 't': /* Topic locked */ - case 'z': /* Secure connections only */ - if (modeok) + if(is_oper || is_machine || is_owner || + is_admin || is_op || is_halfop) x[0] = *mode_ptr; else connected = IRC_WriteStrClient(Origin, @@ -517,7 +600,8 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) if (Mode_Limit_Reached(Client, mode_arg_count++)) goto chan_exit; if (!set) { - if (modeok) + if (is_oper || is_machine || is_owner || + is_admin || is_op || is_halfop) x[0] = *mode_ptr; else connected = IRC_WriteStrClient(Origin, @@ -527,7 +611,8 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) break; } if (arg_arg > mode_arg) { - if (modeok) { + if (is_oper || is_machine || is_owner || + is_admin || is_op || is_halfop) { Channel_ModeDel(Channel, 'k'); Channel_SetKey(Channel, Req->argv[arg_arg]); @@ -553,7 +638,8 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) if (Mode_Limit_Reached(Client, mode_arg_count++)) goto chan_exit; if (!set) { - if (modeok) + if (is_oper || is_machine || is_owner || + is_admin || is_op || is_halfop) x[0] = *mode_ptr; else connected = IRC_WriteStrClient(Origin, @@ -563,7 +649,8 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) break; } if (arg_arg > mode_arg) { - if (modeok) { + if (is_oper || is_machine || is_owner || + is_admin || is_op || is_halfop) { l = atol(Req->argv[arg_arg]); if (l > 0 && l < 0xFFFF) { Channel_ModeDel(Channel, 'l'); @@ -588,61 +675,82 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) } break; case 'O': /* IRC operators only */ - if (modeok) { + if (set) { /* Only IRC operators are allowed to * set the 'O' channel mode! */ - if (set && !(Client_OperByMe(Client) - || Client_Type(Client) == CLIENT_SERVER)) + if(is_oper || is_machine) + x[0] = 'O'; + else connected = IRC_WriteStrClient(Origin, ERR_NOPRIVILEGES_MSG, Client_ID(Origin)); - else - x[0] = 'O'; - } else + } else if(is_oper || is_machine || is_owner || + is_admin || is_op) + x[0] = 'O'; + else connected = IRC_WriteStrClient(Origin, - ERR_CHANOPRIVSNEEDED_MSG, - Client_ID(Origin), - Channel_Name(Channel)); - break; + ERR_CHANOPRIVSNEEDED_MSG, + Client_ID(Origin), + Channel_Name(Channel)); + break; case 'P': /* Persistent channel */ - if (modeok) { + if (set) { /* Only IRC operators are allowed to * set the 'P' channel mode! */ - if (set && !(Client_OperByMe(Client) - || Client_Type(Client) == CLIENT_SERVER)) + if(is_oper || is_machine) + x[0] = 'P'; + else connected = IRC_WriteStrClient(Origin, ERR_NOPRIVILEGES_MSG, Client_ID(Origin)); - else - x[0] = 'P'; - } else + } else if(is_oper || is_machine || is_owner || + is_admin || is_op) + x[0] = 'P'; + else connected = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(Origin), Channel_Name(Channel)); break; /* --- Channel user modes --- */ - case 'a': - case 'h': - case 'q': - if (Client_Type(Client) != CLIENT_SERVER) { + case 'q': /* Owner */ + case 'a': /* Channel admin */ + if(!is_oper && !is_machine && !is_owner && !is_admin) { connected = IRC_WriteStrClient(Origin, - ERR_CHANOPRIVSNEEDED_MSG, + ERR_CHANOPPRIVTOOLOW_MSG, Client_ID(Origin), Channel_Name(Channel)); goto chan_exit; } case 'o': /* Channel operator */ + if(!is_oper && !is_machine && !is_owner && + !is_admin && !is_op) { + connected = IRC_WriteStrClient(Origin, + ERR_CHANOPRIVSNEEDED_MSG, + Client_ID(Origin), + Channel_Name(Channel)); + goto chan_exit; + } + case 'h': /* Half Op */ + if(!is_oper && !is_machine && !is_owner && + !is_admin && !is_op) { + connected = IRC_WriteStrClient(Origin, + ERR_CHANOPRIVSNEEDED_MSG, + Client_ID(Origin), + Channel_Name(Channel)); + goto chan_exit; + } case 'v': /* Voice */ if (arg_arg > mode_arg) { - if (modeok) { + if (is_oper || is_machine || is_owner || + is_admin || is_op || is_halfop) { client = Client_Search(Req->argv[arg_arg]); if (client) x[0] = *mode_ptr; else - connected = IRC_WriteStrClient(Client, + connected = IRC_WriteStrClient(Origin, ERR_NOSUCHNICK_MSG, - Client_ID(Client), + Client_ID(Origin), Req->argv[arg_arg]); } else { connected = IRC_WriteStrClient(Origin, @@ -667,7 +775,8 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel) goto chan_exit; if (arg_arg > mode_arg) { /* modify list */ - if (modeok) { + if (is_oper || is_machine || is_owner || + is_admin || is_op || is_halfop) { connected = set ? Add_To_List(*mode_ptr, Origin, Client, Channel, diff --git a/src/ngircd/irc-op.c b/src/ngircd/irc-op.c index 5e36b02..5c12faf 100644 --- a/src/ngircd/irc-op.c +++ b/src/ngircd/irc-op.c @@ -164,10 +164,18 @@ IRC_INVITE(CLIENT *Client, REQUEST *Req) if (!Channel_IsMemberOf(chan, from)) return IRC_WriteStrClient(from, ERR_NOTONCHANNEL_MSG, Client_ID(Client), Req->argv[1]); + /* Is the channel "invite-disallow"? */ + if (strchr(Channel_Modes(chan), 'V')) + return IRC_WriteStrClient(from, ERR_NOINVITE_MSG, + Client_ID(from), Channel_Name(chan)); + /* Is the channel "invite-only"? */ if (strchr(Channel_Modes(chan), 'i')) { - /* Yes. The user must be channel operator! */ - if (!strchr(Channel_UserModes(chan, from), 'o')) + /* Yes. The user must be channel owner/admin/operator/halfop! */ + if (!strchr(Channel_UserModes(chan, from), 'q') && + !strchr(Channel_UserModes(chan, from), 'a') && + !strchr(Channel_UserModes(chan, from), 'o') && + !strchr(Channel_UserModes(chan, from), 'h')) return IRC_WriteStrClient(from, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(from), Channel_Name(chan)); remember = true; diff --git a/src/ngircd/irc-oper.c b/src/ngircd/irc-oper.c index 21577f0..237107f 100644 --- a/src/ngircd/irc-oper.c +++ b/src/ngircd/irc-oper.c @@ -183,6 +183,8 @@ IRC_REHASH( CLIENT *Client, REQUEST *Req ) Log(LOG_NOTICE|LOG_snotice, "Got REHASH command from \"%s\" ...", Client_Mask(Client)); + IRC_WriteStrClient(Client, RPL_REHASHING_MSG, Client_ID(Client)); + raise(SIGHUP); return CONNECTED; diff --git a/src/ngircd/irc-server.c b/src/ngircd/irc-server.c index cca295a..a587c52 100644 --- a/src/ngircd/irc-server.c +++ b/src/ngircd/irc-server.c @@ -53,8 +53,7 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req ) char str[LINE_LEN]; CLIENT *from, *c; int i; - CONN_ID con; - + assert( Client != NULL ); assert( Req != NULL ); @@ -70,26 +69,44 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req ) LogDebug("Connection %d: got SERVER command (new server link) ...", Client_Conn(Client)); - if(( Req->argc != 2 ) && ( Req->argc != 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - - /* Ist this server configured on out side? */ - for( i = 0; i < MAX_SERVERS; i++ ) if( strcasecmp( Req->argv[0], Conf_Server[i].name ) == 0 ) break; - if( i >= MAX_SERVERS ) - { - Log( LOG_ERR, "Connection %d: Server \"%s\" not configured here!", Client_Conn( Client ), Req->argv[0] ); - Conn_Close( Client_Conn( Client ), NULL, "Server not configured here", true); + if (Req->argc != 2 && Req->argc != 3) + return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, + Client_ID(Client), + Req->command); + + /* Get configuration index of new remote server ... */ + for (i = 0; i < MAX_SERVERS; i++) + if (strcasecmp(Req->argv[0], Conf_Server[i].name) == 0) + break; + + /* Makre sure the remote server is configured here */ + if (i >= MAX_SERVERS) { + Log(LOG_ERR, + "Connection %d: Server \"%s\" not configured here!", + Client_Conn(Client), Req->argv[0]); + Conn_Close(Client_Conn(Client), NULL, + "Server not configured here", true); return DISCONNECTED; } - if( strcmp( Client_Password( Client ), Conf_Server[i].pwd_in ) != 0 ) - { - /* wrong password */ - Log( LOG_ERR, "Connection %d: Got bad password from server \"%s\"!", Client_Conn( Client ), Req->argv[0] ); - Conn_Close( Client_Conn( Client ), NULL, "Bad password", true); + + /* Check server password */ + if (strcmp(Conn_Password(Client_Conn(Client)), + Conf_Server[i].pwd_in) != 0) { + Log(LOG_ERR, + "Connection %d: Got bad password from server \"%s\"!", + Client_Conn(Client), Req->argv[0]); + Conn_Close(Client_Conn(Client), NULL, + "Bad password", true); return DISCONNECTED; } - + /* Is there a registered server with this ID? */ - if( ! Client_CheckID( Client, Req->argv[0] )) return DISCONNECTED; + if (!Client_CheckID(Client, Req->argv[0])) + return DISCONNECTED; + + /* Mark this connection as belonging to an configured server */ + if (!Conf_SetServer(i, Client_Conn(Client))) + return DISCONNECTED; Client_SetID( Client, Req->argv[0] ); Client_SetHops( Client, 1 ); @@ -97,7 +114,6 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req ) /* Is this server registering on our side, or are we connecting to * a remote server? */ - con = Client_Conn(Client); if (Client_Token(Client) != TOKEN_OUTBOUND) { /* Incoming connection, send user/pass */ if (!IRC_WriteStrClient(Client, "PASS %s %s", @@ -106,7 +122,8 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req ) || !IRC_WriteStrClient(Client, "SERVER %s 1 :%s", Conf_ServerName, Conf_ServerInfo)) { - Conn_Close(con, "Unexpected server behavior!", + Conn_Close(Client_Conn(Client), + "Unexpected server behavior!", NULL, false); return DISCONNECTED; } @@ -118,25 +135,25 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req ) Client_SetToken(Client, atoi(Req->argv[1])); } - /* Mark this connection as belonging to an configured server */ - Conf_SetServer(i, con); - /* Check protocol level */ if (Client_Type(Client) == CLIENT_GOTPASS) { /* We got a "simple" PASS command, so the peer is * using the protocol as defined in RFC 1459. */ - if (! (Conn_Options(con) & CONN_RFC1459)) + if (! (Conn_Options(Client_Conn(Client)) & CONN_RFC1459)) Log(LOG_INFO, "Switching connection %d (\"%s\") to RFC 1459 compatibility mode.", - con, Client_ID(Client)); - Conn_SetOption(con, CONN_RFC1459); + Client_Conn(Client), Client_ID(Client)); + Conn_SetOption(Client_Conn(Client), CONN_RFC1459); } Client_SetType(Client, CLIENT_UNKNOWNSERVER); #ifdef ZLIB - if (strchr(Client_Flags(Client), 'Z') && !Zip_InitConn(con)) { - Conn_Close( con, "Can't inizialize compression (zlib)!", NULL, false ); + if (strchr(Client_Flags(Client), 'Z') + && !Zip_InitConn(Client_Conn(Client))) { + Conn_Close(Client_Conn(Client), + "Can't inizialize compression (zlib)!", + NULL, false ); return DISCONNECTED; } #endif @@ -202,10 +219,10 @@ GLOBAL bool IRC_NJOIN( CLIENT *Client, REQUEST *Req ) { char nick_in[COMMAND_LEN], nick_out[COMMAND_LEN], *channame, *ptr, modes[8]; - bool is_op, is_voiced; + bool is_owner, is_chanadmin, is_op, is_halfop, is_voiced; CHANNEL *chan; CLIENT *c; - + assert( Client != NULL ); assert( Req != NULL ); @@ -218,12 +235,16 @@ IRC_NJOIN( CLIENT *Client, REQUEST *Req ) ptr = strtok( nick_in, "," ); while( ptr ) { - is_op = is_voiced = false; - + is_owner = is_chanadmin = is_op = is_halfop = is_voiced = false; + /* cut off prefixes */ - while(( *ptr == '@' ) || ( *ptr == '+' )) + while(( *ptr == '~') || ( *ptr == '&' ) || ( *ptr == '@' ) || + ( *ptr == '%') || ( *ptr == '+' )) { + if( *ptr == '~' ) is_owner = true; + if( *ptr == '&' ) is_chanadmin = true; if( *ptr == '@' ) is_op = true; + if( *ptr == 'h' ) is_halfop = true; if( *ptr == '+' ) is_voiced = true; ptr++; } @@ -234,8 +255,11 @@ IRC_NJOIN( CLIENT *Client, REQUEST *Req ) Channel_Join( c, channame ); chan = Channel_Search( channame ); assert( chan != NULL ); - + + if( is_owner ) Channel_UserModeAdd( chan, c, 'q' ); + if( is_chanadmin ) Channel_UserModeAdd( chan, c, 'a' ); if( is_op ) Channel_UserModeAdd( chan, c, 'o' ); + if( is_halfop ) Channel_UserModeAdd( chan, c, 'h' ); if( is_voiced ) Channel_UserModeAdd( chan, c, 'v' ); /* announce to channel... */ @@ -250,12 +274,15 @@ IRC_NJOIN( CLIENT *Client, REQUEST *Req ) } if( nick_out[0] != '\0' ) strlcat( nick_out, ",", sizeof( nick_out )); + if( is_owner ) strlcat( nick_out, "~", sizeof( nick_out )); + if( is_chanadmin ) strlcat( nick_out, "&", sizeof( nick_out )); if( is_op ) strlcat( nick_out, "@", sizeof( nick_out )); + if( is_halfop ) strlcat( nick_out, "%", sizeof( nick_out )); if( is_voiced ) strlcat( nick_out, "+", sizeof( nick_out )); strlcat( nick_out, ptr, sizeof( nick_out )); } else Log( LOG_ERR, "Got NJOIN for unknown nick \"%s\" for channel \"%s\"!", ptr, channame ); - + /* search for next Nick */ ptr = strtok( NULL, "," ); } diff --git a/src/ngircd/irc.c b/src/ngircd/irc.c index 9508ecc..63c4813 100644 --- a/src/ngircd/irc.c +++ b/src/ngircd/irc.c @@ -25,6 +25,7 @@ #include "conn-func.h" #include "conf.h" #include "channel.h" +#include "conn-encoding.h" #include "defines.h" #include "irc-write.h" #include "log.h" @@ -327,12 +328,18 @@ IRC_HELP( CLIENT *Client, REQUEST *Req ) static char * -Option_String( CONN_ID Idx ) +#ifdef ZLIB +Option_String(CONN_ID Idx) +#else +Option_String(UNUSED CONN_ID Idx) +#endif { static char option_txt[8]; +#ifdef ZLIB UINT16 options; options = Conn_Options(Idx); +#endif strcpy(option_txt, "F"); /* No idea what this means, but the * original ircd sends it ... */ @@ -353,6 +360,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) CHANNEL *chan; char *currentTarget = Req->argv[0]; char *lastCurrentTarget = NULL; + char *message = NULL; assert(Client != NULL); assert(Req != NULL); @@ -384,6 +392,13 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, Client_ID(Client), Req->prefix); +#ifdef ICONV + if (Client_Conn(Client) > NONE) + message = Conn_EncodingFrom(Client_Conn(Client), Req->argv[1]); + else +#endif + message = Req->argv[1]; + /* handle msgtarget = msgto *("," msgto) */ currentTarget = strtok_r(currentTarget, ",", &lastCurrentTarget); ngt_UpperStr(Req->command); @@ -442,7 +457,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) if (nick != NULL && host != NULL) { if (strcasecmp(nick, Client_ID(cl)) == 0 && strcasecmp(user, Client_User(cl)) == 0 && - strcasecmp(host, Client_HostnameCloaked(cl)) == 0) + strcasecmp(host, Client_HostnameDisplayed(cl)) == 0) break; else continue; @@ -450,7 +465,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) if (strcasecmp(user, Client_User(cl)) != 0) continue; if (host != NULL && strcasecmp(host, - Client_HostnameCloaked(cl)) != 0) + Client_HostnameDisplayed(cl)) != 0) continue; if (server != NULL && strcasecmp(server, Client_ID(Client_Introducer(cl))) != 0) @@ -485,6 +500,17 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) Req->command = "PRIVMSG"; } #endif + if (Client_HasMode(cl, 'b') && + !Client_HasMode(from, 'R') && + !Client_HasMode(from, 'o') && + !(Client_Type(from) == CLIENT_SERVER) && + !(Client_Type(from) == CLIENT_SERVICE)) { + if (SendErrors && !IRC_WriteStrClient(from, + ERR_NONONREG_MSG, + Client_ID(from), Client_ID(cl))) + return DISCONNECTED; + goto send_next_target; + } if (Client_HasMode(cl, 'C')) { cl2chan = Channel_FirstChannelOf(cl); @@ -517,12 +543,12 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) } if (!IRC_WriteStrClientPrefix(cl, from, "%s %s :%s", Req->command, Client_ID(cl), - Req->argv[1])) + message)) return DISCONNECTED; } else if (ForceType != CLIENT_SERVICE && (chan = Channel_Search(currentTarget))) { if (!Channel_Write(chan, from, Client, Req->command, - SendErrors, Req->argv[1])) + SendErrors, message)) return DISCONNECTED; } else if (ForceType != CLIENT_SERVICE /* $#: server/target mask, RFC 2812, sec. 3.3.1 */ @@ -530,7 +556,7 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors) && strchr(currentTarget, '.')) { /* targetmask */ if (!Send_Message_Mask(from, Req->command, currentTarget, - Req->argv[1], SendErrors)) + message, SendErrors)) return DISCONNECTED; } else { if (!SendErrors) diff --git a/src/ngircd/lists.c b/src/ngircd/lists.c index 5c6c52c..6faf311 100644 --- a/src/ngircd/lists.c +++ b/src/ngircd/lists.c @@ -283,7 +283,7 @@ Lists_MakeMask(const char *Pattern) excl = NULL; if (!at && !excl) { - /* Neither "!" nor "@" found: use string as nick name */ + /* Neither "!" nor "@" found: use string as nickname */ strlcpy(TheMask, Pattern, sizeof(TheMask) - 5); strlcat(TheMask, "!*@*", sizeof(TheMask)); return TheMask; diff --git a/src/ngircd/log.c b/src/ngircd/log.c index 6f0c4c9..51bd2a5 100644 --- a/src/ngircd/log.c +++ b/src/ngircd/log.c @@ -80,9 +80,9 @@ Log_Init(bool Daemon_Mode) #define LOG_CONS 0 #endif #ifdef LOG_DAEMON - openlog(PACKAGE_NAME, LOG_CONS|LOG_PID, LOG_DAEMON); + openlog(PACKAGE, LOG_CONS|LOG_PID, LOG_DAEMON); #else - openlog(PACKAGE_NAME, LOG_CONS|LOG_PID, 0); + openlog(PACKAGE, LOG_CONS|LOG_PID, 0); #endif #endif } /* Log_Init */ @@ -99,7 +99,7 @@ Log_ReInit(void) #define LOG_CONS 0 #endif closelog(); - openlog(PACKAGE_NAME, LOG_CONS|LOG_PID, Conf_SyslogFacility); + openlog(PACKAGE, LOG_CONS|LOG_PID, Conf_SyslogFacility); #endif Log(LOG_NOTICE, "%s started.", NGIRCd_Version); Log(LOG_INFO, "Using configuration file \"%s\" ...", NGIRCd_ConfFile); @@ -218,7 +218,7 @@ GLOBAL void Log_Init_Subprocess(char UNUSED *Name) { #ifdef SYSLOG - openlog(PACKAGE_NAME, LOG_CONS|LOG_PID, Conf_SyslogFacility); + openlog(PACKAGE, LOG_CONS|LOG_PID, Conf_SyslogFacility); #endif #ifdef DEBUG Log_Subprocess(LOG_DEBUG, "%s sub-process starting, PID %ld.", diff --git a/src/ngircd/login.c b/src/ngircd/login.c index 7f0299c..d79344b 100644 --- a/src/ngircd/login.c +++ b/src/ngircd/login.c @@ -93,13 +93,14 @@ Login_User(CLIENT * Client) * the beahiour of the daemon compiled without PAM support: * because there can't be any "server password", all * passwords supplied are classified as "wrong". */ - if(Client_Password(Client)[0] == '\0') + if(Conn_Password(conn)[0] == '\0') return Login_User_PostAuth(Client); Client_Reject(Client, "Non-empty password", false); return DISCONNECTED; } - if (Conf_PAMIsOptional && strcmp(Client_Password(Client), "") == 0) { + if (Conf_PAMIsOptional && + strcmp(Conn_Password(conn), "") == 0) { /* Clients are not required to send a password and to be PAM- * authenticated at all. If not, they won't become "identified" * and keep the "~" in their supplied user name. @@ -129,7 +130,7 @@ Login_User(CLIENT * Client) } #else /* Check global server password ... */ - if (strcmp(Client_Password(Client), Conf_ServerPwd) != 0) { + if (strcmp(Conn_Password(conn), Conf_ServerPwd) != 0) { /* Bad password! */ Client_Reject(Client, "Bad server password", false); return DISCONNECTED; @@ -162,8 +163,8 @@ Login_User_PostAuth(CLIENT *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)) + Client_ID(Client_ThisServer()), PACKAGE_VERSION, HOST_CPU, + HOST_VENDOR, HOST_OS)) return false; if (!IRC_WriteStrClient (Client, RPL_CREATED_MSG, Client_ID(Client), NGIRCd_StartStr)) diff --git a/src/ngircd/match.c b/src/ngircd/match.c index 79699ea..75bf435 100644 --- a/src/ngircd/match.c +++ b/src/ngircd/match.c @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) + * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors. * * 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 @@ -48,9 +48,9 @@ static int Matche_After_Star PARAMS(( const char *p, const char *t )); /** * Match string with pattern. * - * @param Pattern Pattern to match with - * @param String Input string - * @return true if pattern matches + * @param Pattern Pattern to match with + * @param String Input string + * @return true if pattern matches */ GLOBAL bool Match( const char *Pattern, const char *String ) @@ -64,17 +64,46 @@ Match( const char *Pattern, const char *String ) /** * Match string with pattern case-insensitive. * - * @param pattern Pattern to match with - * @param searchme Input string, at most COMMAND_LEN-1 characters long - * @return true if pattern matches + * @param Pattern Pattern to match with + * @param String Input string, at most COMMAND_LEN-1 characters long + * @return true if pattern matches */ GLOBAL bool -MatchCaseInsensitive(const char *pattern, const char *searchme) +MatchCaseInsensitive(const char *Pattern, const char *String) { char haystack[COMMAND_LEN]; - strlcpy(haystack, searchme, sizeof(haystack)); - return Match(pattern, ngt_LowerStr(haystack)); + strlcpy(haystack, String, sizeof(haystack)); + return Match(Pattern, ngt_LowerStr(haystack)); +} /* MatchCaseInsensitive */ + + +/** + * Match string with pattern case-insensitive. + * + * @param pattern Pattern to match with + * @param String Input string, at most COMMAND_LEN-1 characters long + * @param Separator Character separating the individual patterns in the list + * @return true if pattern matches + */ +GLOBAL bool +MatchCaseInsensitiveList(const char *Pattern, const char *String, + const char *Separator) +{ + char tmp_pattern[COMMAND_LEN], haystack[COMMAND_LEN], *ptr; + + strlcpy(tmp_pattern, Pattern, sizeof(tmp_pattern)); + strlcpy(haystack, String, sizeof(haystack)); + ngt_LowerStr(haystack); + + ptr = strtok(tmp_pattern, Separator); + while (ptr) { + ngt_TrimStr(ptr); + if (Match(ptr, haystack)) + return true; + ptr = strtok(NULL, Separator); + } + return false; } /* MatchCaseInsensitive */ diff --git a/src/ngircd/match.h b/src/ngircd/match.h index 2efe3f5..d4107fb 100644 --- a/src/ngircd/match.h +++ b/src/ngircd/match.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) + * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors. * * 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 @@ -17,8 +17,14 @@ * Wildcard pattern matching (header) */ -GLOBAL bool Match PARAMS(( const char *Pattern, const char *String )); -GLOBAL bool MatchCaseInsensitive PARAMS(( const char *Pattern, const char *searchme )); +GLOBAL bool Match PARAMS((const char *Pattern, const char *String)); + +GLOBAL bool MatchCaseInsensitive PARAMS((const char *Pattern, + const char *String)); + +GLOBAL bool MatchCaseInsensitiveList PARAMS((const char *Pattern, + const char *String, + const char *Separator)); #endif diff --git a/src/ngircd/messages.h b/src/ngircd/messages.h index 96ff2de..a6a6d8c 100644 --- a/src/ngircd/messages.h +++ b/src/ngircd/messages.h @@ -21,7 +21,7 @@ #define RPL_YOURHOST_MSG "002 %s :Your host is %s, running version ngircd-%s (%s/%s/%s)" #define RPL_CREATED_MSG "003 %s :This server has been started %s" #define RPL_MYINFO_MSG "004 %s %s ngircd-%s %s %s" -#define RPL_ISUPPORT1_MSG "005 %s RFC2812 IRCD=ngIRCd CASEMAPPING=ascii PREFIX=(ov)@+ CHANTYPES=#&+ CHANMODES=beI,k,l,imnOPRstz CHANLIMIT=#&+:%d :are supported on this server" +#define RPL_ISUPPORT1_MSG "005 %s RFC2812 IRCD=ngIRCd CHARSET=UTF-8 CASEMAPPING=ascii PREFIX=(qaohv)~&@%%+ CHANTYPES=#&+ CHANMODES=beI,k,l,imMnOPQRstVz CHANLIMIT=#&+:%d :are supported on this server" #define RPL_ISUPPORT2_MSG "005 %s CHANNELLEN=%d NICKLEN=%d TOPICLEN=%d AWAYLEN=%d KICKLEN=%d MODES=%d MAXLIST=beI:%d EXCEPTS=e INVEX=I PENALTY :are supported on this server" #define RPL_TRACELINK_MSG "200 %s Link %s-%s %s %s V%s %ld %d %d" @@ -34,7 +34,6 @@ #define RPL_UMODEIS_MSG "221 %s +%s" #define RPL_SERVLIST_MSG "234 %s %s %s %s %d %d :%s" #define RPL_SERVLISTEND_MSG "235 %s %s %s :End of service listing" - #define RPL_STATSUPTIME "242 %s :Server Up %u days %u:%02u:%02u" #define RPL_LUSERCLIENT_MSG "251 %s :There are %ld users and %ld services on %ld servers" #define RPL_LUSEROP_MSG "252 %s %lu :operator(s) online" @@ -72,6 +71,7 @@ #define RPL_NOTOPIC_MSG "331 %s %s :No topic is set" #define RPL_TOPIC_MSG "332 %s %s :%s" #define RPL_TOPICSETBY_MSG "333 %s %s %s %u" +#define RPL_WHOISBOT_MSG "335 %s %s :is a IRC Bot" #define RPL_INVITING_MSG "341 %s %s %s%s" #define RPL_INVITELIST_MSG "346 %s %s %s" #define RPL_ENDOFINVITELIST_MSG "347 %s %s :End of channel invite list" @@ -92,9 +92,12 @@ #define RPL_MOTDSTART_MSG "375 %s :- %s message of the day" #define RPL_ENDOFMOTD_MSG "376 %s :End of MOTD command" #define RPL_WHOISHOST_MSG "378 %s %s :is connecting from *@%s %s" +#define RPL_WHOISMODES_MSG "379 %s %s :is using modes +%s" #define RPL_YOUREOPER_MSG "381 %s :You are now an IRC Operator" +#define RPL_REHASHING_MSG "382 %s :Rehashing" #define RPL_YOURESERVICE_MSG "383 %s :You are service %s" #define RPL_TIME_MSG "391 %s %s :%s" +#define RPL_HOSTHIDDEN_MSG "396 %s %s :is your displayed hostname now" #define ERR_NOSUCHNICK_MSG "401 %s %s :No such nick or channel name" #define ERR_NOSUCHSERVER_MSG "402 %s %s :No such server" @@ -112,6 +115,7 @@ #define ERR_NONICKNAMEGIVEN_MSG "431 %s :No nickname given" #define ERR_ERRONEUSNICKNAME_MSG "432 %s %s :Erroneous nickname" #define ERR_NICKNAMETOOLONG_MSG "432 %s %s :Nickname too long, max. %u characters" +#define ERR_FORBIDDENNICKNAME_MSG "432 %s %s :Nickname is forbidden/blocked" #define ERR_NICKNAMEINUSE_MSG "433 %s %s :Nickname already in use" #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" @@ -123,31 +127,45 @@ #define ERR_NEEDMOREPARAMS_MSG "461 %s %s :Syntax error" #define ERR_ALREADYREGISTRED_MSG "462 %s :Connection already registered" #define ERR_PASSWDMISMATCH_MSG "464 %s :Invalid password" -#define ERR_CHANNELISFULL_MSG "471 %s %s :Cannot join channel (+l)" -#define ERR_SECURECHANNEL_MSG "471 %s %s :Cannot join channel (+z)" -#define ERR_OPONLYCHANNEL_MSG "471 %s %s :Cannot join channel (+O)" -#define ERR_REGONLYCHANNEL_MSG "471 %s %s :Cannot join channel (+R)" +#define ERR_CHANNELISFULL_MSG "471 %s %s :Cannot join channel (+l) -- Channel is full, try later" +#define ERR_SECURECHANNEL_MSG "471 %s %s :Cannot join channel (+z) -- SSL connections only" +#define ERR_OPONLYCHANNEL_MSG "471 %s %s :Cannot join channel (+O) -- IRC opers only" +#define ERR_REGONLYCHANNEL_MSG "471 %s %s :Cannot join channel (+R) -- Registered users only" #define ERR_UNKNOWNMODE_MSG "472 %s %c :is unknown mode char for %s" -#define ERR_INVITEONLYCHAN_MSG "473 %s %s :Cannot join channel (+i)" -#define ERR_BANNEDFROMCHAN_MSG "474 %s %s :Cannot join channel (+b)" -#define ERR_BADCHANNELKEY_MSG "475 %s %s :Cannot join channel (+k)" +#define ERR_INVITEONLYCHAN_MSG "473 %s %s :Cannot join channel (+i) -- Invited users only" +#define ERR_BANNEDFROMCHAN_MSG "474 %s %s :Cannot join channel (+b) -- You are banned" +#define ERR_BADCHANNELKEY_MSG "475 %s %s :Cannot join channel (+k) -- Wrong channel key" #define ERR_NOCHANMODES_MSG "477 %s %s :Channel doesn't support modes" +#define ERR_NEEDREGGEDNICK_MSG "477 %s %s :Cannot send to channel (+M) -- You need to be identified to a registered account to message this channel" #define ERR_LISTFULL_MSG "478 %s %s %s: Channel list is full (%d)" #define ERR_NOPRIVILEGES_MSG "481 %s :Permission denied" #define ERR_CHANOPRIVSNEEDED_MSG "482 %s %s :You are not channel operator" +#define ERR_CHANOPPRIVTOOLOW_MSG "482 %s %s :Your privileges are too low" +#define ERR_KICKDENY_MSG "482 %s %s :Cannot kick, %s is protected" #define ERR_CANTKILLSERVER_MSG "483 %s :You can't kill a server!" #define ERR_RESTRICTED_MSG "484 %s :Your connection is restricted" +#define ERR_NICKREGISTER_MSG "484 %s :Cannot modify user mode (+R) -- Use IRC services" +#define ERR_NONONREG_MSG "486 %s :Cannot send to user (+b) -- You must identify to a registered nick to private message %s" #define ERR_NOOPERHOST_MSG "491 %s :Not configured for your host" #define ERR_NOTONSAMECHANNEL_MSG "493 %s :You must share a common channel with %s" #define ERR_UMODEUNKNOWNFLAG_MSG "501 %s :Unknown mode" #define ERR_UMODEUNKNOWNFLAG2_MSG "501 %s :Unknown mode \"%c%c\"" #define ERR_USERSDONTMATCH_MSG "502 %s :Can't set/get mode for other users" +#define ERR_NOINVITE_MSG "518 %s :Cannot invite to %s (+V)" #ifdef ZLIB -#define RPL_STATSLINKINFOZIP_MSG "211 %s %s %d %ld %ld/%ld %ld %ld/%ld :%ld" +# define RPL_STATSLINKINFOZIP_MSG "211 %s %s %d %ld %ld/%ld %ld %ld/%ld :%ld" #endif +#ifdef IRCPLUS + +# define RPL_IP_CHARCONV_MSG "801 %s %s :Client encoding set" + +# define ERR_IP_CHARCONV_MSG "851 %s :Can't initialize client encoding" + +#endif /* IRCPLUS */ + #endif /* -eof- */ diff --git a/src/ngircd/ngircd.c b/src/ngircd/ngircd.c index 8a93bcb..f016b6a 100644 --- a/src/ngircd/ngircd.c +++ b/src/ngircd/ngircd.c @@ -330,6 +330,7 @@ main(int argc, const char *argv[]) Channel_Exit(); Class_Exit(); Log_Exit(); + Signals_Exit(); } Pidfile_Delete(); @@ -346,70 +347,106 @@ main(int argc, const char *argv[]) * line switch. */ static void -Fill_Version( void ) +Fill_Version(void) { NGIRCd_VersionAddition[0] = '\0'; -#ifdef SYSLOG - strlcpy( NGIRCd_VersionAddition, "SYSLOG", sizeof NGIRCd_VersionAddition ); +#ifdef ICONV + if (NGIRCd_VersionAddition[0]) + strlcat(NGIRCd_VersionAddition, "+", + sizeof NGIRCd_VersionAddition); + strlcat(NGIRCd_VersionAddition, "CHARCONV", + sizeof NGIRCd_VersionAddition); #endif -#ifdef ZLIB - if( NGIRCd_VersionAddition[0] ) - strlcat( NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition ); - strlcat( NGIRCd_VersionAddition, "ZLIB", sizeof NGIRCd_VersionAddition ); +#ifdef DEBUG + if (NGIRCd_VersionAddition[0]) + strlcat(NGIRCd_VersionAddition, "+", + sizeof NGIRCd_VersionAddition); + strlcat(NGIRCd_VersionAddition, "DEBUG", + sizeof NGIRCd_VersionAddition); #endif -#ifdef SSL_SUPPORT - if ( NGIRCd_VersionAddition[0] ) strlcat( NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition ); - strlcat( NGIRCd_VersionAddition, "SSL", sizeof NGIRCd_VersionAddition ); +#ifdef IDENTAUTH + if (NGIRCd_VersionAddition[0]) + strlcat(NGIRCd_VersionAddition, "+", + sizeof NGIRCd_VersionAddition); + strlcat(NGIRCd_VersionAddition, "IDENT", + sizeof NGIRCd_VersionAddition); #endif -#ifdef TCPWRAP - if( NGIRCd_VersionAddition[0] ) - strlcat( NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition ); - strlcat( NGIRCd_VersionAddition, "TCPWRAP", sizeof NGIRCd_VersionAddition ); +#ifdef WANT_IPV6 + if (NGIRCd_VersionAddition[0]) + strlcat(NGIRCd_VersionAddition, "+", + sizeof(NGIRCd_VersionAddition)); + strlcat(NGIRCd_VersionAddition, "IPv6", + sizeof(NGIRCd_VersionAddition)); #endif -#ifdef IDENTAUTH - if( NGIRCd_VersionAddition[0] ) - strlcat( NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition ); - strlcat( NGIRCd_VersionAddition, "IDENT", sizeof NGIRCd_VersionAddition ); +#ifdef IRCPLUS + if (NGIRCd_VersionAddition[0]) + strlcat(NGIRCd_VersionAddition, "+", + sizeof NGIRCd_VersionAddition); + strlcat(NGIRCd_VersionAddition, "IRCPLUS", + sizeof NGIRCd_VersionAddition); #endif #ifdef PAM if (NGIRCd_VersionAddition[0]) - strlcat(NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition); - strlcat(NGIRCd_VersionAddition, "PAM", sizeof NGIRCd_VersionAddition); + strlcat(NGIRCd_VersionAddition, "+", + sizeof NGIRCd_VersionAddition); + strlcat(NGIRCd_VersionAddition, "PAM", + sizeof NGIRCd_VersionAddition); #endif -#ifdef DEBUG - if( NGIRCd_VersionAddition[0] ) - strlcat( NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition ); - strlcat( NGIRCd_VersionAddition, "DEBUG", sizeof NGIRCd_VersionAddition ); +#ifdef STRICT_RFC + if (NGIRCd_VersionAddition[0]) + strlcat(NGIRCd_VersionAddition, "+", + sizeof NGIRCd_VersionAddition); + strlcat(NGIRCd_VersionAddition, "RFC", + sizeof NGIRCd_VersionAddition); #endif #ifdef SNIFFER - if( NGIRCd_VersionAddition[0] ) - strlcat( NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition ); - strlcat( NGIRCd_VersionAddition, "SNIFFER", sizeof NGIRCd_VersionAddition ); + if (NGIRCd_VersionAddition[0]) + strlcat(NGIRCd_VersionAddition, "+", + sizeof NGIRCd_VersionAddition); + strlcat(NGIRCd_VersionAddition, "SNIFFER", + sizeof NGIRCd_VersionAddition); #endif -#ifdef STRICT_RFC - if( NGIRCd_VersionAddition[0] ) - strlcat( NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition ); - strlcat( NGIRCd_VersionAddition, "RFC", sizeof NGIRCd_VersionAddition ); +#ifdef SSL_SUPPORT + if (NGIRCd_VersionAddition[0]) + strlcat(NGIRCd_VersionAddition, "+", + sizeof NGIRCd_VersionAddition); + strlcat(NGIRCd_VersionAddition, "SSL", + sizeof NGIRCd_VersionAddition); #endif -#ifdef IRCPLUS - if( NGIRCd_VersionAddition[0] ) - strlcat( NGIRCd_VersionAddition, "+", sizeof NGIRCd_VersionAddition ); - strlcat( NGIRCd_VersionAddition, "IRCPLUS", sizeof NGIRCd_VersionAddition ); +#ifdef SYSLOG + if (NGIRCd_VersionAddition[0]) + strlcat(NGIRCd_VersionAddition, "+", + sizeof NGIRCd_VersionAddition); + strlcat(NGIRCd_VersionAddition, "SYSLOG", + sizeof NGIRCd_VersionAddition); #endif -#ifdef WANT_IPV6 +#ifdef TCPWRAP if (NGIRCd_VersionAddition[0]) - strlcat(NGIRCd_VersionAddition, "+", sizeof(NGIRCd_VersionAddition)); - strlcat(NGIRCd_VersionAddition, "IPv6", sizeof(NGIRCd_VersionAddition)); + strlcat(NGIRCd_VersionAddition, "+", + sizeof NGIRCd_VersionAddition); + strlcat(NGIRCd_VersionAddition, "TCPWRAP", + sizeof NGIRCd_VersionAddition); #endif - if( NGIRCd_VersionAddition[0] ) - strlcat( NGIRCd_VersionAddition, "-", sizeof( NGIRCd_VersionAddition )); - - strlcat( NGIRCd_VersionAddition, TARGET_CPU, sizeof( NGIRCd_VersionAddition )); - strlcat( NGIRCd_VersionAddition, "/", sizeof( NGIRCd_VersionAddition )); - strlcat( NGIRCd_VersionAddition, TARGET_VENDOR, sizeof( NGIRCd_VersionAddition )); - strlcat( NGIRCd_VersionAddition, "/", sizeof( NGIRCd_VersionAddition )); - strlcat( NGIRCd_VersionAddition, TARGET_OS, sizeof( NGIRCd_VersionAddition )); +#ifdef ZLIB + if (NGIRCd_VersionAddition[0]) + strlcat(NGIRCd_VersionAddition, "+", + sizeof NGIRCd_VersionAddition); + strlcat(NGIRCd_VersionAddition, "ZLIB", + sizeof NGIRCd_VersionAddition); +#endif + if (NGIRCd_VersionAddition[0]) + strlcat(NGIRCd_VersionAddition, "-", + sizeof(NGIRCd_VersionAddition)); + + strlcat(NGIRCd_VersionAddition, HOST_CPU, + sizeof(NGIRCd_VersionAddition)); + strlcat(NGIRCd_VersionAddition, "/", sizeof(NGIRCd_VersionAddition)); + strlcat(NGIRCd_VersionAddition, HOST_VENDOR, + sizeof(NGIRCd_VersionAddition)); + strlcat(NGIRCd_VersionAddition, "/", sizeof(NGIRCd_VersionAddition)); + strlcat(NGIRCd_VersionAddition, HOST_OS, + sizeof(NGIRCd_VersionAddition)); snprintf(NGIRCd_Version, sizeof NGIRCd_Version, "%s %s-%s", PACKAGE_NAME, PACKAGE_VERSION, NGIRCd_VersionAddition); @@ -530,6 +567,8 @@ Setup_FDStreams(int fd) } /* Setup_FDStreams */ +#if !defined(SINGLE_USER_OS) + /** * Get user and group ID of unprivileged "nobody" user. * @@ -569,6 +608,8 @@ NGIRCd_getNobodyID(uid_t *uid, gid_t *gid ) return true; } /* NGIRCd_getNobodyID */ +#endif + static bool Random_Init_Kern(const char *file) @@ -632,7 +673,7 @@ NGIRCd_Init(bool NGIRCd_NoDaemon) /* SSL initialization */ if (!ConnSSL_InitLibrary()) Log(LOG_WARNING, - "Warning: Error during SSL initialization, continuing ..."); + "Error during SSL initialization, continuing without SSL ..."); /* Change root */ if (Conf_Chroot[0]) { @@ -655,6 +696,7 @@ NGIRCd_Init(bool NGIRCd_NoDaemon) } } +#if !defined(SINGLE_USER_OS) /* Check user ID */ if (Conf_UID == 0) { pwd = getpwuid(0); @@ -681,6 +723,7 @@ NGIRCd_Init(bool NGIRCd_NoDaemon) goto out; } } +#endif /* Change user ID */ if (getuid() != Conf_UID) { @@ -715,7 +758,7 @@ NGIRCd_Init(bool NGIRCd_NoDaemon) } /* New child process */ -#ifndef NeXT +#ifdef HAVE_SETSID (void)setsid(); #else setpgrp(0, getpid()); diff --git a/src/ngircd/numeric.c b/src/ngircd/numeric.c index d59a1dc..9b8240b 100644 --- a/src/ngircd/numeric.c +++ b/src/ngircd/numeric.c @@ -48,12 +48,11 @@ Announce_Channel(CLIENT *Client, CHANNEL *Chan) CL2CHAN *cl2chan; CLIENT *cl; char str[LINE_LEN], *ptr; - bool njoin; + bool njoin, xop; - if (Conn_Options(Client_Conn(Client)) & CONN_RFC1459) - njoin = false; - else - njoin = true; + /* Check features of remote server */ + njoin = Conn_Options(Client_Conn(Client)) & CONN_RFC1459 ? false : true; + xop = strchr(Client_Flags(Client), 'X') ? true : false; /* Get all the members of this channel */ cl2chan = Channel_FirstMember(Chan); @@ -63,14 +62,23 @@ Announce_Channel(CLIENT *Client, CHANNEL *Chan) assert(cl != NULL); if (njoin) { - /* RFC 2813: send NJOIN with nick names and modes + /* RFC 2813: send NJOIN with nicknames and modes * (if user is channel operator or has voice) */ if (str[strlen(str) - 1] != ':') strlcat(str, ",", sizeof(str)); - if (strchr(Channel_UserModes(Chan, cl), 'v')) - strlcat(str, "+", sizeof(str)); + + /* Prepare user prefix (ChanOp, voiced, ...) */ + if (xop && strchr(Channel_UserModes(Chan, cl), 'q')) + strlcat(str, "~", sizeof(str)); + if (xop && strchr(Channel_UserModes(Chan, cl), 'a')) + strlcat(str, "&", sizeof(str)); if (strchr(Channel_UserModes(Chan, cl), 'o')) strlcat(str, "@", sizeof(str)); + if (xop && strchr(Channel_UserModes(Chan, cl), 'h')) + strlcat(str, "%", sizeof(str)); + if (strchr(Channel_UserModes(Chan, cl), 'v')) + strlcat(str, "+", sizeof(str)); + strlcat(str, Client_ID(cl), sizeof(str)); /* Send the data if the buffer is "full" */ @@ -171,24 +179,40 @@ Announce_User(CLIENT * Client, CLIENT * User) Client_ID(User), Client_ID(User), modes); } - return CONNECTED; } else { /* RFC 2813 mode: one combined NICK or SERVICE command */ if (Client_Type(User) == CLIENT_SERVICE - && strchr(Client_Flags(Client), 'S')) - return IRC_WriteStrClient(Client, - "SERVICE %s %d * +%s %d :%s", Client_Mask(User), - Client_MyToken(Client_Introducer(User)), - Client_Modes(User), Client_Hops(User) + 1, - Client_Info(User)); - else - return IRC_WriteStrClient(Client, - "NICK %s %d %s %s %d +%s :%s", - Client_ID(User), Client_Hops(User) + 1, - Client_User(User), Client_Hostname(User), - Client_MyToken(Client_Introducer(User)), - Client_Modes(User), Client_Info(User)); + && strchr(Client_Flags(Client), 'S')) { + if (!IRC_WriteStrClient(Client, + "SERVICE %s %d * +%s %d :%s", + Client_Mask(User), + Client_MyToken(Client_Introducer(User)), + Client_Modes(User), Client_Hops(User) + 1, + Client_Info(User))) + return DISCONNECTED; + } else { + if (!IRC_WriteStrClient(Client, + "NICK %s %d %s %s %d +%s :%s", + Client_ID(User), Client_Hops(User) + 1, + Client_User(User), Client_Hostname(User), + Client_MyToken(Client_Introducer(User)), + Client_Modes(User), Client_Info(User))) + return DISCONNECTED; + } } + + if (strchr(Client_Flags(Client), 'M')) { + /* Synchronize metadata */ + if (Client_HostnameCloaked(User)) { + if (!IRC_WriteStrClient(Client, + "METADATA %s cloakhost :%s", + Client_ID(User), + Client_HostnameCloaked(User))) + return DISCONNECTED; + } + } + + return CONNECTED; } /* Announce_User */ @@ -413,12 +437,12 @@ IRC_Num_ISUPPORT(CLIENT * Client, REQUEST * Req) if ((unsigned int)atol(value) == Conf_MaxNickLength - 1) continue; - /* Nick name length settings are different! */ + /* Nickname length settings are different! */ Log(LOG_ERR, - "Peer uses incompatible nick name length (%d/%d)! Disconnecting ...", + "Peer uses incompatible nickname length (%d/%d)! Disconnecting ...", Conf_MaxNickLength - 1, atoi(value)); Conn_Close(Client_Conn(Client), - "Incompatible nick name length", + "Incompatible nickname length", NULL, false); return DISCONNECTED; } diff --git a/src/ngircd/pam.c b/src/ngircd/pam.c index 6382c59..88872c4 100644 --- a/src/ngircd/pam.c +++ b/src/ngircd/pam.c @@ -102,8 +102,8 @@ PAM_Authenticate(CLIENT *Client) { /* Set supplied client password */ if (password) free(password); - password = strdup(Client_Password(Client)); - conv.appdata_ptr = Client_Password(Client); + password = strdup(Conn_Password(Client_Conn(Client))); + conv.appdata_ptr = Conn_Password(Client_Conn(Client)); /* Initialize PAM */ retval = pam_start("ngircd", Client_OrigUser(Client), &conv, &pam); diff --git a/src/ngircd/parse.c b/src/ngircd/parse.c index 66bfef5..5ff9fcc 100644 --- a/src/ngircd/parse.c +++ b/src/ngircd/parse.c @@ -38,8 +38,10 @@ #include "irc.h" #include "irc-cap.h" #include "irc-channel.h" +#include "irc-encoding.h" #include "irc-info.h" #include "irc-login.h" +#include "irc-metadata.h" #include "irc-mode.h" #include "irc-op.h" #include "irc-oper.h" @@ -60,6 +62,7 @@ static COMMAND My_Commands[] = { { "ADMIN", IRC_ADMIN, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, { "AWAY", IRC_AWAY, CLIENT_USER, 0, 0, 0 }, + { "CAP", IRC_CAP, 0xFFFF, 0, 0, 0 }, { "CONNECT", IRC_CONNECT, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, { "DIE", IRC_DIE, CLIENT_USER, 0, 0, 0 }, { "DISCONNECT", IRC_DISCONNECT, CLIENT_USER, 0, 0, 0 }, @@ -76,6 +79,7 @@ static COMMAND My_Commands[] = { "LINKS", IRC_LINKS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, { "LIST", IRC_LIST, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, { "LUSERS", IRC_LUSERS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "METADATA", IRC_METADATA, CLIENT_SERVER, 0, 0, 0 }, { "MODE", IRC_MODE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, { "MOTD", IRC_MOTD, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, { "NAMES", IRC_NAMES, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, @@ -97,6 +101,7 @@ static COMMAND My_Commands[] = { "SQUERY", IRC_SQUERY, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, { "SQUIT", IRC_SQUIT, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, { "STATS", IRC_STATS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "SVSNICK", IRC_SVSNICK, 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 }, @@ -110,11 +115,15 @@ static COMMAND My_Commands[] = { "WHO", IRC_WHO, CLIENT_USER, 0, 0, 0 }, { "WHOIS", IRC_WHOIS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, { "WHOWAS", IRC_WHOWAS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + #ifdef IRCPLUS { "CHANINFO", IRC_CHANINFO, CLIENT_SERVER, 0, 0, 0 }, +# ifdef ICONV + { "CHARCONV", IRC_CHARCONV, CLIENT_USER, 0, 0, 0 }, +# endif #endif + #ifndef STRICT_RFC - { "CAP", IRC_CAP, 0xFFFF, 0, 0, 0 }, { "GET", IRC_QUIT_HTTP, CLIENT_UNKNOWN, 0, 0, 0 }, { "POST", IRC_QUIT_HTTP, CLIENT_UNKNOWN, 0, 0, 0 }, #endif diff --git a/src/ngircd/sighandlers.c b/src/ngircd/sighandlers.c index efb41bc..8f0a5a1 100644 --- a/src/ngircd/sighandlers.c +++ b/src/ngircd/sighandlers.c @@ -102,7 +102,7 @@ Rehash(void) Log( LOG_NOTICE|LOG_snotice, "Re-reading configuration NOW!" ); - /* Remember old server name and nick name length */ + /* Remember old server name and nickname length */ strlcpy( old_name, Conf_ServerName, sizeof old_name ); old_nicklen = Conf_MaxNickLength; @@ -113,7 +113,7 @@ Rehash(void) /* Close down all listening sockets */ Conn_ExitListeners( ); - /* Recover old server name and nick name length: these values can't + /* Recover old server name and nickname length: these values can't * be changed during run-time */ if (strcmp(old_name, Conf_ServerName) != 0 ) { strlcpy(Conf_ServerName, old_name, sizeof Conf_ServerName); @@ -334,6 +334,7 @@ Signals_Exit(void) #endif close(signalpipe[1]); close(signalpipe[0]); + signalpipe[0] = signalpipe[1] = 0; } /* -eof- */ diff --git a/src/portab/.gitignore b/src/portab/.gitignore index 839a69f..9bac6ac 100644 --- a/src/portab/.gitignore +++ b/src/portab/.gitignore @@ -1 +1,2 @@ +Makefile.am portabtest diff --git a/src/portab/Makefile.am b/src/portab/Makefile.am deleted file mode 100644 index a57ea49..0000000 --- a/src/portab/Makefile.am +++ /dev/null @@ -1,34 +0,0 @@ -# -# ngIRCd -- The Next Generation IRC Daemon -# Copyright (c)2001,2002 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 -# herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 -# der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. -# Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste -# der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. -# - -AUTOMAKE_OPTIONS = ansi2knr - -noinst_LIBRARIES = libngportab.a - -libngportab_a_SOURCES = strdup.c strlcpy.c strtok_r.c vsnprintf.c waitpid.c - -check_PROGRAMS = portabtest - -portabtest_SOURCES = portabtest.c - -portabtest_LDFLAGS = -L. - -portabtest_LDADD = -lngportab - -noinst_HEADERS = imp.h exp.h portab.h splint.h - -maintainer-clean-local: - rm -f Makefile Makefile.in - -TESTS = portabtest - -# -eof- diff --git a/src/portab/Makefile.ng b/src/portab/Makefile.ng new file mode 100644 index 0000000..dac329f --- /dev/null +++ b/src/portab/Makefile.ng @@ -0,0 +1,35 @@ +# +# ngIRCd -- The Next Generation IRC Daemon +# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors +# +# 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. +# + +__ng_Makefile_am_template__ + +EXTRA_DIST = Makefile.ng + +noinst_LIBRARIES = libngportab.a + +libngportab_a_SOURCES = strdup.c strlcpy.c strtok_r.c vsnprintf.c waitpid.c + +check_PROGRAMS = portabtest + +portabtest_SOURCES = portabtest.c + +portabtest_LDFLAGS = -L. + +portabtest_LDADD = -lngportab + +noinst_HEADERS = imp.h exp.h portab.h splint.h + +maintainer-clean-local: + rm -f Makefile Makefile.in Makefile.am + +TESTS = portabtest + +# -eof- diff --git a/src/portab/portab.h b/src/portab/portab.h index 90f36a0..208d350 100644 --- a/src/portab/portab.h +++ b/src/portab/portab.h @@ -1,6 +1,6 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001-2010 Alexander Barton (alex@barton.de) + * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors. * * 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 @@ -112,7 +112,6 @@ typedef unsigned char bool; /* SPLint */ - #ifdef S_SPLINT_S #include "splint.h" #endif @@ -120,18 +119,21 @@ typedef unsigned char bool; /* target constants */ -#ifndef TARGET_OS -#define TARGET_OS "unknown" +#ifndef HOST_OS +#define HOST_OS "unknown" #endif -#ifndef TARGET_CPU -#define TARGET_CPU "unknown" +#ifndef HOST_CPU +#define HOST_CPU "unknown" #endif -#ifndef TARGET_VENDOR -#define TARGET_VENDOR "unknown" +#ifndef HOST_VENDOR +#define HOST_VENDOR "unknown" #endif +#ifdef __HAIKU__ +#define SINGLE_USER_OS +#endif /* configure options */ diff --git a/src/testsuite/.gitignore b/src/testsuite/.gitignore index 5884a48..b33a08f 100644 --- a/src/testsuite/.gitignore +++ b/src/testsuite/.gitignore @@ -1,3 +1,4 @@ +Makefile.am T-ngircd1 T-ngircd2 channel-test diff --git a/src/testsuite/Makefile.am b/src/testsuite/Makefile.am deleted file mode 100644 index 9dc76a7..0000000 --- a/src/testsuite/Makefile.am +++ /dev/null @@ -1,110 +0,0 @@ -# -# ngIRCd -- The Next Generation IRC Daemon -# Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors. -# -# Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen -# der GNU General Public License (GPL), wie von der Free Software Foundation -# herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 -# der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. -# Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste -# der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. -# - -AUTOMAKE_OPTIONS = ../portab/ansi2knr - -INCLUDES = -I$(srcdir)/../portab - -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 invite-test.e \ - join-test.e kick-test.e message-test.e misc-test.e mode-test.e \ - opless-channel-test.e server-link-test.e who-test.e whois-test.e \ - stress-A.e stress-B.e \ - start-server1 stop-server1 ngircd-test1.conf \ - start-server2 stop-server2 ngircd-test2.conf - -all: - -clean-local: - rm -rf logs tests *-test ngircd-test*.log procs.tmp \ - T-ngircd1 ngircd-test1.motd T-ngircd2 ngircd-test2.motd - -maintainer-clean-local: - rm -f Makefile Makefile.in - -check_SCRIPTS = ngircd-TEST-Binary tests.sh - -ngircd-TEST-Binary: - cp ../ngircd/ngircd T-ngircd1 - cp ../ngircd/ngircd T-ngircd2 - [ -f getpid.sh ] || ln -s $(srcdir)/getpid.sh . - -connect-test: tests.sh - rm -f connect-test - ln -s $(srcdir)/tests.sh connect-test - -channel-test: tests.sh - rm -f channel-test - ln -s $(srcdir)/tests.sh channel-test - -invite-test: tests.sh - rm -f invite-test - ln -s $(srcdir)/tests.sh invite-test - -join-test: tests.sh - rm -f join-test - ln -s $(srcdir)/tests.sh join-test - -kick-test: tests.sh - rm -f kick-test - ln -s $(srcdir)/tests.sh kick-test - -message-test: tests.sh - rm -f message-test - ln -s $(srcdir)/tests.sh message-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 - -opless-channel-test: tests.sh - rm -f opless-channel-test - ln -s $(srcdir)/tests.sh opless-channel-test - -server-link-test: tests.sh - rm -f server-link-test - ln -s $(srcdir)/tests.sh server-link-test - -who-test: tests.sh - rm -f who-test - ln -s $(srcdir)/tests.sh who-test - -whois-test: tests.sh - rm -f whois-test - ln -s $(srcdir)/tests.sh whois-test - -TESTS = start-server1 \ - connect-test \ - start-server2 \ - channel-test \ - invite-test \ - join-test \ - kick-test \ - message-test \ - misc-test \ - mode-test \ - opless-channel-test \ - who-test \ - whois-test \ - server-link-test \ - stop-server2 \ - stress-server.sh \ - stop-server1 - -# -eof- diff --git a/src/testsuite/Makefile.ng b/src/testsuite/Makefile.ng new file mode 100644 index 0000000..b906091 --- /dev/null +++ b/src/testsuite/Makefile.ng @@ -0,0 +1,109 @@ +# +# ngIRCd -- The Next Generation IRC Daemon +# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors +# +# 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. +# + +__ng_Makefile_am_template__ + +AM_CPPFLAGS = -I$(srcdir)/../portab + +EXTRA_DIST = \ + Makefile.ng 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 invite-test.e \ + join-test.e kick-test.e message-test.e misc-test.e mode-test.e \ + opless-channel-test.e server-link-test.e who-test.e whois-test.e \ + stress-A.e stress-B.e \ + start-server1 stop-server1 ngircd-test1.conf \ + start-server2 stop-server2 ngircd-test2.conf + +all: + +clean-local: + rm -rf logs tests *-test ngircd-test*.log procs.tmp \ + T-ngircd1 ngircd-test1.motd T-ngircd2 ngircd-test2.motd + +maintainer-clean-local: + rm -f Makefile Makefile.in Makefile.am + +check_SCRIPTS = ngircd-TEST-Binary tests.sh + +ngircd-TEST-Binary: + cp ../ngircd/ngircd T-ngircd1 + cp ../ngircd/ngircd T-ngircd2 + [ -f getpid.sh ] || ln -s $(srcdir)/getpid.sh . + +connect-test: tests.sh + rm -f connect-test + ln -s $(srcdir)/tests.sh connect-test + +channel-test: tests.sh + rm -f channel-test + ln -s $(srcdir)/tests.sh channel-test + +invite-test: tests.sh + rm -f invite-test + ln -s $(srcdir)/tests.sh invite-test + +join-test: tests.sh + rm -f join-test + ln -s $(srcdir)/tests.sh join-test + +kick-test: tests.sh + rm -f kick-test + ln -s $(srcdir)/tests.sh kick-test + +message-test: tests.sh + rm -f message-test + ln -s $(srcdir)/tests.sh message-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 + +opless-channel-test: tests.sh + rm -f opless-channel-test + ln -s $(srcdir)/tests.sh opless-channel-test + +server-link-test: tests.sh + rm -f server-link-test + ln -s $(srcdir)/tests.sh server-link-test + +who-test: tests.sh + rm -f who-test + ln -s $(srcdir)/tests.sh who-test + +whois-test: tests.sh + rm -f whois-test + ln -s $(srcdir)/tests.sh whois-test + +TESTS = start-server1 \ + connect-test \ + start-server2 \ + channel-test \ + invite-test \ + join-test \ + kick-test \ + message-test \ + misc-test \ + mode-test \ + opless-channel-test \ + who-test \ + whois-test \ + server-link-test \ + stop-server2 \ + stress-server.sh \ + stop-server1 + +# -eof- diff --git a/src/testsuite/getpid.sh b/src/testsuite/getpid.sh index 19ced76..96ab474 100755 --- a/src/testsuite/getpid.sh +++ b/src/testsuite/getpid.sh @@ -10,7 +10,7 @@ UNAME=`uname` if [ $UNAME = "FreeBSD" ]; then PS_FLAGS="-a"; PS_PIDCOL="1"; HEAD_FLAGS="-n 1" elif [ $UNAME = "A/UX" ]; then - PS_FLAGS="-ae"; PS_PIDCOL="1"; HEAD_FLAGS="-1" + PS_FLAGS="-af"; PS_PIDCOL="2"; HEAD_FLAGS="-1" elif [ $UNAME = "GNU" ]; then PS_FLAGS="-ax"; PS_PIDCOL="2"; HEAD_FLAGS="-n 1" elif [ $UNAME = "Linux" ]; then diff --git a/src/testsuite/message-test.e b/src/testsuite/message-test.e index d0ffcef..6e63bb5 100644 --- a/src/testsuite/message-test.e +++ b/src/testsuite/message-test.e @@ -53,6 +53,22 @@ expect { "@* PRIVMSG nick :test" } +send "mode nick +b\r" +expect { + timeout { exit 1 } + "MODE nick :+b" +} +send "privmsg nick :test\r" +expect { + timeout { exit 1 } + "486" +} +send "mode nick -b\r" +expect { + timeout { exit 1 } + "MODE nick :-b" +} + # The following two tests using "localhost" as host name # had to be disabled, because there are operating systems # out there, that use "localhost." as host name diff --git a/src/testsuite/mode-test.e b/src/testsuite/mode-test.e index 260cd03..44b6e5d 100644 --- a/src/testsuite/mode-test.e +++ b/src/testsuite/mode-test.e @@ -31,6 +31,46 @@ expect { "@* MODE nick :-i" } +send "join #usermode\r" +expect { + timeout { exit 1 } + "@* JOIN :#usermode" +} +expect { + timeout { exit 1 } + "366" +} + +send "mode #usermode +v nick\r" +expect { + timeout { exit 1 } + "@* MODE #usermode +v nick\r" +} + +send "mode #usermode +h nick\r" +expect { + timeout { exit 1 } + "@* MODE #usermode +h nick\r" +} + +send "mode #usermode +a nick\r" +expect { + timeout { exit 1 } + "482 nick" +} + +send "mode #usermode +q nick\r" +expect { + timeout { exit 1 } + "482 nick" +} + +send "mode #usermode -vho nick nick nick\r" +expect { + timeout { exit 1 } + "@* MODE #usermode -vho nick nick nick" +} + send "oper TestOp 123\r" expect { timeout { exit 1 } @@ -47,6 +87,34 @@ expect { "221 nick +o" } +send "mode #usermode +a nick\r" +expect { + timeout { exit 1 } + "@* MODE #usermode +a nick" +} + +send "mode #usermode +q nick\r" +expect { + timeout { exit 1 } + "@* MODE #usermode +q nick" +} + +send "names #usermode\r" +expect { + timeout { exit 1 } + "353 nick = #usermode :~nick" +} +expect { + timeout { exit 1 } + "366 nick #usermode" +} + +send "part #usermode\r" +expect { + timeout { exit 1 } + "@* PART #usermode" +} + send "join #channel\r" expect { timeout { exit 1 } diff --git a/src/testsuite/start-server.sh b/src/testsuite/start-server.sh index 90832a3..0fd61ea 100755 --- a/src/testsuite/start-server.sh +++ b/src/testsuite/start-server.sh @@ -12,7 +12,7 @@ else id="1" fi -echo_n " starting server ${id} ..." +echo_n "starting server ${id} ..." # remove old logfiles, if this is the first server (ID 1) [ "$id" = "1" ] && rm -rf logs *.log diff --git a/src/testsuite/stop-server.sh b/src/testsuite/stop-server.sh index 7e6ee4f..c531137 100755 --- a/src/testsuite/stop-server.sh +++ b/src/testsuite/stop-server.sh @@ -12,7 +12,7 @@ else id="1" fi -echo_n " stopping server ${id} ..." +echo_n "stopping server ${id} ..." # stop test-server ... pid=`./getpid.sh T-ngircd${id}` diff --git a/src/testsuite/stress-server.sh b/src/testsuite/stress-server.sh index 0f85958..1e82325 100755 --- a/src/testsuite/stress-server.sh +++ b/src/testsuite/stress-server.sh @@ -1,7 +1,7 @@ #!/bin/sh # # ngIRCd Test Suite -# Copyright (c)2002-2004 by Alexander Barton (alex@barton.de) +# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors. # # 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,6 @@ # (at your option) any later version. # Please read the file COPYING, README and AUTHORS for more information. # -# $Id: stress-server.sh,v 1.16 2005/12/30 22:13:21 alex Exp $ -# # detect source directory [ -z "$srcdir" ] && srcdir=`dirname $0` @@ -23,20 +21,21 @@ name=`basename $0` # create directories -mkdir -p logs tests +[ -d logs ] || mkdir logs +[ -d tests ] || mkdir tests # test for required external tools type expect > /dev/null 2>&1 if [ $? -ne 0 ]; then - echo " ${name}: \"expect\" not found."; exit 77 + echo "${name}: \"expect\" not found."; exit 77 fi type telnet > /dev/null 2>&1 if [ $? -ne 0 ]; then - echo " ${name}: \"telnet\" not found."; exit 77 + echo "${name}: \"telnet\" not found."; exit 77 fi # hello world! :-) -echo " stressing server with $CLIENTS clients (be patient!):" +echo "stressing server with $CLIENTS clients (be patient!):" # read in functions . ${srcdir}/functions.inc @@ -51,7 +50,7 @@ while [ ${no} -lt $CLIENTS ]; do done # run first script and check if it succeeds -echo_n " checking stress script ..." +echo_n "checking stress script ..." expect tests/0.e > logs/stress-0.log 2> /dev/null if [ $? -ne 0 ]; then echo " failure!" @@ -65,12 +64,12 @@ while [ ${no} -lt $CLIENTS ]; do expect tests/${no}.e > logs/stress-${no}.log 2> /dev/null & no=`expr ${no} + 1` - echo " started client $no/$CLIENTS." + echo "started client $no/$CLIENTS." [ $MAX -gt 0 ] && $srcdir/wait-tests.sh $MAX done -echo_n " waiting for clients to complete: ." +echo_n "waiting for clients to complete: ." touch logs/check-idle.log while true; do expect ${srcdir}/check-idle.e >> logs/check-idle.log; res=$? diff --git a/src/testsuite/tests.sh b/src/testsuite/tests.sh index 2bd9ae4..1989205 100755 --- a/src/testsuite/tests.sh +++ b/src/testsuite/tests.sh @@ -1,16 +1,24 @@ #!/bin/sh +# # ngIRCd Test Suite -# $Id: tests.sh,v 1.7 2004/09/06 22:04:06 alex Exp $ +# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors. +# +# 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. +# # detect source directory [ -z "$srcdir" ] && srcdir=`dirname $0` name=`basename $0` test=`echo ${name} | cut -d '.' -f 1` -mkdir -p logs +[ -d logs ] || mkdir logs if [ ! -r "$test" ]; then - echo " ${name}: test \"$test\" not found!"; exit 77 + echo "${name}: test \"$test\" not found!"; exit 77 exit 1 fi @@ -19,17 +27,28 @@ fi type expect > /dev/null 2>&1 if [ $? -ne 0 ]; then - echo " ${name}: \"expect\" not found."; exit 77 + echo "${name}: \"expect\" not found."; exit 77 fi type telnet > /dev/null 2>&1 if [ $? -ne 0 ]; then - echo " ${name}: \"telnet\" not found."; exit 77 + echo "${name}: \"telnet\" not found."; exit 77 fi -echo_n " running ${test} ..." -expect ${srcdir}/${test}.e > logs/${test}.log 2>&1; r=$? +# prepare expect script +e_in="${srcdir}/${test}.e" +e_tmp="${test}.e_" +e_exec="$e_in" +if test -t 1 2>/dev/null; then + sed -e 's|^expect |puts -nonewline stderr "."; expect |g' \ + "$e_in" >"$e_tmp" + [ $? -eq 0 ] && e_exec="$e_tmp" +fi + +echo_n "running ${test} ..." +expect "$e_exec" > logs/${test}.log; r=$? [ $r -eq 0 ] && echo " ok." || echo " failure!" +rm -f "$e_tmp" exit $r # -eof- diff --git a/src/testsuite/whois-test.e b/src/testsuite/whois-test.e index 2aed694..fdb21bc 100644 --- a/src/testsuite/whois-test.e +++ b/src/testsuite/whois-test.e @@ -19,6 +19,10 @@ expect { timeout { exit 1 } "311 nick nick ~user localhost* \* :Real Name\r" } +expect { + timeout { exit 1 } + "318 nick nick :" +} send "whois *\r" expect { @@ -44,6 +48,28 @@ expect { "311 nick nick ~user localhost* \* :Real Name\r" } +send "whois unknown\r" +expect { + timeout { exit 1 } + "401 nick unknown :" +} +expect { + timeout { exit 1 } + "318 nick unknown :" +} + +send "whois ngircd.test.server2 nick\r" +expect { + timeout { exit 1 } + ":ngircd.test.server2 311 nick nick ~user localhost* \* :Real Name\r" +} + +send "whois nosuchserver unknown\r" +expect { + timeout { exit 1 } + "402 nick nosuchserver :" +} + send "quit\r" expect { timeout { exit 1 } diff --git a/src/tool/.gitignore b/src/tool/.gitignore new file mode 100644 index 0000000..08a6d72 --- /dev/null +++ b/src/tool/.gitignore @@ -0,0 +1 @@ +Makefile.am diff --git a/src/tool/Makefile.am b/src/tool/Makefile.am deleted file mode 100644 index 5f1e97a..0000000 --- a/src/tool/Makefile.am +++ /dev/null @@ -1,27 +0,0 @@ -# -# ngIRCd -- The Next Generation IRC Daemon -# 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 -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# Please read the file COPYING, README and AUTHORS for more information. -# -# $Id: Makefile.am,v 1.1 2003/01/13 12:20:16 alex Exp $ -# - -AUTOMAKE_OPTIONS = ansi2knr - -INCLUDES = -I$(srcdir)/../portab - -noinst_LIBRARIES = libngtool.a - -libngtool_a_SOURCES = tool.c - -noinst_HEADERS = tool.h - -maintainer-clean-local: - rm -f Makefile Makefile.in - -# -eof- diff --git a/src/tool/Makefile.ng b/src/tool/Makefile.ng new file mode 100644 index 0000000..d88bdc9 --- /dev/null +++ b/src/tool/Makefile.ng @@ -0,0 +1,27 @@ +# +# ngIRCd -- The Next Generation IRC Daemon +# Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors +# +# 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. +# + +__ng_Makefile_am_template__ + +EXTRA_DIST = Makefile.ng + +AM_CPPFLAGS = -I$(srcdir)/../portab + +noinst_LIBRARIES = libngtool.a + +libngtool_a_SOURCES = tool.c + +noinst_HEADERS = tool.h + +maintainer-clean-local: + rm -f Makefile Makefile.in Makefile.am + +# -eof- diff --git a/src/tool/tool.c b/src/tool/tool.c index ef3fb5d..1bb3ebe 100644 --- a/src/tool/tool.c +++ b/src/tool/tool.c @@ -20,7 +20,9 @@ #include #include #include +#include #include +#include #include @@ -82,7 +84,7 @@ ngt_UpperStr(char *String) ptr = String; while(*ptr) { - *ptr = toupper(*ptr); + *ptr = toupper((int)*ptr); ptr++; } return String; @@ -101,7 +103,7 @@ ngt_LowerStr(char *String) ptr = String; while(*ptr) { - *ptr = tolower(*ptr); + *ptr = tolower((int)*ptr); ptr++; } return String; @@ -129,6 +131,30 @@ ngt_TrimLastChr( char *String, const char Chr) } /* ngt_TrimLastChr */ +/** + * Fill a String with random chars + */ +GLOBAL char * +ngt_RandomStr(char *String, const size_t len) +{ + static const char chars[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!\"#$&'()*+,-./:;<=>?@[\\]^_`"; + struct timeval t; + size_t i; + + assert(String != NULL); + + gettimeofday(&t, NULL); + srand((unsigned)(t.tv_usec * t.tv_sec)); + + for (i = 0; i < len; ++i) { + String[i] = chars[rand() % (sizeof(chars) - 1)]; + } + String[len] = '\0'; + + return String; +} /* ngt_RandomStr */ + + #ifdef SYSLOG diff --git a/src/tool/tool.h b/src/tool/tool.h index 60a6537..b05649a 100644 --- a/src/tool/tool.h +++ b/src/tool/tool.h @@ -19,12 +19,6 @@ #include "portab.h" -#ifdef HAVE_ARPA_INET_H -# include -#else -# define PF_INET AF_INET -#endif - GLOBAL void ngt_TrimLastChr PARAMS((char *String, const char Chr )); GLOBAL void ngt_TrimStr PARAMS((char *String )); @@ -32,6 +26,8 @@ GLOBAL void ngt_TrimStr PARAMS((char *String )); GLOBAL char *ngt_UpperStr PARAMS((char *String )); GLOBAL char *ngt_LowerStr PARAMS((char *String )); +GLOBAL char *ngt_RandomStr PARAMS((char *String, const size_t len)); + #ifdef SYSLOG GLOBAL const char *ngt_SyslogFacilityName PARAMS((int Facility)); GLOBAL int ngt_SyslogFacilityID PARAMS((char *Name, int DefaultFacility));