1
0
mirror of https://github.com/osmarks/ngircd.git synced 2025-09-25 13:34:05 +00:00

Compare commits

...

236 Commits

Author SHA1 Message Date
Alexander Barton
b9e6cb3e55 ngIRCd release 19.2 2012-06-19 11:47:15 +02:00
Alexander Barton
dffe5a9d60 doc/Capabilities.txt: document "multi-prefix" capability 2012-06-13 12:19:56 +02:00
Alexander Barton
d7eb343ea0 ngIRCd release 19.2~rc1 2012-06-13 11:40:24 +02:00
Alexander Barton
bf5610a3b9 Merge branch 'bug124-CloakHostModeX'
* bug124-CloakHostModeX:
  Describe "CloakHostModeX" in sample-ngircd.conf an ngircd.conf(5)
  Rename "CloakModeHost" option to "CloakHostModeX"
  Introduce new configuration option "CloakModeHost"

This closes bug #124.
2012-06-11 10:44:28 +02:00
Alexander Barton
7bce6780ca Update ChangeLog and NEWS files 2012-06-09 12:53:44 +02:00
Alexander Barton
bf121ae95f Describe "CloakHostModeX" in sample-ngircd.conf an ngircd.conf(5) 2012-06-09 02:04:50 +02:00
Alexander Barton
7b6b492bdd Rename "CloakModeHost" option to "CloakHostModeX" 2012-06-09 01:58:40 +02:00
Christoph Biedl
aa7db2c0e9 Introduce new configuration option "CloakModeHost"
This closes bug #124.
2012-06-09 01:58:25 +02:00
Alexander Barton
684e50f0a4 Correctly handle asynchronously re-established server links
Don't try to establish an outgoing server link after DNS lookup when this
server re-connected on its own in the meantime.
In addition, log a warning message if we try to update the connection
index of an already connected server structure -- and ignore it.

Up to now, both behaviour could lead to a race when the remote server
connects to this daemon while it still prepares the outgoing connection:

 - The local server prepares the new outgoing connection ...
 - in the meantime the remote server becomes connected and registered.
 - Now the new outgoing connection overwrites the (correct) socket handle,
 - then the 2nd connection becomes disconnected: "already registered",
 - and the 1st connection becomes unhandled ("gets lost") because the
   configuration structure is reset because of the wrong socket handle.

This patch hopefully fixes all these problems.
2012-06-09 01:03:48 +02:00
Alexander Barton
4a90959cb5 Log a debug message when SIGUSR2 is handled 2012-06-08 22:08:52 +02:00
Alexander Barton
9b1cf420f1 doc/Platforms.txt: more updates
Added:
 - armv6l/unkn./linux-gnueabi, gcc 4.4.5
 - i686/pc/linux-gnu, gcc 2.7.2

Updated:
 - i386/pc/solaris2.11, gcc 4.2.3

Thanks to Götz Hoffart!
2012-06-07 17:09:45 +02:00
Alexander Barton
e7e47e77a3 NoticeAuth: Fix test if IDENT reply has been invalid
This fixes

 conn.c: In function ‘cb_Read_Resolver_Result’:
 conn.c:2252: warning: comparison between pointer and integer
2012-06-02 00:32:19 +02:00
Alexander Barton
695df6532e IDENT reply: only allow alphanumeric characters in user name
Only alphanumeric characters are allowed in the user name, so ignore
all IDENT replies that would violate this rule and use the one supplied
by the USER command.
2012-06-02 00:24:53 +02:00
Alexander Barton
6680b536c4 USER command: only allow alphanumeric characters in user name
Only alphanumeric characters are allowed in the user name, so terminate
the connection if any "strage" characters have been supplied by the user.

This is how other IRC daemons (like ircd2.11 and ircd-seven) behave ...
2012-06-01 23:57:51 +02:00
Alexander Barton
a21a7d8b66 doc/Platforms.txt: add powerpc/apple/darwin7.9.0 2012-05-29 17:21:03 +02:00
Alexander Barton
c0d059cd0e Change wording of "TLS initialized" message
Don't use the word "socket" to identify the connection number, but use the
word "connection" like on all the other messages logged.
2012-05-23 17:12:31 +02:00
Alexander Barton
7faa3ed7d6 Pidfile_Create(): Don't leak file descriptor on error path
Detected by cppcheck:
 [src/ngircd/ngircd.c:502]: (error) Resource leak: pidfd
2012-05-22 13:31:08 +02:00
Alexander Barton
c9b152fa41 INSTALL: Add "satisfy prerequisites" section
Include information for RedHat/Fedora and Debian/Ubuntu based
Linux distributions.
2012-05-19 00:45:23 +02:00
Alexander Barton
ae27571414 NEWS, ChangeLog: fixed some misspellings 2012-05-07 22:38:26 +02:00
Alexander Barton
5e5377a063 Numeric 005 (ISUPPORT), CHANMODES: add missing mode "r" 2012-05-01 13:42:57 +02:00
Alexander Barton
884c5bcff1 doc/Platforms.txt: add "armv7l/unknown/linux-gnueabi" 2012-04-29 22:45:46 +02:00
William Pitcock
3a2fcc32cd Add instructions for setting up Atheme. 2012-04-29 19:48:48 +02:00
Alexander Barton
a8aa8c6cbc irc-cap.c: mark arguments of Handle_CAP_ACK() as "unused"
This fixes

 irc-cap.c: In function ‘Handle_CAP_ACK’:
 irc-cap.c:163: warning: unused parameter ‘Client’
 irc-cap.c:163: warning: unused parameter ‘Arg’
2012-04-29 12:39:28 +02:00
Alexander Barton
f01b09ce84 irc-login.c, login.c: add missing include of "string.h"
This fixes the following warnings with GCC 4.4.5 on Linux:

 irc-login.c: In function ‘IRC_PASS’:
 irc-login.c:92: warning: implicit declaration of function ‘strlen’
 irc-login.c:92: warning: incompatible implicit declaration of built-in function ‘strlen’
 irc-login.c:113: warning: incompatible implicit declaration of built-in function ‘strlen’
 irc-login.c:129: warning: implicit declaration of function ‘strchr’
 irc-login.c:129: warning: incompatible implicit declaration of built-in function ‘strchr’
 irc-login.c:133: warning: implicit declaration of function ‘strcmp’
 irc-login.c: In function ‘IRC_SERVICE’:
 irc-login.c:556: warning: incompatible implicit declaration of built-in function ‘strchr’
 login.c: In function ‘Login_User’:
 login.c:131: warning: implicit declaration of function ‘strcmp’
2012-04-29 12:36:23 +02:00
Alexander Barton
2419a701d8 doc/Modes.txt: Document missing channel mode "e" 2012-04-29 12:11:50 +02:00
Alexander Barton
110be707c3 Merge branch 'master' of /srv/git/ngircd
* 'master' of /srv/git/ngircd:
  "multi-prefix" capability 2/2: adjust NAME and WHO handlers
  "multi-prefix" capability 1/2: implement complete CAP infrastructure
  IRC_Send_NAMES(): Code cleanup
  New function Client_CapSet() in addition to Client_Cap{Add|Del}
  "CAP REQ" starts capability negotiation and delays user registration
  Xcode: update project file for Xcode 4.3
  Correctly handle "CAP END", new client type CLIENT_WAITCAPEND
  Implement core IRC capability handling and "CAP" command
  New "login" source file
  Introduce_Client() => Client_Introduce(), and move it to client.c
2012-04-28 01:00:34 +02:00
Alexander Barton
b2743af0ed contrib/platformtest.sh: support "CC=xxx MAKE=yyy ./platformtest.sh"
Now you can use contrib/platformtest.sh on platforms that require a "special"
make (not "make") or compiler (not cc/gcc) binary.
2012-04-28 00:58:23 +02:00
Alexander Barton
76565022fb Merge branch 'capabilities'
* capabilities:
  "multi-prefix" capability 2/2: adjust NAME and WHO handlers
  "multi-prefix" capability 1/2: implement complete CAP infrastructure
  IRC_Send_NAMES(): Code cleanup
  New function Client_CapSet() in addition to Client_Cap{Add|Del}
  "CAP REQ" starts capability negotiation and delays user registration
  Correctly handle "CAP END", new client type CLIENT_WAITCAPEND
  Implement core IRC capability handling and "CAP" command
  New "login" source file
  Introduce_Client() => Client_Introduce(), and move it to client.c
2012-04-28 00:49:37 +02:00
Alexander Barton
4602cb9891 "multi-prefix" capability 2/2: adjust NAME and WHO handlers
The NAME and WHO commands now return multiple usermode prfixes when
the "multi-prefix" capability is in effect for the requesting client.

See <http://ircv3.atheme.org/extensions/multi-prefix-3.1>
2012-04-28 00:39:21 +02:00
Alexander Barton
1d7e99531a "multi-prefix" capability 1/2: implement complete CAP infrastructure
Now ngIRCd is able to handle "CAP LS", "CAP REQ", "CAP LIST", and
"CAP CLEAR" commands.

"multi-prefix" can be set/unset, but has no functionality - yet!
2012-04-28 00:36:41 +02:00
Alexander Barton
f0a9dbe3ad IRC_Send_NAMES(): Code cleanup 2012-04-28 00:20:42 +02:00
Alexander Barton
245782897b New function Client_CapSet() in addition to Client_Cap{Add|Del} 2012-04-27 23:56:56 +02:00
Alexander Barton
2327b17656 "CAP REQ" starts capability negotiation and delays user registration
New helper function Set_CAP_Negotiation().
2012-04-27 22:47:22 +02:00
Alexander Barton
359732af85 Xcode: update project file for Xcode 4.3
(No changes needed)
2012-04-27 15:52:09 +02:00
Alexander Barton
1dea0d91a0 platformtest.sh: Detect Open64 C compiler 2012-04-24 12:10:35 +02:00
Alexander Barton
d67d077a71 Fix 8ec17063: "Lists_Add(): use size of destination when copying data"
Thanks to Florian Westphal for spotting my silliness ...
2012-04-18 17:54:54 +02:00
Alexander Barton
69be7a85a2 Xcode: correctly sort conn-ssl.{c|h} files in file list 2012-04-17 12:57:27 +02:00
Alexander Barton
8ec17063a6 Lists_Add(): use size of destination when copying data
This fixes the following warning of clang:

/src/ngircd/lists.c:152:44:
 warning: size argument in 'strlcpy' call appears to be size of the
 source; expected the size of the destination [-Wstrlcpy-strlcat-size]

But it isn't a real problem, because the size of the source always is the
same than the size of the destination ...
2012-04-17 12:54:38 +02:00
Alexander Barton
da4c1ebe81 Correctly handle "CAP END", new client type CLIENT_WAITCAPEND 2012-03-31 16:37:31 +02:00
Alexander Barton
bd3a7ccb15 Implement core IRC capability handling and "CAP" command
This patch implements the core functions to support "IRC Capabilities"
and the IRC "CAP" command as used by other servers and specified here:
<http://www.leeh.co.uk/draft-mitchell-irc-capabilities-02.html>.

It enables ngIRCd to support the defined handshake, but it doesn't
implement any capabilities, so "CAP LS" and "CAP LIST" always return
the empty set and "CAP REQ ..." always fails with "CAP NAK".
2012-03-31 15:59:06 +02:00
Alexander Barton
edfcc2f9d5 New "login" source file
Rename Hello_User[_PostAuth] to Login_User[_PostAuth] and move it to the
new login.c; and move cb_Read_Auth_Result(), too. This will enable further
code to easily call Login_User() when required.
2012-03-31 15:38:46 +02:00
Alexander Barton
ee362b3bd2 Introduce_Client() => Client_Introduce(), and move it to client.c 2012-03-31 15:24:30 +02:00
Alexander Barton
67bd1bf34f Makefiles: list each source files on a separate line
Patches that add/remove source files become much nicer this way :-)
2012-03-31 12:52:58 +02:00
Alexander Barton
9f3af061cf Add missing documentation files to Xcode project 2012-03-31 12:51:33 +02:00
Alexander Barton
88c3d4896a Don't ignore "permission denied" errors when enabling chroot
Up to now, ngIRCd silently ignored permission denied errors when trying
to enable a chroot setup: only the "not running chrooted" message became
logged later on.

This patch lets ngIRCd exit with a fatal error when the chroot can't
be enabled on startup -- this is the much safer bevahiour!
2012-03-28 11:30:48 +02:00
Alexander Barton
7b6ef3bc8e FAQ: enhance description of chroot setup 2012-03-28 11:29:26 +02:00
Alexander Barton
fbaa751da8 ngIRCd Release 19.1 2012-03-19 19:19:58 +01:00
Alexander Barton
06b6327875 Update ChangeLog for upcoming ngIRCd 19.1 release 2012-03-16 13:55:00 +01:00
Alexander Barton
0d9740b9fa Fix gcc warning, initialize "list" variable to NULL
This fixes the following warning with gcc 4.6.3.:

  irc-mode.c: In function "Channel_Mode":
  irc-mode.c:947:26: error: "list" may be used uninitialized
                     in this function
  irc-mode.c:884:25: error: "list" may be used uninitialized
                     in this function

(The variable has never been used uninitialized, so don't worry)
2012-03-12 22:27:55 +01:00
Alexander Barton
e9be3334d1 Fix manual page "hyphen-used-as-minus-sign" error (lintian)
Thanks to Christoph Biedl for reporting this!
2012-03-12 11:02:17 +01:00
Alexander Barton
0ae74ceaed Fix typo: Please not -> Please note
Thanks to Götz Hoffart!
2012-03-12 09:49:24 +01:00
Alexander Barton
17ffda1c8a Fix typo: recieved -> received
Thanks to Christoph Biedl.
2012-03-12 09:47:19 +01:00
Alexander Barton
0de11ead36 Update NEWS and ChangeLog files 2012-03-05 22:29:53 +01:00
Alexander Barton
9d486db460 Really include _all_ patches to build the Anope module 2012-03-05 21:30:38 +01:00
Christoph Biedl
257fe922d2 getpid.sh: Fix testcase error for Debian using sbuild
When

 * building the ngircd Debian package (on Linux at least) and
 * using the sbuild build system,

the command "ps -af" does not include the commands running inside the
sbuild system. Therefore, start-server.sh will report a fail as getpid.sh
cannot not  find the ./T-ngircd1 just started although it's actually
running. This results in a funny build log ...

         starting server 1 ... failure!
   FAIL: start-server1
         running connect-test ... ok.
   PASS: connect-test

The self-test of getpid.sh however will likely succeed as it's happy if
it sees any process with "sh" somewhere in the name. Things go downhill
from there.

The confusing things are:

  * The alternative cowbuilder/pbuilder does not have this problem.
  * The alternative usage "ps ax" does fine.

So, as a quick hack, the patch attached adds another switch to getpid.sh.
2012-03-03 18:53:03 +01:00
Alexander Barton
1068f88377 Don't log "ngIRCd hello message" two times
Start "regular" logging not until the configuration file has been read in
and "SyslolgFacility" is set, and log all configuration errors using the
generic "daemon" facility.

So if there are no configuration errors, logging starts right after parsing
the configuration and we log the configuration file used _after_ reading it.
But this is no problem because every configuration error message includes
the configuration file name as well.

(The "double hello" has been introduced by commit 3641e51109)
2012-03-02 09:41:13 +01:00
Alexander Barton
9e7360e5fa ngIRCd release 19 2012-02-29 17:35:32 +01:00
Alexander Barton
273d4bdd32 Merge branch 'master' of /srv/git/ngircd
* 'master' of /srv/git/ngircd:
  Update doc/Platforms.txt for ngIRCd 19
  doc/README-Interix.txt: note that GNU make should be used
2012-02-29 14:47:37 +01:00
Alexander Barton
27d244dfae Update doc/Platforms.txt for ngIRCd 19 2012-02-29 14:46:34 +01:00
Alexander Barton
a39a1a5273 doc/README-Interix.txt: note that GNU make should be used 2012-02-29 13:20:09 +01:00
Alexander Barton
ef392e7d37 Update config.guess and config.sub to recent versions 2012-02-27 17:19:44 +01:00
Alexander Barton
c38751191f Don't accept "[SSL]" in config when no SSL support is built in 2012-02-26 15:52:12 +01:00
Alexander Barton
5cbdcf4f0d Fix C syntax: duplicate ";;" should be ";"
Using gcc 2.7.2, this fixes:

 irc-channel.c: In function `join_allowed':
 irc-channel.c:86: parse error before `const'
2012-02-26 15:27:04 +01:00
Alexander Barton
3641e51109 Correctly re-open syslog logging after reading of configuration
Syslog logging has been initialized before reading the configuraton
file, so ngIRCd always used the default facility and ignored the
"SyslogFacility" configuration option.

Thanks to Patrik Schindler for reporting this issue!
2012-02-14 11:01:13 +01:00
Alexander Barton
3f46e93ccc Logging: remove "Activating ..." info message 2012-02-14 10:32:58 +01:00
Alexander Barton
8e3c56e5b2 ngIRCd release 19~rc1 2012-02-12 17:58:50 +01:00
Alexander Barton
e1026d5dd1 Update RPM spec file description to match Debian "control file" 2012-02-12 17:57:33 +01:00
Alexander Barton
f7bdee5f13 Update NEWS and ChangeLog files 2012-02-12 16:48:57 +01:00
Alexander Barton
391aa8d1f7 Fix forwarding of LIST commands
Bug reported by Cahata, thanks!
2012-02-12 13:51:43 +01:00
Alexander Barton
89d99e2ff9 Update preliminary ngIRCd protocol module for Anope 1.9.6 2012-02-04 12:55:41 +01:00
Alexander Barton
c16133c5ee New_Connection(): don't set the client hostname twice
Setting the hostname twice doesn't do much harm a lot, but isn't elegant.
And for IPv6 addresses, it isn't correct the first time (missing []) ...
2012-01-25 17:11:44 +01:00
Alexander Barton
4888984429 Client_SetHostname(): Code cleanup, more debug logging 2012-01-25 17:11:00 +01:00
Florian Westphal
44bb22d23e io: use define for number of possible events 2012-01-24 22:25:22 +01:00
Florian Westphal
c7dd5ea0ba io: remove outer do {} while loops for epoll/kqueue/devpoll backends
simplifies things a bit. io_dispatch() is called repeatedly from the
main loop.
2012-01-24 21:57:23 +01:00
Alexander Barton
871760583c Enhance server command limits
This patch updates the limits for handling commands from a remote server:

 - "<user count> / 5 + <min>" using "<min>=10" during normal operation,
 - the above count multiplied with 5 while servers are syncing.

The intention is to a) make the limit dependent of the number of users
in the network (the more users, the more commands required to sync) and
b) to significantly rise this limit while servers are joining the network
to make the login and synchronization faster.
2012-01-24 02:55:53 +01:00
Alexander Barton
bc20f9ec10 Send a PING at the end of the server sync to detect it
At the end of sending all "state" to the remote server, a PING command
is sent to request a PONG reply. Until then, no "regual" PING was sent,
so Conn_LastPing(<connection>) is null and now becomes non-null in the
PONG command handler.

So the servers are still synchronizing when Conn_LastPing(<connection>)
is 0, which could easily be tested.
2012-01-24 02:46:12 +01:00
Alexander Barton
5a200e1543 New function Conn_UpdatePing() to update the "ping timestamp" 2012-01-24 02:44:57 +01:00
Alexander Barton
d2df7396a8 Conn_UpdateIdle(): Code cleanup 2012-01-24 02:43:55 +01:00
Alexander Barton
3d27073d61 RPL_ISUPPORT_MSG(005): add "EXCEPTS=e INVEX=I"
Thanks to Cahata for the idea!
2012-01-23 22:07:40 +01:00
Alexander Barton
b6f19ea8fe Fix "MAXLIST=beI:50": the limit is the sum of all lists
"Modes which are specified in the same pair share the same maximum size",
so "beI:50" means a total of 50 entries, regardless of the list.

See <http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt>,
thanks to Cahata for reporting this!
2012-01-23 21:51:38 +01:00
Alexander Barton
8c46067b34 Update NEWS and ChangeLog files 2012-01-23 12:30:16 +01:00
Alexander Barton
594fdd02aa New RPL_WHOISHOST_MSG(378): show hostname and IP address
The numeric RPL_WHOISHOST_MSG(378) returns the DNS hostname (if
available) and the IP address of a client in the WHOIS reply.

Only the user itself and local IRC operators get this numeric.
2012-01-22 22:41:39 +01:00
Alexander Barton
6a308fcb42 New function Conn_GetIPAInfo(): get IP address of a connection 2012-01-22 22:35:27 +01:00
Alexander Barton
1537c79132 G/K-Lines: only add and delete valid IRC masks 2012-01-22 18:53:16 +01:00
Alexander Barton
e0c9931ad8 Check G/K-Lines before the client has been registered, too
This allows to use "*!<user>@<host>" or "*!*@<host>" masks to reject
clients even before receiving PASS, NICK and USER commands and before
forking authentication child processes which reduces resource usage.
2012-01-22 18:35:54 +01:00
Alexander Barton
eba95bb0d2 Streamline handling of connection rejects (bad password, G/K-line)
- Use Client_Reject(), get rid of Reject_Client().
 - Refactor Class_IsMember() to Class_GetMemberReason(),
 - New function Class_HandleServerBans().
2012-01-22 18:33:45 +01:00
Alexander Barton
51a6a33056 New function Client_Reject() to reject clients on connect 2012-01-22 18:17:28 +01:00
Alexander Barton
6e28f4a7d1 New function Lists_CheckReason() to get reason of list entries 2012-01-22 18:11:24 +01:00
Alexander Barton
9882e578e9 Update NEWS and ChangeLog files 2012-01-22 15:58:39 +01:00
Alexander Barton
73781c1b38 Fix ERR_{SUMMON|USERS}DISABLED: don't repeat command name in reply 2012-01-22 15:42:11 +01:00
Alexander Barton
f2fa1045e2 Implement channel exception list (mode 'e')
This allows a channel operator to define exception masks that allow users
to join the channel even when a "ban" would match and prevent them from
joining: the exception list (e) overrides the ban list (b).
2012-01-21 19:59:57 +01:00
Alexander Barton
33a165721b {Add|Del}_Ban_Invite > {Add_To|Del_From}_List(): more generic 2012-01-21 19:27:03 +01:00
Alexander Barton
a3a4b5f696 Rename ShowInvitesBans() to ShowChannelList(), make it more flexible 2012-01-21 13:48:31 +01:00
Alexander Barton
39412d6486 PRIVMSG/NOTICE: handle nick!user@host masks case-insensitive
And enhance our test suite to check this a little bit better :-)
2012-01-21 13:21:36 +01:00
Alexander Barton
c1656256df PRIVMSG/NOTICE: don't stop list processing on invalid target
Process further targets, even if one has been a server ID:
just skip this one with an error message and continue.
2012-01-16 12:37:37 +01:00
Alexander Barton
1f4711a547 Implement user mode 'C': require "same channel" to send message
If the target user of a PRIVMSG or NOTICE command has the user mode 'C'
set, it is required that both sender and receiver are on the same channel.

This prevents private flooding by completely unknown clients.
2012-01-16 11:43:22 +01:00
Alexander Barton
4d0069c3a8 New RPL_WHOISREGNICK_MSG(307) numeric: indicate if nick is registered 2012-01-16 02:18:24 +01:00
Alexander Barton
12c60a670e IRC_WHOIS_SendReply(): Code cleanup 2012-01-16 02:15:41 +01:00
Alexander Barton
2f7d0c0839 Limit channel invite and ban lists to 50 entries
- New function Lists_Count().
 - New limit #define MAX_HNDL_CHANNEL_LISTS = 50.
 - New numeric #define ERR_LISTFULL_MSG(478).
 - Adjust numeric RPL_ISUPPORT2_MSG(005) accordingly ("MAXLIST")
2012-01-16 00:29:36 +01:00
Alexander Barton
1afbf71236 Make Send_ListChange() a little bit more generic 2012-01-16 00:15:26 +01:00
Alexander Barton
7ed08f01ef Remove unused prototype of Lists_AlreadyRegistered()
This prototype has been introduced by commit fa7bb279 in 2006,
but as far as I can see, this function never existed ...
2012-01-15 19:46:00 +01:00
Alexander Barton
81cc5f82b5 Channel lists: Fix duplicate check and error messages
- Check correct list for duplicates when adding items.
 - Don't generate any messages when adding duplicates or removing
   non-existing items (this is how ircd-seven and ircu behave).
 - Code cleanup: Add_Ban_Invite(), Del_Ban_Invite().
2012-01-15 19:11:03 +01:00
Alexander Barton
78a3b4c7d6 Don't enforce MAX_HNDL_MODES_ARG on server and service links 2012-01-15 14:33:04 +01:00
Alexander Barton
39d630c00d Update documentation (fix some URL, update some info) 2012-01-14 12:29:53 +01:00
Alexander Barton
4fe6b42c53 Update NEWS and ChangeLog for next ngIRCd release once more 2012-01-13 19:23:07 +01:00
Alexander Barton
d4d8102fc9 Don't stop join handling on faulty channel, skip it (part #2)
Commit 565523cb allowed processing of further channel names given to the
JOIN command when a single name was invalid.

After this patch, the JOIN command handler continues to process channel
name lists even after errors like "channel is full", "too many channels",
and the like and generates appropriate error messages for all the
channels given by the client.
2012-01-13 10:50:00 +01:00
Alexander Barton
77f68b4fd1 JOIN command: don't check channel limit if already member
Don't check the channel limit and don't report "too many channels"
when trying to join a channel that the client is already a member of.
2012-01-13 10:40:20 +01:00
Alexander Barton
2f8877ded4 Return ERR_UNKNOWNMODE(472) for unknown channel modes
The daemon reported ERR_UMODEUNKNOWNFLAG(501), which is wrong.
2012-01-09 23:18:39 +01:00
Alexander Barton
4bff3daf92 Numberic 005 (ISUPPORT), CHANMODES: add "O", "R", "z" modes 2012-01-09 12:34:55 +01:00
Alexander Barton
c5beca8aab Limit list replies of LIST, WHO, WHOIS, and MAX_RPL_WHOWAS
Introduce new #define's MAX_RPL_LIST(100), MAX_RPL_WHO(25),
MAX_RPL_WHOIS(10), and MAX_RPL_WHOWAS(25).
2012-01-06 20:06:25 +01:00
Alexander Barton
f8405b1a4f New function IRC_CheckListTooBig() to check size of list replies
It the limit is reached, a NOTICE is sent to the client and list
processing should stop.
2012-01-06 20:05:07 +01:00
Alexander Barton
fdfc27265e LIST command: compare pattern case insensitive 2012-01-06 19:55:21 +01:00
Alexander Barton
a4d1e6007f IRC_LIST(): Code cleanup 2012-01-06 19:54:23 +01:00
Alexander Barton
9260759cec DEFAULT_WHOWAS->DEF_RPL_WHOWAS; MAX_CMODES_ARG->MAX_HNDL_MODES_ARG
To streamline naming, in preparation for MAX_RPL_WHO and MAX_RPL_WHOWAS :-)
2012-01-06 18:57:31 +01:00
Alexander Barton
c2ac1ad3ba defines.h: Code cleanup and (a little bit) more documentation 2012-01-06 18:25:10 +01:00
Alexander Barton
470d2e2362 RPL_ISUPPORT (numeric 005): Report MODES=<MAX_CMODES_ARG>
"Maximum number of channel modes with parameter allowed per MODE command."
See <http://www.irc.org/tech_docs/005.html> for details.
2012-01-06 17:46:52 +01:00
Alexander Barton
888664435a Channel modes: really break handling when MAX_CMODES_ARG is hit
This fixes 98493077.
2012-01-06 17:43:20 +01:00
Alexander Barton
98493077a2 channel modes: only handle MAX_CMODES_ARG modes with arguments
Limit the MODE command to handle a maximum of MAX_CMODES_ARG (5) channel
modes that require an argument (+Ibkl) per call.

Please note: Further modes that require arguments are silently ignored
and end the handling of any further modes.
This is similar to the behavior of ircd2.11 (silently ignores but seems
to handle other modes) as well as ircd-seven (silently ignores but handles
some(!) other modes) ...
2012-01-06 17:27:29 +01:00
Alexander Barton
1fa2af5b3a Fix handling of channel mode sequence with/without arguments
For example, don't generate wrong error messages when handling
"MODE #chan +IIIIItn *!aa@b *!bb@c *!cc@d *!dd@e *!ee@f".
2012-01-06 17:24:55 +01:00
Alexander Barton
05cc9bf9b0 Conn_Write(): Make sure there is a client when detecting its type
The assert(client != NULL) got triggered during our tests, so there is
an error path that resulted in the connection being still established
(sock >= 0) but the client structure already freed.

So Conn_Write() should handle it!
2012-01-06 03:26:24 +01:00
Alexander Barton
cc06e1ff89 Proc_Close(): Only close socket if it is still valid
It could be invalid when calling Proc_Close() a 2nd time, for exmaple,
which could happen when we hit a timeout doing IDENT requests :-(
2012-01-06 02:26:04 +01:00
Alexander Barton
9fbf592924 WHOIS command: make sure matching is case-insensitive
And make sure that RPL_ENDOFWHOIS replies with the unmodified mask
like it has been received from the client.
2012-01-05 00:51:39 +01:00
Alexander Barton
adf92302bf WHOIS command: don't anser queries for IRC servers
Thanks to Cahata for spotting this!
2012-01-05 00:24:46 +01:00
Alexander Barton
566a451299 WHOIS command: make sure the reply ends with RPL_ENDOFWHOIS
Up to now, each reply for itself ended in RPL_ENDOFWHOIS and queries
for unknown nick names lacked the RPL_ENDOFWHOIS -- both is wrong.
2012-01-05 00:22:57 +01:00
Alexander Barton
e0f8ce093a README: update features list, borrow from list on our website 2012-01-04 23:30:55 +01:00
Alexander Barton
5e3449a241 LINKS command: support <mask> parameter
The <mask> can be used to limit the servers shown in the listing.
2012-01-04 22:51:02 +01:00
Alexander Barton
762b0325df IRC_LINKS(): Code cleanup; more documentation 2012-01-04 22:49:18 +01:00
Alexander Barton
6b62a5ec4f Add 1 second penalty for every further target on PRIVMSG/NOTICE
This reduces the possibility of flooding channels with commands like
"PRIVMSG/NOTICE #a,#n,#c,... :message" a little bit.

Problem noticed by Cahata -- thanks!
2012-01-04 21:46:58 +01:00
Alexander Barton
b24d645ca1 Conn_SetPenalty(): Add new "penalty time" on each function call
Until now, the penalty time has only been set when longer as the
already set one, so it didn't accumulate.

And add documentation for and clean up code in Conn_SetPenalty() and
Conn_ResetPenalty() functions.
2012-01-04 21:39:46 +01:00
Alexander Barton
1bb2fbedcc Enhance log messages when setting user and group 2012-01-03 21:05:35 +01:00
Alexander Barton
3193d5477c NGIRCd_getNobodyID(): Code cleanup 2012-01-03 20:49:42 +01:00
Alexander Barton
edab86e0f8 Display correct error message when "Server{UID|GID}" is invalid
This partly closes bug #118. ngIRCd still starts up even when
Server{UID|GID} is invalid: then the daemon falls back to "nobody"
when running with root(0) privileges (as before).
2012-01-03 20:37:41 +01:00
Alexander Barton
e4006a93e3 NGIRCd_Init(): Code cleanup 2012-01-03 19:34:54 +01:00
Alexander Barton
9069380ddf main(): Code cleanup 2012-01-03 19:25:31 +01:00
Alexander Barton
ab188c1486 README: point to included COPYING file, not gnu.org 2012-01-03 18:56:31 +01:00
Alexander Barton
5eb9f2e717 Update Copyright notices for 2012 2012-01-03 11:30:45 +01:00
Florian Westphal
abfc5c6e27 lists: don't crash if reason ptr is NULL
commit 15fec92ed7
(Update list item, if it already exists) can make ngircd
crash because 'Reason' can be NULL, as reported by
Cahata on the ngircd mailing list.

Doesn't affect any released ngircd versions.

Also, make sure that we do not pass NULL as arguments
to a '%s' printf-like function.
2012-01-02 23:43:13 +01:00
Alexander Barton
565523cbb4 Don't stop join handling on faulty channel, skip it
When JOIN is received with more than one channel name, don't stop
processing on the first error (e.g. bad name, wrong channel key, ...)
but report an error and continue with the other given channel names.

Reported by Cahata -- thanks!
2012-01-02 15:23:17 +01:00
Alexander Barton
013298d4c6 IRC_JOIN(): Code cleanup 2012-01-02 15:22:52 +01:00
Alexander Barton
af13732ec7 ISON command: reply with correct upper-/lowercase nick names
Reported by Cahata -- thanks!
2012-01-02 15:06:44 +01:00
Alexander Barton
408a74b865 IRC_ISON(): Code cleanup 2012-01-02 15:04:40 +01:00
Alexander Barton
f47904bf95 Remove unused "bool have_arg" from IRC_WHO()
This fixes:

 irc-info.c: In function ‘IRC_WHO’:
 irc-info:936:18: warning: variable ‘have_arg’ set but not used
2012-01-02 00:56:31 +01:00
Alexander Barton
70eb8219f5 Update NEWS and ChangeLog for next ngIRCd release 2012-01-01 23:14:28 +01:00
Alexander Barton
9e5b9ddad0 ngircd.conf.5: reword description of "Ports" variable 2012-01-01 17:39:07 +01:00
Alexander Barton
56b7e67307 New configuration option "PAMIsOptional"
When "PAMIsOptional" is set, clients not sending a password are still
allowed to connect: they won't become "identified" and keep the "~"
character prepended to their supplied user name.
2012-01-01 17:12:36 +01:00
Alexander Barton
b681aa5b9f PAM: don't use global password buffer for conv struct
Use the pointer of the password of the client directly.
Eventually we can get rid of the global password again ...
2011-12-31 18:06:17 +01:00
Alexander Barton
b32f3b76e9 doc/Modes.txt: document channel mode "r"
And make clear, that user mode "r" and channel mode "r" are not set by
ngIRCd itself but by IRC services.
2011-12-31 18:04:58 +01:00
Alexander Barton
1a5ed654b4 Fixed handling of WHO commands
This fixes two bugs:
 - "WHO <nick>" returned nothing at all if the user was "+i"
   (reported by Cahata, thanks).
 - "WHO <nick|nickmask>" returned channel names instead of "*"
   when the user was member of a (visible) channel.

Clean up code and add documentation as well.
2011-12-30 14:57:12 +01:00
Alexander Barton
9cbb8f3bb8 Remove unused "time_t now" from Lists_Check()
This fixes:

 lists.c: In function ‘Lists_Check’:
 lists.c:330:9: warning: variable ‘now’ set but not used
2011-12-30 01:03:59 +01:00
Alexander Barton
e19ce437ca Fixed some spelling errors in documentation and code comments
Thanks to Christoph Biedl!
2011-12-30 00:50:27 +01:00
Alexander Barton
4e550bf9ef contrib/Debian/control: Update and complete "Build-Depends" 2011-12-30 00:40:18 +01:00
Alexander Barton
1d29a59f7e Update our Debian package descriptions with "official" ones
See Debian Bug #648241 for details.
2011-12-30 00:36:26 +01:00
Alexander Barton
765c2f26ea Fixed typo in two error messages
Thanks to Christoph Biedl!
2011-12-30 00:32:11 +01:00
Alexander Barton
69fa6f268a LUSERS reply: only count "visible" channels
Rename Channel_Count() to Channel_CountVisible() and only count channels
that are visible to the requesting client, so the existence of secret
channels is no longer revealed by using LUSERS.

Reported by Cahata -- thanks!
2011-12-28 15:11:01 +01:00
Alexander Barton
43509fd22c IRC_Send_LUSERS(): Code cleanup 2011-12-28 14:52:21 +01:00
Alexander Barton
a71abfef4b Don't stop mode handling on unknown modes; skip it
Unknown user and channel modes no longer stop the mode parser, but are
simply ignored. Therefore modes after the unknown one are now handled.

This is how ircd2.10/ircd2.11/ircd-seven behave, at least.

Reported by Cahata -- thanks!
2011-12-28 14:46:17 +01:00
Alexander Barton
8a8e8a3a23 IRC_xLINE(): output an error message for unexpected "lines"
This fixes:

 irc-oper.c: In function ‘IRC_xLINE’:
 irc-oper.c:429: warning: ‘class’ may be used uninitialized in this function
 irc-oper.c:430: warning: ‘class_c’ may be used uninitialized in this function
2011-12-25 20:11:43 +01:00
Alexander Barton
65befdafaa README: Update list of implemented commands 2011-12-25 20:01:28 +01:00
Alexander Barton
15fec92ed7 Update list item, if it already exists
This updates the "validity" (timeout) as well as the "reason" text,
if given.
2011-12-25 19:43:00 +01:00
Alexander Barton
1e4a00f94f Lists_CheckDupeMask(): return pointer to already existing item
The old behavior of returning true/false is compatible to this change,
so there are no other code changes required.
2011-12-25 19:42:03 +01:00
Alexander Barton
338758799d Log better error messages when rejecting clients 2011-12-25 19:27:06 +01:00
Alexander Barton
164e15b8c6 Synchronize G-Lines on server login 2011-12-25 19:12:40 +01:00
Alexander Barton
32bfafafd9 Op_Check(): always accept commands from a remote server itself 2011-12-25 19:11:43 +01:00
Alexander Barton
6ef20e0f9a Class_GetList() now retuns a pointer to list_head structure 2011-12-25 19:11:07 +01:00
Alexander Barton
e86e193e01 Check G-Line and K-Line lists after authenticating clients 2011-12-25 18:03:35 +01:00
Alexander Barton
ae5ebfb9f0 New functions Lists_Expire() and Class_Expire()
GLINE and KLINE lists are cleared automatically now, not when they are
checked. So "STATS g" and "STATS k" no longer show expired entries :-)
2011-12-25 17:44:20 +01:00
Alexander Barton
e9e6224aae Implement IRC_xLINE(): handler for "GLINE" and "KLINE" commands 2011-12-25 16:57:36 +01:00
Alexander Barton
e23f025dd6 Op_Check(): return client that initiated the request or NULL
The old behavior of returning true/false is compatible to this change,
so there are no other code changes required.
2011-12-25 16:52:31 +01:00
Alexander Barton
3ca8703309 irc-oper.c: code cleanup; more documentation 2011-12-25 16:08:00 +01:00
Alexander Barton
fc82efc3e8 Implement IRC "STATS g" and "STATS k" command 2011-12-25 14:50:19 +01:00
Alexander Barton
dc9fcb0fb2 New function Class_GetList() 2011-12-25 14:49:52 +01:00
Alexander Barton
2b95c69ea1 lists.{c|h}: code cleanup; more documentation 2011-12-25 14:48:13 +01:00
Alexander Barton
af70c3dbc9 List and class handling: add optional "reason" text
Adjust Lists_Add() and Class_AddMask() accordingly, implement
Lists_GetReason() and Lists_GetValidity().
2011-12-25 14:19:45 +01:00
Alexander Barton
1e054e0b82 Add new class.{c|h} module to Xcode project 2011-12-24 14:24:07 +01:00
Alexander Barton
06a20b87c4 Add new class.{c|h} to project
Implement Class_{AddMask|DeleteMask|IsMember}() functions.
2011-12-24 13:40:27 +01:00
Alexander Barton
fea2194fc0 Lists: change "only once" property into "valid until"
The old "only once" true/false behavior is still supported, so there
are no other code changes required.
2011-12-24 13:34:25 +01:00
Alexander Barton
872dc5042d Xcode: update project file for Xcode 4.2 2011-12-24 13:22:34 +01:00
Alexander Barton
e1315f30fd define HAVE_GAI_STRERROR for Mac OS X Xcode builds
On Mac OS X 10.7 Lion, this fixes

  In file included from .../contrib/MacOSX/../../src/ngircd/client.c:28:
   /Developer/SDKs/MacOSX10.7.sdk/usr/include/netdb.h:272:13:
   error: expected identifier or '('
2011-12-24 13:16:38 +01:00
Alexander Barton
0a85c58878 Configuration: get rid of Conf_Oper_Count and Conf_Channel_Count
Count elements dynamically when needed.
2011-12-07 10:52:30 +01:00
Alexander Barton
ee21490887 ./configure: Fix logic and quoting of poll() detection code
This fixes commit 8e193df ...
2011-12-05 00:20:27 +01:00
Alexander Barton
8fa92f0a24 Suppress 'Can't create pre-defined channel: invalid name: ""' messages
Skip predefined channel structures that have configured no name,
like the "--configtest" does.
2011-12-04 22:35:20 +01:00
Alexander Barton
8e193df973 Only use poll() when poll.h exists as well 2011-11-25 22:06:44 +01:00
Alexander Barton
9d348d00d9 Not only check for poll(), make sure poll.h exists as well
This fixes building ngIRCd on Debian GNU/Linux 1.3 "Bo" :-)
2011-11-25 21:56:33 +01:00
Alexander Barton
9e48f3f8f8 whois-test: handle local hostname = "localhost.localdomain"
Use the pattern "localhost*" for valid local hostnames.
2011-11-10 11:54:22 +01:00
Alexander Barton
e4a06844a3 sample-ngircd.conf: show correct default for "PAM" variable
The default of "PAM" is "yes" when ngIRCd has been configured to use it,
so show the correct default value in the sample configuration file.

Closes #119.
2011-11-08 21:12:01 +01:00
Alexander Barton
20ccc1bba7 Update GPL 2 license text to current version
See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.
2011-11-06 21:53:15 +01:00
Alexander Barton
13d9e0c5a7 Test for gai_strerror()
If gai_strerror() isn't available, use a macro that simply returns
a static error message (regardless of the real error code).

For example, GNU libc 2.0.7 doesn't implement gai_strerror().
2011-11-06 14:16:59 +01:00
Alexander Barton
a7911e35af Only use AI_NUMERICHOST if it is #define'd
It isn't using GNU libc 2.0.7, for example ...
2011-11-06 14:13:49 +01:00
Alexander Barton
60812b6fdf defines.h: fix comment: "lenth" -> "length"
Reported by Christoph Biedl in #ngircd. Thanks!
2011-11-05 00:35:18 +01:00
Alexander Barton
1ea6811616 Init_Server_Struct(): correctly zero Server->bind_addr
Don't use the size of the pointer, use the size of the variable!
2011-11-05 00:21:19 +01:00
Alexander Barton
d2f54abbed Clean up and fix comments of Check_ArgIsTrue()
Thanks to kaFux for pointing this out!
And fix code formatting as well ...
2011-11-03 09:54:28 +01:00
Alexander Barton
07dbb73c92 Update doc/GIT.txt 2011-09-07 15:39:41 +02:00
Alexander Barton
30796698a9 Only close "unrelated" sockets in forked child processes
This fixes the problem that ngIRCd can't do any IDENT lookups because
of the socket has already been closed in the child process.

The bug has been introduced starting with ngIRCd 17 ... :-(
(commit ID 6ebb31ab35)
2011-09-07 14:51:16 +02:00
Alexander Barton
f173a974be Added doc/Modes.txt: document modes supported by ngIRCd 2011-08-26 16:16:53 +02:00
Alexander Barton
8aac366802 Implemented user mode "R" and channel mode "R"
- User mode "R": indicates that the nick name of this user is "registered".
   This mode isn't handled by ngIRCd itself, but must be set and unset by
   IRC services like Anope.

 - Channel mode "R": only registered users (having the user mode "R" set)
   are allowed to join this channel.
2011-08-26 15:26:38 +02:00
Alexander Barton
69803d6ff1 Use Proc_Close() to remove no longer unused pipes to child processes
This removes spurious (but harmless) debug messages.
2011-08-23 12:32:05 +02:00
Alexander Barton
be6994aece New function Proc_Close() to shutdown pipes to child processes 2011-08-23 12:31:17 +02:00
Alexander Barton
1361b3742d Introduce DEBUG_BUFFER, rework some debug messages
DEBUG_BUFFER is off by default and therefore disables these messages:
 - "Handle_Write() called for connection XX, YY bytes pending ..."
 - "Connection XX: ZZ bytes left in read buffer."
2011-08-23 12:28:04 +02:00
Alexander Barton
d3036c74e9 Testsuite: bind to loopback (127.0.0.1) interface only 2011-08-22 16:54:24 +02:00
Alexander Barton
553e8b6aa3 doc/Platforms.txt: ngIRCd 18 on Nexenta works
Thanks to Götz Hoffart for testing!
2011-08-19 15:51:56 +02:00
Alexander Barton
51d7674ee7 New 2nd message "Nickname too long" for error code 432 2011-08-19 11:09:40 +02:00
Alexander Barton
1189200d4a Client_CheckNick(), Client_IsValidNick(): code cleanup 2011-08-19 10:44:26 +02:00
Alexander Barton
7795b07c53 Merge branch 'ServerMode'
* ServerMode:
  Handle channel user modes 'a', 'h', and 'q' from remote servers
  Handle unknown channel modes on server links
  Handle unknown user modes on server links
  IRC_MODE(), Client_Mode(): code cleanup [2/2]
  Enlarge client user mode buffer, reduce client flags buffer
  Infom clients when other servers change their user modes
  IRC_MODE(), Client_Mode(): code cleanup [1/2]
2011-08-13 21:04:01 +02:00
Alexander Barton
d9325e8030 Merge branch 'bug113-SrvPrefix'
* bug113-SrvPrefix:
  Slightly change (and document!) IRC_KILL() calling convention
  Spoofed prefixes: close connection on non-server links only
2011-08-09 10:16:56 +02:00
Alexander Barton
641045249c Xcode: update project file to Xcode 3.2 or newer
Xcode requires Mac OS X 10.6 or newer; Xcode 4 supports this project
format as well, so effectively you can use Mac OS X 10.6.x or 10.7.x
for building ngIRCd with the Apple Xcode IDE.
2011-08-07 14:42:49 +02:00
Alexander Barton
69f81a359a Xcode: Mac OS X config.h: support 10.5 as well as 10.6/10.7 SDK 2011-08-07 14:41:11 +02:00
Alexander Barton
be03bc672c Xcode: exclude more Xcode 4 specific directories in ".gitignore" 2011-08-02 16:04:23 +02:00
Alexander Barton
160c52400f Cast getpid() and time() results for srand() input
This fixes:

src/ngircd/ngircd.c:596: warning: implicit conversion
 shortens 64-bit value into a 32-bit value

(i686-apple-darwin11-llvm-gcc-4.2)
2011-08-02 13:24:13 +02:00
Alexander Barton
0b8acf1205 Xcode: update and add missing files to project 2011-08-02 13:16:28 +02:00
Alexander Barton
88f6fc5fd8 IRC_QUIT(): disconnect directly linked servers sending QUIT
Without this patch, the server becomes removed from the network and
the client structures, but the connection isn't shut down at all ...
2011-08-02 00:56:49 +02:00
Alexander Barton
da897a2a14 contrib/ngindent: detect "gindent" as GNU indent 2011-08-01 23:39:29 +02:00
Alexander Barton
989c9fa531 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" argument.

Like unknown user and channel modes, these modes are saved and forwarded,
but ignored otherwise.
2011-08-01 23:30:55 +02:00
Alexander Barton
2fd42667c2 Handle unknown channel modes on server links 2011-08-01 22:30:00 +02:00
Alexander Barton
2dfa24d2fa Handle unknown user modes on server links 2011-08-01 22:09:40 +02:00
Alexander Barton
1ed602eb47 IRC_MODE(), Client_Mode(): code cleanup [2/2] 2011-08-01 21:51:31 +02:00
Alexander Barton
ea725b99b7 Enlarge client user mode buffer, reduce client flags buffer
We have to enlage our user mode buffer, so we can handle even unknown
user modes in the future; and reduce the client flags buffer, because
I can't imagine why we ever would need ~100 flags!?

Now we support up to 15 user modes (was: 8) and up to 15 flags (was: 99).

So in the end, we even save 99-15+8-15=77 bytes for each client structure!
2011-08-01 21:28:55 +02:00
Alexander Barton
3dc3a03538 Infom clients when other servers change their user modes 2011-08-01 21:10:16 +02:00
Alexander Barton
95f0e4033c doc/Platforms.txt: re-add mipsel/unknown/linux-gnu with gcc 4.1.2 2011-08-01 10:42:22 +02:00
Alexander Barton
409b2c86c8 Updated doc/Platforms.txt: mipsel/unknown/linux-gnu 2011-08-01 09:08:14 +02:00
Alexander Barton
d692286d7a IRC_MODE(), Client_Mode(): code cleanup [1/2] 2011-08-01 09:07:32 +02:00
Alexander Barton
456e55921d Slightly change (and document!) IRC_KILL() calling convention 2011-07-30 19:48:48 +02:00
Alexander Barton
9f3690c39c Testsuite: make getpid.sh work even when run as root
Use ps(1) flag "-a" (as well as "-f"):
"Select all processes except both session leaders (see getsid(2)) and
processes not associated with a terminal."

Thanks to Götz Hoffart for reporting this problem!
2011-07-30 18:47:58 +02:00
Alexander Barton
6cbe13085d Spoofed prefixes: close connection on non-server links only
On server-links, spoofed prefixes can happen because of the asynchronous
nature of the IRC protocol. So don't break server-links, only log a message
and ignore the command.

This fixes bug 113, see:
<https://arthur.barton.de/bugzilla/show_bug.cgi?id=113>
2011-07-19 16:07:34 +02:00
Alexander Barton
b7780e3f2a Fix typo in doc/Platforms.txt; make Linux footnote more generic 2011-07-10 22:32:29 +02:00
Alexander Barton
04744e9d89 ngIRCd release 18 2011-07-10 20:05:16 +02:00
Alexander Barton
54f04f81e9 Update ChangeLog and NEWS for ngIRCd release 18 2011-07-10 20:02:01 +02:00
Alexander Barton
95e156b519 Updated doc/Platforms.txt for ngIRCd release 18 2011-07-10 19:58:41 +02:00
Alexander Barton
e160121698 MorePrivacy: Don't register WHOWAS information
Citing an email from Florian to the ngIRCd mailing list:

"I wonder what the expected behaviour is when Conf_MorePrivacy is changed
 from 'yes' to 'no' and the config is reloaded.

 At the moment, WHOWAS will start giving out information on Users that
 were connected during Conf_MorePrivacy=yes period.  If this is not
 wanted, Client_RegisterWhowas() should be changed to not store a record
 when Conf_MorePrivacy is enabled."

And I think it is "not wanted" :-)
2011-07-10 14:45:33 +02:00
Alexander Barton
54566b6b32 Add preliminary ngIRCd protocol module for Anope 1.9
See contrib/Anope/README and doc/Services.txt for more details
and installation instructions!
2011-07-10 14:23:11 +02:00
Alexander Barton
c041bb340c Update timestamp of ngircd(8) manual page 2011-07-02 22:02:43 +02:00
Alexander Barton
af60f04fef ngIRCd release 18~rc2 2011-06-29 10:22:46 +02:00
Alexander Barton
2d35731399 GnuTLS: use 1024 (DH_BITS_MIN) as minimum size of the DH prime
For outgoing connections, we use 2048 (DH_BITS) since commit 49b2d0e.

This patch enables ngIRCd to accept incoming connections from other servers
and clients that use at least 1024 bits (and no longer requires 2048 for
incoming connections, too).

Patch proposed by Florian Westphal.
2011-06-28 13:48:33 +02:00
Alexander Barton
7ae7ace579 ngircd.8: document debugging options 2011-06-28 13:45:16 +02:00
Alexander Barton
5f400694cf ngircd.conf.5: strip "SSL" prefix from variables in [SSL] section 2011-06-28 13:21:38 +02:00
Alexander Barton
bd118c65fd Fix some wording, use spellchecker ;-) 2011-06-28 13:12:06 +02:00
Alexander Barton
29c49f643f doc/SSL.txt: adopt to new configuration file layout 2011-06-28 13:11:14 +02:00
104 changed files with 6525 additions and 2247 deletions

View File

@@ -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.
@@ -10,9 +10,10 @@
Note: If you have critics, patches or something else, please feel free to
post a mail to the ngIRCd mailing list: <ngircd-ml@arthur.ath.cx> (please see
<http://ngircd.barton.de/#ml> for details). Don't mail the contributors
directly, if possible!
post a mail to the ngIRCd mailing list: <ngircd-ml@arthur.barton.de> (please
see <http://ngircd.barton.de/#ml> for details).
Don't mail the people listed here directly, if possible!
Main Authors

39
COPYING
View File

@@ -1,12 +1,12 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
@@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
@@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
@@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
@@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
@@ -225,7 +225,7 @@ impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
@@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
@@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
@@ -303,10 +303,9 @@ the "copyright" line and a pointer to where the full notice is found.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
@@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

249
ChangeLog
View File

@@ -2,24 +2,227 @@
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.
-- ChangeLog --
ngIRCd Release 18
ngIRCd Release 19.2 (2012-06-19)
- doc/Capabilities.txt: document "multi-prefix" capability
ngIRCd 19.2~rc1 (2012-06-13)
- New configuration option "CloakHostModeX" to configure the hostname
that gets used for IRC clients which have user mode "+x" enabled.
Up to now, the name of the IRC server itself has been used for this,
which still is the default when "CloakHostModeX" isn't set.
- Correctly handle asynchronously re-established server links: a race
condition could let the daemon loose track of an already re-established
incoming server link while preparing its own outgoing connection.
Peers that both try to connect each other could have been affected.
- Log a debug message when SIGUSR2 is handled in debug mode.
- Only allow alphanumeric characters in user-supplied user names of
USER command and IDENT replies.
- Change wording of "TLS initialized" message to make it more consistent.
- Don't leak file descriptors on error path when creating "PID files".
- Add missing mode "r" to CHANMODES in 005 "ISUPPORT" numeric.
- Update doc/Modes.txt and doc/Platforms.txt documents.
- contrib/platformtest.sh: correctly detect Open64 C compiler and handle
"CC=xxx MAKE=yyy ./platformtest.sh" calling convention.
- Add instructions for setting up Atheme IRC services.
- Implement support for IRC capability handling, the new "CAP" command,
and capablity "multi-prefix" which allows both the NAME and WHO command
handlers to return more than one "class prefix" to the client.
- Update Xcode project files: reference missing documentation files.
- Fix: Don't ignore "permission denied" errors when enabling chroot.
- FAQ: enhance description of chroot setup.
ngIRCd Release 19.1 (2012-03-19)
- Fix gcc warning (v4.6.3), initialize "list" variable to NULL.
- Fix typos: "recieved" -> "received", "Please not" -> "Please note",
and fix lintian(1) warning ""hyphen-used-as-minus-sign", too.
- Really include _all_ patches to build the Anope module into the
distribution archive ... ooops!
- getpid.sh: Fix test case error for Debian using sbuild(1).
- Don't log "ngIRCd hello message" two times when starting up.
ngIRCd Release 19 (2012-02-29)
- Update build system: bump config.guess and config.sub files used by
GNU autoconf/automake to recent versions.
- Fix configuration file parser: don't accept "[SSL]" blocks in the
configuration file when no SSL support is built in ngIRCd.
- Fix building ngIRCd with old gcc versions (e. g. 2.7.2).
- Correctly re-open syslog logging after reading of configuration
file: Syslog logging has been initialized before reading the
configuration, so ngIRCd always used the default facility and ignored
the "SyslogFacility" configuration option ...
Thanks to Patrik Schindler for reporting this issue!
ngIRCd 19~rc1 (2012-02-12)
- Enhance command limits for server links: the limit now is dependent
on the number of users connected in the network and higher while
servers are joining the network to make the login of servers faster.
- Log more information about server synchronization.
- Update preliminary ngIRCd protocol module for Anope 1.9.6, which now
is the only supported version.
- New numeric RPL_WHOISHOST_MSG(378), which returns the DNS host name
(if available) and the IP address of a client in the WHOIS reply.
Only the user itself and local IRC operators get this numeric.
- Implement channel exception list (mode 'e'). This allows a channel
operator to define exception masks that allow users to join the
channel even when a "ban" would match and prevent them from joining:
the exception list (e) overrides the ban list (b).
- PRIVMSG and NOTICE: Handle nick!user@host masks case-insensitive.
- Implement user mode 'C': If the target user of a PRIVMSG or NOTICE
command has the user mode 'C' set, it is required that both sender
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).
- 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.
- Fix both ERR_SUMMONDISABLED(445) and ERR_USERSDISABLED(446) replies.
- MODE command: correctly return ERR_UNKNOWNMODE(472) numeric for
unknown channel modes, instead of ERR_UMODEUNKNOWNFLAG(501).
- ISUPPORT(005) numeric: add "O", "R", and "z" modes to "CHANMODES",
add "EXCEPTS=e" and "INVEX=I", add "MAXLIST=beI:50".
- Limit the number of list items in the reply of LIST (100), WHO (25),
WHOIS (10), and WHOWAS (25) commands.
- LIST command: compare pattern case insensitive.
- Limit the MODE command to handle a maximum number of 5 channel modes
that require an argument (+Ibkl) per call and report this number
in the ISUPPORT(005) numeric: "MODES=5".
- Fix handling of channel mode sequence with/without arguments.
For example, don't generate wrong error messages when handling
"MODE #chan +IIIIItn *!aa@b *!bb@c *!cc@d *!dd@e *!ee@f".
- When sending data on a connection, only try to get the type of
the client if there still is one assigned. This could trigger an
assertion and end the daemon in some error paths.
- Don't try to close already closed/invalid sockets to forked child
processes. This could potentially crash the daemon in some cases
with IDENT lookups enabled.
- WHOIS command: make sure that the reply ends with RPL_ENDOFWHOIS,
don't answer queries for IRC servers, make sure mask matching is
case-insensitive, and that RPL_ENDOFWHOIS numeric is sent with the
unmodified mask (like it has been received from the client).
- LINKS command: support <mask> parameter to limit the reply.
- Add 1 second penalty for every further target on PRIVMSG/NOTICE
commands: this reduces the possibility of flooding channels with
commands like "PRIVMSG/NOTICE #a,#n,#c,... :message" a little bit.
Problem noticed by Cahata, thanks!
- Display correct error message when "Server{UID|GID}" variable in the
configuration file is invalid (not a number and no existing user).
- Update Copyright notices for 2012 :-)
- JOIN command: don't stop handling of channel lists when a single
channel cannot be joined (because of bad name, wrong key or channel
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.
- 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
user name. See "man 5 ngircd.conf" for details.
- Fixed handling of WHO commands. This fixes two bugs: "WHO <nick>"
returned nothing at all if the user was "+i" (reported by Cahata,
thanks) and "WHO <nick|nickmask>" returned channel names instead
of "*" when the user was member of a (visible) channel.
- Fixed some spelling errors in documentation and code comments
(Thanks to Christoph Biedl).
- contrib/Debian/control: Update and complete "Build-Depends" and
update our Debian package descriptions with "official" ones.
- Fixed typo in two error messages.
- LUSERS reply: only count channels that are visible to the requesting
client, so the existence of secret channels is no longer revealed by
using LUSERS. Reported by Cahata, thanks!
- Unknown user and channel modes no longer stop the mode parser, but
are simply ignored. Therefore modes after the unknown one are now
handled. This is how ircd2.10/ircd2.11/ircd-seven behave, at least.
Reported by Cahata, thanks!
- README: Update list of implemented commands.
- Log better error messages when rejecting clients.
- Implement IRC commands "GLINE" and "KLINE" to ban users. G-Lines are
synchronized between server on peering, K-Lines are local only.
If you use "*!<user>@<host>" or "*!*@<host>" masks, these connections
are blocked even before the user is fully logged in (before PASS,
NICK, and USER commands have been processed) and before the child
processes for authentication are forked, so resource usage is smaller.
- Xcode: update project file for Xcode 4.2 and define HAVE_GAI_STRERROR
for Mac OS X Xcode builds.
- ./configure: Fix logic and quoting of poll() detection code: only use
poll() when poll.h exists as well.
- Suppress 'Can't create pre-defined channel: invalid name: ""' message.
- whois-test: handle local host name = "localhost.localdomain" using the
pattern "localhost*" for valid local host names.
- sample-ngircd.conf: show correct default for "PAM" variable: The
default of "PAM" is "yes" when ngIRCd has been configured to use it,
so show the correct default value in the sample configuration file.
(Closes #119)
- Update GPL 2 license text to current version.
- Only close "unrelated" sockets in forked child processes: This fixes
the problem that ngIRCd can't do any IDENT lookups because of the
socket has already been closed in the child process.
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
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
mode "R" set) are allowed to join this channel.
- Test suite: bind to loopback (127.0.0.1) interface only.
- New 2nd message "Nickname too long" for error code 432.
- Xcode: Mac OS X config.h: support 10.5 as well as 10.6/10.7 SDK.
- Xcode: exclude more Xcode 4 specific directories in ".gitignore".
- Disconnect directly linked servers sending QUIT. Without this,
the server becomes removed from the network and the client list,
but the connection isn't shut down at all ...
- contrib/ngindent: detect "gindent" as GNU indent.
- Handle unknown user and channel modes: these modes are saved and
forwarded to other servers, but ignored otherwise.
- 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"
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.
This is required for some services to work correctly.
- Test suite: make getpid.sh work even when run as root.
- Spoofed prefixes: close connection on non-server links only.
On server-links, spoofed prefixes can happen because of the
asynchronous nature of the IRC protocol. So don't break server-
links, only log a message and ignore the command. (Closes #113)
ngIRCd Release 18 (2011-07-10)
- Update timestamp of ngircd(8) manual page.
- Add preliminary ngIRCd protocol module for Anope 1.9 to contrib/Anope/.
- Don't register WHOWAS information when "MorePrivacy" option is in effect.
ngIRCd 18~rc2 (2011-06-29)
- Update documentation, fix some wording, and use a spellchecker :-)
- ngircd.conf.5: strip "SSL" prefix from variables in [SSL] section.
- ngircd.8: document debugging options.
- GnuTLS: use 1024 bits as minimum size of the DH prime. This enables
ngIRCd to accept incoming connections from other servers and clients
that "only" use at least 1024 bits again, like ngIRCd 17 did (and no
longer requires 2048 bits for incoming connections).
ngIRCd 18~rc1 (2011-06-27)
- PAM warning message: make clear which "Password" config option is ignored.
- New configuration opion "MorePrivacy" to "censor" some user information.
When enabled, signon time and idle time is censored. Part and quit
- New configuration option "MorePrivacy" to "censor" some user information.
When enabled, signon time and idle time is left out. Part and quit
messages are made to look the same. WHOWAS requests are silently dropped.
All of this is useful if one wish to conceal users that access the ngircd
servers from TOR or I2P.
- New configuration option "ScrubCTCP" to scrub incoming CTCP commands. If
activated, the server silently drops incomming CTCP requests from both
activated, the server silently drops incoming CTCP requests from both
other servers and from users. The server that scrubs CTCP will not forward
the CTCP requests to other servers in the network either, which can spell
trouble if not every oper knows about the CTCP-scrubbing. Scrubbing CTCP
@@ -43,7 +246,7 @@ ngIRCd Release 18
would be best to just use 4096 bits, but that takes minutes, even on
current hardware ...
- contrib/platformtest.sh: fix gcc version detection.
- Avoid needlesly scary 'buffer overflow' messages: When the write buffer
- Avoid needlessly scary 'buffer overflow' messages: When the write buffer
space grows too large, ngIRCd has to disconnect the client to avoid
wasting too much memory, which is logged with a scary 'write buffer
overflow' message. Change this to a more descriptive wording.
@@ -59,8 +262,8 @@ ngIRCd Release 18
like e.g. snircd (QuakeNet) does.
- Generate WALLOPS message on SQUIT from IRC operators; so SQUIT now behaves
like CONNECT and DISCONNECT commands, when called by an IRC operator.
- Allow servers to send more commands in the first 10 secods ("burst"). This
helps to speed up server login and network synchronisation.
- Allow servers to send more commands in the first 10 seconds ("burst"). This
helps to speed up server login and network synchronization.
- Add support for up to 3 targets in WHOIS queries, also allow up to one
wildcard query from local hosts. Follows ircd 2.10 implementation rather
than RFC 2812. At most 10 entries are returned per wildcard expansion.
@@ -69,8 +272,8 @@ ngIRCd Release 18
variable description.
- Don't use "the.net" in sample-ngircd.conf, use "example.net".
- Terminate incoming connections on HTTP commands "GET" and "POST".
- New configuration option "CloakHost": when set, this hostname is used for
every client instead of the real DNS hostname (or IP address).
- 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
supplied by the IRC client.
@@ -83,7 +286,7 @@ ngIRCd Release 18
- Don't access possibly free'd CLIENT structure. Ooops.
- Allow "Port = 0" in [Server] blocks. Port number 0 marks remote servers
that try to connect to this daemon, but where this daemon never tries to
establis a connection on its own: only incoming connections are allowed.
establish a connection on its own: only incoming connections are allowed.
- Configuration: fix 'Value of "..." is not a number!' for negative values.
- Enable WHOIS command to return information about services.
- Implement channel mode 'O': "IRC operators only". This channel mode is
@@ -100,9 +303,9 @@ ngIRCd Release 18
in [Global] are still accepted, so there is no functional change.
- Fix confusing "adding to invite list" debug messages: adding entries to
ban list produced 'invite list' debug output ...
- Don't throttle services and servers beeing registered.
- Don't throttle services and servers being registered.
- Xcode: correctly sort files :-)
- Don't assert() when serching a client for an invalid server token (this is
- Don't assert() when searching a client for an invalid server token (this is
only relevant when a trusted server on a server-server link sends invalid
commands).
@@ -113,7 +316,7 @@ ngIRCd Release 17.1 (2010-12-19)
- Reset ID of outgoing server link on DNS error correctly
- Don't log critical (or worse) messages to stderr
- Manual page ngircd(8): add SIGNALS section
- Manual pages: update and simplyfy AUTHORS section
- Manual pages: update and simplify AUTHORS section
- Remove "error file" when compiled with debug code enabled
- README: Updated list of implemented commands
- add doc/README-Interix.txt and doc/Bopm.txt to distribution tarball
@@ -175,7 +378,7 @@ ngIRCd Release 17 (2010-11-07)
- configure script: correctly indent IPv6 yes/no summary output.
- Don't reset My_Connections[Idx].lastping when reading data, so the
client lag debug-output is working again.
- Implement user mode "x": hostname cloaking (closes: #102).
- Implement user mode "x": host name cloaking (closes: #102).
- Make configure switch "--docdir" work (closes: #108).
- Reformat and update FAQ.txt a little bit.
- INSTALL: mention SSL, IPv6, and changed handling of MotdFile.
@@ -280,7 +483,7 @@ ngIRCd Release 14.1 (2009-05-05)
- Allow ping timeout quit messages to show the timeout value.
- Fix error handling on compressed links.
- Fix server list announcement.
- Do not remove hostnames from info text.
- Do not remove host names from info text.
ngIRCd Release 14 (2009-04-20)
@@ -376,7 +579,7 @@ ngIRCd 0.12.0 (2008-05-13)
- RPL_WHOREPLY messages generated by IRC_WHO didn't include flags (*,@,+).
(Dana Dahlstrom)
- IRC_WHO now supports search patterns and will test this against user
nickname/servername/hostname, etc. as required by RFC 2812, Section 3.6.1.
nickname/server name/host name, etc. as required by RFC 2812, Section 3.6.1.
(reported by Dana Dahlstrom)
- Add test cases for "WHO" command. (Dana Dahlstrom)
- Implement RFC 2812 handling of "0" argument to 'JOIN': must be treated
@@ -399,7 +602,7 @@ ngIRCd 0.11.0 (2008-01-15)
ngircd to crash [from HEAD]. (CVE-2008-0285)
ngIRCd 0.11.0-pre1 (2008-01-02)
- Use dotted-decimal IP address if hostname is >= 64.
- Use dotted-decimal IP address if host name is >= 64.
- Add support for /STAT u (server uptime) command.
- New [Server] configuration Option "Bind" allows to specify
the source IP address to use when connecting to remote server.
@@ -625,7 +828,7 @@ ngIRCd 0.8.0 (2004-06-26)
original ircd exactly: the unnecessary but missing ":" before the last
parameter has been added.
- Fixed TRACE: don't output "Serv" lines for ourself; display more info.
- Results of the resolver (hostnames and IDENT names) are discarded after
- Results of the resolver (host names and IDENT names) are discarded after
the client is successfully registered with the server.
- Better logging while establishing and shutting down connections.
- The type of service (TOS) of all sockets is set to "interactive" now.
@@ -784,7 +987,7 @@ ngIRCd 0.6.0, 2002-12-24
werden (beide Server versuchen sich dann gegenseitig zu connectieren).
- Test-Suite und Dokumentation an A/UX angepasst.
- unter HP-UX definiert das configure-Script nun _XOPEN_SOURCE_EXTENDED.
- Server identifizieren sich nun mit asyncronen Passwoertern, d.h. das
- Server identifizieren sich nun mit asynchronen Passwoertern, d.h. das
Passwort, welches A an B schickt, kann ein anderes sein als das, welches
B als Antwort an A sendet. In der Konfig.-Datei, Abschnitt "Server",
wurde "Password" dazu durch "MyPassword" und "PeerPassword" ersetzt.
@@ -914,7 +1117,7 @@ ngIRCd 0.5.0, 20.09.2002
- Protokoll- und Server-ID bei PASS-Befehlen auf neues Format umgestellt;
bei empfangenen PASS-Befehlen werden diese zudem nun auch ausgewertet.
Die unterstuetzten Flags sind in doc/Protocol.txt beschrieben.
- mit dem neuen Befehl CHANINFO syncronisieren Server, die das IRC+-
- mit dem neuen Befehl CHANINFO synchronisieren Server, die das IRC+-
Protokoll unterstuetzen, Channel-Modes und Topics.
- neue Option "--disable-ircplus" fuer das configure-Script, um das
IRC+-Protokoll abzuschalten (per Default ist es aktiviert).
@@ -1019,7 +1222,7 @@ ngIRCd 0.3.0, 02.03.2002
- PRIVMSG beachtet nun die Channel-Modes "n" und "m".
- AWAY implementiert. PRIVMSG, MODE, USERHOST und WHOIS angepasst.
- der ngIRCd unterstuetzt nun Channel-Topics (TOPIC-Befehl).
- ausgehende Server-Verbindungen werden nun asyncron connectiert und
- ausgehende Server-Verbindungen werden nun asynchron connectiert und
blockieren nicht mehr den ganzen Server, wenn die Gegenseite nicht
erreicht werden kann (bis zum Timeout konnten Minuten vergehen!).
- Wert der Konfigurations-Variable "ConnectRetry" wird besser beachtet.
@@ -1098,7 +1301,7 @@ ngIRCd 0.0.2, 06.01.2002
- NICK kann nun die Gross- und Kleinschreibung eines Nicks aendern.
- ein Server-Passwort ist nun konfigurierbar.
- neue Befehle: ERROR, SERVER, NJOIN (nur als "Fake"), SQUIT.
- Asyncroner Resolver Hostname->IP implementiert.
- Asynchroner Resolver Hostname->IP implementiert.
- Server-Links teilweise implementiert: bisher kann der ngIRCd jedoch
nur "leafed server" sein, d.h. keine "Client-Server" haben. Einige
Befehle sind auch noch nicht (optimal) angepasst: PRIVMSG funktioniert

31
INSTALL
View File

@@ -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.
@@ -93,7 +93,8 @@ automake ("configure") should be no problem.
The normal installation procedure after getting (and expanding) the source
files (using a distribution archive or GIT) is as following:
1) ./autogen.sh [only necessary when using GIT]
0) Satisfy prerequisites
1) ./autogen.sh [only necessary when using GIT]
2) ./configure
3) make
4) make install
@@ -114,6 +115,30 @@ possible options will be installed there. You'll find its template in the
doc/ directory: sample-ngircd.conf.
0): Satisfy prerequisites
When building from source, you'll need some other software to build ngIRCd:
for example a working C compiler, make tool, GNU automake and autoconf (only
when not using a distribution archive), and a few libraries depending on the
features you want to compile in (like IDENT support, SSL, and PAM).
If you are using one of the "big" operating systems or Linux distributions,
you can use the following commands to install all the required packages to
build the sources including all optional features and to run the test suite:
* RedHat / Fedora based distributions:
yum install \
autoconf automake expect gcc glibc-devel gnutls-devel \
libident-devel make pam-devel tcp_wrappers-devel telnet zlib-devel
* Debian / Ubuntu based distributions:
apt-get install \
autoconf automake build-essential expect libgnutls-dev \
libident-dev libpam-dev libwrap0-dev libz-dev telnet
1): "autogen.sh"
The first step, autogen.sh, is only necessary if the configure-script isn't
@@ -134,7 +159,7 @@ Again: "end users" do not need this step!
The configure-script is used to detect local system dependencies.
In the perfect case, configure should recognise all needed libraries, header
In the perfect case, configure should recognize all needed libraries, header
files and so on. If this shouldn't work, "./configure --help" shows all
possible options.

124
NEWS
View File

@@ -2,22 +2,116 @@
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.
-- NEWS --
ngIRCd Release 18
ngIRCd Release 19.2 (2012-06-19)
ngIRCd 19.2~rc1 (2012-06-13)
- New configuration option "CloakHostModeX" to configure the hostname
that gets used for IRC clients which have user mode "+x" enabled.
Up to now, the name of the IRC server itself has been used for this,
which still is the default when "CloakHostModeX" isn't set.
- Add instructions for setting up Atheme IRC services.
- Implement support for IRC capability handling, the new "CAP" command,
and capablity "multi-prefix" which allows both the NAME and WHO command
handlers to return more than one "class prefix" to the client.
ngIRCd Release 19.1 (2012-03-19)
- Really include _all_ patches to build the Anope module into the
distribution archive ... ooops!
ngIRCd Release 19 (2012-02-29)
ngIRCd 19~rc1 (2012-02-12)
- Update preliminary ngIRCd protocol module for Anope 1.9.6, which now
is the only supported version.
- New numeric RPL_WHOISHOST_MSG(378), which returns the DNS host name
(if available) and the IP address of a client in the WHOIS reply.
Only the user itself and local IRC operators get this numeric.
- Implement channel exception list (mode 'e'). This allows a channel
operator to define exception masks that allow users to join the
channel even when a "ban" would match and prevent them from joining:
the exception list (e) overrides the ban list (b).
- Implement user mode 'C': If the target user of a PRIVMSG or NOTICE
command has the user mode 'C' set, it is required that both sender
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).
- 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.
- Limit the number of list items in the reply of LIST (100), WHO (25),
WHOIS (10), and WHOWAS (25) commands.
- Limit the MODE command to handle a maximum number of 5 channel modes
that require an argument (+Ibkl) per call and report this number
in the ISUPPORT(005) numeric: "MODES=5".
- LINKS command: support <mask> parameter to limit the reply.
- Add 1 second penalty for every further target on PRIVMSG/NOTICE
commands: this reduces the possibility of flooding channels with
commands like "PRIVMSG/NOTICE #a,#n,#c,... :message" a little bit.
Problem noticed by Cahata, thanks!
- 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
user name. See "man 5 ngircd.conf" for details.
- Fixed handling of WHO commands. This fixes two bugs: "WHO <nick>"
returned nothing at all if the user was "+i" (reported by Cahata,
thanks) and "WHO <nick|nickmask>" returned channel names instead
of "*" when the user was member of a (visible) channel.
- LUSERS reply: only count channels that are visible to the requesting
client, so the existence of secret channels is no longer revealed by
using LUSERS. Reported by Cahata, thanks!
- Unknown user and channel modes no longer stop the mode parser, but
are simply ignored. Therefore modes after the unknown one are now
handled. This is how ircd2.10/ircd2.11/ircd-seven behave, at least.
Reported by Cahata, thanks!
- Implement IRC commands "GLINE" and "KLINE" to ban users. G-Lines are
synchronized between server on peering, K-Lines are local only.
If you use "*!<user>@<host>" or "*!*@<host>" masks, these connections
are blocked even before the user is fully logged in (before PASS,
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
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
mode "R" set) are allowed to join this channel.
- Test suite: bind to loopback (127.0.0.1) interface only.
- Handle unknown user and channel modes: these modes are saved and
forwarded to other servers, but ignored otherwise.
- 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"
argument. Like unknown user and channel modes, these modes are saved
and forwarded to other servers, but ignored otherwise.
ngIRCd Release 18 (2011-07-10)
- Add preliminary ngIRCd protocol module for Anope 1.9 to contrib/Anope/.
ngIRCd 18~rc2 (2011-06-29)
- GnuTLS: use 1024 bits as minimum size of the DH prime. This enables
ngIRCd to accept incoming connections from other servers and clients
that "only" use at least 1024 bits again, like ngIRCd 17 did (and no
longer requires 2048 bits for incoming connections).
ngIRCd 18~rc1 (2011-06-27)
- New configuration opion "MorePrivacy" to "censor" some user information.
When enabled, signon time and idle time is censored. Part and quit
- New configuration option "MorePrivacy" to "censor" some user information.
When enabled, signon time and idle time is left out. Part and quit
messages are made to look the same. WHOWAS requests are silently dropped.
All of this is useful if one wish to conceal users that access the ngircd
servers from TOR or I2P.
- New configuration option "ScrubCTCP" to scrub incoming CTCP commands. If
activated, the server silently drops incomming CTCP requests from both
activated, the server silently drops incoming CTCP requests from both
other servers and from users. The server that scrubs CTCP will not forward
the CTCP requests to other servers in the network either, which can spell
trouble if not every oper knows about the CTCP-scrubbing. Scrubbing CTCP
@@ -34,7 +128,7 @@ ngIRCd Release 18
the [Global] section are deprecated now, but are still recognized.
=> Don't forget to check your configuration, use "ngircd --configtest"!
- New documentation "how to contribute": doc/Contributing.txt.
- Avoid needlesly scary 'buffer overflow' messages: When the write buffer
- Avoid needlessly scary 'buffer overflow' messages: When the write buffer
space grows too large, ngIRCd has to disconnect the client to avoid
wasting too much memory, which is logged with a scary 'write buffer
overflow' message. Change this to a more descriptive wording.
@@ -52,8 +146,8 @@ ngIRCd Release 18
(booleans, text strings, integer numbers) and add type information to each
variable description.
- Terminate incoming connections on HTTP commands "GET" and "POST".
- New configuration option "CloakHost": when set, this hostname is used for
every client instead of the real DNS hostname (or IP address).
- 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
supplied by the IRC client.
@@ -63,7 +157,7 @@ ngIRCd Release 18
the moment. This enhances reliability on slow links.
- Allow "Port = 0" in [Server] blocks. Port number 0 marks remote servers
that try to connect to this daemon, but where this daemon never tries to
establis a connection on its own: only incoming connections are allowed.
establish a connection on its own: only incoming connections are allowed.
- Enable WHOIS command to return information about services.
- Implement channel mode 'O': "IRC operators only". This channel mode is
used on DALnet (bahamut), for example.
@@ -105,7 +199,7 @@ ngIRCd Release 17 (2010-11-07)
- Enable the daemon to disable and enable "debug mode" on runtime using
signal SIGUSR1, when debug code is compiled in, not only on startup
using the command line parameters.
- Implement user mode "x": hostname cloaking (closes: #102).
- Implement user mode "x": host name cloaking (closes: #102).
- Change MOTD file handling: ngIRCd now caches the contens of the MOTD
file, so the daemon now requires a HUP signal or REHASH command to
re-read the MOTD file when its content changed.
@@ -210,7 +304,7 @@ ngIRCd 0.12.0 (2008-05-13)
- Implemented IRC commands INFO, SUMMON (dummy), and USERS (dummy) and
enhanced test suite to check these commands. (Dana Dahlstrom)
- IRC_WHO now supports search patterns and will test this against user
nickname/servername/hostname, etc. as required by RFC 2812, Section 3.6.1.
nickname/server name/host name, etc. as required by RFC 2812, Section 3.6.1.
(reported by Dana Dahlstrom)
- Implement RFC 2812 handling of "0" argument to 'JOIN': must be treated
as if the user had sent PART commands for all channels the user is a
@@ -343,7 +437,7 @@ ngIRCd 0.6.0, 2002-12-24
ausgehende Verbindung zu diesem auufzubauen. Dadurch kann nun auf beiden
Servern in der Konfiguration ein Port fuer den Connect konfiguriert
werden (beide Server versuchen sich dann gegenseitig zu connectieren).
- Server identifizieren sich nun mit asyncronen Passwoertern, d.h. das
- Server identifizieren sich nun mit asynchronen Passwoertern, d.h. das
Passwort, welches A an B schickt, kann ein anderes sein als das, welches
B als Antwort an A sendet. In der Konfig.-Datei, Abschnitt "Server",
wurde "Password" dazu durch "MyPassword" und "PeerPassword" ersetzt.
@@ -369,7 +463,7 @@ ngIRCd 0.5.0, 20.09.2002
Konfiguration "sample-ngircd.conf") und bleiben auch dann bestehen,
wenn kein User mehr im Channel ist.
- neue IRC-Befehle: KICK, INVITE, ADMIN, CHANINFO; LIST wurde erweitert.
Mit dem neuen Befehl CHANINFO syncronisieren Server, die das IRC+-
Mit dem neuen Befehl CHANINFO synchronisieren Server, die das IRC+-
Protokoll unterstuetzen, Channel-Modes und Topics. Fuer den ADMIN-Befehl
gibt es neue Konfigurationsoptionen (Sektion "Global"): "AdminInfo1",
"AdminInfo2" und "AdminEMail".
@@ -455,7 +549,3 @@ ngIRCd 0.0.2, 06.01.2002
ngIRCd 0.0.1, 31.12.2001
- erste oeffentliche Version von ngIRCd als "public preview" :-)
--
$Id: NEWS,v 1.88 2008/02/26 22:05:42 fw Exp $

38
README
View File

@@ -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.
@@ -14,9 +14,10 @@ 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 (URL: http://www.gnu.org/licenses/gpl.html). ngIRCd means "next
generation IRC daemon", it's written from scratch and not deduced from the
"grandfather of IRC daemons", the daemon of the IRCNet.
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.
Please see the INSTALL document for installation and upgrade information!
@@ -33,22 +34,24 @@ used in real IRC networks.
Implemented IRC-commands are:
ADMIN, AWAY, CHANINFO, CONNECT, DIE, DISCONNECT, ERROR, HELP, INFO, INVITE,
ISON, JOIN, KICK, KILL, LINKS, LIST, LUSERS, MODE, MOTD, NAMES, NICK, NJOIN,
NOTICE, OPER, PART, PASS, PING, PONG, PRIVMSG, QUIT, REHASH, RESTART, SERVER,
SERVICE, SERVLIST, SQUERY, SQUIT, STATS, SUMMON, TIME, TOPIC, TRACE, USER,
USERHOST, USERS, VERSION, WALLOPS, WEBIRC, WHO, WHOIS, WHOWAS.
ADMIN, AWAY, CHANINFO, CONNECT, DIE, DISCONNECT, ERROR, GLINE, HELP, INFO,
INVITE, ISON, JOIN, KICK, KILL, KLINE, LINKS, LIST, LUSERS, MODE, MOTD,
NAMES, NICK, NJOIN, NOTICE, OPER, PART, PASS, PING, PONG, PRIVMSG, QUIT,
REHASH, RESTART, SERVER, SERVICE, SERVLIST, SQUERY, SQUIT, STATS, SUMMON,
TIME, TOPIC, TRACE, USER, USERHOST, USERS, VERSION, WALLOPS, WEBIRC, WHO,
WHOIS, WHOWAS.
III. Features (or: why use ngIRCd?)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- no problems with servers which have dynamic IP addresses
- simple, easy understandable configuration file,
- freely published open-source C source code,
- ngIRCd will be developed on in the future.
- well arranged (lean) configuration file
- simple to build/install, configure and maintain
- supports IPv6 and SSL
- no problems with servers that have dynamic IP addresses
- freely available, modern, portable and tidy C-source
- wide field of supported platforms, including AIX, A/UX, FreeBSD, HP-UX,
IRIX, Linux, Mac OS X, NetBSD, OpenBSD, Solaris, and Windows with Cygwin.
- ngIRCd is being actively developed since 2001.
IV. Documentation
@@ -68,7 +71,7 @@ releases there.
If you are interested in the latest development versions (which are not
always stable), then please read the section about "GIT" on the homepage and
the file "doc/GIT.txt" which describes the use of GIT, the version control
system used by ngIRCd (homepage: http://git.or.cz/).
system used by ngIRCd (homepage: http://git-scm.com/).
VI. Bugs
@@ -82,5 +85,6 @@ them at the following URL:
There you can read about known bugs and limitations, too.
If you have critics, patches or something else, please feel free to post a
mail to the ngIRCd mailing list: <ngircd-ml@arthur.ath.cx> (please see
<http://ngircd.barton.de/support.php#ml> for details).
mail to the ngIRCd mailing list: <ngircd-ml@arthur.barton.de> (please see
<http://ngircd.barton.de/support.php#ml> for details) or join the ngIRCd
IRC channel: <irc://irc.barton.de/ngircd>.

546
config.guess vendored
View File

@@ -1,10 +1,10 @@
#! /bin/sh
# Attempt to guess a canonical system name.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
# Free Software Foundation, Inc.
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012 Free Software Foundation, Inc.
timestamp='2008-01-23'
timestamp='2012-02-10'
# 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
@@ -17,9 +17,7 @@ timestamp='2008-01-23'
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program; if not, see <http://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@@ -27,16 +25,16 @@ timestamp='2008-01-23'
# the same distribution terms that you use for the rest of that program.
# Originally written by Per Bothner <per@bothner.com>.
# Please send patches to <config-patches@gnu.org>. Submit a context
# diff and a properly formatted ChangeLog entry.
# Originally written by Per Bothner. Please send patches (context
# diff format) to <config-patches@gnu.org> and include a ChangeLog
# entry.
#
# This script attempts to guess a canonical system name similar to
# config.sub. If it succeeds, it prints the system name on stdout, and
# exits with 0. Otherwise, it exits with 1.
#
# The plan is that this can be called by configure scripts if you
# don't specify an explicit build system type.
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD
me=`echo "$0" | sed -e 's,.*/,,'`
@@ -56,8 +54,9 @@ version="\
GNU config.guess ($timestamp)
Originally written by Per Bothner.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -144,7 +143,7 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
*:NetBSD:*:*)
# NetBSD (nbsd) targets should (where applicable) match one or
# more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*,
# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
# *-*-netbsdecoff* and *-*-netbsd*. For targets that recently
# switched to ELF, *-*-netbsd* would select the old
# object file format. This provides both forward
@@ -170,7 +169,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
arm*|i386|m68k|ns32k|sh3*|sparc|vax)
eval $set_cc_for_build
if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep __ELF__ >/dev/null
| grep -q __ELF__
then
# Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
# Return netbsd for either. FIX?
@@ -180,7 +179,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
fi
;;
*)
os=netbsd
os=netbsd
;;
esac
# The OS release
@@ -223,7 +222,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
;;
*5.*)
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
;;
esac
# According to Compaq, /usr/sbin/psrinfo has been available on
@@ -269,7 +268,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# A Xn.n version is an unreleased experimental baselevel.
# 1.2 uses "1.2" for uname -r.
echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
exit ;;
# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
exitcode=$?
trap '' 0
exit $exitcode ;;
Alpha\ *:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# Should we change UNAME_MACHINE based on the output of uname instead
@@ -295,7 +297,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
echo s390-ibm-zvmoe
exit ;;
*:OS400:*:*)
echo powerpc-ibm-os400
echo powerpc-ibm-os400
exit ;;
arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
echo arm-acorn-riscix${UNAME_RELEASE}
@@ -324,14 +326,33 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
case `/usr/bin/uname -p` in
sparc) echo sparc-icl-nx7; exit ;;
esac ;;
s390x:SunOS:*:*)
echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4H:SunOS:5.*:*)
echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
echo i386-pc-auroraux${UNAME_RELEASE}
exit ;;
i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
eval $set_cc_for_build
SUN_ARCH="i386"
# If there is a compiler, see if it is configured for 64-bit objects.
# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
# This test works for both compilers.
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
SUN_ARCH="x86_64"
fi
fi
echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
exit ;;
sun4*:SunOS:6*:*)
# According to config.sub, this is the proper way to canonicalize
@@ -375,23 +396,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
# MiNT. But MiNT is downward compatible to TOS, so this should
# be no problem.
atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
exit ;;
*falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
echo m68k-atari-mint${UNAME_RELEASE}
echo m68k-atari-mint${UNAME_RELEASE}
exit ;;
milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
echo m68k-milan-mint${UNAME_RELEASE}
exit ;;
echo m68k-milan-mint${UNAME_RELEASE}
exit ;;
hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
echo m68k-hades-mint${UNAME_RELEASE}
exit ;;
echo m68k-hades-mint${UNAME_RELEASE}
exit ;;
*:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
echo m68k-unknown-mint${UNAME_RELEASE}
exit ;;
echo m68k-unknown-mint${UNAME_RELEASE}
exit ;;
m68k:machten:*:*)
echo m68k-apple-machten${UNAME_RELEASE}
exit ;;
@@ -461,8 +482,8 @@ EOF
echo m88k-motorola-sysv3
exit ;;
AViiON:dgux:*:*)
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
# DG/UX returns AViiON for all architectures
UNAME_PROCESSOR=`/usr/bin/uname -p`
if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
then
if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
@@ -475,7 +496,7 @@ EOF
else
echo i586-dg-dgux${UNAME_RELEASE}
fi
exit ;;
exit ;;
M88*:DolphinOS:*:*) # DolphinOS (SVR3)
echo m88k-dolphin-sysv3
exit ;;
@@ -532,7 +553,7 @@ EOF
echo rs6000-ibm-aix3.2
fi
exit ;;
*:AIX:*:[456])
*:AIX:*:[4567])
IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
IBM_ARCH=rs6000
@@ -575,52 +596,52 @@ EOF
9000/[678][0-9][0-9])
if [ -x /usr/bin/getconf ]; then
sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
case "${sc_cpu_version}" in
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
case "${sc_kernel_bits}" in
32) HP_ARCH="hppa2.0n" ;;
64) HP_ARCH="hppa2.0w" ;;
sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
case "${sc_cpu_version}" in
523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0
528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1
532) # CPU_PA_RISC2_0
case "${sc_kernel_bits}" in
32) HP_ARCH="hppa2.0n" ;;
64) HP_ARCH="hppa2.0w" ;;
'') HP_ARCH="hppa2.0" ;; # HP-UX 10.20
esac ;;
esac
esac ;;
esac
fi
if [ "${HP_ARCH}" = "" ]; then
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
sed 's/^ //' << EOF >$dummy.c
#define _HPUX_SOURCE
#include <stdlib.h>
#include <unistd.h>
#define _HPUX_SOURCE
#include <stdlib.h>
#include <unistd.h>
int main ()
{
#if defined(_SC_KERNEL_BITS)
long bits = sysconf(_SC_KERNEL_BITS);
#endif
long cpu = sysconf (_SC_CPU_VERSION);
int main ()
{
#if defined(_SC_KERNEL_BITS)
long bits = sysconf(_SC_KERNEL_BITS);
#endif
long cpu = sysconf (_SC_CPU_VERSION);
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
case CPU_PA_RISC2_0:
#if defined(_SC_KERNEL_BITS)
switch (bits)
{
case 64: puts ("hppa2.0w"); break;
case 32: puts ("hppa2.0n"); break;
default: puts ("hppa2.0"); break;
} break;
#else /* !defined(_SC_KERNEL_BITS) */
puts ("hppa2.0"); break;
#endif
default: puts ("hppa1.0"); break;
}
exit (0);
}
switch (cpu)
{
case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
case CPU_PA_RISC2_0:
#if defined(_SC_KERNEL_BITS)
switch (bits)
{
case 64: puts ("hppa2.0w"); break;
case 32: puts ("hppa2.0n"); break;
default: puts ("hppa2.0"); break;
} break;
#else /* !defined(_SC_KERNEL_BITS) */
puts ("hppa2.0"); break;
#endif
default: puts ("hppa1.0"); break;
}
exit (0);
}
EOF
(CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
test -z "$HP_ARCH" && HP_ARCH=hppa
@@ -640,7 +661,7 @@ EOF
# => hppa64-hp-hpux11.23
if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) |
grep __LP64__ >/dev/null
grep -q __LP64__
then
HP_ARCH="hppa2.0w"
else
@@ -711,22 +732,22 @@ EOF
exit ;;
C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
echo c1-convex-bsd
exit ;;
exit ;;
C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
if getsysinfo -f scalar_acc
then echo c32-convex-bsd
else echo c2-convex-bsd
fi
exit ;;
exit ;;
C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
echo c34-convex-bsd
exit ;;
exit ;;
C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
echo c38-convex-bsd
exit ;;
exit ;;
C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
echo c4-convex-bsd
exit ;;
exit ;;
CRAY*Y-MP:*:*:*)
echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
exit ;;
@@ -750,14 +771,14 @@ EOF
exit ;;
F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'`
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
5000:UNIX_System_V:4.*:*)
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'`
FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'`
echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
exit ;;
i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
@@ -769,13 +790,12 @@ EOF
echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
exit ;;
*:FreeBSD:*:*)
case ${UNAME_MACHINE} in
pc98)
echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
UNAME_PROCESSOR=`/usr/bin/uname -p`
case ${UNAME_PROCESSOR} in
amd64)
echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
*)
echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
esac
exit ;;
i*:CYGWIN*:*)
@@ -784,19 +804,22 @@ EOF
*:MINGW*:*)
echo ${UNAME_MACHINE}-pc-mingw32
exit ;;
i*:MSYS*:*)
echo ${UNAME_MACHINE}-pc-msys
exit ;;
i*:windows32*:*)
# uname -m includes "-pc" on this system.
echo ${UNAME_MACHINE}-mingw32
# uname -m includes "-pc" on this system.
echo ${UNAME_MACHINE}-mingw32
exit ;;
i*:PW*:*)
echo ${UNAME_MACHINE}-pc-pw32
exit ;;
*:Interix*:[3456]*)
case ${UNAME_MACHINE} in
*:Interix*:*)
case ${UNAME_MACHINE} in
x86)
echo i586-pc-interix${UNAME_RELEASE}
exit ;;
EM64T | authenticamd)
authenticamd | genuineintel | EM64T)
echo x86_64-unknown-interix${UNAME_RELEASE}
exit ;;
IA64)
@@ -806,6 +829,9 @@ EOF
[345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
echo i${UNAME_MACHINE}-pc-mks
exit ;;
8664:Windows_NT:*)
echo x86_64-pc-mks
exit ;;
i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
# How do we know it's Interix rather than the generic POSIX subsystem?
# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
@@ -835,92 +861,13 @@ EOF
i*86:Minix:*:*)
echo ${UNAME_MACHINE}-pc-minix
exit ;;
arm*:Linux:*:*)
eval $set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
echo ${UNAME_MACHINE}-unknown-linux-gnu
else
echo ${UNAME_MACHINE}-unknown-linux-gnueabi
fi
exit ;;
avr32*:Linux:*:*)
aarch64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
cris:Linux:*:*)
echo cris-axis-linux-gnu
exit ;;
crisv32:Linux:*:*)
echo crisv32-axis-linux-gnu
exit ;;
frv:Linux:*:*)
echo frv-unknown-linux-gnu
exit ;;
ia64:Linux:*:*)
aarch64_be:Linux:*:*)
UNAME_MACHINE=aarch64_be
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
m32r*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
m68*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
mips:Linux:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#undef CPU
#undef mips
#undef mipsel
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
CPU=mipsel
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
CPU=mips
#else
CPU=
#endif
#endif
EOF
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
/^CPU/{
s: ::g
p
}'`"
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
;;
mips64:Linux:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#undef CPU
#undef mips64
#undef mips64el
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
CPU=mips64el
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
CPU=mips64
#else
CPU=
#endif
#endif
EOF
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
/^CPU/{
s: ::g
p
}'`"
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
;;
or32:Linux:*:*)
echo or32-unknown-linux-gnu
exit ;;
ppc:Linux:*:*)
echo powerpc-unknown-linux-gnu
exit ;;
ppc64:Linux:*:*)
echo powerpc64-unknown-linux-gnu
exit ;;
alpha:Linux:*:*)
case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
EV5) UNAME_MACHINE=alphaev5 ;;
@@ -930,11 +877,90 @@ EOF
EV6) UNAME_MACHINE=alphaev6 ;;
EV67) UNAME_MACHINE=alphaev67 ;;
EV68*) UNAME_MACHINE=alphaev68 ;;
esac
objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null
esac
objdump --private-headers /bin/sh | grep -q ld.so.1
if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi
echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC}
exit ;;
arm*:Linux:*:*)
eval $set_cc_for_build
if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_EABI__
then
echo ${UNAME_MACHINE}-unknown-linux-gnu
else
if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
| grep -q __ARM_PCS_VFP
then
echo ${UNAME_MACHINE}-unknown-linux-gnueabi
else
echo ${UNAME_MACHINE}-unknown-linux-gnueabihf
fi
fi
exit ;;
avr32*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
cris:Linux:*:*)
echo ${UNAME_MACHINE}-axis-linux-gnu
exit ;;
crisv32:Linux:*:*)
echo ${UNAME_MACHINE}-axis-linux-gnu
exit ;;
frv:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
hexagon:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
i*86:Linux:*:*)
LIBC=gnu
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#ifdef __dietlibc__
LIBC=dietlibc
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'`
echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
exit ;;
ia64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
m32r*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
m68*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
mips:Linux:*:* | mips64:Linux:*:*)
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#undef CPU
#undef ${UNAME_MACHINE}
#undef ${UNAME_MACHINE}el
#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
CPU=${UNAME_MACHINE}el
#else
#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
CPU=${UNAME_MACHINE}
#else
CPU=
#endif
#endif
EOF
eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; }
;;
or32:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
padre:Linux:*:*)
echo sparc-unknown-linux-gnu
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
echo hppa64-unknown-linux-gnu
exit ;;
parisc:Linux:*:* | hppa:Linux:*:*)
# Look for CPU level
case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
@@ -943,14 +969,17 @@ EOF
*) echo hppa-unknown-linux-gnu ;;
esac
exit ;;
parisc64:Linux:*:* | hppa64:Linux:*:*)
echo hppa64-unknown-linux-gnu
ppc64:Linux:*:*)
echo powerpc64-unknown-linux-gnu
exit ;;
ppc:Linux:*:*)
echo powerpc-unknown-linux-gnu
exit ;;
s390:Linux:*:* | s390x:Linux:*:*)
echo ${UNAME_MACHINE}-ibm-linux
exit ;;
sh64*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
sh*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
@@ -958,78 +987,18 @@ EOF
sparc:Linux:*:* | sparc64:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
tile*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
vax:Linux:*:*)
echo ${UNAME_MACHINE}-dec-linux-gnu
exit ;;
x86_64:Linux:*:*)
echo x86_64-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
xtensa*:Linux:*:*)
echo ${UNAME_MACHINE}-unknown-linux-gnu
echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
i*86:Linux:*:*)
# The BFD linker knows what the default object file format is, so
# first see if it will tell us. cd to the root directory to prevent
# problems with other programs or directories called `ld' in the path.
# Set LC_ALL=C to ensure ld outputs messages in English.
ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \
| sed -ne '/supported targets:/!d
s/[ ][ ]*/ /g
s/.*supported targets: *//
s/ .*//
p'`
case "$ld_supported_targets" in
elf32-i386)
TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu"
;;
a.out-i386-linux)
echo "${UNAME_MACHINE}-pc-linux-gnuaout"
exit ;;
coff-i386)
echo "${UNAME_MACHINE}-pc-linux-gnucoff"
exit ;;
"")
# Either a pre-BFD a.out linker (linux-gnuoldld) or
# one that does not give us useful --help.
echo "${UNAME_MACHINE}-pc-linux-gnuoldld"
exit ;;
esac
# Determine whether the default compiler is a.out or elf
eval $set_cc_for_build
sed 's/^ //' << EOF >$dummy.c
#include <features.h>
#ifdef __ELF__
# ifdef __GLIBC__
# if __GLIBC__ >= 2
LIBC=gnu
# else
LIBC=gnulibc1
# endif
# else
LIBC=gnulibc1
# endif
#else
#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
LIBC=gnu
#else
LIBC=gnuaout
#endif
#endif
#ifdef __dietlibc__
LIBC=dietlibc
#endif
EOF
eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n '
/^LIBC/{
s: ::g
p
}'`"
test x"${LIBC}" != x && {
echo "${UNAME_MACHINE}-pc-linux-${LIBC}"
exit
}
test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; }
;;
i*86:DYNIX/ptx:4*:*)
# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
# earlier versions are messed up and put the nodename in both
@@ -1037,11 +1006,11 @@ EOF
echo i386-sequent-sysv4
exit ;;
i*86:UNIX_SV:4.2MP:2.*)
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I am not positive that other SVR4 systems won't match this,
# Unixware is an offshoot of SVR4, but it has its own version
# number series starting with 2...
# I am not positive that other SVR4 systems won't match this,
# I just have to hope. -- rms.
# Use sysv4.2uw... so that sysv4* matches it.
# Use sysv4.2uw... so that sysv4* matches it.
echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
exit ;;
i*86:OS/2:*:*)
@@ -1058,7 +1027,7 @@ EOF
i*86:syllable:*:*)
echo ${UNAME_MACHINE}-pc-syllable
exit ;;
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*)
i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
echo i386-unknown-lynxos${UNAME_RELEASE}
exit ;;
i*86:*DOS:*:*)
@@ -1073,7 +1042,7 @@ EOF
fi
exit ;;
i*86:*:5:[678]*)
# UnixWare 7.x, OpenUNIX and OpenServer 6.
# UnixWare 7.x, OpenUNIX and OpenServer 6.
case `/bin/uname -X | grep "^Machine"` in
*486*) UNAME_MACHINE=i486 ;;
*Pentium) UNAME_MACHINE=i586 ;;
@@ -1101,10 +1070,13 @@ EOF
exit ;;
pc:*:*:*)
# Left here for compatibility:
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i386.
echo i386-pc-msdosdjgpp
exit ;;
# uname -m prints for DJGPP always 'pc', but it prints nothing about
# the processor, so we play safe by assuming i586.
# Note: whatever this is, it MUST be the same as what config.sub
# prints for the "djgpp" host, or else GDB configury will decide that
# this is a cross-build.
echo i586-pc-msdosdjgpp
exit ;;
Intel:Mach:3*:*)
echo i386-pc-mach3
exit ;;
@@ -1139,8 +1111,18 @@ EOF
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4; exit; } ;;
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4; exit; } ;;
NCR*:*:4.2:* | MPRAS*:*:4.2:*)
OS_REL='.3'
test -r /etc/.relid \
&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
&& { echo i486-ncr-sysv4.3${OS_REL}; exit; }
/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; }
/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
&& { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
echo m68k-unknown-lynxos${UNAME_RELEASE}
exit ;;
@@ -1153,7 +1135,7 @@ EOF
rs6000:LynxOS:2.*:*)
echo rs6000-unknown-lynxos${UNAME_RELEASE}
exit ;;
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*)
PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
echo powerpc-unknown-lynxos${UNAME_RELEASE}
exit ;;
SM[BE]S:UNIX_SV:*:*)
@@ -1173,10 +1155,10 @@ EOF
echo ns32k-sni-sysv
fi
exit ;;
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
# says <Richard.M.Bartel@ccMail.Census.GOV>
echo i586-unisys-sysv4
exit ;;
PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort
# says <Richard.M.Bartel@ccMail.Census.GOV>
echo i586-unisys-sysv4
exit ;;
*:UNIX_System_V:4*:FTX*)
# From Gerald Hewes <hewes@openmarket.com>.
# How about differentiating between stratus architectures? -djm
@@ -1202,11 +1184,11 @@ EOF
exit ;;
R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
if [ -d /usr/nec ]; then
echo mips-nec-sysv${UNAME_RELEASE}
echo mips-nec-sysv${UNAME_RELEASE}
else
echo mips-unknown-sysv${UNAME_RELEASE}
echo mips-unknown-sysv${UNAME_RELEASE}
fi
exit ;;
exit ;;
BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only.
echo powerpc-be-beos
exit ;;
@@ -1216,6 +1198,9 @@ EOF
BePC:BeOS:*:*) # BeOS running on Intel PC compatible.
echo i586-pc-beos
exit ;;
BePC:Haiku:*:*) # Haiku running on Intel PC compatible.
echo i586-pc-haiku
exit ;;
SX-4:SUPER-UX:*:*)
echo sx4-nec-superux${UNAME_RELEASE}
exit ;;
@@ -1243,6 +1228,16 @@ EOF
*:Darwin:*:*)
UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
case $UNAME_PROCESSOR in
i386)
eval $set_cc_for_build
if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then
if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
(CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \
grep IS_64BIT_ARCH >/dev/null
then
UNAME_PROCESSOR="x86_64"
fi
fi ;;
unknown) UNAME_PROCESSOR=powerpc ;;
esac
echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
@@ -1258,6 +1253,9 @@ EOF
*:QNX:*:4*)
echo i386-pc-qnx
exit ;;
NEO-?:NONSTOP_KERNEL:*:*)
echo neo-tandem-nsk${UNAME_RELEASE}
exit ;;
NSE-?:NONSTOP_KERNEL:*:*)
echo nse-tandem-nsk${UNAME_RELEASE}
exit ;;
@@ -1303,13 +1301,13 @@ EOF
echo pdp10-unknown-its
exit ;;
SEI:*:*:SEIUX)
echo mips-sei-seiux${UNAME_RELEASE}
echo mips-sei-seiux${UNAME_RELEASE}
exit ;;
*:DragonFly:*:*)
echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
exit ;;
*:*VMS:*:*)
UNAME_MACHINE=`(uname -p) 2>/dev/null`
UNAME_MACHINE=`(uname -p) 2>/dev/null`
case "${UNAME_MACHINE}" in
A*) echo alpha-dec-vms ; exit ;;
I*) echo ia64-dec-vms ; exit ;;
@@ -1324,6 +1322,12 @@ EOF
i*86:rdos:*:*)
echo ${UNAME_MACHINE}-pc-rdos
exit ;;
i*86:AROS:*:*)
echo ${UNAME_MACHINE}-pc-aros
exit ;;
x86_64:VMkernel:*:*)
echo ${UNAME_MACHINE}-unknown-esx
exit ;;
esac
#echo '(No uname command or uname output not recognized.)' 1>&2
@@ -1346,11 +1350,11 @@ main ()
#include <sys/param.h>
printf ("m68k-sony-newsos%s\n",
#ifdef NEWSOS4
"4"
"4"
#else
""
""
#endif
); exit (0);
); exit (0);
#endif
#endif

269
config.sub vendored
View File

@@ -1,10 +1,10 @@
#! /bin/sh
# Configuration validation subroutine script.
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
# Free Software Foundation, Inc.
# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
# 2011, 2012 Free Software Foundation, Inc.
timestamp='2008-01-16'
timestamp='2012-02-10'
# This file is (in principle) common to ALL GNU software.
# The presence of a machine in this file suggests that SOME GNU software
@@ -21,9 +21,7 @@ timestamp='2008-01-16'
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
# 02110-1301, USA.
# along with this program; if not, see <http://www.gnu.org/licenses/>.
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
@@ -32,13 +30,16 @@ timestamp='2008-01-16'
# Please send patches to <config-patches@gnu.org>. Submit a context
# diff and a properly formatted ChangeLog entry.
# diff and a properly formatted GNU ChangeLog entry.
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
@@ -72,8 +73,9 @@ Report bugs and patches to <config-patches@gnu.org>."
version="\
GNU config.sub ($timestamp)
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
@@ -120,12 +122,18 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
knetbsd*-gnu* | netbsd*-gnu* | \
kopensolaris*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
;;
android-linux)
os=-linux-android
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
;;
*)
basic_machine=`echo $1 | sed 's/-[^-]*$//'`
if [ $basic_machine != $1 ]
@@ -148,10 +156,13 @@ case $os in
-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
-apple | -axis | -knuth | -cray)
-apple | -axis | -knuth | -cray | -microblaze)
os=
basic_machine=$1
;;
-bluegene*)
os=-cnk
;;
-sim | -cisco | -oki | -wec | -winbond)
os=
basic_machine=$1
@@ -166,10 +177,10 @@ case $os in
os=-chorusos
basic_machine=$1
;;
-chorusrdb)
os=-chorusrdb
-chorusrdb)
os=-chorusrdb
basic_machine=$1
;;
;;
-hiux*)
os=-hiuxwe2
;;
@@ -238,24 +249,32 @@ case $basic_machine in
# Some are omitted here because they have special meanings below.
1750a | 580 \
| a29k \
| aarch64 | aarch64_be \
| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
| am33_2.0 \
| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
| be32 | be64 \
| bfin \
| c4x | clipper \
| d10v | d30v | dlx | dsp16xx \
| epiphany \
| fido | fr30 | frv \
| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
| hexagon \
| i370 | i860 | i960 | ia64 \
| ip2k | iq2000 \
| le32 | le64 \
| lm32 \
| m32c | m32r | m32rle | m68000 | m68k | m88k \
| maxq | mb | microblaze | mcore | mep \
| maxq | mb | microblaze | mcore | mep | metag \
| mips | mipsbe | mipseb | mipsel | mipsle \
| mips16 \
| mips64 | mips64el \
| mips64vr | mips64vrel \
| mips64octeon | mips64octeonel \
| mips64orion | mips64orionel \
| mips64r5900 | mips64r5900el \
| mips64vr | mips64vrel \
| mips64vr4100 | mips64vr4100el \
| mips64vr4300 | mips64vr4300el \
| mips64vr5000 | mips64vr5000el \
@@ -268,29 +287,42 @@ case $basic_machine in
| mipsisa64sr71k | mipsisa64sr71kel \
| mipstx39 | mipstx39el \
| mn10200 | mn10300 \
| moxie \
| mt \
| msp430 \
| nds32 | nds32le | nds32be \
| nios | nios2 \
| ns16k | ns32k \
| open8 \
| or32 \
| pdp10 | pdp11 | pj | pjl \
| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
| powerpc | powerpc64 | powerpc64le | powerpcle \
| pyramid \
| rl78 | rx \
| score \
| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
| sh64 | sh64le \
| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
| spu | strongarm \
| tahoe | thumb | tic4x | tic80 | tron \
| v850 | v850e \
| spu \
| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
| ubicom32 \
| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
| we32k \
| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
| z8k)
| x86 | xc16x | xstormy16 | xtensa \
| z8k | z80)
basic_machine=$basic_machine-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12)
# Motorola 68HC11/12.
c54x)
basic_machine=tic54x-unknown
;;
c55x)
basic_machine=tic55x-unknown
;;
c6x)
basic_machine=tic6x-unknown
;;
m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | picochip)
basic_machine=$basic_machine-unknown
os=-none
;;
@@ -300,6 +332,21 @@ case $basic_machine in
basic_machine=mt-unknown
;;
strongarm | thumb | xscale)
basic_machine=arm-unknown
;;
xgate)
basic_machine=$basic_machine-unknown
os=-none
;;
xscaleeb)
basic_machine=armeb-unknown
;;
xscaleel)
basic_machine=armel-unknown
;;
# We use `pc' rather than `unknown'
# because (1) that's what they normally are, and
# (2) the word "unknown" tends to confuse beginning users.
@@ -314,29 +361,36 @@ case $basic_machine in
# Recognize the basic CPU types with company name.
580-* \
| a29k-* \
| aarch64-* | aarch64_be-* \
| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
| arm-* | armbe-* | armle-* | armeb-* | armv*-* \
| avr-* | avr32-* \
| be32-* | be64-* \
| bfin-* | bs2000-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
| c[123]* | c30-* | [cjt]90-* | c4x-* \
| clipper-* | craynv-* | cydra-* \
| d10v-* | d30v-* | dlx-* \
| elxsi-* \
| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
| h8300-* | h8500-* \
| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
| hexagon-* \
| i*86-* | i860-* | i960-* | ia64-* \
| ip2k-* | iq2000-* \
| le32-* | le64-* \
| lm32-* \
| m32c-* | m32r-* | m32rle-* \
| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
| m88110-* | m88k-* | maxq-* | mcore-* \
| m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \
| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
| mips16-* \
| mips64-* | mips64el-* \
| mips64vr-* | mips64vrel-* \
| mips64octeon-* | mips64octeonel-* \
| mips64orion-* | mips64orionel-* \
| mips64r5900-* | mips64r5900el-* \
| mips64vr-* | mips64vrel-* \
| mips64vr4100-* | mips64vr4100el-* \
| mips64vr4300-* | mips64vr4300el-* \
| mips64vr5000-* | mips64vr5000el-* \
@@ -351,27 +405,32 @@ case $basic_machine in
| mmix-* \
| mt-* \
| msp430-* \
| nds32-* | nds32le-* | nds32be-* \
| nios-* | nios2-* \
| none-* | np1-* | ns16k-* | ns32k-* \
| open8-* \
| orion-* \
| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
| pyramid-* \
| romp-* | rs6000-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| rl78-* | romp-* | rs6000-* | rx-* \
| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
| sparclite-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
| tahoe-* | thumb-* \
| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \
| tahoe-* \
| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
| tile*-* \
| tron-* \
| v850-* | v850e-* | vax-* \
| ubicom32-* \
| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
| vax-* \
| we32k-* \
| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
| x86-* | x86_64-* | xc16x-* | xps100-* \
| xstormy16-* | xtensa*-* \
| ymp-* \
| z8k-*)
| z8k-* | z80-*)
;;
# Recognize the basic CPU types without company name, with glob match.
xtensa*)
@@ -393,7 +452,7 @@ case $basic_machine in
basic_machine=a29k-amd
os=-udi
;;
abacus)
abacus)
basic_machine=abacus-unknown
;;
adobe68k)
@@ -439,6 +498,10 @@ case $basic_machine in
basic_machine=m68k-apollo
os=-bsd
;;
aros)
basic_machine=i386-pc
os=-aros
;;
aux)
basic_machine=m68k-apple
os=-aux
@@ -455,10 +518,27 @@ case $basic_machine in
basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
os=-linux
;;
bluegene*)
basic_machine=powerpc-ibm
os=-cnk
;;
c54x-*)
basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c55x-*)
basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c6x-*)
basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
c90)
basic_machine=c90-cray
os=-unicos
;;
cegcc)
basic_machine=arm-unknown
os=-cegcc
;;
convex-c1)
basic_machine=c1-convex
os=-bsd
@@ -487,7 +567,7 @@ case $basic_machine in
basic_machine=craynv-cray
os=-unicosmp
;;
cr16)
cr16 | cr16-*)
basic_machine=cr16-unknown
os=-elf
;;
@@ -526,6 +606,10 @@ case $basic_machine in
basic_machine=m88k-motorola
os=-sysv3
;;
dicos)
basic_machine=i686-pc
os=-dicos
;;
djgpp)
basic_machine=i586-pc
os=-msdosdjgpp
@@ -641,7 +725,6 @@ case $basic_machine in
i370-ibm* | ibm*)
basic_machine=i370-ibm
;;
# I'm not sure what "Sysv32" means. Should this be sysv3.2?
i*86v32)
basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
os=-sysv32
@@ -699,6 +782,9 @@ case $basic_machine in
basic_machine=ns32k-utek
os=-sysv
;;
microblaze)
basic_machine=microblaze-xilinx
;;
mingw32)
basic_machine=i386-pc
os=-mingw32
@@ -735,10 +821,18 @@ case $basic_machine in
ms1-*)
basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
;;
msys)
basic_machine=i386-pc
os=-msys
;;
mvs)
basic_machine=i370-ibm
os=-mvs
;;
nacl)
basic_machine=le32-unknown
os=-nacl
;;
ncr3000)
basic_machine=i486-ncr
os=-sysv4
@@ -803,6 +897,12 @@ case $basic_machine in
np1)
basic_machine=np1-gould
;;
neo-tandem)
basic_machine=neo-tandem
;;
nse-tandem)
basic_machine=nse-tandem
;;
nsr-tandem)
basic_machine=nsr-tandem
;;
@@ -885,9 +985,10 @@ case $basic_machine in
;;
power) basic_machine=power-ibm
;;
ppc) basic_machine=powerpc-unknown
ppc | ppcbe) basic_machine=powerpc-unknown
;;
ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
ppc-* | ppcbe-*)
basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
ppcle | powerpclittle | ppc-le | powerpc-little)
basic_machine=powerpcle-unknown
@@ -981,6 +1082,9 @@ case $basic_machine in
basic_machine=i860-stratus
os=-sysv4
;;
strongarm-* | thumb-*)
basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
;;
sun2)
basic_machine=m68000-sun
;;
@@ -1037,20 +1141,8 @@ case $basic_machine in
basic_machine=t90-cray
os=-unicos
;;
tic54x | c54x*)
basic_machine=tic54x-unknown
os=-coff
;;
tic55x | c55x*)
basic_machine=tic55x-unknown
os=-coff
;;
tic6x | c6x*)
basic_machine=tic6x-unknown
os=-coff
;;
tile*)
basic_machine=tile-unknown
basic_machine=$basic_machine-unknown
os=-linux-gnu
;;
tx39)
@@ -1120,6 +1212,9 @@ case $basic_machine in
xps | xps100)
basic_machine=xps100-honeywell
;;
xscale-* | xscalee[bl]-*)
basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
;;
ymp)
basic_machine=ymp-cray
os=-unicos
@@ -1128,6 +1223,10 @@ case $basic_machine in
basic_machine=z8k-unknown
os=-sim
;;
z80-*-coff)
basic_machine=z80-unknown
os=-sim
;;
none)
basic_machine=none-none
os=-none
@@ -1166,7 +1265,7 @@ case $basic_machine in
we32k)
basic_machine=we32k-att
;;
sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
basic_machine=sh-unknown
;;
sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
@@ -1213,9 +1312,12 @@ esac
if [ x"$os" != x"" ]
then
case $os in
# First match some system type aliases
# that might get confused with valid system types.
# First match some system type aliases
# that might get confused with valid system types.
# -solaris* is a basic system type, with this one exception.
-auroraux)
os=-auroraux
;;
-solaris1 | -solaris1.*)
os=`echo $os | sed -e 's|solaris1|sunos4|'`
;;
@@ -1236,10 +1338,11 @@ case $os in
# Each alternative MUST END IN A *, to match a version number.
# -sysv* is not here because it comes later, after sysvr4.
-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \
| -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
| -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
| -sym* | -kopensolaris* \
| -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
| -aos* \
| -aos* | -aros* \
| -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
| -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
| -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
@@ -1248,9 +1351,10 @@ case $os in
| -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
| -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
| -chorusos* | -chorusrdb* | -cegcc* \
| -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
| -mingw32* | -linux-gnu* | -linux-android* \
| -linux-newlib* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
@@ -1258,7 +1362,7 @@ case $os in
| -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
| -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
| -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
| -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
| -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*)
# Remember, each alternative MUST END IN *, to match a version number.
;;
-qnx*)
@@ -1297,7 +1401,7 @@ case $os in
-opened*)
os=-openedition
;;
-os400*)
-os400*)
os=-os400
;;
-wince*)
@@ -1346,7 +1450,7 @@ case $os in
-sinix*)
os=-sysv4
;;
-tpf*)
-tpf*)
os=-tpf
;;
-triton*)
@@ -1388,6 +1492,11 @@ case $os in
-zvmoe)
os=-zvmoe
;;
-dicos*)
os=-dicos
;;
-nacl*)
;;
-none)
;;
*)
@@ -1410,10 +1519,10 @@ else
# system, and we'll never get to this point.
case $basic_machine in
score-*)
score-*)
os=-elf
;;
spu-*)
spu-*)
os=-elf
;;
*-acorn)
@@ -1425,8 +1534,17 @@ case $basic_machine in
arm*-semi)
os=-aout
;;
c4x-* | tic4x-*)
os=-coff
c4x-* | tic4x-*)
os=-coff
;;
tic54x-*)
os=-coff
;;
tic55x-*)
os=-coff
;;
tic6x-*)
os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
@@ -1446,14 +1564,11 @@ case $basic_machine in
;;
m68000-sun)
os=-sunos3
# This also exists in the configure program, but was not the
# default.
# os=-sunos4
;;
m68*-cisco)
os=-aout
;;
mep-*)
mep-*)
os=-elf
;;
mips*-cisco)
@@ -1480,7 +1595,7 @@ case $basic_machine in
*-ibm)
os=-aix
;;
*-knuth)
*-knuth)
os=-mmixware
;;
*-wec)
@@ -1585,7 +1700,7 @@ case $basic_machine in
-sunos*)
vendor=sun
;;
-aix*)
-cnk*|-aix*)
vendor=ibm
;;
-beos*)

View File

@@ -1,6 +1,6 @@
#
# ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2010 Alexander Barton <alex@barton.de>
# 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
@@ -160,10 +160,12 @@ AC_FUNC_STRFTIME
AC_CHECK_FUNCS([ \
bind gethostbyaddr gethostbyname gethostname inet_ntoa \
setsid setsockopt socket strcasecmp waitpid],,AC_MSG_ERROR([required function missing!]))
setsid setsockopt socket strcasecmp waitpid],,
AC_MSG_ERROR([required function missing!]))
AC_CHECK_FUNCS(getaddrinfo getnameinfo inet_aton sigaction sigprocmask snprintf \
vsnprintf strdup strlcpy strlcat strtok_r)
AC_CHECK_FUNCS([ \
gai_strerror getaddrinfo getnameinfo inet_aton sigaction \
sigprocmask snprintf vsnprintf strdup strlcpy strlcat strtok_r])
# -- Configuration options --
@@ -250,13 +252,21 @@ AC_ARG_WITH(poll,
CPPFLAGS="-I$withval/include $CPPFLAGS"
LDFLAGS="-L$withval/lib $LDFLAGS"
fi
AC_CHECK_FUNCS(poll, x_io_backend=poll\(\),
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, x_io_backend=poll\(\))
AC_CHECK_FUNCS(poll, [
AC_CHECK_HEADERS(poll.h, x_io_backend=poll\(\))
])
]
)
@@ -330,7 +340,7 @@ else
fi
if test "$x_io_backend" = "none"; then
AC_MSG_ERROR([No useabe IO API activated/found!?])
AC_MSG_ERROR([No useable IO API activated/found!?])
fi
# use SSL?
@@ -544,6 +554,7 @@ AC_OUTPUT([ \
src/testsuite/Makefile \
man/Makefile \
contrib/Makefile \
contrib/Anope/Makefile \
contrib/Debian/Makefile \
contrib/MacOSX/Makefile \
contrib/MacOSX/ngIRCd.xcodeproj/Makefile \

View File

@@ -0,0 +1,496 @@
From bc5023fdba8091ab7eee29fe0deeca6843159743 Mon Sep 17 00:00:00 2001
From: Alexander Barton <alex@barton.de>
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<User *>::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<Anope::string>&) { return false; }
+
+ /*
+ * Received: :dev.anope.de MODE #anope +b *!*@*aol*
+ */
+ bool OnMode(const Anope::string &source, const std::vector<Anope::string> &params)
+ {
+ 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] = <unknown>
+ params[2] = username
+ params[3] = host
+ params[4] = <unknown>
+ params[5] = modes
+ params[6] = info
+ */
+ bool OnNick(const Anope::string &source, const std::vector<Anope::string> &params)
+ {
+ 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<Anope::string> &params)
+ {
+ 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<unsigned>(params[1]) : 0, params[3], params[2]);
+ return true;
+ }
+
+ bool OnTopic(const Anope::string &source, const std::vector<Anope::string> &params)
+ {
+ 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 <channelname>\7<umode>
+ */
+ bool OnJoin (const Anope::string &source, const std::vector<Anope::string> &params)
+ {
+ 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 <chan> +<modes>
+ * CHANINFO <chan> +<modes> :<topic>
+ * CHANINFO <chan> +<modes> <key> <limit> :<topic>
+ */
+bool event_chaninfo(const Anope::string &source, const std::vector<Anope::string> &params)
+{
+
+ 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<Anope::string> &params)
+{
+ 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<ChannelMode *> 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<ChannelMode *>::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<Anope::string> &params)
+{
+ 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<Anope::string> &params)
+{
+ return true;
+}
+
+bool event_005(const Anope::string &source, const std::vector<Anope::string> &params)
+{
+ 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<unsigned>(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<Anope::string> &params)
+{
+ return true;
+}
+
+bool event_376(const Anope::string &source, const std::vector<Anope::string> &params)
+{
+ 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

View File

@@ -0,0 +1,60 @@
From 1ea1dd2095e63cef34edbebb729edc687f410a96 Mon Sep 17 00:00:00 2001
From: Alexander Barton <alex@barton.de>
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::vector<Anope::string
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)
@@ -307,7 +307,7 @@ bool event_njoin(const Anope::string &source, const std::vector<Anope::string> &
c = new Channel(params[0], Anope::CurTime);
c->SetFlag(CH_SYNCING);
}
-
+
while (sep.GetToken(buf))
{
std::list<ChannelMode *> Status;
@@ -415,9 +415,9 @@ bool event_376(const Anope::string &source, const std::vector<Anope::string> &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

View File

@@ -0,0 +1,128 @@
From d8eddbeaadc7d161865b5342d59748b80266533c Mon Sep 17 00:00:00 2001
From: DukePyrolator <DukePyrolator@anope.org>
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<User *>::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

View File

@@ -0,0 +1,93 @@
From 88b2b14a76b8ee053b1f6ea64139350260590043 Mon Sep 17 00:00:00 2001
From: DukePyrolator <DukePyrolator@anope.org>
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<unsigned>(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<Anope::string> &params)
+{
+ Server *s = Server::Find(source);
+ if (s && !s->IsSynced())
+ s->Sync(false);
+ return true;
+}
+
+
+
/*
* CHANINFO <chan> +<modes>
* CHANINFO <chan> +<modes> :<topic>
@@ -416,7 +439,7 @@ bool event_376(const Anope::string &source, const std::vector<Anope::string> &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

View File

@@ -0,0 +1,29 @@
From 0d83f8f9ca0de651d664eca6f467f36df0417f7d Mon Sep 17 00:00:00 2001
From: Alexander Barton <alex@barton.de>
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

View File

@@ -0,0 +1,47 @@
From 1914a36b83b1fc6b4678ef261a1a06eefab9a0ca Mon Sep 17 00:00:00 2001
From: Alexander Barton <alex@barton.de>
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

View File

@@ -0,0 +1,96 @@
From 4c9300ede35310ee5642f34e5ac227bd96fc7384 Mon Sep 17 00:00:00 2001
From: DukePyrolator <DukePyrolator@anope.org>
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

View File

@@ -0,0 +1,38 @@
From d363ebd841ea7e1db3c62730023759d69520e0d8 Mon Sep 17 00:00:00 2001
From: Alexander Barton <alex@barton.de>
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

View File

@@ -0,0 +1,143 @@
From e74a5303f2357f4a9915bb91038a2e326323db3c Mon Sep 17 00:00:00 2001
From: Alexander Barton <alex@barton.de>
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

View File

@@ -0,0 +1,57 @@
From d2c45d7c578ec684d3b471020f631847316de196 Mon Sep 17 00:00:00 2001
From: Alexander Barton <alex@barton.de>
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<Anope::string> &p
return true;
}
-
-
/*
* CHANINFO <chan> +<modes>
* CHANINFO <chan> +<modes> :<topic>
@@ -480,7 +477,6 @@ bool event_376(const Anope::string &source, const std::vector<Anope::string> &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

View File

@@ -0,0 +1,29 @@
From 4dc5a3d3e2fbb218461d9459bff1c0a392a75881 Mon Sep 17 00:00:00 2001
From: Alexander Barton <alex@barton.de>
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

View File

@@ -0,0 +1,25 @@
From 99c18cafdee28bfb17fad5f0526b3ed5d1f5f312 Mon Sep 17 00:00:00 2001
From: Alexander Barton <alex@barton.de>
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

View File

@@ -0,0 +1,28 @@
From 5a19b69f0daceb5b12ec751bc919519a7f712f2d Mon Sep 17 00:00:00 2001
From: Alexander Barton <alex@barton.de>
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 <alex@barton.de>
+ * (C) 2011 Anope Team <team@anope.org>
*
* Please read COPYING and README for further details.
*
--
1.7.8.3

View File

@@ -0,0 +1,35 @@
From acc24a7f4488f6ef0fb240a76766db4220b62d53 Mon Sep 17 00:00:00 2001
From: Alexander Barton <alex@barton.de>
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

View File

@@ -0,0 +1,27 @@
From 3a61b190db79848d4519296432ebb2ab714c42b7 Mon Sep 17 00:00:00 2001
From: Alexander Barton <alex@barton.de>
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

View File

@@ -0,0 +1,35 @@
From a7c48fcf47af757cf1b4eeaa6bcc96f4ae1f7410 Mon Sep 17 00:00:00 2001
From: Alexander Barton <alex@barton.de>
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<Anope::string> &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

34
contrib/Anope/Makefile.am Normal file
View File

@@ -0,0 +1,34 @@
#
# 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-

35
contrib/Anope/README Normal file
View File

@@ -0,0 +1,35 @@
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.

View File

@@ -1,3 +1,45 @@
ngircd (19.2-0ab1) unstable; urgency=low
* New "upstream" release: ngIRCd 19.2.
-- Alexander Barton <alex@barton.de> Tue, 19 Jun 2012 11:03:12 +0200
ngircd (19.2~rc1-0ab1) unstable; urgency=low
* New "upstream" release candidate 1 for ngIRC Release 19.2.
-- Alexander Barton <alex@barton.de> Wed, 13 Jun 2012 10:59:34 +0200
ngircd (19.1-0ab1) unstable; urgency=low
* New "upstream" release: ngIRCd 19.1.
-- Alexander Barton <alex@barton.de> Mon, 19 Mar 2012 19:18:28 +0100
ngircd (19-0ab1) unstable; urgency=low
* New "upstream" release: ngIRCd 19.
-- Alexander Barton <alex@barton.de> Wed, 29 Feb 2012 17:34:08 +0100
ngircd (19~rc1-0ab1) unstable; urgency=low
* New "upstream" release candidate 1 for ngIRCd Release 19.
-- Alexander Barton <alex@barton.de> Sun, 12 Feb 2012 17:47:51 +0100
ngircd (18-0ab1) unstable; urgency=low
* New "upstream" release: ngIRCd 18.
-- Alexander Barton <alex@barton.de> Sun, 10 Jul 2011 20:03:20 +0200
ngircd (18~rc2-0ab1) unstable; urgency=low
* New "upstream" release candidate 2 for ngIRCd Release 18.
-- Alexander Barton <alex@barton.de> Wed, 29 Jun 2011 10:20:51 +0200
ngircd (18~rc1-0ab1) unstable; urgency=low
* New "upstream" release candidate 1 for ngIRCd Release 18.

View File

@@ -2,64 +2,60 @@ Source: ngircd
Section: net
Priority: optional
Maintainer: Alexander Barton <alex@barton.de>
Build-Depends: debhelper (>> 4.0.0), libz-dev, libwrap0-dev, libident-dev, libgnutls-dev, libpam0g-dev
Build-Depends: debhelper (>> 4.0.0),
autotools-dev,
expect,
libz-dev,
libwrap0-dev,
libident-dev,
libgnutls-dev,
libpam0g-dev,
telnet,
Standards-Version: 3.9.1
Package: ngircd
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Provides: ircd
Description: A lightweight daemon for the Internet Relay Chat (IRC)
ngIRCd is a free open source daemon for the Internet Relay Chat (IRC)
network. It is written from scratch and is not based upon the original
IRCd like many others.
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 contains the "standard distribution", including support for
syslog logging and compressed server-links using zlib. Please have a look
at the "ngircd-full" package if you need advanced functionality like support
for IPv6 or SSL.
.
Advantages of ngIRCd:
- no problems with servers using changing/non-static IP addresses.
- small and lean configuration file.
- free, modern and open source C code.
- still under active development.
.
ngIRCd is compatible to the "original" ircd 2.10.3p3, so you can run
mixed networks.
Package: ngircd-full
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Provides: ircd
Conflicts: ngircd, ngircd-dbg
Description: A lightweight daemon for the Internet Relay Chat (IRC)
ngIRCd is a free open source daemon for the Internet Relay Chat (IRC)
network. It is written from scratch and is not based upon the original
IRCd like many others.
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.
.
In addition to the features of the "standard package", this package
includes support for TCP wrappers, IDENT requests, the IPv6 protocol and
SSL encrypted client and server links.
.
Advantages of ngIRCd:
- no problems with servers using changing/non-static IP addresses.
- small and lean configuration file.
- free, modern and open source C code.
- still under active development.
.
ngIRCd is compatible to the "original" ircd 2.10.3p3, so you can run
mixed networks.
Package: ngircd-full-dbg
Architecture: any
Depends: ${shlibs:Depends}, ${misc:Depends}
Provides: ircd
Conflicts: ngircd, ngircd-full
Description: A lightweight daemon for the Internet Relay Chat (IRC)
ngIRCd is a free open source daemon for the Internet Relay Chat (IRC)
network. It is written from scratch and is not based upon the original
IRCd like many others.
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.
.
In addition to the features of the "standard package", this package
includes support for TCP wrappers, IDENT requests, the IPv6 protocol and
@@ -67,12 +63,3 @@ Description: A lightweight daemon for the Internet Relay Chat (IRC)
.
And in addition to the "full" variant, the binaries contained in this
package are build with debug code and contain debug symbols.
.
Advantages of ngIRCd:
- no problems with servers using changing/non-static IP addresses.
- small and lean configuration file.
- free, modern and open source C code.
- still under active development.
.
ngIRCd is compatible to the "original" ircd 2.10.3p3, so you can run
mixed networks.

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2010 Alexander Barton (alex@barton.de).
* 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
@@ -74,6 +74,8 @@
/* Define to 1 if you have the <netinet/ip.h> header file. */
#define HAVE_NETINET_IP_H 1
/* Define to 1 if you have the `gai_strerror' function. */
#define HAVE_GAI_STRERROR 1
/* Define to 1 if you have the `kqueue' function. */
#define HAVE_KQUEUE 1
/* Define to 1 if you have the `inet_ntoa' function. */
@@ -103,10 +105,15 @@
#ifdef PAM
/* Define to 1 if you have the `pam_authenticate' function. */
#define HAVE_PAM_AUTHENTICATE 1
#if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1060)
/* Define to 1 if you have the <pam/pam_appl.h> header file. */
#define HAVE_PAM_PAM_APPL_H 1
/* Mac OS X <10.6 doesn't have pam_fail_delay() */
#define NO_PAM_FAIL_DELAY 1
#else
/* Define to 1 if you have the <security/pam_appl.h> header file. */
#define HAVE_SECURITY_PAM_APPL_H 1
#endif
#endif
/* -eof- */

View File

@@ -156,7 +156,7 @@ Each version is given a distinguishing version number. If the Program specifies
{\colortbl;\red255\green255\blue255;}
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural\pardirnatural
\f0\fs26 \cf0 Please not:\
\f0\fs26 \cf0 Please note:\
\
\pard\tx260\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\li260\fi-260\ql\qnatural\pardirnatural
\cf0 \'95 You

View File

@@ -1,2 +1,4 @@
project.xcworkspace
xcuserdata
*.mode1v3
*.pbxuser

View File

@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 44;
objectVersion = 46;
objects = {
/* Begin PBXBuildFile section */
@@ -40,6 +40,10 @@
FA99428C10E82A27007F27ED /* proc.c in Sources */ = {isa = PBXBuildFile; fileRef = FA99428B10E82A27007F27ED /* proc.c */; };
FAA3D27B0F139CDC00B2447E /* conn-ssl.c in Sources */ = {isa = PBXBuildFile; fileRef = FAA3D2790F139CDC00B2447E /* conn-ssl.c */; };
FAA97C57124A271400D5BBA9 /* sighandlers.c in Sources */ = {isa = PBXBuildFile; fileRef = FAA97C55124A271400D5BBA9 /* sighandlers.c */; };
FAACD5F514A6099C006ED74F /* class.c in Sources */ = {isa = PBXBuildFile; fileRef = FAACD5F314A6099C006ED74F /* class.c */; };
FAD5853215271AAB00328741 /* client-cap.c in Sources */ = {isa = PBXBuildFile; fileRef = FAD5853015271AAB00328741 /* client-cap.c */; };
FAD5853515271AB800328741 /* irc-cap.c in Sources */ = {isa = PBXBuildFile; fileRef = FAD5853315271AB800328741 /* irc-cap.c */; };
FAD5853815272C2600328741 /* login.c in Sources */ = {isa = PBXBuildFile; fileRef = FAD5853615272C2500328741 /* login.c */; };
FAE5CC2E0CF2308A007D69B6 /* numeric.c in Sources */ = {isa = PBXBuildFile; fileRef = FAE5CC2D0CF2308A007D69B6 /* numeric.c */; };
/* End PBXBuildFile section */
@@ -170,7 +174,6 @@
FA322D8E0CEF7523001761B3 /* ngIRCd.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = ngIRCd.xcodeproj; sourceTree = "<group>"; };
FA322D910CEF7523001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
FA322D920CEF7523001761B3 /* ngindent */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = ngindent; sourceTree = "<group>"; };
FA322D930CEF7523001761B3 /* ngircd.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = ngircd.sh; sourceTree = "<group>"; };
FA322D940CEF7523001761B3 /* ngircd.spec */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = ngircd.spec; sourceTree = "<group>"; };
FA322D950CEF7523001761B3 /* README */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
FA322D960CEF7523001761B3 /* systrace.policy */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = systrace.policy; sourceTree = "<group>"; };
@@ -196,6 +199,10 @@
FA407F2C0DB159F400271AF1 /* ng_ipaddr.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = ng_ipaddr.c; path = ipaddr/ng_ipaddr.c; sourceTree = "<group>"; };
FA407F2D0DB159F400271AF1 /* ng_ipaddr.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = ng_ipaddr.h; path = ipaddr/ng_ipaddr.h; sourceTree = "<group>"; };
FA407F380DB15AC700271AF1 /* GIT.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = GIT.txt; sourceTree = "<group>"; };
FA4B08E513E7F8FB00765BA3 /* ngircd-bsd.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "ngircd-bsd.sh"; sourceTree = "<group>"; };
FA4B08E613E7F91700765BA3 /* ngIRCd-Logo.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = "ngIRCd-Logo.gif"; sourceTree = "<group>"; };
FA4B08E713E7F91700765BA3 /* ngircd-redhat.init */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "ngircd-redhat.init"; sourceTree = "<group>"; };
FA4B08E813E7F91C00765BA3 /* platformtest.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = platformtest.sh; sourceTree = "<group>"; };
FA77849A133FB9FF00740057 /* sample-ngircd.conf.tmpl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "sample-ngircd.conf.tmpl"; sourceTree = "<group>"; };
FA85178A0FA061EC006A1F5A /* op.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = op.h; sourceTree = "<group>"; };
FA85178B0FA061EC006A1F5A /* op.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = op.c; sourceTree = "<group>"; };
@@ -225,6 +232,21 @@
FAA3D28B0F139D2E00B2447E /* preinstall.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = preinstall.sh; sourceTree = "<group>"; };
FAA97C55124A271400D5BBA9 /* sighandlers.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = sighandlers.c; sourceTree = "<group>"; };
FAA97C56124A271400D5BBA9 /* sighandlers.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = sighandlers.h; sourceTree = "<group>"; };
FAACD5F314A6099C006ED74F /* class.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = class.c; sourceTree = "<group>"; };
FAACD5F414A6099C006ED74F /* class.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = class.h; sourceTree = "<group>"; };
FAD5852F15271A7800328741 /* Capabilities.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Capabilities.txt; sourceTree = "<group>"; };
FAD5853015271AAB00328741 /* client-cap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "client-cap.c"; sourceTree = "<group>"; };
FAD5853115271AAB00328741 /* client-cap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "client-cap.h"; sourceTree = "<group>"; };
FAD5853315271AB800328741 /* irc-cap.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "irc-cap.c"; sourceTree = "<group>"; };
FAD5853415271AB800328741 /* irc-cap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "irc-cap.h"; sourceTree = "<group>"; };
FAD5853615272C2500328741 /* login.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = login.c; sourceTree = "<group>"; };
FAD5853715272C2500328741 /* login.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = login.h; sourceTree = "<group>"; };
FAE22BD215270EA300F1A5AB /* Bopm.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Bopm.txt; sourceTree = "<group>"; };
FAE22BD415270EA300F1A5AB /* Contributing.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Contributing.txt; sourceTree = "<group>"; };
FAE22BD515270EB500F1A5AB /* HowToRelease.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = HowToRelease.txt; sourceTree = "<group>"; };
FAE22BD615270EB500F1A5AB /* Modes.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Modes.txt; sourceTree = "<group>"; };
FAE22BD715270EB500F1A5AB /* PAM.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = PAM.txt; sourceTree = "<group>"; };
FAE22BD815270EC400F1A5AB /* README-Interix.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = "README-Interix.txt"; sourceTree = "<group>"; };
FAE5CC2C0CF2308A007D69B6 /* numeric.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = numeric.h; sourceTree = "<group>"; };
FAE5CC2D0CF2308A007D69B6 /* numeric.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = numeric.c; sourceTree = "<group>"; };
/* End PBXFileReference section */
@@ -292,28 +314,35 @@
FA322CD70CEF74B1001761B3 /* ngircd */ = {
isa = PBXGroup;
children = (
FAA3D2780F139CDC00B2447E /* conf-ssl.h */,
FAA3D2790F139CDC00B2447E /* conn-ssl.c */,
FAA3D27A0F139CDC00B2447E /* conn-ssl.h */,
FA322D020CEF74B1001761B3 /* Makefile.am */,
FA322CD90CEF74B1001761B3 /* array.c */,
FA322CDA0CEF74B1001761B3 /* array.h */,
FA322CDB0CEF74B1001761B3 /* channel.c */,
FA322CDC0CEF74B1001761B3 /* channel.h */,
FAACD5F314A6099C006ED74F /* class.c */,
FAACD5F414A6099C006ED74F /* class.h */,
FA322CDD0CEF74B1001761B3 /* client.c */,
FA322CDE0CEF74B1001761B3 /* client.h */,
FAD5853015271AAB00328741 /* client-cap.c */,
FAD5853115271AAB00328741 /* client-cap.h */,
FA322CDF0CEF74B1001761B3 /* conf.c */,
FA322CE00CEF74B1001761B3 /* conf.h */,
FAA3D2780F139CDC00B2447E /* conf-ssl.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 */,
FA322CE80CEF74B1001761B3 /* hash.c */,
FA322CE90CEF74B1001761B3 /* hash.h */,
FA322CEA0CEF74B1001761B3 /* io.c */,
FA322CEB0CEF74B1001761B3 /* io.h */,
FAD5853315271AB800328741 /* irc-cap.c */,
FAD5853415271AB800328741 /* irc-cap.h */,
FA322CEC0CEF74B1001761B3 /* irc-channel.c */,
FA322CED0CEF74B1001761B3 /* irc-channel.h */,
FA322CEE0CEF74B1001761B3 /* irc-info.c */,
@@ -336,7 +365,8 @@
FA322CFF0CEF74B1001761B3 /* lists.h */,
FA322D000CEF74B1001761B3 /* log.c */,
FA322D010CEF74B1001761B3 /* log.h */,
FA322D020CEF74B1001761B3 /* Makefile.am */,
FAD5853615272C2500328741 /* login.c */,
FAD5853715272C2500328741 /* login.h */,
FA322D030CEF74B1001761B3 /* match.c */,
FA322D040CEF74B1001761B3 /* match.h */,
FA322D050CEF74B1001761B3 /* messages.h */,
@@ -346,6 +376,8 @@
FAE5CC2C0CF2308A007D69B6 /* numeric.h */,
FA85178B0FA061EC006A1F5A /* op.c */,
FA85178A0FA061EC006A1F5A /* op.h */,
FA2D564911EA158B00D37A35 /* pam.c */,
FA2D564811EA158B00D37A35 /* pam.h */,
FA322D080CEF74B1001761B3 /* parse.c */,
FA322D090CEF74B1001761B3 /* parse.h */,
FA99428B10E82A27007F27ED /* proc.c */,
@@ -354,8 +386,6 @@
FA322D0D0CEF74B1001761B3 /* resolve.h */,
FAA97C55124A271400D5BBA9 /* sighandlers.c */,
FAA97C56124A271400D5BBA9 /* sighandlers.h */,
FA2D564811EA158B00D37A35 /* pam.h */,
FA2D564911EA158B00D37A35 /* pam.c */,
);
path = ngircd;
sourceTree = "<group>";
@@ -432,8 +462,11 @@
FA322D730CEF7523001761B3 /* MacOSX */,
FA322D910CEF7523001761B3 /* Makefile.am */,
FA322D920CEF7523001761B3 /* ngindent */,
FA322D930CEF7523001761B3 /* ngircd.sh */,
FA4B08E513E7F8FB00765BA3 /* ngircd-bsd.sh */,
FA4B08E613E7F91700765BA3 /* ngIRCd-Logo.gif */,
FA4B08E713E7F91700765BA3 /* ngircd-redhat.init */,
FA322D940CEF7523001761B3 /* ngircd.spec */,
FA4B08E813E7F91C00765BA3 /* platformtest.sh */,
FA322D950CEF7523001761B3 /* README */,
FA322D960CEF7523001761B3 /* systrace.policy */,
);
@@ -552,18 +585,25 @@
FA322D970CEF752C001761B3 /* doc */ = {
isa = PBXGroup;
children = (
FAA3D2800F139D1500B2447E /* Services.txt */,
FA407F380DB15AC700271AF1 /* GIT.txt */,
FA322D9A0CEF752C001761B3 /* FAQ.txt */,
FA322D9B0CEF752C001761B3 /* Makefile.am */,
FAE22BD215270EA300F1A5AB /* Bopm.txt */,
FAD5852F15271A7800328741 /* Capabilities.txt */,
FAE22BD415270EA300F1A5AB /* Contributing.txt */,
FA322D9A0CEF752C001761B3 /* FAQ.txt */,
FA407F380DB15AC700271AF1 /* GIT.txt */,
FAE22BD515270EB500F1A5AB /* HowToRelease.txt */,
FAE22BD615270EB500F1A5AB /* Modes.txt */,
FAE22BD715270EB500F1A5AB /* PAM.txt */,
FA322D9C0CEF752C001761B3 /* Platforms.txt */,
FA322D9D0CEF752C001761B3 /* Protocol.txt */,
FA322D9E0CEF752C001761B3 /* README-AUX.txt */,
FA322D9F0CEF752C001761B3 /* README-BeOS.txt */,
FAE22BD815270EC400F1A5AB /* README-Interix.txt */,
FA322DA00CEF752C001761B3 /* RFC.txt */,
FAA3D2800F139D1500B2447E /* Services.txt */,
FA322DA90CEF752C001761B3 /* SSL.txt */,
FA77849A133FB9FF00740057 /* sample-ngircd.conf.tmpl */,
FA322DA20CEF752C001761B3 /* src */,
FA322DA90CEF752C001761B3 /* SSL.txt */,
);
name = doc;
path = ../../doc;
@@ -641,8 +681,11 @@
/* Begin PBXProject section */
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0430;
};
buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "ngIRCd" */;
compatibilityVersion = "Xcode 3.0";
compatibilityVersion = "Xcode 3.2";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
@@ -703,6 +746,10 @@
FA99428C10E82A27007F27ED /* proc.c in Sources */,
FA2D564A11EA158B00D37A35 /* pam.c in Sources */,
FAA97C57124A271400D5BBA9 /* sighandlers.c in Sources */,
FAACD5F514A6099C006ED74F /* class.c in Sources */,
FAD5853215271AAB00328741 /* client-cap.c in Sources */,
FAD5853515271AB800328741 /* irc-cap.c in Sources */,
FAD5853815272C2600328741 /* login.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -713,6 +760,7 @@
isa = XCBuildConfiguration;
buildSettings = {
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
@@ -738,13 +786,11 @@
1DEB928B08733DD80010E9CD /* Default */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
GCC_VERSION = 4.0;
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
GCC_VERSION = 4.2;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PREBINDING = NO;
SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk";
SDKROOT = macosx10.6;
};
name = Default;
};
@@ -754,12 +800,11 @@
ARCHS = "$(NATIVE_ARCH_ACTUAL)";
GCC_DEBUGGING_SYMBOLS = full;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_VERSION = 4.0;
GCC_VERSION = 4.2;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
ONLY_ACTIVE_ARCH = YES;
PREBINDING = NO;
SDKROOT = "";
SDKROOT = macosx;
};
name = Debug;
};
@@ -767,6 +812,7 @@
isa = XCBuildConfiguration;
buildSettings = {
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;

View File

@@ -1,6 +1,6 @@
#
# ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2009 Alexander Barton (alex@barton.de)
# 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
@@ -9,7 +9,7 @@
# Please read the file COPYING, README and AUTHORS for more information.
#
SUBDIRS = Debian MacOSX
SUBDIRS = Anope Debian MacOSX
EXTRA_DIST = README ngircd.spec systrace.policy ngindent ngircd-bsd.sh \
ngIRCd-Logo.gif ngircd-redhat.init platformtest.sh

View File

@@ -1,15 +1,17 @@
ngIRCd - Next Generation IRC Server
http://ngircd.barton.de/
(c)2001-2009 Alexander Barton,
alex@barton.de, http://www.barton.de/
(c)2001-2011 Alexander Barton and Contributors.
ngIRCd is free software and published under the
terms of the GNU General Public License.
-- 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").

View File

@@ -4,6 +4,7 @@ INDENTARGS="-kr -i8 -ts8 -l80 -c3 -cd41 -ss -ncs -psl"
# check if indent(1) is available
type indent >/dev/null 2>&1 && INDENT="indent"
type gindent >/dev/null 2>&1 && INDENT="gindent"
type gnuindent >/dev/null 2>&1 && INDENT="gnuindent"
if [ -z "$INDENT" ]; then

View File

@@ -1,5 +1,5 @@
%define name ngircd
%define version 18~rc1
%define version 19.2
%define release 1
%define prefix %{_prefix}
@@ -15,18 +15,19 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
BuildRequires: zlib-devel, openssl-devel
%description
ngIRCd is a free open source daemon for the Internet Relay Chat (IRC),
developed under the GNU General Public License (GPL). It's written from
scratch and is not based upon the original IRCd like many others.
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.
Advantages:
- no problems with servers using changing/non-static IP addresses.
- small and lean configuration file.
- free, modern and open source C code.
- still under active development.
ngIRCd is compatible to the "original" ircd 2.10.3p3, so you can run
mixed networks.
- well arranged (lean) configuration file
- simple to build/install, configure and maintain
- supports IPv6 and SSL
- no problems with servers that have dynamic IP addresses
- freely available, modern, portable and tidy C-source
- ngIRCd is being actively developed since 11 years.
%prep
%setup -q

View File

@@ -1,7 +1,7 @@
#!/bin/sh
#
# ngIRCd -- The Next Generation IRC Daemon
# Copyright (c)2001-2010 Alexander Barton <alex@barton.de>
# 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
@@ -21,13 +21,16 @@ PLATFORM=
COMPILER="unknown"
VERSION="unknown"
DATE=`date "+%y-%m-%d"`
CONFIGURE=
MAKE=
CHECK=
RUN=
COMMENT=
R_CONFIGURE=
R_MAKE=
R_CHECK=
R_RUN=
[ -n "$MAKE" ] || MAKE="make"
export MAKE CC
while [ $# -gt 0 ]; do
case "$1" in
"-v")
@@ -61,20 +64,20 @@ if [ -r ./configure ]; then
echo "$NAME: Running \"./configure\" script ..."
[ -n "$VERBOSE" ] && ./configure || ./configure >/dev/null
if [ $? -eq 0 -a -r ./Makefile ]; then
CONFIGURE=1
echo "$NAME: Running \"make\" ..."
[ -n "$VERBOSE" ] && make || make >/dev/null
R_CONFIGURE=1
echo "$NAME: Running \"$MAKE\" ..."
[ -n "$VERBOSE" ] && "$MAKE" || "$MAKE" >/dev/null
if [ $? -eq 0 -a -x src/ngircd/ngircd ]; then
MAKE=1
echo "$NAME: Running \"make check\" ..."
[ -n "$VERBOSE" ] && make check || make check >/dev/null
R_MAKE=1
echo "$NAME: Running \"$MAKE check\" ..."
[ -n "$VERBOSE" ] && "$MAKE" check || "$MAKE" check >/dev/null
if [ $? -eq 0 ]; then
CHECK=1
RUN=$CHECK
R_CHECK=1
R_RUN=$R_CHECK
else
./src/ngircd/ngircd --help 2>/dev/null \
| grep "^ngircd" >/dev/null
[ $? -eq 0 ] && RUN=1
[ $? -eq 0 ] && R_RUN=1
fi
fi
fi
@@ -96,9 +99,14 @@ if [ -r "Makefile" ]; then
CC=$(grep "^CC = " Makefile | cut -d' ' -f3)
$CC --version 2>&1 | grep -i "GCC" >/dev/null
if [ $? -eq 0 ]; then
COMPILER=$($CC --version | head -1 \
| cut -d')' -f2 | cut -d' ' -f2)
COMPILER="gcc $COMPILER"
$CC --version 2>&1 | grep -i "Open64" >/dev/null
if [ $? -eq 0 ]; then
COMPILER="Open64"
else
COMPILER=$($CC --version | head -1 \
| cut -d')' -f2 | cut -d' ' -f2)
COMPILER="gcc $COMPILER"
fi
else
case "$CC" in
gcc*)
@@ -130,10 +138,10 @@ else
[ $? -eq 0 ] && COMMENT="(3)"
fi
[ -n "$CONFIGURE" ] && C="Y" || C="N"
[ -n "$MAKE" ] && M="Y" || M="N"
[ -n "$CHECK" ] && T="Y" || T="N"
[ -n "$RUN" ] && R="Y" || R="N"
[ -n "$R_CONFIGURE" ] && C="Y" || C="N"
[ -n "$R_MAKE" ] && M="Y" || M="N"
[ -n "$R_CHECK" ] && T="Y" || T="N"
[ -n "$R_RUN" ] && R="Y" || R="N"
[ -n "$COMMENT" ] && COMMENT=" $COMMENT"
echo

28
doc/Capabilities.txt Normal file
View File

@@ -0,0 +1,28 @@
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.
-- Capabilities.txt --
This document lists and describes the "IRC capabilities" that ngIRCd supports
and can be requested by a IRC/IRCv3 client that supports the "CAP" command.
ngIRCd implements the "IRC Client Capabilities Extension" as described here:
<http://www.leeh.co.uk/draft-mitchell-irc-capabilities-02.html>
I. Supported Capabilities
~~~~~~~~~~~~~~~~~~~~~~~~~
* "multi-prefix"
When requested, the multi-prefix client capability will cause the IRC
server to send all possible prefixes which apply to a user in NAMES and
WHO output.
See <http://ircv3.atheme.org/extensions/multi-prefix-3.1>.

View File

@@ -64,11 +64,19 @@ A: ngIRCd does not write its own log file. Instead, ngIRCd uses syslog(3).
Q: I cannot connect to remote peers when I use the chroot option, the
following is logged: "Can't resolve example.com: unknown error!".
A: see next question blow ...
Q: When running ngIRCd inside a chroot, no IP addresses can be translated
in DNS names, errors like "Name or service not known" are logged.
A: On Linux/glibc with chroot enabled you need to put some libraries inside
the chroot as well, notably libnss_dns; maybe others. Unfortunately, even
linking ngIRCd statically does not help this. The only known workaround
is to either disable chroot support or to link against dietlibc instead
of glibc. (tnx to Sebastian Siewior)
linking ngIRCd statically does not help this. So you can either copy
all the required files into the chroot directory:
$ mkdir -p ./chroot/etc ./chroot/lib
$ cp -a /etc/hosts /etc/resolv.conf /etc/nsswitch.conf ./chroot/etc/
$ cp -a /lib/libresolv* /lib/libnss_* ./chroot/lib/
Or you can try to link ngIRCd against an other C library (like dietlibc)
that doesn't depend on NSS modules and/or these files.
Q: I have added an [Oper] section, how do i log on as IRC operator?
A: You can use the /OPER command in your IRC client to become an IRC operator.

View File

@@ -9,13 +9,23 @@
-- GIT.txt --
The source code of ngIRCd is maintained using git, the stupid content
tracker.
The source code of ngIRCd is maintained using GIT, an distributed version
control system. Homepage including documentation: <http://git-scm.com/>.
I. Getting the source code
~~~~~~~~~~~~~~~~~~~~~~~~~~
To access the source tree anonymously, run:
I. Viewing the source code online
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The ngIRCd "GITweb" interface allows you to browse the GIT repository and
to see all individual files, tags, branches, commits etc.:
<http://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd.git>
II. Getting the source code
~~~~~~~~~~~~~~~~~~~~~~~~~~~
To access (copy, clone) the source tree repository anonymously, run:
$ git clone git://ngircd.barton.de/ngircd.git
@@ -23,23 +33,23 @@ Thereby a new folder "ngircd" will be created containing all the individual
source files.
The newly created directory ("ngircd") is the "working directory", all
git commands will be executed from within this directory in the future.
GIT commands will be executed from within this directory in the future.
Please note: When checking out a fresh copy of ngIRCd using git, the
Please note: When checking out a fresh copy of ngIRCd using GIT, the
configure script doesn't exist; you have to run the autogen.sh shell script
(which is included in the source tree) to generate it. This requires you to
have GNU automake and GNU autoconf installed on your system. Please see the
file INSTALL for details!
To update the git tree:
To update the local GIT repository:
$ git pull
This retrieves all changes and merges them into the current branch.
II. Contributing
~~~~~~~~~~~~~~~~
III. Contributing
~~~~~~~~~~~~~~~~~
Patches should be sent to the ngircd mailing list. List homepage:
http://arthur.barton.de/mailman/listinfo/ngircd-ml
@@ -48,7 +58,8 @@ If you do not want to send them to the list, you can also mail them
to Alex Barton, <alex@barton.de>.
III. Write Access
~~~~~~~~~~~~~~~~~
If you want to contribute a couple of patches and write access to the git
IV. Write Access
~~~~~~~~~~~~~~~~
If you want to contribute a couple of patches and write access to the GIT
repository would be handy, please contact Alex Barton, <alex@barton.de>.

View File

@@ -1,13 +1,12 @@
#
# 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
#
# 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.
# 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.
#
.tmpl:
@@ -17,9 +16,22 @@
SUFFIXES = .tmpl
static_docs = Bopm.txt FAQ.txt GIT.txt HowToRelease.txt PAM.txt Platforms.txt \
Protocol.txt README-AUX.txt README-BeOS.txt README-Interix.txt RFC.txt \
SSL.txt Services.txt
static_docs = \
Bopm.txt \
Capabilities.txt \
FAQ.txt \
GIT.txt \
HowToRelease.txt \
Modes.txt \
PAM.txt \
Platforms.txt \
Protocol.txt \
README-AUX.txt \
README-BeOS.txt \
README-Interix.txt \
RFC.txt \
Services.txt \
SSL.txt
doc_templates = sample-ngircd.conf.tmpl

77
doc/Modes.txt Normal file
View File

@@ -0,0 +1,77 @@
ngIRCd - Next Generation IRC Server
http://ngircd.barton.de/
(c)2001-2011 Alexander Barton and Contributors.
ngIRCd is free software and published under the
terms of the GNU General Public License.
-- Modes.txt --
This document lists the different user modes, channel modes, and channel
user modes that ngIRCd supports.
I. User Modes
~~~~~~~~~~~~~
User modes are attributes a user has in the network, regardless of the
channels he is using at the moment.
mode since description
a 0.3.0 User is away.
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.
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.
w 0.11.0 User wants to receive WALLOPS messages.
x 17 Hostname of this user is "cloaked".
II. Channel Modes
~~~~~~~~~~~~~~~~~
Channel modes are attributes of specific channels which are valid for all
users joined (or trying to join) to this channel. Some modes add and remove
users to lists (e.g. "invite list", "ban list"), others have parameters
(like "channel key"), most are simple flags (like "moderated").
mode since description
b 0.5.0 Add/remove a host mask to the ban list.
e 19 Add/remove a host mask to the exception list.
i 0.5.0 Channel is "invite only".
I 0.5.0 Add/remove a host mask to the invite list.
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.
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".
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.
z 16 Only users connected via SSL are allowed to join the channel.
III. Channel User Modes
~~~~~~~~~~~~~~~~~~~~~~~
Channel user modes are attributes that a particular user has in a specific
channel of which he is a member.
mode since description
o 0.2.0 User is channel operator and can op/kick/... other members.
v 0.2.0 User is "voiced" and can speak even if channel is moderated.
Notes
~~~~~
(1) This mode is not set by ngIRCd itself but by services. ngIRCd handles
the mode transparently and possibly adjusts its behaviour.

View File

@@ -1,9 +1,8 @@
ngIRCd - Next Generation IRC Server
http://ngircd.barton.de/
(c)2001-2010 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.
@@ -27,53 +26,62 @@ list can be updated. Thanks for your help!
Platform Compiler ngIRCd Date Tester C M T R See
--------------------------- ------------ ---------- -------- ------ - - - - ---
alpha/unknown/netbsd3.0 gcc 3.3.3 CVSHEAD 06-05-07 fw Y Y Y Y (3)
armv6l/unkn./linux-gnueabi gcc 4.4.5 19.1 12-06-04 goetz Y Y Y Y (5)
armv7l/unkn./linux-gnueabi gcc 4.4.3 19.1 12-04-29 goetz Y Y Y Y (5)
hppa/unknown/openbsd3.5 gcc 2.95.3 CVSHEAD 04-05-25 alex Y Y Y Y
hppa1.1/unknown/linux-gnu gcc 3.3.3 0.8.0 04-05-30 alex Y Y Y Y
hppa2.0/unknown/linux-gnu gcc 3.3.5 13~rc1 08-12-02 alex Y Y Y Y
hppa2.0w-hp-hpux11.11 gcc 4.2.3 14.1 09-07-22 goetz Y Y Y Y
i386/apple/darwin9.7.0 gcc 4.0.1 14.1 09-08-04 alex Y Y Y Y (3)
i386/apple/darwin10.4.0 gcc 4.2.1 17 10-11-07 alex Y Y Y Y (3)
i386/apple/darwin10.8.0 gcc 4.2.1 19 12-02-26 alex Y Y Y Y (3)
i386/apple/darwin11.3.0 gcc 4.2.1 19 12-02-26 alex Y Y Y Y (3)
i386/pc/solaris2.9 gcc 3.2.2 CVSHEAD 04-02-24 alex Y Y Y Y
i386/pc/solaris2.11 gcc 3.4.3 17 10-11-07 alex Y Y N Y (4)
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 17 10-11-07 alex Y Y Y Y (3)
i386/unknown/freebsd7.3 gcc 4.2.1 17 10-11-07 alex Y Y Y Y (3)
i686/unknown/gnu0.3 gcc 4.4.5 17 10-11-07 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)
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.1 gcc 2.95.3 CVSHEAD 04-02-24 alex Y Y Y Y
i386/unknown/netbsdelf1.6.2 gcc 2.95.3 18 11-07-10 goetz Y Y Y Y
i386/unknown/netbsdelf3.0.1 gcc 3.3.3 0.10.0-p1 06-08-30 alex Y Y Y Y (3)
i386/unknown/netbsdelf4.0 gcc 4.1.2 17 10-11-07 alex Y Y Y Y (3)
i386/unknown/netbsdelf5.0.2 gcc 4.1.3 17 10-11-07 alex Y Y Y Y (3)
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/interix3.5 gcc 3.3 15 10-01-22 alex Y Y N Y
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)
i686/pc/linux-gnu gcc 2.95.4 0.8.0 04-05-30 alex Y Y Y Y (1)
i686/pc/linux-gnu gcc 3.3.5 14.1 09-08-04 alex Y Y Y Y (1)
i386/pc/linux-gnu gcc 4.1.2 13~rc1 08-12-05 alex Y Y Y Y (1)
i686/pc/linux-gnu gcc 4.3.2 14.1 09-08-04 alex Y Y Y Y (1)
m68k/apple/aux3.0.1 gcc 2.7.2 17 10-11-07 alex Y Y N Y
m68k/apple/aux3.0.1 Orig. A/UX 17 10-11-07 alex Y Y N Y (2)
m68k/apple/aux3.1.1 Orig. A/UX 0.7.x-CVS 03-04-22 alex Y Y Y Y (2)
m68k/apple/aux3.1.1 gcc 2.7.2 19 12-02-26 alex Y Y N Y
m68k/apple/aux3.1.1 Orig. A/UX 19 12-02-26 alex Y Y N Y (2)
m68k/hp/hp-ux9.10 Orig. HPUX 0.7.x-CVS 03-04-30 goetz Y Y Y Y
m88k/dg/dgux5.4R3.10 gcc 2.5.8 CVSHEAD 04-03-15 alex Y Y ? ?
mipsel/unknown/linux-gnu gcc 4.1.2 18 11-07-05 goetz Y Y N Y (1)
mipsel/unknown/linux-gnu gcc 4.4.5 18 11-07-30 goetz Y Y Y Y (1)
powerpc/apple/darwin6.5 gcc 3.1 0.7.x-CVS 03-04-23 alex Y Y Y Y
powerpc/apple/darwin7.9.0 gcc 3.3 CVSHEAD 06-05-07 fw Y Y Y Y (3)
powerpc/apple/darwin8.1.0 gcc 4.0 0.9.x-CVS 05-06-27 alex Y Y Y Y
powerpc/apple/darwin7.9.0 gcc 3.3 19.1 12-05-22 goetz Y Y Y Y (3)
powerpc/apple/darwin8.11.0 gcc 4.0.1 18 11-07-02 goetz Y Y Y Y (3)
powerpc/unknown/linux-gnu gcc 3.3.3 0.8.0 04-05-30 alex Y Y Y Y
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 17 10-11-07 alex Y Y Y Y (3)
x86_64/unknown/linux-gnu gcc 4.3.2 17 10-11-07 alex Y Y Y Y (1)
x86_64/unknown/openbsd4.7 gcc 3.3.5 17 10-11-07 alex Y Y Y Y (3)
x86_64/unknown/freebsd8.1 gcc 4.2.1 19 12-02-26 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)
Notes
~~~~~
(1) i686/pc/linux-gnu & x86_64/unknown/linux-gnu:
(1) */*/linux-gnu (Linux platforms):
ngIRCd has been tested with various Linux distributions, such as SuSE,
RedHat, Debian, and Gentoo using Kernels 2.2.x, 2.4.x and 2.6.x with
various versions of the GNU C compiler (starting with 2.95.x and up to

View File

@@ -1,12 +1,10 @@
ngIRCd - Next Generation IRC Server
(c)2001-2010 Alexander Barton,
alex@barton.de, http://www.barton.de/
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.
terms of the GNU General Public License.
-- README-Interix.txt --
@@ -20,10 +18,13 @@ Windows Server 2003. SUA is supported on Windows Server 2003 R2, Windows
Server 2008 & 2008 R2, Windows Vista, and Windows 7 -- so ngIRCd should be
able to run on all of these platforms.
But please note that the poll() API function is not fully implemented by
SFU/SUA and therefore can't be used by ngIRCd -- which normally would be
the default. Please see <http://www.suacommunity.com/faqs.aspx> section
4.25 for details:
But please note that two things:
1. Don't use the poll() IO API
The poll() API function is not fully implemented by SFU/SUA and therefore
can't be used by ngIRCd -- which normally would be the default. Please see
<http://www.suacommunity.com/faqs.aspx> section 4.25 for details:
"If you do try to use the poll() API your program will block on the
API call forever. You must direct your program to build using the
@@ -35,3 +36,9 @@ So when running the ./configure script, you HAVE TO DISABLE poll() support:
ngIRCd then defaults to using the select() API function which works fine.
2. Use GNU make(1)
Starting with ngIRCd 18, our build system doesn't work with the default
make(1) binary of Interix, you should use GNU make instead (tested with
version 3.82 built from source).

View File

@@ -34,7 +34,7 @@ possible to handle unencrypted and encrypted connections on the same port!
This is a limitation of the IRC protocol ...
You have to set (at least) the following configuration variables in the
[GLOBAL] section of ngircd.conf(5): SSLPorts, SSLKeyFile, and SSLCertFile.
[SSL] section of ngircd.conf(5): Ports, KeyFile, and CertFile.
Now IRC clients are able to connect using SSL on the configured port(s).
(Using port 6697 for encrypted connections is common.)

View File

@@ -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-2011 Alexander Barton and Contributors.
ngIRCd is free software and published under the
terms of the GNU General Public License.
@@ -14,9 +13,12 @@ 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.
Services have been tested using "IRC Services" version 5.x by Andrew Church,
homepage: <http://www.ircservices.za.net/>. This document describes setting up
ngIRCd and these services.
Support for Services has been tested using "IRC Services" version 5.x by
Andrew Church (<http://achurch.org/services/>), Anope 1.9 using a
preliminary protocol module for ngIRCd (<http://www.anope.org/>), and
Atheme 7.0.2 or later.
This document describes setting up ngIRCd and these services.
Setting up ngIRCd
@@ -36,6 +38,31 @@ Example:
ServiceMask = *Serv
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!
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:
uplink
{
host = "server.irc.net"
port = 6667
password = "123abc"
}
serverinfo
{
name = "services.irc.net"
type = "ngircd"
}
Setting up IRC Services 5.1.x
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -66,5 +93,25 @@ In modules.conf:
The documentation of IRC Services can be found here:
<http://www.ircservices.za.net/docs/>
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!

View File

@@ -57,7 +57,7 @@
# This tells ngIRCd to write its current process ID to a file.
# Note that the pidfile is written AFTER chroot and switching the
# user ID, e.g. the directory the pidfile resides in must be
# writeable by the ngIRCd user and exist in the chroot directory.
# writable by the ngIRCd user and exist in the chroot directory.
;PidFile = /var/run/ngircd/ngircd.pid
# Ports on which the server should listen. There may be more than
@@ -110,7 +110,7 @@
[Options]
# Optional features and configuration options to further tweak the
# behavior of ngIRCd. If you wan't to get started quickly, you most
# behavior of ngIRCd. If you want to get started quickly, you most
# probably don't have to make changes here -- they are all optional.
# Are remote IRC operators allowed to control this server, e.g.
@@ -127,7 +127,13 @@
# 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!
;CloakHost = irc.example.net
;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!
;CloakHostModeX = cloaked.user
# Set every clients' user name to their nick name
;CloakUserToNick = yes
@@ -140,6 +146,8 @@
;DNS = yes
# Do IDENT lookups if ngIRCd has been compiled with support for it.
# Users identified using IDENT are registered without the "~" character
# prepended to their user name.
;Ident = yes
# Enhance user privacy slightly (useful for IRC server on TOR or I2P)
@@ -160,7 +168,22 @@
;OperServerMode = no
# Use PAM if ngIRCd has been compiled with support for it.
;PAM = no
# Users identified using PAM are registered without the "~" character
# prepended to their user name.
;PAM = yes
# When PAM is enabled, all clients are required to be authenticated
# using PAM; connecting to the server without successful PAM
# authentication isn't possible.
# If this option is set, clients not sending a password are still
# allowed to connect: they won't become "identified" and keep the "~"
# character prepended to their supplied user name.
# Please note: To make some use of this behavior, it most probably
# isn't useful to enable "Ident", "PAM" and "PAMIsOptional" at the
# same time, because you wouldn't be able to distinguish between
# Ident'ified and PAM-authenticated users: both don't have a "~"
# character prepended to their respective user names!
;PAMIsOptional = no
# Allow Pre-Defined Channels only (see Section [Channels])
;PredefChannelsOnly = no
@@ -170,7 +193,7 @@
# "PONG" reply.
;RequireAuthPing = no
# Silently drop all incomming CTCP requests.
# Silently drop all incoming CTCP requests.
;ScrubCTCP = no
# Syslog "facility" to which ngIRCd should send log messages.

View File

@@ -1,7 +1,7 @@
.\"
.\" ngircd(8) manual page template
.\"
.TH ngircd 8 "Dec 2010" ngircd "ngIRCd Manual"
.TH ngircd 8 "Mar 2012" ngircd "ngIRCd Manual"
.SH NAME
ngIRCd \- the next generation IRC daemon
.SH SYNOPSIS
@@ -26,7 +26,7 @@ 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.
.SH OPTIONS
The default behaviour of
The default behavior of
.BR ngircd
is to read its standard configuration file (see below), to detach from the
controlling terminal and to wait for clients.
@@ -68,7 +68,7 @@ Default "message of the day" (MOTD).
The daemon understands the following signals:
.TP
\fBTERM\fR
Shut down all conections and terminate the daemon.
Shut down all connections and terminate the daemon.
.TP
\fBHUP\fR
Shut down all listening sockets, re-read the configuration file and
@@ -76,6 +76,31 @@ re-initialize the daemon.
.SH HINTS
It's wise to use "ngircd \-\-configtest" to validate the configuration file
after changing it.
.SH DEBUGGING
When ngIRCd is compiled with debug code, that is, its source code has
been ./configure'd with "\-\-enable\-debug" and/or "\-\-enable\-sniffer" (witch
enables debug mode automatically as well), you can use two more command
line options and two more signals to debug problems with the daemon itself
or IRC clients:
.PP
\fBOptions:\fR
.TP
\fB\-d\fR, \fB\-\-debug\fR
Enable debug mode and log extra messages.
.TP
\fB\-s\fR, \fB\-\-sniffer\fR
Enable IRC protocol sniffer, which logs all sent and received IRC commands to
the console/syslog. This option requires that ngIRCd has been ./configure'd
with "\-\-enable\-sniffer" and enables debug mode automatically, too.
.PP
\fBSignals:\fR
.TP
\fBUSR1\fR
Toggle debug mode on and off during runtime.
.TP
\fBUSR2\fR
Dump internal server state to the console/syslog when debug mode is on (use
command line option \-\-debug or signal USR1).
.SH AUTHORS
Alexander Barton, <alex@barton.de>
.br

View File

@@ -1,7 +1,7 @@
.\"
.\" ngircd.conf(5) manual page template
.\"
.TH ngircd.conf 5 "Jun 2011" ngircd "ngIRCd Manual"
.TH ngircd.conf 5 "Mar 2012" ngircd "ngIRCd Manual"
.SH NAME
ngircd.conf \- configuration file of ngIRCd
.SH SYNOPSIS
@@ -128,13 +128,12 @@ if ngIRCd is using PAM!
\fBPidFile\fR (string)
This tells ngIRCd to write its current process ID to a file. Note that the
pidfile is written AFTER chroot and switching the user ID, e.g. the directory
the pidfile resides in must be writeable by the ngIRCd user and exist in the
the pidfile resides in must be writable by the ngIRCd user and exist in the
chroot directory (if configured, see above).
.TP
\fBPorts\fR (list of numbers)
Ports on which the server should listen. There may be more than one port,
separated with commas (","). Default: 6667, unless \fBSSL_Ports\fR are also
specified.
Ports on which the server should listen for unencrypted connections. There
may be more than one port, separated with commas (","). Default: 6667.
.TP
\fBServerGID\fR (string or number)
Group ID under which the ngIRCd should run; you can use the name of the
@@ -192,7 +191,7 @@ If a client fails to answer a PING with a PONG within <PongTimeout>
seconds, it will be disconnected by the server. Default: 20.
.SH [OPTIONS]
Optional features and configuration options to further tweak the behavior of
ngIRCd. If you wan't to get started quickly, you most probably don't have to
ngIRCd. If you want to get started quickly, you most probably don't have to
make changes here -- they are all optional.
.TP
\fBAllowRemoteOper\fR (boolean)
@@ -221,6 +220,17 @@ don't change.
Don't use the percentage sign ("%"), it is reserved for future extensions!
.RE
.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
.TP
\fBCloakUserToNick\fR (boolean)
Set every clients' user name to their nick name and hide the one supplied
by the IRC client. Default: no.
@@ -244,6 +254,8 @@ Default: yes.
\fBIdent\fR (boolean)
If ngIRCd is compiled with IDENT support this can be used to disable IDENT
lookups at run time.
Users identified using IDENT are registered without the "~" character
prepended to their user name.
Default: yes.
.TP
\fBMorePrivacy\fR (boolean)
@@ -274,8 +286,23 @@ only enable it if you have ircd-irc2 servers in your IRC network.
If ngIRCd is compiled with PAM support this can be used to disable all calls
to the PAM library at runtime; all users connecting without password are
allowed to connect, all passwords given will fail.
Users identified using PAM are registered without the "~" character
prepended to their user name.
Default: yes.
.TP
\fBPAMIsOptional\fR (boolean)
When PAM is enabled, all clients are required to be authenticated using PAM;
connecting to the server without successful PAM authentication isn't possible.
If this option is set, clients not sending a password are still allowed to
connect: they won't become "identified" and keep the "~" character prepended
to their supplied user name.
Please note:
To make some use of this behavior, it most probably isn't useful to enable
"Ident", "PAM" and "PAMIsOptional" at the same time, because you wouldn't be
able to distinguish between Ident'ified and PAM-authenticated users: both
don't have a "~" character prepended to their respective user names!
Default: no.
.TP
\fBPredefChannelsOnly\fR (boolean)
If enabled, no new channels can be created. Useful if you do not want to have
other channels than those defined in [Channel] sections in the configuration
@@ -291,7 +318,7 @@ Default: no.
If set to true, ngIRCd will silently drop all CTCP requests sent to it from
both clients and servers. It will also not forward CTCP requests to any
other servers. CTCP requests can be used to query user clients about which
software they are using and which versions said softare is. CTCP can also be
software they are using and which versions said software is. CTCP can also be
used to reveal clients IP numbers. ACTION CTCP requests are not blocked,
this means that /me commands will not be dropped, but please note that
blocking CTCP will disable file sharing between users!
@@ -314,10 +341,10 @@ All SSL-related configuration variables are located in the
section. Please note that this whole section is only recognized by ngIRCd
when it is compiled with support for SSL using OpenSSL or GnuTLS!
.TP
\fBSSLCertFile\fR (string)
\fBCertFile\fR (string)
SSL Certificate file of the private server key.
.TP
\fBSSLDHFile\fR (string)
\fBDHFile\fR (string)
Name of the Diffie-Hellman Parameter file. Can be created with GnuTLS
"certtool \-\-generate-dh-params" or "openssl dhparam". If this file is not
present, it will be generated on startup when ngIRCd was compiled with GnuTLS
@@ -325,14 +352,14 @@ support (this may take some time). If ngIRCd was compiled with OpenSSL, then
(Ephemeral)-Diffie-Hellman Key Exchanges and several Cipher Suites will not be
available.
.TP
\fBSSLKeyFile\fR (string)
\fBKeyFile\fR (string)
Filename of SSL Server Key to be used for SSL connections. This is required
for SSL/TLS support.
.TP
\fBSSLKeyFilePassword\fR (string)
\fBKeyFilePassword\fR (string)
OpenSSL only: Password to decrypt the private key file.
.TP
\fBSSLPorts\fR (list of numbers)
\fBPorts\fR (list of numbers)
Same as \fBPorts\fR , except that ngIRCd will expect incoming connections
to be SSL/TLS encrypted. Common port numbers for SSL-encrypted IRC are 6669
and 6697. Default: none.

View File

@@ -32,7 +32,9 @@ ng_ipaddr_init(ng_ipaddr_t *addr, const char *ip_str, UINT16 port)
assert(ip_str);
memset(&hints, 0, sizeof(hints));
#ifdef AI_NUMERICHOST
hints.ai_flags = AI_NUMERICHOST;
#endif
#ifndef WANT_IPV6 /* do not convert ipv6 addresses */
hints.ai_family = AF_INET;
#endif

View File

@@ -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
@@ -18,20 +18,84 @@ LINTARGS = -weak -warnunixlib +unixlib -booltype BOOLEAN \
sbin_PROGRAMS = ngircd
ngircd_SOURCES = ngircd.c array.c channel.c client.c conf.c conn.c conn-func.c \
conn-ssl.c conn-zip.c hash.c io.c irc.c irc-channel.c irc-info.c irc-login.c \
irc-mode.c irc-op.c irc-oper.c irc-server.c irc-write.c lists.c log.c \
match.c op.c numeric.c pam.c parse.c proc.c resolve.c sighandlers.c
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 client.h conf.h conf-ssl.h conn.h \
conn-func.h conn-ssl.h conn-zip.h hash.h io.h irc.h irc-channel.h \
irc-info.h irc-login.h irc-mode.h irc-op.h irc-oper.h irc-server.h \
irc-write.h lists.h log.h match.h numeric.h op.h pam.h parse.h proc.h \
resolve.h sighandlers.h defines.h messages.h
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

View File

@@ -84,7 +84,7 @@ extern void* array_get PARAMS((array* a, size_t membersize, size_t pos));
/* free the contents of this array. */
extern void array_free PARAMS((array* a));
/* overwrite array with zeroes before free */
/* overwrite array with zeros before free */
extern void array_free_wipe PARAMS((array* a));
/* return pointer to first element in this array */

View File

@@ -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
@@ -87,6 +87,14 @@ Channel_GetListBans(CHANNEL *c)
}
GLOBAL struct list_head *
Channel_GetListExcepts(CHANNEL *c)
{
assert(c != NULL);
return &c->list_excepts;
}
GLOBAL struct list_head *
Channel_GetListInvites(CHANNEL *c)
{
@@ -110,9 +118,12 @@ Channel_InitPredefined( void )
assert(channel_count == 0 || conf_chan != NULL);
for (i = 0; i < channel_count; i++, conf_chan++) {
if (!conf_chan->name[0] || !Channel_IsValidName(conf_chan->name)) {
Log(LOG_ERR, "Can't create pre-defined channel: invalid name: \"%s\"",
conf_chan->name);
if (!conf_chan->name[0])
continue;
if (!Channel_IsValidName(conf_chan->name)) {
Log(LOG_ERR,
"Can't create pre-defined channel: invalid name: \"%s\"",
conf_chan->name);
continue;
}
@@ -158,6 +169,7 @@ Free_Channel(CHANNEL *chan)
array_free(&chan->topic);
array_free(&chan->keyfile);
Lists_Free(&chan->list_bans);
Lists_Free(&chan->list_excepts);
Lists_Free(&chan->list_invites);
free(chan);
@@ -349,20 +361,31 @@ Channel_Quit( CLIENT *Client, const char *Reason )
} /* Channel_Quit */
/**
* Get number of channels this server knows and that are "visible" to
* the given client. If no client is given, all channels will be counted.
*
* @param Client The client to check or NULL.
* @return Number of channels visible to the client.
*/
GLOBAL unsigned long
Channel_Count( void )
Channel_CountVisible (CLIENT *Client)
{
CHANNEL *c;
unsigned long count = 0;
c = My_Channels;
while( c )
{
count++;
while(c) {
if (Client) {
if (!strchr(Channel_Modes(c), 's')
|| Channel_IsMemberOf(c, Client))
count++;
} else
count++;
c = c->next;
}
return count;
} /* Channel_Count */
}
GLOBAL unsigned long
@@ -774,6 +797,13 @@ Channel_SetMaxUsers(CHANNEL *Chan, unsigned long Count)
} /* Channel_SetMaxUsers */
/**
* Check if a client is allowed to send to a specific channel.
*
* @param Chan The channel to check.
* @param From The client that wants to send.
* @return true if the client is allowed to send, false otherwise.
*/
static bool
Can_Send_To_Channel(CHANNEL *Chan, CLIENT *From)
{
@@ -808,6 +838,9 @@ Can_Send_To_Channel(CHANNEL *Chan, CLIENT *From)
if (strchr(Channel_Modes(Chan), 'm'))
return false;
if (Lists_Check(&Chan->list_excepts, From))
return true;
return !Lists_Check(&Chan->list_bans, From);
}
@@ -999,8 +1032,17 @@ GLOBAL bool
Channel_AddBan(CHANNEL *c, const char *mask )
{
struct list_head *h = Channel_GetListBans(c);
LogDebug("Adding \"%s\" to \"%s\" %s list", mask, Channel_Name(c), "ban");
return Lists_Add(h, mask, false);
LogDebug("Adding \"%s\" to \"%s\" ban list", mask, Channel_Name(c));
return Lists_Add(h, mask, false, NULL);
}
GLOBAL bool
Channel_AddExcept(CHANNEL *c, const char *mask )
{
struct list_head *h = Channel_GetListExcepts(c);
LogDebug("Adding \"%s\" to \"%s\" exception list", mask, Channel_Name(c));
return Lists_Add(h, mask, false, NULL);
}
@@ -1008,30 +1050,31 @@ GLOBAL bool
Channel_AddInvite(CHANNEL *c, const char *mask, bool onlyonce)
{
struct list_head *h = Channel_GetListInvites(c);
LogDebug("Adding \"%s\" to \"%s\" %s list", mask, Channel_Name(c), "invite");
return Lists_Add(h, mask, onlyonce);
LogDebug("Adding \"%s\" to \"%s\" invite list", mask, Channel_Name(c));
return Lists_Add(h, mask, onlyonce, NULL);
}
static bool
ShowInvitesBans(struct list_head *head, CLIENT *Client, CHANNEL *Channel, bool invite)
ShowChannelList(struct list_head *head, CLIENT *Client, CHANNEL *Channel,
char *msg, char *msg_end)
{
struct list_elem *e;
char *msg = invite ? RPL_INVITELIST_MSG : RPL_BANLIST_MSG;
char *msg_end;
assert( Client != NULL );
assert( Channel != NULL );
assert (Client != NULL);
assert (Channel != NULL);
e = Lists_GetFirst(head);
while (e) {
if( ! IRC_WriteStrClient( Client, msg, Client_ID( Client ),
Channel_Name( Channel ), Lists_GetMask(e) )) return DISCONNECTED;
if (!IRC_WriteStrClient(Client, msg, Client_ID(Client),
Channel_Name(Channel),
Lists_GetMask(e)))
return DISCONNECTED;
e = Lists_GetNext(e);
}
msg_end = invite ? RPL_ENDOFINVITELIST_MSG : RPL_ENDOFBANLIST_MSG;
return IRC_WriteStrClient( Client, msg_end, Client_ID( Client ), Channel_Name( Channel ));
return IRC_WriteStrClient(Client, msg_end, Client_ID(Client),
Channel_Name(Channel));
}
@@ -1043,7 +1086,21 @@ Channel_ShowBans( CLIENT *Client, CHANNEL *Channel )
assert( Channel != NULL );
h = Channel_GetListBans(Channel);
return ShowInvitesBans(h, Client, Channel, false);
return ShowChannelList(h, Client, Channel, RPL_BANLIST_MSG,
RPL_ENDOFBANLIST_MSG);
}
GLOBAL bool
Channel_ShowExcepts( CLIENT *Client, CHANNEL *Channel )
{
struct list_head *h;
assert( Channel != NULL );
h = Channel_GetListExcepts(Channel);
return ShowChannelList(h, Client, Channel, RPL_EXCEPTLIST_MSG,
RPL_ENDOFEXCEPTLIST_MSG);
}
@@ -1055,7 +1112,8 @@ Channel_ShowInvites( CLIENT *Client, CHANNEL *Channel )
assert( Channel != NULL );
h = Channel_GetListInvites(Channel);
return ShowInvitesBans(h, Client, Channel, true);
return ShowChannelList(h, Client, Channel, RPL_INVITELIST_MSG,
RPL_ENDOFINVITELIST_MSG);
}

View File

@@ -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
@@ -38,6 +38,7 @@ typedef struct _CHANNEL
char key[CLIENT_PASS_LEN]; /* Channel key ("password", mode "k" ) */
unsigned long maxusers; /* Maximum number of members (mode "l") */
struct list_head list_bans; /* list head of banned users */
struct list_head list_excepts; /* list head of (ban) exception list */
struct list_head list_invites; /* list head of invited users */
array keyfile; /* Name of the channel key file */
} CHANNEL;
@@ -58,6 +59,7 @@ typedef POINTER CL2CHAN;
#endif
GLOBAL struct list_head *Channel_GetListBans PARAMS((CHANNEL *c));
GLOBAL struct list_head *Channel_GetListExcepts PARAMS((CHANNEL *c));
GLOBAL struct list_head *Channel_GetListInvites PARAMS((CHANNEL *c));
GLOBAL void Channel_Init PARAMS(( void ));
@@ -72,7 +74,7 @@ GLOBAL void Channel_Quit PARAMS(( CLIENT *Client, const char *Reason ));
GLOBAL void Channel_Kick PARAMS((CLIENT *Peer, CLIENT *Target, CLIENT *Origin,
const char *Name, const char *Reason));
GLOBAL unsigned long Channel_Count PARAMS(( void ));
GLOBAL unsigned long Channel_CountVisible PARAMS((CLIENT *Client));
GLOBAL unsigned long Channel_MemberCount PARAMS(( CHANNEL *Chan ));
GLOBAL int Channel_CountForUser PARAMS(( CLIENT *Client ));
@@ -123,10 +125,13 @@ GLOBAL char *Channel_TopicWho PARAMS(( CHANNEL *Chan ));
GLOBAL unsigned int Channel_CreationTime PARAMS(( CHANNEL *Chan ));
#endif
GLOBAL bool Channel_AddInvite PARAMS((CHANNEL *c, const char *Mask, bool OnlyOnce ));
GLOBAL bool Channel_AddBan PARAMS((CHANNEL *c, const char *Mask ));
GLOBAL bool Channel_AddBan PARAMS((CHANNEL *c, const char *Mask));
GLOBAL bool Channel_AddExcept PARAMS((CHANNEL *c, const char *Mask));
GLOBAL bool Channel_AddInvite PARAMS((CHANNEL *c, const char *Mask,
bool OnlyOnce));
GLOBAL bool Channel_ShowBans PARAMS((CLIENT *client, CHANNEL *c));
GLOBAL bool Channel_ShowExcepts PARAMS((CLIENT *client, CHANNEL *c));
GLOBAL bool Channel_ShowInvites PARAMS((CLIENT *client, CHANNEL *c));
GLOBAL void Channel_LogServer PARAMS((const char *msg));

143
src/ngircd/class.c Normal file
View File

@@ -0,0 +1,143 @@
/*
* 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
* User class management.
*/
#include "imp.h"
#include <assert.h>
#include <string.h>
#include "defines.h"
#include "array.h"
#include "conn.h"
#include "client.h"
#include "lists.h"
#include "match.h"
#include "stdio.h"
#include "exp.h"
#include "class.h"
struct list_head My_Classes[CLASS_COUNT];
char Reject_Reason[COMMAND_LEN];
GLOBAL void
Class_Init(void)
{
memset(My_Classes, 0, sizeof(My_Classes));
}
GLOBAL void
Class_Exit(void)
{
int i;
for (i = 0; i < CLASS_COUNT; Lists_Free(&My_Classes[i++]));
}
GLOBAL char *
Class_GetMemberReason(const int Class, CLIENT *Client)
{
char *reason;
assert(Class < CLASS_COUNT);
assert(Client != NULL);
reason = Lists_CheckReason(&My_Classes[Class], Client);
if (!reason)
return NULL;
if (!*reason)
reason = "listed";
switch(Class) {
case CLASS_GLINE:
snprintf(Reject_Reason, sizeof(Reject_Reason),
"\"%s\" (G-Line)", reason);
return Reject_Reason;
case CLASS_KLINE:
snprintf(Reject_Reason, sizeof(Reject_Reason),
"\"%s\" (K-Line)", reason);
return Reject_Reason;
}
return reason;
}
/**
* Check if a client is banned from this server: GLINE, KLINE.
*
* If a client isn't allowed to connect, it will be disconnected again.
*
* @param Client The client to check.
* @return CONNECTED if client is allowed to join, DISCONNECTED if not.
*/
GLOBAL bool
Class_HandleServerBans(CLIENT *Client)
{
char *rejectptr;
assert(Client != NULL);
rejectptr = Class_GetMemberReason(CLASS_GLINE, Client);
if (!rejectptr)
rejectptr = Class_GetMemberReason(CLASS_KLINE, Client);
if (rejectptr) {
Client_Reject(Client, rejectptr, true);
return DISCONNECTED;
}
return CONNECTED;
}
GLOBAL bool
Class_AddMask(const int Class, const char *Mask, time_t ValidUntil,
const char *Reason)
{
assert(Class < CLASS_COUNT);
assert(Mask != NULL);
assert(Reason != NULL);
return Lists_Add(&My_Classes[Class], Lists_MakeMask(Mask),
ValidUntil, Reason);
}
GLOBAL void
Class_DeleteMask(const int Class, const char *Mask)
{
assert(Class < CLASS_COUNT);
assert(Mask != NULL);
Lists_Del(&My_Classes[Class], Lists_MakeMask(Mask));
}
GLOBAL struct list_head *
Class_GetList(const int Class)
{
assert(Class < CLASS_COUNT);
return &My_Classes[Class];
}
GLOBAL void
Class_Expire(void)
{
Lists_Expire(&My_Classes[CLASS_GLINE], "G-Line");
Lists_Expire(&My_Classes[CLASS_KLINE], "K-Line");
}
/* -eof- */

41
src/ngircd/class.h Normal file
View File

@@ -0,0 +1,41 @@
/*
* 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 __class_h__
#define __class_h__
/**
* @file
* User class management.
*/
#define CLASS_KLINE 0
#define CLASS_GLINE 1
#define CLASS_COUNT 2
GLOBAL void Class_Init PARAMS((void));
GLOBAL void Class_Exit PARAMS((void));
GLOBAL bool Class_AddMask PARAMS((const int Class, const char *Mask,
const time_t ValidUntil, const char *Reason));
GLOBAL void Class_DeleteMask PARAMS((const int Class, const char *Mask));
GLOBAL char *Class_GetMemberReason PARAMS((const int Class, CLIENT *Client));
GLOBAL bool Class_HandleServerBans PARAMS((CLIENT *Client));
GLOBAL struct list_head *Class_GetList PARAMS((const int Class));
GLOBAL void Class_Expire PARAMS((void));
#endif /* __class_h__ */
/* -eof- */

73
src/ngircd/client-cap.c Normal file
View File

@@ -0,0 +1,73 @@
/*
* 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 __client_cap_c__
#include "portab.h"
/**
* @file
* Functions to deal with IRC Capabilities
*/
#include "imp.h"
#include <assert.h>
#include "defines.h"
#include "conn.h"
#include "client.h"
#include "log.h"
#include "exp.h"
#include "client-cap.h"
GLOBAL int
Client_Cap(CLIENT *Client)
{
assert (Client != NULL);
return Client->capabilities;
}
GLOBAL void
Client_CapSet(CLIENT *Client, int Cap)
{
assert(Client != NULL);
assert(Cap >= 0);
Client->capabilities = Cap;
LogDebug("Set new capability of \"%s\" to %d.",
Client_ID(Client), Client->capabilities);
}
GLOBAL void
Client_CapAdd(CLIENT *Client, int Cap)
{
assert(Client != NULL);
assert(Cap > 0);
Client->capabilities |= Cap;
LogDebug("Add capability %d, new capability of \"%s\" is %d.",
Cap, Client_ID(Client), Client->capabilities);
}
GLOBAL void
Client_CapDel(CLIENT *Client, int Cap)
{
assert(Client != NULL);
assert(Cap > 0);
Client->capabilities &= ~Cap;
LogDebug("Delete capability %d, new capability of \"%s\" is %d.",
Cap, Client_ID(Client), Client->capabilities);
}
/* -eof- */

31
src/ngircd/client-cap.h Normal file
View File

@@ -0,0 +1,31 @@
/*
* 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 __client_cap_h__
#define __client_cap_h__
/**
* @file
* Functions to deal with IRC Capabilities (header)
*/
#define CLIENT_CAP_PENDING 1 /* Capability negotiation pending */
#define CLIENT_CAP_SUPPORTED 2 /* Client supports IRC capabilities */
#define CLIENT_CAP_MULTI_PREFIX 4 /* multi-prefix */
GLOBAL int Client_Cap PARAMS((CLIENT *Client));
GLOBAL void Client_CapSet PARAMS((CLIENT *Client, int Cap));
GLOBAL void Client_CapAdd PARAMS((CLIENT *Client, int Cap));
GLOBAL void Client_CapDel PARAMS((CLIENT *Client, int Cap));
#endif

View File

@@ -37,6 +37,7 @@
#include "ngircd.h"
#include "channel.h"
#include "conf.h"
#include "conn-func.h"
#include "hash.h"
#include "irc-write.h"
#include "log.h"
@@ -69,6 +70,8 @@ static CLIENT *Init_New_Client PARAMS((CONN_ID Idx, CLIENT *Introducer,
static void Destroy_UserOrService PARAMS((CLIENT *Client,const char *Txt, const char *FwdMsg,
bool SendQuit));
static void cb_introduceClient PARAMS((CLIENT *Client, CLIENT *Prefix,
void *i));
GLOBAL void
Client_Init( void )
@@ -186,7 +189,6 @@ Init_New_Client(CONN_ID Idx, CLIENT *Introducer, CLIENT *TopServer,
assert(Idx >= NONE);
assert(Introducer != NULL);
assert(Hostname != NULL);
client = New_Client_Struct();
if (!client)
@@ -313,16 +315,29 @@ Client_Destroy( CLIENT *Client, const char *LogMsg, const char *FwdMsg, bool Sen
} /* Client_Destroy */
/**
* Set client hostname.
*
* If global hostname cloaking is in effect, don't set the real hostname
* but the configured one.
*
* @param Client The client of which the hostname should be set.
* @param Hostname The new hostname.
*/
GLOBAL void
Client_SetHostname( CLIENT *Client, const char *Hostname )
{
assert( Client != NULL );
assert( Hostname != NULL );
assert(Client != NULL);
assert(Hostname != NULL);
if (strlen(Conf_CloakHost)) {
strlcpy( Client->host, Conf_CloakHost, sizeof( Client->host ));
LogDebug("Updating hostname of \"%s\": \"%s\" -> \"%s\"",
Client_ID(Client), Client->host, Conf_CloakHost);
strlcpy(Client->host, Conf_CloakHost, sizeof(Client->host));
} else {
strlcpy( Client->host, Hostname, sizeof( Client->host ));
LogDebug("Updating hostname of \"%s\": \"%s\" -> \"%s\"",
Client_ID(Client), Client->host, Hostname);
strlcpy(Client->host, Hostname, sizeof(Client->host));
}
} /* Client_SetHostname */
@@ -768,7 +783,7 @@ Client_NextHop( CLIENT *Client )
* Return ID of a client: "client!user@host"
* 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 erlier results!
* nest invocations without overwriting earlier results!
* @param Client Pointer to client structure
* @return Pointer to global buffer containing the client ID
*/
@@ -793,7 +808,7 @@ 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 erlier results!
* 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
@@ -810,7 +825,9 @@ Client_MaskCloaked(CLIENT *Client)
return Client_Mask(Client);
snprintf(Mask_Buffer, GETID_LEN, "%s!%s@%s",
Client->id, Client->user, Client_ID(Client->introducer));
Client->id, Client->user,
*Conf_CloakHostModeX ? Conf_CloakHostModeX
: Client_ID(Client->introducer));
return Mask_Buffer;
} /* Client_MaskCloaked */
@@ -847,23 +864,37 @@ Client_Away( CLIENT *Client )
} /* Client_Away */
/**
* Make sure that a given nickname is valid.
*
* If the nickname is not valid for the given client, this function sends back
* the appropriate error messages.
*
* @param Client Client that wants to change the nickname.
* @param Nick New nick name.
* @returns true if nickname is valid, false otherwise.
*/
GLOBAL bool
Client_CheckNick( CLIENT *Client, char *Nick )
Client_CheckNick(CLIENT *Client, char *Nick)
{
assert( Client != NULL );
assert( Nick != NULL );
assert(Client != NULL);
assert(Nick != NULL);
if (! Client_IsValidNick( Nick ))
{
IRC_WriteStrClient( Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID( Client ), Nick );
if (!Client_IsValidNick(Nick)) {
if (strlen(Nick ) >= Conf_MaxNickLength)
IRC_WriteStrClient(Client, ERR_NICKNAMETOOLONG_MSG,
Client_ID(Client), Nick,
Conf_MaxNickLength - 1);
else
IRC_WriteStrClient(Client, ERR_ERRONEUSNICKNAME_MSG,
Client_ID(Client), Nick);
return false;
}
/* Nick bereits vergeben? */
if( Client_Search( Nick ))
{
/* den Nick gibt es bereits */
IRC_WriteStrClient( Client, ERR_NICKNAMEINUSE_MSG, Client_ID( Client ), Nick );
/* Nickname already registered? */
if (Client_Search(Nick)) {
IRC_WriteStrClient(Client, ERR_NICKNAMEINUSE_MSG,
Client_ID(Client), Nick);
return false;
}
@@ -1019,23 +1050,31 @@ Client_MyMaxUserCount( void )
} /* Client_MyMaxUserCount */
/**
* Check that a given nickname is valid.
*
* @param Nick the nickname to check.
* @returns true if nickname is valid, false otherwise.
*/
GLOBAL bool
Client_IsValidNick( const char *Nick )
Client_IsValidNick(const char *Nick)
{
const char *ptr;
static const char goodchars[] = ";0123456789-";
assert( Nick != NULL );
assert (Nick != NULL);
if( Nick[0] == '#' ) return false;
if( strchr( goodchars, Nick[0] )) return false;
if( strlen( Nick ) >= Conf_MaxNickLength) return false;
if (strchr(goodchars, Nick[0]))
return false;
if (strlen(Nick ) >= Conf_MaxNickLength)
return false;
ptr = Nick;
while( *ptr )
{
if (( *ptr < 'A' ) && ( ! strchr( goodchars, *ptr ))) return false;
if ( *ptr > '}' ) return false;
while (*ptr) {
if (*ptr < 'A' && !strchr(goodchars, *ptr ))
return false;
if (*ptr > '}')
return false;
ptr++;
}
@@ -1075,6 +1114,79 @@ Client_StartTime(CLIENT *Client)
} /* Client_Uptime */
/**
* Reject a client when logging in.
*
* This function is called when a client isn't allowed to connect to this
* server. Possible reasons are bad server password, bad PAM password,
* or that the client is G/K-Line'd.
*
* After calling this function, the client isn't connected any more.
*
* @param Client The client to reject.
* @param Reason The reason why the client has been rejected.
* @param InformClient If true, send the exact reason to the client.
*/
GLOBAL void
Client_Reject(CLIENT *Client, const char *Reason, bool InformClient)
{
char info[COMMAND_LEN];
assert(Client != NULL);
assert(Reason != NULL);
if (InformClient)
snprintf(info, sizeof(info), "Access denied: %s", Reason);
else
strcpy(info, "Access denied: Bad password?");
Log(LOG_ERR,
"User \"%s\" rejected (connection %d): %s!",
Client_Mask(Client), Client_Conn(Client), Reason);
Conn_Close(Client_Conn(Client), Reason, info, true);
}
/**
* Introduce a new user or service client in the network.
*
* @param From Remote server introducing the client or NULL (local).
* @param Client New client.
* @param Type Type of the client (CLIENT_USER or CLIENT_SERVICE).
*/
GLOBAL void
Client_Introduce(CLIENT *From, CLIENT *Client, int Type)
{
/* Set client type (user or service) */
Client_SetType(Client, Type);
if (From) {
if (Conf_IsService(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).",
Client_TypeText(Client), Client_Mask(Client),
Client_Modes(Client), Client_ID(From),
Client_ID(Client_Introducer(Client)),
Client_Hops(Client), Client_Hops(Client) > 1 ? "s": "");
} else {
Log(LOG_NOTICE, "%s \"%s\" registered (connection %d).",
Client_TypeText(Client), Client_Mask(Client),
Client_Conn(Client));
Log_ServerNotice('c', "Client connecting: %s (%s@%s) [%s] - %s",
Client_ID(Client), Client_User(Client),
Client_Hostname(Client),
Conn_IPA(Client_Conn(Client)),
Client_TypeText(Client));
}
/* Inform other servers */
IRC_WriteStrServersPrefixFlag_CB(From,
From != NULL ? From : Client_ThisServer(),
'\0', cb_introduceClient, (void *)Client);
} /* Client_Introduce */
static unsigned long
Count( CLIENT_TYPE Type )
{
@@ -1192,6 +1304,10 @@ Client_RegisterWhowas( CLIENT *Client )
assert( Client != NULL );
/* Don't register WHOWAS information when "MorePrivacy" is enabled. */
if (Conf_MorePrivacy)
return;
now = time(NULL);
/* Don't register clients that were connected less than 30 seconds. */
if( now - Client->starttime < 30 )
@@ -1290,6 +1406,59 @@ Destroy_UserOrService(CLIENT *Client, const char *Txt, const char *FwdMsg, bool
} /* Destroy_UserOrService */
/**
* Introduce a new user or service client to a remote server.
*
* This function differentiates between RFC1459 and RFC2813 server links and
* generates the appropriate commands to register the new user or service.
*
* @param To The remote server to inform.
* @param Prefix Prefix for the generated commands.
* @param data CLIENT structure of the new client.
*/
static void
cb_introduceClient(CLIENT *To, CLIENT *Prefix, void *data)
{
CLIENT *c = (CLIENT *)data;
CONN_ID conn;
char *modes, *user, *host;
modes = Client_Modes(c);
user = Client_User(c) ? Client_User(c) : "-";
host = Client_Hostname(c) ? Client_Hostname(c) : "-";
conn = Client_Conn(To);
if (Conn_Options(conn) & CONN_RFC1459) {
/* RFC 1459 mode: separate NICK and USER commands */
Conn_WriteStr(conn, "NICK %s :%d", Client_ID(c),
Client_Hops(c) + 1);
Conn_WriteStr(conn, ":%s USER %s %s %s :%s",
Client_ID(c), user, host,
Client_ID(Client_Introducer(c)), Client_Info(c));
if (modes[0])
Conn_WriteStr(conn, ":%s MODE %s +%s",
Client_ID(c), Client_ID(c), modes);
} else {
/* RFC 2813 mode: one combined NICK or SERVICE command */
if (Client_Type(c) == CLIENT_SERVICE
&& strchr(Client_Flags(To), 'S'))
IRC_WriteStrClientPrefix(To, Prefix,
"SERVICE %s %d * +%s %d :%s",
Client_Mask(c),
Client_MyToken(Client_Introducer(c)),
Client_Modes(c), Client_Hops(c) + 1,
Client_Info(c));
else
IRC_WriteStrClientPrefix(To, Prefix,
"NICK %s %d %s %s %d +%s :%s",
Client_ID(c), Client_Hops(c) + 1,
user, host,
Client_MyToken(Client_Introducer(c)),
modes, Client_Info(c));
}
} /* cb_introduceClient */
#ifdef DEBUG
GLOBAL void

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2008 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
@@ -29,12 +29,13 @@
#ifndef STRICT_RFC
# define CLIENT_WAITAUTHPING 512 /* waiting for AUTH PONG from client */
#endif
#define CLIENT_WAITCAPEND 1024 /* waiting for "CAP END" command */
#define CLIENT_TYPE int
#include "defines.h"
#if defined(__client_c__) | defined(S_SPLINT_S)
#if defined(__client_c__) | defined(__client_cap_c__) | defined(S_SPLINT_S)
typedef struct _CLIENT
{
@@ -58,6 +59,7 @@ typedef struct _CLIENT
bool oper_by_me; /* client is local IRC operator on this server? */
char away[CLIENT_AWAY_LEN]; /* AWAY text (valid if mode 'a' is set) */
char flags[CLIENT_FLAGS_LEN]; /* flags of the client */
int capabilities; /* enabled IRC capabilities */
} CLIENT;
#else
@@ -163,6 +165,11 @@ GLOBAL void Client_RegisterWhowas PARAMS(( CLIENT *Client ));
GLOBAL const char *Client_TypeText PARAMS((CLIENT *Client));
GLOBAL void Client_Reject PARAMS((CLIENT *Client, const char *Reason,
bool InformClient));
GLOBAL void Client_Introduce PARAMS((CLIENT *From, CLIENT *Client, int Type));
#ifdef DEBUG
GLOBAL void Client_DebugDump PARAMS((void));
#endif

View File

@@ -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
@@ -55,12 +55,10 @@ static bool Use_Log = true, Using_MotdFile = true;
static CONF_SERVER New_Server;
static int New_Server_Idx;
static size_t Conf_Oper_Count;
static size_t Conf_Channel_Count;
static char Conf_MotdFile[FNAME_LEN];
static void Set_Defaults PARAMS(( bool InitServers ));
static bool Read_Config PARAMS(( bool ngircd_starting ));
static bool Read_Config PARAMS(( bool TestOnly, bool IsStarting ));
static bool Validate_Config PARAMS(( bool TestOnly, bool Rehash ));
static void Handle_GLOBAL PARAMS(( int Line, char *Var, char *Arg ));
@@ -208,7 +206,7 @@ ports_parse(array *a, int Line, char *Arg)
GLOBAL void
Conf_Init( void )
{
Read_Config( true );
Read_Config(false, true);
Validate_Config(false, false);
}
@@ -220,7 +218,7 @@ Conf_Init( void )
GLOBAL bool
Conf_Rehash( void )
{
if (!Read_Config(false))
if (!Read_Config(false, false))
return false;
Validate_Config(false, true);
@@ -265,18 +263,18 @@ static void
opers_puts(void)
{
struct Conf_Oper *op;
size_t len;
size_t count, i;
len = array_length(&Conf_Opers, sizeof(*op));
count = array_length(&Conf_Opers, sizeof(*op));
op = array_start(&Conf_Opers);
while (len--) {
assert(op->name[0]);
for (i = 0; i < count; i++, op++) {
if (!op->name[0])
continue;
puts("[OPERATOR]");
printf(" Name = %s\n", op->name);
printf(" Password = %s\n", op->pwd);
printf(" Mask = %s\n\n", op->mask ? op->mask : "");
op++;
}
}
@@ -301,7 +299,7 @@ Conf_Test( void )
Use_Log = false;
if (! Read_Config(true))
if (!Read_Config(true, true))
return 1;
config_valid = Validate_Config(true, false);
@@ -360,6 +358,7 @@ Conf_Test( void )
printf(" AllowRemoteOper = %s\n", yesno_to_str(Conf_AllowRemoteOper));
printf(" ChrootDir = %s\n", Conf_Chroot);
printf(" CloakHost = %s\n", Conf_CloakHost);
printf(" CloakHostModeX = %s\n", Conf_CloakHostModeX);
printf(" CloakUserToNick = %s\n", yesno_to_str(Conf_CloakUserToNick));
#ifdef WANT_IPV6
printf(" ConnectIPv4 = %s\n", yesno_to_str(Conf_ConnectIPv6));
@@ -375,6 +374,7 @@ Conf_Test( void )
printf(" OperServerMode = %s\n", yesno_to_str(Conf_OperServerMode));
#ifdef PAM
printf(" PAM = %s\n", yesno_to_str(Conf_PAM));
printf(" PAMIsOptional = %s\n", yesno_to_str(Conf_PAMIsOptional));
#endif
printf(" PredefChannelsOnly = %s\n", yesno_to_str(Conf_PredefChannelsOnly));
#ifndef STRICT_RFC
@@ -493,6 +493,14 @@ Conf_SetServer( int ConfServer, CONN_ID Idx )
assert( ConfServer > NONE );
assert( Idx > NONE );
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;
}
Conf_Server[ConfServer].conn_id = Idx;
}
@@ -677,6 +685,7 @@ Set_Defaults(bool InitServers)
#endif
strlcpy(Conf_Chroot, CHROOT_DIR, sizeof(Conf_Chroot));
strcpy(Conf_CloakHost, "");
strcpy(Conf_CloakHostModeX, "");
Conf_CloakUserToNick = false;
Conf_ConnectIPv4 = true;
#ifdef WANT_IPV6
@@ -699,6 +708,7 @@ Set_Defaults(bool InitServers)
#else
Conf_PAM = false;
#endif
Conf_PAMIsOptional = false;
Conf_PredefChannelsOnly = false;
#ifdef SYSLOG
Conf_ScrubCTCP = false;
@@ -709,10 +719,6 @@ Set_Defaults(bool InitServers)
#endif
#endif
/* Initialize IRC operators and channels */
Conf_Oper_Count = 0;
Conf_Channel_Count = 0;
/* Initialize server configuration structures */
if (InitServers) {
for (i = 0; i < MAX_SERVERS;
@@ -782,11 +788,12 @@ Read_Motd(const char *filename)
* successfully; false otherwise.
*/
static bool
Read_Config( bool ngircd_starting )
Read_Config(bool TestOnly, bool IsStarting)
{
char section[LINE_LEN], str[LINE_LEN], *var, *arg, *ptr;
const UINT16 defaultport = 6667;
int line, i, n;
size_t count;
FILE *fd;
/* Open configuration file */
@@ -795,16 +802,19 @@ Read_Config( bool ngircd_starting )
/* No configuration file found! */
Config_Error( LOG_ALERT, "Can't read configuration \"%s\": %s",
NGIRCd_ConfFile, strerror( errno ));
if (!ngircd_starting)
if (!IsStarting)
return false;
Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME );
exit( 1 );
}
opers_free();
Set_Defaults( ngircd_starting );
Set_Defaults(IsStarting);
Config_Error( LOG_INFO, "Reading configuration from \"%s\" ...", NGIRCd_ConfFile );
if (TestOnly)
Config_Error(LOG_INFO,
"Reading configuration from \"%s\" ...",
NGIRCd_ConfFile );
/* Clean up server configuration structure: mark all already
* configured servers as "once" so that they are deleted
@@ -857,10 +867,13 @@ Read_Config( bool ngircd_starting )
/* Is this the beginning of a new section? */
if(( str[0] == '[' ) && ( str[strlen( str ) - 1] == ']' )) {
strlcpy( section, str, sizeof( section ));
if (strcasecmp(section, "[GLOBAL]") == 0 ||
strcasecmp(section, "[LIMITS]") == 0 ||
strcasecmp(section, "[OPTIONS]") == 0 ||
strcasecmp(section, "[SSL]") == 0)
if (strcasecmp(section, "[GLOBAL]") == 0
|| strcasecmp(section, "[LIMITS]") == 0
|| strcasecmp(section, "[OPTIONS]") == 0
#ifdef SSL_SUPPORT
|| strcasecmp(section, "[SSL]") == 0
#endif
)
continue;
if( strcasecmp( section, "[SERVER]" ) == 0 ) {
@@ -887,12 +900,30 @@ Read_Config( bool ngircd_starting )
else New_Server_Idx = i;
continue;
}
if (strcasecmp(section, "[CHANNEL]") == 0) {
Conf_Channel_Count++;
count = array_length(&Conf_Channels,
sizeof(struct Conf_Channel));
if (!array_alloc(&Conf_Channels,
sizeof(struct Conf_Channel),
count)) {
Config_Error(LOG_ERR,
"Could not allocate memory for new operator (line %d)",
line);
}
continue;
}
if (strcasecmp(section, "[OPERATOR]") == 0) {
Conf_Oper_Count++;
count = array_length(&Conf_Opers,
sizeof(struct Conf_Oper));
if (!array_alloc(&Conf_Opers,
sizeof(struct Conf_Oper),
count)) {
Config_Error(LOG_ERR,
"Could not allocate memory for new channel (line &d)",
line);
}
continue;
}
@@ -978,17 +1009,21 @@ Read_Config( bool ngircd_starting )
}
/**
* Check whether an string argument is true or false.
* Check whether a string argument is "true" or "false".
*
* @param Arg Input string.
* @returns true if string has been parsed as "yes"/"true"/"on".
* @returns true if the input string has been parsed as "yes", "true"
* (case insensitive) or a non-zero integer value.
*/
static bool
Check_ArgIsTrue( const char *Arg )
Check_ArgIsTrue(const char *Arg)
{
if( strcasecmp( Arg, "yes" ) == 0 ) return true;
if( strcasecmp( Arg, "true" ) == 0 ) return true;
if( atoi( Arg ) != 0 ) return true;
if (strcasecmp(Arg, "yes") == 0)
return true;
if (strcasecmp(Arg, "true") == 0)
return true;
if (atoi(Arg) != 0)
return true;
return false;
}
@@ -1289,7 +1324,9 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
else {
Conf_GID = (unsigned int)atoi(Arg);
if (!Conf_GID && strcmp(Arg, "0"))
Config_Error_NaN(Line, Var);
Config_Error(LOG_WARNING,
"%s, line %d: Value of \"%s\" is not a valid group name or ID!",
NGIRCd_ConfFile, Line, Var);
}
return;
}
@@ -1300,7 +1337,9 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
else {
Conf_UID = (unsigned int)atoi(Arg);
if (!Conf_UID && strcmp(Arg, "0"))
Config_Error_NaN(Line, Var);
Config_Error(LOG_WARNING,
"%s, line %d: Value of \"%s\" is not a valid user name or ID!",
NGIRCd_ConfFile, Line, Var);
}
return;
}
@@ -1440,6 +1479,12 @@ Handle_OPTIONS(int Line, char *Var, char *Arg)
Config_Error_TooLong(Line, Var);
return;
}
if (strcasecmp(Var, "CloakHostModeX") == 0) {
len = strlcpy(Conf_CloakHostModeX, Arg, sizeof(Conf_CloakHostModeX));
if (len >= sizeof(Conf_CloakHostModeX))
Config_Error_TooLong(Line, Var);
return;
}
if (strcasecmp(Var, "CloakUserToNick") == 0) {
Conf_CloakUserToNick = Check_ArgIsTrue(Arg);
return;
@@ -1483,6 +1528,10 @@ Handle_OPTIONS(int Line, char *Var, char *Arg)
WarnPAM(Line);
return;
}
if (strcasecmp(Var, "PAMIsOptional") == 0 ) {
Conf_PAMIsOptional = Check_ArgIsTrue(Arg);
return;
}
if (strcasecmp(Var, "PredefChannelsOnly") == 0) {
Conf_PredefChannelsOnly = Check_ArgIsTrue(Arg);
return;
@@ -1580,13 +1629,11 @@ Handle_OPERATOR( int Line, char *Var, char *Arg )
assert( Line > 0 );
assert( Var != NULL );
assert( Arg != NULL );
assert( Conf_Oper_Count > 0 );
op = array_alloc(&Conf_Opers, sizeof(*op), Conf_Oper_Count - 1);
if (!op) {
Config_Error(LOG_ERR, "Could not allocate memory for operator (%d:%s = %s)", Line, Var, Arg);
op = array_get(&Conf_Opers, sizeof(*op),
array_length(&Conf_Opers, sizeof(*op)) - 1);
if (!op)
return;
}
if (strcasecmp(Var, "Name") == 0) {
/* Name of IRC operator */
@@ -1752,21 +1799,17 @@ static void
Handle_CHANNEL(int Line, char *Var, char *Arg)
{
size_t len;
size_t chancount;
struct Conf_Channel *chan;
assert( Line > 0 );
assert( Var != NULL );
assert( Arg != NULL );
assert(Conf_Channel_Count > 0);
chancount = Conf_Channel_Count - 1;
chan = array_alloc(&Conf_Channels, sizeof(*chan), chancount);
if (!chan) {
Config_Error(LOG_ERR, "Could not allocate memory for predefined channel (%d:%s = %s)", Line, Var, Arg);
chan = array_get(&Conf_Channels, sizeof(*chan),
array_length(&Conf_Channels, sizeof(*chan)) - 1);
if (!chan)
return;
}
if (strcasecmp(Var, "Name") == 0) {
if (!Handle_Channelname(chan, Arg))
Config_Error_TooLong(Line, Var);
@@ -1913,8 +1956,10 @@ Validate_Config(bool Configtest, bool Rehash)
}
}
Log(LOG_DEBUG,
"Configuration: Operators=%d, Servers=%d[%d], Channels=%d",
Conf_Oper_Count, servers, servers_once, Conf_Channel_Count);
"Configuration: Operators=%ld, Servers=%d[%d], Channels=%ld",
array_length(&Conf_Opers, sizeof(struct Conf_Oper)),
servers, servers_once,
array_length(&Conf_Channels, sizeof(struct Conf_Channel)));
#endif
return config_valid;
@@ -2044,7 +2089,7 @@ Init_Server_Struct( CONF_SERVER *Server )
Proc_InitStruct(&Server->res_stat);
Server->conn_id = NONE;
memset(&Server->bind_addr, 0, sizeof(&Server->bind_addr));
memset(&Server->bind_addr, 0, sizeof(Server->bind_addr));
}
/* -eof- */

View File

@@ -154,7 +154,7 @@ GLOBAL bool Conf_OperCanMode;
/**
* If true, mask channel MODE commands of IRC operators to the server.
* Background: ircd2 will ignore channel MODE commands if an IRC operator
* gives chanel operator privileges to someone without being a channel operator
* gives channel operator privileges to someone without being a channel operator
* himself. This enables a workaround: it masks the MODE command as coming
* from the IRC server and not the IRC operator.
*/
@@ -166,6 +166,9 @@ GLOBAL bool Conf_AllowRemoteOper;
/** Cloaked hostname of the clients */
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? */
GLOBAL bool Conf_CloakUserToNick;
@@ -184,6 +187,9 @@ GLOBAL bool Conf_NoticeAuth;
/** Enable all usage of PAM, even when compiled with support for it */
GLOBAL bool Conf_PAM;
/** Don't require all clients to send a password an to be PAM authenticated */
GLOBAL bool Conf_PAMIsOptional;
/** Disable all CTCP commands except for /me ? */
GLOBAL bool Conf_ScrubCTCP;

View File

@@ -30,13 +30,30 @@
#include "conn-func.h"
/**
* Update "idle timestamp", the time of the last visible user action
* (e. g. like sending messages, joining or leaving channels).
*
* @param Idx Connection index.
*/
GLOBAL void
Conn_UpdateIdle( CONN_ID Idx )
Conn_UpdateIdle(CONN_ID Idx)
{
assert( Idx > NONE );
My_Connections[Idx].lastprivmsg = time( NULL );
assert(Idx > NONE);
My_Connections[Idx].lastprivmsg = time(NULL);
}
/**
* Update "ping timestamp", the time of the last outgoing PING request.
*
* @param Idx Connection index.
*/
GLOBAL void
Conn_UpdatePing(CONN_ID Idx)
{
assert(Idx > NONE);
My_Connections[Idx].lastping = time(NULL);
}
/*
* Get signon time of a connection.
@@ -65,35 +82,56 @@ Conn_LastPing( CONN_ID Idx )
} /* Conn_LastPing */
/**
* Add "penalty time" for a connection.
*
* During the "penalty time" the socket is ignored completely, no new data
* is read. This function only increases the penalty, it is not possible to
* decrease the penalty time.
*
* @param Idex Connection index.
* @param Seconds Seconds to add.
* @see Conn_ResetPenalty
*/
GLOBAL void
Conn_SetPenalty( CONN_ID Idx, time_t Seconds )
Conn_SetPenalty(CONN_ID Idx, time_t Seconds)
{
/* set Penalty-Delay for a socket.
* during the penalty, the socket is ignored completely, no new
* data is read. This function only increases the penalty, it is
* not possible to decrease the penalty time.
*/
time_t t;
assert( Idx > NONE );
assert( Seconds >= 0 );
t = time( NULL ) + Seconds;
if (t > My_Connections[Idx].delaytime)
assert(Idx > NONE);
assert(Seconds >= 0);
t = time(NULL);
if (My_Connections[Idx].delaytime < t)
My_Connections[Idx].delaytime = t;
My_Connections[Idx].delaytime += Seconds;
#ifdef DEBUG
Log(LOG_DEBUG, "Add penalty time on connection %d: %ld second(s).",
Idx, (long)Seconds);
Log(LOG_DEBUG,
"Add penalty time on connection %d: %ld second%s, total %ld second%s.",
Idx, (long)Seconds, Seconds != 1 ? "s" : "",
My_Connections[Idx].delaytime - t,
My_Connections[Idx].delaytime - t != 1 ? "s" : "");
#endif
} /* Conn_SetPenalty */
/**
* Reset the "penalty time" for one connection.
*
* @param Idx Connection index.
* @see Conn_SetPenalty
*/
GLOBAL void
Conn_ResetPenalty( CONN_ID Idx )
Conn_ResetPenalty(CONN_ID Idx)
{
assert( Idx > NONE );
assert(Idx > NONE);
My_Connections[Idx].delaytime = 0;
#ifdef DEBUG
Log(LOG_DEBUG, "Penalty time on connection %d has been reset.");
#endif
} /* Conn_ResetPenalty */

View File

@@ -29,7 +29,9 @@
#endif
GLOBAL void Conn_UpdateIdle PARAMS(( CONN_ID Idx ));
GLOBAL void Conn_UpdateIdle PARAMS((CONN_ID Idx));
GLOBAL void Conn_UpdatePing PARAMS((CONN_ID Idx));
GLOBAL time_t Conn_GetSignon PARAMS((CONN_ID Idx));
GLOBAL time_t Conn_GetIdle PARAMS(( CONN_ID Idx ));
GLOBAL time_t Conn_LastPing PARAMS(( CONN_ID Idx ));

View File

@@ -52,9 +52,10 @@ static bool ConnSSL_LoadServerKey_openssl PARAMS(( SSL_CTX *c ));
#include <gnutls/x509.h>
#define DH_BITS 2048
#define DH_BITS_MIN 1024
static gnutls_certificate_credentials_t x509_cred;
static gnutls_dh_params_t dh_params;
static bool ConnSSL_LoadServerKey_gnutls PARAMS(( void ));
#endif
@@ -426,7 +427,7 @@ ConnSSL_Init_SSL(CONNECTION *c)
ConnSSL_Free(c);
return false;
}
gnutls_dh_set_prime_bits(c->ssl_state.gnutls_session, DH_BITS);
gnutls_dh_set_prime_bits(c->ssl_state.gnutls_session, DH_BITS_MIN);
#endif
Conn_OPTION_ADD(c, CONN_SSL);
return true;
@@ -548,17 +549,18 @@ ConnSSL_LogCertInfo( CONNECTION *c )
assert(ssl);
Log(LOG_INFO, "New %s connection using cipher %s on socket %d.",
SSL_get_version(ssl), SSL_get_cipher(ssl), c->sock);
Log(LOG_INFO, "Connection %d: initialized %s using cipher %s.",
c->sock, SSL_get_version(ssl), SSL_get_cipher(ssl));
#endif
#ifdef HAVE_LIBGNUTLS
gnutls_session_t sess = c->ssl_state.gnutls_session;
gnutls_cipher_algorithm_t cipher = gnutls_cipher_get(sess);
Log(LOG_INFO, "New %s connection using cipher %s-%s on socket %d.",
Log(LOG_INFO, "Connection %d: initialized %s using cipher %s-%s.",
c->sock,
gnutls_protocol_get_name(gnutls_protocol_get_version(sess)),
gnutls_cipher_get_name(cipher),
gnutls_mac_get_name(gnutls_mac_get(sess)), c->sock);
gnutls_mac_get_name(gnutls_mac_get(sess)));
#endif
}

View File

@@ -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
@@ -9,6 +9,8 @@
* Please read the file COPYING, README and AUTHORS for more information.
*/
#undef DEBUG_BUFFER
#define CONN_MODULE
#include "portab.h"
@@ -63,6 +65,7 @@
#include "ngircd.h"
#include "array.h"
#include "client.h"
#include "class.h"
#include "conf.h"
#include "conn-ssl.h"
#include "conn-zip.h"
@@ -79,8 +82,8 @@
#define SERVER_WAIT (NONE - 1)
#define MAX_COMMANDS 3
#define MAX_COMMANDS_SERVER 10
#define MAX_COMMANDS_SERVICE MAX_COMMANDS_SERVER
#define MAX_COMMANDS_SERVER_MIN 10
#define MAX_COMMANDS_SERVICE 10
static bool Handle_Write PARAMS(( CONN_ID Idx ));
@@ -367,7 +370,7 @@ cb_clientserver_ssl(int sock, short what)
/**
* Initialite connecion module.
* Initialize connecion module.
*/
GLOBAL void
Conn_Init( void )
@@ -433,12 +436,13 @@ Conn_Exit( void )
* they don't hold connections open that the main process wants to close.
*/
GLOBAL void
Conn_CloseAllSockets(void)
Conn_CloseAllSockets(int ExceptOf)
{
CONN_ID idx;
for(idx = 0; idx < Pool_Size; idx++) {
if(My_Connections[idx].sock > NONE)
if(My_Connections[idx].sock > NONE &&
My_Connections[idx].sock != ExceptOf)
close(My_Connections[idx].sock);
}
}
@@ -739,6 +743,9 @@ Conn_Handler(void)
Check_Servers();
Check_Connections();
/* Expire outdated class/list items */
Class_Expire();
/* Look for non-empty read buffers ... */
for (i = 0; i < Pool_Size; i++) {
if ((My_Connections[i].sock > NONE)
@@ -929,22 +936,25 @@ Conn_Write( CONN_ID Idx, char *Data, size_t Len )
assert( Data != NULL );
assert( Len > 0 );
c = Conn_GetClient(Idx);
assert( c != NULL);
/* Servers do get special write buffer limits, so they can generate
* all the messages that are required while peering. */
if (Client_Type(c) == CLIENT_SERVER)
writebuf_limit = WRITEBUFFER_SLINK_LEN;
/* Is the socket still open? A previous call to Conn_Write()
* may have closed the connection due to a fatal error.
* In this case it is sufficient to return an error, as well. */
if( My_Connections[Idx].sock <= NONE ) {
if (My_Connections[Idx].sock <= NONE) {
LogDebug("Skipped write on closed socket (connection %d).", Idx);
return false;
}
/* Make sure that there still exists a CLIENT structure associated
* with this connection and check if this is a server or not: */
c = Conn_GetClient(Idx);
if (c) {
/* Servers do get special write buffer limits, so they can
* generate all the messages that are required while peering. */
if (Client_Type(c) == CLIENT_SERVER)
writebuf_limit = WRITEBUFFER_SLINK_LEN;
} else
LogDebug("Write on socket without client (connection %d)!?", Idx);
#ifdef ZLIB
if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ZIP )) {
/* Compressed link:
@@ -1007,7 +1017,7 @@ Conn_Write( CONN_ID Idx, char *Data, size_t Len )
GLOBAL void
Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClient )
{
/* Close connection. Open pipes of asyncronous resolver
/* Close connection. Open pipes of asynchronous resolver
* sub-processes are closed down. */
CLIENT *c;
@@ -1216,6 +1226,20 @@ Conn_SyncServerStruct(void)
} /* SyncServerStruct */
/**
* Get IP address string of a connection.
*
* @param Idx Connection index.
* @return Pointer to a global buffer containing the IP address as string.
*/
GLOBAL const char *
Conn_GetIPAInfo(CONN_ID Idx)
{
assert(Idx > NONE);
return ng_ipaddr_tostr(&My_Connections[Idx].addr);
}
/**
* Send out data of write buffer; connect new sockets.
*
@@ -1255,9 +1279,11 @@ Handle_Write( CONN_ID Idx )
return true;
}
#ifdef DEBUG_BUFFER
LogDebug
("Handle_Write() called for connection %d, %ld bytes pending ...",
Idx, wdatalen);
#endif
#ifdef SSL_SUPPORT
if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_SSL )) {
@@ -1326,6 +1352,8 @@ New_Connection(int Sock)
assert(Sock > NONE);
LogDebug("Accepting new connection on socket %d ...", Sock);
new_sock_len = (int)sizeof(new_addr);
new_sock = accept(Sock, (struct sockaddr *)&new_addr,
(socklen_t *)&new_sock_len);
@@ -1410,7 +1438,7 @@ New_Connection(int Sock)
return -1;
}
c = Client_NewLocal(new_sock, ip_str, CLIENT_UNKNOWN, false);
c = Client_NewLocal(new_sock, NULL, CLIENT_UNKNOWN, false);
if (!c) {
Log(LOG_ALERT,
"Can't accept connection: can't create client structure!");
@@ -1561,7 +1589,7 @@ Read_Request( CONN_ID Idx )
if (!array_catb(&My_Connections[Idx].zip.rbuf, readbuf,
(size_t) len)) {
Log(LOG_ERR,
"Could not append recieved data to zip input buffer (connn %d): %d bytes!",
"Could not append received data to zip input buffer (connection %d): %d bytes!",
Idx, len);
Conn_Close(Idx, "Receive buffer space exhausted", NULL,
false);
@@ -1571,7 +1599,9 @@ Read_Request( CONN_ID Idx )
#endif
{
if (!array_catb( &My_Connections[Idx].rbuf, readbuf, len)) {
Log( LOG_ERR, "Could not append recieved data to input buffer (connn %d): %d bytes!", Idx, len );
Log(LOG_ERR,
"Could not append received data to input buffer (connection %d): %d bytes!",
Idx, len);
Conn_Close(Idx, "Receive buffer space exhausted", NULL, false );
}
}
@@ -1644,16 +1674,15 @@ Handle_Buffer(CONN_ID Idx)
assert(c != NULL);
/* Servers do get special command limits, so they can process
* all the messages that are required while peering. */
/* Servers get special command limits that depend on the user count */
switch (Client_Type(c)) {
case CLIENT_SERVER:
/* Allow servers to send more commands in the first 10 secods
maxcmd = (int)(Client_UserCount() / 5)
+ MAX_COMMANDS_SERVER_MIN;
/* Allow servers to handle even more commands while peering
* to speed up server login and network synchronisation. */
if (starttime - Client_StartTime(c) < 10)
maxcmd = MAX_COMMANDS_SERVER * 5;
else
maxcmd = MAX_COMMANDS_SERVER;
if (Conn_LastPing(Idx) == 0)
maxcmd *= 5;
break;
case CLIENT_SERVICE:
maxcmd = MAX_COMMANDS_SERVICE; break;
@@ -1753,8 +1782,10 @@ Handle_Buffer(CONN_ID Idx)
return 0; /* error -> connection has been closed */
array_moveleft(&My_Connections[Idx].rbuf, 1, len);
#ifdef DEBUG_BUFFER
LogDebug("Connection %d: %d bytes left in read buffer.",
Idx, array_bytes(&My_Connections[Idx].rbuf));
#endif
#ifdef ZLIB
if ((!old_z) && (My_Connections[Idx].options & CONN_ZIP) &&
(array_bytes(&My_Connections[Idx].rbuf) > 0)) {
@@ -1818,7 +1849,7 @@ Check_Connections(void)
time(NULL) - Conf_PingTimeout) {
/* We need to send a PING ... */
LogDebug("Connection %d: sending PING ...", i);
My_Connections[i].lastping = time(NULL);
Conn_UpdatePing(i);
Conn_WriteStr(i, "PING :%s",
Client_ID(Client_ThisServer()));
}
@@ -1904,6 +1935,14 @@ New_Server( int Server , ng_ipaddr_t *dest)
assert( Server > NONE );
/* Make sure that the remote server hasn't re-linked to this server
* asynchronously on its own */
if (Conf_Server[Server].conn_id > NONE) {
Log(LOG_INFO,
"Connection to \"%s\" meanwhile re-established, aborting preparation.");
return;
}
if (!ng_ipaddr_tostr_r(dest, ip_str)) {
Log(LOG_WARNING, "New_Server: Could not convert IP to string");
return;
@@ -1977,7 +2016,7 @@ New_Server( int Server , ng_ipaddr_t *dest)
Client_SetToken( c, TOKEN_OUTBOUND );
/* Register connection */
Conf_Server[Server].conn_id = new_sock;
Conf_SetServer(Server, new_sock);
My_Connections[new_sock].sock = new_sock;
My_Connections[new_sock].addr = *dest;
My_Connections[new_sock].client = c;
@@ -2051,13 +2090,14 @@ Init_Socket( int Sock )
/* Set type of service (TOS) */
#if defined(IPPROTO_IP) && defined(IPTOS_LOWDELAY)
value = IPTOS_LOWDELAY;
LogDebug("Setting IP_TOS on socket %d to IPTOS_LOWDELAY.", Sock);
if (setsockopt(Sock, IPPROTO_IP, IP_TOS, &value,
(socklen_t) sizeof(value))) {
LogDebug("Can't set socket option IP_TOS: %s!",
strerror(errno));
/* ignore this error */
}
} else
LogDebug("IP_TOS on socket %d has been set to IPTOS_LOWDELAY.",
Sock);
#endif
return true;
@@ -2098,6 +2138,7 @@ cb_Connect_to_Server(int fd, UNUSED short events)
/* Read result from pipe */
len = Proc_Read(&Conf_Server[i].res_stat, dest_addrs, sizeof(dest_addrs));
Proc_Close(&Conf_Server[i].res_stat);
if (len == 0) {
/* Error resolving hostname: reset server structure */
Conf_Server[i].conn_id = NONE;
@@ -2141,6 +2182,7 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
char *identptr;
#ifdef IDENTAUTH
char readbuf[HOST_LEN + 2 + CLIENT_USER_LEN];
char *ptr;
#else
char readbuf[HOST_LEN + 1];
#endif
@@ -2157,6 +2199,7 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
/* Read result from pipe */
len = Proc_Read(&My_Connections[i].proc_stat, readbuf, sizeof readbuf -1);
Proc_Close(&My_Connections[i].proc_stat);
if (len == 0)
return;
@@ -2192,11 +2235,30 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
#ifdef IDENTAUTH
++identptr;
if (*identptr) {
Log(LOG_INFO, "IDENT lookup for connection %d: \"%s\".", i, identptr);
Client_SetUser(c, identptr, true);
if (Conf_NoticeAuth)
ptr = identptr;
while (*ptr) {
if ((*ptr < '0' || *ptr > '9') &&
(*ptr < 'A' || *ptr > 'Z') &&
(*ptr < 'a' || *ptr > 'z'))
break;
ptr++;
}
if (*ptr) {
/* Erroneous IDENT reply */
Log(LOG_NOTICE,
"Got invalid IDENT reply for connection %d! Ignored.",
i);
} else {
Log(LOG_INFO,
"IDENT lookup for connection %d: \"%s\".",
i, identptr);
Client_SetUser(c, identptr, true);
}
if (Conf_NoticeAuth) {
(void)Conn_WriteStr(i,
"NOTICE AUTH :*** Got ident response");
"NOTICE AUTH :*** Got %sident response",
*ptr ? "invalid " : "");
}
} else {
Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i);
if (Conf_NoticeAuth && Conf_Ident)
@@ -2204,6 +2266,7 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
"NOTICE AUTH :*** No ident response");
}
#endif
Class_HandleServerBans(c);
}
#ifdef DEBUG
else Log( LOG_DEBUG, "Resolver: discarding result for already registered connection %d.", i );

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2010 Alexander Barton <alex@barton.de>
* 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
@@ -106,7 +106,7 @@ GLOBAL long WCounter;
GLOBAL void Conn_Init PARAMS((void ));
GLOBAL void Conn_Exit PARAMS(( void ));
GLOBAL void Conn_CloseAllSockets PARAMS((void));
GLOBAL void Conn_CloseAllSockets PARAMS((int ExceptOf));
GLOBAL unsigned int Conn_InitListeners PARAMS(( void ));
GLOBAL void Conn_ExitListeners PARAMS(( void ));
@@ -131,6 +131,8 @@ Conn_UsesSSL(UNUSED CONN_ID Idx)
{ return false; }
#endif
GLOBAL const char *Conn_GetIPAInfo PARAMS((CONN_ID Idx));
GLOBAL long Conn_Count PARAMS((void));
GLOBAL long Conn_CountMax PARAMS((void));
GLOBAL long Conn_CountAccepted PARAMS((void));

View File

@@ -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
@@ -17,98 +17,188 @@
* Global constants ("#defines") used by the ngIRCd.
*/
/* Internal flags */
/** Flag: there is no connection. */
#define NONE -1
#define FNAME_LEN 256 /* Max. length of file name */
/** Flag: connection is (still) established. */
#define CONNECTED true
#define LINE_LEN 256 /* Max. length of a line in the
configuration file */
#define HOST_LEN 256 /* Max. lenght of fully qualified host
names (e. g. "abc.domain.tld") */
#define MAX_SERVERS 16 /* Max. count of configurable servers */
#define MAX_WHOWAS 64 /* Max. number of WHOWAS items */
#define DEFAULT_WHOWAS 5 /* default count for WHOWAS command */
#define CONNECTION_POOL 100 /* Size of default connection pool */
#define CLIENT_ID_LEN 64 /* Max. length of an IRC ID; see RFC
RFC 2812 section 1.1 and 1.2.1 */
#define CLIENT_NICK_LEN_DEFAULT 10 /* Default nick length, see. RFC 2812
* section 1.2.1 */
#define CLIENT_NICK_LEN 32 /* Maximum nick name length */
#define CLIENT_PASS_LEN 21 /* Max. password length */
#define CLIENT_USER_LEN 10 /* Max. length of user name ("login")
see RFC 2812, section 1.2.1 */
#define CLIENT_NAME_LEN 32 /* Max. length of "real names" */
#define CLIENT_HOST_LEN 64 /* Max. host name length */
#define CLIENT_MODE_LEN 9 /* Max. lenth of all client modes */
#define CLIENT_INFO_LEN 64 /* Max. length of server info texts */
#define CLIENT_AWAY_LEN 128 /* Max. length of away messages */
#define CLIENT_FLAGS_LEN 100 /* Max. length of client flags */
#define CHANNEL_NAME_LEN 51 /* Max. length of a channel name, see
RFC 2812 section 1.3 */
#define CHANNEL_MODE_LEN 9 /* Max. length of channel modes */
#define COMMAND_LEN 513 /* Max. IRC command length, see. RFC
2812 section 3.2 */
#define READBUFFER_LEN 2048 /* Size of the read buffer of a
connection in bytes. */
#define WRITEBUFFER_FLUSH_LEN 4096 /* Size of a write buffer that triggers
buffer flushing if more space is
needed for storing data. */
#define WRITEBUFFER_MAX_LEN 32768 /* Maximum size of the write buffer of a
connection in bytes. */
#define WRITEBUFFER_SLINK_LEN 65536 /* Maximum size of the write buffer of a
server link connection in bytes. */
#define PROTOVER "0210" /* Implemented IRC protocol version,
see RFC 2813 section 4.1.1. */
#define PROTOIRC "-IRC" /* Protocol suffix, see RFC 2813
section 4.1.1 */
#define PROTOIRCPLUS "-IRC+" /* Protocol suffix used by the IRC+
protocol, see doc/Protocol.txt */
#ifdef IRCPLUS
# define IRCPLUSFLAGS "CHLS" /* Standard IRC+ flags */
#endif
#define STARTUP_DELAY 1 /* Delay outgoing connections n seconds
after startup. */
#define RECONNECT_DELAY 3 /* Time to delay re-connect attempts
in seconds. */
#define USERMODES "aciorswx" /* Supported user modes. */
#define CHANMODES "biIklmnoOPstvz" /* Supported channel modes. */
#define CONNECTED true /* Internal status codes. */
/** Flag: connection isn't established (any more). */
#define DISCONNECTED false
#define DEFAULT_AWAY_MSG "Away" /* Away message for users connected to
linked servers. */
/** Tag for outbound server links. */
#define TOKEN_OUTBOUND -2
#define DEFAULT_TOPIC_ID "-Server-" /* Default ID for "topic owner". */
#define CONFIG_FILE "/ngircd.conf" /* Configuration file name. */
#define MOTD_FILE "/ngircd.motd" /* Name of the MOTD file. */
#define CHROOT_DIR "" /* Default chroot() directory. */
#define PID_FILE "" /* Default file for the process ID. */
/* Generic buffer sizes */
#define ERROR_DIR "/tmp" /* Error directory used in debug mode */
/** Max. length of a line in the configuration file. */
#define LINE_LEN 256
#define MAX_LOG_MSG_LEN 256 /* Max. length of a log message. */
/** Max. length of a log message. */
#define MAX_LOG_MSG_LEN 256
#define TOKEN_OUTBOUND -2 /* Tag for outbound server links. */
/** Max. length of file name. */
#define FNAME_LEN 256
#define NOTICE_TXTPREFIX "" /* Prefix for NOTICEs from the server
to users. Some servers use '*'. */
/** Max. lenght of fully qualified host names (e. g. "abc.domain.tld"). */
#define HOST_LEN 256
/* Size of structures */
/** Max. count of configurable servers. */
#define MAX_SERVERS 16
/** Max. number of WHOWAS list items that can be stored. */
#define MAX_WHOWAS 64
/** Size of default connection pool. */
#define CONNECTION_POOL 100
/* Hard-coded (default) options */
/** Delay after startup before outgoing connections are initiated in seconds. */
#define STARTUP_DELAY 1
/** Time to delay re-connect attempts in seconds. */
#define RECONNECT_DELAY 3
/** Configuration file name. */
#define CONFIG_FILE "/ngircd.conf"
/** Name of the MOTD file. */
#define MOTD_FILE "/ngircd.motd"
/** Default chroot() directory. */
#define CHROOT_DIR ""
/** Default file for the process ID. */
#define PID_FILE ""
/* Sizes of "IRC elements": nicks, users, ... */
/** Max. length of an IRC ID (incl. NULL); see RFC 2812 section 1.1 and 1.2.1. */
#define CLIENT_ID_LEN 64
/** Default nick length (including NULL), see. RFC 2812 section 1.2.1. */
#define CLIENT_NICK_LEN_DEFAULT 10
/** Maximum nick name 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
/** Max. length of "real names" (including NULL). */
#define CLIENT_NAME_LEN 32
/** Max. host name length (including NULL). */
#define CLIENT_HOST_LEN 64
/** Max. length of all client modes (including NULL). */
#define CLIENT_MODE_LEN 16
/** Max. length of server info texts (including NULL). */
#define CLIENT_INFO_LEN 64
/** Max. length of away messages (including NULL). */
#define CLIENT_AWAY_LEN 128
/** Max. length of client flags (including NULL). */
#define CLIENT_FLAGS_LEN 16
/** Max. length of a channel name (including NULL), see RFC 2812 section 1.3. */
#define CHANNEL_NAME_LEN 51
/** Max. length of channel modes (including NULL). */
#define CHANNEL_MODE_LEN 9
/** Max. IRC command length (including NULL), see. RFC 2812 section 3.2. */
#define COMMAND_LEN 513
/* Read and write buffer sizes */
/** Size of the read buffer of a connection in bytes. */
#define READBUFFER_LEN 2048
/** Size that triggers write buffer flushing if more space is needed. */
#define WRITEBUFFER_FLUSH_LEN 4096
/** Maximum size of the write buffer of a connection in bytes. */
#define WRITEBUFFER_MAX_LEN 32768
/** Maximum size of the write buffer of a server link connection in bytes. */
#define WRITEBUFFER_SLINK_LEN 65536
/* IRC/IRC+ protocol */
/** Implemented IRC protocol version, see RFC 2813 section 4.1.1. */
#define PROTOVER "0210"
/** Protocol suffix, see RFC 2813 section 4.1.1. */
#define PROTOIRC "-IRC"
/** Protocol suffix used by the IRC+ protocol, see <doc/Protocol.txt>. */
#define PROTOIRCPLUS "-IRC+"
#ifdef IRCPLUS
/** Standard IRC+ flags. */
# define IRCPLUSFLAGS "CHLS"
#endif
/** Supported user modes. */
#define USERMODES "acCiorRswx"
/** Supported channel modes. */
#define CHANMODES "beiIklmnoOPrRstvz"
/** Away message for users connected to linked servers. */
#define DEFAULT_AWAY_MSG "Away"
/** Default ID for "topic owner". */
#define DEFAULT_TOPIC_ID "-Server-"
/** Prefix for NOTICEs from the server to users. Some servers use '*'. */
#define NOTICE_TXTPREFIX ""
/** Suffix for oversized messages that have been shortened and cut off. */
#define CUT_TXTSUFFIX "[CUT]"
/* 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
/** Max. number of channel modes with arguments per MODE command. */
#define MAX_HNDL_MODES_ARG 5
/** Max. number of WHO replies. */
#define MAX_RPL_WHO 25
/** Max. number of WHOIS replies. */
#define MAX_RPL_WHOIS 10
/** Default count of WHOWAS command replies. */
#define DEF_RPL_WHOWAS 5
/** Max count of WHOWAS command replies. */
#define MAX_RPL_WHOWAS 25
#define CUT_TXTSUFFIX "[CUT]" /* Suffix for oversized messages that
have been shortened and cut off. */
#endif

View File

@@ -41,6 +41,7 @@ typedef struct {
#define INIT_IOEVENT { NULL, -1, 0, NULL }
#define IO_ERROR 4
#define MAX_EVENTS 100
#ifdef HAVE_EPOLL_CREATE
# define IO_USE_EPOLL 1
@@ -54,7 +55,7 @@ typedef struct {
# ifdef HAVE_SYS_DEVPOLL_H
# define IO_USE_DEVPOLL 1
# else
# ifdef HAVE_POLL
# if defined(HAVE_POLL) && defined(HAVE_POLL_H)
# define IO_USE_POLL 1
# else
# ifdef HAVE_SELECT
@@ -160,39 +161,34 @@ io_dispatch_devpoll(struct timeval *tv)
{
struct dvpoll dvp;
time_t sec = tv->tv_sec * 1000;
int i, total, ret, timeout = tv->tv_usec + sec;
int i, ret, timeout = tv->tv_usec + sec;
short what;
struct pollfd p[100];
struct pollfd p[MAX_EVENTS];
if (timeout < 0)
timeout = 1000;
total = 0;
do {
dvp.dp_timeout = timeout;
dvp.dp_nfds = 100;
dvp.dp_fds = p;
ret = ioctl(io_masterfd, DP_POLL, &dvp);
total += ret;
if (ret <= 0)
return total;
for (i=0; i < ret ; i++) {
what = 0;
if (p[i].revents & (POLLIN|POLLPRI))
what = IO_WANTREAD;
dvp.dp_timeout = timeout;
dvp.dp_nfds = MAX_EVENTS;
dvp.dp_fds = p;
ret = ioctl(io_masterfd, DP_POLL, &dvp);
if (p[i].revents & POLLOUT)
what |= IO_WANTWRITE;
for (i=0; i < ret ; i++) {
what = 0;
if (p[i].revents & (POLLIN|POLLPRI))
what = IO_WANTREAD;
if (p[i].revents && !what) {
/* other flag is set, probably POLLERR */
what = IO_ERROR;
}
io_docallback(p[i].fd, what);
if (p[i].revents & POLLOUT)
what |= IO_WANTWRITE;
if (p[i].revents && !what) {
/* other flag is set, probably POLLERR */
what = IO_ERROR;
}
} while (ret == 100);
io_docallback(p[i].fd, what);
}
return total;
return ret;
}
@@ -462,37 +458,30 @@ static int
io_dispatch_epoll(struct timeval *tv)
{
time_t sec = tv->tv_sec * 1000;
int i, total = 0, ret, timeout = tv->tv_usec + sec;
struct epoll_event epoll_ev[100];
int i, ret, timeout = tv->tv_usec + sec;
struct epoll_event epoll_ev[MAX_EVENTS];
short type;
if (timeout < 0)
timeout = 1000;
do {
ret = epoll_wait(io_masterfd, epoll_ev, 100, timeout);
total += ret;
if (ret <= 0)
return total;
ret = epoll_wait(io_masterfd, epoll_ev, MAX_EVENTS, timeout);
for (i = 0; i < ret; i++) {
type = 0;
if (epoll_ev[i].events & (EPOLLERR | EPOLLHUP))
type = IO_ERROR;
for (i = 0; i < ret; i++) {
type = 0;
if (epoll_ev[i].events & (EPOLLERR | EPOLLHUP))
type = IO_ERROR;
if (epoll_ev[i].events & (EPOLLIN | EPOLLPRI))
type |= IO_WANTREAD;
if (epoll_ev[i].events & (EPOLLIN | EPOLLPRI))
type |= IO_WANTREAD;
if (epoll_ev[i].events & EPOLLOUT)
type |= IO_WANTWRITE;
if (epoll_ev[i].events & EPOLLOUT)
type |= IO_WANTWRITE;
io_docallback(epoll_ev[i].data.fd, type);
}
io_docallback(epoll_ev[i].data.fd, type);
}
timeout = 0;
} while (ret == 100);
return total;
return ret;
}
static void
@@ -576,58 +565,50 @@ io_event_change_kqueue(int fd, short what, const int action)
static int
io_dispatch_kqueue(struct timeval *tv)
{
int i, total = 0, ret;
struct kevent kev[100];
int i, ret;
struct kevent kev[MAX_EVENTS];
struct kevent *newevents;
struct timespec ts;
int newevents_len;
ts.tv_sec = tv->tv_sec;
ts.tv_nsec = tv->tv_usec * 1000;
do {
newevents_len = (int) array_length(&io_evcache, sizeof (struct kevent));
newevents = (newevents_len > 0) ? array_start(&io_evcache) : NULL;
assert(newevents_len >= 0);
newevents_len = (int) array_length(&io_evcache, sizeof (struct kevent));
newevents = (newevents_len > 0) ? array_start(&io_evcache) : NULL;
assert(newevents_len >= 0);
ret = kevent(io_masterfd, newevents, newevents_len, kev, 100, &ts);
if (newevents && ret != -1)
array_trunc(&io_evcache);
ret = kevent(io_masterfd, newevents, newevents_len, kev, MAX_EVENTS, &ts);
if (newevents && ret != -1)
array_trunc(&io_evcache);
total += ret;
if (ret <= 0)
return total;
for (i = 0; i < ret; i++) {
io_debug("dispatch_kqueue: fd, kev.flags", (int)kev[i].ident, kev[i].flags);
if (kev[i].flags & (EV_EOF|EV_ERROR)) {
if (kev[i].flags & EV_ERROR)
Log(LOG_ERR, "kevent fd %d: EV_ERROR (%s)",
(int)kev[i].ident, strerror((int)kev[i].data));
io_docallback((int)kev[i].ident, IO_ERROR);
continue;
}
switch (kev[i].filter) {
case EVFILT_READ:
io_docallback((int)kev[i].ident, IO_WANTREAD);
break;
case EVFILT_WRITE:
io_docallback((int)kev[i].ident, IO_WANTWRITE);
break;
default:
LogDebug("Unknown kev.filter number %d for fd %d",
kev[i].filter, kev[i].ident);
/* Fall through */
case EV_ERROR:
io_docallback((int)kev[i].ident, IO_ERROR);
break;
}
for (i = 0; i < ret; i++) {
io_debug("dispatch_kqueue: fd, kev.flags", (int)kev[i].ident, kev[i].flags);
if (kev[i].flags & (EV_EOF|EV_ERROR)) {
if (kev[i].flags & EV_ERROR)
Log(LOG_ERR, "kevent fd %d: EV_ERROR (%s)",
(int)kev[i].ident, strerror((int)kev[i].data));
io_docallback((int)kev[i].ident, IO_ERROR);
continue;
}
ts.tv_sec = 0;
ts.tv_nsec = 0;
} while (ret == 100);
return total;
switch (kev[i].filter) {
case EVFILT_READ:
io_docallback((int)kev[i].ident, IO_WANTREAD);
break;
case EVFILT_WRITE:
io_docallback((int)kev[i].ident, IO_WANTWRITE);
break;
default:
LogDebug("Unknown kev.filter number %d for fd %d",
kev[i].filter, kev[i].ident);
/* Fall through */
case EV_ERROR:
io_docallback((int)kev[i].ident, IO_ERROR);
break;
}
}
return ret;
}
static void

291
src/ngircd/irc-cap.c Normal file
View File

@@ -0,0 +1,291 @@
/*
* 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
* Handler for IRC capability ("CAP") commands
*/
#include "imp.h"
#include <assert.h>
#include <string.h>
#include "defines.h"
#include "conn.h"
#include "channel.h"
#include "client-cap.h"
#include "irc-write.h"
#include "log.h"
#include "login.h"
#include "messages.h"
#include "parse.h"
#include "exp.h"
#include "irc-cap.h"
bool Handle_CAP_LS PARAMS((CLIENT *Client, char *Arg));
bool Handle_CAP_LIST PARAMS((CLIENT *Client, char *Arg));
bool Handle_CAP_REQ PARAMS((CLIENT *Client, char *Arg));
bool Handle_CAP_ACK PARAMS((CLIENT *Client, char *Arg));
bool Handle_CAP_CLEAR PARAMS((CLIENT *Client));
bool Handle_CAP_END PARAMS((CLIENT *Client));
void Set_CAP_Negotiation PARAMS((CLIENT *Client));
int Parse_CAP PARAMS((int Capabilities, char *Args));
char *Get_CAP_String PARAMS((int Capabilities));
/**
* Handler for the IRCv3 "CAP" 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_CAP(CLIENT *Client, REQUEST *Req)
{
assert(Client != NULL);
assert(Req != NULL);
/* Bad number of prameters? */
if (Req->argc < 1 || Req->argc > 2)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
LogDebug("Got \"%s %s\" command from \"%s\" ...",
Req->command, Req->argv[0], Client_ID(Client));
if (Req->argc == 1) {
if (strcasecmp(Req->argv[0], "CLEAR") == 0)
return Handle_CAP_CLEAR(Client);
if (strcasecmp(Req->argv[0], "END") == 0)
return Handle_CAP_END(Client);
}
if (Req->argc >= 1 && Req->argc <= 2) {
if (strcasecmp(Req->argv[0], "LS") == 0)
return Handle_CAP_LS(Client, Req->argv[1]);
if (strcasecmp(Req->argv[0], "LIST") == 0)
return Handle_CAP_LIST(Client, Req->argv[1]);
}
if (Req->argc == 2) {
if (strcasecmp(Req->argv[0], "REQ") == 0)
return Handle_CAP_REQ(Client, Req->argv[1]);
if (strcasecmp(Req->argv[0], "ACK") == 0)
return Handle_CAP_ACK(Client, Req->argv[1]);
}
return IRC_WriteStrClient(Client, ERR_INVALIDCAP_MSG,
Client_ID(Client), Req->argv[0]);
}
/**
* Handler for the "CAP LS" command.
*
* @param Client The client from which this command has been received.
* @param Arg Command argument or NULL.
* @returns CONNECTED or DISCONNECTED.
*/
bool
Handle_CAP_LS(CLIENT *Client, UNUSED char *Arg)
{
assert(Client != NULL);
Set_CAP_Negotiation(Client);
return IRC_WriteStrClient(Client,
"CAP %s LS :multi-prefix",
Client_ID(Client));
}
/**
* Handler for the "CAP LIST" command.
*
* @param Client The client from which this command has been received.
* @param Arg Command argument or NULL.
* @returns CONNECTED or DISCONNECTED.
*/
bool
Handle_CAP_LIST(CLIENT *Client, UNUSED char *Arg)
{
assert(Client != NULL);
return IRC_WriteStrClient(Client, "CAP %s LIST :%s", Client_ID(Client),
Get_CAP_String(Client_Cap(Client)));
}
/**
* Handler for the "CAP REQ" command.
*
* @param Client The client from which this command has been received.
* @param Arg Command argument.
* @returns CONNECTED or DISCONNECTED.
*/
bool
Handle_CAP_REQ(CLIENT *Client, char *Arg)
{
int new_cap;
assert(Client != NULL);
assert(Arg != NULL);
Set_CAP_Negotiation(Client);
new_cap = Parse_CAP(Client_Cap(Client), Arg);
if (new_cap < 0)
return IRC_WriteStrClient(Client, "CAP %s NAK :%s",
Client_ID(Client), Arg);
Client_CapSet(Client, new_cap);
return IRC_WriteStrClient(Client, "CAP %s ACK :%s",
Client_ID(Client), Arg);
}
/**
* Handler for the "CAP ACK" command.
*
* @param Client The client from which this command has been received.
* @param Arg Command argument.
* @returns CONNECTED or DISCONNECTED.
*/
bool
Handle_CAP_ACK(UNUSED CLIENT *Client, UNUSED char *Arg)
{
assert(Client != NULL);
assert(Arg != NULL);
return CONNECTED;
}
/**
* Handler for the "CAP CLEAR" command.
*
* @param Client The client from which this command has been received.
* @returns CONNECTED or DISCONNECTED.
*/
bool
Handle_CAP_CLEAR(CLIENT *Client)
{
int cap_old;
assert(Client != NULL);
cap_old = Client_Cap(Client);
if (cap_old & CLIENT_CAP_MULTI_PREFIX)
Client_CapDel(Client, CLIENT_CAP_MULTI_PREFIX);
return IRC_WriteStrClient(Client, "CAP %s ACK :%s", Client_ID(Client),
Get_CAP_String(cap_old));
}
/**
* Handler for the "CAP END" command.
*
* @param Client The client from which this command has been received.
* @returns CONNECTED or DISCONNECTED.
*/
bool
Handle_CAP_END(CLIENT *Client)
{
assert(Client != NULL);
if (Client_Type(Client) != CLIENT_USER) {
/* User is still logging in ... */
Client_CapDel(Client, CLIENT_CAP_PENDING);
if (Client_Type(Client) == CLIENT_WAITCAPEND) {
/* Only "CAP END" was missing: log in! */
return Login_User(Client);
}
}
return CONNECTED;
}
/**
* Set CAP negotiation status and mark client as "supports capabilities".
*
* @param Client The client to handle.
*/
void
Set_CAP_Negotiation(CLIENT *Client)
{
assert(Client != NULL);
if (Client_Type(Client) != CLIENT_USER)
Client_CapAdd(Client, CLIENT_CAP_PENDING);
Client_CapAdd(Client, CLIENT_CAP_SUPPORTED);
}
/**
* Parse capability string and return numeric flag value.
*
* @param Args The string containing space-separated capability names.
* @return Changed capability flags or 0 on error.
*/
int
Parse_CAP(int Capabilities, char *Args)
{
static char tmp[COMMAND_LEN];
char *ptr;
assert(Args != NULL);
strlcpy(tmp, Args, sizeof(tmp));
ptr = strtok(tmp, " ");
while (ptr) {
if (*ptr == '-') {
/* drop capabilities */
ptr++;
if (strcmp(ptr, "multi-prefix") == 0)
Capabilities &= ~CLIENT_CAP_MULTI_PREFIX;
else
return -1;
} else {
/* request capabilities */
if (strcmp(ptr, "multi-prefix") == 0)
Capabilities |= CLIENT_CAP_MULTI_PREFIX;
else
return -1;
}
ptr = strtok(NULL, " ");
}
return Capabilities;
}
/**
* Return textual representation of capability flags.
*
* Please note: this function returns a pointer to a global buffer and
* therefore isn't thread safe!
*
* @param Capabilities Capability flags (bitmask).
* @return Pointer to textual representation.
*/
char
*Get_CAP_String(int Capabilities)
{
static char txt[COMMAND_LEN];
txt[0] = '\0';
if (Capabilities & CLIENT_CAP_MULTI_PREFIX)
strlcat(txt, "multi-prefix ", sizeof(txt));
return txt;
}
/* -eof- */

24
src/ngircd/irc-cap.h Normal file
View File

@@ -0,0 +1,24 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2010 Alexander Barton (alex@barton.de).
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*/
#ifndef __irc_cap_h__
#define __irc_cap_h__
/**
* @file
* Handler for IRC capability ("CAP") commands (header)
*/
GLOBAL bool IRC_CAP PARAMS((CLIENT *Client, REQUEST *Req));
#endif
/* -eof- */

View File

@@ -31,6 +31,7 @@
#include "match.h"
#include "messages.h"
#include "parse.h"
#include "irc.h"
#include "irc-info.h"
#include "irc-write.h"
#include "conf.h"
@@ -81,7 +82,7 @@ static bool
join_allowed(CLIENT *Client, CHANNEL *chan, const char *channame,
const char *key)
{
bool is_invited, is_banned;
bool is_invited, is_banned, is_exception;
const char *channel_modes;
/* Allow IRC operators to overwrite channel limits */
@@ -89,9 +90,10 @@ join_allowed(CLIENT *Client, CHANNEL *chan, const char *channame,
return true;
is_banned = Lists_Check(Channel_GetListBans(chan), Client);
is_exception = Lists_Check(Channel_GetListExcepts(chan), Client);
is_invited = Lists_Check(Channel_GetListInvites(chan), Client);
if (is_banned && !is_invited) {
if (is_banned && !is_invited && !is_exception) {
/* Client is banned from channel (and not on invite list) */
IRC_WriteStrClient(Client, ERR_BANNEDFROMCHAN_MSG,
Client_ID(Client), channame);
@@ -137,6 +139,13 @@ join_allowed(CLIENT *Client, CHANNEL *chan, const char *channame,
return false;
}
if (strchr(channel_modes, 'R') && !strchr(Client_Modes(Client), 'R')) {
/* Only registered users are allowed! */
IRC_WriteStrClient(Client, ERR_REGONLYCHANNEL_MSG,
Client_ID(Client), channame);
return false;
}
return true;
} /* join_allowed */
@@ -237,7 +246,7 @@ join_forward(CLIENT *Client, CLIENT *target, CHANNEL *chan,
IRC_WriteStrChannelPrefix(Client, chan, target, false,
"JOIN :%s", channame);
/* syncronize channel modes */
/* synchronize channel modes */
if (modes[1]) {
IRC_WriteStrChannelPrefix(Client, chan, target, false,
"MODE %s +%s %s", channame,
@@ -294,9 +303,9 @@ join_send_topic(CLIENT *Client, CLIENT *target, CHANNEL *chan,
*
* See RFC 2812, 3.2.1 "Join message"; RFC 2813, 4.2.1 "Join message".
*
* @param Client The client from which this command has been received
* @param Req Request structure with prefix and all parameters
* @returns CONNECTED or DISCONNECTED
* @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_JOIN( CLIENT *Client, REQUEST *Req )
@@ -305,8 +314,8 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
CLIENT *target;
CHANNEL *chan;
assert( Client != NULL );
assert( Req != NULL );
assert (Client != NULL);
assert (Req != NULL);
/* Bad number of arguments? */
if (Req->argc < 1 || Req->argc > 2)
@@ -320,7 +329,8 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
target = Client;
if (!target)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, Client_ID(Client), Req->prefix);
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix);
/* Is argument "0"? */
if (Req->argc == 1 && !strncmp("0", Req->argv[0], 2))
@@ -352,24 +362,35 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
chan = Channel_Search(channame);
if (!chan && Conf_PredefChannelsOnly) {
/* channel must be created, but server does not allow this */
IRC_WriteStrClient(Client, ERR_BANNEDFROMCHAN_MSG, Client_ID(Client), channame);
break;
/* channel must be created, but forbidden by config */
IRC_WriteStrClient(Client, ERR_BANNEDFROMCHAN_MSG,
Client_ID(Client), channame);
goto join_next;
}
/* Local client? */
if (Client_Type(Client) == CLIENT_USER) {
if (chan) {
/* Already existing channel: already member? */
if (Channel_IsMemberOf(chan, Client))
goto join_next;
}
/* Test if the user has reached the channel limit */
if ((Conf_MaxJoins > 0) &&
(Channel_CountForUser(Client) >= Conf_MaxJoins))
return IRC_WriteStrClient(Client,
(Channel_CountForUser(Client) >= Conf_MaxJoins)) {
if (!IRC_WriteStrClient(Client,
ERR_TOOMANYCHANNELS_MSG,
Client_ID(Client), channame);
Client_ID(Client), channame))
return DISCONNECTED;
goto join_next;
}
if (chan) {
/* Already existing channel: check if the
* client is allowed to join */
if (!join_allowed(Client, chan, channame, key))
break;
goto join_next;
} else {
/* New channel: first user will become channel
* operator unless this is a modeless channel */
@@ -392,7 +413,7 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
/* Join channel (and create channel if it doesn't exist) */
if (!Channel_Join(target, channame))
break;
goto join_next;
if (!chan) { /* channel is new; it has been created above */
chan = Channel_Search(channame);
@@ -411,6 +432,7 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
if (!join_send_topic(Client, target, chan, channame))
break; /* write error */
join_next:
/* next channel? */
channame = strtok_r(NULL, ",", &lastchan);
if (channame && key)
@@ -582,9 +604,9 @@ IRC_TOPIC( CLIENT *Client, REQUEST *Req )
* This implementation handles the local case as well as the forwarding of the
* LIST command to other servers in the IRC network.
*
* @param Client The client from which this command has been received
* @param Req Request structure with prefix and all parameters
* @returns CONNECTED or DISCONNECTED
* @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_LIST( CLIENT *Client, REQUEST *Req )
@@ -592,79 +614,84 @@ IRC_LIST( CLIENT *Client, REQUEST *Req )
char *pattern;
CHANNEL *chan;
CLIENT *from, *target;
int count = 0;
assert( Client != NULL );
assert( Req != NULL );
assert(Client != NULL);
assert(Req != NULL);
/* Bad number of prameters? */
if( Req->argc > 2 )
return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID( Client ), Req->command );
if (Req->argc > 2)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
if( Req->argc > 0 )
pattern = strtok( Req->argv[0], "," );
if (Req->argc > 0)
pattern = strtok(Req->argv[0], ",");
else
pattern = "*";
/* Get sender from prefix, if any */
if( Client_Type( Client ) == CLIENT_SERVER )
from = Client_Search( Req->prefix );
if (Client_Type(Client) == CLIENT_SERVER)
from = Client_Search(Req->prefix);
else
from = Client;
if( ! from )
return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG,
Client_ID( Client ), Req->prefix );
if (!from)
return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
Client_ID(Client), Req->prefix);
if( Req->argc == 2 )
{
if (Req->argc == 2) {
/* Forward to other server? */
target = Client_Search( Req->argv[1] );
if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER ))
return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG,
Client_ID( Client ), Req->argv[1] );
target = Client_Search(Req->argv[1]);
if (! target || Client_Type(target) != CLIENT_SERVER)
return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG,
Client_ID(Client),
Req->argv[1]);
if( target != Client_ThisServer( ))
{
if (target != Client_ThisServer()) {
/* Target is indeed an other server, forward it! */
return IRC_WriteStrClientPrefix( target, from,
"LIST %s :%s", Client_ID( from ),
Req->argv[1] );
return IRC_WriteStrClientPrefix(target, from,
"LIST %s :%s",
Req->argv[0],
Req->argv[1]);
}
}
while( pattern )
{
while (pattern) {
/* Loop through all the channels */
chan = Channel_First( );
while( chan )
{
if (Req->argc > 0)
ngt_LowerStr(pattern);
chan = Channel_First();
while (chan) {
/* Check search pattern */
if( Match( pattern, Channel_Name( chan )))
{
if (MatchCaseInsensitive(pattern, Channel_Name(chan))) {
/* Gotcha! */
if( ! strchr( Channel_Modes( chan ), 's' ) ||
Channel_IsMemberOf( chan, from ))
{
if( ! IRC_WriteStrClient( from,
RPL_LIST_MSG, Client_ID( from ),
Channel_Name( chan ),
Channel_MemberCount( chan ),
Channel_Topic( chan )))
if (!strchr(Channel_Modes(chan), 's')
|| Channel_IsMemberOf(chan, from)) {
if (IRC_CheckListTooBig(from, count,
MAX_RPL_LIST,
"LIST"))
break;
if (!IRC_WriteStrClient(from,
RPL_LIST_MSG, Client_ID(from),
Channel_Name(chan),
Channel_MemberCount(chan),
Channel_Topic( chan )))
return DISCONNECTED;
count++;
}
}
chan = Channel_Next( chan );
chan = Channel_Next(chan);
}
/* Get next name ... */
if( Req->argc > 0 )
pattern = strtok( NULL, "," );
if(Req->argc > 0)
pattern = strtok(NULL, ",");
else
pattern = NULL;
}
return IRC_WriteStrClient( from, RPL_LISTEND_MSG, Client_ID( from ));
IRC_SetPenalty(from, 2);
return IRC_WriteStrClient(from, RPL_LISTEND_MSG, Client_ID(from));
} /* IRC_LIST */

View File

@@ -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
@@ -28,14 +28,18 @@
#include "conn-func.h"
#include "conn-zip.h"
#include "channel.h"
#include "class.h"
#include "conf.h"
#include "defines.h"
#include "lists.h"
#include "log.h"
#include "messages.h"
#include "match.h"
#include "tool.h"
#include "parse.h"
#include "irc.h"
#include "irc-write.h"
#include "client-cap.h"
#include "exp.h"
#include "irc-info.h"
@@ -152,6 +156,15 @@ IRC_INFO(CLIENT * Client, REQUEST * Req)
} /* IRC_INFO */
/**
* Handler for the IRC "ISON" command.
*
* See RFC 2812, 4.9 "Ison message".
*
* @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_ISON( CLIENT *Client, REQUEST *Req )
{
@@ -160,80 +173,103 @@ IRC_ISON( CLIENT *Client, REQUEST *Req )
char *ptr;
int i;
assert( Client != NULL );
assert( Req != NULL );
assert(Client != NULL);
assert(Req != NULL);
/* Falsche Anzahl Parameter? */
if(( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
/* Bad number of arguments? */
if (Req->argc < 1)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
strlcpy( rpl, RPL_ISON_MSG, sizeof rpl );
for( i = 0; i < Req->argc; i++ )
{
ptr = strtok( Req->argv[i], " " );
while( ptr )
{
ngt_TrimStr( ptr );
c = Client_Search( ptr );
if( c && ( Client_Type( c ) == CLIENT_USER ))
{
/* Dieser Nick ist "online" */
strlcat( rpl, ptr, sizeof( rpl ));
strlcat( rpl, " ", sizeof( rpl ));
strlcpy(rpl, RPL_ISON_MSG, sizeof rpl);
for (i = 0; i < Req->argc; i++) {
/* "All" ircd even parse ":<x> <y> ..." arguments and split
* them up; so we do the same ... */
ptr = strtok(Req->argv[i], " ");
while (ptr) {
ngt_TrimStr(ptr);
c = Client_Search(ptr);
if (c && Client_Type(c) == CLIENT_USER) {
strlcat(rpl, Client_ID(c), sizeof(rpl));
strlcat(rpl, " ", sizeof(rpl));
}
ptr = strtok( NULL, " " );
ptr = strtok(NULL, " ");
}
}
ngt_TrimLastChr(rpl, ' ');
return IRC_WriteStrClient( Client, rpl, Client_ID( Client ) );
return IRC_WriteStrClient(Client, rpl, Client_ID(Client));
} /* IRC_ISON */
/**
* Handler for the IRC "LINKS" command.
*
* See RFC 2812, 3.4.5 "Links message".
*
* @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_LINKS( CLIENT *Client, REQUEST *Req )
IRC_LINKS(CLIENT *Client, REQUEST *Req)
{
CLIENT *target, *from, *c;
char *mask;
assert( Client != NULL );
assert( Req != NULL );
assert(Client != NULL);
assert(Req != NULL);
if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
IRC_SetPenalty(Client, 1);
/* Server-Mask ermitteln */
if( Req->argc > 0 ) mask = Req->argv[Req->argc - 1];
else mask = "*";
if (Req->argc > 2)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
/* Absender ermitteln */
if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
else from = Client;
if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
/* Get pointer to server mask or "*", if none given */
if (Req->argc > 0)
mask = Req->argv[Req->argc - 1];
else
mask = "*";
/* An anderen Server forwarden? */
if( Req->argc == 2 )
{
target = Client_Search( Req->argv[0] );
if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[0] );
else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LINKS %s %s", Req->argv[0], Req->argv[1] );
if (Client_Type(Client) == CLIENT_SERVER)
from = Client_Search(Req->prefix);
else
from = Client;
if (!from)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix);
/* Forward? */
if (Req->argc == 2) {
target = Client_Search(Req->argv[0]);
if (! target || Client_Type(target) != CLIENT_SERVER)
return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG,
Client_ID(from),
Req->argv[0] );
else
if (target != Client_ThisServer())
return IRC_WriteStrClientPrefix(target, from,
"LINKS %s %s", Req->argv[0],
Req->argv[1]);
}
/* Wer ist der Absender? */
if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix );
else target = Client;
if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
c = Client_First( );
while( c )
{
if( Client_Type( c ) == CLIENT_SERVER )
{
if( ! IRC_WriteStrClient( target, RPL_LINKS_MSG, Client_ID( target ), Client_ID( c ), Client_ID( Client_TopServer( c ) ? Client_TopServer( c ) : Client_ThisServer( )), Client_Hops( c ), Client_Info( c ))) return DISCONNECTED;
c = Client_First();
while (c) {
if (Client_Type(c) == CLIENT_SERVER
&& MatchCaseInsensitive(mask, Client_ID(c))) {
if (!IRC_WriteStrClient(from, RPL_LINKS_MSG,
Client_ID(from), Client_ID(c),
Client_ID(Client_TopServer(c)
? Client_TopServer(c)
: Client_ThisServer()),
Client_Hops(c), Client_Info(c)))
return DISCONNECTED;
}
c = Client_Next( c );
c = Client_Next(c);
}
IRC_SetPenalty( target, 1 );
return IRC_WriteStrClient( target, RPL_ENDOFLINKS_MSG, Client_ID( target ), mask );
return IRC_WriteStrClient(from, RPL_ENDOFLINKS_MSG,
Client_ID(from), mask);
} /* IRC_LINKS */
@@ -478,6 +514,8 @@ IRC_STATS( CLIENT *Client, REQUEST *Req )
COMMAND *cmd;
time_t time_now;
unsigned int days, hrs, mins;
struct list_head *list;
struct list_elem *list_item;
assert(Client != NULL);
assert(Req != NULL);
@@ -516,6 +554,28 @@ IRC_STATS( CLIENT *Client, REQUEST *Req )
query = '*';
switch (query) {
case 'g': /* Network-wide bans ("G-Lines") */
case 'G':
case 'k': /* Server-local bans ("K-Lines") */
case 'K':
if (!Client_HasMode(from, 'o'))
return IRC_WriteStrClient(from, ERR_NOPRIVILEGES_MSG,
Client_ID(from));
if (query == 'g' || query == 'G')
list = Class_GetList(CLASS_GLINE);
else
list = Class_GetList(CLASS_KLINE);
list_item = Lists_GetFirst(list);
while (list_item) {
if (!IRC_WriteStrClient(from, RPL_STATSXLINE_MSG,
Client_ID(from), query,
Lists_GetMask(list_item),
Lists_GetValidity(list_item),
Lists_GetReason(list_item)))
return DISCONNECTED;
list_item = Lists_GetNext(list_item);
}
break;
case 'l': /* Link status (servers and own link) */
case 'L':
time_now = time(NULL);
@@ -589,10 +649,10 @@ IRC_STATS( CLIENT *Client, REQUEST *Req )
* therefore answers with ERR_SUMMONDISABLED.
*/
GLOBAL bool
IRC_SUMMON(CLIENT * Client, REQUEST * Req)
IRC_SUMMON(CLIENT * Client, UNUSED REQUEST * Req)
{
return IRC_WriteStrClient(Client, ERR_SUMMONDISABLED_MSG,
Client_ID(Client), Req->command);
Client_ID(Client));
} /* IRC_SUMMON */
@@ -682,10 +742,10 @@ IRC_USERHOST(CLIENT *Client, REQUEST *Req)
* See RFC 2812 section 4.6. As suggested there the command is disabled.
*/
GLOBAL bool
IRC_USERS(CLIENT * Client, REQUEST * Req)
IRC_USERS(CLIENT * Client, UNUSED REQUEST * Req)
{
return IRC_WriteStrClient(Client, ERR_USERSDISABLED_MSG,
Client_ID(Client), Req->command);
Client_ID(Client));
} /* IRC_USERS */
@@ -748,8 +808,16 @@ who_flags_status(const char *client_modes)
static const char *
who_flags_qualifier(const char *chan_user_modes)
who_flags_qualifier(CLIENT *Client, const char *chan_user_modes)
{
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, 'o'))
return "@";
else if (strchr(chan_user_modes, 'v'))
@@ -758,8 +826,16 @@ who_flags_qualifier(const char *chan_user_modes)
}
/**
* Send WHO reply for a "channel target" ("WHO #channel").
*
* @param Client Client requesting the information.
* @param Chan Channel being requested.
* @param OnlyOps Only display IRC operators.
* @return CONNECTED or DISCONNECTED.
*/
static bool
IRC_Send_WHO(CLIENT *Client, CHANNEL *Chan, bool OnlyOps)
IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps)
{
bool is_visible, is_member, is_ircop;
CL2CHAN *cl2chan;
@@ -767,6 +843,7 @@ IRC_Send_WHO(CLIENT *Client, CHANNEL *Chan, bool OnlyOps)
const char *chan_user_modes;
char flags[8];
CLIENT *c;
int count = 0;
assert( Client != NULL );
assert( Chan != NULL );
@@ -775,7 +852,8 @@ IRC_Send_WHO(CLIENT *Client, CHANNEL *Chan, bool OnlyOps)
/* Secret channel? */
if (!is_member && strchr(Channel_Modes(Chan), 's'))
return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), Channel_Name(Chan));
return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG,
Client_ID(Client), Channel_Name(Chan));
cl2chan = Channel_FirstMember(Chan);
for (; cl2chan ; cl2chan = Channel_NextMember(Chan, cl2chan)) {
@@ -788,141 +866,178 @@ IRC_Send_WHO(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(chan_user_modes), sizeof(flags));
strlcat(flags, who_flags_qualifier(c, chan_user_modes),
sizeof(flags));
if (!write_whoreply(Client, c, Channel_Name(Chan), flags))
if (!write_whoreply(Client, c, Channel_Name(Chan),
flags))
return DISCONNECTED;
count++;
}
}
return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), Channel_Name(Chan));
} /* IRC_Send_WHO */
return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client),
Channel_Name(Chan));
}
GLOBAL bool
IRC_WHO( CLIENT *Client, REQUEST *Req )
/**
* Send WHO reply for a "mask target" ("WHO m*sk").
*
* @param Client Client requesting the information.
* @param Mask Mask being requested or NULL for "all" clients.
* @param OnlyOps Only display IRC operators.
* @return CONNECTED or DISCONNECTED.
*/
static bool
IRC_WHO_Mask(CLIENT *Client, char *Mask, bool OnlyOps)
{
bool only_ops, have_arg, client_match;
const char *channelname, *client_modes, *chan_user_modes;
char pattern[COMMAND_LEN];
char flags[4];
CL2CHAN *cl2chan;
CHANNEL *chan, *cn;
CLIENT *c;
CL2CHAN *cl2chan;
CHANNEL *chan;
bool client_match, is_visible;
char flags[4];
int count = 0;
assert( Client != NULL );
assert( Req != NULL );
assert (Client != NULL);
if (Mask)
ngt_LowerStr(Mask);
for (c = Client_First(); c != NULL; c = Client_Next(c)) {
if (Client_Type(c) != CLIENT_USER)
continue;
if (OnlyOps && !Client_HasMode(c, 'o'))
continue;
if (Mask) {
/* Match pattern against user host/server/name/nick */
client_match = MatchCaseInsensitive(Mask,
Client_Hostname(c));
if (!client_match)
client_match = MatchCaseInsensitive(Mask,
Client_ID(Client_Introducer(c)));
if (!client_match)
client_match = MatchCaseInsensitive(Mask,
Client_Info(c));
if (!client_match)
client_match = MatchCaseInsensitive(Mask,
Client_ID(c));
if (!client_match)
continue; /* no match: skip this client */
}
is_visible = !Client_HasMode(c, 'i');
/* Target client is invisible, but mask matches exactly? */
if (!is_visible && Mask && strcasecmp(Client_ID(c), Mask) == 0)
is_visible = true;
/* Target still invisible, but are both on the same channel? */
if (!is_visible) {
cl2chan = Channel_FirstChannelOf(Client);
while (cl2chan && !is_visible) {
chan = Channel_GetChannel(cl2chan);
if (Channel_IsMemberOf(chan, c))
is_visible = true;
cl2chan = Channel_NextChannelOf(Client, cl2chan);
}
}
if (!is_visible) /* target user is not visible */
continue;
if (IRC_CheckListTooBig(Client, count, MAX_RPL_WHO, "WHO"))
break;
strcpy(flags, who_flags_status(Client_Modes(c)));
if (strchr(Client_Modes(c), 'o'))
strlcat(flags, "*", sizeof(flags));
if (!write_whoreply(Client, c, "*", flags))
return DISCONNECTED;
count++;
}
return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client),
Mask ? Mask : "*");
}
/**
* Handler for the IRC "WHO" command.
*
* See RFC 2812, 3.6.1 "Who query".
*
* @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_WHO(CLIENT *Client, REQUEST *Req)
{
bool only_ops;
CHANNEL *chan;
assert (Client != NULL);
assert (Req != NULL);
if (Req->argc > 2)
return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
only_ops = false;
have_arg = false;
if (Req->argc == 2) {
if (strcmp(Req->argv[1], "o") == 0)
only_ops = true;
#ifdef STRICT_RFC
else return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, Client_ID(Client), Req->command);
else
return IRC_WriteStrClient(Client,
ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client),
Req->command);
#endif
}
IRC_SetPenalty(Client, 1);
if (Req->argc >= 1) { /* Channel or Mask. */
if (Req->argc >= 1) {
/* Channel or mask given */
chan = Channel_Search(Req->argv[0]);
if (chan)
return IRC_Send_WHO(Client, chan, only_ops);
if (strcmp(Req->argv[0], "0") != 0) { /* RFC stupidity, same as no arguments */
have_arg = true;
strlcpy(pattern, Req->argv[0], sizeof(pattern));
ngt_LowerStr(pattern);
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);
}
}
for (c = Client_First(); c != NULL; c = Client_Next(c)) {
if (Client_Type(c) != CLIENT_USER)
continue;
/*
* RFC 2812, 3.6.1:
* In the absence of the parameter, all visible (users who aren't
* invisible (user mode +i) and who don't have a common channel
* with the requesting client) are listed.
*
* The same result can be achieved by using a [sic] of "0"
* or any wildcard which will end up matching every visible user.
*
* The [sic] passed to WHO is matched against users' host, server, real name and
* nickname if the channel cannot be found.
*/
client_modes = Client_Modes(c);
if (strchr(client_modes, 'i'))
continue;
if (only_ops && !strchr(client_modes, 'o'))
continue;
if (have_arg) { /* match pattern against user host/server/name/nick */
client_match = MatchCaseInsensitive(pattern, Client_Hostname(c)); /* user's host */
if (!client_match)
client_match = MatchCaseInsensitive(pattern, Client_ID(Client_Introducer(c))); /* server */
if (!client_match)
client_match = Match(Req->argv[0], Client_Info(c)); /* realname */
if (!client_match)
client_match = MatchCaseInsensitive(pattern, Client_ID(c)); /* nick name */
if (!client_match) /* This isn't the client you're looking for */
continue;
}
strcpy(flags, who_flags_status(client_modes));
if (strchr(client_modes, 'o')) /* this client is an operator */
strlcat(flags, "*", sizeof(flags));
/* Search suitable channel */
cl2chan = Channel_FirstChannelOf(c);
while (cl2chan) {
cn = Channel_GetChannel(cl2chan);
if (Channel_IsMemberOf(cn, Client) ||
!strchr(Channel_Modes(cn), 's'))
{
channelname = Channel_Name(cn);
break;
}
cl2chan = Channel_NextChannelOf(c, cl2chan);
}
if (cl2chan) {
chan = Channel_GetChannel(cl2chan);
chan_user_modes = Channel_UserModes(chan, c);
strlcat(flags, who_flags_qualifier(chan_user_modes), sizeof(flags));
} else
channelname = "*";
if (!write_whoreply(Client, c, channelname, flags))
return DISCONNECTED;
}
if (Req->argc > 0)
channelname = Req->argv[0];
else
channelname = "*";
return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), channelname);
/* No channel or (valid) mask given */
IRC_SetPenalty(Client, 2);
return IRC_WHO_Mask(Client, NULL, only_ops);
} /* IRC_WHO */
/**
* Generate WHOIS reply of one actual client.
*
* @param Client The client from which this command has been received.
* @param from The client requesting the information ("originator").
* @param c The client of which information should be returned.
* @returns CONNECTED or DISCONNECTED.
* @param Client The client from which this command has been received.
* @param from The client requesting the information ("originator").
* @param c The client of which information should be returned.
* @return CONNECTED or DISCONNECTED.
*/
static bool
IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c)
@@ -931,6 +1046,10 @@ IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c)
CL2CHAN *cl2chan;
CHANNEL *chan;
assert(Client != NULL);
assert(from != NULL);
assert(c != NULL);
/* Nick, user, hostname and client info */
if (!IRC_WriteStrClient(from, RPL_WHOISUSER_MSG, Client_ID(from),
Client_ID(c), Client_User(c),
@@ -968,7 +1087,7 @@ IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c)
if (str[strlen(str) - 1] != ':')
strlcat(str, " ", sizeof(str));
strlcat(str, who_flags_qualifier(Channel_UserModes(chan, c)),
strlcat(str, who_flags_qualifier(c, Channel_UserModes(chan, c)),
sizeof(str));
strlcat(str, Channel_Name(chan), sizeof(str));
@@ -988,33 +1107,43 @@ IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c)
/* IRC-Operator? */
if (Client_HasMode(c, 'o') &&
!IRC_WriteStrClient(from, RPL_WHOISOPERATOR_MSG,
Client_ID(from), Client_ID(c)))
return DISCONNECTED;
!IRC_WriteStrClient(from, RPL_WHOISOPERATOR_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;
!IRC_WriteStrClient(from, RPL_WHOISSSL_MSG, Client_ID(from),
Client_ID(c)))
return DISCONNECTED;
/* Registered nick name? */
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;
/* Idle and signon time (local clients only!) */
if (!Conf_MorePrivacy && Client_Conn(c) > NONE &&
!IRC_WriteStrClient(from, RPL_WHOISIDLE_MSG,
Client_ID(from), Client_ID(c),
(unsigned long)Conn_GetIdle(Client_Conn(c)),
(unsigned long)Conn_GetSignon(Client_Conn(c))))
return DISCONNECTED;
!IRC_WriteStrClient(from, RPL_WHOISIDLE_MSG,
Client_ID(from), Client_ID(c),
(unsigned long)Conn_GetIdle(Client_Conn(c)),
(unsigned long)Conn_GetSignon(Client_Conn(c))))
return DISCONNECTED;
/* Away? */
if (Client_HasMode(c, 'a') &&
!IRC_WriteStrClient(from, RPL_AWAY_MSG,
Client_ID(from), Client_ID(c),
Client_Away(c)))
return DISCONNECTED;
!IRC_WriteStrClient(from, RPL_AWAY_MSG,
Client_ID(from), Client_ID(c), Client_Away(c)))
return DISCONNECTED;
return IRC_WriteStrClient(from, RPL_ENDOFWHOIS_MSG,
Client_ID(from), Client_ID(c));
return CONNECTED;
} /* IRC_WHOIS_SendReply */
@@ -1034,7 +1163,7 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req )
unsigned int match_count = 0, found = 0;
bool has_wildcards, is_remote;
bool got_wildcard = false;
const char *query;
char mask[COMMAND_LEN], *query;
assert( Client != NULL );
assert( Req != NULL );
@@ -1075,7 +1204,8 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req )
Req->argv[0], Req->argv[1]);
is_remote = Client_Conn(from) < 0;
for (query = strtok(Req->argv[Req->argc - 1], ",");
strlcpy(mask, Req->argv[Req->argc - 1], sizeof(mask));
for (query = strtok(ngt_LowerStr(mask), ",");
query && found < 3;
query = strtok(NULL, ","), found++)
{
@@ -1086,11 +1216,11 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req )
* - no wildcards for remote clients
* - only one wildcard target per local client
*
* also, at most ten matches are returned.
* Also, at most MAX_RPL_WHOIS matches are returned.
*/
if (!has_wildcards || is_remote) {
c = Client_Search(query);
if (c) {
if (c && Client_Type(c) == CLIENT_USER) {
if (!IRC_WHOIS_SendReply(Client, from, c))
return DISCONNECTED;
} else {
@@ -1112,21 +1242,28 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req )
got_wildcard = true;
IRC_SetPenalty(Client, 3);
for (c = Client_First(); c && match_count < 10; c = Client_Next(c)) {
for (c = Client_First(); c; c = Client_Next(c)) {
if (IRC_CheckListTooBig(Client, match_count,
MAX_RPL_WHOIS, "WHOIS"))
break;
if (Client_Type(c) != CLIENT_USER)
continue;
if (!MatchCaseInsensitive(query, Client_ID(c)))
continue;
if (!IRC_WHOIS_SendReply(Client, from, c))
return DISCONNECTED;
match_count++;
}
if (match_count == 0)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->argv[Req->argc - 1]);
IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client),
Req->argv[Req->argc - 1]);
}
return CONNECTED;
return IRC_WriteStrClient(from, RPL_ENDOFWHOIS_MSG,
Client_ID(from), Req->argv[Req->argc - 1]);
} /* IRC_WHOIS */
@@ -1208,11 +1345,11 @@ IRC_WHOWAS( CLIENT *Client, REQUEST *Req )
if (last < 0)
last = 0;
max = DEFAULT_WHOWAS;
max = DEF_RPL_WHOWAS;
if (Req->argc > 1) {
max = atoi(Req->argv[1]);
if (max < 1)
max = MAX_WHOWAS;
max = MAX_RPL_WHOWAS;
}
/*
@@ -1251,38 +1388,55 @@ IRC_WHOWAS( CLIENT *Client, REQUEST *Req )
} /* IRC_WHOWAS */
/**
* Send LUSERS reply to a client.
*
* @param Client The receipient of the information.
* @return CONNECTED or DISCONNECTED.
*/
GLOBAL bool
IRC_Send_LUSERS( CLIENT *Client )
IRC_Send_LUSERS(CLIENT *Client)
{
unsigned long cnt;
#ifndef STRICT_RFC
unsigned long max;
#endif
assert( Client != NULL );
assert(Client != NULL);
/* Users, services and serevers in the network */
if( ! IRC_WriteStrClient( Client, RPL_LUSERCLIENT_MSG, Client_ID( Client ), Client_UserCount( ), Client_ServiceCount( ), Client_ServerCount( ))) return DISCONNECTED;
if (!IRC_WriteStrClient(Client, RPL_LUSERCLIENT_MSG, Client_ID(Client),
Client_UserCount(), Client_ServiceCount(),
Client_ServerCount()))
return DISCONNECTED;
/* Number of IRC operators */
cnt = Client_OperCount( );
if( cnt > 0 )
{
if( ! IRC_WriteStrClient( Client, RPL_LUSEROP_MSG, Client_ID( Client ), cnt )) return DISCONNECTED;
if (cnt > 0) {
if (!IRC_WriteStrClient(Client, RPL_LUSEROP_MSG,
Client_ID(Client), cnt))
return DISCONNECTED;
}
/* Unknown connections */
cnt = Client_UnknownCount( );
if( cnt > 0 )
{
if( ! IRC_WriteStrClient( Client, RPL_LUSERUNKNOWN_MSG, Client_ID( Client ), cnt )) return DISCONNECTED;
if (cnt > 0) {
if (!IRC_WriteStrClient(Client, RPL_LUSERUNKNOWN_MSG,
Client_ID(Client), cnt))
return DISCONNECTED;
}
/* Number of created channels */
if( ! IRC_WriteStrClient( Client, RPL_LUSERCHANNELS_MSG, Client_ID( Client ), Channel_Count( ))) return DISCONNECTED;
if (!IRC_WriteStrClient(Client, RPL_LUSERCHANNELS_MSG,
Client_ID(Client),
Channel_CountVisible(Client)))
return DISCONNECTED;
/* Number of local users, services and servers */
if( ! IRC_WriteStrClient( Client, RPL_LUSERME_MSG, Client_ID( Client ), Client_MyUserCount( ), Client_MyServiceCount( ), Client_MyServerCount( ))) return DISCONNECTED;
if (!IRC_WriteStrClient(Client, RPL_LUSERME_MSG, Client_ID(Client),
Client_MyUserCount(), Client_MyServiceCount(),
Client_MyServerCount()))
return DISCONNECTED;
#ifndef STRICT_RFC
/* Maximum number of local users */
@@ -1379,60 +1533,77 @@ IRC_Show_MOTD( CLIENT *Client )
} /* IRC_Show_MOTD */
/**
* Send NAMES reply for a specific client and channel.
*
* @param Client The client requesting the NAMES information.
* @param Chan The channel
* @return CONNECTED or DISCONNECTED.
*/
GLOBAL bool
IRC_Send_NAMES( CLIENT *Client, CHANNEL *Chan )
IRC_Send_NAMES(CLIENT * Client, CHANNEL * Chan)
{
bool is_visible, is_member;
char str[LINE_LEN + 1];
CL2CHAN *cl2chan;
CLIENT *cl;
assert( Client != NULL );
assert( Chan != NULL );
assert(Client != NULL);
assert(Chan != NULL);
if( Channel_IsMemberOf( Chan, Client )) is_member = true;
else is_member = false;
if (Channel_IsMemberOf(Chan, Client))
is_member = true;
else
is_member = false;
/* Do not print info on channel memberships to anyone that is not member? */
if (Conf_MorePrivacy && !is_member)
return CONNECTED;
/* Secret channel? */
if( ! is_member && strchr( Channel_Modes( Chan ), 's' )) return CONNECTED;
if (!is_member && strchr(Channel_Modes(Chan), 's'))
return CONNECTED;
/* Alle Mitglieder suchen */
snprintf( str, sizeof( str ), RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan ));
cl2chan = Channel_FirstMember( Chan );
while( cl2chan )
{
cl = Channel_GetClient( cl2chan );
snprintf(str, sizeof(str), RPL_NAMREPLY_MSG, Client_ID(Client), "=",
Channel_Name(Chan));
cl2chan = Channel_FirstMember(Chan);
while (cl2chan) {
cl = Channel_GetClient(cl2chan);
if( strchr( Client_Modes( cl ), 'i' )) is_visible = false;
else is_visible = true;
if (strchr(Client_Modes(cl), 'i'))
is_visible = false;
else
is_visible = true;
if( is_member || is_visible )
{
/* Nick anhaengen */
if( str[strlen( str ) - 1] != ':' ) strlcat( str, " ", sizeof( str ));
if( strchr( Channel_UserModes( Chan, cl ), 'o' )) strlcat( str, "@", sizeof( str ));
else if( strchr( Channel_UserModes( Chan, cl ), 'v' )) strlcat( str, "+", sizeof( str ));
strlcat( str, Client_ID( cl ), sizeof( str ));
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));
}
strlcat(str, Client_ID(cl), sizeof(str));
if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 ))
{
/* Zeile wird zu lang: senden! */
if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED;
snprintf( str, sizeof( str ), RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan ));
if (strlen(str) > (LINE_LEN - CLIENT_NICK_LEN - 4)) {
if (!IRC_WriteStrClient(Client, "%s", str))
return DISCONNECTED;
snprintf(str, sizeof(str), RPL_NAMREPLY_MSG,
Client_ID(Client), "=",
Channel_Name(Chan));
}
}
/* naechstes Mitglied suchen */
cl2chan = Channel_NextMember( Chan, cl2chan );
cl2chan = Channel_NextMember(Chan, cl2chan);
}
if( str[strlen( str ) - 1] != ':')
{
/* Es sind noch Daten da, die gesendet werden muessen */
if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED;
if (str[strlen(str) - 1] != ':') {
if (!IRC_WriteStrClient(Client, "%s", str))
return DISCONNECTED;
}
return CONNECTED;
@@ -1453,7 +1624,8 @@ IRC_Send_ISUPPORT(CLIENT * Client)
return IRC_WriteStrClient(Client, RPL_ISUPPORT2_MSG, Client_ID(Client),
CHANNEL_NAME_LEN - 1, Conf_MaxNickLength - 1,
COMMAND_LEN - 23, CLIENT_AWAY_LEN - 1,
COMMAND_LEN - 113);
COMMAND_LEN - 113, MAX_HNDL_MODES_ARG,
MAX_HNDL_CHANNEL_LISTS);
} /* IRC_Send_ISUPPORT */

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2010 Alexander Barton (alex@barton.de)
* 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
@@ -18,21 +18,17 @@
#include "imp.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <signal.h>
#include <unistd.h>
#include "ngircd.h"
#include "conn-func.h"
#include "class.h"
#include "conf.h"
#include "channel.h"
#include "io.h"
#include "log.h"
#include "login.h"
#include "messages.h"
#include "pam.h"
#include "parse.h"
#include "irc.h"
#include "irc-info.h"
@@ -41,19 +37,7 @@
#include "exp.h"
#include "irc-login.h"
static bool Hello_User PARAMS(( CLIENT *Client ));
static bool Hello_User_PostAuth PARAMS(( CLIENT *Client ));
static void Kill_Nick PARAMS(( char *Nick, char *Reason ));
static void Introduce_Client PARAMS((CLIENT *To, CLIENT *Client, int Type));
static void Reject_Client PARAMS((CLIENT *Client));
static void cb_introduceClient PARAMS((CLIENT *Client, CLIENT *Prefix,
void *i));
#ifdef PAM
static void cb_Read_Auth_Result PARAMS((int r_fd, UNUSED short events));
#endif
/**
* Handler for the IRC "PASS" command.
@@ -285,7 +269,7 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
/* If we received a valid USER command already then
* register the new client! */
if( Client_Type( Client ) == CLIENT_GOTUSER )
return Hello_User( Client );
return Login_User( Client );
else
Client_SetType( Client, CLIENT_GOTNICK );
} else {
@@ -395,7 +379,7 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
Client_Mask(c));
Client_SetType(c, CLIENT_GOTNICK);
} else
Introduce_Client(Client, c, CLIENT_USER);
Client_Introduce(Client, c, CLIENT_USER);
return CONNECTED;
}
@@ -416,9 +400,7 @@ GLOBAL bool
IRC_USER(CLIENT * Client, REQUEST * Req)
{
CLIENT *c;
#ifdef IDENTAUTH
char *ptr;
#endif
assert(Client != NULL);
assert(Req != NULL);
@@ -436,7 +418,19 @@ IRC_USER(CLIENT * Client, REQUEST * Req)
Client_ID(Client),
Req->command);
/* User name */
/* User name: only alphanumeric characters are allowed! */
ptr = Req->argv[0];
while (*ptr) {
if ((*ptr < '0' || *ptr > '9') &&
(*ptr < 'A' || *ptr > 'Z') &&
(*ptr < 'a' || *ptr > 'z')) {
Conn_Close(Client_Conn(Client), NULL,
"Invalid user name", true);
return DISCONNECTED;
}
ptr++;
}
#ifdef IDENTAUTH
ptr = Client_User(Client);
if (!ptr || !*ptr || *ptr == '~')
@@ -457,7 +451,7 @@ IRC_USER(CLIENT * Client, REQUEST * Req)
LogDebug("Connection %d: got valid USER command ...",
Client_Conn(Client));
if (Client_Type(Client) == CLIENT_GOTNICK)
return Hello_User(Client);
return Login_User(Client);
else
Client_SetType(Client, CLIENT_GOTUSER);
return CONNECTED;
@@ -487,7 +481,7 @@ IRC_USER(CLIENT * Client, REQUEST * Req)
/* RFC 1459 style user registration?
* Introduce client to network: */
if (Client_Type(c) == CLIENT_GOTNICK)
Introduce_Client(Client, c, CLIENT_USER);
Client_Introduce(Client, c, CLIENT_USER);
return CONNECTED;
} else if (Client_Type(Client) == CLIENT_USER) {
@@ -601,7 +595,7 @@ IRC_SERVICE(CLIENT *Client, REQUEST *Req)
return CONNECTED;
}
Introduce_Client(Client, c, CLIENT_SERVICE);
Client_Introduce(Client, c, CLIENT_SERVICE);
return CONNECTED;
} /* IRC_SERVICE */
@@ -653,32 +647,37 @@ IRC_QUIT( CLIENT *Client, REQUEST *Req )
CLIENT *target;
char quitmsg[LINE_LEN];
assert( Client != NULL );
assert( Req != NULL );
assert(Client != NULL);
assert(Req != NULL);
/* Wrong number of arguments? */
if( Req->argc > 1 )
return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
if (Req->argc > 1)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
if (Req->argc == 1)
strlcpy(quitmsg, Req->argv[0], sizeof quitmsg);
if ( Client_Type( Client ) == CLIENT_SERVER )
{
if (Client_Type(Client) == CLIENT_SERVER) {
/* Server */
target = Client_Search( Req->prefix );
if( ! target )
{
Log( LOG_WARNING, "Got QUIT from %s for unknown client!?", Client_ID( Client ));
target = Client_Search(Req->prefix);
if (!target) {
Log(LOG_WARNING,
"Got QUIT from %s for unknown client!?",
Client_ID(Client));
return CONNECTED;
}
Client_Destroy( target, "Got QUIT command.", Req->argc == 1 ? quitmsg : NULL, true);
return CONNECTED;
}
else
{
if (target != Client) {
Client_Destroy(target, "Got QUIT command.",
Req->argc == 1 ? quitmsg : NULL, true);
return CONNECTED;
} else {
Conn_Close(Client_Conn(Client), "Got QUIT command.",
Req->argc == 1 ? quitmsg : NULL, true);
return DISCONNECTED;
}
} else {
if (Req->argc == 1 && quitmsg[0] != '\"') {
/* " " to avoid confusion */
strlcpy(quitmsg, "\"", sizeof quitmsg);
@@ -687,7 +686,8 @@ IRC_QUIT( CLIENT *Client, REQUEST *Req )
}
/* User, Service, or not yet registered */
Conn_Close( Client_Conn( Client ), "Got QUIT command.", Req->argc == 1 ? quitmsg : NULL, true);
Conn_Close(Client_Conn(Client), "Got QUIT command.",
Req->argc == 1 ? quitmsg : NULL, true);
return DISCONNECTED;
}
@@ -874,7 +874,7 @@ IRC_PONG(CLIENT *Client, REQUEST *Req)
if (auth_ping == atoi(Req->argv[0])) {
Conn_SetAuthPing(conn, 0);
if (Client_Type(Client) == CLIENT_WAITAUTHPING)
Hello_User(Client);
Login_User(Client);
} else
if (!IRC_WriteStrClient(Client,
"To connect, type /QUOTE PONG %ld",
@@ -883,212 +883,20 @@ IRC_PONG(CLIENT *Client, REQUEST *Req)
}
#endif
#ifdef DEBUG
if (conn > NONE)
Log(LOG_DEBUG,
"Connection %d: received PONG. Lag: %ld seconds.", conn,
time(NULL) - Conn_LastPing(Client_Conn(Client)));
else
Log(LOG_DEBUG,
"Connection %d: received PONG.", conn);
#endif
if (Client_Type(Client) == CLIENT_SERVER && Conn_LastPing(conn) == 0) {
Log(LOG_INFO,
"Synchronization with \"%s\" done (connection %d): %ld seconds [%ld users, %ld channels]",
Client_ID(Client), conn, time(NULL) - Conn_GetSignon(conn),
Client_UserCount(), Channel_CountVisible(NULL));
Conn_UpdatePing(conn);
} else
LogDebug("Connection %d: received PONG. Lag: %ld seconds.",
conn, time(NULL) - Conn_LastPing(conn));
return CONNECTED;
} /* IRC_PONG */
/**
* Initiate client registration.
*
* This function is called after the daemon received the required NICK and
* USER commands of a new client. If the daemon is compiled with support for
* PAM, the authentication sub-processs is forked; otherwise the global server
* password is checked.
*
* @param Client The client logging in.
* @returns CONNECTED or DISCONNECTED.
*/
static bool
Hello_User(CLIENT * Client)
{
#ifdef PAM
int pipefd[2], result;
pid_t pid;
#endif
CONN_ID conn;
assert(Client != NULL);
conn = Client_Conn(Client);
#ifndef STRICT_RFC
if (Conf_AuthPing) {
/* Did we receive the "auth PONG" already? */
if (Conn_GetAuthPing(conn)) {
Client_SetType(Client, CLIENT_WAITAUTHPING);
LogDebug("Connection %d: Waiting for AUTH PONG ...", conn);
return CONNECTED;
}
}
#endif
#ifdef PAM
if (!Conf_PAM) {
/* Don't do any PAM authentication at all, instead emulate
* 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')
return Hello_User_PostAuth(Client);
Reject_Client(Client);
return DISCONNECTED;
}
/* Fork child process for PAM authentication; and make sure that the
* process timeout is set higher than the login timeout! */
pid = Proc_Fork(Conn_GetProcStat(conn), pipefd,
cb_Read_Auth_Result, Conf_PongTimeout + 1);
if (pid > 0) {
LogDebug("Authenticator for connection %d created (PID %d).",
conn, pid);
return CONNECTED;
} else {
/* Sub process */
Log_Init_Subprocess("Auth");
result = PAM_Authenticate(Client);
if (write(pipefd[1], &result, sizeof(result)) != sizeof(result))
Log_Subprocess(LOG_ERR,
"Failed to pipe result to parent!");
Log_Exit_Subprocess("Auth");
exit(0);
}
#else
/* Check global server password ... */
if (strcmp(Client_Password(Client), Conf_ServerPwd) != 0) {
/* Bad password! */
Reject_Client(Client);
return DISCONNECTED;
}
return Hello_User_PostAuth(Client);
#endif
}
#ifdef PAM
/**
* Read result of the authenticatior sub-process from pipe
*
* @param r_fd File descriptor of the pipe.
* @param events (ignored IO specification)
*/
static void
cb_Read_Auth_Result(int r_fd, UNUSED short events)
{
CONN_ID conn;
CLIENT *client;
int result;
size_t len;
PROC_STAT *proc;
LogDebug("Auth: Got callback on fd %d, events %d", r_fd, events);
conn = Conn_GetFromProc(r_fd);
if (conn == NONE) {
/* Ops, none found? Probably the connection has already
* been closed!? We'll ignore that ... */
io_close(r_fd);
LogDebug("Auth: Got callback for unknown connection!?");
return;
}
proc = Conn_GetProcStat(conn);
client = Conn_GetClient(conn);
/* Read result from pipe */
len = Proc_Read(proc, &result, sizeof(result));
if (len == 0)
return;
if (len != sizeof(result)) {
Log(LOG_CRIT, "Auth: Got malformed result!");
Reject_Client(client);
return;
}
if (result == true) {
Client_SetUser(client, Client_OrigUser(client), true);
(void)Hello_User_PostAuth(client);
} else
Reject_Client(client);
}
#endif
/**
* Reject a client because of wrong password.
*
* This function is called either when the global server password or a password
* checked using PAM has been wrong.
*
* @param Client The client to reject.
*/
static void
Reject_Client(CLIENT *Client)
{
Log(LOG_ERR,
"User \"%s\" rejected (connection %d): Access denied!",
Client_Mask(Client), Client_Conn(Client));
Conn_Close(Client_Conn(Client), NULL,
"Access denied! Bad password?", true);
}
/**
* Finish client registration.
*
* Introduce the new client to the network and send all "hello messages"
* to it after authentication has been succeeded.
*
* @param Client The client logging in.
* @returns CONNECTED or DISCONNECTED.
*/
static bool
Hello_User_PostAuth(CLIENT *Client)
{
Introduce_Client(NULL, Client, CLIENT_USER);
if (!IRC_WriteStrClient
(Client, RPL_WELCOME_MSG, Client_ID(Client), Client_Mask(Client)))
return false;
if (!IRC_WriteStrClient
(Client, RPL_YOURHOST_MSG, Client_ID(Client),
Client_ID(Client_ThisServer()), PACKAGE_VERSION, TARGET_CPU,
TARGET_VENDOR, TARGET_OS))
return false;
if (!IRC_WriteStrClient
(Client, RPL_CREATED_MSG, Client_ID(Client), NGIRCd_StartStr))
return false;
if (!IRC_WriteStrClient
(Client, RPL_MYINFO_MSG, Client_ID(Client),
Client_ID(Client_ThisServer()), PACKAGE_VERSION, USERMODES,
CHANMODES))
return false;
/* Features supported by this server (005 numeric, ISUPPORT),
* see <http://www.irc.org/tech_docs/005.html> for details. */
if (!IRC_Send_ISUPPORT(Client))
return DISCONNECTED;
if (!IRC_Send_LUSERS(Client))
return DISCONNECTED;
if (!IRC_Show_MOTD(Client))
return DISCONNECTED;
/* Suspend the client for a second ... */
IRC_SetPenalty(Client, 1);
return CONNECTED;
}
/**
* Kill all users with a specific nick name in the network.
*
@@ -1096,114 +904,23 @@ Hello_User_PostAuth(CLIENT *Client)
* @param Reason Reason for the KILL.
*/
static void
Kill_Nick( char *Nick, char *Reason )
Kill_Nick(char *Nick, char *Reason)
{
REQUEST r;
assert( Nick != NULL );
assert( Reason != NULL );
assert (Nick != NULL);
assert (Reason != NULL);
r.prefix = (char *)Client_ThisServer( );
r.prefix = NULL;
r.argv[0] = Nick;
r.argv[1] = Reason;
r.argc = 2;
Log( LOG_ERR, "User(s) with nick \"%s\" will be disconnected: %s", Nick, Reason );
IRC_KILL( Client_ThisServer( ), &r );
Log(LOG_ERR, "User(s) with nick \"%s\" will be disconnected: %s",
Nick, Reason);
IRC_KILL(Client_ThisServer(), &r);
} /* Kill_Nick */
/**
* Introduce a new user or service client in the network.
*
* @param From Remote server introducing the client or NULL (local).
* @param Client New client.
* @param Type Type of the client (CLIENT_USER or CLIENT_SERVICE).
*/
static void
Introduce_Client(CLIENT *From, CLIENT *Client, int Type)
{
/* Set client type (user or service) */
Client_SetType(Client, Type);
if (From) {
if (Conf_IsService(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).",
Client_TypeText(Client), Client_Mask(Client),
Client_Modes(Client), Client_ID(From),
Client_ID(Client_Introducer(Client)),
Client_Hops(Client), Client_Hops(Client) > 1 ? "s": "");
} else {
Log(LOG_NOTICE, "%s \"%s\" registered (connection %d).",
Client_TypeText(Client), Client_Mask(Client),
Client_Conn(Client));
Log_ServerNotice('c', "Client connecting: %s (%s@%s) [%s] - %s",
Client_ID(Client), Client_User(Client),
Client_Hostname(Client),
Conn_IPA(Client_Conn(Client)),
Client_TypeText(Client));
}
/* Inform other servers */
IRC_WriteStrServersPrefixFlag_CB(From,
From != NULL ? From : Client_ThisServer(),
'\0', cb_introduceClient, (void *)Client);
} /* Introduce_Client */
/**
* Introduce a new user or service client to a remote server.
*
* This function differentiates between RFC1459 and RFC2813 server links and
* generates the appropriate commands to register the new user or service.
*
* @param To The remote server to inform.
* @param Prefix Prefix for the generated commands.
* @param data CLIENT structure of the new client.
*/
static void
cb_introduceClient(CLIENT *To, CLIENT *Prefix, void *data)
{
CLIENT *c = (CLIENT *)data;
CONN_ID conn;
char *modes, *user, *host;
modes = Client_Modes(c);
user = Client_User(c) ? Client_User(c) : "-";
host = Client_Hostname(c) ? Client_Hostname(c) : "-";
conn = Client_Conn(To);
if (Conn_Options(conn) & CONN_RFC1459) {
/* RFC 1459 mode: separate NICK and USER commands */
Conn_WriteStr(conn, "NICK %s :%d", Client_ID(c),
Client_Hops(c) + 1);
Conn_WriteStr(conn, ":%s USER %s %s %s :%s",
Client_ID(c), user, host,
Client_ID(Client_Introducer(c)), Client_Info(c));
if (modes[0])
Conn_WriteStr(conn, ":%s MODE %s +%s",
Client_ID(c), Client_ID(c), modes);
} else {
/* RFC 2813 mode: one combined NICK or SERVICE command */
if (Client_Type(c) == CLIENT_SERVICE
&& strchr(Client_Flags(To), 'S'))
IRC_WriteStrClientPrefix(To, Prefix,
"SERVICE %s %d * +%s %d :%s",
Client_Mask(c),
Client_MyToken(Client_Introducer(c)),
Client_Modes(c), Client_Hops(c) + 1,
Client_Info(c));
else
IRC_WriteStrClientPrefix(To, Prefix,
"NICK %s %d %s %s %d +%s :%s",
Client_ID(c), Client_Hops(c) + 1,
user, host,
Client_MyToken(Client_Introducer(c)),
modes, Client_Info(c));
}
} /* cb_introduceClient */
/* -eof- */

View File

@@ -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
@@ -36,39 +36,54 @@
#include "irc-mode.h"
static bool Client_Mode PARAMS(( CLIENT *Client, REQUEST *Req, CLIENT *Origin,
CLIENT *Target ));
static bool Channel_Mode PARAMS(( CLIENT *Client, REQUEST *Req, CLIENT *Origin,
CHANNEL *Channel ));
static bool Client_Mode PARAMS((CLIENT *Client, REQUEST *Req, CLIENT *Origin,
CLIENT *Target));
static bool Channel_Mode PARAMS((CLIENT *Client, REQUEST *Req, CLIENT *Origin,
CHANNEL *Channel));
static bool Add_Ban_Invite PARAMS((int what, CLIENT *Prefix, CLIENT *Client,
CHANNEL *Channel, const char *Pattern));
static bool Del_Ban_Invite PARAMS((int what, CLIENT *Prefix, CLIENT *Client,
CHANNEL *Channel, const char *Pattern));
static bool Add_To_List PARAMS((char what, CLIENT *Prefix, CLIENT *Client,
CHANNEL *Channel, const char *Pattern));
static bool Del_From_List PARAMS((char what, CLIENT *Prefix, CLIENT *Client,
CHANNEL *Channel, const char *Pattern));
static bool Send_ListChange PARAMS((const char *Mode, CLIENT *Prefix,
CLIENT *Client, CHANNEL *Channel, const char *Mask));
static bool Send_ListChange PARAMS((const bool IsAdd, const char ModeChar,
CLIENT *Prefix, CLIENT *Client,
CHANNEL *Channel, const char *Mask));
/**
* Handler for the IRC "MODE" command.
*
* See RFC 2812 section 3.1.5 ("user mode message") and section 3.2.3
* ("channel mode message"), and RFC 2811 section 4 ("channel modes").
*
* @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_MODE( CLIENT *Client, REQUEST *Req )
{
CLIENT *cl, *origin;
CHANNEL *chan;
assert( Client != NULL );
assert( Req != NULL );
assert(Client != NULL);
assert(Req != NULL);
/* No parameters? */
if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
if (Req->argc < 1)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
/* Origin for answers */
if( Client_Type( Client ) == CLIENT_SERVER )
{
origin = Client_Search( Req->prefix );
if( ! origin ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
}
else origin = Client;
if (Client_Type(Client) == CLIENT_SERVER) {
origin = Client_Search(Req->prefix);
if (!origin)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client),
Req->prefix);
} else
origin = Client;
/* Channel or user mode? */
cl = NULL; chan = NULL;
@@ -88,178 +103,242 @@ IRC_MODE( CLIENT *Client, REQUEST *Req )
} /* IRC_MODE */
/**
* Check if the "mode limit" for a client has been reached.
*
* This limit doesn't apply for servers or services!
*
* @param Client The client to check.
* @param Count The number of modes already handled.
* @return true if the limit has been reached.
*/
static bool
Mode_Limit_Reached(CLIENT *Client, int Count)
{
if (Client_Type(Client) == CLIENT_SERVER
|| Client_Type(Client) == CLIENT_SERVICE)
return false;
if (Count < MAX_HNDL_MODES_ARG)
return false;
return true;
}
/**
* Handle client mode requests
*
* @param Client The client from which this command has been received.
* @param Req Request structure with prefix and all parameters.
* @param Origin The originator of the MODE command (prefix).
* @param Target The target (client) of this MODE command.
* @returns CONNECTED or DISCONNECTED.
*/
static bool
Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
{
/* Handle client mode requests */
char the_modes[COMMAND_LEN], x[2], *mode_ptr;
bool ok, set;
int mode_arg;
size_t len;
/* Is the client allowed to request or change the modes? */
if( Client_Type( Client ) == CLIENT_USER )
{
if (Client_Type(Client) == CLIENT_USER) {
/* Users are only allowed to manipulate their own modes! */
if( Target != Client ) return IRC_WriteStrClient( Client, ERR_USERSDONTMATCH_MSG, Client_ID( Client ));
if (Target != Client)
return IRC_WriteStrClient(Client,
ERR_USERSDONTMATCH_MSG,
Client_ID(Client));
}
/* Mode request: let's answer it :-) */
if( Req->argc == 1 ) return IRC_WriteStrClient( Origin, RPL_UMODEIS_MSG, Client_ID( Origin ), Client_Modes( Target ));
if (Req->argc == 1)
return IRC_WriteStrClient(Origin, RPL_UMODEIS_MSG,
Client_ID(Origin),
Client_Modes(Target));
mode_arg = 1;
mode_ptr = Req->argv[mode_arg];
/* Initial state: set or unset modes? */
if( *mode_ptr == '+' ) set = true;
else if( *mode_ptr == '-' ) set = false;
else return IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Origin ));
/* Prepare reply string */
if( set ) strcpy( the_modes, "+" );
else strcpy( the_modes, "-" );
if (*mode_ptr == '+') {
set = true;
strcpy(the_modes, "+");
} else if (*mode_ptr == '-') {
set = false;
strcpy(the_modes, "-");
} else
return IRC_WriteStrClient(Origin, ERR_UMODEUNKNOWNFLAG_MSG,
Client_ID(Origin));
x[1] = '\0';
ok = CONNECTED;
while( mode_ptr )
{
while (mode_ptr) {
mode_ptr++;
if( ! *mode_ptr )
{
if (!*mode_ptr) {
/* Try next argument if there's any */
mode_arg++;
if( mode_arg < Req->argc ) mode_ptr = Req->argv[mode_arg];
else break;
if (mode_arg < Req->argc)
mode_ptr = Req->argv[mode_arg];
else
break;
}
switch( *mode_ptr )
{
case '+':
case '-':
if((( *mode_ptr == '+' ) && ( ! set )) || (( *mode_ptr == '-' ) && ( set )))
{
/* Action modifier ("+"/"-") must be changed ... */
len = strlen( the_modes ) - 1;
if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' ))
{
/* Adjust last action modifier in result */
the_modes[len] = *mode_ptr;
}
else
{
/* Append modifier character to result string */
x[0] = *mode_ptr;
strlcat( the_modes, x, sizeof( the_modes ));
}
if( *mode_ptr == '+' ) set = true;
else set = false;
switch(*mode_ptr) {
case '+':
case '-':
if ((*mode_ptr == '+' && !set)
|| (*mode_ptr == '-' && set)) {
/* Action modifier ("+"/"-") must be changed */
len = strlen(the_modes) - 1;
if (the_modes[len] == '+'
|| the_modes[len] == '-') {
/* Last character in the "result
* string" was an "action", so just
* overwrite it with the new action */
the_modes[len] = *mode_ptr;
} else {
/* Append new modifier character to
* the resulting mode string */
x[0] = *mode_ptr;
strlcat(the_modes, x,
sizeof(the_modes));
}
continue;
if (*mode_ptr == '+')
set = true;
else
set = false;
}
continue;
}
/* Validate modes */
x[0] = '\0';
switch( *mode_ptr )
{
case 'i': /* Invisible */
case 's': /* Server messages */
case 'w': /* Wallops messages */
x[0] = *mode_ptr;
break;
case 'a': /* Away */
if( Client_Type( Client ) == CLIENT_SERVER )
{
x[0] = 'a';
Client_SetAway( Origin, DEFAULT_AWAY_MSG );
}
else ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin ));
break;
case 'c': /* Receive connect notices
* (only settable by IRC operators!) */
if(!set || Client_OperByMe(Origin)
|| Client_Type(Client) == CLIENT_SERVER)
x[0] = 'c';
else
ok = IRC_WriteStrClient(Origin,
switch (*mode_ptr) {
case 'C': /* Only messages from clients sharing a channel */
case 'i': /* Invisible */
case 's': /* Server messages */
case 'w': /* Wallops messages */
x[0] = *mode_ptr;
break;
case 'a': /* Away */
if (Client_Type(Client) == CLIENT_SERVER) {
x[0] = 'a';
Client_SetAway(Origin, DEFAULT_AWAY_MSG);
} else
ok = IRC_WriteStrClient(Origin,
ERR_NOPRIVILEGES_MSG,
Client_ID(Origin));
break;
case 'o': /* IRC operator (only unsettable!) */
if(( ! set ) || ( Client_Type( Client ) == CLIENT_SERVER ))
{
Client_SetOperByMe( Target, false );
x[0] = 'o';
}
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';
else ok = IRC_WriteStrClient( Origin, ERR_RESTRICTED_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
x[0] = 'x';
break;
default:
Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", set ? '+' : '-', *mode_ptr, Client_ID( Origin ));
if( Client_Type( Client ) != CLIENT_SERVER ) ok = IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Origin ), set ? '+' : '-', *mode_ptr );
break;
case 'c': /* Receive connect notices
* (only settable by IRC operators!) */
if (!set || Client_Type(Client) == CLIENT_SERVER
|| Client_OperByMe(Origin))
x[0] = 'c';
else
ok = IRC_WriteStrClient(Origin,
ERR_NOPRIVILEGES_MSG,
Client_ID(Origin));
break;
case 'o': /* IRC operator (only unsettable!) */
if (!set || Client_Type(Client) == CLIENT_SERVER) {
Client_SetOperByMe(Target, false);
x[0] = 'o';
} 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';
else
ok = IRC_WriteStrClient(Origin,
ERR_RESTRICTED_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
x[0] = 'x';
break;
default:
if (Client_Type(Client) != CLIENT_SERVER) {
Log(LOG_DEBUG,
"Unknown mode \"%c%c\" from \"%s\"!?",
set ? '+' : '-', *mode_ptr,
Client_ID(Origin));
ok = IRC_WriteStrClient(Origin,
ERR_UMODEUNKNOWNFLAG2_MSG,
Client_ID(Origin),
set ? '+' : '-',
*mode_ptr);
x[0] = '\0';
goto client_exit;
} else {
Log(LOG_DEBUG,
"Handling unknown mode \"%c%c\" from \"%s\" for \"%s\" ...",
set ? '+' : '-', *mode_ptr,
Client_ID(Origin), Client_ID(Target));
x[0] = *mode_ptr;
}
}
if( ! ok ) break;
if (!ok)
break;
/* Is there a valid mode change? */
if( ! x[0] ) continue;
if( set )
{
/* Set mode */
if( Client_ModeAdd( Target, x[0] )) strlcat( the_modes, x, sizeof( the_modes ));
if (!x[0])
continue;
if (set) {
if (Client_ModeAdd(Target, x[0]))
strlcat(the_modes, x, sizeof(the_modes));
} else {
if (Client_ModeDel(Target, x[0]))
strlcat(the_modes, x, sizeof(the_modes));
}
else
{
/* Unset mode */
if( Client_ModeDel( Target, x[0] )) strlcat( the_modes, x, sizeof( the_modes ));
}
}
client_exit:
/* Are there changed modes? */
if( the_modes[1] )
{
/* Remoce needless action modifier characters */
len = strlen( the_modes ) - 1;
if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' )) the_modes[len] = '\0';
if( Client_Type( Client ) == CLIENT_SERVER )
{
/* Are there changed modes? */
if (the_modes[1]) {
/* Remove needless action modifier characters */
len = strlen(the_modes) - 1;
if (the_modes[len] == '+' || the_modes[len] == '-')
the_modes[len] = '\0';
if (Client_Type(Client) == CLIENT_SERVER) {
/* Forward modes to other servers */
IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
}
else
{
if (Client_Conn(Target) != NONE) {
/* Remote server (service?) changed modes
* for one of our clients. Inform it! */
IRC_WriteStrClientPrefix(Target, Origin,
"MODE %s :%s",
Client_ID(Target),
the_modes);
}
IRC_WriteStrServersPrefix(Client, Origin,
"MODE %s :%s",
Client_ID(Target),
the_modes);
} else {
/* Send reply to client and inform other servers */
ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
ok = IRC_WriteStrClientPrefix(Client, Origin,
"MODE %s :%s",
Client_ID(Target),
the_modes);
IRC_WriteStrServersPrefix(Client, Origin,
"MODE %s :%s",
Client_ID(Target),
the_modes);
}
LogDebug("%s \"%s\": Mode change, now \"%s\".",
Client_TypeText(Target), Client_Mask(Target),
Client_Modes(Target));
}
IRC_SetPenalty( Client, 1 );
IRC_SetPenalty(Client, 1);
return ok;
} /* Client_Mode */
@@ -319,7 +398,7 @@ 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;
int mode_arg, arg_arg;
int mode_arg, arg_arg, mode_arg_count = 0;
CLIENT *client;
long l;
size_t len;
@@ -372,6 +451,8 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
mode_ptr++;
if (!*mode_ptr) {
/* Try next argument if there's any */
if (arg_arg < 0)
break;
if (arg_arg > mode_arg)
mode_arg = arg_arg;
else
@@ -421,6 +502,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
case 'i': /* Invite only */
case 'm': /* Moderated */
case 'n': /* Only members can write */
case 'R': /* Registered users only */
case 's': /* Secret channel */
case 't': /* Topic locked */
case 'z': /* Secure connections only */
@@ -432,6 +514,8 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
Client_ID(Origin), Channel_Name(Channel));
break;
case 'k': /* Channel key */
if (Mode_Limit_Reached(Client, mode_arg_count++))
goto chan_exit;
if (!set) {
if (modeok)
x[0] = *mode_ptr;
@@ -466,6 +550,8 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
}
break;
case 'l': /* Member limit */
if (Mode_Limit_Reached(Client, mode_arg_count++))
goto chan_exit;
if (!set) {
if (modeok)
x[0] = *mode_ptr;
@@ -536,6 +622,16 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
Channel_Name(Channel));
break;
/* --- Channel user modes --- */
case 'a':
case 'h':
case 'q':
if (Client_Type(Client) != CLIENT_SERVER) {
connected = IRC_WriteStrClient(Origin,
ERR_CHANOPRIVSNEEDED_MSG,
Client_ID(Origin),
Channel_Name(Channel));
goto chan_exit;
}
case 'o': /* Channel operator */
case 'v': /* Voice */
if (arg_arg > mode_arg) {
@@ -566,14 +662,17 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
/* --- Channel lists --- */
case 'I': /* Invite lists */
case 'b': /* Ban lists */
case 'e': /* Channel exception lists */
if (Mode_Limit_Reached(Client, mode_arg_count++))
goto chan_exit;
if (arg_arg > mode_arg) {
/* modify list */
if (modeok) {
connected = set
? Add_Ban_Invite(*mode_ptr, Origin,
? Add_To_List(*mode_ptr, Origin,
Client, Channel,
Req->argv[arg_arg])
: Del_Ban_Invite(*mode_ptr, Origin,
: Del_From_List(*mode_ptr, Origin,
Client, Channel,
Req->argv[arg_arg]);
} else {
@@ -585,25 +684,38 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
Req->argv[arg_arg][0] = '\0';
arg_arg++;
} else {
if (*mode_ptr == 'I')
switch (*mode_ptr) {
case 'I':
Channel_ShowInvites(Origin, Channel);
else
break;
case 'b':
Channel_ShowBans(Origin, Channel);
break;
case 'e':
Channel_ShowExcepts(Origin, Channel);
break;
}
}
break;
default:
Log(LOG_DEBUG,
"Unknown mode \"%c%c\" from \"%s\" on %s!?",
set ? '+' : '-', *mode_ptr, Client_ID(Origin),
Channel_Name(Channel));
if (Client_Type(Client) != CLIENT_SERVER)
if (Client_Type(Client) != CLIENT_SERVER) {
Log(LOG_DEBUG,
"Unknown mode \"%c%c\" from \"%s\" on %s!?",
set ? '+' : '-', *mode_ptr,
Client_ID(Origin), Channel_Name(Channel));
connected = IRC_WriteStrClient(Origin,
ERR_UMODEUNKNOWNFLAG2_MSG,
Client_ID(Origin),
set ? '+' : '-', *mode_ptr);
x[0] = '\0';
goto chan_exit;
} /* switch() */
ERR_UNKNOWNMODE_MSG,
Client_ID(Origin), *mode_ptr,
Channel_Name(Channel));
x[0] = '\0';
} else {
Log(LOG_DEBUG,
"Handling unknown mode \"%c%c\" from \"%s\" on %s ...",
set ? '+' : '-', *mode_ptr,
Client_ID(Origin), Channel_Name(Channel));
x[0] = *mode_ptr;
}
}
if (!connected)
break;
@@ -729,82 +841,151 @@ IRC_AWAY( CLIENT *Client, REQUEST *Req )
} /* IRC_AWAY */
/**
* Add entries to channel invite, ban and exception lists.
*
* @param what Can be 'I' for invite, 'b' for ban, and 'e' for exception list.
* @param Prefix The originator of the command.
* @param Client The sender of the command.
* @param Channel The channel of which the list should be modified.
* @param Pattern The pattern to add to the list.
* @return CONNECTED or DISCONNECTED.
*/
static bool
Add_Ban_Invite(int what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Pattern)
Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
const char *Pattern)
{
const char *mask;
bool already;
bool ret;
struct list_head *list = NULL;
long int current_count;
assert( Client != NULL );
assert( Channel != NULL );
assert( Pattern != NULL );
assert(what == 'I' || what == 'b');
assert(Client != NULL);
assert(Channel != NULL);
assert(Pattern != NULL);
assert(what == 'I' || what == 'b' || what == 'e');
mask = Lists_MakeMask(Pattern);
current_count = Lists_Count(Channel_GetListInvites(Channel))
+ Lists_Count(Channel_GetListExcepts(Channel))
+ Lists_Count(Channel_GetListBans(Channel));
switch(what) {
case 'I':
list = Channel_GetListInvites(Channel);
break;
case 'b':
list = Channel_GetListBans(Channel);
break;
case 'e':
list = Channel_GetListExcepts(Channel);
break;
}
if (Lists_CheckDupeMask(list, mask))
return CONNECTED;
if (Client_Type(Client) == CLIENT_USER &&
current_count >= MAX_HNDL_CHANNEL_LISTS)
return IRC_WriteStrClient(Client, ERR_LISTFULL_MSG,
Client_ID(Client),
Channel_Name(Channel), mask,
MAX_HNDL_CHANNEL_LISTS);
switch (what) {
case 'I':
if (!Channel_AddInvite(Channel, mask, false))
return CONNECTED;
break;
case 'b':
if (!Channel_AddBan(Channel, mask))
return CONNECTED;
break;
case 'e':
if (!Channel_AddExcept(Channel, mask))
return CONNECTED;
break;
}
return Send_ListChange(true, what, Prefix, Client, Channel, mask);
}
/**
* Delete entries from channel invite, ban and exeption lists.
*
* @param what Can be 'I' for invite, 'b' for ban, and 'e' for exception list.
* @param Prefix The originator of the command.
* @param Client The sender of the command.
* @param Channel The channel of which the list should be modified.
* @param Pattern The pattern to add to the list.
* @return CONNECTED or DISCONNECTED.
*/
static bool
Del_From_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
const char *Pattern)
{
const char *mask;
struct list_head *list = NULL;
assert(Client != NULL);
assert(Channel != NULL);
assert(Pattern != NULL);
assert(what == 'I' || what == 'b' || what == 'e');
mask = Lists_MakeMask(Pattern);
already = Lists_CheckDupeMask(Channel_GetListInvites(Channel), mask);
if (!already) {
if (what == 'I')
ret = Channel_AddInvite(Channel, mask, false);
else
ret = Channel_AddBan(Channel, mask);
if (!ret)
return CONNECTED;
switch (what) {
case 'I':
list = Channel_GetListInvites(Channel);
break;
case 'b':
list = Channel_GetListBans(Channel);
break;
case 'e':
list = Channel_GetListExcepts(Channel);
break;
}
if (already && (Client_Type(Prefix) == CLIENT_SERVER))
if (!Lists_CheckDupeMask(list, mask))
return CONNECTED;
if (what == 'I')
return Send_ListChange("+I", Prefix, Client, Channel, mask);
return Send_ListChange("+b", Prefix, Client, Channel, mask);
}
static bool
Del_Ban_Invite(int what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Pattern)
{
const char *mask;
struct list_head *list;
assert( Client != NULL );
assert( Channel != NULL );
assert( Pattern != NULL );
assert(what == 'I' || what == 'b');
mask = Lists_MakeMask( Pattern );
if (what == 'I')
list = Channel_GetListInvites(Channel);
else
list = Channel_GetListBans(Channel);
Lists_Del(list, mask);
if (what == 'I')
return Send_ListChange( "-I", Prefix, Client, Channel, mask );
return Send_ListChange( "-b", Prefix, Client, Channel, mask );
return Send_ListChange(false, what, Prefix, Client, Channel, mask);
}
/**
* Send information about changed channel invite/ban/exception lists to clients.
*
* @param IsAdd true if the list item has been added, false otherwise.
* @param ModeChar The mode to use (e. g. 'b' or 'I')
* @param Prefix The originator of the mode list change.
* @param Client The sender of the command.
* @param Channel The channel of which the list has been modified.
* @param Mask The mask which has been added or removed.
* @return CONNECTED or DISCONNECTED.
*/
static bool
Send_ListChange(const char *Mode, CLIENT *Prefix, CLIENT *Client,
CHANNEL *Channel, const char *Mask)
Send_ListChange(const bool IsAdd, const char ModeChar, CLIENT *Prefix,
CLIENT *Client, CHANNEL *Channel, const char *Mask)
{
bool ok;
bool ok = true;
if( Client_Type( Client ) == CLIENT_USER )
{
/* send confirmation to client */
ok = IRC_WriteStrClientPrefix( Client, Prefix, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
}
else ok = true;
/* Send confirmation to the client */
if (Client_Type(Client) == CLIENT_USER)
ok = IRC_WriteStrClientPrefix(Client, Prefix, "MODE %s %c%c %s",
Channel_Name(Channel),
IsAdd ? '+' : '-',
ModeChar, Mask);
/* to other servers */
IRC_WriteStrServersPrefix( Client, Prefix, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
IRC_WriteStrServersPrefix(Client, Prefix, "MODE %s %c%c %s",
Channel_Name(Channel), IsAdd ? '+' : '-',
ModeChar, Mask);
/* and local users in channel */
IRC_WriteStrChannelPrefix( Client, Channel, Prefix, false, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
IRC_WriteStrChannelPrefix(Client, Channel, Prefix, false,
"MODE %s %c%c %s", Channel_Name(Channel),
IsAdd ? '+' : '-', ModeChar, Mask );
return ok;
} /* Send_ListChange */

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
* 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
@@ -27,6 +27,7 @@
#include "conn-func.h"
#include "conf.h"
#include "channel.h"
#include "class.h"
#include "irc-write.h"
#include "log.h"
#include "match.h"
@@ -37,7 +38,6 @@
#include <exp.h>
#include "irc-oper.h"
/**
* Handle invalid received OPER command.
* Log OPER attempt and send error message to client.
@@ -52,7 +52,15 @@ Bad_OperPass(CLIENT *Client, char *errtoken, char *errmsg)
Client_ID(Client));
} /* Bad_OperPass */
/**
* Handler for the IRC "OPER" command.
*
* See RFC 2812, 3.1.4 "Oper message".
*
* @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_OPER( CLIENT *Client, REQUEST *Req )
{
@@ -62,7 +70,9 @@ IRC_OPER( CLIENT *Client, REQUEST *Req )
assert( Client != NULL );
assert( Req != NULL );
if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
if (Req->argc != 2)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
len = array_length(&Conf_Opers, sizeof(*op));
op = array_start(&Conf_Opers);
@@ -77,20 +87,33 @@ IRC_OPER( CLIENT *Client, REQUEST *Req )
if (op[i].mask && (!Match(op[i].mask, Client_Mask(Client))))
return Bad_OperPass(Client, op[i].mask, "hostmask check failed");
if( ! Client_HasMode( Client, 'o' ))
{
Client_ModeAdd( Client, 'o' );
if( ! IRC_WriteStrClient( Client, "MODE %s :+o", Client_ID( Client ))) return DISCONNECTED;
IRC_WriteStrServersPrefix( NULL, Client, "MODE %s :+o", Client_ID( Client ));
if (!Client_HasMode(Client, 'o')) {
Client_ModeAdd(Client, 'o');
if (!IRC_WriteStrClient(Client, "MODE %s :+o",
Client_ID(Client)))
return DISCONNECTED;
IRC_WriteStrServersPrefix(NULL, Client, "MODE %s :+o",
Client_ID(Client));
}
if( ! Client_OperByMe( Client )) Log( LOG_NOTICE|LOG_snotice, "Got valid OPER from \"%s\", user is an IRC operator now.", Client_Mask( Client ));
if (!Client_OperByMe(Client))
Log(LOG_NOTICE|LOG_snotice,
"Got valid OPER from \"%s\", user is an IRC operator now.",
Client_Mask(Client));
Client_SetOperByMe( Client, true);
return IRC_WriteStrClient( Client, RPL_YOUREOPER_MSG, Client_ID( Client ));
Client_SetOperByMe(Client, true);
return IRC_WriteStrClient(Client, RPL_YOUREOPER_MSG, Client_ID(Client));
} /* IRC_OPER */
/**
* Handler for the IRC "DIE" command.
*
* See RFC 2812, 4.3 "Die message".
*
* @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_DIE(CLIENT * Client, REQUEST * Req)
{
@@ -133,7 +156,15 @@ IRC_DIE(CLIENT * Client, REQUEST * Req)
return CONNECTED;
} /* IRC_DIE */
/**
* Handler for the IRC "REHASH" command.
*
* See RFC 2812, 4.2 "Rehash message".
*
* @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_REHASH( CLIENT *Client, REQUEST *Req )
{
@@ -146,15 +177,26 @@ IRC_REHASH( CLIENT *Client, REQUEST *Req )
return Op_NoPrivileges(Client, Req);
/* Bad number of parameters? */
if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
if (Req->argc != 0)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command );
Log( LOG_NOTICE|LOG_snotice, "Got REHASH command from \"%s\" ...", Client_Mask( Client ));
Log(LOG_NOTICE|LOG_snotice, "Got REHASH command from \"%s\" ...",
Client_Mask(Client));
raise(SIGHUP);
return CONNECTED;
} /* IRC_REHASH */
/**
* Handler for the IRC "RESTART" command.
*
* See RFC 2812, 4.4 "Restart message".
*
* @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_RESTART( CLIENT *Client, REQUEST *Req )
{
@@ -167,16 +209,25 @@ IRC_RESTART( CLIENT *Client, REQUEST *Req )
return Op_NoPrivileges(Client, Req);
/* Bad number of parameters? */
if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
if (Req->argc != 0)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
Log( LOG_NOTICE|LOG_snotice, "Got RESTART command from \"%s\" ...", Client_Mask( Client ));
Log(LOG_NOTICE|LOG_snotice, "Got RESTART command from \"%s\" ...",
Client_Mask(Client));
NGIRCd_SignalRestart = true;
return CONNECTED;
} /* IRC_RESTART */
/**
* Connect configured or new server.
* Handler for the IRC "CONNECT" command.
*
* See RFC 2812, 3.4.7 "Connect message".
*
* @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_CONNECT(CLIENT * Client, REQUEST * Req)
@@ -272,9 +323,15 @@ IRC_CONNECT(CLIENT * Client, REQUEST * Req)
return CONNECTED;
} /* IRC_CONNECT */
/**
* Disconnect (and disable) configured server.
* Handler for the IRC "DISCONNECT" command.
*
* This command is not specified in the IRC RFCs, it is an extension
* of ngIRCd: it shuts down and disables a configured server connection.
*
* @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_DISCONNECT(CLIENT * Client, REQUEST * Req)
@@ -315,7 +372,15 @@ IRC_DISCONNECT(CLIENT * Client, REQUEST * Req)
return DISCONNECTED;
} /* IRC_DISCONNECT */
/**
* Handler for the IRC "WALLOPS" command.
*
* See RFC 2812, 4.7 "Operwall message".
*
* @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_WALLOPS( CLIENT *Client, REQUEST *Req )
{
@@ -325,12 +390,14 @@ IRC_WALLOPS( CLIENT *Client, REQUEST *Req )
assert( Req != NULL );
if (Req->argc != 1)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, Client_ID(Client), Req->command);
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
switch (Client_Type(Client)) {
case CLIENT_USER:
if (!Client_OperByMe(Client))
return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG, Client_ID(Client));
return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG,
Client_ID(Client));
from = Client;
break;
case CLIENT_SERVER:
@@ -341,11 +408,87 @@ IRC_WALLOPS( CLIENT *Client, REQUEST *Req )
}
if (!from)
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, Client_ID(Client), Req->prefix);
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
Client_ID(Client), Req->prefix);
IRC_SendWallops(Client, from, "%s", Req->argv[0]);
return CONNECTED;
} /* IRC_WALLOPS */
/**
* Handle <?>LINE commands (GLINE, KLINE).
*
* @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_xLINE(CLIENT *Client, REQUEST *Req)
{
CLIENT *from;
int class;
char class_c;
assert(Client != NULL);
assert(Req != NULL);
from = Op_Check(Client, Req);
if (!from)
return Op_NoPrivileges(Client, Req);
/* Bad number of parameters? */
if (Req->argc != 1 && Req->argc != 3)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
switch(Req->command[0]) {
case 'g':
case 'G':
class = CLASS_GLINE; class_c = 'G';
break;
case 'k':
case 'K':
class = CLASS_KLINE; class_c = 'K';
break;
default:
Log(LOG_CRIT,
"IRC_xLINE() called for unknown line: %c!? Ignored.",
Req->command[0]);
return CONNECTED;
}
if (Req->argc == 1) {
/* Delete mask from list */
Class_DeleteMask(class, Req->argv[0]);
Log(LOG_NOTICE|LOG_snotice,
"\"%s\" deleted \"%s\" from %c-Line list.",
Client_Mask(from), Req->argv[0], class_c);
if (class == CLASS_GLINE) {
/* Inform other servers */
IRC_WriteStrServersPrefix(Client, from, "%s %s",
Req->command, Req->argv[0]);
}
} else {
/* Add new mask to list */
if (Class_AddMask(class, Req->argv[0],
time(NULL) + atol(Req->argv[1]),
Req->argv[2])) {
Log(LOG_NOTICE|LOG_snotice,
"\"%s\" added \"%s\" to %c-Line list: \"%s\" (%ld seconds).",
Client_Mask(from), Req->argv[0], class_c,
Req->argv[2], atol(Req->argv[1]));
if (class == CLASS_GLINE) {
/* Inform other servers */
IRC_WriteStrServersPrefix(Client, from,
"%s %s %s :%s", Req->command,
Req->argv[0], Req->argv[1],
Req->argv[2]);
}
}
}
return CONNECTED;
}
/* -eof- */

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
* 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
@@ -25,6 +25,8 @@ GLOBAL bool IRC_CONNECT PARAMS((CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_DISCONNECT PARAMS((CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_WALLOPS PARAMS(( CLIENT *Client, REQUEST *Req ));
GLOBAL bool IRC_xLINE PARAMS((CLIENT *Client, REQUEST *Req));
#endif
/* -eof- */

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2004 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
@@ -45,6 +45,35 @@ static bool Send_Message_Mask PARAMS((CLIENT *from, char *command,
bool SendErrors));
/**
* Check if a list limit is reached and inform client accordingly.
*
* @param From The client.
* @param Count Reply item count.
* @param Limit Reply limit.
* @param Name Name of the list.
* @return true if list limit has been reached; false otherwise.
*/
GLOBAL bool
IRC_CheckListTooBig(CLIENT *From, const int Count, const int Limit,
const char *Name)
{
assert(From != NULL);
assert(Count >= 0);
assert(Limit > 0);
assert(Name != NULL);
if (Count < Limit)
return false;
(void)IRC_WriteStrClient(From,
"NOTICE %s :%s list limit (%d) reached!",
Client_ID(From), Name, Limit);
IRC_SetPenalty(From, 2);
return true;
}
GLOBAL bool
IRC_ERROR( CLIENT *Client, REQUEST *Req )
{
@@ -63,13 +92,21 @@ IRC_ERROR( CLIENT *Client, REQUEST *Req )
/**
* Kill client on request.
* Handler for the IRC "KILL" command.
*
* This function implements the IRC command "KILL" wich is used to selectively
* disconnect clients. It can be used by IRC operators and servers, for example
* to "solve" nick collisions after netsplits.
* to "solve" nick collisions after netsplits. See RFC 2812 section 3.7.1.
*
* Please note that this function is also called internally, without a real
* KILL command being received over the network! Client is Client_ThisServer()
* in this case. */
* in this case, and the prefix in Req is NULL.
*
* @param Client The client from which this command has been received
* or Client_ThisServer() when generated interanlly.
* @param Req Request structure with prefix and all parameters.
* @returns CONNECTED or DISCONNECTED.
*/
GLOBAL bool
IRC_KILL( CLIENT *Client, REQUEST *Req )
{
@@ -77,55 +114,47 @@ IRC_KILL( CLIENT *Client, REQUEST *Req )
char reason[COMMAND_LEN], *msg;
CONN_ID my_conn, conn;
assert( Client != NULL );
assert( Req != NULL );
assert (Client != NULL);
assert (Req != NULL);
if(( Client_Type( Client ) != CLIENT_SERVER ) &&
( ! Client_OperByMe( Client )))
{
/* The originator of the KILL is neither an IRC operator of
* this server nor a server. */
return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG,
Client_ID( Client ));
}
if (Client_Type(Client) != CLIENT_SERVER && !Client_OperByMe(Client))
return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG,
Client_ID(Client));
if( Req->argc != 2 )
{
/* This command requires exactly 2 parameters! */
return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID( Client ), Req->command );
}
if (Req->argc != 2)
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
Client_ID(Client), Req->command);
if( Req->prefix ) prefix = Client_Search( Req->prefix );
else prefix = Client;
if( ! prefix )
{
Log( LOG_WARNING, "Got KILL with invalid prefix: \"%s\"!",
Req->prefix );
prefix = Client_ThisServer( );
}
if( Client != Client_ThisServer( ))
{
/* This is a "real" KILL received from the network. */
Log( LOG_NOTICE|LOG_snotice, "Got KILL command from \"%s\" for \"%s\": %s",
Client_Mask( prefix ), Req->argv[0], Req->argv[1] );
}
/* Build reason string */
if( Client_Type( Client ) == CLIENT_USER )
{
/* Prefix the "reason" if the originator is a regular user,
* so users can't spoof KILLs of servers. */
snprintf( reason, sizeof( reason ), "KILLed by %s: %s",
Client_ID( Client ), Req->argv[1] );
}
/* Get prefix (origin); use the client if no prefix is given. */
if (Req->prefix)
prefix = Client_Search(Req->prefix);
else
strlcpy( reason, Req->argv[1], sizeof( reason ));
prefix = Client;
/* Log a warning message and use this server as origin when the
* prefix (origin) is invalid. */
if (!prefix) {
Log(LOG_WARNING, "Got KILL with invalid prefix: \"%s\"!",
Req->prefix );
prefix = Client_ThisServer();
}
if (Client != Client_ThisServer())
Log(LOG_NOTICE|LOG_snotice,
"Got KILL command from \"%s\" for \"%s\": %s",
Client_Mask(prefix), Req->argv[0], Req->argv[1]);
/* Build reason string: Prefix the "reason" if the originator is a
* regular user, so users can't spoof KILLs of servers. */
if (Client_Type(Client) == CLIENT_USER)
snprintf(reason, sizeof(reason), "KILLed by %s: %s",
Client_ID(Client), Req->argv[1]);
else
strlcpy(reason, Req->argv[1], sizeof(reason));
/* Inform other servers */
IRC_WriteStrServersPrefix( Client, prefix, "KILL %s :%s",
Req->argv[0], reason );
IRC_WriteStrServersPrefix(Client, prefix, "KILL %s :%s",
Req->argv[0], reason);
/* Save ID of this connection */
my_conn = Client_Conn( Client );
@@ -320,6 +349,7 @@ static bool
Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
{
CLIENT *cl, *from;
CL2CHAN *cl2chan;
CHANNEL *chan;
char *currentTarget = Req->argv[0];
char *lastCurrentTarget = NULL;
@@ -410,8 +440,8 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
Client_Type(cl) != CLIENT_SERVICE)
continue;
if (nick != NULL && host != NULL) {
if (strcmp(nick, Client_ID(cl)) == 0 &&
strcmp(user, Client_User(cl)) == 0 &&
if (strcasecmp(nick, Client_ID(cl)) == 0 &&
strcasecmp(user, Client_User(cl)) == 0 &&
strcasecmp(host, Client_HostnameCloaked(cl)) == 0)
break;
else
@@ -439,11 +469,11 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
#else
if (Client_Type(cl) != ForceType) {
#endif
if (!SendErrors)
return CONNECTED;
return IRC_WriteStrClient(from, ERR_NOSUCHNICK_MSG,
Client_ID(from),
currentTarget);
if (SendErrors && !IRC_WriteStrClient(
from, ERR_NOSUCHNICK_MSG,Client_ID(from),
currentTarget))
return DISCONNECTED;
goto send_next_target;
}
#ifndef STRICT_RFC
@@ -456,6 +486,23 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
}
#endif
if (Client_HasMode(cl, 'C')) {
cl2chan = Channel_FirstChannelOf(cl);
while (cl2chan) {
chan = Channel_GetChannel(cl2chan);
if (Channel_IsMemberOf(chan, from))
break;
cl2chan = Channel_NextChannelOf(cl, cl2chan);
}
if (!cl2chan) {
if (SendErrors && !IRC_WriteStrClient(
from, ERR_NOTONSAMECHANNEL_MSG,
Client_ID(from), Client_ID(cl)))
return DISCONNECTED;
goto send_next_target;
}
}
if (SendErrors && (Client_Type(Client) != CLIENT_SERVER)
&& strchr(Client_Modes(cl), 'a')) {
/* Target is away */
@@ -493,7 +540,10 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
return DISCONNECTED;
}
send_next_target:
currentTarget = strtok_r(NULL, ",", &lastCurrentTarget);
if (currentTarget)
Conn_SetPenalty(Client_Conn(Client), 1);
}
return CONNECTED;

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
* Copyright (c)2001-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,6 +17,9 @@
* IRC commands (header)
*/
GLOBAL bool IRC_CheckListTooBig PARAMS((CLIENT *From, const int Count,
const int Limit, const char *Name));
GLOBAL bool IRC_ERROR PARAMS((CLIENT *Client, REQUEST *Req));
GLOBAL bool IRC_KILL PARAMS((CLIENT *Client, REQUEST *Req));
GLOBAL bool IRC_NOTICE PARAMS((CLIENT *Client, REQUEST *Req));

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2005 Alexander Barton (alex@barton.de)
* 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
@@ -37,89 +37,176 @@
#define MASK_LEN (2*CLIENT_HOST_LEN)
struct list_elem {
struct list_elem *next;
char mask[MASK_LEN];
bool onlyonce;
struct list_elem *next; /** pointer to next list element */
char mask[MASK_LEN]; /** IRC mask */
char *reason; /** Optional "reason" text */
time_t valid_until; /** 0: unlimited; 1: once; t(>1): until t */
};
/**
* Get IRC mask stored in list element.
*
* @param list_elem List element.
* @return Pointer to IRC mask
*/
GLOBAL const char *
Lists_GetMask(const struct list_elem *e)
{
assert(e != NULL);
return e->mask;
}
/**
* Get optional "reason" text stored in list element.
*
* @param list_elem List element.
* @return Pointer to "reason" text or empty string ("").
*/
GLOBAL const char *
Lists_GetReason(const struct list_elem *e)
{
assert(e != NULL);
return e->reason ? e->reason : "";
}
/**
* Get "validity" value stored in list element.
*
* @param list_elem List element.
* @return Validity: 0=unlimited, 1=once, >1 until this time stamp.
*/
GLOBAL time_t
Lists_GetValidity(const struct list_elem *e)
{
assert(e != NULL);
return e->valid_until;
}
/**
* Get first list element of a list.
*
* @param h List head.
* @return Pointer to first list element.
*/
GLOBAL struct list_elem*
Lists_GetFirst(const struct list_head *h)
{
assert(h != NULL);
return h->first;
}
/**
* Get next list element of a list.
*
* @param e Current list element.
* @return Pointer to next list element.
*/
GLOBAL struct list_elem*
Lists_GetNext(const struct list_elem *e)
{
assert(e != NULL);
return e->next;
}
/**
* Add a new mask to a list.
*
* @param h List head.
* @param Mask The IRC mask to add to the list.
* @param ValidUntil 0: unlimited, 1: only once, t>1: until given time_t.
* @param Reason Reason string or NULL, if no reason should be saved.
* @return true on success, false otherwise.
*/
bool
Lists_Add(struct list_head *header, const char *Mask, bool OnlyOnce )
Lists_Add(struct list_head *h, const char *Mask, time_t ValidUntil,
const char *Reason)
{
struct list_elem *e, *newelem;
assert( header != NULL );
assert( Mask != NULL );
assert(h != NULL);
assert(Mask != NULL);
if (Lists_CheckDupeMask(header, Mask )) return true;
e = Lists_CheckDupeMask(h, Mask);
if (e) {
e->valid_until = ValidUntil;
if (Reason) {
free(e->reason);
e->reason = strdup(Reason);
}
return true;
}
e = Lists_GetFirst(header);
e = Lists_GetFirst(h);
newelem = malloc(sizeof(struct list_elem));
if( ! newelem ) {
Log( LOG_EMERG, "Can't allocate memory for new Ban/Invite entry!" );
if (!newelem) {
Log(LOG_EMERG,
"Can't allocate memory for new list entry!");
return false;
}
strlcpy( newelem->mask, Mask, sizeof( newelem->mask ));
newelem->onlyonce = OnlyOnce;
strlcpy(newelem->mask, Mask, sizeof(newelem->mask));
if (Reason) {
newelem->reason = strdup(Reason);
if (!newelem->reason)
Log(LOG_EMERG,
"Can't allocate memory for new list reason text!");
}
else
newelem->reason = NULL;
newelem->valid_until = ValidUntil;
newelem->next = e;
header->first = newelem;
h->first = newelem;
return true;
}
/**
* Delete a list element from a list.
*
* @param h List head.
* @param p Pointer to previous list element or NULL, if there is none.
* @param victim List element to delete.
*/
static void
Lists_Unlink(struct list_head *header, struct list_elem *p, struct list_elem *victim)
Lists_Unlink(struct list_head *h, struct list_elem *p, struct list_elem *victim)
{
assert(victim != NULL);
assert(header != NULL);
assert(h != NULL);
if (p) p->next = victim->next;
else header->first = victim->next;
if (p)
p->next = victim->next;
else
h->first = victim->next;
if (victim->reason)
free(victim->reason);
free(victim);
}
/**
* Delete a given IRC mask from a list.
*
* @param h List head.
* @param Mask IRC mask to delete from the list.
*/
GLOBAL void
Lists_Del(struct list_head *header, const char *Mask)
Lists_Del(struct list_head *h, const char *Mask)
{
struct list_elem *e, *last, *victim;
assert( header != NULL );
assert( Mask != NULL );
assert(h != NULL);
assert(Mask != NULL);
last = NULL;
e = Lists_GetFirst(header);
while( e ) {
if(strcasecmp( e->mask, Mask ) == 0 ) {
e = Lists_GetFirst(h);
while (e) {
if (strcasecmp(e->mask, Mask) == 0) {
LogDebug("Deleted \"%s\" from list", e->mask);
victim = e;
e = victim->next;
Lists_Unlink(header, last, victim);
Lists_Unlink(h, last, victim);
continue;
}
last = e;
@@ -127,7 +214,11 @@ Lists_Del(struct list_head *header, const char *Mask)
}
}
/**
* Free a complete list.
*
* @param head List head.
*/
GLOBAL void
Lists_Free(struct list_head *head)
{
@@ -138,101 +229,193 @@ Lists_Free(struct list_head *head)
e = head->first;
head->first = NULL;
while (e) {
LogDebug("Deleted \"%s\" from invite list" , e->mask);
LogDebug("Deleted \"%s\" from list" , e->mask);
victim = e;
e = e->next;
free( victim );
if (victim->reason)
free(victim->reason);
free(victim);
}
}
GLOBAL bool
/**
* Check if an IRC mask is already contained in a list.
*
* @param h List head.
* @param Mask IRC mask to test.
* @return true if mask is already stored in the list, false otherwise.
*/
GLOBAL struct list_elem *
Lists_CheckDupeMask(const struct list_head *h, const char *Mask )
{
struct list_elem *e;
e = h->first;
while (e) {
if (strcasecmp( e->mask, Mask ) == 0 )
return true;
if (strcasecmp(e->mask, Mask) == 0)
return e;
e = e->next;
}
return false;
return NULL;
}
/**
* Generate a valid IRC mask from "any" string given.
*
* Attention: This mask is only valid until the next call to Lists_MakeMask(),
* because a single global buffer ist used! You have to copy the generated
* mask to some sane location yourself!
*
* @param Pattern Source string to generate an IRC mask for.
* @return Pointer to global result buffer.
*/
GLOBAL const char *
Lists_MakeMask(const char *Pattern)
{
/* This function generats a valid IRC mask of "any" string. This
* mask is only valid until the next call to Lists_MakeMask(),
* because a single global buffer is used. You have to copy the
* generated mask to some sane location yourself! */
static char TheMask[MASK_LEN];
char *excl, *at;
assert( Pattern != NULL );
assert(Pattern != NULL);
excl = strchr( Pattern, '!' );
at = strchr( Pattern, '@' );
excl = strchr(Pattern, '!');
at = strchr(Pattern, '@');
if(( at ) && ( at < excl )) excl = NULL;
if (at && at < excl)
excl = NULL;
if(( ! at ) && ( ! excl ))
{
if (!at && !excl) {
/* Neither "!" nor "@" found: use string as nick name */
strlcpy( TheMask, Pattern, sizeof( TheMask ) - 5 );
strlcat( TheMask, "!*@*", sizeof( TheMask ));
strlcpy(TheMask, Pattern, sizeof(TheMask) - 5);
strlcat(TheMask, "!*@*", sizeof(TheMask));
return TheMask;
}
if(( ! at ) && ( excl ))
{
if (!at && excl) {
/* Domain part is missing */
strlcpy( TheMask, Pattern, sizeof( TheMask ) - 3 );
strlcat( TheMask, "@*", sizeof( TheMask ));
strlcpy(TheMask, Pattern, sizeof(TheMask) - 3);
strlcat(TheMask, "@*", sizeof(TheMask));
return TheMask;
}
if(( at ) && ( ! excl ))
{
if (at && !excl) {
/* User name is missing */
*at = '\0'; at++;
strlcpy( TheMask, Pattern, sizeof( TheMask ) - 5 );
strlcat( TheMask, "!*@", sizeof( TheMask ));
strlcat( TheMask, at, sizeof( TheMask ));
strlcpy(TheMask, Pattern, sizeof(TheMask) - 5);
strlcat(TheMask, "!*@", sizeof(TheMask));
strlcat(TheMask, at, sizeof(TheMask));
return TheMask;
}
/* All parts (nick, user and domain name) are given */
strlcpy( TheMask, Pattern, sizeof( TheMask ));
strlcpy(TheMask, Pattern, sizeof(TheMask));
return TheMask;
} /* Lists_MakeMask */
/**
* Check if a client is listed in a list.
*
* @param h List head.
* @param Client Client to check.
* @return true if client is listed, false if not.
*/
bool
Lists_Check( struct list_head *header, CLIENT *Client)
Lists_Check(struct list_head *h, CLIENT *Client)
{
struct list_elem *e, *last;
return Lists_CheckReason(h, Client) != NULL;
}
assert( header != NULL );
/**
* Check if a client is listed in a list and return the "reason".
*
* @param h List head.
* @param Client Client to check.
* @return true if client is listed, false if not.
*/
char *
Lists_CheckReason(struct list_head *h, CLIENT *Client)
{
struct list_elem *e, *last, *next;
e = header->first;
assert(h != NULL);
e = h->first;
last = NULL;
while( e ) {
if( Match( e->mask, Client_Mask( Client ))) {
if( e->onlyonce ) { /* delete entry */
LogDebug("Deleted \"%s\" from list", e->mask);
Lists_Unlink(header, last, e);
while (e) {
next = e->next;
if (Match(e->mask, Client_Mask(Client))) {
if (e->valid_until == 1) {
/* Entry is valid only once, delete it */
LogDebug("Deleted \"%s\" from list (used).",
e->mask);
Lists_Unlink(h, last, e);
}
return true;
return e->reason ? e->reason : "";
}
last = e;
e = e->next;
e = next;
}
return false;
return NULL;
}
/**
* Check list and purge expired entries.
*
* @param h List head.
*/
GLOBAL void
Lists_Expire(struct list_head *h, const char *ListName)
{
struct list_elem *e, *last, *next;
time_t now;
assert(h != NULL);
e = h->first;
last = NULL;
now = time(NULL);
while (e) {
next = e->next;
if (e->valid_until > 1 && e->valid_until < now) {
/* Entry is expired, delete it */
if (e->reason)
Log(LOG_INFO,
"Deleted \"%s\" (\"%s\") from %s list (expired).",
e->mask, e->reason, ListName);
else
Log(LOG_INFO,
"Deleted \"%s\" from %s list (expired).",
e->mask, ListName);
Lists_Unlink(h, last, e);
e = next;
continue;
}
last = e;
e = next;
}
}
/**
* Return the number of entries of a list.
*
* @param h List head.
* @return Number of items.
*/
GLOBAL unsigned long
Lists_Count(struct list_head *h)
{
struct list_elem *e;
unsigned long count = 0;
assert(h != NULL);
e = h->first;
while (e) {
count++;
e = e->next;
}
return count;
}
/* -eof- */

View File

@@ -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
@@ -29,18 +29,24 @@ struct list_head {
GLOBAL struct list_elem *Lists_GetFirst PARAMS((const struct list_head *));
GLOBAL struct list_elem *Lists_GetNext PARAMS((const struct list_elem *));
GLOBAL bool Lists_Check PARAMS((struct list_head *head, CLIENT *client ));
GLOBAL bool Lists_CheckDupeMask PARAMS((const struct list_head *head, const char *mask ));
GLOBAL bool Lists_Check PARAMS((struct list_head *head, CLIENT *client));
GLOBAL char *Lists_CheckReason PARAMS((struct list_head *head, CLIENT *client));
GLOBAL struct list_elem *Lists_CheckDupeMask PARAMS((const struct list_head *head,
const char *mask));
GLOBAL bool Lists_Add PARAMS((struct list_head *header, const char *Mask, bool OnlyOnce ));
GLOBAL void Lists_Del PARAMS((struct list_head *head, const char *Mask ));
GLOBAL bool Lists_Add PARAMS((struct list_head *h, const char *Mask,
time_t ValidUntil, const char *Reason));
GLOBAL void Lists_Del PARAMS((struct list_head *head, const char *Mask));
GLOBAL unsigned long Lists_Count PARAMS((struct list_head *h));
GLOBAL bool Lists_AlreadyRegistered PARAMS(( const struct list_head *head, const char *Mask));
GLOBAL void Lists_Free PARAMS(( struct list_head *head ));
GLOBAL void Lists_Free PARAMS((struct list_head *head));
GLOBAL const char *Lists_MakeMask PARAMS((const char *Pattern));
GLOBAL const char *Lists_GetMask PARAMS(( const struct list_elem *e ));
GLOBAL const char *Lists_GetMask PARAMS((const struct list_elem *e));
GLOBAL const char *Lists_GetReason PARAMS((const struct list_elem *e));
GLOBAL time_t Lists_GetValidity PARAMS((const struct list_elem *e));
GLOBAL void Lists_Expire PARAMS((struct list_head *h, const char *ListName));
#endif

View File

@@ -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
@@ -44,7 +44,6 @@
#include "log.h"
static char Init_Txt[127];
static bool Is_Daemon;
@@ -65,47 +64,46 @@ Log_Message(int Level, const char *msg)
}
/**
* Initialitze logging.
* This function is called before the configuration file is read in.
*
* @param Daemon_Mode Set to true if ngIRCd is running as daemon.
*/
GLOBAL void
Log_Init( bool Daemon_Mode )
Log_Init(bool Daemon_Mode)
{
Is_Daemon = Daemon_Mode;
#ifdef SYSLOG
#ifndef LOG_CONS /* Kludge: mips-dec-ultrix4.5 has no LOG_CONS */
#define LOG_CONS 0
#endif
#ifdef LOG_DAEMON
openlog(PACKAGE_NAME, LOG_CONS|LOG_PID, LOG_DAEMON);
#else
openlog(PACKAGE_NAME, LOG_CONS|LOG_PID, 0);
#endif
#endif
} /* Log_Init */
/**
* Re-init logging after reading the configuration file.
*/
GLOBAL void
Log_ReInit(void)
{
#ifdef SYSLOG
#ifndef LOG_CONS /* Kludge: mips-dec-ultrix4.5 has no LOG_CONS */
#define LOG_CONS 0
#endif
closelog();
openlog(PACKAGE_NAME, LOG_CONS|LOG_PID, Conf_SyslogFacility);
#endif
Log( LOG_NOTICE, "%s started.", NGIRCd_Version );
/* Information about "Operation Mode" */
Init_Txt[0] = '\0';
#ifdef DEBUG
if( NGIRCd_Debug )
{
strlcpy( Init_Txt, "debug-mode", sizeof Init_Txt );
}
#endif
if( ! Is_Daemon )
{
if( Init_Txt[0] ) strlcat( Init_Txt, ", ", sizeof Init_Txt );
strlcat( Init_Txt, "no-daemon-mode", sizeof Init_Txt );
}
if( NGIRCd_Passive )
{
if( Init_Txt[0] ) strlcat( Init_Txt, ", ", sizeof Init_Txt );
strlcat( Init_Txt, "passive-mode", sizeof Init_Txt );
}
#ifdef SNIFFER
if( NGIRCd_Sniffer )
{
if( Init_Txt[0] ) strlcat( Init_Txt, ", ", sizeof Init_Txt );
strlcat( Init_Txt, "network sniffer", sizeof Init_Txt );
}
#endif
if( Init_Txt[0] ) Log( LOG_INFO, "Activating: %s.", Init_Txt );
} /* Log_Init */
Log(LOG_NOTICE, "%s started.", NGIRCd_Version);
Log(LOG_INFO, "Using configuration file \"%s\" ...", NGIRCd_ConfFile);
}
GLOBAL void

View File

@@ -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
@@ -36,6 +36,7 @@ GLOBAL void Log_Init PARAMS(( bool Daemon_Mode ));
GLOBAL void Log_Exit PARAMS(( void ));
GLOBAL void Log PARAMS(( int Level, const char *Format, ... ));
GLOBAL void Log_ReInit PARAMS((void));
GLOBAL void Log_ServerNotice PARAMS((char UserMode, const char *Format, ...));

243
src/ngircd/login.c Normal file
View File

@@ -0,0 +1,243 @@
/*
* 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
* Functions to deal with client logins
*/
#include "imp.h"
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include "defines.h"
#include "conn.h"
#include "class.h"
#include "client.h"
#include "client-cap.h"
#include "channel.h"
#include "conf.h"
#include "io.h"
#include "parse.h"
#include "log.h"
#include "messages.h"
#include "ngircd.h"
#include "pam.h"
#include "irc-info.h"
#include "irc-write.h"
#include "exp.h"
#include "login.h"
#ifdef PAM
static void cb_Read_Auth_Result PARAMS((int r_fd, UNUSED short events));
#endif
/**
* Initiate client login.
*
* This function is called after the daemon received the required NICK and
* USER commands of a new client. If the daemon is compiled with support for
* PAM, the authentication sub-processs is forked; otherwise the global server
* password is checked.
*
* @param Client The client logging in.
* @returns CONNECTED or DISCONNECTED.
*/
GLOBAL bool
Login_User(CLIENT * Client)
{
#ifdef PAM
int pipefd[2], result;
pid_t pid;
#endif
CONN_ID conn;
assert(Client != NULL);
conn = Client_Conn(Client);
#ifndef STRICT_RFC
if (Conf_AuthPing) {
/* Did we receive the "auth PONG" already? */
if (Conn_GetAuthPing(conn)) {
Client_SetType(Client, CLIENT_WAITAUTHPING);
LogDebug("Connection %d: Waiting for AUTH PONG ...", conn);
return CONNECTED;
}
}
#endif
/* Still waiting for "CAP END" command? */
if (Client_Cap(Client) & CLIENT_CAP_PENDING) {
Client_SetType(Client, CLIENT_WAITCAPEND);
LogDebug("Connection %d: Waiting for CAP END ...", conn);
return CONNECTED;
}
#ifdef PAM
if (!Conf_PAM) {
/* Don't do any PAM authentication at all, instead emulate
* 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')
return Login_User_PostAuth(Client);
Client_Reject(Client, "Non-empty password", false);
return DISCONNECTED;
}
if (Conf_PAMIsOptional && strcmp(Client_Password(Client), "") == 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.
* Therefore it is sensible to either set Conf_PAMisOptional or
* to enable IDENT lookups -- not both. */
return Login_User_PostAuth(Client);
}
/* Fork child process for PAM authentication; and make sure that the
* process timeout is set higher than the login timeout! */
pid = Proc_Fork(Conn_GetProcStat(conn), pipefd,
cb_Read_Auth_Result, Conf_PongTimeout + 1);
if (pid > 0) {
LogDebug("Authenticator for connection %d created (PID %d).",
conn, pid);
return CONNECTED;
} else {
/* Sub process */
Log_Init_Subprocess("Auth");
Conn_CloseAllSockets(NONE);
result = PAM_Authenticate(Client);
if (write(pipefd[1], &result, sizeof(result)) != sizeof(result))
Log_Subprocess(LOG_ERR,
"Failed to pipe result to parent!");
Log_Exit_Subprocess("Auth");
exit(0);
}
#else
/* Check global server password ... */
if (strcmp(Client_Password(Client), Conf_ServerPwd) != 0) {
/* Bad password! */
Client_Reject(Client, "Bad server password", false);
return DISCONNECTED;
}
return Login_User_PostAuth(Client);
#endif
}
/**
* Finish client registration.
*
* Introduce the new client to the network and send all "hello messages"
* to it after authentication has been succeeded.
*
* @param Client The client logging in.
* @return CONNECTED or DISCONNECTED.
*/
GLOBAL bool
Login_User_PostAuth(CLIENT *Client)
{
assert(Client != NULL);
if (Class_HandleServerBans(Client) != CONNECTED)
return DISCONNECTED;
Client_Introduce(NULL, Client, CLIENT_USER);
if (!IRC_WriteStrClient
(Client, RPL_WELCOME_MSG, Client_ID(Client), Client_Mask(Client)))
return false;
if (!IRC_WriteStrClient
(Client, RPL_YOURHOST_MSG, Client_ID(Client),
Client_ID(Client_ThisServer()), PACKAGE_VERSION, TARGET_CPU,
TARGET_VENDOR, TARGET_OS))
return false;
if (!IRC_WriteStrClient
(Client, RPL_CREATED_MSG, Client_ID(Client), NGIRCd_StartStr))
return false;
if (!IRC_WriteStrClient
(Client, RPL_MYINFO_MSG, Client_ID(Client),
Client_ID(Client_ThisServer()), PACKAGE_VERSION, USERMODES,
CHANMODES))
return false;
/* Features supported by this server (005 numeric, ISUPPORT),
* see <http://www.irc.org/tech_docs/005.html> for details. */
if (!IRC_Send_ISUPPORT(Client))
return DISCONNECTED;
if (!IRC_Send_LUSERS(Client))
return DISCONNECTED;
if (!IRC_Show_MOTD(Client))
return DISCONNECTED;
/* Suspend the client for a second ... */
IRC_SetPenalty(Client, 1);
return CONNECTED;
}
#ifdef PAM
/**
* Read result of the authenticatior sub-process from pipe
*
* @param r_fd File descriptor of the pipe.
* @param events (ignored IO specification)
*/
static void
cb_Read_Auth_Result(int r_fd, UNUSED short events)
{
CONN_ID conn;
CLIENT *client;
int result;
size_t len;
PROC_STAT *proc;
LogDebug("Auth: Got callback on fd %d, events %d", r_fd, events);
conn = Conn_GetFromProc(r_fd);
if (conn == NONE) {
/* Ops, none found? Probably the connection has already
* been closed!? We'll ignore that ... */
io_close(r_fd);
LogDebug("Auth: Got callback for unknown connection!?");
return;
}
proc = Conn_GetProcStat(conn);
client = Conn_GetClient(conn);
/* Read result from pipe */
len = Proc_Read(proc, &result, sizeof(result));
Proc_Close(proc);
if (len == 0)
return;
if (len != sizeof(result)) {
Log(LOG_CRIT, "Auth: Got malformed result!");
Client_Reject(client, "Internal error", false);
return;
}
if (result == true) {
Client_SetUser(client, Client_OrigUser(client), true);
(void)Login_User_PostAuth(client);
} else
Client_Reject(client, "Bad password", false);
}
#endif
/* -eof- */

25
src/ngircd/login.h Normal file
View File

@@ -0,0 +1,25 @@
/*
* 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 __login_h__
#define __login_h__
/**
* @file
* Functions to deal with client logins (header)
*/
GLOBAL bool Login_User PARAMS((CLIENT * Client));
GLOBAL bool Login_User_PostAuth PARAMS((CLIENT *Client));
#endif
/* -eof- */

View File

@@ -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
@@ -21,14 +21,15 @@
#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=bI,k,l,imnPst CHANLIMIT=#&+:%d :are supported on this server"
#define RPL_ISUPPORT2_MSG "005 %s CHANNELLEN=%d NICKLEN=%d TOPICLEN=%d AWAYLEN=%d KICKLEN=%d PENALTY :are supported on this server"
#define RPL_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_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"
#define RPL_TRACEOPERATOR_MSG "204 %s Oper 2 :%s"
#define RPL_TRACESERVER_MSG "206 %s Serv 1 0S 0C %s[%s@%s] *!*@%s :V%s"
#define RPL_STATSLINKINFO_MSG "211 %s %s %d %ld %ld %ld %ld :%ld"
#define RPL_STATSCOMMANDS_MSG "212 %s %s %ld %ld %ld"
#define RPL_STATSXLINE_MSG "216 %s %c %s %ld :%s"
#define RPL_ENDOFSTATS_MSG "219 %s %c :End of STATS report"
#define RPL_UMODEIS_MSG "221 %s +%s"
#define RPL_SERVLIST_MSG "234 %s %s %s %s %d %d :%s"
@@ -55,6 +56,7 @@
#define RPL_ISON_MSG "303 %s :"
#define RPL_UNAWAY_MSG "305 %s :You are no longer marked as being away"
#define RPL_NOWAWAY_MSG "306 %s :You have been marked as being away"
#define RPL_WHOISREGNICK_MSG "307 %s %s :is a registered nick"
#define RPL_WHOISUSER_MSG "311 %s %s %s %s * :%s"
#define RPL_WHOISSERVER_MSG "312 %s %s %s :%s"
#define RPL_WHOISOPERATOR_MSG "313 %s %s :is an IRC operator"
@@ -73,6 +75,8 @@
#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"
#define RPL_EXCEPTLIST_MSG "348 %s %s %s"
#define RPL_ENDOFEXCEPTLIST_MSG "349 %s %s :End of channel exception list"
#define RPL_VERSION_MSG "351 %s %s-%s.%s %s :%s"
#define RPL_WHOREPLY_MSG "352 %s %s %s %s %s %s %s :%d %s"
#define RPL_NAMREPLY_MSG "353 %s %s %s :"
@@ -87,6 +91,7 @@
#define RPL_MOTD_MSG "372 %s :- %s"
#define RPL_MOTDSTART_MSG "375 %s :- %s message of the day"
#define RPL_ENDOFMOTD_MSG "376 %s :End of MOTD command"
#define RPL_WHOISHOST_MSG "378 %s %s :is connecting from *@%s %s"
#define RPL_YOUREOPER_MSG "381 %s :You are now an IRC Operator"
#define RPL_YOURESERVICE_MSG "383 %s :You are service %s"
#define RPL_TIME_MSG "391 %s %s :%s"
@@ -98,6 +103,7 @@
#define ERR_TOOMANYCHANNELS_MSG "405 %s %s :You have joined too many channels"
#define ERR_WASNOSUCHNICK_MSG "406 %s %s :There was no such nickname"
#define ERR_NOORIGIN_MSG "409 %s :No origin specified"
#define ERR_INVALIDCAP_MSG "410 %s %s :Invalid CAP subcommand"
#define ERR_NORECIPIENT_MSG "411 %s :No recipient given (%s)"
#define ERR_NOTEXTTOSEND_MSG "412 %s :No text to send"
#define ERR_WILDTOPLEVEL "414 %s :Wildcard in toplevel domain"
@@ -105,12 +111,13 @@
#define ERR_NOMOTD_MSG "422 %s :MOTD file is missing"
#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_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"
#define ERR_USERONCHANNEL_MSG "443 %s %s %s :is already on channel"
#define ERR_SUMMONDISABLED_MSG "445 %s %s :SUMMON has been disabled"
#define ERR_USERSDISABLED_MSG "446 %s %s :USERS has been disabled"
#define ERR_SUMMONDISABLED_MSG "445 %s :SUMMON has been disabled"
#define ERR_USERSDISABLED_MSG "446 %s :USERS has been disabled"
#define ERR_NOTREGISTERED_MSG "451 %s :Connection not registered"
#define ERR_NOTREGISTEREDSERVER_MSG "451 %s :Connection not registered as server link"
#define ERR_NEEDMOREPARAMS_MSG "461 %s %s :Syntax error"
@@ -119,16 +126,19 @@
#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_UNKNOWNMODE_MSG "472 %s: %c :is unknown mode char for %s"
#define ERR_REGONLYCHANNEL_MSG "471 %s %s :Cannot join channel (+R)"
#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_NOCHANMODES_MSG "477 %s %s :Channel doesn't support modes"
#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_CANTKILLSERVER_MSG "483 %s :You can't kill a server!"
#define ERR_RESTRICTED_MSG "484 %s :Your connection is restricted"
#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\""

View File

@@ -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
@@ -38,6 +38,7 @@
#include "defines.h"
#include "conn.h"
#include "class.h"
#include "conf-ssl.h"
#include "channel.h"
#include "conf.h"
@@ -73,12 +74,12 @@ static bool NGIRCd_Init PARAMS(( bool ));
* Here all starts: this function is called by the operating system loader,
* it is the first portion of code executed of ngIRCd.
*
* @param argc The number of arguments passed to ngIRCd on the command line.
* @param argv An array containing all the arguments passed to ngIRCd.
* @return Global exit code of ngIRCd, zero on success.
* @param argc The number of arguments passed to ngIRCd on the command line.
* @param argv An array containing all the arguments passed to ngIRCd.
* @return Global exit code of ngIRCd, zero on success.
*/
GLOBAL int
main( int argc, const char *argv[] )
main(int argc, const char *argv[])
{
bool ok, configtest = false;
bool NGIRCd_NoDaemon = false;
@@ -91,7 +92,7 @@ main( int argc, const char *argv[] )
mtrace();
#endif
umask( 0077 );
umask(0077);
NGIRCd_SignalQuit = NGIRCd_SignalRestart = false;
NGIRCd_Passive = false;
@@ -101,75 +102,62 @@ main( int argc, const char *argv[] )
#ifdef SNIFFER
NGIRCd_Sniffer = false;
#endif
strlcpy( NGIRCd_ConfFile, SYSCONFDIR, sizeof( NGIRCd_ConfFile ));
strlcat( NGIRCd_ConfFile, CONFIG_FILE, sizeof( NGIRCd_ConfFile ));
strlcpy(NGIRCd_ConfFile, SYSCONFDIR, sizeof(NGIRCd_ConfFile));
strlcat(NGIRCd_ConfFile, CONFIG_FILE, sizeof(NGIRCd_ConfFile));
Fill_Version( );
Fill_Version();
/* parse conmmand line */
for( i = 1; i < argc; i++ )
{
for (i = 1; i < argc; i++) {
ok = false;
if(( argv[i][0] == '-' ) && ( argv[i][1] == '-' ))
{
if (argv[i][0] == '-' && argv[i][1] == '-') {
/* long option */
if( strcmp( argv[i], "--config" ) == 0 )
{
if( i + 1 < argc )
{
if (strcmp(argv[i], "--config") == 0) {
if (i + 1 < argc) {
/* Ok, there's an parameter left */
strlcpy( NGIRCd_ConfFile, argv[i + 1], sizeof( NGIRCd_ConfFile ));
strlcpy(NGIRCd_ConfFile, argv[i+1],
sizeof(NGIRCd_ConfFile));
/* next parameter */
i++; ok = true;
}
}
if( strcmp( argv[i], "--configtest" ) == 0 )
{
if (strcmp(argv[i], "--configtest") == 0) {
configtest = true;
ok = true;
}
#ifdef DEBUG
if( strcmp( argv[i], "--debug" ) == 0 )
{
if (strcmp(argv[i], "--debug") == 0) {
NGIRCd_Debug = true;
ok = true;
}
#endif
if( strcmp( argv[i], "--help" ) == 0 )
{
Show_Version( );
puts( "" ); Show_Help( ); puts( "" );
exit( 1 );
if (strcmp(argv[i], "--help") == 0) {
Show_Version();
puts(""); Show_Help( ); puts( "" );
exit(1);
}
if( strcmp( argv[i], "--nodaemon" ) == 0 )
{
if (strcmp(argv[i], "--nodaemon") == 0) {
NGIRCd_NoDaemon = true;
ok = true;
}
if( strcmp( argv[i], "--passive" ) == 0 )
{
if (strcmp(argv[i], "--passive") == 0) {
NGIRCd_Passive = true;
ok = true;
}
#ifdef SNIFFER
if( strcmp( argv[i], "--sniffer" ) == 0 )
{
if (strcmp(argv[i], "--sniffer") == 0) {
NGIRCd_Sniffer = true;
ok = true;
}
#endif
if( strcmp( argv[i], "--version" ) == 0 )
{
Show_Version( );
exit( 1 );
if (strcmp(argv[i], "--version") == 0) {
Show_Version();
exit(1);
}
}
else if(( argv[i][0] == '-' ) && ( argv[i][1] != '-' ))
{
else if(argv[i][0] == '-' && argv[i][1] != '-') {
/* short option */
for( n = 1; n < strlen( argv[i] ); n++ )
{
for (n = 1; n < strlen(argv[i]); n++) {
ok = false;
#ifdef DEBUG
if (argv[i][n] == 'd') {
@@ -178,14 +166,14 @@ main( int argc, const char *argv[] )
}
#endif
if (argv[i][n] == 'f') {
if(( ! argv[i][n + 1] ) && ( i + 1 < argc ))
{
if (!argv[i][n+1] && i+1 < argc) {
/* Ok, next character is a blank */
strlcpy( NGIRCd_ConfFile, argv[i + 1], sizeof( NGIRCd_ConfFile ));
strlcpy(NGIRCd_ConfFile, argv[i+1],
sizeof(NGIRCd_ConfFile));
/* go to the following parameter */
i++;
n = strlen( argv[i] );
n = strlen(argv[i]);
ok = true;
}
}
@@ -220,55 +208,58 @@ main( int argc, const char *argv[] )
exit(1);
}
if (! ok) {
printf( "%s: invalid option \"-%c\"!\n", PACKAGE_NAME, argv[i][n] );
printf( "Try \"%s --help\" for more information.\n", PACKAGE_NAME );
exit( 1 );
if (!ok) {
printf("%s: invalid option \"-%c\"!\n",
PACKAGE_NAME, argv[i][n]);
printf("Try \"%s --help\" for more information.\n",
PACKAGE_NAME);
exit(1);
}
}
}
if( ! ok )
{
printf( "%s: invalid option \"%s\"!\n", PACKAGE_NAME, argv[i] );
printf( "Try \"%s --help\" for more information.\n", PACKAGE_NAME );
exit( 1 );
if (!ok) {
printf("%s: invalid option \"%s\"!\n",
PACKAGE_NAME, argv[i]);
printf("Try \"%s --help\" for more information.\n",
PACKAGE_NAME);
exit(1);
}
}
/* Debug level for "VERSION" command */
NGIRCd_DebugLevel[0] = '\0';
#ifdef DEBUG
if( NGIRCd_Debug ) strcpy( NGIRCd_DebugLevel, "1" );
if (NGIRCd_Debug)
strcpy(NGIRCd_DebugLevel, "1");
#endif
#ifdef SNIFFER
if( NGIRCd_Sniffer )
{
if (NGIRCd_Sniffer) {
NGIRCd_Debug = true;
strcpy( NGIRCd_DebugLevel, "2" );
strcpy(NGIRCd_DebugLevel, "2");
}
#endif
if( configtest )
{
Show_Version( ); puts( "" );
exit( Conf_Test( ));
if (configtest) {
Show_Version(); puts("");
exit(Conf_Test());
}
while( ! NGIRCd_SignalQuit )
{
while (!NGIRCd_SignalQuit) {
/* Initialize global variables */
NGIRCd_Start = time( NULL );
(void)strftime( NGIRCd_StartStr, 64, "%a %b %d %Y at %H:%M:%S (%Z)", localtime( &NGIRCd_Start ));
NGIRCd_Start = time(NULL);
(void)strftime(NGIRCd_StartStr, 64,
"%a %b %d %Y at %H:%M:%S (%Z)",
localtime(&NGIRCd_Start));
NGIRCd_SignalRestart = false;
NGIRCd_SignalQuit = false;
Random_Init();
/* Initialize modules, part I */
Log_Init( ! NGIRCd_NoDaemon );
Conf_Init( );
Log_Init(!NGIRCd_NoDaemon);
Random_Init();
Conf_Init();
Log_ReInit();
/* Initialize the "main program": chroot environment, user and
* group ID, ... */
@@ -279,17 +270,22 @@ main( int argc, const char *argv[] )
/* Initialize modules, part II: these functions are eventually
* called with already dropped privileges ... */
Channel_Init( );
Client_Init( );
Conn_Init( );
Channel_Init();
Client_Init();
Conn_Init();
Class_Init();
if (!io_library_init(CONNECTION_POOL)) {
Log(LOG_ALERT, "Fatal: Cannot initialize IO routines: %s", strerror(errno));
Log(LOG_ALERT,
"Fatal: Could not initialize IO routines: %s",
strerror(errno));
exit(1);
}
if (!Signals_Init()) {
Log(LOG_ALERT, "Fatal: Could not set up signal handlers: %s", strerror(errno));
Log(LOG_ALERT,
"Fatal: Could not set up signal handlers: %s",
strerror(errno));
exit(1);
}
@@ -297,39 +293,45 @@ main( int argc, const char *argv[] )
* used by ngIRCd in PASS commands and the known "extended
* flags" are described in doc/Protocol.txt. */
#ifdef IRCPLUS
snprintf( NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s:%s", PROTOVER, PROTOIRCPLUS, PACKAGE_NAME, PACKAGE_VERSION, IRCPLUSFLAGS );
snprintf(NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s:%s",
PROTOVER, PROTOIRCPLUS, PACKAGE_NAME, PACKAGE_VERSION,
IRCPLUSFLAGS);
#ifdef ZLIB
strcat( NGIRCd_ProtoID, "Z" );
strcat(NGIRCd_ProtoID, "Z");
#endif
if( Conf_OperCanMode ) strcat( NGIRCd_ProtoID, "o" );
#else
snprintf( NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s", PROTOVER, PROTOIRC, PACKAGE_NAME, PACKAGE_VERSION );
#endif
strlcat( NGIRCd_ProtoID, " P", sizeof NGIRCd_ProtoID );
if (Conf_OperCanMode)
strcat(NGIRCd_ProtoID, "o");
#else /* IRCPLUS */
snprintf(NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s",
PROTOVER, PROTOIRC, PACKAGE_NAME, PACKAGE_VERSION);
#endif /* IRCPLUS */
strlcat(NGIRCd_ProtoID, " P", sizeof NGIRCd_ProtoID);
#ifdef ZLIB
strlcat( NGIRCd_ProtoID, "Z", sizeof NGIRCd_ProtoID );
strlcat(NGIRCd_ProtoID, "Z", sizeof NGIRCd_ProtoID);
#endif
LogDebug("Protocol and server ID is \"%s\".", NGIRCd_ProtoID);
Channel_InitPredefined( );
Channel_InitPredefined();
if( Conn_InitListeners( ) < 1 )
{
Log( LOG_ALERT, "Server isn't listening on a single port!" );
Log( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME );
Pidfile_Delete( );
exit( 1 );
if (Conn_InitListeners() < 1) {
Log(LOG_ALERT,
"Server isn't listening on a single port!" );
Log(LOG_ALERT,
"%s exiting due to fatal errors!", PACKAGE_NAME);
Pidfile_Delete();
exit(1);
}
/* Main Run Loop */
Conn_Handler( );
Conn_Handler();
Conn_Exit( );
Client_Exit( );
Channel_Exit( );
Log_Exit( );
Conn_Exit();
Client_Exit();
Channel_Exit();
Class_Exit();
Log_Exit();
}
Pidfile_Delete( );
Pidfile_Delete();
return 0;
} /* main */
@@ -421,7 +423,7 @@ static void
Show_Version( void )
{
puts( NGIRCd_Version );
puts( "Copyright (c)2001-2011 Alexander Barton (<alex@barton.de>) and Contributors." );
puts( "Copyright (c)2001-2012 Alexander Barton (<alex@barton.de>) and Contributors." );
puts( "Homepage: <http://ngircd.barton.de/>\n" );
puts( "This is free software; see the source for copying conditions. There is NO" );
puts( "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." );
@@ -496,7 +498,8 @@ Pidfile_Create(pid_t pid)
len = snprintf(pidbuf, sizeof pidbuf, "%ld\n", (long)pid);
if (len < 0 || len >= (int)sizeof pidbuf) {
Log( LOG_ERR, "Error converting pid");
Log(LOG_ERR, "Error converting pid");
close(pidfd);
return;
}
@@ -553,9 +556,10 @@ NGIRCd_getNobodyID(uid_t *uid, gid_t *gid )
#endif
pwd = getpwnam("nobody");
if (!pwd) return false;
if (!pwd)
return false;
if ( !pwd->pw_uid || !pwd->pw_gid)
if (!pwd->pw_uid || !pwd->pw_gid)
return false;
*uid = pwd->pw_uid;
@@ -593,19 +597,19 @@ Random_Init(void)
return;
if (Random_Init_Kern("/dev/arandom"))
return;
srand(rand() ^ getpid() ^ time(NULL));
srand(rand() ^ (unsigned)getpid() ^ (unsigned)time(NULL));
}
/**
* Initialize ngIRCd daemon.
*
* @param NGIRCd_NoDaemon Set to true if ngIRCd should run in the
* foreground and not as a daemon.
* @return true on success.
* @param NGIRCd_NoDaemon Set to true if ngIRCd should run in the
* foreground (and not as a daemon).
* @return true on success.
*/
static bool
NGIRCd_Init( bool NGIRCd_NoDaemon )
NGIRCd_Init(bool NGIRCd_NoDaemon)
{
static bool initialized;
bool chrooted = false;
@@ -621,57 +625,72 @@ NGIRCd_Init( bool NGIRCd_NoDaemon )
/* open /dev/null before chroot() */
fd = open( "/dev/null", O_RDWR);
if (fd < 0)
Log(LOG_WARNING, "Could not open /dev/null: %s", strerror(errno));
Log(LOG_WARNING, "Could not open /dev/null: %s",
strerror(errno));
}
/* SSL initialization */
if (!ConnSSL_InitLibrary())
Log(LOG_WARNING,
"Warning: Error during SSL initialization, continuing ...");
if( Conf_Chroot[0] ) {
if( chdir( Conf_Chroot ) != 0 ) {
Log( LOG_ERR, "Can't chdir() in ChrootDir (%s): %s", Conf_Chroot, strerror( errno ));
/* Change root */
if (Conf_Chroot[0]) {
if (chdir(Conf_Chroot) != 0) {
Log(LOG_ERR, "Can't chdir() in ChrootDir (%s): %s",
Conf_Chroot, strerror(errno));
goto out;
}
if( chroot( Conf_Chroot ) != 0 ) {
if (errno != EPERM) {
Log( LOG_ERR, "Can't change root directory to \"%s\": %s",
Conf_Chroot, strerror( errno ));
goto out;
}
if (chroot(Conf_Chroot) != 0) {
Log(LOG_ERR,
"Can't change root directory to \"%s\": %s",
Conf_Chroot, strerror(errno));
goto out;
} else {
chrooted = true;
Log( LOG_INFO, "Changed root and working directory to \"%s\".", Conf_Chroot );
Log(LOG_INFO,
"Changed root and working directory to \"%s\".",
Conf_Chroot);
}
}
/* Check user ID */
if (Conf_UID == 0) {
Log(LOG_INFO, "ServerUID must not be 0, using \"nobody\" instead.", Conf_UID);
if (! NGIRCd_getNobodyID(&Conf_UID, &Conf_GID)) {
Log(LOG_WARNING, "Could not get user/group ID of user \"nobody\": %s",
errno ? strerror(errno) : "not found" );
pwd = getpwuid(0);
Log(LOG_INFO,
"ServerUID must not be %s(0), using \"nobody\" instead.",
pwd ? pwd->pw_name : "?");
if (!NGIRCd_getNobodyID(&Conf_UID, &Conf_GID)) {
Log(LOG_WARNING,
"Could not get user/group ID of user \"nobody\": %s",
errno ? strerror(errno) : "not found" );
goto out;
}
}
/* Change group ID */
if (getgid() != Conf_GID) {
/* Change group ID */
if (setgid(Conf_GID) != 0) {
real_errno = errno;
Log( LOG_ERR, "Can't change group ID to %u: %s", Conf_GID, strerror( errno ));
grp = getgrgid(Conf_GID);
Log(LOG_ERR, "Can't change group ID to %s(%u): %s",
grp ? grp->gr_name : "?", Conf_GID,
strerror(errno));
if (real_errno != EPERM)
goto out;
}
}
/* Change user ID */
if (getuid() != Conf_UID) {
/* Change user ID */
if (setuid(Conf_UID) != 0) {
real_errno = errno;
Log(LOG_ERR, "Can't change user ID to %u: %s", Conf_UID, strerror(errno));
if (real_errno != EPERM)
pwd = getpwuid(Conf_UID);
Log(LOG_ERR, "Can't change user ID to %s(%u): %s",
pwd ? pwd->pw_name : "?", Conf_UID,
strerror(errno));
if (real_errno != EPERM)
goto out;
}
}
@@ -681,26 +700,27 @@ NGIRCd_Init( bool NGIRCd_NoDaemon )
/* Normally a child process is forked which isn't any longer
* connected to ther controlling terminal. Use "--nodaemon"
* to disable this "daemon mode" (useful for debugging). */
if ( ! NGIRCd_NoDaemon ) {
pid = fork( );
if( pid > 0 ) {
if (!NGIRCd_NoDaemon) {
pid = fork();
if (pid > 0) {
/* "Old" process: exit. */
exit( 0 );
exit(0);
}
if( pid < 0 ) {
if (pid < 0) {
/* Error!? */
fprintf( stderr, "%s: Can't fork: %s!\nFatal error, exiting now ...\n",
PACKAGE_NAME, strerror( errno ));
exit( 1 );
fprintf(stderr,
"%s: Can't fork: %s!\nFatal error, exiting now ...\n",
PACKAGE_NAME, strerror(errno));
exit(1);
}
/* New child process */
#ifndef NeXT
(void)setsid( );
(void)setsid();
#else
setpgrp(0, getpid());
#endif
if (chdir( "/" ) != 0)
if (chdir("/") != 0)
Log(LOG_ERR, "Can't change directory to '/': %s",
strerror(errno));
@@ -711,19 +731,19 @@ NGIRCd_Init( bool NGIRCd_NoDaemon )
}
pid = getpid();
Pidfile_Create( pid );
Pidfile_Create(pid);
/* Check UID/GID we are running as, can be different from values
* configured (e. g. if we were already started with a UID>0. */
Conf_UID = getuid();
Conf_GID = getgid();
pwd = getpwuid( Conf_UID );
grp = getgrgid( Conf_GID );
pwd = getpwuid(Conf_UID);
grp = getgrgid(Conf_GID);
Log(LOG_INFO, "Running as user %s(%ld), group %s(%ld), with PID %ld.",
pwd ? pwd->pw_name : "unknown", (long)Conf_UID,
grp ? grp->gr_name : "unknown", (long)Conf_GID, (long)pid);
pwd ? pwd->pw_name : "unknown", (long)Conf_UID,
grp ? grp->gr_name : "unknown", (long)Conf_GID, (long)pid);
if (chrooted) {
Log(LOG_INFO, "Running with root directory \"%s\".",
@@ -732,20 +752,23 @@ NGIRCd_Init( bool NGIRCd_NoDaemon )
} else
Log(LOG_INFO, "Not running with changed root directory.");
/* Change working directory to home directory of the user
* we are running as (only when running in daemon mode and not in chroot) */
/* Change working directory to home directory of the user we are
* running as (only when running in daemon mode and not in chroot) */
if (NGIRCd_NoDaemon)
return true;
if (pwd) {
if (!NGIRCd_NoDaemon ) {
if( chdir( pwd->pw_dir ) == 0 )
Log( LOG_DEBUG, "Changed working directory to \"%s\" ...", pwd->pw_dir );
else
Log( LOG_INFO, "Notice: Can't change working directory to \"%s\": %s",
pwd->pw_dir, strerror( errno ));
}
} else {
Log( LOG_ERR, "Can't get user informaton for UID %d!?", Conf_UID );
}
if (chdir(pwd->pw_dir) == 0)
Log(LOG_DEBUG,
"Changed working directory to \"%s\" ...",
pwd->pw_dir);
else
Log(LOG_INFO,
"Notice: Can't change working directory to \"%s\": %s",
pwd->pw_dir, strerror(errno));
} else
Log(LOG_ERR, "Can't get user informaton for UID %d!?", Conf_UID);
return true;
out:

View File

@@ -28,6 +28,7 @@
#include "conn.h"
#include "conn-func.h"
#include "channel.h"
#include "class.h"
#include "irc-write.h"
#include "lists.h"
#include "log.h"
@@ -194,8 +195,10 @@ Announce_User(CLIENT * Client, CLIENT * User)
#ifdef IRCPLUS
/**
* Synchronize invite and ban lists between servers
* @param Client New server
* Synchronize invite, ban, G- and K-Line lists between servers.
*
* @param Client New server.
* @return CONNECTED or DISCONNECTED.
*/
static bool
Synchronize_Lists(CLIENT * Client)
@@ -206,6 +209,18 @@ Synchronize_Lists(CLIENT * Client)
assert(Client != NULL);
/* g-lines */
head = Class_GetList(CLASS_GLINE);
elem = Lists_GetFirst(head);
while (elem) {
if (!IRC_WriteStrClient(Client, "GLINE %s %ld :%s",
Lists_GetMask(elem),
Lists_GetValidity(elem) - time(NULL),
Lists_GetReason(elem)))
return DISCONNECTED;
elem = Lists_GetNext(elem);
}
c = Channel_First();
while (c) {
/* ban list */
@@ -369,6 +384,10 @@ IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req)
}
#endif
if (!IRC_WriteStrClient(Client, "PING :%s",
Client_ID(Client_ThisServer())))
return DISCONNECTED;
return CONNECTED;
} /* IRC_Num_ENDOFMOTD */

View File

@@ -58,9 +58,15 @@ Op_NoPrivileges(CLIENT * Client, REQUEST * Req)
/**
* Check that the client is an IRC operator allowed to administer this server.
* Check that the originator of a request is an IRC operator and allowed
* to administer this server.
*
* @param CLient Client from which the command has been received.
* @param Req Request structure.
* @return CLIENT structure of the client that initiated the command or
* NULL if client is not allowed to execute operator commands.
*/
GLOBAL bool
GLOBAL CLIENT *
Op_Check(CLIENT * Client, REQUEST * Req)
{
CLIENT *c;
@@ -72,15 +78,20 @@ Op_Check(CLIENT * Client, REQUEST * Req)
c = Client_Search(Req->prefix);
else
c = Client;
if (!c)
return false;
return NULL;
if (Client_Type(Client) == CLIENT_SERVER
&& Client_Type(c) == CLIENT_SERVER)
return c;
if (!Client_HasMode(c, 'o'))
return false;
return NULL;
if (!Client_OperByMe(c) && !Conf_AllowRemoteOper)
return false;
return NULL;
/* The client is an local IRC operator, or this server is configured
* to trust remote operators. */
return true;
return c;
} /* Op_Check */

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2009 Alexander Barton (alex@barton.de)
* 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
@@ -18,7 +18,7 @@
*/
GLOBAL bool Op_NoPrivileges PARAMS((CLIENT * Client, REQUEST * Req));
GLOBAL bool Op_Check PARAMS((CLIENT * Client, REQUEST * Req));
GLOBAL CLIENT *Op_Check PARAMS((CLIENT * Client, REQUEST * Req));
#endif

View File

@@ -103,7 +103,7 @@ PAM_Authenticate(CLIENT *Client) {
if (password)
free(password);
password = strdup(Client_Password(Client));
conv.appdata_ptr = password;
conv.appdata_ptr = Client_Password(Client);
/* Initialize PAM */
retval = pam_start("ngircd", Client_OrigUser(Client), &conv, &pam);

View File

@@ -36,6 +36,7 @@
#include "imp.h"
#include "irc.h"
#include "irc-cap.h"
#include "irc-channel.h"
#include "irc-info.h"
#include "irc-login.h"
@@ -63,6 +64,7 @@ static COMMAND My_Commands[] =
{ "DIE", IRC_DIE, CLIENT_USER, 0, 0, 0 },
{ "DISCONNECT", IRC_DISCONNECT, CLIENT_USER, 0, 0, 0 },
{ "ERROR", IRC_ERROR, 0xFFFF, 0, 0, 0 },
{ "GLINE", IRC_xLINE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "HELP", IRC_HELP, CLIENT_USER, 0, 0, 0 },
{ "INFO", IRC_INFO, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "INVITE", IRC_INVITE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
@@ -70,6 +72,7 @@ static COMMAND My_Commands[] =
{ "JOIN", IRC_JOIN, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "KICK", IRC_KICK, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "KILL", IRC_KILL, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "KLINE", IRC_xLINE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
{ "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 },
@@ -111,6 +114,7 @@ static COMMAND My_Commands[] =
{ "CHANINFO", IRC_CHANINFO, CLIENT_SERVER, 0, 0, 0 },
#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
@@ -325,13 +329,21 @@ Validate_Prefix( CONN_ID Idx, REQUEST *Req, bool *Closed )
/* check if the client named in the prefix is expected
* to come from that direction */
if (Client_NextHop(c) != client) {
Log(LOG_ERR,
"Spoofed prefix \"%s\" from \"%s\" (connection %d, command \"%s\")!",
Req->prefix, Client_Mask(Conn_GetClient(Idx)), Idx,
Req->command);
Conn_Close(Idx, NULL, "Spoofed prefix", true);
*Closed = true;
if (Client_Type(c) != CLIENT_SERVER) {
Log(LOG_ERR,
"Spoofed prefix \"%s\" from \"%s\" (connection %d, command \"%s\")!",
Req->prefix, Client_Mask(Conn_GetClient(Idx)), Idx,
Req->command);
Conn_Close(Idx, NULL, "Spoofed prefix", true);
*Closed = true;
} else {
Log(LOG_INFO,
"Ignoring spoofed prefix \"%s\" from \"%s\" (connection %d, command \"%s\").",
Req->prefix, Client_Mask(Conn_GetClient(Idx)), Idx,
Req->command);
}
return false;
}
return true;

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2010 Alexander Barton (alex@barton.de)
* 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
@@ -79,7 +79,6 @@ Proc_Fork(PROC_STAT *proc, int *pipefds, void (*cbfunc)(int, short), int timeout
signal(SIGALRM, Proc_GenericSignalHandler);
close(pipefds[0]);
alarm(timeout);
Conn_CloseAllSockets();
return 0;
}
@@ -138,14 +137,28 @@ Proc_Read(PROC_STAT *proc, void *buffer, size_t buflen)
return 0;
Log(LOG_CRIT, "Can't read from child process %ld: %s",
proc->pid, strerror(errno));
Proc_Close(proc);
bytes_read = 0;
} else if (bytes_read == 0) {
/* EOF: clean up */
LogDebug("Child process %ld: EOF reached, closing pipe.",
proc->pid);
Proc_Close(proc);
}
#if DEBUG
else if (bytes_read == 0)
LogDebug("Can't read from child process %ld: EOF", proc->pid);
#endif
Proc_InitStruct(proc);
return (size_t)bytes_read;
}
/**
* Close pipe to a forked child process.
*/
GLOBAL void
Proc_Close(PROC_STAT *proc)
{
/* Close socket, if it exists */
if (proc->pipe_fd >= 0)
io_close(proc->pipe_fd);
Proc_InitStruct(proc);
}
/* -eof- */

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2010 Alexander Barton (alex@barton.de)
* 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
@@ -38,6 +38,9 @@ GLOBAL void Proc_GenericSignalHandler PARAMS((int Signal));
GLOBAL size_t Proc_Read PARAMS((PROC_STAT *proc, void *buffer, size_t buflen));
GLOBAL void Proc_Close PARAMS((PROC_STAT *proc));
#endif
/* -eof- */

View File

@@ -1,6 +1,6 @@
/*
* ngIRCd -- The Next Generation IRC Daemon
* Copyright (c)2001-2009 by Alexander Barton (alex@barton.de)
* 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
@@ -75,7 +75,8 @@ Resolve_Addr(PROC_STAT * s, const ng_ipaddr_t *Addr, int identsock,
} else if( pid == 0 ) {
/* Sub process */
Log_Init_Subprocess("Resolver");
Do_ResolveAddr( Addr, identsock, pipefd[1]);
Conn_CloseAllSockets(identsock);
Do_ResolveAddr(Addr, identsock, pipefd[1]);
Log_Exit_Subprocess("Resolver");
exit(0);
}
@@ -104,6 +105,7 @@ Resolve_Name( PROC_STAT *s, const char *Host, void (*cbfunc)(int, short))
} else if( pid == 0 ) {
/* Sub process */
Log_Init_Subprocess("Resolver");
Conn_CloseAllSockets(NONE);
Do_ResolveName(Host, pipefd[1]);
Log_Exit_Subprocess("Resolver");
exit(0);

View File

@@ -218,8 +218,11 @@ Signal_Handler_BH(int Signal)
break;
#ifdef DEBUG
case SIGUSR2:
if (NGIRCd_Debug)
if (NGIRCd_Debug) {
Log(LOG_INFO|LOG_snotice,
"Got SIGUSR2, dumping internal state ...");
Dump_State();
}
break;
default:
Log(LOG_DEBUG, "Got signal %d! Ignored.", Signal);

View File

@@ -164,6 +164,10 @@ extern char * strtok_r PARAMS((char *str, const char *delim, char **saveptr));
extern int vsnprintf PARAMS(( char *str, size_t count, const char *fmt, va_list args ));
#endif
#ifndef HAVE_GAI_STRERROR
#define gai_strerror(r) "unknown error"
#endif
#ifndef PACKAGE_NAME
#define PACKAGE_NAME PACKAGE
#endif

View File

@@ -13,10 +13,12 @@ elif [ $UNAME = "A/UX" ]; then
PS_FLAGS="-ae"; PS_PIDCOL="1"; HEAD_FLAGS="-1"
elif [ $UNAME = "GNU" ]; then
PS_FLAGS="-ax"; PS_PIDCOL="2"; HEAD_FLAGS="-n 1"
elif [ $UNAME = "Linux" ]; then
PS_FLAGS="ax"; PS_PIDCOL="1"; HEAD_FLAGS="-n 1"
elif [ $UNAME = "SunOS" ]; then
PS_FLAGS="-af"; PS_PIDCOL=2; HEAD_FLAGS="-n 1"
else
PS_FLAGS="-f"; PS_PIDCOL="2"; HEAD_FLAGS="-n 1"
PS_FLAGS="-af"; PS_PIDCOL="2"; HEAD_FLAGS="-n 1"
ps $PS_FLAGS > /dev/null 2>&1
if [ $? -ne 0 ]; then PS_FLAGS="a"; PS_PIDCOL="1"; fi
fi

View File

@@ -35,7 +35,7 @@ expect {
"@* PRIVMSG nick :test\r*@* PRIVMSG nick :test"
}
send "privmsg nick,#testChannel,nick :test\r"
send "privmsg Nick,#testChannel,nick :test\r"
expect {
timeout { exit 1 }
"@* PRIVMSG nick :test\r*401*@* PRIVMSG nick :test"
@@ -47,7 +47,7 @@ expect {
"401"
}
send "privmsg ~user@ngircd.test.server :test\r"
send "privmsg ~UsEr@ngIRCd.Test.Server :test\r"
expect {
timeout { exit 1 }
"@* PRIVMSG nick :test"
@@ -65,7 +65,7 @@ expect {
# "@* PRIVMSG nick :test"
#}
#
#send "privmsg nick!~user@localhost :test\r"
#send "privmsg Nick!~User@LocalHost :test\r"
#expect {
# timeout { exit 1 }
# "@* PRIVMSG nick :test"

Some files were not shown because too many files have changed in this diff Show More