mirror of
				https://github.com/osmarks/ngircd.git
				synced 2025-10-25 19:17:38 +00:00 
			
		
		
		
	Compare commits
	
		
			205 Commits
		
	
	
		
			branch-0-1
			...
			rel-0-12-0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | f44007f42f | ||
|   | 1a56c77751 | ||
|   | 78257374f0 | ||
|   | fc93044909 | ||
|   | 2e0c62df91 | ||
|   | c5ba599140 | ||
|   | afc67ff323 | ||
|   | 6cfc56064e | ||
|   | 4a81367dac | ||
|   | 8c425945a2 | ||
|   | bb6ee46892 | ||
|   | 6052d04c60 | ||
|   | 9194319399 | ||
|   | 32bf6d4de0 | ||
|   | 33b1204349 | ||
|   | 09968ee843 | ||
|   | 523a6fad09 | ||
|   | 54b17fc201 | ||
|   | 25f48a2a34 | ||
|   | 22fa782be7 | ||
|   | b187fac244 | ||
|   | 6e9389b86c | ||
|   | 2f6d7a649c | ||
|   | a8e0eb62e9 | ||
|   | 7df90846e1 | ||
|   | 4ea2932967 | ||
|   | 92a9092208 | ||
|   | a0efcdccfa | ||
|   | 012aeca32b | ||
|   | c4a505d3a8 | ||
|   | 8df445316a | ||
|   | 11af32466f | ||
|   | 5538115537 | ||
|   | b8643477ba | ||
|   | 796dcf6a62 | ||
|   | 6b0c094809 | ||
|   | b36fc3b095 | ||
|   | 2dd51a98e4 | ||
|   | 761ae2b1a4 | ||
|   | 87cae1465b | ||
|   | b7135ea76a | ||
|   | 248f8e0b70 | ||
|   | 7b33424c13 | ||
|   | 7c82cc236b | ||
|   | 307f8abd74 | ||
|   | bc63064d5c | ||
|   | be844d74d3 | ||
|   | 637d739285 | ||
|   | 66e68de16a | ||
|   | 7f44a2ad1c | ||
|   | abb1abeb77 | ||
|   | ab1f48a346 | ||
|   | feb31e4200 | ||
|   | c31ad221a6 | ||
|   | 44cdf1b1ca | ||
|   | e710e8ae37 | ||
|   | 89ba1bdcba | ||
|   | 0250acc50b | ||
|   | ec80cc99c6 | ||
|   | 5147b675cb | ||
|   | ddecfcd831 | ||
|   | 2f71fbb2a1 | ||
|   | 1784180bf3 | ||
|   | 634ef8c131 | ||
|   | 4d152b771e | ||
|   | c634303765 | ||
|   | cb0d594e61 | ||
|   | 000a227a74 | ||
|   | 6bd35bf090 | ||
|   | 3022d7cff3 | ||
|   | f86ce17f1c | ||
|   | 42db159d26 | ||
|   | 59b19ea6a3 | ||
|   | 4add9c29ed | ||
|   | d1364ab488 | ||
|   | 56256535c5 | ||
|   | 35b6f3997c | ||
|   | 463c5cb7c5 | ||
|   | 7548aa089c | ||
|   | 478a8c01f9 | ||
|   | 61e6b5c0aa | ||
|   | 91a6fffaa0 | ||
|   | 2ce5b734bd | ||
|   | f99f9a8f02 | ||
|   | 4715ccf9ca | ||
|   | 8974e90552 | ||
|   | 2fe13f0a45 | ||
|   | 20ce56cc5b | ||
|   | 47a0379e2b | ||
|   | 37563537a9 | ||
|   | 82d32ffb28 | ||
|   | 024588dbe7 | ||
|   | 47ca178a21 | ||
|   | 12db0bdc4f | ||
|   | 53b98fd7e9 | ||
|   | c7d4d85666 | ||
|   | 4659dae6eb | ||
|   | 68f896eee0 | ||
|   | 06bfb3adfb | ||
|   | 2f305331a1 | ||
|   | ad7361dfe0 | ||
|   | e47c9d750f | ||
|   | 001c00b273 | ||
|   | b861f536b2 | ||
|   | 877bcc55f2 | ||
|   | 8f162f4e17 | ||
|   | 089ca21b3d | ||
|   | 137a139112 | ||
|   | b160f574de | ||
|   | d223b587e4 | ||
|   | 77939c382d | ||
|   | f586052f2b | ||
|   | d4ed056147 | ||
|   | 9021ea2070 | ||
|   | 640367e886 | ||
|   | 4b9e52eb4d | ||
|   | 69081851ac | ||
|   | efcca62a35 | ||
|   | cd65e0a56e | ||
|   | 2275add327 | ||
|   | fd1091541b | ||
|   | 5675be4cd9 | ||
|   | f1486e6a53 | ||
|   | 22a9ed6694 | ||
|   | ddf56cbe5f | ||
|   | 255edf7eab | ||
|   | 5930a29197 | ||
|   | 07d8da60de | ||
|   | 44afe042d1 | ||
|   | a073bc89c4 | ||
|   | 63e89ceb21 | ||
|   | 09416f36bf | ||
|   | 508b55126f | ||
|   | 9f65979979 | ||
|   | 2e34ddae53 | ||
|   | 09deb857ce | ||
|   | 8c14d397ba | ||
|   | 99eab1e216 | ||
|   | c93d089736 | ||
|   | 429f85b77a | ||
|   | ea2a4b3370 | ||
|   | f9b9850662 | ||
|   | 1b852fce72 | ||
|   | 82aaffe55d | ||
|   | 40199e0b56 | ||
|   | 95b7dbcc18 | ||
|   | 43f8d149bb | ||
|   | 949a4ef793 | ||
|   | f74781647a | ||
|   | 5c78230283 | ||
|   | ee568cc444 | ||
|   | 2d9a3ec484 | ||
|   | 262d945284 | ||
|   | f6ce2d557a | ||
|   | 4243cae985 | ||
|   | 40226d26b2 | ||
|   | d2f7d3087d | ||
|   | 3f1e03edd9 | ||
|   | 23e7f7f0dd | ||
|   | f36746a4d0 | ||
|   | 8cb0e3af68 | ||
|   | eb3ddace46 | ||
|   | 5040d56489 | ||
|   | fb0fbe908d | ||
|   | fa7bb2790a | ||
|   | 5877bca4bc | ||
|   | 37602d1523 | ||
|   | a09034563a | ||
|   | 5b35b101f2 | ||
|   | 058d3085a9 | ||
|   | 74883f57da | ||
|   | 018e351630 | ||
|   | 6e105bf87e | ||
|   | 61966a6088 | ||
|   | 27c96632f1 | ||
|   | 4108e16be6 | ||
|   | 4e02bdc322 | ||
|   | ca5e09865e | ||
|   | fb0c7ad252 | ||
|   | d8950c5dd0 | ||
|   | 257312b102 | ||
|   | 27d947fb7d | ||
|   | bed98979dc | ||
|   | bddb4914b4 | ||
|   | 4c6c6ecf0e | ||
|   | a2f5a05ff8 | ||
|   | 639eb40035 | ||
|   | 0d6f9d4e3e | ||
|   | 147de9dfa9 | ||
|   | f6e729443e | ||
|   | e426c131c7 | ||
|   | b9661ae65d | ||
|   | 035f7fb2fe | ||
|   | 1b2c228de5 | ||
|   | 4d7d1d23be | ||
|   | e2aacff7d4 | ||
|   | 0eccdbc137 | ||
|   | 939ee6a39b | ||
|   | 8423b89996 | ||
|   | 7d87318b04 | ||
|   | 83caef4598 | ||
|   | 7378860aea | ||
|   | 6eb3f3055d | ||
|   | c888c81adf | ||
|   | fac4682212 | 
							
								
								
									
										17
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| Makefile | ||||
| Makefile.in | ||||
| aclocal.m4 | ||||
| ansi2knr.1 | ||||
| ansi2knr.c | ||||
| ansi2knr.h | ||||
| autom4te.cache | ||||
| config.log | ||||
| config.status | ||||
| configure | ||||
| configure.lineno | ||||
| depcomp | ||||
| install-sh | ||||
| missing | ||||
| .deps | ||||
| *.a | ||||
| *.o | ||||
							
								
								
									
										12
									
								
								AUTHORS
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								AUTHORS
									
									
									
									
									
								
							| @@ -1,7 +1,7 @@ | ||||
|  | ||||
|                      ngIRCd - Next Generation IRC Server | ||||
|  | ||||
|                         (c)2001-2005 Alexander Barton, | ||||
|                         (c)2001-2007 Alexander Barton, | ||||
|                     alex@barton.de, http://www.barton.de/ | ||||
|  | ||||
|                ngIRCd is free software and published under the | ||||
| @@ -10,9 +10,16 @@ | ||||
|                        -- AUTHORS and CONTRIBUTORS -- | ||||
|  | ||||
|  | ||||
| Note: If you have critics, patches or something else, please feel free to | ||||
| post a mail to the ngIRCd mailing list: <ngircd-ml@arthur.ath.cx> (please see | ||||
| <http://ngircd.barton.de/#ml> for details). Don't mail the contributors | ||||
| directly, if possible! | ||||
|  | ||||
|  | ||||
| Main Authors | ||||
| ~~~~~~~~~~~~ | ||||
| Alexander Barton, <alex@barton.de> (alex) | ||||
| Florian Westphal, <westphal@foo.fh-furtwangen.de> (fw) | ||||
|  | ||||
|  | ||||
| Contributors | ||||
| @@ -21,7 +28,6 @@ Goetz Hoffart, <goetz@hoffart.de> (goetz) | ||||
| Ilja Osthoff, <i.osthoff@gmx.net> (ilja) | ||||
| Benjamin Pineau, <ben@zouh.org> | ||||
| Sean Reifschneider, <jafo-rpms@tummy.com> | ||||
| Florian Westphal, <westphal@foo.fh-furtwangen.de> (fw) | ||||
|  | ||||
|  | ||||
| Code snippets | ||||
| @@ -32,4 +38,4 @@ Andrew Tridgell & Martin Pool: strl{cpy|cat}()-functions | ||||
|  | ||||
|  | ||||
| --  | ||||
| $Id: AUTHORS,v 1.11 2005/03/19 14:24:52 alex Exp $ | ||||
| $Id: AUTHORS,v 1.13 2007/10/04 15:18:48 alex Exp $ | ||||
|   | ||||
							
								
								
									
										129
									
								
								ChangeLog
									
									
									
									
									
								
							
							
						
						
									
										129
									
								
								ChangeLog
									
									
									
									
									
								
							| @@ -1,7 +1,7 @@ | ||||
|  | ||||
|                      ngIRCd - Next Generation IRC Server | ||||
|  | ||||
|                         (c)2001-2005 Alexander Barton, | ||||
|                         (c)2001-2008 Alexander Barton, | ||||
|                     alex@barton.de, http://www.barton.de/ | ||||
|  | ||||
|                ngIRCd is free software and published under the | ||||
| @@ -10,8 +10,129 @@ | ||||
|                                -- ChangeLog -- | ||||
|  | ||||
|  | ||||
| ngIRCd CVSHEAD | ||||
| ngIRCd 0.12.0 (2008-05-13) | ||||
|  | ||||
|   - Fix Bug: 85: "WHO #SecretChannel" that user is not a member of now returns | ||||
|     proper RPL_ENDOFWHO_MSG instead of nothing. (Ali Shemiran) | ||||
|   - Fix complie on FreeBSD 5.4 and AIX. | ||||
|   - If bind() fails, also print ip address and not just the port number. | ||||
|  | ||||
|   ngIRCd 0.12.0-pre2 (2008-04-29) | ||||
|   - IPv6: Add config options to disabe ipv4/ipv6 support. | ||||
|   - Don't include doc/CVS.txt in distribution archive, use doc/GIT.txt now! | ||||
|   - Documentation: get rid of some more references to CVS, switch to GIT. | ||||
|   - Get rid of cvs-version.* and CVSDATE definition. | ||||
|   - Report ERR_NOTONCHANNEL when trying to part a channel one is not member of. | ||||
|   - Testsuite: remove erroneous ConfUID setting in config file. | ||||
|  | ||||
|   ngIRCd 0.12.0-pre1 (2008-04-20) | ||||
|   - Include Mac OS X Xcode project in distribution archives. | ||||
|   - Do not exit on SIGHUP or /REHASH if the config file cannot opened. | ||||
|   - Add IPv6 support. | ||||
|   - Install a LaunchDaemon script to start/stop ngIRCd on Mac OS X. | ||||
|   - Implemented IRC commands INFO, SUMMON (dummy), and USERS (dummy) and | ||||
|     enhanced test suite to check these commands. (Dana Dahlstrom) | ||||
|   - RPL_WHOREPLY messages generated by IRC_WHO didn't include flags (*,@,+). | ||||
|     (Dana Dahlstrom) | ||||
|   - IRC_WHO now supports search patterns and will test this against user | ||||
|     nickname/servername/hostname, etc. as required by RFC 2812, Section 3.6.1. | ||||
|     (reported by Dana Dahlstrom) | ||||
|   - Add test cases for "WHO" command. (Dana Dahlstrom) | ||||
|   - Implement RFC 2812 handling of "0" argument to 'JOIN': must be treated | ||||
|     as if the user had sent PART commands for all channels the user is a | ||||
|     member of. (Dana Dahlstrom) | ||||
|   - Allow NOTICEs to be sent to a channel. (Fabian Schlager) | ||||
|  | ||||
| ngIRCd 0.11.1 (2008-02-26) | ||||
|  | ||||
|   - Fix sending of JOIN commands between servers when remote server appended | ||||
|     mode flags. (Rolf Eike Beer) [from HEAD] | ||||
|   - Send "G" instead of "H" flag in WHO replies. (reported by Dana Dahlstrom) | ||||
|   - Under some circumstances ngIRCd issued channel MODE message with a | ||||
|     trailing space. (Dana Dahlstrom) [from HEAD] | ||||
|  | ||||
| ngIRCd 0.11.0 (2008-01-15) | ||||
|  | ||||
|   ngIRCd 0.11.0-pre2 (2008-01-07) | ||||
|   - SECURITY: IRC_PART could reference invalid memory, causing | ||||
|     ngircd to crash [from HEAD]. | ||||
|    | ||||
|   ngIRCd 0.11.0-pre1 (2008-01-02) | ||||
|   - Use dotted-decimal IP address if hostname is >= 64. | ||||
|   - Add support for /STAT u (server uptime) command. | ||||
|   - New [Server] configuration Option "Bind" allows to specify | ||||
|     the source ip adress to use when connecting to remote server. | ||||
|   - New configuration option "MaxNickLength" to specify the allowed maximum | ||||
|     length of user nick names. Note: must be unique in an IRC network! | ||||
|   - Enhanced the IRC+ protocol to support an enhanced "server handshake" and | ||||
|     enable server to recognice numeric 005 (ISUPPORT) and 376 (ENDOFMOTD). | ||||
|     See doc/Protocol.txt for details. | ||||
|   - Re-added doc/SSL.txt to distribution -- got lost somewhere!? | ||||
|   - Fixes the wrong logging output when nested servers are introduced | ||||
|     to the network as well as the wrong output of the LINKS command. | ||||
|   - Update Mac OS X Xcode project file for Xcode 3. | ||||
|   - Adjust test suite to be usable on HP/UX 11.11 :-) | ||||
|   - Fix code to compile using K&R C compiler and ansi2kr again. | ||||
|   - New config option NoDNS: Disables DNS lookups when clients connect. | ||||
|   - Fixed propagation of channel mode 'P' on server links. | ||||
|   - Numeric 317: implemented "signon time" (displayed in WHOIS result). | ||||
|   - Fixed code that prevented GCC 2.95 to compile ngIRCd. | ||||
|   - Adjust path names in manual pages according to "./configure" settings. | ||||
|   - Added new server configuration option "Passive" for "Server" blocks to | ||||
|     disable automatic outgoing connections (similar to -p option to ngircd, | ||||
|     but only for the specified server). (Tassilo Schweyer) | ||||
|   - Don't connect to a server if a connection to another server within the | ||||
|     same group is already in progress. | ||||
|   - Added support for the WALLOPS command. Usage is restricted to IRC | ||||
|     operators. | ||||
|  | ||||
| ngIRCd 0.10.4 (2008-01-07) | ||||
|  | ||||
|   - SECURITY: IRC_PART could reference invalid memory, causing | ||||
|     ngircd to crash [from HEAD]. | ||||
|    | ||||
| ngIRCd 0.10.3 (2007-08-01) | ||||
|  | ||||
|   - SECURITY: Fixed a severe bug in handling JOIN commands, which could | ||||
|     cause the server to crash. Thanks to Sebastian Vesper, <net@veoson.net>. | ||||
|  | ||||
| ngIRCd 0.10.2 (2007-06-08) | ||||
|  | ||||
|   ngIRCd 0.10.2-pre2 (2007-05-19) | ||||
|   - Server links are allowed to use larger write buffers now (up to 50 KB). | ||||
|  | ||||
|   ngIRCd 0.10.2-pre1 (2007-05-05) | ||||
|   - Fix compressed server links (broken since 0.10.0). | ||||
|   - Predefined Channel configuration now allows specification of channel key | ||||
|     (mode k) and maximum user count (mode l). | ||||
|   - When using epoll() IO interface, compile in the select() interface as | ||||
|     well and fall back to it when epoll() isn't available on runtime. | ||||
|   - New configure option "--without-select" to disable select() IO API | ||||
|     (even when using epoll(), see above). | ||||
|   - Added support for IO APIs "poll()" and "/dev/poll". | ||||
|   - Reorganized internal handling of invite and ban lists. | ||||
|  | ||||
| ngIRCd 0.10.1 (2006-12-17) | ||||
|  | ||||
|   - Fixed validation of server names containing digits. | ||||
|   - Update the "info text" of the local server after re-reading configuration. | ||||
|   - Changed Numerics 265 and 266 to follow ircd 2.11.x "standards". | ||||
|   - Allow PASS syntax defined in RFC 1459 for server links, too. | ||||
|   - Enhanced ISUPPORT message (005 numeric). | ||||
|   - New configuration option "PredefChannelsOnly": if set, clients can only | ||||
|     join predefined channels. | ||||
|   - Code cleanups: use "LogDebug(...)" instead of "Log(LOG_DEBUG, ...)", use | ||||
|     "strcspn()", unsigned vs. signed, use "const", fix whitespaces, ... | ||||
|  | ||||
| ngIRCd 0.10.0 (2006-10-01) | ||||
|  | ||||
|   - Fixed file handle leak when daemon is not able to send MOTD to a client. | ||||
|  | ||||
|   ngIRCd 0.10.0-pre2 (2006-09-09) | ||||
|   - Fixed build problems with GCC option -fstack-protector. | ||||
|   - Minor documentation updates. | ||||
|  | ||||
|   ngIRCd 0.10.0-pre1 (2006-08-02) | ||||
|   - Validate "ServerName" (see RFC 2812, section 2.3.1). | ||||
|   - Enhanced DIE to accept a single parameter ("comment text") which is sent | ||||
|     to all locally connected clients before the server goes down. | ||||
| @@ -651,7 +772,3 @@ ngIRCd 0.0.2, 06.01.2002 | ||||
| ngIRCd 0.0.1, 31.12.2001 | ||||
|  | ||||
|   - erste oeffentliche Version von ngIRCd als "public preview" :-) | ||||
|  | ||||
|  | ||||
| --  | ||||
| $Id: ChangeLog,v 1.302 2006/07/23 16:42:45 alex Exp $ | ||||
|   | ||||
							
								
								
									
										24
									
								
								INSTALL
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								INSTALL
									
									
									
									
									
								
							| @@ -1,7 +1,7 @@ | ||||
|  | ||||
|                      ngIRCd - Next Generation IRC Server | ||||
|  | ||||
|                       (c)2001-2004 by Alexander Barton, | ||||
|                         (c)2001-2007 Alexander Barton, | ||||
|                     alex@barton.de, http://www.barton.de/ | ||||
|  | ||||
|                ngIRCd is free software and published under the | ||||
| @@ -51,9 +51,9 @@ on modern UNIX-like systems that are supported by GNU autoconf and GNU | ||||
| automake ("configure") should be no problem. | ||||
|  | ||||
| The normal installation procedure after getting (and expanding) the source | ||||
| files (using a distribution archive or CVS) is as following: | ||||
| files (using a distribution archive or GIT) is as following: | ||||
|  | ||||
|   1) ./autogen.sh	[only necessary when using CVS] | ||||
|   1) ./autogen.sh	[only necessary when using GIT] | ||||
|   2) ./configure | ||||
|   3) make | ||||
|   4) make install | ||||
| @@ -77,7 +77,7 @@ doc/ directory: sample-ngircd.conf. | ||||
|  | ||||
| The first step, autogen.sh, is only necessary if the configure-script isn't | ||||
| already generated. This never happens in official ("stable") releases in | ||||
| tar.gz-archives, but when using CVS. | ||||
| tar.gz-archives, but when using GIT. | ||||
|  | ||||
| This step is therefore only interesting for developers. | ||||
|  | ||||
| @@ -149,14 +149,20 @@ standard locations. | ||||
|   The Z compression library ("libz") is required for this option. | ||||
|    | ||||
| * IO Backend (autodetected by default): | ||||
|   --with-select[=<path>] / --without-select | ||||
|   --with-poll[=<path>] / --without-poll | ||||
|   --with-devpoll[=<path>] / --without-devpoll | ||||
|   --with-epoll[=<path>] / --without-epoll | ||||
|   --with-kqueue[=<path>] / --without-kqueue   | ||||
|  | ||||
|   ngIRCd can use three different IO "backends": the "old school" select() | ||||
|   ngIRCd can use different IO "backends": the "old school" select() and poll() | ||||
|   API which should be supported by most UNIX-like operating systems, or the | ||||
|   more efficient and flexible epoll() (Linux 2.6) or kqueue() (BSD) APIs. | ||||
|   more efficient and flexible epoll() (Linux >=2.6), kqueue() (BSD) and | ||||
|   /dev/poll APIs. | ||||
|   By default the IO backend is autodetected, but you can use "--without-xxx" | ||||
|   to disable a more enhanced API and force the daemon to use select(). | ||||
|   to disable a more enhanced API. | ||||
|   When using the epoll() API, support for select() is compiled in as well by | ||||
|   default to enable the binary to run on older Linux kernels (<2.6), too. | ||||
|  | ||||
| * IDENT-Support: | ||||
|   --with-ident[=<path>] | ||||
| @@ -238,7 +244,3 @@ These parameters could be passed to the ngIRCd: | ||||
| Use "--help" to see a short help text describing all available parameters | ||||
| the server understands, with "--version" the ngIRCd shows its version | ||||
| number. In both cases the server exits after the output. | ||||
|  | ||||
|  | ||||
| --  | ||||
| $Id: INSTALL,v 1.23 2005/12/30 22:43:23 alex Exp $ | ||||
|   | ||||
							
								
								
									
										12
									
								
								Makefile.am
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Makefile.am
									
									
									
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| # | ||||
| # ngIRCd -- The Next Generation IRC Daemon | ||||
| # Copyright (c)2001-2003 by Alexander Barton (alex@barton.de) | ||||
| # Copyright (c)2001-2008 Alexander Barton (alex@barton.de) | ||||
| # | ||||
| # This program is free software; you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| @@ -8,8 +8,6 @@ | ||||
| # (at your option) any later version. | ||||
| # Please read the file COPYING, README and AUTHORS for more information. | ||||
| # | ||||
| # $Id: Makefile.am,v 1.17 2005/07/22 21:01:52 alex Exp $ | ||||
| # | ||||
|  | ||||
| AUTOMAKE_OPTIONS = gnu | ||||
|  | ||||
| @@ -24,6 +22,9 @@ maintainer-clean-local: | ||||
| 	rm -f mkinstalldirs missing depcomp install-sh | ||||
| 	rm -f config.log debian | ||||
|  | ||||
| testsuite: | ||||
| 	make -C src/testsuite check | ||||
|  | ||||
| lint: | ||||
| 	make -C src/ngircd lint | ||||
|  | ||||
| @@ -31,9 +32,10 @@ srcdoc: | ||||
| 	make -C doc srcdoc | ||||
|  | ||||
| xcode: | ||||
| 	@xcodebuild -project contrib/MacOSX/ngIRCd.xcode -list >/dev/null 2>&1 \ | ||||
| 	@xcodebuild -project contrib/MacOSX/ngIRCd.xcodeproj -list \ | ||||
| 	 >/dev/null 2>&1 \ | ||||
| 	 || ( echo; echo "Error: \"xcodebuild\" not found!"; echo; exit 1 ) | ||||
| 	xcodebuild -project contrib/MacOSX/ngIRCd.xcode -alltargets \ | ||||
| 	xcodebuild -project contrib/MacOSX/ngIRCd.xcodeproj -alltargets \ | ||||
| 	 -buildstyle Development | ||||
|  | ||||
| rpm: distcheck | ||||
|   | ||||
							
								
								
									
										65
									
								
								NEWS
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								NEWS
									
									
									
									
									
								
							| @@ -1,7 +1,7 @@ | ||||
|  | ||||
|                      ngIRCd - Next Generation IRC Server | ||||
|  | ||||
|                         (c)2001-2005 Alexander Barton, | ||||
|                         (c)2001-2008 Alexander Barton, | ||||
|                     alex@barton.de, http://www.barton.de/ | ||||
|  | ||||
|                ngIRCd is free software and published under the | ||||
| @@ -10,6 +10,67 @@ | ||||
|                                   -- NEWS -- | ||||
|  | ||||
|  | ||||
| ngIRCd 0.12.0 (2008-05-13) | ||||
|  | ||||
|   ngIRCd 0.12.0-pre2 (2008-04-29) | ||||
|   - IPv6: Add config options to disabe ipv4/ipv6 support. | ||||
|  | ||||
|   ngIRCd 0.12.0-pre1 (2008-04-20) | ||||
|   - Add IPv6 support. | ||||
|   - Install a LaunchDaemon script to start/stop ngIRCd on Mac OS X. | ||||
|   - Implemented IRC commands INFO, SUMMON (dummy), and USERS (dummy) and | ||||
|     enhanced test suite to check these commands. (Dana Dahlstrom) | ||||
|   - IRC_WHO now supports search patterns and will test this against user | ||||
|     nickname/servername/hostname, etc. as required by RFC 2812, Section 3.6.1. | ||||
|     (reported by Dana Dahlstrom) | ||||
|   - Implement RFC 2812 handling of "0" argument to 'JOIN': must be treated | ||||
|     as if the user had sent PART commands for all channels the user is a | ||||
|     member of. (Dana Dahlstrom) | ||||
|   - Allow NOTICEs to be sent to a channel. (Fabian Schlager) | ||||
|  | ||||
| ngIRCd 0.11.0 (2008-01-15) | ||||
|  | ||||
|   - Add support for /STAT u (server uptime) command. | ||||
|   - New [Server] configuration Option "Bind" allows to specify | ||||
|     the source ip adress to use when connecting to remote server. | ||||
|   - New configuration option "MaxNickLength" to specify the allowed maximum | ||||
|     length of user nick names. Note: must be unique in an IRC network! | ||||
|   - Numeric 317: implemented "signon time" (displayed in WHOIS result). | ||||
|   - Added new server configuration option "Passive" for "Server" blocks to | ||||
|     disable automatic outgoing connections (similar to -p option to ngircd, | ||||
|     but only for the specified server). (Tassilo Schweyer) | ||||
|   - Added support for the WALLOPS command. Usage is restricted to IRC | ||||
|     operators. | ||||
|  | ||||
| ngIRCd 0.10.2 (2007-06-08) | ||||
|  | ||||
|   - Predefined channel configuration now allows specification of channel key | ||||
|     (mode k) and maximum user count (mode l): variables "Key" and "MaxUsers". | ||||
|   - When using the epoll() IO interface, compile in the select() interface as | ||||
|     well and fall back to it when epoll() isn't available on runtime. | ||||
|   - Added support for IO APIs "poll()" and "/dev/poll". | ||||
|  | ||||
| ngIRCd 0.10.1 (2006-12-17) | ||||
|  | ||||
|   - Allow PASS syntax defined in RFC 1459 for server links, too. | ||||
|   - New configuration option "PredefChannelsOnly": if set, clients can only | ||||
|     join predefined channels. | ||||
|  | ||||
| ngIRCd 0.10.0 (2006-10-01) | ||||
|  | ||||
|   ngIRCd 0.10.0-pre1 (2006-08-02) | ||||
|   - Enhanced DIE to accept a single parameter ("comment text") which is sent | ||||
|     to all locally connected clients before the server goes down. | ||||
|   - JOIN now supports more than one channel key at a time. | ||||
|   - Implemented numeric "333": Time and user name who set a channel topic. | ||||
|   - Channel topics are no longer limited to 127 characters: now the only limit | ||||
|     is the maximum length of an IRC command, i. e. 512 bytes (in practice, this | ||||
|     limits the topic to about 490 characters due to protocol overhead). | ||||
|   - Reverse DNS lookup code now checks the result by doing an additional | ||||
|     lookup to prevent spoofing. | ||||
|   - Added new IO layer which (optionally) supports epoll() and kqueue() in | ||||
|     addition to the select() interface. | ||||
|  | ||||
| ngIRCd 0.9.0 (2005-07-24) | ||||
|  | ||||
|   - Never run with root privileges but always switch the user ID. | ||||
| @@ -208,4 +269,4 @@ ngIRCd 0.0.1, 31.12.2001 | ||||
|  | ||||
|  | ||||
| --  | ||||
| $Id: NEWS,v 1.75 2005/07/26 19:41:49 alex Exp $ | ||||
| $Id: NEWS,v 1.88 2008/02/26 22:05:42 fw Exp $ | ||||
|   | ||||
							
								
								
									
										20
									
								
								README
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								README
									
									
									
									
									
								
							| @@ -1,7 +1,7 @@ | ||||
|  | ||||
|                      ngIRCd - Next Generation IRC Server | ||||
|  | ||||
|                         (c)2001-2005 Alexander Barton, | ||||
|                         (c)2001-2007 Alexander Barton, | ||||
|                     alex@barton.de, http://www.barton.de/ | ||||
|  | ||||
|                ngIRCd is free software and published under the | ||||
| @@ -19,6 +19,8 @@ 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. | ||||
|  | ||||
| Please see the INSTALL document for installation and upgrade information! | ||||
|  | ||||
|  | ||||
| II. Status | ||||
| ~~~~~~~~~~~ | ||||
| @@ -35,7 +37,8 @@ Implemented IRC-commands are: | ||||
| ADMIN, AWAY, CHANINFO, CONNECT, DIE, DISCONNECT, ERROR, HELP, INVITE, ISON, | ||||
| JOIN, KICK, KILL, LINKS, LIST, LUSERS, MODE, MOTD, NAMES, NICK, NJOIN, NOTICE, | ||||
| OPER, PART, PASS, PING, PONG, PRIVMSG, QUIT, REHASH, RESTART, SERVER, SQUIT, | ||||
| STATS, TIME, TOPIC, TRACE, USER, USERHOST, VERSION, WHO, WHOIS, WHOWAS. | ||||
| STATS, TIME, TOPIC, TRACE, USER, USERHOST, VERSION, WALLOPS, WHO, WHOIS, | ||||
| WHOWAS. | ||||
|  | ||||
|  | ||||
| III. Features (or: why use ngIRCd?) | ||||
| @@ -64,9 +67,9 @@ the newest information about the ngIRCd and the most recent ("stable") | ||||
| releases there. | ||||
|  | ||||
| If you are interested in the latest development versions (which are not | ||||
| always stable), then please read the section "CVS" on the homepage and | ||||
| the file "doc/CVS.txt" which describes the use of CVS, the "Concurrent | ||||
| Versioning System". | ||||
| 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/). | ||||
|  | ||||
|  | ||||
| VI. Bugs | ||||
| @@ -80,8 +83,5 @@ 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 <alex@barton.de>. | ||||
|  | ||||
|  | ||||
| --  | ||||
| $Id: README,v 1.21 2005/07/09 14:39:42 alex Exp $ | ||||
| mail to the ngIRCd mailing list: <ngircd-ml@arthur.ath.cx> (please see | ||||
| <http://ngircd.barton.de/#ml> for details). | ||||
|   | ||||
							
								
								
									
										23
									
								
								autogen.sh
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								autogen.sh
									
									
									
									
									
								
							| @@ -9,7 +9,7 @@ | ||||
| # (at your option) any later version. | ||||
| # Please read the file COPYING, README and AUTHORS for more information. | ||||
| # | ||||
| # $Id: autogen.sh,v 1.14 2005/02/21 15:23:23 alex Exp $ | ||||
| # $Id: autogen.sh,v 1.15 2007/10/07 13:02:15 alex Exp $ | ||||
| # | ||||
|  | ||||
| # | ||||
| @@ -124,17 +124,22 @@ if [ -z "$EXIST" ]; then | ||||
| fi | ||||
| [ "$VERBOSE" = "1" ] && echo "Using \"$EXIST\" to test for tools." | ||||
|  | ||||
| # We want to use GNU automake 1.7, if available (WANT_AUTOMAKE is used by | ||||
| # We want to use GNU automake 1.9, if available (WANT_AUTOMAKE is used by | ||||
| # the wrapper scripts of Gentoo Linux, AUTOMAKE_VERSION is used by OpenBSD); | ||||
| # same applies for GNU autoconf, we want to use version 2.59. | ||||
| AUTOMAKE_VERSION=1.7 | ||||
| AUTOCONF_VERSION=2.59 | ||||
| export AUTOMAKE_VERSION AUTOCONF_VERSION | ||||
| WANT_AUTOMAKE=1.7 | ||||
| export WANT_AUTOMAKE | ||||
| # same applies for GNU autoconf, we want to use version 2.59. -- But only | ||||
| # set these preferences if not already set! | ||||
| if [ -z "$AUTOMAKE_VERSION" -a -z "$WANT_AUTOMAKE" ]; then | ||||
| 	AUTOMAKE_VERSION=1.9 | ||||
| 	WANT_AUTOMAKE=1.9 | ||||
| fi | ||||
| if [ -z "$AUTOCONF_VERSION" -a -z "$WANT_AUTOCONF" ]; then | ||||
| 	AUTOCONF_VERSION=2.59 | ||||
| 	WANT_AUTOCONF=2.59 | ||||
| fi | ||||
| export AUTOMAKE_VERSION WANT_AUTOMAKE AUTOCONF_VERSION WANT_AUTOCONF | ||||
|  | ||||
| # Try to detect the needed tools when no environment variable already | ||||
| # spezifies one: | ||||
| # specifies one: | ||||
| echo "Searching tools ..." | ||||
| [ -z "$ACLOCAL" ] && ACLOCAL=`Search aclocal 1` | ||||
| [ "$VERBOSE" = "1" ] && echo "ACLOCAL=$ACLOCAL" | ||||
|   | ||||
							
								
								
									
										47
									
								
								config.guess
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										47
									
								
								config.guess
									
									
									
									
										vendored
									
									
								
							| @@ -1,9 +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 Free Software Foundation, Inc. | ||||
| #   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, | ||||
| #   Inc. | ||||
|  | ||||
| timestamp='2006-02-23' | ||||
| timestamp='2007-03-06' | ||||
|  | ||||
| # 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 | ||||
| @@ -160,6 +161,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in | ||||
| 	    arm*) machine=arm-unknown ;; | ||||
| 	    sh3el) machine=shl-unknown ;; | ||||
| 	    sh3eb) machine=sh-unknown ;; | ||||
| 	    sh5el) machine=sh5le-unknown ;; | ||||
| 	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;; | ||||
| 	esac | ||||
| 	# The Operating System including object format, if it has switched | ||||
| @@ -210,7 +212,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in | ||||
| 	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} | ||||
| 	exit ;; | ||||
|     macppc:MirBSD:*:*) | ||||
| 	echo powerppc-unknown-mirbsd${UNAME_RELEASE} | ||||
| 	echo powerpc-unknown-mirbsd${UNAME_RELEASE} | ||||
| 	exit ;; | ||||
|     *:MirBSD:*:*) | ||||
| 	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} | ||||
| @@ -770,6 +772,8 @@ EOF | ||||
| 	case ${UNAME_MACHINE} in | ||||
| 	    pc98) | ||||
| 		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; | ||||
| 	    amd64) | ||||
| 		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; | ||||
| 	    *) | ||||
| 		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; | ||||
| 	esac | ||||
| @@ -777,10 +781,7 @@ EOF | ||||
|     i*:CYGWIN*:*) | ||||
| 	echo ${UNAME_MACHINE}-pc-cygwin | ||||
| 	exit ;; | ||||
|     i*:MINGW*:*) | ||||
| 	echo ${UNAME_MACHINE}-pc-mingw32 | ||||
| 	exit ;; | ||||
|     i*:MSYS_NT-*:*:*) | ||||
|     *:MINGW*:*) | ||||
| 	echo ${UNAME_MACHINE}-pc-mingw32 | ||||
| 	exit ;; | ||||
|     i*:windows32*:*) | ||||
| @@ -790,12 +791,15 @@ EOF | ||||
|     i*:PW*:*) | ||||
| 	echo ${UNAME_MACHINE}-pc-pw32 | ||||
| 	exit ;; | ||||
|     x86:Interix*:[345]*) | ||||
| 	echo i586-pc-interix${UNAME_RELEASE} | ||||
| 	exit ;; | ||||
|     EM64T:Interix*:[345]*) | ||||
| 	echo x86_64-unknown-interix${UNAME_RELEASE} | ||||
| 	exit ;; | ||||
|     *:Interix*:[3456]*) | ||||
|     	case ${UNAME_MACHINE} in | ||||
| 	    x86)  | ||||
| 		echo i586-pc-interix${UNAME_RELEASE} | ||||
| 		exit ;; | ||||
| 	    EM64T | authenticamd) | ||||
| 		echo x86_64-unknown-interix${UNAME_RELEASE} | ||||
| 		exit ;; | ||||
| 	esac ;; | ||||
|     [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) | ||||
| 	echo i${UNAME_MACHINE}-pc-mks | ||||
| 	exit ;; | ||||
| @@ -831,6 +835,9 @@ EOF | ||||
|     arm*:Linux:*:*) | ||||
| 	echo ${UNAME_MACHINE}-unknown-linux-gnu | ||||
| 	exit ;; | ||||
|     avr32*:Linux:*:*) | ||||
| 	echo ${UNAME_MACHINE}-unknown-linux-gnu | ||||
| 	exit ;; | ||||
|     cris:Linux:*:*) | ||||
| 	echo cris-axis-linux-gnu | ||||
| 	exit ;; | ||||
| @@ -947,6 +954,9 @@ EOF | ||||
|     x86_64:Linux:*:*) | ||||
| 	echo x86_64-unknown-linux-gnu | ||||
| 	exit ;; | ||||
|     xtensa:Linux:*:*) | ||||
|     	echo xtensa-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 | ||||
| @@ -989,7 +999,7 @@ EOF | ||||
| 	LIBC=gnulibc1 | ||||
| 	# endif | ||||
| 	#else | ||||
| 	#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__sun) | ||||
| 	#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) | ||||
| 	LIBC=gnu | ||||
| 	#else | ||||
| 	LIBC=gnuaout | ||||
| @@ -1205,6 +1215,15 @@ EOF | ||||
|     SX-6:SUPER-UX:*:*) | ||||
| 	echo sx6-nec-superux${UNAME_RELEASE} | ||||
| 	exit ;; | ||||
|     SX-7:SUPER-UX:*:*) | ||||
| 	echo sx7-nec-superux${UNAME_RELEASE} | ||||
| 	exit ;; | ||||
|     SX-8:SUPER-UX:*:*) | ||||
| 	echo sx8-nec-superux${UNAME_RELEASE} | ||||
| 	exit ;; | ||||
|     SX-8R:SUPER-UX:*:*) | ||||
| 	echo sx8r-nec-superux${UNAME_RELEASE} | ||||
| 	exit ;; | ||||
|     Power*:Rhapsody:*:*) | ||||
| 	echo powerpc-apple-rhapsody${UNAME_RELEASE} | ||||
| 	exit ;; | ||||
|   | ||||
							
								
								
									
										68
									
								
								config.sub
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										68
									
								
								config.sub
									
									
									
									
										vendored
									
									
								
							| @@ -1,9 +1,10 @@ | ||||
| #! /bin/sh | ||||
| # Configuration validation subroutine script. | ||||
| #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, | ||||
| #   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. | ||||
| #   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, | ||||
| #   Inc. | ||||
|  | ||||
| timestamp='2006-02-23' | ||||
| timestamp='2007-01-18' | ||||
|  | ||||
| # This file is (in principle) common to ALL GNU software. | ||||
| # The presence of a machine in this file suggests that SOME GNU software | ||||
| @@ -240,15 +241,16 @@ case $basic_machine in | ||||
| 	| 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 \ | ||||
| 	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ | ||||
| 	| bfin \ | ||||
| 	| c4x | clipper \ | ||||
| 	| d10v | d30v | dlx | dsp16xx \ | ||||
| 	| fr30 | frv \ | ||||
| 	| fido | fr30 | frv \ | ||||
| 	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ | ||||
| 	| i370 | i860 | i960 | ia64 \ | ||||
| 	| ip2k | iq2000 \ | ||||
| 	| m32r | m32rle | m68000 | m68k | m88k | maxq | mb | microblaze | mcore \ | ||||
| 	| m32c | m32r | m32rle | m68000 | m68k | m88k \ | ||||
| 	| maxq | mb | microblaze | mcore | mep \ | ||||
| 	| mips | mipsbe | mipseb | mipsel | mipsle \ | ||||
| 	| mips16 \ | ||||
| 	| mips64 | mips64el \ | ||||
| @@ -274,21 +276,19 @@ case $basic_machine in | ||||
| 	| pdp10 | pdp11 | pj | pjl \ | ||||
| 	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ | ||||
| 	| pyramid \ | ||||
| 	| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ | ||||
| 	| score \ | ||||
| 	| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ | ||||
| 	| sh64 | sh64le \ | ||||
| 	| sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \ | ||||
| 	| sparcv8 | sparcv9 | sparcv9b \ | ||||
| 	| strongarm \ | ||||
| 	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ | ||||
| 	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \ | ||||
| 	| spu | strongarm \ | ||||
| 	| tahoe | thumb | tic4x | tic80 | tron \ | ||||
| 	| v850 | v850e \ | ||||
| 	| we32k \ | ||||
| 	| x86 | xscale | xscalee[bl] | xstormy16 | xtensa \ | ||||
| 	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \ | ||||
| 	| z8k) | ||||
| 		basic_machine=$basic_machine-unknown | ||||
| 		;; | ||||
| 	m32c) | ||||
| 		basic_machine=$basic_machine-unknown | ||||
| 		;; | ||||
| 	m6811 | m68hc11 | m6812 | m68hc12) | ||||
| 		# Motorola 68HC11/12. | ||||
| 		basic_machine=$basic_machine-unknown | ||||
| @@ -318,18 +318,18 @@ case $basic_machine in | ||||
| 	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ | ||||
| 	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ | ||||
| 	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \ | ||||
| 	| avr-* \ | ||||
| 	| avr-* | avr32-* \ | ||||
| 	| bfin-* | bs2000-* \ | ||||
| 	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \ | ||||
| 	| clipper-* | craynv-* | cydra-* \ | ||||
| 	| d10v-* | d30v-* | dlx-* \ | ||||
| 	| elxsi-* \ | ||||
| 	| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ | ||||
| 	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ | ||||
| 	| h8300-* | h8500-* \ | ||||
| 	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ | ||||
| 	| i*86-* | i860-* | i960-* | ia64-* \ | ||||
| 	| ip2k-* | iq2000-* \ | ||||
| 	| m32r-* | m32rle-* \ | ||||
| 	| m32c-* | m32r-* | m32rle-* \ | ||||
| 	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ | ||||
| 	| m88110-* | m88k-* | maxq-* | mcore-* \ | ||||
| 	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ | ||||
| @@ -358,23 +358,21 @@ case $basic_machine in | ||||
| 	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ | ||||
| 	| pyramid-* \ | ||||
| 	| romp-* | rs6000-* \ | ||||
| 	| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \ | ||||
| 	| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ | ||||
| 	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ | ||||
| 	| sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \ | ||||
| 	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ | ||||
| 	| sparclite-* \ | ||||
| 	| sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ | ||||
| 	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \ | ||||
| 	| tahoe-* | thumb-* \ | ||||
| 	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ | ||||
| 	| tron-* \ | ||||
| 	| v850-* | v850e-* | vax-* \ | ||||
| 	| we32k-* \ | ||||
| 	| x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \ | ||||
| 	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \ | ||||
| 	| xstormy16-* | xtensa-* \ | ||||
| 	| ymp-* \ | ||||
| 	| z8k-*) | ||||
| 		;; | ||||
| 	m32c-*) | ||||
| 		;; | ||||
| 	# Recognize the various machine names and aliases which stand | ||||
| 	# for a CPU type and a company and sometimes even an OS. | ||||
| 	386bsd) | ||||
| @@ -912,6 +910,10 @@ case $basic_machine in | ||||
| 	sb1el) | ||||
| 		basic_machine=mipsisa64sb1el-unknown | ||||
| 		;; | ||||
| 	sde) | ||||
| 		basic_machine=mipsisa32-sde | ||||
| 		os=-elf | ||||
| 		;; | ||||
| 	sei) | ||||
| 		basic_machine=mips-sei | ||||
| 		os=-seiux | ||||
| @@ -923,6 +925,9 @@ case $basic_machine in | ||||
| 		basic_machine=sh-hitachi | ||||
| 		os=-hms | ||||
| 		;; | ||||
| 	sh5el) | ||||
| 		basic_machine=sh5le-unknown | ||||
| 		;; | ||||
| 	sh64) | ||||
| 		basic_machine=sh64-unknown | ||||
| 		;; | ||||
| @@ -1128,7 +1133,7 @@ case $basic_machine in | ||||
| 	sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele) | ||||
| 		basic_machine=sh-unknown | ||||
| 		;; | ||||
| 	sparc | sparcv8 | sparcv9 | sparcv9b) | ||||
| 	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) | ||||
| 		basic_machine=sparc-sun | ||||
| 		;; | ||||
| 	cydra) | ||||
| @@ -1217,7 +1222,7 @@ case $os in | ||||
| 	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ | ||||
| 	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ | ||||
| 	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ | ||||
| 	      | -skyos* | -haiku* | -rdos*) | ||||
| 	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops*) | ||||
| 	# Remember, each alternative MUST END IN *, to match a version number. | ||||
| 		;; | ||||
| 	-qnx*) | ||||
| @@ -1369,6 +1374,12 @@ else | ||||
| # system, and we'll never get to this point. | ||||
|  | ||||
| case $basic_machine in | ||||
|         score-*) | ||||
| 		os=-elf | ||||
| 		;; | ||||
|         spu-*) | ||||
| 		os=-elf | ||||
| 		;; | ||||
| 	*-acorn) | ||||
| 		os=-riscix1.2 | ||||
| 		;; | ||||
| @@ -1378,9 +1389,9 @@ case $basic_machine in | ||||
| 	arm*-semi) | ||||
| 		os=-aout | ||||
| 		;; | ||||
|     c4x-* | tic4x-*) | ||||
|         os=-coff | ||||
|         ;; | ||||
|         c4x-* | tic4x-*) | ||||
|         	os=-coff | ||||
| 		;; | ||||
| 	# This must come before the *-dec entry. | ||||
| 	pdp10-*) | ||||
| 		os=-tops20 | ||||
| @@ -1406,6 +1417,9 @@ case $basic_machine in | ||||
| 	m68*-cisco) | ||||
| 		os=-aout | ||||
| 		;; | ||||
|         mep-*) | ||||
| 		os=-elf | ||||
| 		;; | ||||
| 	mips*-cisco) | ||||
| 		os=-elf | ||||
| 		;; | ||||
|   | ||||
							
								
								
									
										182
									
								
								configure.in
									
									
									
									
									
								
							
							
						
						
									
										182
									
								
								configure.in
									
									
									
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| # | ||||
| # ngIRCd -- The Next Generation IRC Daemon | ||||
| # Copyright (c)2001-2005 Alexander Barton <alex@barton.de> | ||||
| # Copyright (c)2001-2008 Alexander Barton <alex@barton.de> | ||||
| # | ||||
| # This program is free software; you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| @@ -8,13 +8,11 @@ | ||||
| # (at your option) any later version. | ||||
| # Please read the file COPYING, README and AUTHORS for more information. | ||||
| # | ||||
| # $Id: configure.in,v 1.118 2006/05/17 16:44:14 alex Exp $ | ||||
| # | ||||
|  | ||||
| # -- Initialisation -- | ||||
|  | ||||
| AC_PREREQ(2.50) | ||||
| AC_INIT(ngircd, CVSHEAD) | ||||
| AC_INIT(ngircd, 0.12.0) | ||||
| AC_CONFIG_SRCDIR(src/ngircd/ngircd.c) | ||||
| AC_CANONICAL_TARGET | ||||
| AM_INIT_AUTOMAKE(1.6) | ||||
| @@ -30,6 +28,7 @@ AH_TEMPLATE([SYSLOG], [Define if syslog should be used for logging]) | ||||
| AH_TEMPLATE([ZLIB], [Define if zlib compression should be enabled]) | ||||
| AH_TEMPLATE([TCPWRAP], [Define if TCP wrappers should be used]) | ||||
| AH_TEMPLATE([IRCPLUS], [Define if IRC+ protocol should be used]) | ||||
| AH_TEMPLATE([WANT_IPV6], [Define if IPV6 protocol should be enabled]) | ||||
| AH_TEMPLATE([ZEROCONF], [Define if support for Zeroconf should be included]) | ||||
| AH_TEMPLATE([IDENTAUTH], [Define if the server should do IDENT requests]) | ||||
|  | ||||
| @@ -53,33 +52,33 @@ AC_PROG_RANLIB | ||||
|  | ||||
| AM_C_PROTOTYPES | ||||
| AC_C_CONST | ||||
| AC_C_INLINE | ||||
|  | ||||
| # -- Hard coded system and compiler dependencies/features/options ... -- | ||||
|  | ||||
| AC_DEFUN([GCC_STACK_PROTECT_CC],[ | ||||
|   ssp_cc=yes | ||||
|   # we use -fstack-protector-all for the test to enfoce the use of the guard variable  | ||||
|   AC_MSG_CHECKING([whether ${CC} accepts -fstack-protector]) | ||||
|   ssp_old_cflags="$CFLAGS" | ||||
|   CFLAGS="$CFLAGS -fstack-protector-all" | ||||
|   AC_TRY_LINK(,,, ssp_cc=no) | ||||
|   echo $ssp_cc | ||||
|   CFLAGS="$ssp_old_cflags" | ||||
|   if test "X$ssp_cc" = "Xyes"; then | ||||
|       CFLAGS="$CFLAGS -fstack-protector" | ||||
|       AC_DEFINE([ENABLE_SSP_CC], 1, [Define if SSP C support is enabled.]) | ||||
|   fi | ||||
| ]) | ||||
|  | ||||
|  | ||||
| if test "$GCC" = "yes"; then | ||||
| 	# We are using the GNU C compiler. Good! | ||||
| 	CFLAGS="$CFLAGS -pipe -W -Wall -Wpointer-arith -Wstrict-prototypes" | ||||
|  | ||||
| 	GCC_STACK_PROTECT_CC | ||||
| fi | ||||
|  | ||||
|  | ||||
| AC_DEFUN([GCC_STACK_PROTECT_CC],[ | ||||
|   ssp_cc=yes | ||||
|   if test "X$CC" != "X"; then | ||||
|     AC_MSG_CHECKING([whether ${CC} accepts -fstack-protector]) | ||||
|     ssp_old_cflags="$CFLAGS" | ||||
|     CFLAGS="$CFLAGS -fstack-protector" | ||||
|     AC_TRY_COMPILE(,,, ssp_cc=no) | ||||
|     echo $ssp_cc | ||||
|     if test "X$ssp_cc" = "Xno"; then | ||||
|       CFLAGS="$ssp_old_cflags" | ||||
|     else | ||||
|       AC_DEFINE([ENABLE_SSP_CC], 1, [Define if SSP C support is enabled.]) | ||||
|     fi | ||||
|   fi | ||||
| ]) | ||||
|  | ||||
| GCC_STACK_PROTECT_CC | ||||
|  | ||||
| case "$target_os" in | ||||
| 	hpux*) | ||||
| 		# This is HP/UX, we need to define _XOPEN_SOURCE_EXTENDED | ||||
| @@ -138,17 +137,15 @@ AC_FUNC_STRFTIME | ||||
|  | ||||
| AC_CHECK_FUNCS([ \ | ||||
| 	bind gethostbyaddr gethostbyname gethostname inet_ntoa malloc memmove \ | ||||
| 	memset realloc setsid setsockopt socket strcasecmp strchr strerror \ | ||||
| 	memset realloc setsid setsockopt socket strcasecmp strchr strcspn strerror \ | ||||
| 	strstr waitpid],,AC_MSG_ERROR([required function missing!])) | ||||
|  | ||||
| AC_CHECK_FUNCS(inet_aton isdigit sigaction snprintf vsnprintf strdup strlcpy strlcat) | ||||
|  | ||||
| AC_CHECK_FUNCS(select,[AC_CHECK_HEADERS(sys/select.h)], | ||||
| 	AC_MSG_ERROR([required function select() is missing!]) | ||||
| ) | ||||
|  | ||||
| # -- Configuration options -- | ||||
|  | ||||
| # use syslog? | ||||
|  | ||||
| x_syslog_on=no | ||||
| AC_ARG_WITH(syslog, | ||||
| 	[  --without-syslog        disable syslog (autodetected by default)], | ||||
| @@ -174,6 +171,8 @@ if test "$x_syslog_on" = "yes"; then | ||||
| 	AC_CHECK_HEADERS(syslog.h,,AC_MSG_ERROR([required C header missing!])) | ||||
| fi | ||||
|  | ||||
| # use zlib compression? | ||||
|  | ||||
| x_zlib_on=no | ||||
| AC_ARG_WITH(zlib, | ||||
| 	[  --without-zlib          disable zlib compression (autodetected by default)], | ||||
| @@ -198,44 +197,120 @@ if test "$x_zlib_on" = "yes"; then | ||||
| 	AC_CHECK_HEADERS(zlib.h,,AC_MSG_ERROR([required C header missing!])) | ||||
| fi | ||||
|  | ||||
| # detect which IO API to use: | ||||
|  | ||||
| x_io_backend=select | ||||
| AC_ARG_WITH(epoll, | ||||
| 	[  --without-epoll         disable epoll support (autodetected by default)], | ||||
| x_io_backend=none | ||||
|  | ||||
| AC_ARG_WITH(select, | ||||
| 	[  --without-select        disable select IO support (autodetected by default)], | ||||
| 	[	if test "$withval" != "no"; then | ||||
| 			if test "$withval" != "yes"; then | ||||
| 				CFLAGS="-I$withval/include $CFLAGS" | ||||
| 				CPPFLAGS="-I$withval/include $CPPFLAGS" | ||||
| 				LDFLAGS="-L$withval/lib $LDFLAGS" | ||||
| 			fi | ||||
| 			AC_CHECK_FUNCS(epoll_create, x_io_backend=epoll, | ||||
| 				AC_MSG_ERROR([Can't enable epoll support!]) | ||||
| 			AC_CHECK_FUNCS(select, x_io_select=yes, | ||||
| 				AC_MSG_ERROR([Can't enable select IO support!]) | ||||
| 			) | ||||
| 		fi | ||||
| 	], | ||||
| 	[ | ||||
| 		AC_CHECK_FUNCS(epoll_create, x_io_backend=epoll) | ||||
| 		AC_CHECK_FUNCS(select, x_io_select=yes) | ||||
| 	] | ||||
| ) | ||||
|  | ||||
| AC_ARG_WITH(poll, | ||||
| 	[  --without-poll          disable poll support (autodetected by default)], | ||||
| 	[	if test "$withval" != "no"; then | ||||
| 			if test "$withval" != "yes"; then | ||||
| 				CFLAGS="-I$withval/include $CFLAGS" | ||||
| 				CPPFLAGS="-I$withval/include $CPPFLAGS" | ||||
| 				LDFLAGS="-L$withval/lib $LDFLAGS" | ||||
| 			fi | ||||
| 			AC_CHECK_FUNCS(poll, x_io_backend=poll\(\), | ||||
| 				AC_MSG_ERROR([Can't enable poll IO support!]) | ||||
| 			) | ||||
| 		fi | ||||
| 	], | ||||
| 	[ | ||||
| 		AC_CHECK_FUNCS(poll, x_io_backend=poll\(\)) | ||||
| 	] | ||||
| ) | ||||
|  | ||||
| AC_ARG_WITH(devpoll, | ||||
| 	[  --without-devpoll       disable /dev/poll IO support (autodetected by default)], | ||||
| 	[	if test "$withval" != "no"; then | ||||
| 			if test "$withval" != "yes"; then | ||||
| 				CFLAGS="-I$withval/include $CFLAGS" | ||||
| 				CPPFLAGS="-I$withval/include $CPPFLAGS" | ||||
| 				LDFLAGS="-L$withval/lib $LDFLAGS" | ||||
| 			fi | ||||
|  | ||||
| 				AC_CHECK_HEADERS(sys/devpoll.h,,AC_MSG_ERROR([required C header missing!])) | ||||
| 		fi | ||||
| 	], | ||||
| 	[ | ||||
| 		AC_CHECK_HEADERS(sys/devpoll.h, x_io_backend=/dev/poll) | ||||
| 	] | ||||
| ) | ||||
|  | ||||
| AC_ARG_WITH(epoll, | ||||
| 	[  --without-epoll         disable epoll IO support (autodetected by default)], | ||||
| 	[	if test "$withval" != "no"; then | ||||
| 			if test "$withval" != "yes"; then | ||||
| 				CFLAGS="-I$withval/include $CFLAGS" | ||||
| 				CPPFLAGS="-I$withval/include $CPPFLAGS" | ||||
| 				LDFLAGS="-L$withval/lib $LDFLAGS" | ||||
| 			fi | ||||
| 			AC_CHECK_FUNCS(epoll_create, x_io_epoll=yes, | ||||
| 				AC_MSG_ERROR([Can't enable epoll IO support!]) | ||||
| 			) | ||||
| 		fi | ||||
| 	], | ||||
| 	[ | ||||
| 		AC_CHECK_FUNCS(epoll_create, x_io_epoll=yes) | ||||
| 	] | ||||
| ) | ||||
|  | ||||
| AC_ARG_WITH(kqueue, | ||||
| 	[  --without-kqueue        disable kqueue support (autodetected by default)], | ||||
| 	[  --without-kqueue        disable kqueue IO support (autodetected by default)], | ||||
| 	[	if test "$withval" != "no"; then | ||||
| 			if test "$withval" != "yes"; then | ||||
| 				CFLAGS="-I$withval/include $CFLAGS" | ||||
| 				CPPFLAGS="-I$withval/include $CPPFLAGS" | ||||
| 				LDFLAGS="-L$withval/lib $LDFLAGS" | ||||
| 			fi | ||||
| 			AC_CHECK_FUNCS(kqueue, x_io_backend=kqueue, | ||||
| 				AC_MSG_ERROR([Can't enable kqueue support!]) | ||||
| 			AC_CHECK_FUNCS(kqueue, x_io_backend=kqueue\(\), | ||||
| 				AC_MSG_ERROR([Can't enable kqueue IO support!]) | ||||
| 			) | ||||
| 		fi | ||||
| 	], | ||||
| 	[ | ||||
| 		AC_CHECK_FUNCS(kqueue, x_io_backend=kqueue) | ||||
| 		AC_CHECK_FUNCS(kqueue, x_io_backend=kqueue\(\)) | ||||
| 	] | ||||
| ) | ||||
|  | ||||
| if test "$x_io_epoll" = "yes" -a "$x_io_select" = "yes"; then | ||||
| 	# when epoll() and select() are available, we'll use both! | ||||
| 	x_io_backend="epoll(), select()" | ||||
| else | ||||
| 	if test "$x_io_epoll" = "yes"; then | ||||
| 		# we prefere epoll() if it is available | ||||
| 		x_io_backend="epoll()" | ||||
| 	else | ||||
| 		if test "$x_io_select" = "yes" -a "$x_io_backend" = "none"; then | ||||
| 			# we'll use select, when available and no "better" | ||||
| 			# interface has been detected ... | ||||
| 			x_io_backend="select()" | ||||
| 		fi | ||||
| 	fi | ||||
| fi | ||||
|  | ||||
| if test "$x_io_backend" = "none"; then | ||||
| 	AC_MSG_ERROR([No useabe IO API activated/found!?]) | ||||
| fi | ||||
|  | ||||
| # use TCP wrappers? | ||||
|  | ||||
| x_tcpwrap_on=no | ||||
| AC_ARG_WITH(tcp-wrappers, | ||||
| @@ -266,6 +341,8 @@ int deny_severity = 0; | ||||
| 	] | ||||
| ) | ||||
|  | ||||
| # include support for "zeroconf"? | ||||
|  | ||||
| x_zeroconf_on=no | ||||
| AC_ARG_WITH(zeroconf, | ||||
| 	[  --with-zeroconf         enable support for "Zeroconf"], | ||||
| @@ -314,6 +391,8 @@ if test "$x_zeroconf_on" = "howl"; then | ||||
| 	AC_DEFINE(ZEROCONF, 1) | ||||
| fi | ||||
|  | ||||
| # do IDENT requests using libident? | ||||
|  | ||||
| x_identauth_on=no | ||||
| AC_ARG_WITH(ident, | ||||
| 	[  --with-ident            enable "IDENT" ("AUTH") protocol support], | ||||
| @@ -335,6 +414,8 @@ if test "$x_identauth_on" = "yes"; then | ||||
| 	AC_CHECK_HEADERS(ident.h,,AC_MSG_ERROR([required C header missing!])) | ||||
| fi | ||||
|  | ||||
| # compile in IRC+ protocol support? | ||||
|  | ||||
| x_ircplus_on=yes | ||||
| AC_ARG_ENABLE(ircplus, | ||||
| 	[  --disable-ircplus       disable IRC+ protocol], | ||||
| @@ -344,6 +425,21 @@ if test "$x_ircplus_on" = "yes"; then | ||||
| 	AC_DEFINE(IRCPLUS, 1) | ||||
| fi | ||||
|  | ||||
| # enable support for IPv6? | ||||
| x_ipv6_on=no | ||||
| AC_ARG_ENABLE(ipv6, | ||||
| 	[  --enable-ipv6           enable IPv6 protocol support], | ||||
| 	if test "$enableval" = "yes"; then x_ipv6_on=yes; fi | ||||
| ) | ||||
| if test "$x_ipv6_on" = "yes"; then | ||||
| 	AC_CHECK_FUNCS([ \ | ||||
| 		getaddrinfo getnameinfo \ | ||||
| 		],,AC_MSG_ERROR([required function missing for IPv6 support!])) | ||||
| 	AC_DEFINE(WANT_IPV6, 1) | ||||
| fi | ||||
|  | ||||
| # compile in IRC "sniffer"? | ||||
|  | ||||
| x_sniffer_on=no; x_debug_on=no | ||||
| AC_ARG_ENABLE(sniffer, | ||||
| 	[  --enable-sniffer        enable IRC traffic sniffer (enables debug mode)], | ||||
| @@ -353,6 +449,8 @@ AC_ARG_ENABLE(sniffer, | ||||
| 	fi | ||||
| ) | ||||
|  | ||||
| # enable additional debugging code? | ||||
|  | ||||
| AC_ARG_ENABLE(debug, | ||||
| 	[  --enable-debug          show additional debug output], | ||||
| 	if test "$enableval" = "yes"; then x_debug_on=yes; fi | ||||
| @@ -362,6 +460,8 @@ if test "$x_debug_on" = "yes"; then | ||||
| 	test "$GCC" = "yes" && CFLAGS="-pedantic $CFLAGS" | ||||
| fi | ||||
|  | ||||
| # enable "strict RFC rules"? | ||||
|  | ||||
| x_strict_rfc_on=no | ||||
| AC_ARG_ENABLE(strict-rfc, | ||||
| 	[  --enable-strict-rfc     strict RFC conformance -- may break clients!], | ||||
| @@ -389,6 +489,7 @@ AC_OUTPUT([ \ | ||||
| 	doc/src/Makefile \ | ||||
| 	src/Makefile \ | ||||
| 	src/portab/Makefile \ | ||||
| 	src/ipaddr/Makefile \ | ||||
| 	src/tool/Makefile \ | ||||
| 	src/ngircd/Makefile \ | ||||
| 	src/testsuite/Makefile \ | ||||
| @@ -396,6 +497,7 @@ AC_OUTPUT([ \ | ||||
| 	contrib/Makefile \ | ||||
| 	contrib/Debian/Makefile \ | ||||
| 	contrib/MacOSX/Makefile \ | ||||
| 	contrib/MacOSX/ngIRCd.xcodeproj/Makefile \ | ||||
| ]) | ||||
|  | ||||
| type dpkg >/dev/null 2>&1 | ||||
| @@ -482,8 +584,10 @@ test "$x_identauth_on" = "yes" \ | ||||
| 	&& echo $ECHO_N "yes   $ECHO_C" \ | ||||
| 	|| echo $ECHO_N "no    $ECHO_C" | ||||
| echo $ECHO_N "        I/O backend: $ECHO_C" | ||||
| 	echo "\"$x_io_backend()\"" | ||||
| 	echo "\"$x_io_backend\"" | ||||
|  | ||||
| echo $ECHO_N "      IPv6 protocol: $ECHO_C" | ||||
| echo "$x_ipv6_on" | ||||
| echo | ||||
|  | ||||
| # -eof- | ||||
|   | ||||
| @@ -1,3 +1,76 @@ | ||||
| ngircd (0.12.0-0ab0-pre3) unstable; urgency=low | ||||
|  | ||||
|   * New "upstream" release ngIRCd 0.12.0. | ||||
|  | ||||
|  -- Alexander Barton <alex@barton.de>  Tue, 13 May 2008 12:30:31 +0200 | ||||
|  | ||||
| ngircd (0.12.0-0ab0-pre2) unstable; urgency=low | ||||
|  | ||||
|   * Second prereloease of upcoming new "upstrem" release 0.12.0-pre1. | ||||
|  | ||||
|  -- Alexander Barton <alex@barton.de>  Tue, 29 Apr 2008 23:06:14 +0200 | ||||
|  | ||||
| ngircd (0.12.0-0ab0-pre1) unstable; urgency=low | ||||
|  | ||||
|   * Prereloease of upcoming new "upstrem" release 0.12.0-pre1. | ||||
|  | ||||
|  -- Alexander Barton <alex@barton.de>  Sun, 20 Apr 2008 15:43:34 +0200 | ||||
|  | ||||
| ngircd (0.11.0-0ab0-pre2) unstable; urgency=low | ||||
|  | ||||
|   * Second prerelease of upcoming new "upstream release". | ||||
|  | ||||
|  -- Alexander Barton <alex@barton.de>  Mon,  7 Jan 2008 15:32:42 +0100 | ||||
|  | ||||
| ngircd (0.11.0-0ab0-pre1) unstable; urgency=low | ||||
|  | ||||
|   * Prerelease of upcoming new "upstream release". | ||||
|  | ||||
|  -- Alexander Barton <alex@barton.de>  Wed,  2 Jan 2008 21:33:15 +0100 | ||||
|  | ||||
| ngircd (0.10.4-0ab1) unstable; urgency=high | ||||
|  | ||||
|   * New "upstream" release: 0.10.4 - fixing a security bug. | ||||
|  | ||||
|  -- Alexander Barton <alex@barton.de>  Mon,  7 Jan 2008 22:04:44 +0100 | ||||
|  | ||||
| ngircd (0.10.0-0ab1) unstable; urgency=low | ||||
|  | ||||
|   * New "upstream" release: 0.10.0 | ||||
|  | ||||
|  -- Alexander Barton <alex@barton.de>  Sun,  1 Oct 2006 18:14:21 +0200 | ||||
|  | ||||
| ngircd (0.10.0-0ab0-pre2-1) unstable; urgency=low | ||||
|  | ||||
|   * Bumped standards version to 3.7.2.1. | ||||
|   * Added "Provides: ircd" to Debian control file. | ||||
|  | ||||
|  -- Alexander Barton <alex@barton.de>  Sun,  1 Oct 2006 16:25:33 +0200 | ||||
|  | ||||
| ngircd (0.10.0-0ab0-pre2) unstable; urgency=low | ||||
|  | ||||
|   * Second "upstream" prerelease of upcoming 0.10.0 release. | ||||
|  | ||||
|  -- Alexander Barton <alex@barton.de>  Sat,  9 Sep 2006 20:57:52 +0200 | ||||
|  | ||||
| ngircd (0.10.0-0ab0-pre1) unstable; urgency=low | ||||
|  | ||||
|   * Prerelease of upcoming new "upstream release". | ||||
|  | ||||
|  -- Alexander Barton <alex@barton.de>  Wed,  2 Aug 2006 12:01:07 +0200 | ||||
|  | ||||
| ngircd (0.9.2-0ab1) unstable; urgency=low | ||||
|  | ||||
|   * New "upstream release" fixing a few bugs in 0.9.1. | ||||
|  | ||||
|  -- Alexander Barton <alex@barton.de>  Sat, 15 Oct 2005 14:10:34 +0200 | ||||
|  | ||||
| ngircd (0.9.1-0ab1) unstable; urgency=medium | ||||
|  | ||||
|   * New "upstream release" addressing two problems in ngIRCd 0.9.0. | ||||
|  | ||||
|  -- Alexander Barton <alex@barton.de>  Wed,  3 Aug 2005 15:10:41 +0200 | ||||
|  | ||||
| ngircd (0.9.0-0ab2) unstable; urgency=medium | ||||
|  | ||||
|   * Init script: fixed a problem with symbolic links in runlevel directories | ||||
|   | ||||
| @@ -3,11 +3,12 @@ Section: net | ||||
| Priority: optional | ||||
| Maintainer: Alexander Barton <alex@barton.de> | ||||
| Build-Depends: debhelper (>> 4.0.0), libz-dev, libwrap-dev, libident-dev | ||||
| Standards-Version: 3.5.8 | ||||
| Standards-Version: 3.7.2.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 | ||||
| @@ -28,6 +29,7 @@ Description: A lightweight daemon for the Internet Relay Chat (IRC) | ||||
| Package: ngircd-full | ||||
| Architecture: any | ||||
| Depends: ${shlibs:Depends}, ${misc:Depends} | ||||
| Provides: ircd | ||||
| Conflicts: ngircd | ||||
| Description: A lightweight daemon for the Internet Relay Chat (IRC) | ||||
|  ngIRCd is a free open source daemon for the Internet Relay Chat (IRC) | ||||
|   | ||||
| @@ -2,9 +2,20 @@ | ||||
| # | ||||
| # ngIRCd start and stop script for Debian-based systems | ||||
| # | ||||
| # $Id: ngircd.init,v 1.6 2005/07/26 19:37:18 alex Exp $ | ||||
| # $Id: ngircd.init,v 1.7 2006/12/26 14:43:46 alex Exp $ | ||||
| # | ||||
|  | ||||
| ### BEGIN INIT INFO | ||||
| # Provides:		ircd | ||||
| # Required-Start:	$local_fs | ||||
| # Required-Stop:	$local_fs | ||||
| # Should-Start:		$syslog $network | ||||
| # Should-Stop:		$syslog $network | ||||
| # Default-Start:	2 3 4 5 | ||||
| # Default-Stop:		0 1 6 | ||||
| # Short-Description:	Next Generation IRC Server | ||||
| ### END INIT INFO | ||||
|  | ||||
| PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin | ||||
| DAEMON=/usr/sbin/ngircd | ||||
| NAME=ngIRCd | ||||
|   | ||||
| @@ -1,13 +1,20 @@ | ||||
| #!/bin/sh | ||||
| # | ||||
| # Debian post-installation script | ||||
| # $Id: ngircd.postinst,v 1.1 2003/12/31 17:20:11 alex Exp $ | ||||
| # $Id: ngircd.postinst,v 1.2 2006/12/26 14:44:40 alex Exp $ | ||||
| # | ||||
|  | ||||
| if [ -f /etc/ngircd/ngircd.conf ]; then | ||||
| 	# make sure that configuration file is not world readable | ||||
| 	chmod o= /etc/ngircd/ngircd.conf | ||||
| fi | ||||
| set -e | ||||
|  | ||||
| case "$1" in | ||||
| 	configure) | ||||
| 		if [ -f /etc/ngircd/ngircd.conf ]; then | ||||
| 			# make sure that the configuration file is not | ||||
| 			# world-readable, it contains passwords! | ||||
| 			chmod o= /etc/ngircd/ngircd.conf | ||||
| 		fi | ||||
| 		;; | ||||
| esac | ||||
|  | ||||
| #DEBHELPER# | ||||
|  | ||||
|   | ||||
							
								
								
									
										1
									
								
								contrib/MacOSX/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								contrib/MacOSX/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| build | ||||
| @@ -1,6 +1,6 @@ | ||||
| # | ||||
| # ngIRCd -- The Next Generation IRC Daemon | ||||
| # Copyright (c)2001-2004 Alexander Barton <alex@barton.de> | ||||
| # Copyright (c)2001-2008 Alexander Barton <alex@barton.de> | ||||
| # | ||||
| # This program is free software; you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| @@ -8,9 +8,40 @@ | ||||
| # (at your option) any later version. | ||||
| # Please read the file COPYING, README and AUTHORS for more information. | ||||
| # | ||||
| # $Id: Makefile.am,v 1.2 2004/05/11 00:34:26 alex Exp $ | ||||
| # $Id: Makefile.am,v 1.3 2008/02/17 15:31:15 alex Exp $ | ||||
| # | ||||
|  | ||||
| SUBDIRS = ngIRCd.xcodeproj | ||||
|  | ||||
| EXTRA_DIST = de.barton.ngircd.plist.tmpl config.h cvs-version.h | ||||
|  | ||||
| SUFFIXES = .tmpl . | ||||
|  | ||||
| .tmpl: | ||||
| 	sed \ | ||||
| 	    -e s@:SBINDIR:@${sbindir}@ \ | ||||
| 	    <$< >$@ | ||||
|  | ||||
| install-data-local: | ||||
| 	[ `uname -s` != "Darwin" ] || make install-sys-darwin | ||||
|  | ||||
| install-sys-darwin: | ||||
| 	@if [ `id -u` -eq 0 ]; then \ | ||||
| 	  make install-sys-darwin-root; \ | ||||
| 	else \ | ||||
| 	  echo; \ | ||||
| 	  echo " ** NOTE: Not installing with root privileges, so the LaunchDaemon script"; \ | ||||
| 	  echo " ** \"/Library/LaunchDaemons/de.barton.ngircd.plist\" can't be installed/updated!"; \ | ||||
| 	  echo; \ | ||||
| 	fi | ||||
|  | ||||
| install-sys-darwin-root: de.barton.ngircd.plist | ||||
| 	install -c -m 644 -b -o root -g wheel de.barton.ngircd.plist /Library/LaunchDaemons/de.barton.ngircd.plist | ||||
| 	@echo | ||||
| 	@echo " ** \"/Library/LaunchDaemons/de.barton.ngircd.plist\" has been installed," | ||||
| 	@echo " ** but is disabled. Use launchctl(8) to enable/run ngIRCd on Darwin/Mac OS X." | ||||
| 	@echo | ||||
|  | ||||
| clean-local: | ||||
| 	rm -rf build | ||||
|  | ||||
|   | ||||
							
								
								
									
										92
									
								
								contrib/MacOSX/config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								contrib/MacOSX/config.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| /* | ||||
|  * ngIRCd -- The Next Generation IRC Daemon | ||||
|  * Copyright (c)2001-2007 Alexander Barton (alex@barton.de). | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: config.h,v 1.1 2007/11/19 22:11:36 alex Exp $ | ||||
|  * | ||||
|  * Static configuration file for Mac OS X Xcode project | ||||
|  */ | ||||
|  | ||||
| #define PACKAGE_NAME "ngircd" | ||||
| #define VERSION "??" | ||||
| #define SYSCONFDIR "/etc/ngircd" | ||||
|  | ||||
| /* -- Build options -- */ | ||||
|  | ||||
| /* Define if debug-mode should be enabled */ | ||||
| #define DEBUG 1 | ||||
|  | ||||
| /* Define if the server should do IDENT requests */ | ||||
| /*#define IDENTAUTH 1*/ | ||||
|  | ||||
| /* Define if IRC+ protocol should be used */ | ||||
| #define IRCPLUS 1 | ||||
|  | ||||
| /* Define if IRC sniffer should be enabled */ | ||||
| /*#define SNIFFER 1*/ | ||||
|  | ||||
| /* Define if syslog should be used for logging */ | ||||
| #define SYSLOG 1 | ||||
|  | ||||
| /* Define if TCP wrappers should be used */ | ||||
| /*#define TCPWRAP 1*/ | ||||
|  | ||||
| /* Define if support for Zeroconf should be included */ | ||||
| /*#define ZEROCONF 1*/ | ||||
|  | ||||
| /* Define if zlib compression should be enabled */ | ||||
| #define ZLIB 1 | ||||
|  | ||||
| /* -- Supported features -- */ | ||||
|  | ||||
| /* Define if SSP C support is enabled. */ | ||||
| #define ENABLE_SSP_CC 1 | ||||
|  | ||||
| /* Define to 1 if the C compiler supports function prototypes. */ | ||||
| #define PROTOTYPES 1 | ||||
| /* Define like PROTOTYPES; this can be used by system headers. */ | ||||
| #define __PROTOTYPES 1 | ||||
|  | ||||
| /* Define to 1 if you have the <sys/types.h> header file. */ | ||||
| #define HAVE_SYS_TYPES_H 1 | ||||
| /* Define to 1 if you have the <inttypes.h> header file. */ | ||||
| #define HAVE_INTTYPES_H 1 | ||||
| /* Define to 1 if you have the <stddef.h> header file. */ | ||||
| #define HAVE_STDDEF_H 1 | ||||
| /* Define to 1 if you have the <stdbool.h> header file. */ | ||||
| #define HAVE_STDBOOL_H 1 | ||||
| /* Define to 1 if you have the <arpa/inet.h> header file. */ | ||||
| #define HAVE_ARPA_INET_H 1 | ||||
|  | ||||
| /* Define to 1 if you have the `kqueue' function. */ | ||||
| #define HAVE_KQUEUE 1 | ||||
| /* Define to 1 if you have the `inet_ntoa' function. */ | ||||
| #define HAVE_INET_NTOA 1 | ||||
| /* Define to 1 if you have the `snprintf' function. */ | ||||
| #define HAVE_SNPRINTF 1 | ||||
| /* Define to 1 if you have the `strlcat' function. */ | ||||
| #define HAVE_STRLCAT 1 | ||||
| /* Define to 1 if you have the `strlcpy' function. */ | ||||
| #define HAVE_STRLCPY 1 | ||||
| /* Define to 1 if you have the `strdup' function. */ | ||||
| #define HAVE_STRDUP 1 | ||||
| /* Define to 1 if you have the `vsnprintf' function. */ | ||||
| #define HAVE_VSNPRINTF 1 | ||||
|  | ||||
| /* Define if socklen_t exists */ | ||||
| #define HAVE_socklen_t 1 | ||||
|  | ||||
| #ifdef ZEROCONF | ||||
| /* Define to 1 if you have the <DNSServiceDiscovery/DNSServiceDiscovery.h> header file. */ | ||||
| #define HAVE_DNSSERVICEDISCOVERY_DNSSERVICEDISCOVERY_H 1 | ||||
| /* Define to 1 if you have the `DNSServiceRegistrationCreate' function. */ | ||||
| #define HAVE_DNSSERVICEREGISTRATIONCREATE 1 | ||||
| #endif | ||||
|  | ||||
| /* -eof- */ | ||||
							
								
								
									
										0
									
								
								contrib/MacOSX/cvs-version.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								contrib/MacOSX/cvs-version.h
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										19
									
								
								contrib/MacOSX/de.barton.ngircd.plist.tmpl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								contrib/MacOSX/de.barton.ngircd.plist.tmpl
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||
| <plist version="1.0"> | ||||
| <dict> | ||||
| 	<key>Disabled</key> | ||||
| 	<true/> | ||||
| 	<key>KeepAlive</key> | ||||
| 	<true/> | ||||
| 	<key>Label</key> | ||||
| 	<string>de.barton.ngIRCd</string> | ||||
| 	<key>ProgramArguments</key> | ||||
| 	<array> | ||||
| 		<string>:SBINDIR:/ngircd</string> | ||||
| 		<string>--nodaemon</string> | ||||
| 	</array> | ||||
| 	<key>RunAtLoad</key> | ||||
| 	<true/> | ||||
| </dict> | ||||
| </plist> | ||||
							
								
								
									
										2
									
								
								contrib/MacOSX/ngIRCd.xcodeproj/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								contrib/MacOSX/ngIRCd.xcodeproj/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| *.mode1v3 | ||||
| *.pbxuser | ||||
							
								
								
									
										17
									
								
								contrib/MacOSX/ngIRCd.xcodeproj/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								contrib/MacOSX/ngIRCd.xcodeproj/Makefile.am
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| # | ||||
| # ngIRCd -- The Next Generation IRC Daemon | ||||
| # Copyright (c)2001-2008 Alexander Barton <alex@barton.de> | ||||
| # | ||||
| # This program is free software; you can redistribute it and/or modify | ||||
| # it under the terms of the GNU General Public License as published by | ||||
| # the Free Software Foundation; either version 2 of the License, or | ||||
| # (at your option) any later version. | ||||
| # Please read the file COPYING, README and AUTHORS for more information. | ||||
| # | ||||
|  | ||||
| EXTRA_DIST = project.pbxproj | ||||
|  | ||||
| maintainer-clean-local: | ||||
| 	rm -f Makefile Makefile.in | ||||
|  | ||||
| # -eof- | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,5 +1,5 @@ | ||||
| %define name    ngircd | ||||
| %define version CVSHEAD | ||||
| %define version 0.12.0 | ||||
| %define release 1 | ||||
| %define prefix  %{_prefix} | ||||
|  | ||||
|   | ||||
							
								
								
									
										57
									
								
								doc/CVS.txt
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								doc/CVS.txt
									
									
									
									
									
								
							| @@ -1,57 +0,0 @@ | ||||
|  | ||||
|                      ngIRCd - Next Generation IRC Server | ||||
|  | ||||
|                       (c)2001-2003 by Alexander Barton, | ||||
|                     alex@barton.de, http://www.barton.de/ | ||||
|  | ||||
|                ngIRCd is free software and published under the | ||||
|                    terms of the GNU General Public License. | ||||
|  | ||||
|                                  -- CVS.txt -- | ||||
|  | ||||
|  | ||||
| The source code of ngIRCd is maintained using the "Concurrent Versions | ||||
| System" (CVS). Thereby several developers can work with the source tree at | ||||
| the same time. | ||||
|  | ||||
|  | ||||
| I. Anonymous read-only Access | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| To access the source tree anonymously in read-only mode, follow these steps: | ||||
|  | ||||
| Login to the CVS server: | ||||
|  | ||||
|  $ cvs -d:pserver:anonymous@ngircd.barton.de:/srv/cvs/ngircd login | ||||
|  | ||||
| Use "anonymous" as user name and no password (just hit Return). Now you can | ||||
| check out the sources: | ||||
|  | ||||
|  $ cvs -d:pserver:anonymous@ngircd.barton.de:/srv/cvs/ngircd checkout ngircd | ||||
|  | ||||
| Thereby a new folder "ngircd" will be created containing all the individual | ||||
| source files. (Substitute the last "ngircd" with "website" to check out all | ||||
| the files of the homepage of ngIRCd.) | ||||
|  | ||||
| The newly created folder ("ngircd" or "website") is the "working folder", all | ||||
| CVS commands will be executed from within this folder in the future. | ||||
|  | ||||
| Please note: When checking out a fresh copy of ngIRCd from CVS, the | ||||
| configure script doesn't exist; you have to run the autogen.sh shell script | ||||
| (which is included in the source tree) to generate it. This requires you to | ||||
| have GNU automake and GNU autoconf installed on your system. | ||||
|  | ||||
| Updating the CVS tree: | ||||
|  | ||||
|  $ cvs update -d -P [<filename>] | ||||
|  | ||||
| You can update a single file or the complete source tree. | ||||
|  | ||||
|  | ||||
| III. Write Access | ||||
| ~~~~~~~~~~~~~~~~~ | ||||
| If you want to contribute a couple of patches and write access to the CVS | ||||
| repository would be handy, please contact Alex Barton, <alex@barton.de>. | ||||
|  | ||||
|  | ||||
| --  | ||||
| $Id: CVS.txt,v 1.8 2006/07/23 12:43:15 alex Exp $ | ||||
							
								
								
									
										11
									
								
								doc/FAQ.txt
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								doc/FAQ.txt
									
									
									
									
									
								
							| @@ -62,15 +62,6 @@ A: On Linux/glibc with chroot enabled you need to put some libraries inside | ||||
|    is to either disable chroot support or to link against dietlibc instead | ||||
|    of glibc. (tnx to Sebastian Siewior) | ||||
|  | ||||
| Q: I am running Linux and ngircd dies on startup with the follwing errors: | ||||
|    IO subsystem: epoll (hint size 100, initial maxfd 100, masterfd -1). | ||||
|    Cannot initialize IO routines: Function not implemented | ||||
|    Server isn't listening on a single port! | ||||
|    ngircd exiting due to fatal errors! | ||||
| A: epoll is only supported on 2.6 Linux kernels. Either use a 2.6 kernel, or | ||||
|    re-run configure with the --without-epoll parameter. After configure | ||||
|    completed, you should see select() being listed as IO backend: | ||||
|    '(I/O backend: "select()"'). | ||||
|  | ||||
| IV. Bugs!? | ||||
| ~~~~~~~~~~ | ||||
| @@ -85,4 +76,4 @@ A: Please file a bug report at <http://ngircd.barton.de/bugzilla/index.cgi>! | ||||
|  | ||||
|  | ||||
| --  | ||||
| $Id: FAQ.txt,v 1.11 2005/12/09 21:14:56 fw Exp $ | ||||
| $Id: FAQ.txt,v 1.12 2008/01/02 22:47:58 alex Exp $ | ||||
|   | ||||
							
								
								
									
										45
									
								
								doc/GIT.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								doc/GIT.txt
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
|                      ngIRCd - Next Generation IRC Server | ||||
|  | ||||
|                                  -- GIT.txt -- | ||||
|  | ||||
| The source code of ngIRCd is maintained using git, the stupid content | ||||
| tracker. | ||||
|  | ||||
| I. Getting the source code | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| To access the source tree anonymously, run: | ||||
|  | ||||
|  $ git clone git://ngircd.barton.de/ngircd.git | ||||
|  | ||||
| Thereby a new folder "ngircd" will be created containing all the individual | ||||
| source files. | ||||
|  | ||||
| The newly created directory ("ngircd") is the "working directory", all | ||||
| git commands will be executed from within this directory in the future. | ||||
|  | ||||
| Please note: When checking out a fresh copy of ngIRCd using git, the | ||||
| configure script doesn't exist; you have to run the autogen.sh shell script | ||||
| (which is included in the source tree) to generate it. This requires you to | ||||
| have GNU automake and GNU autoconf installed on your system. | ||||
|  | ||||
| To update the git tree: | ||||
|  | ||||
|  $ git pull | ||||
|  | ||||
| This retrieves all changes and merges them into the current branch. | ||||
|  | ||||
| II. Contributing | ||||
| ~~~~~~~~~~~~~~~~ | ||||
|  | ||||
| Patches should be sent to the ngircd mailing list. List homepage: | ||||
| http://arthur.barton.de/mailman/listinfo/ngircd-ml | ||||
|  | ||||
| If you do not want to send them to the list, you can also mail them | ||||
| to Alex Barton, <alex@barton.de>. | ||||
|  | ||||
|  | ||||
| III. Write Access | ||||
| ~~~~~~~~~~~~~~~~~ | ||||
| If you want to contribute a couple of patches and write access to the git | ||||
| repository would be handy, please contact Alex Barton, <alex@barton.de>. | ||||
|  | ||||
| @@ -1,6 +1,6 @@ | ||||
| # | ||||
| # ngIRCd -- The Next Generation IRC Daemon | ||||
| # Copyright (c)2001-2003 by Alexander Barton (alex@barton.de) | ||||
| # Copyright (c)2001-2008 by Alexander Barton (alex@barton.de) | ||||
| # | ||||
| # Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen | ||||
| # der GNU General Public License (GPL), wie von der Free Software Foundation | ||||
| @@ -9,13 +9,11 @@ | ||||
| # Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste | ||||
| # der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. | ||||
| # | ||||
| # $Id: Makefile.am,v 1.21 2005/11/29 20:59:57 alex Exp $ | ||||
| # | ||||
|  | ||||
| SUBDIRS = src | ||||
|  | ||||
| EXTRA_DIST = CVS.txt FAQ.txt Protocol.txt Platforms.txt README-AUX.txt \ | ||||
| 	README-BeOS.txt RFC.txt Zeroconf.txt  sample-ngircd.conf | ||||
| EXTRA_DIST = FAQ.txt GIT.txt Protocol.txt Platforms.txt README-AUX.txt \ | ||||
| 	README-BeOS.txt RFC.txt SSL.txt Zeroconf.txt sample-ngircd.conf | ||||
|  | ||||
| maintainer-clean-local: | ||||
| 	rm -f Makefile Makefile.in | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
|  | ||||
|                      ngIRCd - Next Generation IRC Server | ||||
|  | ||||
|                         (c)2001-2004 Alexander Barton | ||||
|                         (c)2001-2006 Alexander Barton | ||||
|                     alex@barton.de, http://www.barton.de/ | ||||
|  | ||||
|                ngIRCd is free software and published under the | ||||
| @@ -26,24 +26,32 @@ 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)		 | ||||
| alpha/unknown/netbsd3.0     gcc 3.3.3    CVSHEAD    06-05-07 fw     Y Y Y Y (3) | ||||
| 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    0.9.x-CVS  05-06-27 alex   Y Y Y Y | ||||
| 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    CVSHEAD    06-08-04 alex   Y Y Y Y | ||||
| i386/unknown/freebsd5.2.1   gcc 3.3.3    0.8.0      04-05-30 alex   Y Y Y Y | ||||
| i386/unknown/freebsd6.1     gcc 3.4.4    CVSHEAD    06-05-07 fw     Y Y Y Y (4) | ||||
| i386/unknown/freebsd6.0     gcc 3.4.4    0.10.0-p1  06-08-04 alex   Y Y Y Y (3) | ||||
| i386/unknown/freebsd6.1     gcc 3.4.4    CVSHEAD    06-05-07 fw     Y Y Y Y (3) | ||||
| i386/unknown/gnu0.3         gcc 3.3.3    0.8.0      04-05-30 alex   Y Y n Y | ||||
| i386/unknown/netbsdelf1.6.1 gcc 2.95.3   CVSHEAD    04-02-24 alex   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/openbsd3.9     gcc 3.3.5    0.10.0-p1  06-08-30 alex   Y Y Y Y (3) | ||||
| i686/pc/cygwin              gcc 3.3.1    0.8.0      04-05-30 alex   Y Y n Y | ||||
| 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.3    0.8.0      04-05-30 alex   Y Y Y Y (1) | ||||
| i386/pc/linux-gnu           gcc 4.1.2    0.10.0-p1  06-08-30 alex   Y Y Y Y (1) | ||||
| m68k/apple/aux3.1.1         Orig. A/UX   0.7.x-CVS  03-04-22 alex   Y Y Y 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 ? ? | ||||
| powerpc/apple/darwin6.5     gcc 3.1      0.7.x-CVS  03-04-23 alex   Y Y Y Y | ||||
| powerpc/apple/darwin7.4.0   gcc 3.3      0.8.0      04-05-30 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/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 | ||||
| @@ -51,16 +59,19 @@ sparc/unkn./netbsdelf1.6.1  gcc 2.95.3   0.8.0      04-05-30 alex   Y Y Y Y | ||||
|  | ||||
| Notes | ||||
| ~~~~~ | ||||
|  | ||||
| (1) i686/pc/linux-gnu: | ||||
|     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 (2.95.3, 3.0, 3.2, and 3.3). The | ||||
|     eldest glibc used was glibc-2.0.7. ngIRCd compiled and run on all these | ||||
|     systems without problems. | ||||
|     various versions of the GNU C compiler (starting with 2.95.x and up to | ||||
|     version 4.1.x). The eldest glibc used was glibc-2.0.7. ngIRCd compiled | ||||
|     and run on all these systems without problems. | ||||
|     Actual Linux kernels (2.6.x) and glic's support the epoll() IO interface. | ||||
|  | ||||
| (2) This compiler is an pre-ANSI C compiler, therefore the source code is | ||||
|     automatically converted using the included ansi2knr tool while building. | ||||
| (3) kqueue io backend			 | ||||
| (4) 6.1-PRERELEASE | ||||
|  | ||||
| (3) Using the kqueue() IO interface. | ||||
|  | ||||
| --  | ||||
| $Id: Platforms.txt,v 1.14 2006/05/07 11:07:13 fw Exp $ | ||||
| $Id: Platforms.txt,v 1.18 2006/10/08 14:09:16 alex Exp $ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
|  | ||||
|                      ngIRCd - Next Generation IRC Server | ||||
|  | ||||
|                       (c)2001-2003 by Alexander Barton, | ||||
|                         (c)2001-2007 Alexander Barton, | ||||
|                     alex@barton.de, http://www.barton.de/ | ||||
|  | ||||
|                ngIRCd is free software and published under the | ||||
| @@ -79,6 +79,9 @@ The following <serverflags> are defined at the moment: | ||||
|      peer understands this flag, it will send "MODE +I" and "MODE +b" | ||||
|      commands after the server link has been established. | ||||
|  | ||||
| - H: The server supports the "enhanced server handshake", see section II.2 | ||||
|      for a detailed description. | ||||
|  | ||||
| - o: IRC operators are allowed to change channel- and channel-user-modes | ||||
|      even if they aren't channel-operator of the affected channel. | ||||
|  | ||||
| @@ -90,7 +93,50 @@ The optional parameter <options> is used to propagate server options as | ||||
| defined in RFC 2813, section 4.1.1. | ||||
|  | ||||
|  | ||||
| II.2 Exchange channel-modes, topics, and persistent channels | ||||
| II.2 Enhanced Server Handshake | ||||
|  | ||||
| The "enhanced server handshake" is used when both servers support this IRC+ | ||||
| extension, which is indicated by the 'H' flag in the <serverflags> sent with | ||||
| the PASS command, see section II.1. | ||||
|  | ||||
| It basically means, that after exchanging the PASS and SERVER commands the | ||||
| server is not registered in the network (as usual), but that IRC numerics | ||||
| are exchanged until the numeric 376 (ENDOFMOTD) is received. Afterwards the | ||||
| peer is registered in the network as with the regular IRC protocol. | ||||
|  | ||||
| A server implementing the enhanced server handshake (and indicating this | ||||
| using 'H' in the <serverflags>) MUST ignore all unknown numerics to it | ||||
| silently. | ||||
|  | ||||
| In addition, such a server should at least send the numeric 005 (ISUPPORT) | ||||
| to its peer, containing the following information. Syntax: <key>=<value>, | ||||
| one token per IRC parameter. If the server has to send more than 12 token | ||||
| it must send separate ISUPPORT numerics (this is a limitation of the IRC | ||||
| protocol which allows at max 15 arguments per command). | ||||
|  | ||||
|  - NICKLEN: Maximum nickname length. Default: 9. | ||||
|  - CASEMAPPING: Case mapping used for nick- and channel name comparing. | ||||
|    Default: "ascii", the chars [a-z] are lowercase of [A-Z]. | ||||
|  - PREFIX: List of channel modes a person can get and the respective prefix | ||||
|    a channel or nickname will get in case the person has it. The order of the | ||||
|    modes goes from most powerful to least powerful. Default: "(ov)@+" | ||||
|  - CHANTYPES: Supported channel prefixes. Default: "#". | ||||
|  - CHANMODES: List of channel modes for 4 types, separated by comma (","): | ||||
|    Mode that adds or removes a nick or address to a list, mode that changes | ||||
|    a setting (both have always has a parameter), mode that changes a setting | ||||
|    and only has a parameter when set, and mode that changes a setting and | ||||
|    never has a parameter. For example "bI,k,l,imnPst". | ||||
|  - CHANLIMIT: Maximum number of channels allowed to join by channel prefix, | ||||
|    for example "#:10". | ||||
|  | ||||
| Please see <http://www.irc.org/tech_docs/005.html> for details. | ||||
|  | ||||
| The information exchanged using ISUPPORT can be used to detect configuration | ||||
| incompatibilities (different maximum nick name length, for example) and | ||||
| therefore to disconnect the peer prior to registering it in the network. | ||||
|  | ||||
|  | ||||
| II.3 Exchange channel-modes, topics, and persistent channels | ||||
|  | ||||
|      Command: CHANINFO | ||||
|   Parameters: <channel> +<modes> <key> <limit> [<topic>] | ||||
| @@ -115,4 +161,4 @@ channel mode). In this case <limit> should be "0". | ||||
|  | ||||
|  | ||||
| --  | ||||
| $Id: Protocol.txt,v 1.13 2005/08/27 19:00:06 alex Exp $ | ||||
| $Id: Protocol.txt,v 1.14 2007/11/21 12:16:35 alex Exp $ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
|  | ||||
|                      ngIRCd - Next Generation IRC Server | ||||
|  | ||||
|                         (c)2001-2005 Alexander Barton | ||||
|                         (c)2001-2006 Alexander Barton | ||||
|                     alex@barton.de, http://www.barton.de/ | ||||
|  | ||||
|                ngIRCd is free software and published under the | ||||
| @@ -16,7 +16,8 @@ with DNS Service Discovery (DNS-SD[3]). | ||||
| To use this features you can use one of two APIs: | ||||
|  | ||||
|   a) Apple "Bonjour" API as used by Mac OS X, | ||||
|   b) the Howl[4] Zeroconf library. | ||||
|   b) the Howl[4] Zeroconf library or the Howl compatibility layer | ||||
|      of the newer Avahi[5] library. | ||||
|  | ||||
| When calling the configure script using the "--with-zeroconf" switch the | ||||
| avalable API will be autodetected and the required additional libraries will | ||||
| @@ -32,7 +33,8 @@ Links: | ||||
|  [2] http://www.multicastdns.org/ | ||||
|  [3] http://www.dns-sd.org/ | ||||
|  [4] http://www.porchdogsoft.com/products/howl/ | ||||
|  [5] http://avahi.org/ | ||||
|  | ||||
|  | ||||
| --  | ||||
| $Id: Zeroconf.txt,v 1.1 2005/07/08 16:19:03 alex Exp $ | ||||
| $Id: Zeroconf.txt,v 1.2 2006/08/03 14:37:29 alex Exp $ | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| # $Id: sample-ngircd.conf,v 1.37 2006/04/09 12:27:23 alex Exp $ | ||||
| # $Id: sample-ngircd.conf,v 1.44 2008/01/07 23:02:29 alex Exp $ | ||||
|  | ||||
| # | ||||
| # This is a sample configuration file for the ngIRCd, which must be adepted | ||||
| @@ -6,6 +6,10 @@ | ||||
| # | ||||
| # Comments are started with "#" or ";". | ||||
| # | ||||
| # A lot of configuration options in this file start with a ";". You have | ||||
| # to remove the ";" in front of each variable to actually set a value! | ||||
| # The disabled variables are shown with example values for completeness. | ||||
| # | ||||
| # Use "ngircd --configtest" (see manual page ngircd(8)) to validate that the | ||||
| # server interprets the configuration file as expected! | ||||
| # | ||||
| @@ -93,17 +97,37 @@ | ||||
| 	# server? (This is a compatibility hack for ircd-irc2 servers) | ||||
| 	;OperServerMode = no | ||||
|  | ||||
| 	# Allow Pre-Defined Channels only (see Section [Channels]) | ||||
| 	;PredefChannelsOnly = no | ||||
|  | ||||
| 	# Don't do any DNS lookups when a client connects to the server. | ||||
| 	;NoDNS = no | ||||
|  | ||||
| 	# allow both ipv4 and ipv6 clients to connect by opening both | ||||
| 	# ipv4 and ipv6 sockets | ||||
| 	;ListenIPv6 = yes | ||||
| 	;ListenIPv4 = yes | ||||
|  | ||||
| 	# try to connect to other irc servers using ipv4 and ipv6, if possible | ||||
| 	;ConnectIPv6 = yes | ||||
| 	;ConnectIPv4 = yes | ||||
|  | ||||
| 	# Maximum number of simultaneous connection the server is allowed | ||||
| 	# to accept (<=0: unlimited): | ||||
| 	;MaxConnections = -1 | ||||
| 	# to accept (0: unlimited): | ||||
| 	;MaxConnections = 0 | ||||
|  | ||||
| 	# Maximum number of simultaneous connections from a single IP address | ||||
| 	# the server will accept (<=0: unlimited): | ||||
| 	# the server will accept (0: unlimited): | ||||
| 	;MaxConnectionsIP = 5 | ||||
|  | ||||
| 	# Maximum number of channels a user can be member of (<=0: no limit): | ||||
| 	# Maximum number of channels a user can be member of (0: no limit): | ||||
| 	;MaxJoins = 10 | ||||
|  | ||||
| 	# Maximum length of an user nick name (Default: 9, as in RFC 2812). | ||||
| 	# Please note that all servers in an IRC network MUST use the same | ||||
| 	# maximum nick name length! | ||||
| 	;MaxNickLength = 9 | ||||
|  | ||||
| [Operator] | ||||
| 	# [Operator] sections are used to define IRC Operators. There may be | ||||
| 	# more than one [Operator] block, one for each local operator. | ||||
| @@ -142,6 +166,10 @@ | ||||
| 	# this server should establish the connection). | ||||
| 	;Host = connect-to-host.the.net | ||||
|  | ||||
| 	# IP address to use as _source_ address for the connection. if unspecified, | ||||
| 	# ngircd will let the operating system pick an address. | ||||
| 	;Bind = 10.0.0.1 | ||||
|  | ||||
| 	# Port of the server to which the ngIRCd should connect. If you | ||||
| 	# assign no port the ngIRCd waits for incoming connections. | ||||
| 	;Port = 6667 | ||||
| @@ -157,6 +185,13 @@ | ||||
| 	# Group of this server (optional) | ||||
| 	;Group = 123 | ||||
|  | ||||
| 	# Set the "Passive" option to "yes" if you don't want this ngIRCd to | ||||
| 	# connect to the configured peer (same as leaving the "Port" variable | ||||
| 	# empty). The advantage of this option is that you can actually configure | ||||
| 	# a port an use the IRC command CONNECT more easily to manually connect | ||||
| 	# this specific server later. | ||||
| 	;Passive = no | ||||
|  | ||||
| [Server] | ||||
| 	# More [Server] sections, if you like ... | ||||
|  | ||||
| @@ -175,7 +210,13 @@ | ||||
| 	;Topic = a great topic | ||||
|  | ||||
| 	# Initial channel modes | ||||
| 	;Modes = tn | ||||
| 	;Modes = tnk | ||||
|  | ||||
| 	# initial channel password (mode k) | ||||
| 	;Key = Secret | ||||
|  | ||||
| 	# maximum users per channel (mode l) | ||||
| 	;MaxUsers = 23 | ||||
|  | ||||
| [Channel] | ||||
| 	# More [Channel] sections, if you like ... | ||||
|   | ||||
							
								
								
									
										1
									
								
								doc/src/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								doc/src/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| html | ||||
| @@ -8,14 +8,14 @@ | ||||
| # (at your option) any later version. | ||||
| # Please read the file COPYING, README and AUTHORS for more information. | ||||
| # | ||||
| # $Id: Makefile.am,v 1.2 2006/04/08 16:35:03 alex Exp $ | ||||
| # $Id: Makefile.am,v 1.3 2006/12/28 14:04:28 alex Exp $ | ||||
| # | ||||
|  | ||||
| maintainer-clean-local: | ||||
| 	rm -f Makefile Makefile.in | ||||
|  | ||||
| distclean-local: | ||||
| 	rm -f html | ||||
| 	rm -rf html | ||||
|  | ||||
| srcdoc: | ||||
| 	@doxygen --version >/dev/null 2>&1 \ | ||||
|   | ||||
							
								
								
									
										2
									
								
								man/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								man/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| ngircd.8 | ||||
| ngircd.conf.5 | ||||
| @@ -9,12 +9,25 @@ | ||||
| # Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste | ||||
| # der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. | ||||
| # | ||||
| # $Id: Makefile.am,v 1.5 2002/04/04 13:02:41 alex Exp $ | ||||
| # $Id: Makefile.am,v 1.6 2006/12/25 16:13:26 alex Exp $ | ||||
| # | ||||
|  | ||||
| TEMPLATE_MANS = ngircd.conf.5.tmpl ngircd.8.tmpl | ||||
|  | ||||
| SUFFIXES = .tmpl . | ||||
|  | ||||
| .tmpl: | ||||
| 	sed \ | ||||
| 	    -e s@:SBINDIR:@${sbindir}@ \ | ||||
| 	    -e s@:BINDIR:@${bindir}@ \ | ||||
| 	    -e s@:ETCDIR:@${sysconfdir}@ \ | ||||
| 	    <$< >$@ | ||||
|  | ||||
| man_MANS = ngircd.conf.5 ngircd.8 | ||||
|  | ||||
| EXTRA_DIST = $(man_MANS) | ||||
| CLEANFILES = $(man_MANS) | ||||
|  | ||||
| EXTRA_DIST = $(TEMPLATE_MANS) | ||||
|  | ||||
| maintainer-clean-local: | ||||
| 	rm -f Makefile Makefile.in | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| .\" | ||||
| .\" $Id: ngircd.8,v 1.11 2005/08/12 13:20:54 alex Exp $ | ||||
| .\" $Id: ngircd.8.tmpl,v 1.2 2007/11/15 01:03:29 fw Exp $ | ||||
| .\" | ||||
| .TH ngircd 8 "August 2005" ngircd "ngIRCd Manual" | ||||
| .SH NAME | ||||
| @@ -23,7 +23,8 @@ Linux, Mac OS X, NetBSD, OpenBSD, Solaris, and Windows with Cygwin. | ||||
| .PP | ||||
| As ngIRCd relies on UNIX standards and uses GNU automake and GNU autoconf | ||||
| there are good chances that it also supports other UNIX-based operating | ||||
| systems as well. | ||||
| systems as well. By default, ngIRCd writes diagnostic and informational messages using | ||||
| the syslog mechanism. | ||||
| .SH OPTIONS | ||||
| The default behaviour of | ||||
| .BR ngircd | ||||
| @@ -55,11 +56,11 @@ Output version information and exit. | ||||
| \fB\-\-help\fR | ||||
| Display a brief help text and exit. | ||||
| .SH FILES | ||||
| .I /usr/local/etc/ngircd.conf | ||||
| .I :ETCDIR:/ngircd.conf | ||||
| .RS | ||||
| The system wide default configuration file. | ||||
| .RE | ||||
| .I /usr/local/etc/ngircd.motd | ||||
| .I :ETCDIR:/ngircd.motd | ||||
| .RS | ||||
| Default "message of the day" (MOTD). | ||||
| .RE | ||||
| @@ -1,11 +1,11 @@ | ||||
| .\" | ||||
| .\" $Id: ngircd.conf.5,v 1.20 2005/09/02 14:39:00 fw Exp $ | ||||
| .\" $Id: ngircd.conf.5.tmpl,v 1.7 2007/11/23 16:26:03 fw Exp $ | ||||
| .\" | ||||
| .TH ngircd.conf 5 "August 2005" ngircd "ngIRCd Manual" | ||||
| .SH NAME | ||||
| ngircd.conf \- configuration file of ngIRCd | ||||
| .SH SYNOPSIS | ||||
| .B /usr/local/etc/ngircd.conf | ||||
| .B :ETCDIR:/ngircd.conf | ||||
| .SH DESCRIPTION | ||||
| .BR ngircd.conf | ||||
| is the configuration file of the | ||||
| @@ -146,18 +146,53 @@ If OperCanUseMode is enabled, this may lead the compatibility problems with | ||||
| Servers that run the ircd-irc2 Software. This Option "masks" mode requests | ||||
| by non-chanops as if they were coming from the server. Default: no. | ||||
| .TP | ||||
| \fBPredefChannelsOnly\fR | ||||
| If enabled, no new channels can be created. Useful if | ||||
| you do not want to have channels other than those defined in | ||||
| the config file. | ||||
| Default: No. | ||||
| .TP | ||||
| \fBNoDNS\fR | ||||
| If enabled, ngircd will not make DNS lookups when clients connect. | ||||
| If you configure ngircd to connect to other servers, ngircd may still | ||||
| perform a DNS lookup if required. | ||||
| Default: No. | ||||
| .TP | ||||
| \fBListenIPv4\fR | ||||
| Set this to no if you do not want ngircd to accept clients using the standard internet protocol, ipv4. | ||||
| This allows use of ngircd in ipv6-only setups. | ||||
| Default: Yes. | ||||
| .TP | ||||
| \fBListenIPv6\fR | ||||
| Set this to no if you do not want ngircd to accept clients using the new internet protocol, ipv6. | ||||
| Default: Yes. | ||||
| .TP | ||||
| \fBConnectIPv4\fR | ||||
| Set this to no if you do not want ngircd to connect to other irc servers using ipv4. | ||||
| This allows use of ngircd in ipv6-only setups. | ||||
| Default: Yes. | ||||
| .TP | ||||
| \fBConnectIPv6\fR | ||||
| Set this to no if you do not want ngircd to connect to other irc servers using ipv6. | ||||
| Default: Yes. | ||||
| .TP | ||||
| \fBMaxConnections\fR | ||||
| Maximum number of simultaneous connection the server is allowed to accept | ||||
| (<=0: unlimited). Default: -1. | ||||
| (0: unlimited). Default: 0. | ||||
| .TP | ||||
| \fBMaxConnectionsIP\fR | ||||
| Maximum number of simultaneous connections from a single IP address that | ||||
| the server will accept (<=0: unlimited). This configuration options lowers | ||||
| the server will accept (0: unlimited). This configuration options lowers | ||||
| the risk of denial of service attacks (DoS). Default: 5. | ||||
| .TP | ||||
| \fBMaxJoins\fR | ||||
| Maximum number of channels a user can be member of (<=0: no limit). | ||||
| Maximum number of channels a user can be member of (0: no limit). | ||||
| Default: 10. | ||||
| .TP | ||||
| \fBMaxNickLength\fR | ||||
| Maximum length of an user nick name (Default: 9, as in RFC 2812). Please | ||||
| note that all servers in an IRC network MUST use the same maximum nick name | ||||
| length! | ||||
| .SH [OPERATOR] | ||||
| .I [Operator] | ||||
| sections are used to define IRC Operators. There may be more than one | ||||
| @@ -195,6 +230,10 @@ IRC name of the server | ||||
| \fBHost\fR | ||||
| Internet host name of the peer | ||||
| .TP | ||||
| \fBBind\fR | ||||
| IP address to use as source IP for the outgoing connection. Default ist | ||||
| to let the operating system decide. | ||||
| .TP | ||||
| \fBPort\fR | ||||
| Port of the server to which the ngIRCd should connect. If you assign no port | ||||
| the ngIRCd waits for incoming connections. | ||||
| @@ -209,6 +248,9 @@ Foreign password for this connection. This password has to be configured as | ||||
| .TP | ||||
| \fBGroup\fR | ||||
| Group of this server (optional). | ||||
| \fBPassive\fR | ||||
| Disable automatic connection even if port value is specified. Default: false. | ||||
| You can use the IRC Operator command CONNECT later on to create the link. | ||||
| .SH [CHANNEL] | ||||
| Pre-defined channels can be configured in | ||||
| .I [Channel] | ||||
| @@ -230,6 +272,12 @@ Topic for this channel | ||||
| .TP | ||||
| \fBModes\fR | ||||
| Initial channel modes. | ||||
| .TP | ||||
| \fBKey\fR | ||||
| Sets initial channel key (only relevant if mode k is set) | ||||
| .TP | ||||
| \fBMaxUsers\fR | ||||
| Set maximum user limit for this channel (only relevant if mode l is set) | ||||
| .SH HINTS | ||||
| It's wise to use "ngircd --configtest" to validate the configuration file | ||||
| after changing it. See | ||||
							
								
								
									
										3
									
								
								src/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| config.h | ||||
| config.h.in | ||||
| stamp-h1 | ||||
| @@ -8,10 +8,10 @@ | ||||
| # (at your option) any later version. | ||||
| # Please read the file COPYING, README and AUTHORS for more information. | ||||
| # | ||||
| # $Id: Makefile.am,v 1.7 2005/07/22 21:01:03 alex Exp $ | ||||
| # $Id: Makefile.am,v 1.8 2008/02/26 22:04:15 fw Exp $ | ||||
| # | ||||
|  | ||||
| SUBDIRS = portab tool ngircd testsuite | ||||
| SUBDIRS = portab tool ipaddr ngircd testsuite | ||||
|  | ||||
| maintainer-clean-local: | ||||
| 	rm -f Makefile Makefile.in config.h config.h.in stamp-h.in | ||||
|   | ||||
							
								
								
									
										14
									
								
								src/ipaddr/Makefile.am
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/ipaddr/Makefile.am
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| AUTOMAKE_OPTIONS = ansi2knr | ||||
|  | ||||
| INCLUDES = -I$(srcdir)/../portab | ||||
|  | ||||
| noinst_LIBRARIES = libngipaddr.a | ||||
|  | ||||
| libngipaddr_a_SOURCES = ng_ipaddr.c | ||||
|  | ||||
| noinst_HEADERS = ng_ipaddr.h | ||||
|  | ||||
| maintainer-clean-local: | ||||
| 	rm -f Makefile Makefile.in | ||||
|  | ||||
| # -eof- | ||||
							
								
								
									
										167
									
								
								src/ipaddr/ng_ipaddr.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								src/ipaddr/ng_ipaddr.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,167 @@ | ||||
| /* | ||||
|  * Functions for AF_ agnostic ipv4/ipv6 handling. | ||||
|  * | ||||
|  * (c) 2008 Florian Westphal <fw@strlen.de>, public domain. | ||||
|  */ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| #include <assert.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #ifdef HAVE_GETADDRINFO | ||||
| #include <netdb.h> | ||||
| #include <sys/types.h> | ||||
| #endif | ||||
|  | ||||
| #include "ng_ipaddr.h" | ||||
|  | ||||
| GLOBAL bool | ||||
| ng_ipaddr_init(ng_ipaddr_t *addr, const char *ip_str, UINT16 port) | ||||
| { | ||||
| #ifdef HAVE_GETADDRINFO | ||||
| 	int ret; | ||||
| 	char portstr[64]; | ||||
| 	struct addrinfo *res0; | ||||
| 	struct addrinfo hints = { | ||||
| #ifndef WANT_IPV6	/* only accept v4 addresses */ | ||||
| 		.ai_family = AF_INET, | ||||
| #endif | ||||
| 		.ai_flags = AI_NUMERICHOST | ||||
| 	}; | ||||
|  | ||||
| 	if (ip_str == NULL) | ||||
| 		hints.ai_flags |= AI_PASSIVE; | ||||
|  | ||||
| 	/* silly, but ngircd stores UINT16 in server config, not string */ | ||||
| 	snprintf(portstr, sizeof(portstr), "%u", (unsigned int) port); | ||||
| 	ret = getaddrinfo(ip_str, portstr, &hints, &res0); | ||||
| 	assert(ret == 0); | ||||
| 	if (ret != 0) | ||||
| 		return false; | ||||
|  | ||||
| 	assert(sizeof(*addr) >= res0->ai_addrlen); | ||||
| 	if (sizeof(*addr) >= res0->ai_addrlen) | ||||
| 		memcpy(addr, res0->ai_addr, res0->ai_addrlen); | ||||
| 	else | ||||
| 		ret = -1; | ||||
| 	freeaddrinfo(res0); | ||||
| 	return ret == 0; | ||||
| #else /* HAVE_GETADDRINFO */ | ||||
| 	if (ip_str == NULL) | ||||
| 		ip_str = "0.0.0.0"; | ||||
| 	addr->sin4.sin_family = AF_INET; | ||||
| # ifdef HAVE_INET_ATON | ||||
| 	if (inet_aton(ip_str, &addr->sin4.sin_addr) == 0) | ||||
| 		return false; | ||||
| # else | ||||
| 	addr->sin4.sin_addr.s_addr = inet_addr(ip_str); | ||||
| 	if (addr->sin4.sin_addr.s_addr == (unsigned) -1) | ||||
| 		return false; | ||||
| # endif | ||||
| 	ng_ipaddr_setport(addr, port); | ||||
| 	return true; | ||||
| #endif /* HAVE_GETADDRINFO */ | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL void | ||||
| ng_ipaddr_setport(ng_ipaddr_t *a, UINT16 port) | ||||
| { | ||||
| #ifdef WANT_IPV6 | ||||
| 	int af; | ||||
|  | ||||
| 	assert(a != NULL); | ||||
|  | ||||
| 	af = a->sa.sa_family; | ||||
|  | ||||
| 	assert(af == AF_INET || af == AF_INET6); | ||||
|  | ||||
| 	switch (af) { | ||||
| 	case AF_INET: | ||||
| 		a->sin4.sin_port = htons(port); | ||||
| 		break; | ||||
| 	case AF_INET6: | ||||
| 		a->sin6.sin6_port = htons(port); | ||||
| 		break; | ||||
| 	} | ||||
| #else /* WANT_IPV6 */ | ||||
| 	assert(a != NULL); | ||||
| 	assert(a->sin4.sin_family == AF_INET); | ||||
| 	a->sin4.sin_port = htons(port); | ||||
| #endif /* WANT_IPV6 */ | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| ng_ipaddr_ipequal(const ng_ipaddr_t *a, const ng_ipaddr_t *b) | ||||
| { | ||||
| 	assert(a != NULL); | ||||
| 	assert(b != NULL); | ||||
| #ifdef WANT_IPV6 | ||||
| 	if (a->sa.sa_family != b->sa.sa_family) | ||||
| 		return false; | ||||
| 	assert(ng_ipaddr_salen(a) == ng_ipaddr_salen(b)); | ||||
| 	switch (a->sa.sa_family) { | ||||
| 	case AF_INET6: | ||||
| 		return IN6_ARE_ADDR_EQUAL(&a->sin6.sin6_addr, &b->sin6.sin6_addr); | ||||
| 	case AF_INET: | ||||
| 		return memcmp(&a->sin4.sin_addr, &b->sin4.sin_addr, sizeof(a->sin4.sin_addr)) == 0; | ||||
| 	} | ||||
| 	return false; | ||||
| #else | ||||
| 	assert(a->sin4.sin_family == AF_INET); | ||||
| 	assert(b->sin4.sin_family == AF_INET); | ||||
| 	return memcmp(&a->sin4.sin_addr, &b->sin4.sin_addr, sizeof(a->sin4.sin_addr)) == 0; | ||||
| #endif | ||||
| } | ||||
|  | ||||
|  | ||||
| #ifdef WANT_IPV6 | ||||
| GLOBAL const char * | ||||
| ng_ipaddr_tostr(const ng_ipaddr_t *addr) | ||||
| { | ||||
| 	static char strbuf[NG_INET_ADDRSTRLEN]; | ||||
|  | ||||
| 	strbuf[0] = 0; | ||||
|  | ||||
| 	ng_ipaddr_tostr_r(addr, strbuf); | ||||
| 	return strbuf; | ||||
| } | ||||
|  | ||||
|  | ||||
| /* str must be at least NG_INET_ADDRSTRLEN bytes long */ | ||||
| GLOBAL bool | ||||
| ng_ipaddr_tostr_r(const ng_ipaddr_t *addr, char *str) | ||||
| { | ||||
| #ifdef HAVE_GETNAMEINFO | ||||
| 	const struct sockaddr *sa = (const struct sockaddr *) addr; | ||||
| 	int ret; | ||||
|  | ||||
| 	*str = 0; | ||||
|  | ||||
| 	ret = getnameinfo(sa, ng_ipaddr_salen(addr), | ||||
| 			str, NG_INET_ADDRSTRLEN, NULL, 0, NI_NUMERICHOST); | ||||
| 	/* | ||||
| 	 * avoid leading ':'. | ||||
| 	 * causes mis-interpretation of client host in e.g. /WHOIS | ||||
| 	 */ | ||||
| 	if (*str == ':') { | ||||
| 		char tmp[NG_INET_ADDRSTRLEN] = "0"; | ||||
| 		ret = getnameinfo(sa, ng_ipaddr_salen(addr), | ||||
| 				tmp+1, sizeof(tmp) -1, NULL, 0, NI_NUMERICHOST); | ||||
| 		if (ret == 0) | ||||
| 			strlcpy(str, tmp, NG_INET_ADDRSTRLEN); | ||||
| 	} | ||||
| 	assert (ret == 0); | ||||
| 	return ret == 0; | ||||
| #else | ||||
| 	abort(); /* WANT_IPV6 depends on HAVE_GETNAMEINFO */ | ||||
| #endif | ||||
| } | ||||
|  | ||||
| #endif /* WANT_IPV6 */ | ||||
|  | ||||
| /* -eof- */ | ||||
							
								
								
									
										118
									
								
								src/ipaddr/ng_ipaddr.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								src/ipaddr/ng_ipaddr.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,118 @@ | ||||
| /* | ||||
|  * Functions for AF_ agnostic ipv4/ipv6 handling. | ||||
|  * | ||||
|  * (c) 2008 Florian Westphal <fw@strlen.de>, public domain. | ||||
|  */ | ||||
|  | ||||
| #ifndef NG_IPADDR_HDR | ||||
| #define NG_IPADDR_HDR | ||||
| #include "portab.h" | ||||
|  | ||||
| #include <sys/socket.h> | ||||
| #include <netinet/in.h> | ||||
|  | ||||
| #ifdef HAVE_ARPA_INET_H | ||||
| # include <arpa/inet.h> | ||||
| #else | ||||
| # define PF_INET AF_INET | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #ifdef WANT_IPV6 | ||||
| #define NG_INET_ADDRSTRLEN	INET6_ADDRSTRLEN | ||||
| #else | ||||
| #define NG_INET_ADDRSTRLEN	16 | ||||
| #endif | ||||
|  | ||||
|  | ||||
| #ifdef WANT_IPV6 | ||||
| typedef union { | ||||
| 	struct sockaddr sa; | ||||
| 	struct sockaddr_in sin4; | ||||
| 	struct sockaddr_in6 sin6; | ||||
| } ng_ipaddr_t; | ||||
| #else | ||||
| /* assume compiler can't deal with typedef struct {... */ | ||||
| struct NG_IP_ADDR_DONTUSE { | ||||
| 	struct sockaddr_in sin4; | ||||
| }; | ||||
| typedef struct NG_IP_ADDR_DONTUSE ng_ipaddr_t; | ||||
| #endif | ||||
|  | ||||
|  | ||||
| static inline int | ||||
| ng_ipaddr_af(const ng_ipaddr_t *a) | ||||
| { | ||||
| #ifdef WANT_IPV6 | ||||
| 	return a->sa.sa_family; | ||||
| #else | ||||
| 	assert(a->sin4.sin_family == 0 || a->sin4.sin_family == AF_INET); | ||||
| 	return a->sin4.sin_family; | ||||
| #endif | ||||
| } | ||||
|  | ||||
|  | ||||
| static inline socklen_t | ||||
| ng_ipaddr_salen(const ng_ipaddr_t *a) | ||||
| { | ||||
| #ifdef WANT_IPV6 | ||||
| 	assert(a->sa.sa_family == AF_INET || a->sa.sa_family == AF_INET6); | ||||
| 	if (a->sa.sa_family == AF_INET6) | ||||
| 		return sizeof(a->sin6); | ||||
| #endif | ||||
| 	assert(a->sin4.sin_family == AF_INET); | ||||
| 	return sizeof(a->sin4); | ||||
| } | ||||
|  | ||||
|  | ||||
| static inline UINT16 | ||||
| ng_ipaddr_getport(const ng_ipaddr_t *a) | ||||
| { | ||||
| #ifdef WANT_IPV6 | ||||
| 	int af = a->sa.sa_family; | ||||
|  | ||||
| 	assert(af == AF_INET || af == AF_INET6); | ||||
|  | ||||
| 	if (af == AF_INET6) | ||||
| 		return ntohs(a->sin6.sin6_port); | ||||
| #endif /* WANT_IPV6 */ | ||||
| 	assert(a->sin4.sin_family == AF_INET); | ||||
| 	return ntohs(a->sin4.sin_port); | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * init a ng_ipaddr_t object. | ||||
|  * @param addr: pointer to ng_ipaddr_t to initialize. | ||||
|  * @param ip_str: ip address in dotted-decimal (ipv4) or hexadecimal (ipv6) notation | ||||
|  *                if ip_str is NULL it is treated as 0.0.0.0/[::] | ||||
|  * @param port: transport layer port number to use. | ||||
|  */ | ||||
| GLOBAL bool ng_ipaddr_init PARAMS((ng_ipaddr_t *addr, const char *ip_str, UINT16 port)); | ||||
|  | ||||
| /* set sin4/sin6_port, depending on a->sa_family */ | ||||
| GLOBAL void ng_ipaddr_setport PARAMS((ng_ipaddr_t *a, UINT16 port)); | ||||
|  | ||||
| /* return true if a and b have the same IP address. If a and b have different AF, return false. */ | ||||
| GLOBAL bool ng_ipaddr_ipequal PARAMS((const ng_ipaddr_t *a, const ng_ipaddr_t *b)); | ||||
|  | ||||
|  | ||||
| #ifdef WANT_IPV6 | ||||
| /* convert struct sockaddr to string, returns pointer to static buffer */ | ||||
| GLOBAL const char *ng_ipaddr_tostr PARAMS((const ng_ipaddr_t *addr)); | ||||
|  | ||||
| /* convert struct sockaddr to string. dest must be NG_INET_ADDRSTRLEN bytes long */ | ||||
| GLOBAL bool ng_ipaddr_tostr_r PARAMS((const ng_ipaddr_t *addr, char *dest)); | ||||
| #else | ||||
| static inline const char * | ||||
| ng_ipaddr_tostr(const ng_ipaddr_t *addr) { return inet_ntoa(addr->sin4.sin_addr); } | ||||
|  | ||||
| static inline bool | ||||
| ng_ipaddr_tostr_r(const ng_ipaddr_t *addr, char *d) | ||||
| { | ||||
| 	strlcpy(d, inet_ntoa(addr->sin4.sin_addr), NG_INET_ADDRSTRLEN); | ||||
| 	return true; | ||||
| } | ||||
| #endif | ||||
| #endif | ||||
|  | ||||
| /* -eof- */ | ||||
							
								
								
									
										5
									
								
								src/ngircd/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/ngircd/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| check-help | ||||
| check-version | ||||
| cvs-version.h | ||||
| cvs-version.new | ||||
| ngircd | ||||
| @@ -8,12 +8,12 @@ | ||||
| # (at your option) any later version. | ||||
| # Please read the file COPYING, README and AUTHORS for more information. | ||||
| # | ||||
| # $Id: Makefile.am,v 1.49 2006/03/11 01:48:50 alex Exp $ | ||||
| # $Id: Makefile.am,v 1.51 2008/02/26 22:04:17 fw Exp $ | ||||
| # | ||||
|  | ||||
| AUTOMAKE_OPTIONS = ../portab/ansi2knr | ||||
|  | ||||
| INCLUDES = -I$(srcdir)/../portab -I$(srcdir)/../tool | ||||
| INCLUDES = -I$(srcdir)/../portab -I$(srcdir)/../tool -I$(srcdir)/../ipaddr | ||||
|  | ||||
| LINTARGS = -weak -warnunixlib +unixlib -booltype BOOLEAN \ | ||||
|  -varuse -retvalother -emptyret -unrecog | ||||
| @@ -23,20 +23,20 @@ sbin_PROGRAMS = ngircd | ||||
| ngircd_SOURCES = ngircd.c array.c channel.c client.c conf.c conn.c conn-func.c \ | ||||
| 	conn-zip.c hash.c io.c irc.c irc-channel.c irc-info.c irc-login.c \ | ||||
| 	irc-mode.c irc-op.c irc-oper.c irc-server.c irc-write.c lists.c log.c \ | ||||
| 	match.c parse.c rendezvous.c resolve.c | ||||
| 	match.c numeric.c parse.c rendezvous.c resolve.c | ||||
|  | ||||
| ngircd_LDFLAGS = -L../portab -L../tool | ||||
| ngircd_LDFLAGS = -L../portab -L../tool -L../ipaddr | ||||
|  | ||||
| ngircd_LDADD = -lngportab -lngtool | ||||
| ngircd_LDADD = -lngportab -lngtool -lngipaddr | ||||
|  | ||||
| noinst_HEADERS = ngircd.h array.h channel.h client.h conf.h conn.h conn-func.h \ | ||||
| 	conn-zip.h hash.h io.h irc.h irc-channel.h irc-info.h irc-login.h \ | ||||
| 	irc-mode.h irc-op.h irc-oper.h irc-server.h irc-write.h lists.h log.h \ | ||||
| 	match.h parse.h rendezvous.h resolve.h \ | ||||
| 	match.h numeric.h parse.h rendezvous.h resolve.h \ | ||||
| 	defines.h messages.h | ||||
|  | ||||
| clean-local: | ||||
| 	rm -f check-version check-help lint.out cvs-version.* | ||||
| 	rm -f check-version check-help lint.out | ||||
|  | ||||
| maintainer-clean-local: | ||||
| 	rm -f Makefile Makefile.in | ||||
| @@ -77,23 +77,6 @@ lint: | ||||
| 	 || echo "Result: no warnings found."; \ | ||||
| 	echo; [ $$warnings -gt 0 ] && exit 1 | ||||
|  | ||||
| ngircd.c: cvs-version.h | ||||
|  | ||||
| irc-login.c: cvs-version.h | ||||
|  | ||||
| irc-info.c: cvs-version.h | ||||
|  | ||||
| cvs-version.h: cvs-date | ||||
|  | ||||
| cvs-date: | ||||
| 	grep VERSION ../config.h | grep "CVS" \ | ||||
| 	 && echo "#define CVSDATE \"$$( grep "\$$Id" $(srcdir)/*.c \ | ||||
| 	    | $(AWK) "{ print \$$9 }" | sort | tail -1 \ | ||||
| 	    | sed -e "s/\//-/g" )\"" > cvs-version.new \ | ||||
| 	 || echo "" > cvs-version.new | ||||
| 	diff cvs-version.h cvs-version.new 2>/dev/null \ | ||||
| 	 || cp cvs-version.new cvs-version.h | ||||
|  | ||||
| TESTS = check-version check-help | ||||
|  | ||||
| # -eof- | ||||
|   | ||||
| @@ -12,7 +12,7 @@ | ||||
|  | ||||
| #include "array.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: array.c,v 1.11 2006/07/01 22:11:48 fw Exp $"; | ||||
| static char UNUSED id[] = "$Id: array.c,v 1.15 2007/11/18 15:05:35 alex Exp $"; | ||||
|  | ||||
| #include <assert.h> | ||||
|  | ||||
| @@ -28,9 +28,9 @@ static char UNUSED id[] = "$Id: array.c,v 1.11 2006/07/01 22:11:48 fw Exp $"; | ||||
|  | ||||
| #define array_UNUSABLE(x)	( !(x)->mem || (0 == (x)->allocated) ) | ||||
|  | ||||
| #define ALIGN_32U(x)            (((x)+31U  ) & ~(31U)) | ||||
| #define ALIGN_1024U(x)          (((x)+1023U) & ~(1023U)) | ||||
| #define ALIGN_4096U(x)          (((x)+4095U) & ~(4095U)) | ||||
| #define ALIGN_32U(x)            (((x)+(unsigned)31  ) & ~((unsigned)31)) | ||||
| #define ALIGN_1024U(x)          (((x)+(unsigned)1023) & ~((unsigned)1023)) | ||||
| #define ALIGN_4096U(x)          (((x)+(unsigned)4095) & ~((unsigned)4095)) | ||||
|  | ||||
|  | ||||
| static bool | ||||
| @@ -66,10 +66,7 @@ array_alloc(array * a, size_t size, size_t pos) | ||||
|  | ||||
| 	assert(size > 0); | ||||
|  | ||||
| 	if (pos_plus1 < pos) | ||||
| 		return NULL; | ||||
|  | ||||
| 	if (!safemult_sizet(size, pos_plus1, &alloc)) | ||||
| 	if (pos_plus1 == 0 || !safemult_sizet(size, pos_plus1, &alloc)) | ||||
| 		return NULL; | ||||
|  | ||||
| 	if (a->allocated < alloc) { | ||||
| @@ -250,20 +247,22 @@ void * | ||||
| array_get(array * a, size_t membersize, size_t pos) | ||||
| { | ||||
| 	size_t totalsize; | ||||
| 	size_t posplus1 = pos + 1; | ||||
|  | ||||
| 	assert(membersize > 0); | ||||
| 	assert(a != NULL); | ||||
|  | ||||
| 	if (array_UNUSABLE(a)) | ||||
| 	if (!posplus1 || array_UNUSABLE(a)) | ||||
| 		return NULL; | ||||
|  | ||||
| 	if (!safemult_sizet(pos, membersize, &totalsize)) | ||||
| 	if (!safemult_sizet(posplus1, membersize, &totalsize)) | ||||
| 		return NULL; | ||||
|  | ||||
| 	if (a->allocated < totalsize) | ||||
| 		return NULL; | ||||
|  | ||||
| 	return a->mem + pos * membersize; | ||||
| 	totalsize = pos * membersize; | ||||
| 	return a->mem + totalsize; | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -271,7 +270,7 @@ void | ||||
| array_free(array * a) | ||||
| { | ||||
| 	assert(a != NULL); | ||||
| #ifdef DEBUG | ||||
| #ifdef DEBUG_ARRAY | ||||
| 	Log(LOG_DEBUG, | ||||
| 	    "array_free(): %u bytes free'd (%u bytes still used at time of free()).", | ||||
| 	    a->allocated, a->used); | ||||
| @@ -283,16 +282,6 @@ array_free(array * a) | ||||
| } | ||||
|  | ||||
|  | ||||
| void | ||||
| array_free_wipe(array * a) | ||||
| { | ||||
| 	if (!array_UNUSABLE(a)) | ||||
| 		memset(a->mem, 0, a->allocated); | ||||
|  | ||||
| 	array_free(a); | ||||
| } | ||||
|  | ||||
|  | ||||
| void * | ||||
| array_start(const array * const a) | ||||
| { | ||||
| @@ -331,9 +320,6 @@ array_moveleft(array * a, size_t membersize, size_t pos) | ||||
| 	assert(a != NULL); | ||||
| 	assert(membersize > 0); | ||||
|  | ||||
| 	if (!pos) | ||||
| 		return; | ||||
|  | ||||
| 	if (!safemult_sizet(membersize, pos, &bytepos)) { | ||||
| 		a->used = 0; | ||||
| 		return; | ||||
|   | ||||
| @@ -17,7 +17,7 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: channel.c,v 1.56 2006/07/24 22:54:09 alex Exp $"; | ||||
| static char UNUSED id[] = "$Id: channel.c,v 1.65 2008/02/05 16:31:35 fw Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| @@ -56,7 +56,7 @@ static CL2CHAN *My_Cl2Chan; | ||||
|  | ||||
| static CL2CHAN *Get_Cl2Chan PARAMS(( CHANNEL *Chan, CLIENT *Client )); | ||||
| static CL2CHAN *Add_Client PARAMS(( CHANNEL *Chan, CLIENT *Client )); | ||||
| static bool Remove_Client PARAMS(( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, char *Reason, bool InformServer )); | ||||
| static bool Remove_Client PARAMS(( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, const char *Reason, bool InformServer )); | ||||
| static CL2CHAN *Get_First_Cl2Chan PARAMS(( CLIENT *Client, CHANNEL *Chan )); | ||||
| static CL2CHAN *Get_Next_Cl2Chan PARAMS(( CL2CHAN *Start, CLIENT *Client, CHANNEL *Chan )); | ||||
| static bool Delete_Channel PARAMS(( CHANNEL *Chan )); | ||||
| @@ -70,6 +70,22 @@ Channel_Init( void ) | ||||
| } /* Channel_Init */ | ||||
|  | ||||
|  | ||||
| GLOBAL struct list_head * | ||||
| Channel_GetListBans(CHANNEL *c) | ||||
| { | ||||
| 	assert(c != NULL); | ||||
| 	return &c->list_bans; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL struct list_head * | ||||
| Channel_GetListInvites(CHANNEL *c) | ||||
| { | ||||
| 	assert(c != NULL); | ||||
| 	return &c->list_invites; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL void | ||||
| Channel_InitPredefined( void ) | ||||
| { | ||||
| @@ -114,7 +130,10 @@ Channel_InitPredefined( void ) | ||||
| 			c = Conf_Channel[i].modes; | ||||
| 			while (*c) | ||||
| 				Channel_ModeAdd(chan, *c++); | ||||
| 		 | ||||
|  | ||||
| 			Channel_SetKey(chan, Conf_Channel[i].key); | ||||
| 			Channel_SetMaxUsers(chan, Conf_Channel[i].maxusers); | ||||
|  | ||||
| 			Log(LOG_INFO, "Created pre-defined channel \"%s\".", | ||||
| 							Conf_Channel[i].name ); | ||||
| 		} | ||||
| @@ -129,7 +148,7 @@ Channel_Exit( void ) | ||||
| { | ||||
| 	CHANNEL *c, *c_next; | ||||
| 	CL2CHAN *cl2chan, *cl2chan_next; | ||||
| 	 | ||||
|  | ||||
| 	/* Channel-Strukturen freigeben */ | ||||
| 	c = My_Channels; | ||||
| 	while( c ) | ||||
| @@ -173,7 +192,7 @@ Channel_Join( CLIENT *Client, char *Name ) | ||||
| 	{ | ||||
| 		/* Gibt es noch nicht? Dann neu anlegen: */ | ||||
| 		chan = Channel_Create( Name ); | ||||
| 		if( ! chan ) return false; | ||||
| 		if (!chan) return false; | ||||
| 	} | ||||
|  | ||||
| 	/* User dem Channel hinzufuegen */ | ||||
| @@ -182,25 +201,38 @@ Channel_Join( CLIENT *Client, char *Name ) | ||||
| } /* Channel_Join */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Remove client from channel. | ||||
|  * This function lets a client lead a channel. First, the function checks | ||||
|  * if the channel exists and the client is a member of it and sends out | ||||
|  * appropriate error messages if not. The real work is done by the function | ||||
|  * Remove_Client(). | ||||
|  */ | ||||
| GLOBAL bool | ||||
| Channel_Part( CLIENT *Client, CLIENT *Origin, char *Name, char *Reason ) | ||||
| Channel_Part(CLIENT * Client, CLIENT * Origin, const char *Name, const char *Reason) | ||||
| { | ||||
| 	CHANNEL *chan; | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Name != NULL ); | ||||
| 	assert( Reason != NULL ); | ||||
| 	assert(Client != NULL); | ||||
| 	assert(Name != NULL); | ||||
| 	assert(Reason != NULL); | ||||
|  | ||||
| 	chan = Channel_Search( Name ); | ||||
| 	if(( ! chan ) || ( ! Get_Cl2Chan( chan, Client ))) | ||||
| 	{ | ||||
| 		IRC_WriteStrClient( Client, ERR_NOSUCHCHANNEL_MSG, Client_ID( Client ), Name ); | ||||
| 	chan = Channel_Search(Name); | ||||
| 	if (!chan) { | ||||
| 		IRC_WriteStrClient(Client, ERR_NOSUCHCHANNEL_MSG, | ||||
| 				   Client_ID(Client), Name); | ||||
| 		return false; | ||||
| 	} | ||||
| 	if (!Get_Cl2Chan(chan, Client)) { | ||||
| 		IRC_WriteStrClient(Client, ERR_NOTONCHANNEL_MSG, | ||||
| 				   Client_ID(Client), Name); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	/* User aus Channel entfernen */ | ||||
| 	if( ! Remove_Client( REMOVE_PART, chan, Client, Origin, Reason, true)) return false; | ||||
| 	else return true; | ||||
| 	if (!Remove_Client(REMOVE_PART, chan, Client, Origin, Reason, true)) | ||||
| 		return false; | ||||
| 	else | ||||
| 		return true; | ||||
| } /* Channel_Part */ | ||||
|  | ||||
|  | ||||
| @@ -214,7 +246,6 @@ Channel_Kick( CLIENT *Client, CLIENT *Origin, char *Name, char *Reason ) | ||||
| 	assert( Name != NULL ); | ||||
| 	assert( Reason != NULL ); | ||||
|  | ||||
| 	/* Channel suchen */ | ||||
| 	chan = Channel_Search( Name ); | ||||
| 	if( ! chan ) | ||||
| 	{ | ||||
| @@ -266,11 +297,11 @@ Channel_Quit( CLIENT *Client, char *Reason ) | ||||
| } /* Channel_Quit */ | ||||
|  | ||||
|  | ||||
| GLOBAL long | ||||
| GLOBAL unsigned long | ||||
| Channel_Count( void ) | ||||
| { | ||||
| 	CHANNEL *c; | ||||
| 	long count = 0; | ||||
| 	unsigned long count = 0; | ||||
| 	 | ||||
| 	c = My_Channels; | ||||
| 	while( c ) | ||||
| @@ -282,11 +313,11 @@ Channel_Count( void ) | ||||
| } /* Channel_Count */ | ||||
|  | ||||
|  | ||||
| GLOBAL long | ||||
| GLOBAL unsigned long | ||||
| Channel_MemberCount( CHANNEL *Chan ) | ||||
| { | ||||
| 	CL2CHAN *cl2chan; | ||||
| 	long count = 0; | ||||
| 	unsigned long count = 0; | ||||
|  | ||||
| 	assert( Chan != NULL ); | ||||
|  | ||||
| @@ -321,27 +352,9 @@ Channel_CountForUser( CLIENT *Client ) | ||||
| } /* Channel_CountForUser */ | ||||
|  | ||||
|  | ||||
| GLOBAL int | ||||
| Channel_PCount( void ) | ||||
| { | ||||
| 	/* Count the number of persistent (mode 'P') channels */ | ||||
|  | ||||
| 	CHANNEL *chan; | ||||
| 	int count = 0; | ||||
|  | ||||
| 	chan = My_Channels; | ||||
| 	while( chan ) | ||||
| 	{ | ||||
| 		if( strchr( chan->modes, 'P' )) count++; | ||||
| 		chan = chan->next; | ||||
| 	} | ||||
|  | ||||
| 	return count; | ||||
| } /* Channel_PCount */ | ||||
|  | ||||
|  | ||||
| GLOBAL char * | ||||
| Channel_Name( CHANNEL *Chan ) | ||||
| GLOBAL const char * | ||||
| Channel_Name( const CHANNEL *Chan ) | ||||
| { | ||||
| 	assert( Chan != NULL ); | ||||
| 	return Chan->name; | ||||
| @@ -364,7 +377,7 @@ Channel_Key( CHANNEL *Chan ) | ||||
| } /* Channel_Key */ | ||||
|  | ||||
|  | ||||
| GLOBAL long | ||||
| GLOBAL unsigned long | ||||
| Channel_MaxUsers( CHANNEL *Chan ) | ||||
| { | ||||
| 	assert( Chan != NULL ); | ||||
| @@ -388,7 +401,7 @@ Channel_Next( CHANNEL *Chan ) | ||||
|  | ||||
|  | ||||
| GLOBAL CHANNEL * | ||||
| Channel_Search( char *Name ) | ||||
| Channel_Search( const char *Name ) | ||||
| { | ||||
| 	/* Channel-Struktur suchen */ | ||||
| 	 | ||||
| @@ -463,25 +476,13 @@ Channel_GetChannel( CL2CHAN *Cl2Chan ) | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Channel_IsValidName( char *Name ) | ||||
| Channel_IsValidName( const char *Name ) | ||||
| { | ||||
| 	/* Pruefen, ob Name als Channelname gueltig */ | ||||
|  | ||||
| 	char *ptr, badchars[10]; | ||||
| 	 | ||||
| 	assert( Name != NULL ); | ||||
|  | ||||
| 	if(( Name[0] != '#' ) || ( strlen( Name ) >= CHANNEL_NAME_LEN )) return false; | ||||
|  | ||||
| 	ptr = Name; | ||||
| 	strcpy( badchars, " ,:\007" ); | ||||
| 	while( *ptr ) | ||||
| 	{ | ||||
| 		if( strchr( badchars, *ptr )) return false; | ||||
| 		ptr++; | ||||
| 	} | ||||
| 	 | ||||
| 	return true; | ||||
| 	return Name[strcspn(Name, " ,:\007")] == 0; | ||||
| } /* Channel_IsValidName */ | ||||
|  | ||||
|  | ||||
| @@ -548,7 +549,7 @@ Channel_UserModeAdd( CHANNEL *Chan, CLIENT *Client, char Mode ) | ||||
|  | ||||
| 	cl2chan = Get_Cl2Chan( Chan, Client ); | ||||
| 	assert( cl2chan != NULL ); | ||||
| 	 | ||||
|  | ||||
| 	x[0] = Mode; x[1] = '\0'; | ||||
| 	if( ! strchr( cl2chan->modes, x[0] )) | ||||
| 	{ | ||||
| @@ -594,7 +595,7 @@ GLOBAL char * | ||||
| Channel_UserModes( CHANNEL *Chan, CLIENT *Client ) | ||||
| { | ||||
| 	/* return Users' Channel-Modes */ | ||||
| 	 | ||||
|  | ||||
| 	CL2CHAN *cl2chan; | ||||
|  | ||||
| 	assert( Chan != NULL ); | ||||
| @@ -614,9 +615,7 @@ Channel_IsMemberOf( CHANNEL *Chan, CLIENT *Client ) | ||||
|  | ||||
| 	assert( Chan != NULL ); | ||||
| 	assert( Client != NULL ); | ||||
|  | ||||
| 	if( Get_Cl2Chan( Chan, Client )) return true; | ||||
| 	else return false; | ||||
| 	return Get_Cl2Chan(Chan, Client) != NULL; | ||||
| } /* Channel_IsMemberOf */ | ||||
|  | ||||
|  | ||||
| @@ -661,12 +660,9 @@ Channel_SetTopic(CHANNEL *Chan, CLIENT *Client, char *Topic) | ||||
| 	if (len < array_bytes(&Chan->topic)) | ||||
| 		array_free(&Chan->topic); | ||||
|  | ||||
| 	if (!array_copyb(&Chan->topic, Topic, len)) | ||||
| 	if (len >= COMMAND_LEN || !array_copyb(&Chan->topic, Topic, len+1)) | ||||
| 		Log(LOG_WARNING, "could not set new Topic \"%s\" on %s: %s", | ||||
| 					Topic, Chan->name, strerror(errno)); | ||||
|  | ||||
| 	array_cat0(&Chan->topic); | ||||
|  | ||||
| #ifndef STRICT_RFC | ||||
| 	Chan->topic_time = time(NULL); | ||||
| 	if (Client != NULL && Client_Type(Client) != CLIENT_SERVER) | ||||
| @@ -698,52 +694,80 @@ Channel_SetKey( CHANNEL *Chan, char *Key ) | ||||
| 	assert( Key != NULL ); | ||||
|  | ||||
| 	strlcpy( Chan->key, Key, sizeof( Chan->key )); | ||||
| 	Log( LOG_DEBUG, "Channel %s: Key is now \"%s\".", Chan->name, Chan->key ); | ||||
| 	LogDebug("Channel %s: Key is now \"%s\".", Chan->name, Chan->key ); | ||||
| } /* Channel_SetKey */ | ||||
|  | ||||
|  | ||||
| GLOBAL void | ||||
| Channel_SetMaxUsers( CHANNEL *Chan, long Count ) | ||||
| Channel_SetMaxUsers(CHANNEL *Chan, unsigned long Count) | ||||
| { | ||||
| 	assert( Chan != NULL ); | ||||
|  | ||||
| 	Chan->maxusers = Count; | ||||
| 	Log( LOG_DEBUG, "Channel %s: Member limit is now %ld.", Chan->name, Chan->maxusers ); | ||||
| 	LogDebug("Channel %s: Member limit is now %lu.", Chan->name, Chan->maxusers ); | ||||
| } /* Channel_SetMaxUsers */ | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Channel_Write( CHANNEL *Chan, CLIENT *From, CLIENT *Client, char *Text ) | ||||
| static bool | ||||
| Can_Send_To_Channel(CHANNEL *Chan, CLIENT *From) | ||||
| { | ||||
| 	bool is_member, has_voice, is_op, ok; | ||||
| 	bool is_member, has_voice, is_op; | ||||
|  | ||||
| 	/* Okay, target is a channel */ | ||||
| 	is_member = has_voice = is_op = false; | ||||
| 	if( Channel_IsMemberOf( Chan, From )) | ||||
| 	{ | ||||
|  | ||||
| 	if (Channel_IsMemberOf(Chan, From)) { | ||||
| 		is_member = true; | ||||
| 		if( strchr( Channel_UserModes( Chan, From ), 'v' )) has_voice = true; | ||||
| 		if( strchr( Channel_UserModes( Chan, From ), 'o' )) is_op = true; | ||||
| 		if (strchr(Channel_UserModes(Chan, From), 'v')) | ||||
| 			has_voice = true; | ||||
| 		if (strchr(Channel_UserModes(Chan, From), 'o')) | ||||
| 			is_op = true; | ||||
| 	} | ||||
|  | ||||
| 	/* Is the client allowed to write to channel? */ | ||||
| 	ok = true; | ||||
| 	if( strchr( Channel_Modes( Chan ), 'n' ) && ( ! is_member )) ok = false; | ||||
| 	if( strchr( Channel_Modes( Chan ), 'm' ) && ( ! is_op ) && ( ! has_voice )) ok = false; | ||||
| 	 | ||||
| 	/* Is the client banned? */ | ||||
| 	if( Lists_CheckBanned( From, Chan )) | ||||
| 	{ | ||||
| 		/* Client is banned, but is he channel operator or has voice? */ | ||||
| 		if(( ! has_voice ) && ( ! is_op )) ok = false; | ||||
| 	} | ||||
| 	/* | ||||
| 	 * Is the client allowed to write to channel? | ||||
| 	 * | ||||
| 	 * If channel mode n set: non-members cannot send to channel. | ||||
| 	 * If channel mode m set: need voice. | ||||
| 	 */ | ||||
| 	if (strchr(Channel_Modes(Chan), 'n') && !is_member) | ||||
| 		return false; | ||||
|  | ||||
| 	if( ! ok ) return IRC_WriteStrClient( From, ERR_CANNOTSENDTOCHAN_MSG, Client_ID( From ), Channel_Name( Chan )); | ||||
| 	if (is_op || has_voice) | ||||
| 		return true; | ||||
|  | ||||
| 	/* Send text */ | ||||
| 	if( Client_Conn( From ) > NONE ) Conn_UpdateIdle( Client_Conn( From )); | ||||
| 	return IRC_WriteStrChannelPrefix( Client, Chan, From, true, "PRIVMSG %s :%s", Channel_Name( Chan ), Text ); | ||||
| } /* Channel_Write */ | ||||
| 	if (strchr(Channel_Modes(Chan), 'm')) | ||||
| 		return false; | ||||
|  | ||||
| 	return !Lists_Check(&Chan->list_bans, From); | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Channel_Write(CHANNEL *Chan, CLIENT *From, CLIENT *Client, const char *Text) | ||||
| { | ||||
| 	if (!Can_Send_To_Channel(Chan, From)) | ||||
| 		return IRC_WriteStrClient(From, ERR_CANNOTSENDTOCHAN_MSG, Client_ID(From), Channel_Name(Chan)); | ||||
|  | ||||
| 	if (Client_Conn(From) > NONE) | ||||
| 		Conn_UpdateIdle(Client_Conn(From)); | ||||
|  | ||||
| 	return IRC_WriteStrChannelPrefix(Client, Chan, From, true, | ||||
| 			"PRIVMSG %s :%s", Channel_Name(Chan), Text); | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Channel_Notice(CHANNEL *Chan, CLIENT *From, CLIENT *Client, const char *Text) | ||||
| { | ||||
| 	if (!Can_Send_To_Channel(Chan, From)) | ||||
| 		return true; /* no error, see RFC 2812 */ | ||||
|  | ||||
| 	if (Client_Conn(From) > NONE) | ||||
| 		Conn_UpdateIdle(Client_Conn(From)); | ||||
|  | ||||
| 	return IRC_WriteStrChannelPrefix(Client, Chan, From, true, | ||||
| 			"NOTICE %s :%s", Channel_Name(Chan), Text); | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL CHANNEL * | ||||
| @@ -753,7 +777,7 @@ Channel_Create( char *Name ) | ||||
| 	CHANNEL *c; | ||||
|  | ||||
| 	assert( Name != NULL ); | ||||
| 	 | ||||
|  | ||||
| 	c = (CHANNEL *)malloc( sizeof( CHANNEL )); | ||||
| 	if( ! c ) | ||||
| 	{ | ||||
| @@ -765,9 +789,7 @@ Channel_Create( char *Name ) | ||||
| 	c->hash = Hash( c->name ); | ||||
| 	c->next = My_Channels; | ||||
| 	My_Channels = c; | ||||
| #ifdef DEBUG	 | ||||
| 	Log( LOG_DEBUG, "Created new channel structure for \"%s\".", Name ); | ||||
| #endif | ||||
| 	LogDebug("Created new channel structure for \"%s\".", Name); | ||||
| 	return c; | ||||
| } /* Channel_Create */ | ||||
|  | ||||
| @@ -820,7 +842,7 @@ Add_Client( CHANNEL *Chan, CLIENT *Client ) | ||||
|  | ||||
|  | ||||
| static bool | ||||
| Remove_Client( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, char *Reason, bool InformServer ) | ||||
| Remove_Client( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, const char *Reason, bool InformServer ) | ||||
| { | ||||
| 	CL2CHAN *cl2chan, *last_cl2chan; | ||||
| 	CHANNEL *c; | ||||
| @@ -851,25 +873,42 @@ Remove_Client( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, char *Re | ||||
| 	switch( Type ) | ||||
| 	{ | ||||
| 		case REMOVE_QUIT: | ||||
| 			/* QUIT: andere Server wurden bereits informiert, vgl. Client_Destroy(); | ||||
| 			 * hier also "nur" noch alle User in betroffenen Channeln infomieren */ | ||||
| 			/* QUIT: other servers have already been notified, see Client_Destroy(); | ||||
| 			 * so only inform other clients in same channel. */ | ||||
| 			assert( InformServer == false ); | ||||
| 			Log( LOG_DEBUG, "User \"%s\" left channel \"%s\" (%s).", Client_Mask( Client ), c->name, Reason ); | ||||
| 			LogDebug("User \"%s\" left channel \"%s\" (%s).", | ||||
| 					Client_Mask( Client ), c->name, Reason ); | ||||
| 			break; | ||||
| 		case REMOVE_KICK: | ||||
| 			/* User wurde geKICKed: ggf. andere Server sowie alle betroffenen User | ||||
| 			 * im entsprechenden Channel informieren */ | ||||
| 			if( InformServer ) IRC_WriteStrServersPrefix( Client_NextHop( Origin ), Origin, "KICK %s %s :%s", c->name, Client_ID( Client ), Reason ); | ||||
| 			IRC_WriteStrChannelPrefix( Client, c, Origin, false, "KICK %s %s :%s", c->name, Client_ID( Client ), Reason ); | ||||
| 			if(( Client_Conn( Client ) > NONE ) && ( Client_Type( Client ) == CLIENT_USER )) IRC_WriteStrClientPrefix( Client, Origin, "KICK %s %s :%s", c->name, Client_ID( Client ), Reason ); | ||||
| 			Log( LOG_DEBUG, "User \"%s\" has been kicked of \"%s\" by \"%s\": %s.", Client_Mask( Client ), c->name, Client_ID( Origin ), Reason ); | ||||
| 			/* User was KICKed: inform other servers and all users in channel */ | ||||
| 			if( InformServer ) | ||||
| 				IRC_WriteStrServersPrefix( Client_NextHop( Origin ), | ||||
| 					Origin, "KICK %s %s :%s", c->name, Client_ID( Client ), Reason); | ||||
| 			IRC_WriteStrChannelPrefix(Client, c, Origin, false, "KICK %s %s :%s", | ||||
| 							c->name, Client_ID( Client ), Reason ); | ||||
| 			if ((Client_Conn(Client) > NONE) && | ||||
| 					(Client_Type(Client) == CLIENT_USER)) | ||||
| 			{ | ||||
| 				IRC_WriteStrClientPrefix(Client, Origin, "KICK %s %s :%s", | ||||
| 								c->name, Client_ID( Client ), Reason); | ||||
| 			} | ||||
| 			LogDebug("User \"%s\" has been kicked of \"%s\" by \"%s\": %s.", | ||||
| 				Client_Mask( Client ), c->name, Client_ID(Origin), Reason); | ||||
| 			break; | ||||
| 		default: | ||||
| 			/* PART */ | ||||
| 			if( InformServer ) IRC_WriteStrServersPrefix( Origin, Client, "PART %s :%s", c->name, Reason ); | ||||
| 			IRC_WriteStrChannelPrefix( Origin, c, Client, false, "PART %s :%s", c->name, Reason ); | ||||
| 			if(( Client_Conn( Origin ) > NONE ) && ( Client_Type( Origin ) == CLIENT_USER )) IRC_WriteStrClientPrefix( Origin, Client, "PART %s :%s", c->name, Reason ); | ||||
| 			Log( LOG_DEBUG, "User \"%s\" left channel \"%s\" (%s).", Client_Mask( Client ), c->name, Reason ); | ||||
| 		default: /* PART */ | ||||
| 			if (InformServer) | ||||
| 				IRC_WriteStrServersPrefix(Origin, Client, "PART %s :%s", c->name, Reason); | ||||
|  | ||||
| 			IRC_WriteStrChannelPrefix(Origin, c, Client, false, "PART %s :%s", | ||||
| 									c->name, Reason); | ||||
|  | ||||
| 			if ((Client_Conn(Origin) > NONE) && | ||||
| 					(Client_Type(Origin) == CLIENT_USER)) | ||||
| 			{ | ||||
| 				IRC_WriteStrClientPrefix( Origin, Client, "PART %s :%s", c->name, Reason); | ||||
| 				LogDebug("User \"%s\" left channel \"%s\" (%s).", | ||||
| 					Client_Mask(Client), c->name, Reason); | ||||
| 			} | ||||
| 	} | ||||
|  | ||||
| 	/* Wenn Channel nun leer und nicht pre-defined: loeschen */ | ||||
| @@ -877,11 +916,73 @@ Remove_Client( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, char *Re | ||||
| 	{ | ||||
| 		if( ! Get_First_Cl2Chan( NULL, Chan )) Delete_Channel( Chan ); | ||||
| 	} | ||||
| 		 | ||||
|  | ||||
| 	return true; | ||||
| } /* Remove_Client */ | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Channel_AddBan(CHANNEL *c, const char *mask ) | ||||
| { | ||||
| 	struct list_head *h = Channel_GetListBans(c); | ||||
| 	return Lists_Add(h, mask, false); | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Channel_AddInvite(CHANNEL *c, const char *mask, bool onlyonce) | ||||
| { | ||||
| 	struct list_head *h = Channel_GetListInvites(c); | ||||
| 	return Lists_Add(h, mask, onlyonce); | ||||
| } | ||||
|  | ||||
|  | ||||
| static bool | ||||
| ShowInvitesBans(struct list_head *head, CLIENT *Client, CHANNEL *Channel, bool invite) | ||||
| { | ||||
| 	struct list_elem *e; | ||||
| 	char *msg = invite ? RPL_INVITELIST_MSG : RPL_BANLIST_MSG; | ||||
| 	char *msg_end; | ||||
|  | ||||
| 	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; | ||||
| 		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 )); | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Channel_ShowBans( CLIENT *Client, CHANNEL *Channel ) | ||||
| { | ||||
| 	struct list_head *h; | ||||
|  | ||||
| 	assert( Channel != NULL ); | ||||
|  | ||||
| 	h = Channel_GetListBans(Channel); | ||||
| 	return ShowInvitesBans(h, Client, Channel, false); | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Channel_ShowInvites( CLIENT *Client, CHANNEL *Channel ) | ||||
| { | ||||
| 	struct list_head *h; | ||||
|  | ||||
| 	assert( Channel != NULL ); | ||||
|  | ||||
| 	h = Channel_GetListInvites(Channel); | ||||
| 	return ShowInvitesBans(h, Client, Channel, true); | ||||
| } | ||||
|  | ||||
|  | ||||
| static CL2CHAN * | ||||
| Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan ) | ||||
| { | ||||
| @@ -911,7 +1012,7 @@ static bool | ||||
| Delete_Channel( CHANNEL *Chan ) | ||||
| { | ||||
| 	/* Channel-Struktur loeschen */ | ||||
| 	 | ||||
|  | ||||
| 	CHANNEL *chan, *last_chan; | ||||
|  | ||||
| 	last_chan = NULL; | ||||
| @@ -927,13 +1028,14 @@ Delete_Channel( CHANNEL *Chan ) | ||||
| 	Log( LOG_DEBUG, "Freed channel structure for \"%s\".", Chan->name ); | ||||
|  | ||||
| 	/* Invite- und Ban-Lists aufraeumen */ | ||||
| 	Lists_DeleteChannel( chan ); | ||||
| 	Lists_Free( &chan->list_bans ); | ||||
| 	Lists_Free( &chan->list_invites ); | ||||
|  | ||||
| 	/* Neu verketten und freigeben */ | ||||
| 	if( last_chan ) last_chan->next = chan->next; | ||||
| 	else My_Channels = chan->next; | ||||
| 	free( chan ); | ||||
| 		 | ||||
|  | ||||
| 	return true; | ||||
| } /* Delete_Channel */ | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: channel.h,v 1.29 2005/09/02 12:50:25 alex Exp $ | ||||
|  * $Id: channel.h,v 1.35 2008/02/05 16:31:35 fw Exp $ | ||||
|  * | ||||
|  * Channel management (header) | ||||
|  */ | ||||
| @@ -20,6 +20,7 @@ | ||||
|  | ||||
| #if defined(__channel_c__) | defined(S_SPLINT_S) | ||||
|  | ||||
| #include "lists.h" | ||||
| #include "defines.h" | ||||
| #include "array.h" | ||||
|  | ||||
| @@ -35,7 +36,9 @@ typedef struct _CHANNEL | ||||
| 	char topic_who[CLIENT_NICK_LEN];/* Nickname of user that set topic */ | ||||
| #endif | ||||
| 	char key[CLIENT_PASS_LEN];	/* Channel key ("password", mode "k" ) */ | ||||
| 	long maxusers;			/* Maximum number of members (mode "l") */ | ||||
| 	unsigned long maxusers;		/* Maximum number of members (mode "l") */ | ||||
| 	struct list_head list_bans;	/* list head of banned users */ | ||||
| 	struct list_head list_invites;	/* list head of invited users */ | ||||
| } CHANNEL; | ||||
|  | ||||
| typedef struct _CLIENT2CHAN | ||||
| @@ -53,35 +56,36 @@ typedef POINTER CL2CHAN; | ||||
|  | ||||
| #endif | ||||
|  | ||||
| GLOBAL struct list_head *Channel_GetListBans PARAMS((CHANNEL *c)); | ||||
| GLOBAL struct list_head *Channel_GetListInvites PARAMS((CHANNEL *c)); | ||||
|  | ||||
| GLOBAL void Channel_Init PARAMS(( void )); | ||||
| GLOBAL void Channel_InitPredefined PARAMS((  void )); | ||||
| GLOBAL void Channel_Exit PARAMS(( void )); | ||||
|  | ||||
| GLOBAL bool Channel_Join PARAMS(( CLIENT *Client, char *Name )); | ||||
| GLOBAL bool Channel_Part PARAMS(( CLIENT *Client, CLIENT *Origin, char *Name, char *Reason )); | ||||
| GLOBAL bool Channel_Part PARAMS(( CLIENT *Client, CLIENT *Origin, const char *Name, const char *Reason )); | ||||
|  | ||||
| GLOBAL void Channel_Quit PARAMS(( CLIENT *Client, char *Reason )); | ||||
|  | ||||
| GLOBAL void Channel_Kick PARAMS((  CLIENT *Client, CLIENT *Origin, char *Name, char *Reason )); | ||||
|  | ||||
| GLOBAL long Channel_Count PARAMS(( void )); | ||||
| GLOBAL long Channel_MemberCount PARAMS(( CHANNEL *Chan )); | ||||
| GLOBAL unsigned long Channel_Count PARAMS(( void )); | ||||
| GLOBAL unsigned long Channel_MemberCount PARAMS(( CHANNEL *Chan )); | ||||
| GLOBAL int Channel_CountForUser PARAMS(( CLIENT *Client )); | ||||
| GLOBAL int Channel_PCount PARAMS(( void )); | ||||
|  | ||||
| GLOBAL char *Channel_Name PARAMS(( CHANNEL *Chan )); | ||||
| GLOBAL const char *Channel_Name PARAMS(( const CHANNEL *Chan )); | ||||
| GLOBAL char *Channel_Modes PARAMS(( CHANNEL *Chan )); | ||||
| GLOBAL char *Channel_Topic PARAMS(( CHANNEL *Chan )); | ||||
| GLOBAL char *Channel_Key PARAMS(( CHANNEL *Chan )); | ||||
| GLOBAL long Channel_MaxUsers PARAMS(( CHANNEL *Chan )); | ||||
| GLOBAL unsigned long Channel_MaxUsers PARAMS(( CHANNEL *Chan )); | ||||
|  | ||||
| GLOBAL void Channel_SetTopic PARAMS(( CHANNEL *Chan, CLIENT *Client, char *Topic )); | ||||
| GLOBAL void Channel_SetModes PARAMS(( CHANNEL *Chan, char *Modes )); | ||||
| GLOBAL void Channel_SetKey PARAMS(( CHANNEL *Chan, char *Key )); | ||||
| GLOBAL void Channel_SetMaxUsers PARAMS(( CHANNEL *Chan, long Count )); | ||||
| GLOBAL void Channel_SetMaxUsers PARAMS(( CHANNEL *Chan, unsigned long Count )); | ||||
|  | ||||
| GLOBAL CHANNEL *Channel_Search PARAMS(( char *Name )); | ||||
| GLOBAL CHANNEL *Channel_Search PARAMS(( const char *Name )); | ||||
|  | ||||
| GLOBAL CHANNEL *Channel_First PARAMS(( void )); | ||||
| GLOBAL CHANNEL *Channel_Next PARAMS(( CHANNEL *Chan )); | ||||
| @@ -94,7 +98,7 @@ GLOBAL CL2CHAN *Channel_NextChannelOf PARAMS(( CLIENT *Client, CL2CHAN *Cl2Chan | ||||
| GLOBAL CLIENT *Channel_GetClient PARAMS(( CL2CHAN *Cl2Chan )); | ||||
| GLOBAL CHANNEL *Channel_GetChannel PARAMS(( CL2CHAN *Cl2Chan )); | ||||
|  | ||||
| GLOBAL bool Channel_IsValidName PARAMS(( char *Name )); | ||||
| GLOBAL bool Channel_IsValidName PARAMS(( const char *Name )); | ||||
|  | ||||
| GLOBAL bool Channel_ModeAdd PARAMS(( CHANNEL *Chan, char Mode )); | ||||
| GLOBAL bool Channel_ModeDel PARAMS(( CHANNEL *Chan, char Mode )); | ||||
| @@ -105,7 +109,8 @@ GLOBAL char *Channel_UserModes PARAMS(( CHANNEL *Chan, CLIENT *Client )); | ||||
|  | ||||
| GLOBAL bool Channel_IsMemberOf PARAMS(( CHANNEL *Chan, CLIENT *Client )); | ||||
|  | ||||
| GLOBAL bool Channel_Write PARAMS(( CHANNEL *Chan, CLIENT *From, CLIENT *Client, char *Text )); | ||||
| GLOBAL bool Channel_Write PARAMS(( CHANNEL *Chan, CLIENT *From, CLIENT *Client, const char *Text )); | ||||
| GLOBAL bool Channel_Notice PARAMS(( CHANNEL *Chan, CLIENT *From, CLIENT *Client, const char *Text)); | ||||
|  | ||||
| GLOBAL CHANNEL *Channel_Create PARAMS(( char *Name )); | ||||
|  | ||||
| @@ -114,8 +119,10 @@ GLOBAL unsigned int Channel_TopicTime PARAMS(( CHANNEL *Chan )); | ||||
| GLOBAL char *Channel_TopicWho 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_ShowBans PARAMS((CLIENT *client, CHANNEL *c)); | ||||
| GLOBAL bool Channel_ShowInvites PARAMS((CLIENT *client, CHANNEL *c)); | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /* -eof- */ | ||||
|   | ||||
| @@ -17,7 +17,7 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: client.c,v 1.91 2006/04/23 10:37:27 fw Exp $"; | ||||
| static char UNUSED id[] = "$Id: client.c,v 1.98 2008/04/04 19:30:01 fw Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| @@ -55,10 +55,11 @@ static char GetID_Buffer[GETID_LEN]; | ||||
|  | ||||
| static WHOWAS My_Whowas[MAX_WHOWAS]; | ||||
| static int Last_Whowas = -1; | ||||
| static long Max_Users, My_Max_Users; | ||||
|  | ||||
|  | ||||
| static long Count PARAMS(( CLIENT_TYPE Type )); | ||||
| static long MyCount PARAMS(( CLIENT_TYPE Type )); | ||||
| static unsigned long Count PARAMS(( CLIENT_TYPE Type )); | ||||
| static unsigned long MyCount PARAMS(( CLIENT_TYPE Type )); | ||||
|  | ||||
| static CLIENT *New_Client_Struct PARAMS(( void )); | ||||
| static void Generate_MyToken PARAMS(( CLIENT *Client )); | ||||
| @@ -68,13 +69,6 @@ static CLIENT *Init_New_Client PARAMS((CONN_ID Idx, CLIENT *Introducer, | ||||
|  CLIENT *TopServer, int Type, char *ID, char *User, char *Hostname, | ||||
|  char *Info, int Hops, int Token, char *Modes, bool Idented)); | ||||
|  | ||||
| #ifndef Client_DestroyNow | ||||
| GLOBAL void Client_DestroyNow PARAMS((CLIENT *Client )); | ||||
| #endif | ||||
|  | ||||
|  | ||||
| long Max_Users = 0, My_Max_Users = 0; | ||||
|  | ||||
|  | ||||
| GLOBAL void | ||||
| Client_Init( void ) | ||||
| @@ -98,9 +92,10 @@ Client_Init( void ) | ||||
| 	This_Server->hops = 0; | ||||
|  | ||||
| 	gethostname( This_Server->host, CLIENT_HOST_LEN ); | ||||
| 	h = gethostbyname( This_Server->host ); | ||||
| 	if( h ) strlcpy( This_Server->host, h->h_name, sizeof( This_Server->host )); | ||||
|  | ||||
| 	if (!Conf_NoDNS) { | ||||
| 		h = gethostbyname( This_Server->host ); | ||||
| 		if (h) strlcpy(This_Server->host, h->h_name, sizeof(This_Server->host)); | ||||
| 	} | ||||
| 	Client_SetID( This_Server, Conf_ServerName ); | ||||
| 	Client_SetInfo( This_Server, Conf_ServerInfo ); | ||||
|  | ||||
| @@ -211,8 +206,8 @@ Init_New_Client(CONN_ID Idx, CLIENT *Introducer, CLIENT *TopServer, | ||||
| 	if( Modes ) Client_SetModes( client, Modes ); | ||||
| 	if( Type == CLIENT_SERVER ) Generate_MyToken( client ); | ||||
|  | ||||
| 	/* ist der User away? */ | ||||
| 	if( strchr( client->modes, 'a' )) strlcpy( client->away, DEFAULT_AWAY_MSG, sizeof( client->away )); | ||||
| 	if( strchr( client->modes, 'a' )) | ||||
| 		strlcpy( client->away, DEFAULT_AWAY_MSG, sizeof( client->away )); | ||||
|  | ||||
| 	/* Verketten */ | ||||
| 	client->next = (POINTER *)My_Clients; | ||||
| @@ -336,43 +331,14 @@ Client_Destroy( CLIENT *Client, char *LogMsg, char *FwdMsg, bool SendQuit ) | ||||
| } /* Client_Destroy */ | ||||
|  | ||||
|  | ||||
| GLOBAL void | ||||
| Client_DestroyNow( CLIENT *Client ) | ||||
| { | ||||
| 	/* Destroy client structure immediately. This function is only | ||||
| 	 * intended for the connection layer to remove client structures | ||||
| 	 * of connections that can't be established! */ | ||||
|  | ||||
| 	CLIENT *last, *c; | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
|  | ||||
| 	last = NULL; | ||||
| 	c = My_Clients; | ||||
| 	while( c ) | ||||
| 	{ | ||||
| 		if( c == Client ) | ||||
| 		{ | ||||
| 			/* Wir haben den Client gefunden: entfernen */ | ||||
| 			if( last ) last->next = c->next; | ||||
| 			else My_Clients = (CLIENT *)c->next; | ||||
| 			free( c ); | ||||
| 			break; | ||||
| 		} | ||||
| 		last = c; | ||||
| 		c = (CLIENT *)c->next; | ||||
| 	} | ||||
| } /* Client_DestroyNow */ | ||||
|  | ||||
|  | ||||
| GLOBAL void | ||||
| Client_SetHostname( CLIENT *Client, char *Hostname ) | ||||
| { | ||||
| 	/* Hostname eines Clients setzen */ | ||||
| 	 | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Hostname != NULL ); | ||||
| 	 | ||||
|  | ||||
| 	strlcpy( Client->host, Hostname, sizeof( Client->host )); | ||||
| } /* Client_SetHostname */ | ||||
|  | ||||
| @@ -399,7 +365,7 @@ Client_SetUser( CLIENT *Client, char *User, bool Idented ) | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( User != NULL ); | ||||
| 	 | ||||
|  | ||||
| 	if( Idented ) strlcpy( Client->user, User, sizeof( Client->user )); | ||||
| 	else | ||||
| 	{ | ||||
| @@ -416,7 +382,7 @@ Client_SetInfo( CLIENT *Client, char *Info ) | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Info != NULL ); | ||||
| 	 | ||||
|  | ||||
| 	strlcpy( Client->info, Info, sizeof( Client->info )); | ||||
| } /* Client_SetInfo */ | ||||
|  | ||||
| @@ -452,7 +418,7 @@ Client_SetPassword( CLIENT *Client, char *Pwd ) | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Pwd != NULL ); | ||||
| 	 | ||||
|  | ||||
| 	strlcpy( Client->pwd, Pwd, sizeof( Client->pwd )); | ||||
| } /* Client_SetPassword */ | ||||
|  | ||||
| @@ -522,7 +488,7 @@ Client_ModeAdd( CLIENT *Client, char Mode ) | ||||
| 	 */ | ||||
|  | ||||
| 	char x[2]; | ||||
| 	 | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
|  | ||||
| 	x[0] = Mode; x[1] = '\0'; | ||||
| @@ -641,7 +607,8 @@ Client_ID( CLIENT *Client ) | ||||
| 	assert( Client != NULL ); | ||||
|  | ||||
| #ifdef DEBUG | ||||
| 	if( Client->type == CLIENT_USER ) assert( strlen( Client->id ) < CLIENT_NICK_LEN ); | ||||
| 	if(Client->type == CLIENT_USER) | ||||
| 		assert(strlen(Client->id) < Conf_MaxNickLength); | ||||
| #endif | ||||
| 						    | ||||
| 	if( Client->id[0] ) return Client->id; | ||||
| @@ -661,8 +628,7 @@ GLOBAL char * | ||||
| Client_User( CLIENT *Client ) | ||||
| { | ||||
| 	assert( Client != NULL ); | ||||
| 	if( Client->user[0] ) return Client->user; | ||||
| 	else return "~"; | ||||
| 	return Client->user[0] ? Client->user : "~"; | ||||
| } /* Client_User */ | ||||
|  | ||||
|  | ||||
| @@ -734,11 +700,13 @@ GLOBAL CLIENT * | ||||
| Client_NextHop( CLIENT *Client ) | ||||
| { | ||||
| 	CLIENT *c; | ||||
| 	 | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
|  | ||||
| 	c = Client; | ||||
| 	while( c->introducer && ( c->introducer != c ) && ( c->introducer != This_Server )) c = c->introducer; | ||||
| 	while( c->introducer && ( c->introducer != c ) && ( c->introducer != This_Server )) | ||||
| 		c = c->introducer; | ||||
|  | ||||
| 	return c; | ||||
| } /* Client_NextHop */ | ||||
|  | ||||
| @@ -750,7 +718,7 @@ Client_Mask( CLIENT *Client ) | ||||
| 	 * Prefixe benoetigt wird. */ | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	 | ||||
|  | ||||
| 	if( Client->type == CLIENT_SERVER ) return Client->id; | ||||
|  | ||||
| 	snprintf( GetID_Buffer, GETID_LEN, "%s!%s@%s", Client->id, Client->user, Client->host ); | ||||
| @@ -795,12 +763,9 @@ Client_Away( CLIENT *Client ) | ||||
| GLOBAL bool | ||||
| Client_CheckNick( CLIENT *Client, char *Nick ) | ||||
| { | ||||
| 	/* Nick ueberpruefen */ | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Nick != NULL ); | ||||
| 	 | ||||
| 	/* Nick ungueltig? */ | ||||
|  | ||||
| 	if( ! Client_IsValidNick( Nick )) | ||||
| 	{ | ||||
| 		IRC_WriteStrClient( Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID( Client ), Nick ); | ||||
| @@ -913,13 +878,12 @@ Client_MyServiceCount( void ) | ||||
| } /* Client_MyServiceCount */ | ||||
|  | ||||
|  | ||||
| GLOBAL long | ||||
| GLOBAL unsigned long | ||||
| Client_MyServerCount( void ) | ||||
| { | ||||
| 	CLIENT *c; | ||||
| 	long cnt; | ||||
| 	unsigned long cnt = 0; | ||||
|  | ||||
| 	cnt = 0; | ||||
| 	c = My_Clients; | ||||
| 	while( c ) | ||||
| 	{ | ||||
| @@ -930,13 +894,12 @@ Client_MyServerCount( void ) | ||||
| } /* Client_MyServerCount */ | ||||
|  | ||||
|  | ||||
| GLOBAL long | ||||
| GLOBAL unsigned long | ||||
| Client_OperCount( void ) | ||||
| { | ||||
| 	CLIENT *c; | ||||
| 	long cnt; | ||||
| 	unsigned long cnt = 0; | ||||
|  | ||||
| 	cnt = 0; | ||||
| 	c = My_Clients; | ||||
| 	while( c ) | ||||
| 	{ | ||||
| @@ -947,19 +910,19 @@ Client_OperCount( void ) | ||||
| } /* Client_OperCount */ | ||||
|  | ||||
|  | ||||
| GLOBAL long | ||||
| GLOBAL unsigned long | ||||
| Client_UnknownCount( void ) | ||||
| { | ||||
| 	CLIENT *c; | ||||
| 	long cnt; | ||||
| 	unsigned long cnt = 0; | ||||
|  | ||||
| 	cnt = 0; | ||||
| 	c = My_Clients; | ||||
| 	while( c ) | ||||
| 	{ | ||||
| 		if( c && ( c->type != CLIENT_USER ) && ( c->type != CLIENT_SERVICE ) && ( c->type != CLIENT_SERVER )) cnt++; | ||||
| 		c = (CLIENT *)c->next; | ||||
| 	} | ||||
|  | ||||
| 	return cnt; | ||||
| } /* Client_UnknownCount */ | ||||
|  | ||||
| @@ -979,28 +942,25 @@ Client_MyMaxUserCount( void ) | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Client_IsValidNick( char *Nick ) | ||||
| Client_IsValidNick( const char *Nick ) | ||||
| { | ||||
| 	/* Ist der Nick gueltig? */ | ||||
| 	const char *ptr; | ||||
| 	static const char goodchars[] = ";0123456789-"; | ||||
|  | ||||
| 	char *ptr, goodchars[20]; | ||||
| 	 | ||||
| 	assert( Nick != NULL ); | ||||
|  | ||||
| 	strcpy( goodchars, ";0123456789-" ); | ||||
|  | ||||
| 	if( Nick[0] == '#' ) return false; | ||||
| 	if( strchr( goodchars, Nick[0] )) return false; | ||||
| 	if( strlen( Nick ) >= CLIENT_NICK_LEN ) return false; | ||||
| 	if( strlen( Nick ) >= Conf_MaxNickLength) return false; | ||||
|  | ||||
| 	ptr = Nick; | ||||
| 	while( *ptr ) | ||||
| 	{ | ||||
| 		if(( *ptr < 'A' ) && ( ! strchr( goodchars, *ptr ))) return false; | ||||
| 		if(( *ptr > '}' ) && ( ! strchr( goodchars, *ptr ))) return false; | ||||
| 		if (( *ptr < 'A' ) && ( ! strchr( goodchars, *ptr ))) return false; | ||||
| 		if ( *ptr > '}' ) return false; | ||||
| 		ptr++; | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	return true; | ||||
| } /* Client_IsValidNick */ | ||||
|  | ||||
| @@ -1037,13 +997,12 @@ Client_StartTime(CLIENT *Client) | ||||
| } /* Client_Uptime */ | ||||
|  | ||||
|  | ||||
| static long | ||||
| static unsigned long | ||||
| Count( CLIENT_TYPE Type ) | ||||
| { | ||||
| 	CLIENT *c; | ||||
| 	long cnt; | ||||
| 	unsigned long cnt = 0; | ||||
|  | ||||
| 	cnt = 0; | ||||
| 	c = My_Clients; | ||||
| 	while( c ) | ||||
| 	{ | ||||
| @@ -1054,13 +1013,12 @@ Count( CLIENT_TYPE Type ) | ||||
| } /* Count */ | ||||
|  | ||||
|  | ||||
| static long | ||||
| static unsigned long | ||||
| MyCount( CLIENT_TYPE Type ) | ||||
| { | ||||
| 	CLIENT *c; | ||||
| 	long cnt; | ||||
| 	unsigned long cnt = 0; | ||||
|  | ||||
| 	cnt = 0; | ||||
| 	c = My_Clients; | ||||
| 	while( c ) | ||||
| 	{ | ||||
| @@ -1075,9 +1033,9 @@ static CLIENT * | ||||
| New_Client_Struct( void ) | ||||
| { | ||||
| 	/* Neue CLIENT-Struktur pre-initialisieren */ | ||||
| 	 | ||||
|  | ||||
| 	CLIENT *c; | ||||
| 	 | ||||
|  | ||||
| 	c = (CLIENT *)malloc( sizeof( CLIENT )); | ||||
| 	if( ! c ) | ||||
| 	{ | ||||
| @@ -1130,7 +1088,7 @@ Adjust_Counters( CLIENT *Client ) | ||||
| 	assert( Client != NULL ); | ||||
|  | ||||
| 	if( Client->type != CLIENT_USER ) return; | ||||
| 	 | ||||
|  | ||||
| 	if( Client->conn_id != NONE ) | ||||
| 	{ | ||||
| 		/* Local connection */ | ||||
| @@ -1153,7 +1111,7 @@ Client_RegisterWhowas( CLIENT *Client ) | ||||
| { | ||||
| 	int slot; | ||||
| 	time_t now; | ||||
| 	 | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
|  | ||||
| 	now = time(NULL); | ||||
| @@ -1167,7 +1125,7 @@ Client_RegisterWhowas( CLIENT *Client ) | ||||
| #ifdef DEBUG | ||||
| 	Log( LOG_DEBUG, "Saving WHOWAS information to slot %d ...", slot ); | ||||
| #endif | ||||
| 	 | ||||
|  | ||||
| 	My_Whowas[slot].time = now; | ||||
| 	strlcpy( My_Whowas[slot].id, Client_ID( Client ), | ||||
| 		 sizeof( My_Whowas[slot].id )); | ||||
| @@ -1179,7 +1137,7 @@ Client_RegisterWhowas( CLIENT *Client ) | ||||
| 		 sizeof( My_Whowas[slot].info )); | ||||
| 	strlcpy( My_Whowas[slot].server, Client_ID( Client_Introducer( Client )), | ||||
| 		 sizeof( My_Whowas[slot].server )); | ||||
| 	 | ||||
|  | ||||
| 	Last_Whowas = slot; | ||||
| } /* Client_RegisterWhowas */ | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: client.h,v 1.42 2006/04/23 10:37:27 fw Exp $ | ||||
|  * $Id: client.h,v 1.46 2007/01/23 16:07:19 alex Exp $ | ||||
|  * | ||||
|  * Client management (header) | ||||
|  */ | ||||
| @@ -23,10 +23,9 @@ | ||||
| #define CLIENT_GOTNICK 4		/* client did send NICK */ | ||||
| #define CLIENT_GOTUSER 8		/* client did send USER */ | ||||
| #define CLIENT_USER 16			/* client is an IRC user */ | ||||
| #define CLIENT_UNKNOWNSERVER 32		/* unregistered server connection */ | ||||
| #define CLIENT_GOTPASSSERVER 64		/* client did send PASS in "server style" */ | ||||
| #define CLIENT_SERVER 128		/* client is a server */ | ||||
| #define CLIENT_SERVICE 256		/* client is a service */ | ||||
| #define CLIENT_SERVER 32		/* client is a server */ | ||||
| #define CLIENT_SERVICE 64		/* client is a service */ | ||||
| #define CLIENT_UNKNOWNSERVER 128	/* unregistered server connection */ | ||||
|  | ||||
| #define CLIENT_TYPE int | ||||
|  | ||||
| @@ -81,9 +80,6 @@ GLOBAL CLIENT *Client_NewRemoteServer PARAMS(( CLIENT *Introducer, char *Hostnam | ||||
| GLOBAL CLIENT *Client_NewRemoteUser PARAMS(( CLIENT *Introducer, char *Nick, int Hops, char *User, char *Hostname, int Token, char *Modes, char *Info, bool Idented )); | ||||
|  | ||||
| GLOBAL void Client_Destroy PARAMS(( CLIENT *Client, char *LogMsg, char *FwdMsg, bool SendQuit )); | ||||
| #ifdef CONN_MODULE | ||||
| GLOBAL void Client_DestroyNow PARAMS(( CLIENT *Client )); | ||||
| #endif | ||||
|  | ||||
| GLOBAL CLIENT *Client_ThisServer PARAMS(( void )); | ||||
|  | ||||
| @@ -138,15 +134,15 @@ GLOBAL bool Client_CheckID PARAMS(( CLIENT *Client, char *ID )); | ||||
| GLOBAL long Client_UserCount PARAMS(( void )); | ||||
| GLOBAL long Client_ServiceCount PARAMS(( void )); | ||||
| GLOBAL long Client_ServerCount PARAMS(( void )); | ||||
| GLOBAL long Client_OperCount PARAMS(( void )); | ||||
| GLOBAL long Client_UnknownCount PARAMS(( void )); | ||||
| GLOBAL unsigned long Client_OperCount PARAMS(( void )); | ||||
| GLOBAL unsigned long Client_UnknownCount PARAMS(( void )); | ||||
| GLOBAL long Client_MyUserCount PARAMS(( void )); | ||||
| GLOBAL long Client_MyServiceCount PARAMS(( void )); | ||||
| GLOBAL long Client_MyServerCount PARAMS(( void )); | ||||
| GLOBAL unsigned long Client_MyServerCount PARAMS(( void )); | ||||
| GLOBAL long Client_MaxUserCount PARAMS((  void )); | ||||
| GLOBAL long Client_MyMaxUserCount PARAMS((  void )); | ||||
|  | ||||
| GLOBAL bool Client_IsValidNick PARAMS(( char *Nick )); | ||||
| GLOBAL bool Client_IsValidNick PARAMS(( const char *Nick )); | ||||
|  | ||||
| GLOBAL WHOWAS *Client_GetWhowas PARAMS(( void )); | ||||
| GLOBAL int Client_GetLastWhowasIndex PARAMS(( void )); | ||||
|   | ||||
| @@ -14,7 +14,7 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: conf.c,v 1.92 2006/07/23 16:42:45 alex Exp $"; | ||||
| static char UNUSED id[] = "$Id: conf.c,v 1.105 2008/03/18 20:12:47 fw Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| @@ -57,7 +57,7 @@ static int New_Server_Idx; | ||||
|  | ||||
|  | ||||
| static void Set_Defaults PARAMS(( bool InitServers )); | ||||
| static void Read_Config PARAMS(( void )); | ||||
| static bool Read_Config PARAMS(( bool ngircd_starting )); | ||||
| static void Validate_Config PARAMS(( bool TestOnly, bool Rehash )); | ||||
|  | ||||
| static void Handle_GLOBAL PARAMS(( int Line, char *Var, char *Arg )); | ||||
| @@ -134,21 +134,33 @@ ports_parse(array *a, int Line, char *Arg) | ||||
| GLOBAL void | ||||
| Conf_Init( void ) | ||||
| { | ||||
| 	Set_Defaults( true ); | ||||
| 	Read_Config( ); | ||||
| 	Read_Config( true ); | ||||
| 	Validate_Config(false, false); | ||||
| } /* Config_Init */ | ||||
|  | ||||
|  | ||||
| GLOBAL void | ||||
| GLOBAL bool | ||||
| Conf_Rehash( void ) | ||||
| { | ||||
| 	Set_Defaults( false ); | ||||
| 	Read_Config( ); | ||||
| 	if (!Read_Config(false)) | ||||
| 		return false; | ||||
| 	Validate_Config(false, true); | ||||
|  | ||||
| 	/* Update CLIENT structure of local server */ | ||||
| 	Client_SetInfo(Client_ThisServer(), Conf_ServerInfo); | ||||
| 	return true; | ||||
| } /* Config_Rehash */ | ||||
|  | ||||
|  | ||||
| static const char* | ||||
| yesno_to_str(int boolean_value) | ||||
| { | ||||
| 	if (boolean_value) | ||||
| 		return "yes"; | ||||
| 	return "no"; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL int | ||||
| Conf_Test( void ) | ||||
| { | ||||
| @@ -160,9 +172,8 @@ Conf_Test( void ) | ||||
| 	char *topic; | ||||
|  | ||||
| 	Use_Log = false; | ||||
| 	Set_Defaults( true ); | ||||
|  | ||||
| 	Read_Config( ); | ||||
| 	Read_Config( true ); | ||||
| 	Validate_Config(true, false); | ||||
|  | ||||
| 	/* If stdin and stdout ("you can read our nice message and we can | ||||
| @@ -199,15 +210,25 @@ Conf_Test( void ) | ||||
| 	printf( "  PingTimeout = %d\n", Conf_PingTimeout ); | ||||
| 	printf( "  PongTimeout = %d\n", Conf_PongTimeout ); | ||||
| 	printf( "  ConnectRetry = %d\n", Conf_ConnectRetry ); | ||||
| 	printf( "  OperCanUseMode = %s\n", Conf_OperCanMode == true? "yes" : "no" ); | ||||
| 	printf( "  OperServerMode = %s\n", Conf_OperServerMode == true? "yes" : "no" ); | ||||
| 	printf( "  MaxConnections = %ld\n", Conf_MaxConnections>0 ? Conf_MaxConnections : -1); | ||||
| 	printf( "  MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP>0 ? Conf_MaxConnectionsIP : -1); | ||||
| 	printf( "  MaxJoins = %d\n\n", Conf_MaxJoins>0 ? Conf_MaxJoins : -1); | ||||
| 	printf( "  OperCanUseMode = %s\n", yesno_to_str(Conf_OperCanMode)); | ||||
| 	printf( "  OperServerMode = %s\n", yesno_to_str(Conf_OperServerMode)); | ||||
| 	printf( "  PredefChannelsOnly = %s\n", yesno_to_str(Conf_PredefChannelsOnly)); | ||||
| 	printf( "  NoDNS = %s\n", yesno_to_str(Conf_NoDNS)); | ||||
|  | ||||
| #ifdef WANT_IPV6 | ||||
| 	printf("  ListenIPv6 = %s\n", yesno_to_str(Conf_ListenIPv6)); | ||||
| 	printf("  ListenIPv4 = %s\n", yesno_to_str(Conf_ListenIPv4)); | ||||
| 	printf("  ConnectIPv4 = %s\n", yesno_to_str(Conf_ConnectIPv6)); | ||||
| 	printf("  ConnectIPv6 = %s\n", yesno_to_str(Conf_ConnectIPv4)); | ||||
| #endif | ||||
| 	printf( "  MaxConnections = %ld\n", Conf_MaxConnections); | ||||
| 	printf( "  MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP); | ||||
| 	printf( "  MaxJoins = %d\n", Conf_MaxJoins>0 ? Conf_MaxJoins : -1); | ||||
| 	printf( "  MaxNickLength = %u\n\n", Conf_MaxNickLength - 1); | ||||
|  | ||||
| 	for( i = 0; i < Conf_Oper_Count; i++ ) { | ||||
| 		if( ! Conf_Oper[i].name[0] ) continue; | ||||
| 		 | ||||
|  | ||||
| 		/* Valid "Operator" section */ | ||||
| 		puts( "[OPERATOR]" ); | ||||
| 		printf( "  Name = %s\n", Conf_Oper[i].name ); | ||||
| @@ -218,7 +239,7 @@ Conf_Test( void ) | ||||
|  | ||||
| 	for( i = 0; i < MAX_SERVERS; i++ ) { | ||||
| 		if( ! Conf_Server[i].name[0] ) continue; | ||||
| 		 | ||||
|  | ||||
| 		/* Valid "Server" section */ | ||||
| 		puts( "[SERVER]" ); | ||||
| 		printf( "  Name = %s\n", Conf_Server[i].name ); | ||||
| @@ -226,21 +247,24 @@ Conf_Test( void ) | ||||
| 		printf( "  Port = %u\n", (unsigned int)Conf_Server[i].port ); | ||||
| 		printf( "  MyPassword = %s\n", Conf_Server[i].pwd_in ); | ||||
| 		printf( "  PeerPassword = %s\n", Conf_Server[i].pwd_out ); | ||||
| 		printf( "  Group = %d\n\n", Conf_Server[i].group ); | ||||
| 		printf( "  Group = %d\n", Conf_Server[i].group ); | ||||
| 		printf( "  Passive = %s\n\n", Conf_Server[i].flags & CONF_SFLAG_DISABLED ? "yes" : "no"); | ||||
| 	} | ||||
|  | ||||
| 	for( i = 0; i < Conf_Channel_Count; i++ ) { | ||||
| 		if( ! Conf_Channel[i].name[0] ) continue; | ||||
| 		 | ||||
|  | ||||
| 		/* Valid "Channel" section */ | ||||
| 		puts( "[CHANNEL]" ); | ||||
| 		printf( "  Name = %s\n", Conf_Channel[i].name ); | ||||
| 		printf( "  Modes = %s\n", Conf_Channel[i].modes ); | ||||
| 		printf( "  Key = %s\n", Conf_Channel[i].key ); | ||||
| 		printf( "  MaxUsers = %lu\n", Conf_Channel[i].maxusers ); | ||||
|  | ||||
| 		topic = (char*)array_start(&Conf_Channel[i].topic); | ||||
| 		printf( "  Topic = %s\n\n", topic ? topic : ""); | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	return 0; | ||||
| } /* Conf_Test */ | ||||
|  | ||||
| @@ -268,14 +292,14 @@ Conf_UnsetServer( CONN_ID Idx ) | ||||
| 			Init_Server_Struct( &Conf_Server[i] ); | ||||
| 		} else { | ||||
| 			/* Set time for next connect attempt */ | ||||
|  			t = time(NULL); | ||||
|  			if (Conf_Server[i].lasttry < t - Conf_ConnectRetry) { | ||||
|  				/* The connection has been "long", so we don't | ||||
|  				 * require the next attempt to be delayed. */ | ||||
|  				Conf_Server[i].lasttry = | ||||
|  					t - Conf_ConnectRetry + RECONNECT_DELAY; | ||||
|  			} else | ||||
|  				Conf_Server[i].lasttry = t; | ||||
| 			t = time(NULL); | ||||
| 			if (Conf_Server[i].lasttry < t - Conf_ConnectRetry) { | ||||
| 				/* The connection has been "long", so we don't | ||||
| 				 * require the next attempt to be delayed. */ | ||||
| 				Conf_Server[i].lasttry = | ||||
| 					t - Conf_ConnectRetry + RECONNECT_DELAY; | ||||
| 			} else | ||||
| 				Conf_Server[i].lasttry = t; | ||||
| 		} | ||||
| 	} | ||||
| } /* Conf_UnsetServer */ | ||||
| @@ -297,9 +321,9 @@ GLOBAL int | ||||
| Conf_GetServer( CONN_ID Idx ) | ||||
| { | ||||
| 	/* Get index of server in configuration structure */ | ||||
| 	 | ||||
|  | ||||
| 	int i = 0; | ||||
| 	 | ||||
|  | ||||
| 	assert( Idx > NONE ); | ||||
|  | ||||
| 	for( i = 0; i < MAX_SERVERS; i++ ) { | ||||
| @@ -330,6 +354,24 @@ Conf_EnableServer( char *Name, UINT16 Port ) | ||||
| } /* Conf_EnableServer */ | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Conf_EnablePassiveServer(const char *Name) | ||||
| { | ||||
| 	/* Enable specified server */ | ||||
| 	int i; | ||||
|  | ||||
| 	assert( Name != NULL ); | ||||
| 	for (i = 0; i < MAX_SERVERS; i++) { | ||||
| 		if ((strcasecmp( Conf_Server[i].name, Name ) == 0) && (Conf_Server[i].port > 0)) { | ||||
| 			/* BINGO! Enable server */ | ||||
| 			Conf_Server[i].flags &= ~CONF_SFLAG_DISABLED; | ||||
| 			return true; | ||||
| 		} | ||||
| 	} | ||||
| 	return false; | ||||
| } /* Conf_EnablePassiveServer */ | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Conf_DisableServer( char *Name ) | ||||
| { | ||||
| @@ -377,7 +419,7 @@ Conf_AddServer( char *Name, UINT16 Port, char *Host, char *MyPwd, char *PeerPwd | ||||
| 	strlcpy( Conf_Server[i].pwd_in, PeerPwd, sizeof( Conf_Server[i].pwd_in )); | ||||
| 	Conf_Server[i].port = Port; | ||||
| 	Conf_Server[i].flags = CONF_SFLAG_ONCE; | ||||
| 	 | ||||
|  | ||||
| 	return true; | ||||
| } /* Conf_AddServer */ | ||||
|  | ||||
| @@ -409,7 +451,7 @@ Set_Defaults( bool InitServers ) | ||||
| 	strcpy( Conf_ListenAddress, "" ); | ||||
|  | ||||
| 	Conf_UID = Conf_GID = 0; | ||||
| 	 | ||||
|  | ||||
| 	Conf_PingTimeout = 120; | ||||
| 	Conf_PongTimeout = 20; | ||||
|  | ||||
| @@ -419,19 +461,27 @@ Set_Defaults( bool InitServers ) | ||||
| 	Conf_Channel_Count = 0; | ||||
|  | ||||
| 	Conf_OperCanMode = false; | ||||
| 	Conf_NoDNS = false; | ||||
| 	Conf_PredefChannelsOnly = false; | ||||
| 	Conf_OperServerMode = false; | ||||
| 	 | ||||
| 	Conf_MaxConnections = -1; | ||||
|  | ||||
| 	Conf_ConnectIPv4 = true; | ||||
| 	Conf_ListenIPv4 = true; | ||||
| 	Conf_ConnectIPv6 = true; | ||||
| 	Conf_ListenIPv6 = true; | ||||
|  | ||||
| 	Conf_MaxConnections = 0; | ||||
| 	Conf_MaxConnectionsIP = 5; | ||||
| 	Conf_MaxJoins = 10; | ||||
| 	Conf_MaxNickLength = CLIENT_NICK_LEN_DEFAULT; | ||||
|  | ||||
| 	/* Initialize server configuration structures */ | ||||
| 	if( InitServers ) for( i = 0; i < MAX_SERVERS; Init_Server_Struct( &Conf_Server[i++] )); | ||||
| } /* Set_Defaults */ | ||||
|  | ||||
|  | ||||
| static void | ||||
| Read_Config( void ) | ||||
| static bool | ||||
| Read_Config( bool ngircd_starting ) | ||||
| { | ||||
| 	/* Read configuration file. */ | ||||
|  | ||||
| @@ -446,10 +496,14 @@ Read_Config( void ) | ||||
| 		/* No configuration file found! */ | ||||
| 		Config_Error( LOG_ALERT, "Can't read configuration \"%s\": %s", | ||||
| 					NGIRCd_ConfFile, strerror( errno )); | ||||
| 		if (!ngircd_starting) | ||||
| 			return false; | ||||
| 		Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME ); | ||||
| 		exit( 1 ); | ||||
| 	} | ||||
|  | ||||
| 	Set_Defaults( ngircd_starting ); | ||||
|  | ||||
| 	Config_Error( LOG_INFO, "Reading configuration from \"%s\" ...", NGIRCd_ConfFile ); | ||||
|  | ||||
| 	/* Clean up server configuration structure: mark all already | ||||
| @@ -550,6 +604,8 @@ Read_Config( void ) | ||||
| 					/* Initialize new channel structure */ | ||||
| 					strcpy( Conf_Channel[Conf_Channel_Count].name, "" ); | ||||
| 					strcpy( Conf_Channel[Conf_Channel_Count].modes, "" ); | ||||
| 					strcpy( Conf_Channel[Conf_Channel_Count].key, "" ); | ||||
| 					Conf_Channel[Conf_Channel_Count].maxusers = 0; | ||||
| 					array_free(&Conf_Channel[Conf_Channel_Count].topic); | ||||
| 					Conf_Channel_Count++; | ||||
| 				} | ||||
| @@ -594,6 +650,7 @@ Read_Config( void ) | ||||
| 			exit( 1 ); | ||||
| 		} | ||||
| 	} | ||||
| 	return true; | ||||
| } /* Read_Config */ | ||||
|  | ||||
|  | ||||
| @@ -608,6 +665,27 @@ Check_ArgIsTrue( const char *Arg ) | ||||
| } /* Check_ArgIsTrue */ | ||||
|  | ||||
|  | ||||
| static unsigned int Handle_MaxNickLength(int Line, const char *Arg) | ||||
| { | ||||
| 	unsigned new; | ||||
|  | ||||
| 	new = (unsigned) atoi(Arg) + 1; | ||||
| 	if (new > CLIENT_NICK_LEN) { | ||||
| 		Config_Error(LOG_WARNING, | ||||
| 			     "%s, line %d: Value of \"MaxNickLength\" exceeds %u!", | ||||
| 			     NGIRCd_ConfFile, Line, CLIENT_NICK_LEN - 1); | ||||
| 		return CLIENT_NICK_LEN; | ||||
| 	} | ||||
| 	if (new < 2) { | ||||
| 		Config_Error(LOG_WARNING, | ||||
| 			     "%s, line %d: Value of \"MaxNickLength\" must be at least 1!", | ||||
| 			     NGIRCd_ConfFile, Line); | ||||
| 		return 2; | ||||
| 	} | ||||
| 	return new; | ||||
| } /* Handle_MaxNickLength */ | ||||
|  | ||||
|  | ||||
| static void | ||||
| Handle_GLOBAL( int Line, char *Var, char *Arg ) | ||||
| { | ||||
| @@ -750,6 +828,43 @@ Handle_GLOBAL( int Line, char *Var, char *Arg ) | ||||
| 		} | ||||
| 		return; | ||||
| 	} | ||||
| 	if( strcasecmp( Var, "PredefChannelsOnly" ) == 0 ) { | ||||
| 		/* Should we only allow pre-defined-channels? (i.e. users cannot create their own channels) */ | ||||
| 		Conf_PredefChannelsOnly = Check_ArgIsTrue( Arg ); | ||||
| 		return; | ||||
| 	} | ||||
| 	if( strcasecmp( Var, "NoDNS" ) == 0 ) { | ||||
| 		/* don't do reverse dns lookups when clients connect? */ | ||||
| 		Conf_NoDNS = Check_ArgIsTrue( Arg ); | ||||
| 		return; | ||||
| 	} | ||||
| #ifdef WANT_IPV6 | ||||
| 	/* the default setting for all the WANT_IPV6 special options is 'true' */ | ||||
| 	if( strcasecmp( Var, "ListenIPv6" ) == 0 ) { | ||||
| 		/* listen on ipv6 sockets, if available? */ | ||||
| 		Conf_ListenIPv6 = Check_ArgIsTrue( Arg ); | ||||
| 		return; | ||||
| 	} | ||||
| 	if( strcasecmp( Var, "ListenIPv4" ) == 0 ) { | ||||
| 		/* | ||||
| 		 * listen on ipv4 sockets, if available? | ||||
| 		 * this allows "ipv6-only" setups. | ||||
| 		 */ | ||||
| 		Conf_ListenIPv4 = Check_ArgIsTrue( Arg ); | ||||
| 		return; | ||||
| 	} | ||||
| 	if( strcasecmp( Var, "ConnectIPv6" ) == 0 ) { | ||||
| 		/* connect to other hosts using ipv6, if they have an AAAA record? */ | ||||
| 		Conf_ConnectIPv6 = Check_ArgIsTrue( Arg ); | ||||
| 		return; | ||||
| 	} | ||||
| 	if( strcasecmp( Var, "ConnectIPv4" ) == 0 ) { | ||||
| 		/* connect to other hosts using ipv4. | ||||
| 		 * again, this can be used for ipv6-only setups */ | ||||
| 		Conf_ConnectIPv4 = Check_ArgIsTrue( Arg ); | ||||
| 		return; | ||||
| 	} | ||||
| #endif | ||||
| 	if( strcasecmp( Var, "OperCanUseMode" ) == 0 ) { | ||||
| 		/* Are IRC operators allowed to use MODE in channels they aren't Op in? */ | ||||
| 		Conf_OperCanMode = Check_ArgIsTrue( Arg ); | ||||
| @@ -761,7 +876,7 @@ Handle_GLOBAL( int Line, char *Var, char *Arg ) | ||||
| 		return; | ||||
| 	} | ||||
| 	if( strcasecmp( Var, "MaxConnections" ) == 0 ) { | ||||
| 		/* Maximum number of connections. Values <= 0 are equal to "no limit". */ | ||||
| 		/* Maximum number of connections. 0 -> "no limit". */ | ||||
| #ifdef HAVE_ISDIGIT | ||||
| 		if( ! isdigit( (int)*Arg )) Config_Error_NaN( Line, Var); | ||||
| 		else | ||||
| @@ -770,7 +885,7 @@ Handle_GLOBAL( int Line, char *Var, char *Arg ) | ||||
| 		return; | ||||
| 	} | ||||
| 	if( strcasecmp( Var, "MaxConnectionsIP" ) == 0 ) { | ||||
| 		/* Maximum number of simultaneous connections from one IP. Values <= 0 -> "no limit" */ | ||||
| 		/* Maximum number of simultaneous connections from one IP. 0 -> "no limit" */ | ||||
| #ifdef HAVE_ISDIGIT | ||||
| 		if( ! isdigit( (int)*Arg )) Config_Error_NaN( Line, Var ); | ||||
| 		else | ||||
| @@ -779,7 +894,7 @@ Handle_GLOBAL( int Line, char *Var, char *Arg ) | ||||
| 		return; | ||||
| 	} | ||||
| 	if( strcasecmp( Var, "MaxJoins" ) == 0 ) { | ||||
| 		/* Maximum number of channels a user can join. Values <= 0 are equal to "no limit". */ | ||||
| 		/* Maximum number of channels a user can join. 0 -> "no limit". */ | ||||
| #ifdef HAVE_ISDIGIT | ||||
| 		if( ! isdigit( (int)*Arg )) Config_Error_NaN( Line, Var ); | ||||
| 		else | ||||
| @@ -787,6 +902,13 @@ Handle_GLOBAL( int Line, char *Var, char *Arg ) | ||||
| 		Conf_MaxJoins = atoi( Arg ); | ||||
| 		return; | ||||
| 	} | ||||
| 	if( strcasecmp( Var, "MaxNickLength" ) == 0 ) { | ||||
| 		/* Maximum length of a nick name; must be same on all servers | ||||
| 		 * within the IRC network! */ | ||||
| 		Conf_MaxNickLength = Handle_MaxNickLength(Line, Arg); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if( strcasecmp( Var, "Listen" ) == 0 ) { | ||||
| 		/* IP-Address to bind sockets */ | ||||
| 		len = strlcpy( Conf_ListenAddress, Arg, sizeof( Conf_ListenAddress )); | ||||
| @@ -867,6 +989,14 @@ Handle_SERVER( int Line, char *Var, char *Arg ) | ||||
| 			Config_Error_TooLong( Line, Var ); | ||||
| 		return; | ||||
| 	} | ||||
| 	if (strcasecmp(Var, "Bind") == 0) { | ||||
| 		if (ng_ipaddr_init(&New_Server.bind_addr, Arg, 0)) | ||||
| 			return; | ||||
|  | ||||
| 		Config_Error(LOG_ERR, "%s, line %d (section \"Server\"): Can't parse IP address \"%s\"", | ||||
| 				NGIRCd_ConfFile, Line, Arg); | ||||
| 		return; | ||||
| 	} | ||||
| 	if( strcasecmp( Var, "MyPassword" ) == 0 ) { | ||||
| 		/* Password of this server which is sent to the peer */ | ||||
| 		if (*Arg == ':') { | ||||
| @@ -906,12 +1036,32 @@ Handle_SERVER( int Line, char *Var, char *Arg ) | ||||
| 		New_Server.group = atoi( Arg ); | ||||
| 		return; | ||||
| 	} | ||||
| 	if( strcasecmp( Var, "Passive" ) == 0 ) { | ||||
| 		if (Check_ArgIsTrue(Arg)) | ||||
| 			New_Server.flags |= CONF_SFLAG_DISABLED; | ||||
| 		return; | ||||
| 	} | ||||
| 	 | ||||
| 	Config_Error( LOG_ERR, "%s, line %d (section \"Server\"): Unknown variable \"%s\"!", | ||||
| 								NGIRCd_ConfFile, Line, Var ); | ||||
| } /* Handle_SERVER */ | ||||
|  | ||||
|  | ||||
| static bool | ||||
| Handle_Channelname(size_t chancount, const char *name) | ||||
| { | ||||
| 	size_t size = sizeof( Conf_Channel[chancount].name ); | ||||
| 	char *dest = Conf_Channel[chancount].name; | ||||
|  | ||||
| 	if (*name && *name != '#') { | ||||
| 		*dest = '#'; | ||||
| 		--size; | ||||
| 		++dest; | ||||
| 	} | ||||
| 	return size > strlcpy(dest, name, size); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| Handle_CHANNEL( int Line, char *Var, char *Arg ) | ||||
| { | ||||
| @@ -925,9 +1075,7 @@ Handle_CHANNEL( int Line, char *Var, char *Arg ) | ||||
| 		chancount = Conf_Channel_Count - 1; | ||||
|  | ||||
| 	if( strcasecmp( Var, "Name" ) == 0 ) { | ||||
| 		/* Name of the channel */ | ||||
| 		len = strlcpy( Conf_Channel[chancount].name, Arg, sizeof( Conf_Channel[chancount].name )); | ||||
| 		if (len >= sizeof( Conf_Channel[chancount].name )) | ||||
| 		if (!Handle_Channelname(chancount, Arg)) | ||||
| 			Config_Error_TooLong( Line, Var ); | ||||
| 		return; | ||||
| 	} | ||||
| @@ -945,6 +1093,22 @@ Handle_CHANNEL( int Line, char *Var, char *Arg ) | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if( strcasecmp( Var, "Key" ) == 0 ) { | ||||
| 		/* Initial Channel Key (mode k) */ | ||||
| 		len = strlcpy(Conf_Channel[chancount].key, Arg, sizeof(Conf_Channel[chancount].key)); | ||||
| 		if (len >= sizeof( Conf_Channel[chancount].key )) | ||||
| 			Config_Error_TooLong(Line, Var); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if( strcasecmp( Var, "MaxUsers" ) == 0 ) { | ||||
| 		/* maximum user limit, mode l */ | ||||
| 		Conf_Channel[chancount].maxusers = (unsigned long) atol(Arg); | ||||
| 		if (Conf_Channel[chancount].maxusers == 0) | ||||
| 			Config_Error_NaN(Line, Var); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	Config_Error( LOG_ERR, "%s, line %d (section \"Channel\"): Unknown variable \"%s\"!", | ||||
| 								NGIRCd_ConfFile, Line, Var ); | ||||
| } /* Handle_CHANNEL */ | ||||
| @@ -965,7 +1129,7 @@ Validate_Config(bool Configtest, bool Rehash) | ||||
| 	do { | ||||
| 		if (*ptr >= 'a' && *ptr <= 'z') continue; | ||||
| 		if (*ptr >= 'A' && *ptr <= 'Z') continue; | ||||
| 		if (*ptr >= '1' && *ptr <= '0') continue; | ||||
| 		if (*ptr >= '0' && *ptr <= '9') continue; | ||||
| 		if (ptr > Conf_ServerName) { | ||||
| 			if (*ptr == '.' || *ptr == '-') | ||||
| 				continue; | ||||
| @@ -1022,6 +1186,16 @@ Validate_Config(bool Configtest, bool Rehash) | ||||
| 			     "No administrative information configured but required by RFC!"); | ||||
| 	} | ||||
|  | ||||
| #ifdef WANT_IPV6 | ||||
| 	if (!Conf_ListenIPv4 && !Conf_ListenIPv6) | ||||
| 		Config_Error(LOG_ALERT, | ||||
| 			"Both \"ListenIPv4\" and \"ListenIPv6\" are set to 'no'; no network protocol available!"); | ||||
|  | ||||
| 	if (!Conf_ConnectIPv4 && !Conf_ConnectIPv6) | ||||
| 		Config_Error(LOG_ALERT, | ||||
| 			"Both \"ConnectIPv4\" and \"ConnectIPv6\" are set to 'no'; ngircd will fail to connect to other irc servers"); | ||||
| #endif | ||||
|  | ||||
| #ifdef DEBUG | ||||
| 	servers = servers_once = 0; | ||||
| 	for (i = 0; i < MAX_SERVERS; i++) { | ||||
| @@ -1101,6 +1275,7 @@ Init_Server_Struct( CONF_SERVER *Server ) | ||||
|  | ||||
| 	Resolve_Init(&Server->res_stat); | ||||
| 	Server->conn_id = NONE; | ||||
| 	memset(&Server->bind_addr, 0, sizeof(&Server->bind_addr)); | ||||
| } /* Init_Server_Struct */ | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: conf.h,v 1.40 2006/05/10 21:24:01 alex Exp $ | ||||
|  * $Id: conf.h,v 1.49 2008/03/18 20:12:47 fw Exp $ | ||||
|  * | ||||
|  * Configuration management (header) | ||||
|  */ | ||||
| @@ -22,6 +22,8 @@ | ||||
| #include "defines.h" | ||||
| #include "array.h" | ||||
| #include "portab.h" | ||||
| #include "tool.h" | ||||
| #include "ng_ipaddr.h" | ||||
|  | ||||
| typedef struct _Conf_Oper | ||||
| { | ||||
| @@ -33,7 +35,6 @@ typedef struct _Conf_Oper | ||||
| typedef struct _Conf_Server | ||||
| { | ||||
| 	char host[HOST_LEN];		/* Hostname */ | ||||
| 	char ip[16];			/* IP address (Resolver) */ | ||||
| 	char name[CLIENT_ID_LEN];	/* IRC-Client-ID */ | ||||
| 	char pwd_in[CLIENT_PASS_LEN];	/* Password which must be received */ | ||||
| 	char pwd_out[CLIENT_PASS_LEN];	/* Password to send to peer */ | ||||
| @@ -43,12 +44,16 @@ typedef struct _Conf_Server | ||||
| 	RES_STAT res_stat;		/* Status of the resolver */ | ||||
| 	int flags;			/* Flags */ | ||||
| 	CONN_ID conn_id;		/* ID of server connection or NONE */ | ||||
| 	ng_ipaddr_t bind_addr;		/* source address to use for outgoing connections */ | ||||
| 	ng_ipaddr_t dst_addr[2];	/* list of addresses to connect to */ | ||||
| } CONF_SERVER; | ||||
|  | ||||
| typedef struct _Conf_Channel | ||||
| { | ||||
| 	char name[CHANNEL_NAME_LEN];	/* Name of the channel */ | ||||
| 	char modes[CHANNEL_MODE_LEN];	/* Initial channel modes */ | ||||
| 	char key[CLIENT_PASS_LEN];      /* Channel key ("password", mode "k" ) */ | ||||
| 	unsigned long maxusers;		/* maximum usercount for this channel, mode "l" */ | ||||
| 	array topic;			/* Initial topic */ | ||||
| } CONF_CHANNEL; | ||||
|  | ||||
| @@ -110,10 +115,30 @@ GLOBAL CONF_SERVER Conf_Server[MAX_SERVERS]; | ||||
| /* Pre-defined channels */ | ||||
| GLOBAL CONF_CHANNEL Conf_Channel[MAX_DEFCHANNELS]; | ||||
| GLOBAL unsigned int Conf_Channel_Count; | ||||
| /* Pre-defined channels only */ | ||||
| GLOBAL bool Conf_PredefChannelsOnly; | ||||
|  | ||||
| /* Are IRC operators allowed to always use MODE? */ | ||||
| GLOBAL bool Conf_OperCanMode; | ||||
|  | ||||
| /* Disable all DNS functions? */ | ||||
| GLOBAL bool Conf_NoDNS; | ||||
|  | ||||
| /* listen for incoming ipv6 connections if OS supports it (default: yes)? */ | ||||
| GLOBAL bool Conf_ListenIPv6; | ||||
|  | ||||
| /* listen for incoming ipv4 connections if OS supports it (default: yes)? */ | ||||
| GLOBAL bool Conf_ListenIPv4; | ||||
|  | ||||
| /* | ||||
|  * try to connect to remote systems using the ipv6 protocol, | ||||
|  * if they have an ipv6 address? (default yes) | ||||
|  */ | ||||
| GLOBAL bool Conf_ConnectIPv6; | ||||
|  | ||||
| /* same as above, but for ipv4 hosts, default: yes  */ | ||||
| GLOBAL bool Conf_ConnectIPv4; | ||||
|  | ||||
| /* If an IRC op gives chanop privileges without being a chanop, | ||||
|  * ircd2 will ignore the command. This enables a workaround: | ||||
|  * It masks the command as coming from the server */ | ||||
| @@ -128,9 +153,11 @@ GLOBAL int Conf_MaxJoins; | ||||
| /* Maximum number of connections per IP address */ | ||||
| GLOBAL int Conf_MaxConnectionsIP; | ||||
|  | ||||
| /* Maximum length of a nick name */ | ||||
| GLOBAL unsigned int Conf_MaxNickLength; | ||||
|  | ||||
| GLOBAL void Conf_Init PARAMS((void)); | ||||
| GLOBAL void Conf_Rehash PARAMS((void)); | ||||
| GLOBAL bool Conf_Rehash PARAMS((void)); | ||||
| GLOBAL int Conf_Test PARAMS((void)); | ||||
|  | ||||
| GLOBAL void Conf_UnsetServer PARAMS(( CONN_ID Idx )); | ||||
| @@ -138,6 +165,7 @@ GLOBAL void Conf_SetServer PARAMS(( int ConfServer, CONN_ID Idx )); | ||||
| GLOBAL int Conf_GetServer PARAMS(( CONN_ID Idx )); | ||||
|  | ||||
| GLOBAL bool Conf_EnableServer PARAMS(( char *Name, UINT16 Port )); | ||||
| GLOBAL bool Conf_EnablePassiveServer PARAMS((const char *Name)); | ||||
| GLOBAL bool Conf_DisableServer PARAMS(( char *Name )); | ||||
| GLOBAL bool Conf_AddServer PARAMS(( char *Name, UINT16 Port, char *Host, char *MyPwd, char *PeerPwd )); | ||||
|  | ||||
|   | ||||
| @@ -16,11 +16,12 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: conn-func.c,v 1.10 2006/05/10 21:24:01 alex Exp $"; | ||||
| static char UNUSED id[] = "$Id: conn-func.c,v 1.12 2008/03/11 14:05:27 alex Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| #include <log.h> | ||||
| #include <string.h> | ||||
| #include "log.h" | ||||
|  | ||||
| #include "conn.h" | ||||
| #include "client.h" | ||||
| @@ -39,6 +40,16 @@ Conn_UpdateIdle( CONN_ID Idx ) | ||||
| } | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * Get signon time of a connection. | ||||
|  */ | ||||
| GLOBAL time_t | ||||
| Conn_GetSignon(CONN_ID Idx) | ||||
| { | ||||
| 	assert(Idx > NONE); | ||||
| 	return My_Connections[Idx].signon; | ||||
| } | ||||
|  | ||||
| GLOBAL time_t | ||||
| Conn_GetIdle( CONN_ID Idx ) | ||||
| { | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: conn-func.h,v 1.5 2006/05/10 21:24:01 alex Exp $ | ||||
|  * $Id: conn-func.h,v 1.7 2007/10/04 15:03:56 alex Exp $ | ||||
|  * | ||||
|  * Connection management: Global functions (header) | ||||
|  */ | ||||
| @@ -27,6 +27,7 @@ | ||||
|  | ||||
|  | ||||
| GLOBAL void Conn_UpdateIdle PARAMS(( CONN_ID Idx )); | ||||
| GLOBAL time_t Conn_GetSignon PARAMS((CONN_ID Idx)); | ||||
| GLOBAL time_t Conn_GetIdle PARAMS(( CONN_ID Idx )); | ||||
| GLOBAL time_t Conn_LastPing PARAMS(( CONN_ID Idx )); | ||||
| GLOBAL time_t Conn_StartTime PARAMS(( CONN_ID Idx )); | ||||
| @@ -52,9 +53,9 @@ GLOBAL UINT16 Conn_Options PARAMS(( CONN_ID Idx )); | ||||
| GLOBAL void Conn_ResetWCounter PARAMS(( void )); | ||||
| GLOBAL long Conn_WCounter PARAMS(( void )); | ||||
|  | ||||
| #define Conn_OPTION_ADD( x, opt )   ( (x)->options |= opt )  | ||||
| #define Conn_OPTION_DEL( x, opt )   ( (x)->options &= ~opt ) | ||||
| #define Conn_OPTION_ISSET( x, opt ) ( (x)->options & opt ) | ||||
| #define Conn_OPTION_ADD( x, opt )   ( (x)->options |= (opt) ) | ||||
| #define Conn_OPTION_DEL( x, opt )   ( (x)->options &= ~(opt) ) | ||||
| #define Conn_OPTION_ISSET( x, opt ) ( ((x)->options & (opt)) != 0) | ||||
|  | ||||
| #endif | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  * ngIRCd -- The Next Generation IRC Daemon | ||||
|  * Copyright (c)2001-2006 Alexander Barton (alex@barton.de) | ||||
|  * Copyright (c)2001-2007 Alexander Barton (alex@barton.de) | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
| @@ -22,7 +22,7 @@ | ||||
| /* enable more zlib related debug messages: */ | ||||
| /* #define DEBUG_ZLIB */ | ||||
|  | ||||
| static char UNUSED id[] = "$Id: conn-zip.c,v 1.11 2006/07/23 15:19:20 alex Exp $"; | ||||
| static char UNUSED id[] = "$Id: conn-zip.c,v 1.16 2007/05/17 23:34:24 alex Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| @@ -82,47 +82,63 @@ Zip_InitConn( CONN_ID Idx ) | ||||
| } /* Zip_InitConn */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Copy data to the compression buffer of a connection. We do collect | ||||
|  * some data there until it's full so that we can achieve better | ||||
|  * compression ratios. | ||||
|  * If the (pre-)compression buffer is full, we try to flush it ("actually | ||||
|  * compress some data") and to add the new (uncompressed) data afterwards. | ||||
|  * @param Idx Connection handle. | ||||
|  * @param Data Pointer to the data. | ||||
|  * @param Len Length of the data to add. | ||||
|  * @return true on success, false otherwise. */ | ||||
| GLOBAL bool | ||||
| Zip_Buffer( CONN_ID Idx, char *Data, size_t Len ) | ||||
| { | ||||
| 	/* Daten zum Komprimieren im "Kompressions-Puffer" sammeln. | ||||
| 	* Es wird true bei Erfolg, sonst false geliefert. */ | ||||
| 	size_t buflen; | ||||
|  | ||||
| 	assert( Idx > NONE ); | ||||
| 	assert( Data != NULL ); | ||||
| 	assert( Len > 0 ); | ||||
| 	assert( Len <= ZWRITEBUFFER_LEN ); | ||||
|  | ||||
| 	if (Len > ZWRITEBUFFER_LEN) | ||||
| 		return false; | ||||
|  | ||||
| 	if ( array_bytes( &My_Connections[Idx].zip.wbuf ) >= ZWRITEBUFFER_LEN ) { | ||||
| 	buflen = array_bytes(&My_Connections[Idx].zip.wbuf); | ||||
| 	if (buflen + Len >= WRITEBUFFER_SLINK_LEN) { | ||||
| 		/* compression buffer is full, flush */ | ||||
| 		if( ! Zip_Flush( Idx )) return false; | ||||
| 	} | ||||
|  | ||||
| 	/* check again; if zip buf is still too large do not append data: | ||||
| 	 * otherwise the zip wbuf would grow too large */ | ||||
| 	buflen = array_bytes(&My_Connections[Idx].zip.wbuf); | ||||
| 	if (buflen + Len >= WRITEBUFFER_SLINK_LEN) | ||||
| 		return false; | ||||
|  | ||||
| 	return array_catb(&My_Connections[Idx].zip.wbuf, Data, Len); | ||||
| } /* Zip_Buffer */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Compress data in ZIP buffer and move result to the write buffer of | ||||
|  * the connection. | ||||
|  * @param Idx Connection handle. | ||||
|  * @retrun true on success, false otherwise. | ||||
|  */ | ||||
| GLOBAL bool | ||||
| Zip_Flush( CONN_ID Idx ) | ||||
| { | ||||
| 	/* Daten komprimieren und in Schreibpuffer kopieren. | ||||
| 	* Es wird true bei Erfolg, sonst false geliefert. */ | ||||
|  | ||||
| 	int result; | ||||
| 	unsigned char zipbuf[WRITEBUFFER_LEN]; | ||||
| 	unsigned char zipbuf[WRITEBUFFER_SLINK_LEN]; | ||||
| 	int zipbuf_used = 0; | ||||
| 	z_stream *out; | ||||
|  | ||||
| 	out = &My_Connections[Idx].zip.out; | ||||
|  | ||||
| 	out->next_in = array_start(&My_Connections[Idx].zip.wbuf); | ||||
| 	if (!out->next_in) | ||||
| 		return false; | ||||
|  | ||||
| 	out->avail_in = (uInt)array_bytes(&My_Connections[Idx].zip.wbuf); | ||||
| 	if (!out->avail_in) | ||||
| 		return true;	/* nothing to do. */ | ||||
|  | ||||
| 	out->next_in = array_start(&My_Connections[Idx].zip.wbuf); | ||||
| 	assert(out->next_in != NULL); | ||||
|  | ||||
| 	out->next_out = zipbuf; | ||||
| 	out->avail_out = (uInt)sizeof zipbuf; | ||||
| @@ -139,14 +155,26 @@ Zip_Flush( CONN_ID Idx ) | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	assert(out->avail_out <= WRITEBUFFER_LEN); | ||||
| 	zipbuf_used = WRITEBUFFER_LEN - out->avail_out; | ||||
| 	if (out->avail_out <= 0) { | ||||
| 		/* Not all data was compressed, because data became | ||||
| 		 * bigger while compressing it. */ | ||||
| 		Log (LOG_ALERT, "Compression error: buffer overvlow!?"); | ||||
| 		Conn_Close(Idx, "Compression error!", NULL, false); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	assert(out->avail_out <= WRITEBUFFER_SLINK_LEN); | ||||
|  | ||||
| 	zipbuf_used = WRITEBUFFER_SLINK_LEN - out->avail_out; | ||||
| #ifdef DEBUG_ZIP | ||||
| 	Log(LOG_DEBUG, "zipbuf_used: %d", zipbuf_used); | ||||
| #endif | ||||
| 	if (!array_catb(&My_Connections[Idx].wbuf, | ||||
| 			(char *)zipbuf, (size_t) zipbuf_used)) | ||||
| 			(char *)zipbuf, (size_t) zipbuf_used)) { | ||||
| 		Log (LOG_ALERT, "Compression error: can't copy data!?"); | ||||
| 		Conn_Close(Idx, "Compression error!", NULL, false); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	My_Connections[Idx].bytes_out += zipbuf_used; | ||||
| 	My_Connections[Idx].zip.bytes_out += array_bytes(&My_Connections[Idx].zip.wbuf);  | ||||
| @@ -178,10 +206,9 @@ Unzip_Buffer( CONN_ID Idx ) | ||||
| 		return true; | ||||
|  | ||||
| 	in = &My_Connections[Idx].zip.in; | ||||
| 	 | ||||
|  | ||||
| 	in->next_in = array_start(&My_Connections[Idx].zip.rbuf); | ||||
| 	if (!in->next_in) | ||||
| 		return false; | ||||
| 	assert(in->next_in != NULL); | ||||
|  | ||||
| 	in->avail_in = z_rdatalen; | ||||
| 	in->next_out = unzipbuf; | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  * ngIRCd -- The Next Generation IRC Daemon | ||||
|  * Copyright (c)2001-2005 Alexander Barton <alex@barton.de> | ||||
|  * Copyright (c)2001-2007 Alexander Barton (alex@barton.de) | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
| @@ -17,7 +17,7 @@ | ||||
| #include "portab.h" | ||||
| #include "io.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: conn.c,v 1.198 2006/07/23 23:05:20 alex Exp $"; | ||||
| static char UNUSED id[] = "$Id: conn.c,v 1.221 2008/02/26 22:04:17 fw Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| @@ -41,12 +41,6 @@ static char UNUSED id[] = "$Id: conn.c,v 1.198 2006/07/23 23:05:20 alex Exp $"; | ||||
| # include <netinet/ip.h> | ||||
| #endif | ||||
|  | ||||
| #ifdef HAVE_ARPA_INET_H | ||||
| # include <arpa/inet.h> | ||||
| #else | ||||
| # define PF_INET AF_INET | ||||
| #endif | ||||
|  | ||||
| #ifdef HAVE_STDINT_H | ||||
| # include <stdint.h>			/* e.g. for Mac OS X */ | ||||
| #endif | ||||
| @@ -83,6 +77,7 @@ static char UNUSED id[] = "$Id: conn.c,v 1.198 2006/07/23 23:05:20 alex Exp $"; | ||||
|  | ||||
|  | ||||
| static bool Handle_Write PARAMS(( CONN_ID Idx )); | ||||
| static bool Conn_Write PARAMS(( CONN_ID Idx, char *Data, size_t Len )); | ||||
| static int New_Connection PARAMS(( int Sock )); | ||||
| static CONN_ID Socket2Index PARAMS(( int Sock )); | ||||
| static void Read_Request PARAMS(( CONN_ID Idx )); | ||||
| @@ -91,10 +86,9 @@ static void Check_Connections PARAMS(( void )); | ||||
| static void Check_Servers PARAMS(( void )); | ||||
| static void Init_Conn_Struct PARAMS(( CONN_ID Idx )); | ||||
| static bool Init_Socket PARAMS(( int Sock )); | ||||
| static void New_Server PARAMS(( int Server )); | ||||
| static void New_Server PARAMS(( int Server, ng_ipaddr_t *dest )); | ||||
| static void Simple_Message PARAMS(( int Sock, const char *Msg )); | ||||
| static int Count_Connections PARAMS(( struct sockaddr_in addr )); | ||||
| static int NewListener PARAMS(( const UINT16 Port )); | ||||
| static int NewListener PARAMS(( int af, const UINT16 Port )); | ||||
|  | ||||
| static array My_Listeners; | ||||
| static array My_ConnArray; | ||||
| @@ -123,7 +117,6 @@ cb_connserver(int sock, UNUSED short what) | ||||
| { | ||||
| 	int res, err; | ||||
| 	socklen_t sock_len; | ||||
| 	CLIENT *c; | ||||
| 	CONN_ID idx = Socket2Index( sock ); | ||||
| 	if (idx <= NONE) { | ||||
| 		LogDebug("cb_connserver wants to write on unknown socket?!"); | ||||
| @@ -150,17 +143,28 @@ cb_connserver(int sock, UNUSED short what) | ||||
|  			    Conf_Server[Conf_GetServer(idx)].port, | ||||
|  			    idx, strerror(err)); | ||||
|  | ||||
| 		/* Clean up the CLIENT structure (to avoid silly log | ||||
|  		 * messages) and call Conn_Close() to do the rest. */ | ||||
|  		c = Conn_GetClient(idx); | ||||
|  		if (c) | ||||
| 			Client_DestroyNow(c); | ||||
|   | ||||
|  		Conn_Close(idx, "Can't connect!", NULL, false); | ||||
|   | ||||
| 		res = Conf_GetServer(idx); | ||||
| 		assert(res >= 0); | ||||
|  | ||||
| 		Conn_Close(idx, "Can't connect!", NULL, false); | ||||
|  | ||||
| 		if (res < 0) | ||||
| 			return; | ||||
| 		if (ng_ipaddr_af(&Conf_Server[res].dst_addr[0])) { | ||||
| 			/* more addresses to try... */ | ||||
| 			New_Server(res, &Conf_Server[res].dst_addr[0]); | ||||
| 			/* connection to dst_addr[0] in progress, remove this address... */ | ||||
| 			Conf_Server[res].dst_addr[0] = Conf_Server[res].dst_addr[1]; | ||||
|  | ||||
| 			memset(&Conf_Server[res].dst_addr[1], 0, sizeof(&Conf_Server[res].dst_addr[1])); | ||||
| 		} | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	res = Conf_GetServer(idx); | ||||
| 	assert(res >= 0); | ||||
| 	if (res >= 0) /* connect succeeded, remove all additional addresses */ | ||||
| 		memset(&Conf_Server[res].dst_addr, 0, sizeof(&Conf_Server[res].dst_addr)); | ||||
| 	Conn_OPTION_DEL( &My_Connections[idx], CONN_ISCONNECTING ); | ||||
| 	server_login(idx); | ||||
| } | ||||
| @@ -267,10 +271,10 @@ Conn_Exit( void ) | ||||
| } /* Conn_Exit */ | ||||
|  | ||||
|  | ||||
| static int | ||||
| ports_initlisteners(array *a, void (*func)(int,short)) | ||||
| static unsigned int | ||||
| ports_initlisteners(array *a, int af, void (*func)(int,short)) | ||||
| { | ||||
| 	int created = 0; | ||||
| 	unsigned int created = 0; | ||||
| 	size_t len; | ||||
| 	int fd; | ||||
| 	UINT16 *port; | ||||
| @@ -278,7 +282,7 @@ ports_initlisteners(array *a, void (*func)(int,short)) | ||||
| 	len = array_length(a, sizeof (UINT16)); | ||||
| 	port = array_start(a); | ||||
| 	while(len--) { | ||||
| 		fd = NewListener( *port ); | ||||
| 		fd = NewListener(af, *port); | ||||
| 		if (fd < 0) { | ||||
| 			port++; | ||||
| 			continue; | ||||
| @@ -298,19 +302,24 @@ ports_initlisteners(array *a, void (*func)(int,short)) | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL int | ||||
| GLOBAL unsigned int | ||||
| Conn_InitListeners( void ) | ||||
| { | ||||
| 	/* Initialize ports on which the server should accept connections */ | ||||
|  | ||||
| 	int created; | ||||
| 	unsigned int created = 0; | ||||
|  | ||||
| 	if (!io_library_init(CONNECTION_POOL)) { | ||||
| 		Log(LOG_EMERG, "Cannot initialize IO routines: %s", strerror(errno)); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	created = ports_initlisteners(&Conf_ListenPorts, cb_listen); | ||||
| #ifdef WANT_IPV6 | ||||
| 	if (Conf_ListenIPv6) | ||||
| 		created = ports_initlisteners(&Conf_ListenPorts, AF_INET6, cb_listen); | ||||
| #endif | ||||
| 	if (Conf_ListenIPv4) | ||||
| 		created += ports_initlisteners(&Conf_ListenPorts, AF_INET, cb_listen); | ||||
|  | ||||
| 	return created; | ||||
| } /* Conn_InitListeners */ | ||||
| @@ -340,52 +349,79 @@ Conn_ExitListeners( void ) | ||||
| } /* Conn_ExitListeners */ | ||||
|  | ||||
|  | ||||
| static bool | ||||
| InitSinaddrListenAddr(int af, ng_ipaddr_t *addr, UINT16 Port) | ||||
| { | ||||
| 	bool ret; | ||||
| 	const char *listen_addrstr = NULL; | ||||
| #ifdef WANT_IPV6 | ||||
| 	if (af == AF_INET) | ||||
| 		listen_addrstr = "0.0.0.0"; | ||||
| #else | ||||
| 	(void)af; | ||||
| #endif | ||||
| 	if (Conf_ListenAddress[0]) /* overrides V4/V6 atm */ | ||||
| 		listen_addrstr = Conf_ListenAddress; | ||||
|  | ||||
| 	ret = ng_ipaddr_init(addr, listen_addrstr, Port); | ||||
| 	if (!ret) { | ||||
| 		if (!listen_addrstr) | ||||
| 			listen_addrstr = ""; | ||||
| 		Log(LOG_CRIT, "Can't bind to %s:%u: can't convert ip address \"%s\"", | ||||
| 					listen_addrstr, Port, listen_addrstr); | ||||
| 	} | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| set_v6_only(int af, int sock) | ||||
| { | ||||
| #if defined(IPV6_V6ONLY) && defined(WANT_IPV6) | ||||
| 	int on = 1; | ||||
|  | ||||
| 	if (af != AF_INET6) | ||||
| 		return; | ||||
|  | ||||
| 	if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on))) | ||||
| 		Log(LOG_ERR, "Could not set IPV6_V6ONLY: %s", strerror(errno)); | ||||
| #else | ||||
| 	(void)af; | ||||
| 	(void)sock; | ||||
| #endif | ||||
| } | ||||
|  | ||||
|  | ||||
| /* return new listening port file descriptor or -1 on failure */ | ||||
| static int | ||||
| NewListener( const UINT16 Port ) | ||||
| NewListener(int af, const UINT16 Port) | ||||
| { | ||||
| 	/* Create new listening socket on specified port */ | ||||
|  | ||||
| 	struct sockaddr_in addr; | ||||
| 	struct in_addr inaddr; | ||||
| 	ng_ipaddr_t addr; | ||||
| 	int sock; | ||||
| #ifdef ZEROCONF | ||||
| 	char name[CLIENT_ID_LEN], *info; | ||||
| #endif | ||||
| 	if (!InitSinaddrListenAddr(af, &addr, Port)) | ||||
| 		return -1; | ||||
|  | ||||
| 	/* Server-"Listen"-Socket initialisieren */ | ||||
| 	memset( &addr, 0, sizeof( addr )); | ||||
| 	memset( &inaddr, 0, sizeof( inaddr )); | ||||
| 	addr.sin_family = (sa_family_t)AF_INET; | ||||
| 	addr.sin_port = htons( Port ); | ||||
| 	if( Conf_ListenAddress[0] ) | ||||
| 	{ | ||||
| #ifdef HAVE_INET_ATON | ||||
| 		if( inet_aton( Conf_ListenAddress, &inaddr ) == 0 ) | ||||
| #else | ||||
| 		inaddr.s_addr = inet_addr( Conf_ListenAddress ); | ||||
| 		if( inaddr.s_addr == (unsigned)-1 ) | ||||
| #endif | ||||
| 		{ | ||||
| 			Log( LOG_CRIT, "Can't listen on %s:%u: can't convert ip address %s!", | ||||
| 					Conf_ListenAddress, Port, Conf_ListenAddress ); | ||||
| 			return -1; | ||||
| 		} | ||||
| 	} | ||||
| 	else inaddr.s_addr = htonl( INADDR_ANY ); | ||||
| 	addr.sin_addr = inaddr; | ||||
|  | ||||
| 	sock = socket( PF_INET, SOCK_STREAM, 0); | ||||
| 	sock = socket(ng_ipaddr_af(&addr), SOCK_STREAM, 0); | ||||
| 	if( sock < 0 ) { | ||||
| 		Log( LOG_CRIT, "Can't create socket: %s!", strerror( errno )); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	if( ! Init_Socket( sock )) return -1; | ||||
| 	af = ng_ipaddr_af(&addr); | ||||
|  | ||||
| 	if (bind(sock, (struct sockaddr *)&addr, (socklen_t)sizeof(addr)) != 0) { | ||||
| 		Log( LOG_CRIT, "Can't bind socket: %s!", strerror( errno )); | ||||
| 		close( sock ); | ||||
| 	set_v6_only(af, sock); | ||||
|  | ||||
| 	if (!Init_Socket(sock)) | ||||
| 		return -1; | ||||
|  | ||||
| 	if (bind(sock, (struct sockaddr *)&addr, ng_ipaddr_salen(&addr)) != 0) { | ||||
| 		Log(LOG_CRIT, "Can't bind socket to address %s:%d - %s", | ||||
| 			ng_ipaddr_tostr(&addr), Port, strerror(errno)); | ||||
| 		close(sock); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| @@ -402,8 +438,12 @@ NewListener( const UINT16 Port ) | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	if( Conf_ListenAddress[0]) Log( LOG_INFO, "Now listening on %s:%d (socket %d).", Conf_ListenAddress, Port, sock ); | ||||
| 	else Log( LOG_INFO, "Now listening on 0.0.0.0:%d (socket %d).", Port, sock ); | ||||
| #ifdef WANT_IPV6 | ||||
| 	if (af == AF_INET6) | ||||
| 		Log(LOG_INFO, "Now listening on [%s]:%d (socket %d).", ng_ipaddr_tostr(&addr), Port, sock); | ||||
| 	else | ||||
| #endif | ||||
| 		Log(LOG_INFO, "Now listening on %s:%d (socket %d).", ng_ipaddr_tostr(&addr), Port, sock); | ||||
|  | ||||
| #ifdef ZEROCONF | ||||
| 	/* Get best server description text */ | ||||
| @@ -615,51 +655,74 @@ va_dcl | ||||
| } /* Conn_WriteStr */ | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| /** | ||||
|  * Append Data to the outbound write buffer of a connection. | ||||
|  * @param Idx Index of the connection. | ||||
|  * @param Data pointer to the data. | ||||
|  * @param Len length of Data. | ||||
|  * @return true on success, false otherwise. | ||||
|  */ | ||||
| static bool | ||||
| Conn_Write( CONN_ID Idx, char *Data, size_t Len ) | ||||
| { | ||||
| 	/* Daten in Socket schreiben. Bei "fatalen" Fehlern wird | ||||
| 	 * der Client disconnectiert und false geliefert. */ | ||||
|  | ||||
| 	CLIENT *c; | ||||
| 	size_t writebuf_limit = WRITEBUFFER_LEN; | ||||
| 	assert( Idx > NONE ); | ||||
| 	assert( Data != NULL ); | ||||
| 	assert( Len > 0 ); | ||||
|  | ||||
| 	/* Ist der entsprechende Socket ueberhaupt noch offen? In einem | ||||
| 	 * "Handler-Durchlauf" kann es passieren, dass dem nicht mehr so | ||||
| 	 * ist, wenn einer von mehreren Conn_Write()'s fehlgeschlagen ist. | ||||
| 	 * In diesem Fall wird hier einfach ein Fehler geliefert. */ | ||||
| 	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 ) { | ||||
| 		LogDebug("Skipped write on closed socket (connection %d).", Idx ); | ||||
| 		LogDebug("Skipped write on closed socket (connection %d).", Idx); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	/* Pruefen, ob im Schreibpuffer genuegend Platz ist. Ziel ist es, | ||||
| 	 * moeglichts viel im Puffer zu haben und _nicht_ gleich alles auf den | ||||
| 	 * Socket zu schreiben (u.a. wg. Komprimierung). */ | ||||
| 	if( array_bytes(&My_Connections[Idx].wbuf) >= WRITEBUFFER_LEN) { | ||||
| 		/* Der Puffer ist dummerweise voll. Jetzt versuchen, den Puffer | ||||
| 		 * zu schreiben, wenn das nicht klappt, haben wir ein Problem ... */ | ||||
| 		if( ! Handle_Write( Idx )) return false; | ||||
|  | ||||
| 		/* check again: if our writebuf is twice als large as the initial limit: Kill connection */ | ||||
| 		if( array_bytes(&My_Connections[Idx].wbuf) >= (WRITEBUFFER_LEN*2)) { | ||||
| 			Log( LOG_NOTICE, "Write buffer overflow (connection %d)!", Idx ); | ||||
| 			Conn_Close( Idx, "Write buffer overflow!", NULL, false ); | ||||
| 			return false; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| #ifdef ZLIB | ||||
| 	if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ZIP )) { | ||||
| 		/* Daten komprimieren und in Puffer kopieren */ | ||||
| 		if( ! Zip_Buffer( Idx, Data, Len )) return false; | ||||
| 		/* Compressed link: | ||||
| 		 * Zip_Buffer() does all the dirty work for us: it flushes | ||||
| 		 * the (pre-)compression buffers if required and handles | ||||
| 		 * all error conditions. */ | ||||
| 		if (!Zip_Buffer(Idx, Data, Len)) | ||||
| 			return false; | ||||
| 	} | ||||
| 	else | ||||
| #endif | ||||
| 	{ | ||||
| 		/* Daten in Puffer kopieren */ | ||||
| 		if (!array_catb( &My_Connections[Idx].wbuf, Data, Len )) | ||||
| 		/* Uncompressed link: | ||||
| 		 * Check if outbound buffer has enough space for the data. */ | ||||
| 		if (array_bytes(&My_Connections[Idx].wbuf) + Len >= | ||||
| 		    writebuf_limit) { | ||||
| 			/* Buffer is full, flush it. Handle_Write deals with | ||||
| 			 * low-level errors, if any. */ | ||||
| 			if (!Handle_Write(Idx)) | ||||
| 				return false; | ||||
| 		} | ||||
|  | ||||
| 		/* When the write buffer is still too big after flushing it, | ||||
| 		 * the connection will be killed. */ | ||||
| 		if (array_bytes(&My_Connections[Idx].wbuf) + Len >= | ||||
| 		    writebuf_limit) { | ||||
| 			Log(LOG_NOTICE, | ||||
| 			    "Write buffer overflow (connection %d, size %lu byte)!", | ||||
| 			    Idx, | ||||
| 			    (unsigned long)array_bytes(&My_Connections[Idx].wbuf)); | ||||
| 			Conn_Close(Idx, "Write buffer overflow!", NULL, false); | ||||
| 			return false; | ||||
| 		} | ||||
|  | ||||
| 		/* Copy data to write buffer */ | ||||
| 		if (!array_catb(&My_Connections[Idx].wbuf, Data, Len)) | ||||
| 			return false; | ||||
|  | ||||
| 		My_Connections[Idx].bytes_out += Len; | ||||
| @@ -681,6 +744,7 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient ) | ||||
| 	CLIENT *c; | ||||
| 	char *txt; | ||||
| 	double in_k, out_k; | ||||
| 	UINT16 port; | ||||
| #ifdef ZLIB | ||||
| 	double in_z_k, out_z_k; | ||||
| 	int in_p, out_p; | ||||
| @@ -700,7 +764,7 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient ) | ||||
|  | ||||
| 	/* Mark link as "closing" */ | ||||
| 	Conn_OPTION_ADD( &My_Connections[Idx], CONN_ISCLOSING ); | ||||
| 		 | ||||
|  | ||||
| 	if (LogMsg) | ||||
| 		txt = LogMsg; | ||||
| 	else | ||||
| @@ -708,9 +772,9 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient ) | ||||
| 	if (! txt) | ||||
| 		txt = "Reason unknown"; | ||||
|  | ||||
| 	port = ng_ipaddr_getport(&My_Connections[Idx].addr); | ||||
| 	Log(LOG_INFO, "Shutting down connection %d (%s) with %s:%d ...", Idx, | ||||
| 	    LogMsg ? LogMsg : FwdMsg, My_Connections[Idx].host, | ||||
| 	    ntohs(My_Connections[Idx].addr.sin_port)); | ||||
| 	    LogMsg ? LogMsg : FwdMsg, My_Connections[Idx].host, port); | ||||
|  | ||||
| 	/* Search client, if any */ | ||||
| 	c = Conn_GetClient( Idx ); | ||||
| @@ -728,7 +792,6 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient ) | ||||
| 			 (double)My_Connections[Idx].bytes_out / 1024); | ||||
| 		} | ||||
| #endif | ||||
|  | ||||
| 		/* Send ERROR to client (see RFC!) */ | ||||
| 		if (FwdMsg) | ||||
| 			Conn_WriteStr(Idx, "ERROR :%s", FwdMsg); | ||||
| @@ -751,7 +814,7 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient ) | ||||
| 		Log(LOG_CRIT, | ||||
| 		    "Error closing connection %d (socket %d) with %s:%d - %s! (ignored)", | ||||
| 		    Idx, My_Connections[Idx].sock, My_Connections[Idx].host, | ||||
| 		    ntohs(My_Connections[Idx].addr.sin_port), strerror(errno)); | ||||
| 		    port, strerror(errno)); | ||||
| 	} | ||||
|  | ||||
| 	/* Mark socket as invalid: */ | ||||
| @@ -780,8 +843,7 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient ) | ||||
| 		out_p = (int)(( out_k * 100 ) / out_z_k ); | ||||
| 		Log(LOG_INFO, | ||||
| 		    "Connection %d with %s:%d closed (in: %.1fk/%.1fk/%d%%, out: %.1fk/%.1fk/%d%%).", | ||||
| 		    Idx, My_Connections[Idx].host, | ||||
| 		    ntohs(My_Connections[Idx].addr.sin_port), | ||||
| 		    Idx, My_Connections[Idx].host, port, | ||||
| 		    in_k, in_z_k, in_p, out_k, out_z_k, out_p); | ||||
| 	} | ||||
| 	else | ||||
| @@ -789,8 +851,7 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient ) | ||||
| 	{ | ||||
| 		Log(LOG_INFO, | ||||
| 		    "Connection %d with %s:%d closed (in: %.1fk, out: %.1fk).", | ||||
| 		    Idx, My_Connections[Idx].host, | ||||
| 		    ntohs(My_Connections[Idx].addr.sin_port), | ||||
| 		    Idx, My_Connections[Idx].host, port, | ||||
| 		    in_k, out_k); | ||||
| 	} | ||||
|  | ||||
| @@ -872,24 +933,23 @@ Handle_Write( CONN_ID Idx ) | ||||
| 	wdatalen = array_bytes(&My_Connections[Idx].wbuf ); | ||||
|  | ||||
| #ifdef ZLIB | ||||
| 	if (wdatalen == 0 && !array_bytes(&My_Connections[Idx].zip.wbuf)) { | ||||
| 		io_event_del(My_Connections[Idx].sock, IO_WANTWRITE ); | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	/* write buffer empty, but not compression buffer? | ||||
|          * -> flush compression buffer! */ | ||||
| 	if (wdatalen == 0) | ||||
| 		Zip_Flush(Idx); | ||||
| #else | ||||
| 	if (wdatalen == 0) { | ||||
| 		io_event_del(My_Connections[Idx].sock, IO_WANTWRITE ); | ||||
| 		return true; | ||||
| 		/* Write buffer is empty, so we try to flush the compression | ||||
| 		 * buffer and get some data to work with from there :-) */ | ||||
| 		if (!Zip_Flush(Idx)) | ||||
| 			return false; | ||||
|  | ||||
| 		/* Now the write buffer most probably has changed: */ | ||||
| 		wdatalen = array_bytes(&My_Connections[Idx].wbuf); | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	/* Zip_Flush() may have changed the write buffer ... */ | ||||
| 	wdatalen = array_bytes(&My_Connections[Idx].wbuf); | ||||
| 	if (wdatalen == 0) { | ||||
| 		/* Still no data, fine. */ | ||||
| 		io_event_del(My_Connections[Idx].sock, IO_WANTWRITE ); | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	LogDebug | ||||
| 	    ("Handle_Write() called for connection %d, %ld bytes pending ...", | ||||
| 	     Idx, wdatalen); | ||||
| @@ -914,6 +974,22 @@ Handle_Write( CONN_ID Idx ) | ||||
| } /* Handle_Write */ | ||||
|  | ||||
|  | ||||
| static int | ||||
| Count_Connections(ng_ipaddr_t *a) | ||||
| { | ||||
| 	int i, cnt; | ||||
|  | ||||
| 	cnt = 0; | ||||
| 	for (i = 0; i < Pool_Size; i++) { | ||||
| 		if (My_Connections[i].sock <= NONE) | ||||
| 			continue; | ||||
| 		if (ng_ipaddr_ipequal(&My_Connections[i].addr, a)) | ||||
| 			cnt++; | ||||
| 	} | ||||
| 	return cnt; | ||||
| } /* Count_Connections */ | ||||
|  | ||||
|  | ||||
| static int | ||||
| New_Connection( int Sock ) | ||||
| { | ||||
| @@ -923,14 +999,16 @@ New_Connection( int Sock ) | ||||
| #ifdef TCPWRAP | ||||
| 	struct request_info req; | ||||
| #endif | ||||
| 	struct sockaddr_in new_addr; | ||||
| 	ng_ipaddr_t new_addr; | ||||
| 	char ip_str[NG_INET_ADDRSTRLEN]; | ||||
| 	int new_sock, new_sock_len, new_Pool_Size; | ||||
| 	CLIENT *c; | ||||
| 	long cnt; | ||||
|  | ||||
| 	assert( Sock > NONE ); | ||||
| 	/* Connection auf Listen-Socket annehmen */ | ||||
| 	new_sock_len = (int)sizeof new_addr; | ||||
| 	new_sock_len = (int)sizeof(new_addr); | ||||
|  | ||||
| 	new_sock = accept(Sock, (struct sockaddr *)&new_addr, | ||||
| 			  (socklen_t *)&new_sock_len); | ||||
| 	if (new_sock < 0) { | ||||
| @@ -938,14 +1016,18 @@ New_Connection( int Sock ) | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	if (!ng_ipaddr_tostr_r(&new_addr, ip_str)) { | ||||
| 		Log(LOG_CRIT, "fd %d: Can't convert IP address!", new_sock); | ||||
| 		Simple_Message(new_sock, "ERROR :Internal Server Error"); | ||||
| 		close(new_sock); | ||||
| 	} | ||||
|  | ||||
| #ifdef TCPWRAP | ||||
| 	/* Validate socket using TCP Wrappers */ | ||||
| 	request_init( &req, RQ_DAEMON, PACKAGE_NAME, RQ_FILE, new_sock, RQ_CLIENT_SIN, &new_addr, NULL ); | ||||
| 	fromhost(&req); | ||||
| 	if( ! hosts_access( &req )) | ||||
| 	{ | ||||
| 		/* Access denied! */ | ||||
| 		Log( deny_severity, "Refused connection from %s (by TCP Wrappers)!", inet_ntoa( new_addr.sin_addr )); | ||||
| 	if (!hosts_access(&req)) { | ||||
| 		Log (deny_severity, "Refused connection from %s (by TCP Wrappers)!", ip_str); | ||||
| 		Simple_Message( new_sock, "ERROR :Connection refused" ); | ||||
| 		close( new_sock ); | ||||
| 		return -1; | ||||
| @@ -955,13 +1037,12 @@ New_Connection( int Sock ) | ||||
| 	/* Socket initialisieren */ | ||||
| 	if (!Init_Socket( new_sock )) | ||||
| 		return -1; | ||||
| 	 | ||||
|  | ||||
| 	/* Check IP-based connection limit */ | ||||
| 	cnt = Count_Connections( new_addr ); | ||||
| 	if(( Conf_MaxConnectionsIP > 0 ) && ( cnt >= Conf_MaxConnectionsIP )) | ||||
| 	{ | ||||
| 	cnt = Count_Connections(&new_addr); | ||||
| 	if ((Conf_MaxConnectionsIP > 0) && (cnt >= Conf_MaxConnectionsIP)) { | ||||
| 		/* Access denied, too many connections from this IP address! */ | ||||
| 		Log( LOG_ERR, "Refused connection from %s: too may connections (%ld) from this IP address!", inet_ntoa( new_addr.sin_addr ), cnt); | ||||
| 		Log( LOG_ERR, "Refused connection from %s: too may connections (%ld) from this IP address!", ip_str, cnt); | ||||
| 		Simple_Message( new_sock, "ERROR :Connection refused, too many connections from your IP address!" ); | ||||
| 		close( new_sock ); | ||||
| 		return -1; | ||||
| @@ -995,11 +1076,19 @@ New_Connection( int Sock ) | ||||
| 			Init_Conn_Struct(Pool_Size++); | ||||
| 	} | ||||
|  | ||||
| 	c = Client_NewLocal( new_sock, inet_ntoa( new_addr.sin_addr ), CLIENT_UNKNOWN, false ); | ||||
| 	/* register callback */ | ||||
| 	if (!io_event_create( new_sock, IO_WANTREAD, cb_clientserver)) { | ||||
| 		Log(LOG_ALERT, "Can't accept connection: io_event_create failed!"); | ||||
| 		Simple_Message(new_sock, "ERROR :Internal error"); | ||||
| 		close(new_sock); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	c = Client_NewLocal(new_sock, ip_str, CLIENT_UNKNOWN, false ); | ||||
| 	if( ! c ) { | ||||
| 		Log( LOG_ALERT, "Can't accept connection: can't create client structure!" ); | ||||
| 		Simple_Message( new_sock, "ERROR :Internal error" ); | ||||
| 		close( new_sock ); | ||||
| 		Log(LOG_ALERT, "Can't accept connection: can't create client structure!"); | ||||
| 		Simple_Message(new_sock, "ERROR :Internal error"); | ||||
| 		io_close(new_sock); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| @@ -1008,27 +1097,19 @@ New_Connection( int Sock ) | ||||
| 	My_Connections[new_sock].addr = new_addr; | ||||
| 	My_Connections[new_sock].client = c; | ||||
|  | ||||
| 	/* register callback */ | ||||
| 	if (!io_event_create( new_sock, IO_WANTREAD, cb_clientserver)) { | ||||
| 		Simple_Message( new_sock, "ERROR :Internal error" ); | ||||
| 		Conn_Close( new_sock, "io_event_create() failed", NULL, false ); | ||||
| 		return -1; | ||||
| 	} | ||||
|  | ||||
| 	Log( LOG_INFO, "Accepted connection %d from %s:%d on socket %d.", new_sock, | ||||
| 			inet_ntoa( new_addr.sin_addr ), ntohs( new_addr.sin_port), Sock ); | ||||
| 			ip_str, ng_ipaddr_getport(&new_addr), Sock); | ||||
|  | ||||
| 	/* Hostnamen ermitteln */ | ||||
| 	strlcpy( My_Connections[new_sock].host, inet_ntoa( new_addr.sin_addr ), | ||||
| 						sizeof( My_Connections[new_sock].host )); | ||||
| 	strlcpy(My_Connections[new_sock].host, ip_str, sizeof(My_Connections[new_sock].host)); | ||||
|  | ||||
| 	Client_SetHostname( c, My_Connections[new_sock].host ); | ||||
| 	Client_SetHostname(c, My_Connections[new_sock].host); | ||||
|  | ||||
| 	Resolve_Addr(&My_Connections[new_sock].res_stat, &new_addr, | ||||
| 		My_Connections[new_sock].sock, cb_Read_Resolver_Result); | ||||
| 	if (!Conf_NoDNS) | ||||
| 		Resolve_Addr(&My_Connections[new_sock].res_stat, &new_addr, | ||||
| 			My_Connections[new_sock].sock, cb_Read_Resolver_Result); | ||||
|  | ||||
| 	/* Penalty-Zeit setzen */ | ||||
| 	Conn_SetPenalty( new_sock, 4 ); | ||||
| 	Conn_SetPenalty(new_sock, 4); | ||||
| 	return new_sock; | ||||
| } /* New_Connection */ | ||||
|  | ||||
| @@ -1050,47 +1131,52 @@ Socket2Index( int Sock ) | ||||
| } /* Socket2Index */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Read data from the network to the read buffer. If an error occures, | ||||
|  * the socket of this connection will be shut down. | ||||
|  */ | ||||
| static void | ||||
| Read_Request( CONN_ID Idx ) | ||||
| { | ||||
| 	/* Daten von Socket einlesen und entsprechend behandeln. | ||||
| 	 * Tritt ein Fehler auf, so wird der Socket geschlossen. */ | ||||
|  | ||||
| 	ssize_t len; | ||||
| 	char readbuf[1024]; | ||||
| 	char readbuf[READBUFFER_LEN]; | ||||
| 	CLIENT *c; | ||||
|  | ||||
| 	assert( Idx > NONE ); | ||||
| 	assert( My_Connections[Idx].sock > NONE ); | ||||
|  | ||||
| #ifdef ZLIB | ||||
| 	if (( array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN ) || | ||||
| 		( array_bytes(&My_Connections[Idx].zip.rbuf) >= ZREADBUFFER_LEN )) | ||||
| 	if ((array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN) || | ||||
| 		(array_bytes(&My_Connections[Idx].zip.rbuf) >= READBUFFER_LEN)) | ||||
| #else | ||||
| 	if ( array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN ) | ||||
| 	if (array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN) | ||||
| #endif | ||||
| 	{ | ||||
| 		/* Der Lesepuffer ist voll */ | ||||
| 		Log( LOG_ERR, "Receive buffer overflow (connection %d): %d bytes!", Idx, | ||||
| 						array_bytes(&My_Connections[Idx].rbuf)); | ||||
| 		/* Read buffer is full */ | ||||
| 		Log(LOG_ERR, | ||||
| 		    "Receive buffer overflow (connection %d): %d bytes!", | ||||
| 		    Idx, array_bytes(&My_Connections[Idx].rbuf)); | ||||
| 		Conn_Close( Idx, "Receive buffer overflow!", NULL, false ); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	len = read( My_Connections[Idx].sock, readbuf, sizeof readbuf -1 ); | ||||
| 	if( len == 0 ) { | ||||
| 		Log( LOG_INFO, "%s:%d (%s) is closing the connection ...", | ||||
| 			My_Connections[Idx].host, ntohs( My_Connections[Idx].addr.sin_port), | ||||
| 					inet_ntoa( My_Connections[Idx].addr.sin_addr )); | ||||
| 		Conn_Close( Idx, "Socket closed!", "Client closed connection", false ); | ||||
| 	len = read(My_Connections[Idx].sock, readbuf, sizeof(readbuf)); | ||||
| 	if (len == 0) { | ||||
| 		Log(LOG_INFO, "%s:%u (%s) is closing the connection ...", | ||||
| 				My_Connections[Idx].host, | ||||
| 				(unsigned int) ng_ipaddr_getport(&My_Connections[Idx].addr), | ||||
| 				ng_ipaddr_tostr(&My_Connections[Idx].addr)); | ||||
| 		Conn_Close(Idx, | ||||
| 			   "Socket closed!", "Client closed connection", | ||||
| 			   false); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if( len < 0 ) { | ||||
| 	if (len < 0) { | ||||
| 		if( errno == EAGAIN ) return; | ||||
| 		Log( LOG_ERR, "Read error on connection %d (socket %d): %s!", Idx, | ||||
| 					My_Connections[Idx].sock, strerror( errno )); | ||||
| 		Conn_Close( Idx, "Read error!", "Client closed connection", false ); | ||||
| 		Log(LOG_ERR, "Read error on connection %d (socket %d): %s!", | ||||
| 		    Idx, My_Connections[Idx].sock, strerror(errno)); | ||||
| 		Conn_Close(Idx, "Read error!", "Client closed connection", | ||||
| 			   false); | ||||
| 		return; | ||||
| 	} | ||||
| #ifdef ZLIB | ||||
| @@ -1107,8 +1193,7 @@ Read_Request( CONN_ID Idx ) | ||||
| 	} else | ||||
| #endif | ||||
| 	{ | ||||
| 		readbuf[len] = 0; | ||||
| 		if (!array_cats( &My_Connections[Idx].rbuf, readbuf )) { | ||||
| 		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 ); | ||||
| 			Conn_Close( Idx, "Receive buffer overflow!", NULL, false ); | ||||
| 		} | ||||
| @@ -1227,11 +1312,6 @@ Handle_Buffer( CONN_ID Idx ) | ||||
| 			/* The last Command activated Socket-Compression. | ||||
| 			 * Data that was read after that needs to be copied to Unzip-buf | ||||
| 			 * for decompression */ | ||||
| 			if( array_bytes(&My_Connections[Idx].rbuf)> ZREADBUFFER_LEN ) { | ||||
| 				Log( LOG_ALERT, "Connection %d: No space left in unzip buf (need %u bytes)!", | ||||
| 								Idx, array_bytes(&My_Connections[Idx].rbuf )); | ||||
| 				return false; | ||||
| 			} | ||||
| 			if (!array_copy( &My_Connections[Idx].zip.rbuf, &My_Connections[Idx].rbuf )) | ||||
| 				return false; | ||||
|  | ||||
| @@ -1319,7 +1399,7 @@ Check_Servers( void ) | ||||
| 		if( Conf_Server[i].group > NONE ) { | ||||
| 			for (n = 0; n < MAX_SERVERS; n++) { | ||||
| 				if (n == i) continue; | ||||
| 				if ((Conf_Server[n].conn_id > NONE) && | ||||
| 				if ((Conf_Server[n].conn_id != NONE) && | ||||
| 					(Conf_Server[n].group == Conf_Server[i].group)) | ||||
| 						break; | ||||
| 			} | ||||
| @@ -1333,6 +1413,7 @@ Check_Servers( void ) | ||||
|  | ||||
| 		/* Okay, try to connect now */ | ||||
| 		Conf_Server[i].lasttry = time_now; | ||||
| 		Conf_Server[i].conn_id = SERVER_WAIT; | ||||
| 		assert(Resolve_Getfd(&Conf_Server[i].res_stat) < 0); | ||||
| 		Resolve_Name(&Conf_Server[i].res_stat, Conf_Server[i].host, cb_Connect_to_Server); | ||||
| 	} | ||||
| @@ -1340,54 +1421,50 @@ Check_Servers( void ) | ||||
|  | ||||
|  | ||||
| static void | ||||
| New_Server( int Server ) | ||||
| New_Server( int Server , ng_ipaddr_t *dest) | ||||
| { | ||||
| 	/* Establish new server link */ | ||||
|  | ||||
| 	struct sockaddr_in new_addr; | ||||
| 	struct in_addr inaddr; | ||||
| 	int res, new_sock; | ||||
| 	char ip_str[NG_INET_ADDRSTRLEN]; | ||||
| 	int af_dest, res, new_sock; | ||||
| 	CLIENT *c; | ||||
|  | ||||
| 	assert( Server > NONE ); | ||||
|  | ||||
| 	Log( LOG_INFO, "Establishing connection to \"%s\", %s, port %d ... ", Conf_Server[Server].host, | ||||
| 							Conf_Server[Server].ip, Conf_Server[Server].port ); | ||||
|  | ||||
| #ifdef HAVE_INET_ATON | ||||
| 	if( inet_aton( Conf_Server[Server].ip, &inaddr ) == 0 ) | ||||
| #else | ||||
| 	memset( &inaddr, 0, sizeof( inaddr )); | ||||
| 	inaddr.s_addr = inet_addr( Conf_Server[Server].ip ); | ||||
| 	if( inaddr.s_addr == (unsigned)-1 ) | ||||
| #endif | ||||
| 	{ | ||||
| 		Log( LOG_ERR, "Can't connect to \"%s\": can't convert ip address %s!", | ||||
| 				Conf_Server[Server].host, Conf_Server[Server].ip ); | ||||
| 	if (!ng_ipaddr_tostr_r(dest, ip_str)) { | ||||
| 		Log(LOG_WARNING, "New_Server: Could not convert IP to string"); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	memset( &new_addr, 0, sizeof( new_addr )); | ||||
| 	new_addr.sin_family = (sa_family_t)AF_INET; | ||||
| 	new_addr.sin_addr = inaddr; | ||||
| 	new_addr.sin_port = htons( Conf_Server[Server].port ); | ||||
| 	Log( LOG_INFO, "Establishing connection to \"%s\", %s, port %d ... ", | ||||
| 			Conf_Server[Server].host, ip_str, Conf_Server[Server].port ); | ||||
|  | ||||
| 	new_sock = socket( PF_INET, SOCK_STREAM, 0 ); | ||||
| 	if ( new_sock < 0 ) { | ||||
| 	af_dest = ng_ipaddr_af(dest); | ||||
| 	new_sock = socket(af_dest, SOCK_STREAM, 0); | ||||
| 	if (new_sock < 0) { | ||||
| 		Log( LOG_CRIT, "Can't create socket: %s!", strerror( errno )); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if( ! Init_Socket( new_sock )) return; | ||||
| 	if (!Init_Socket(new_sock)) | ||||
| 		return; | ||||
|  | ||||
| 	res = connect(new_sock, (struct sockaddr *)&new_addr, | ||||
| 			(socklen_t)sizeof(new_addr)); | ||||
| 	/* is a bind address configured? */ | ||||
| 	res = ng_ipaddr_af(&Conf_Server[Server].bind_addr); | ||||
| 	/* if yes, bind now. If it fails, warn and let connect() pick a source address */ | ||||
| 	if (res && bind(new_sock, (struct sockaddr *) &Conf_Server[Server].bind_addr, | ||||
| 				ng_ipaddr_salen(&Conf_Server[Server].bind_addr))) | ||||
| 	{ | ||||
| 		ng_ipaddr_tostr_r(&Conf_Server[Server].bind_addr, ip_str); | ||||
| 		Log(LOG_WARNING, "Can't bind socket to %s: %s!", ip_str, strerror(errno)); | ||||
| 	} | ||||
| 	ng_ipaddr_setport(dest, Conf_Server[Server].port); | ||||
| 	res = connect(new_sock, (struct sockaddr *) dest, ng_ipaddr_salen(dest)); | ||||
| 	if(( res != 0 ) && ( errno != EINPROGRESS )) { | ||||
| 		Log( LOG_CRIT, "Can't connect socket: %s!", strerror( errno )); | ||||
| 		close( new_sock ); | ||||
| 		return; | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	if (!array_alloc(&My_ConnArray, sizeof(CONNECTION), (size_t)new_sock)) { | ||||
| 		Log(LOG_ALERT, | ||||
| 		    "Cannot allocate memory for server connection (socket %d)", | ||||
| @@ -1402,8 +1479,9 @@ New_Server( int Server ) | ||||
|  | ||||
| 	Init_Conn_Struct(new_sock); | ||||
|  | ||||
| 	c = Client_NewLocal( new_sock, inet_ntoa( new_addr.sin_addr ), CLIENT_UNKNOWNSERVER, false ); | ||||
| 	if( ! c ) { | ||||
| 	ng_ipaddr_tostr_r(dest, ip_str); | ||||
| 	c = Client_NewLocal(new_sock, ip_str, CLIENT_UNKNOWNSERVER, false); | ||||
| 	if (!c) { | ||||
| 		Log( LOG_ALERT, "Can't establish connection: can't create client structure!" ); | ||||
| 		close( new_sock ); | ||||
| 		return; | ||||
| @@ -1415,7 +1493,7 @@ New_Server( int Server ) | ||||
| 	/* Register connection */ | ||||
| 	Conf_Server[Server].conn_id = new_sock; | ||||
| 	My_Connections[new_sock].sock = new_sock; | ||||
| 	My_Connections[new_sock].addr = new_addr; | ||||
| 	My_Connections[new_sock].addr = *dest; | ||||
| 	My_Connections[new_sock].client = c; | ||||
| 	strlcpy( My_Connections[new_sock].host, Conf_Server[Server].host, | ||||
| 				sizeof(My_Connections[new_sock].host )); | ||||
| @@ -1434,14 +1512,17 @@ New_Server( int Server ) | ||||
| } /* New_Server */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Initialize connection structure. | ||||
|  */ | ||||
| static void | ||||
| Init_Conn_Struct( CONN_ID Idx ) | ||||
| Init_Conn_Struct(CONN_ID Idx) | ||||
| { | ||||
| 	time_t now = time( NULL ); | ||||
| 	/* Connection-Struktur initialisieren */ | ||||
| 	time_t now = time(NULL); | ||||
|  | ||||
| 	memset( &My_Connections[Idx], 0, sizeof ( CONNECTION )); | ||||
| 	memset(&My_Connections[Idx], 0, sizeof(CONNECTION)); | ||||
| 	My_Connections[Idx].sock = -1; | ||||
| 	My_Connections[Idx].signon = now; | ||||
| 	My_Connections[Idx].lastdata = now; | ||||
| 	My_Connections[Idx].lastprivmsg = now; | ||||
| 	Resolve_Init(&My_Connections[Idx].res_stat); | ||||
| @@ -1491,7 +1572,9 @@ cb_Connect_to_Server(int fd, UNUSED short events) | ||||
| 	/* Read result of resolver sub-process from pipe and start connection */ | ||||
| 	int i; | ||||
| 	size_t len; | ||||
| 	char readbuf[HOST_LEN + 1]; | ||||
| 	ng_ipaddr_t dest_addrs[4];	/* we can handle at most 3; but we read up to | ||||
| 					   four so we can log the 'more than we can handle' | ||||
| 					   condition */ | ||||
|  | ||||
| 	LogDebug("Resolver: Got forward lookup callback on fd %d, events %d", fd, events); | ||||
|  | ||||
| @@ -1499,7 +1582,7 @@ cb_Connect_to_Server(int fd, UNUSED short events) | ||||
| 		  if (Resolve_Getfd(&Conf_Server[i].res_stat) == fd ) | ||||
| 			  break; | ||||
| 	} | ||||
| 	 | ||||
|  | ||||
| 	if( i >= MAX_SERVERS) { | ||||
| 		/* Ops, no matching server found?! */ | ||||
| 		io_close( fd ); | ||||
| @@ -1508,16 +1591,28 @@ cb_Connect_to_Server(int fd, UNUSED short events) | ||||
| 	} | ||||
|  | ||||
| 	/* Read result from pipe */ | ||||
| 	len = Resolve_Read(&Conf_Server[i].res_stat, readbuf, sizeof readbuf -1); | ||||
| 	len = Resolve_Read(&Conf_Server[i].res_stat, dest_addrs, sizeof(dest_addrs)); | ||||
| 	if (len == 0) | ||||
| 		return; | ||||
| 	 | ||||
| 	readbuf[len] = '\0'; | ||||
| 	LogDebug("Got result from resolver: \"%s\" (%u bytes read).", readbuf, len); | ||||
| 	strlcpy( Conf_Server[i].ip, readbuf, sizeof( Conf_Server[i].ip )); | ||||
|  | ||||
| 	assert((len % sizeof(ng_ipaddr_t)) == 0); | ||||
|  | ||||
| 	LogDebug("Got result from resolver: %u structs (%u bytes).", len/sizeof(ng_ipaddr_t), len); | ||||
|  | ||||
| 	memset(&Conf_Server[i].dst_addr, 0, sizeof(&Conf_Server[i].dst_addr)); | ||||
| 	if (len > sizeof(ng_ipaddr_t)) { | ||||
| 		/* more than one address for this hostname, remember them | ||||
| 		 * in case first address is unreachable/not available */ | ||||
| 		len -= sizeof(ng_ipaddr_t); | ||||
| 		if (len > sizeof(&Conf_Server[i].dst_addr)) { | ||||
| 			len = sizeof(&Conf_Server[i].dst_addr); | ||||
| 			Log(LOG_NOTICE, "Notice: Resolver returned more IP Addresses for host than we can handle," | ||||
| 					" additional addresses dropped"); | ||||
| 		} | ||||
| 		memcpy(&Conf_Server[i].dst_addr, &dest_addrs[1], len); | ||||
| 	} | ||||
| 	/* connect() */ | ||||
| 	New_Server(i); | ||||
| 	New_Server(i, dest_addrs); | ||||
| } /* cb_Read_Forward_Lookup */ | ||||
|  | ||||
|  | ||||
| @@ -1584,10 +1679,10 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events ) | ||||
| #ifdef IDENTAUTH | ||||
| 		++identptr; | ||||
| 		if (*identptr) { | ||||
| 			Log( LOG_INFO, "IDENT lookup for connection %ld: \"%s\".", i, identptr); | ||||
| 			Client_SetUser( c, identptr, true ); | ||||
| 			Log(LOG_INFO, "IDENT lookup for connection %d: \"%s\".", i, identptr); | ||||
| 			Client_SetUser(c, identptr, true); | ||||
| 		} else { | ||||
| 			Log( LOG_INFO, "IDENT lookup for connection %ld: no result.", i ); | ||||
| 			Log(LOG_INFO, "IDENT lookup for connection %d: no result.", i); | ||||
| 		} | ||||
| #endif | ||||
| 	} | ||||
| @@ -1616,19 +1711,6 @@ Simple_Message( int Sock, const char *Msg ) | ||||
| } /* Simple_Error */ | ||||
|  | ||||
|  | ||||
| static int | ||||
| Count_Connections( struct sockaddr_in addr_in ) | ||||
| { | ||||
| 	int i, cnt; | ||||
| 	 | ||||
| 	cnt = 0; | ||||
| 	for( i = 0; i < Pool_Size; i++ ) { | ||||
| 		if(( My_Connections[i].sock > NONE ) && ( My_Connections[i].addr.sin_addr.s_addr == addr_in.sin_addr.s_addr )) cnt++; | ||||
| 	} | ||||
| 	return cnt; | ||||
| } /* Count_Connections */ | ||||
|  | ||||
|  | ||||
| GLOBAL CLIENT * | ||||
| Conn_GetClient( CONN_ID Idx )  | ||||
| { | ||||
| @@ -1639,9 +1721,9 @@ Conn_GetClient( CONN_ID Idx ) | ||||
| 	assert( Idx >= 0 ); | ||||
|  | ||||
| 	c = array_get(&My_ConnArray, sizeof (CONNECTION), (size_t)Idx); | ||||
| 	 | ||||
|  | ||||
| 	assert(c != NULL); | ||||
| 	 | ||||
|  | ||||
| 	return c ? c->client : NULL; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: conn.h,v 1.42 2006/05/10 21:24:01 alex Exp $ | ||||
|  * $Id: conn.h,v 1.46 2008/02/26 22:04:17 fw Exp $ | ||||
|  * | ||||
|  * Connection management (header) | ||||
|  */ | ||||
| @@ -38,6 +38,8 @@ typedef int CONN_ID; | ||||
| #include "defines.h" | ||||
| #include "resolve.h" | ||||
| #include "array.h" | ||||
| #include "tool.h" | ||||
| #include "ng_ipaddr.h" | ||||
|  | ||||
| #ifdef ZLIB | ||||
| #include <zlib.h> | ||||
| @@ -54,11 +56,12 @@ typedef struct _ZipData | ||||
| typedef struct _Connection | ||||
| { | ||||
| 	int sock;			/* Socket handle */ | ||||
| 	struct sockaddr_in addr;	/* Client address */ | ||||
| 	ng_ipaddr_t addr;		/* Client address */ | ||||
| 	RES_STAT res_stat;		/* Status of resolver process */ | ||||
| 	char host[HOST_LEN];		/* Hostname */ | ||||
| 	array rbuf;			/* Read buffer */ | ||||
| 	array wbuf;			/* Write buffer */ | ||||
| 	time_t signon;			/* Signon ("connect") time */ | ||||
| 	time_t lastdata;		/* Last activity */ | ||||
| 	time_t lastping;		/* Last PING */ | ||||
| 	time_t lastprivmsg;		/* Last PRIVMSG */ | ||||
| @@ -83,12 +86,11 @@ GLOBAL long WCounter; | ||||
| GLOBAL void Conn_Init PARAMS((void )); | ||||
| GLOBAL void Conn_Exit PARAMS(( void )); | ||||
|  | ||||
| GLOBAL int Conn_InitListeners PARAMS(( void )); | ||||
| GLOBAL unsigned int Conn_InitListeners PARAMS(( void )); | ||||
| GLOBAL void Conn_ExitListeners PARAMS(( void )); | ||||
|  | ||||
| GLOBAL void Conn_Handler PARAMS(( void )); | ||||
|  | ||||
| GLOBAL bool Conn_Write PARAMS(( CONN_ID Idx, char *Data, size_t Len )); | ||||
| GLOBAL bool Conn_WriteStr PARAMS(( CONN_ID Idx, char *Format, ... )); | ||||
|  | ||||
| GLOBAL void Conn_Close PARAMS(( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient )); | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  * ngIRCd -- The Next Generation IRC Daemon | ||||
|  * Copyright (c)2001-2005 Alexander Barton (alex@barton.de) | ||||
|  * Copyright (c)2001-2007 Alexander Barton (alex@barton.de) | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
| @@ -8,7 +8,7 @@ | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: defines.h,v 1.58 2006/06/15 20:28:15 alex Exp $ | ||||
|  * $Id: defines.h,v 1.62 2007/11/21 12:16:36 alex Exp $ | ||||
|  */ | ||||
|  | ||||
|  | ||||
| @@ -47,14 +47,15 @@ | ||||
|  | ||||
| #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 10		/* Max. nick length, see. RFC 2812 | ||||
| 					   section 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 8		/* Max. lenth of all client modes */ | ||||
| #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 */ | ||||
| @@ -70,13 +71,8 @@ | ||||
| 					   connection in bytes. */ | ||||
| #define WRITEBUFFER_LEN 4096		/* Size of the write buffer of a | ||||
| 					   connection in bytes. */ | ||||
|  | ||||
| #ifdef ZLIB | ||||
| #define ZREADBUFFER_LEN 1024		/* Size of the compressed read buffer | ||||
| 					   of a connection in bytes. */ | ||||
| #define ZWRITEBUFFER_LEN 4096		/* Size of the compressed write buffer | ||||
| 					   of a connection in bytes. */ | ||||
| #endif | ||||
| #define WRITEBUFFER_SLINK_LEN 51200	/* 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. */ | ||||
| @@ -86,7 +82,7 @@ | ||||
| 					   protocol, see doc/Protocol.txt */ | ||||
|  | ||||
| #ifdef IRCPLUS | ||||
| # define IRCPLUSFLAGS "CL"		/* Standard IRC+ flags */ | ||||
| # define IRCPLUSFLAGS "CHL"		/* Standard IRC+ flags */ | ||||
| #endif | ||||
|  | ||||
| #define STARTUP_DELAY 1			/* Delay outgoing connections n seconds | ||||
|   | ||||
| @@ -14,7 +14,7 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: hash.c,v 1.12 2005/07/31 20:13:08 alex Exp $"; | ||||
| static char UNUSED id[] = "$Id: hash.c,v 1.13 2006/10/06 21:23:47 fw Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| @@ -31,7 +31,7 @@ static UINT32 jenkins_hash PARAMS(( register UINT8 *k, register UINT32 length, r | ||||
|  | ||||
|  | ||||
| GLOBAL UINT32 | ||||
| Hash( char *String ) | ||||
| Hash( const char *String ) | ||||
| { | ||||
| 	/* Hash-Wert ueber String berechnen */ | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: hash.h,v 1.5 2005/03/19 18:43:48 fw Exp $ | ||||
|  * $Id: hash.h,v 1.6 2006/10/06 21:23:47 fw Exp $ | ||||
|  * | ||||
|  * Hash calculation (header) | ||||
|  */ | ||||
| @@ -17,8 +17,7 @@ | ||||
| #ifndef __hash_h__ | ||||
| #define __hash_h__ | ||||
|  | ||||
|  | ||||
| GLOBAL UINT32 Hash PARAMS((char *String )); | ||||
| GLOBAL UINT32 Hash PARAMS((const char *String )); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										1031
									
								
								src/ngircd/io.c
									
									
									
									
									
								
							
							
						
						
									
										1031
									
								
								src/ngircd/io.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -7,10 +7,10 @@ | ||||
|  * | ||||
|  * I/O abstraction interface header | ||||
|  * | ||||
|  * $Id: io.h,v 1.3 2005/07/14 09:15:58 alex Exp $ | ||||
|  * $Id: io.h,v 1.4 2006/12/25 22:53:52 alex Exp $ | ||||
|  */ | ||||
|  | ||||
| #ifndef io_H_inclucded | ||||
| #ifndef io_H_included | ||||
| #define io_H_included | ||||
|  | ||||
| #include "portab.h" | ||||
|   | ||||
| @@ -14,7 +14,7 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: irc-channel.c,v 1.35 2006/03/16 20:14:16 fw Exp $"; | ||||
| static char UNUSED id[] = "$Id: irc-channel.c,v 1.45 2008/02/24 18:57:38 fw Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| @@ -40,196 +40,233 @@ static char UNUSED id[] = "$Id: irc-channel.c,v 1.35 2006/03/16 20:14:16 fw Exp | ||||
| #include "irc-channel.h" | ||||
|  | ||||
|  | ||||
| /* | ||||
|  * RFC 2812, (3.2.1 Join message Command): | ||||
|  *  Note that this message | ||||
|  *  accepts a special argument ("0"), which is a special request to leave all | ||||
|  *  channels the user is currently a member of. The server will process this | ||||
|  *  message as if the user had sent a PART command (See Section 3.2.2) for | ||||
|  *  each channel he is a member of. | ||||
|  */ | ||||
| static bool | ||||
| part_from_all_channels(CLIENT* client, CLIENT *target) | ||||
| { | ||||
| 	CL2CHAN *cl2chan; | ||||
| 	CHANNEL *chan; | ||||
|  | ||||
| 	while ((cl2chan = Channel_FirstChannelOf(target))) { | ||||
| 		chan = Channel_GetChannel(cl2chan); | ||||
| 		assert( chan != NULL ); | ||||
| 		Channel_Part(target, client, Channel_Name(chan), Client_ID(target)); | ||||
| 	} | ||||
| 	return CONNECTED; | ||||
| } | ||||
|  | ||||
|  | ||||
| static bool | ||||
| join_allowed(CLIENT *Client, CLIENT *target, CHANNEL *chan, | ||||
| 			const char *channame, const char *key) | ||||
| { | ||||
| 	bool is_invited, is_banned; | ||||
| 	const char *channel_modes; | ||||
|  | ||||
| 	is_banned = Lists_Check(Channel_GetListBans(chan), target); | ||||
| 	is_invited = Lists_Check(Channel_GetListInvites(chan), target); | ||||
|  | ||||
| 	if (is_banned && !is_invited) { | ||||
| 		IRC_WriteStrClient(Client, ERR_BANNEDFROMCHAN_MSG, Client_ID(Client), channame); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	channel_modes = Channel_Modes(chan); | ||||
| 	if ((strchr(channel_modes, 'i')) && !is_invited) { | ||||
| 		/* Channel is "invite-only" (and Client wasn't invited) */ | ||||
| 		IRC_WriteStrClient(Client, ERR_INVITEONLYCHAN_MSG, Client_ID(Client), channame); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	/* Is the channel protected by a key? */ | ||||
| 	if (strchr(channel_modes, 'k') && | ||||
| 		strcmp(Channel_Key(chan), key ? key : "")) | ||||
| 	{ | ||||
| 		IRC_WriteStrClient(Client, ERR_BADCHANNELKEY_MSG, Client_ID(Client), channame); | ||||
| 		return false; | ||||
| 	} | ||||
| 	/* Are there already too many members? */ | ||||
| 	if ((strchr(channel_modes, 'l')) && (Channel_MaxUsers(chan) <= Channel_MemberCount(chan))) { | ||||
| 		IRC_WriteStrClient(Client, ERR_CHANNELISFULL_MSG, Client_ID(Client), channame); | ||||
| 		return false; | ||||
| 	} | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| join_set_channelmodes(CHANNEL *chan, CLIENT *target, const char *flags) | ||||
| { | ||||
| 	if (flags) { | ||||
| 		while (*flags) { | ||||
| 			Channel_UserModeAdd(chan, target, *flags); | ||||
| 			flags++; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* If channel persistent and client is ircop: make client chanop */ | ||||
| 	if (strchr(Channel_Modes(chan), 'P') && strchr(Client_Modes(target), 'o')) | ||||
| 		Channel_UserModeAdd(chan, target, 'o'); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| join_forward(CLIENT *Client, CLIENT *target, CHANNEL *chan, | ||||
| 					const char *channame) | ||||
| { | ||||
| 	char modes[8]; | ||||
|  | ||||
| 	strlcpy(&modes[1], Channel_UserModes(chan, target), sizeof(modes) - 1); | ||||
|  | ||||
| 	if (modes[1]) | ||||
| 		modes[0] = 0x7; | ||||
| 	else | ||||
| 		modes[0] = '\0'; | ||||
| 	/* forward to other servers */ | ||||
| 	IRC_WriteStrServersPrefix(Client, target, "JOIN :%s%s", channame, modes); | ||||
|  | ||||
| 	/* tell users in this channel about the new client */ | ||||
| 	IRC_WriteStrChannelPrefix(Client, chan, target, false, "JOIN :%s", channame); | ||||
| 	if (modes[1]) | ||||
| 		IRC_WriteStrChannelPrefix(Client, chan, target, false, "MODE %s +%s %s", | ||||
| 						channame, &modes[1], Client_ID(target)); | ||||
| } | ||||
|  | ||||
|  | ||||
| static bool | ||||
| join_send_topic(CLIENT *Client, CLIENT *target, CHANNEL *chan, | ||||
| 					const char *channame) | ||||
| { | ||||
| 	const char *topic; | ||||
|  | ||||
| 	if (Client_Type(Client) != CLIENT_USER) | ||||
| 		return true; | ||||
| 	/* acknowledge join */ | ||||
| 	if (!IRC_WriteStrClientPrefix(Client, target, "JOIN :%s", channame)) | ||||
| 		return false; | ||||
|  | ||||
| 	/* Send topic to client, if any */ | ||||
| 	topic = Channel_Topic(chan); | ||||
| 	assert(topic != NULL); | ||||
| 	if (*topic) { | ||||
| 		if (!IRC_WriteStrClient(Client, RPL_TOPIC_MSG, | ||||
| 			Client_ID(Client), channame, topic)) | ||||
| 				return false; | ||||
| #ifndef STRICT_RFC | ||||
| 		if (!IRC_WriteStrClient(Client, RPL_TOPICSETBY_MSG, | ||||
| 			Client_ID(Client), channame, | ||||
| 			Channel_TopicWho(chan), | ||||
| 			Channel_TopicTime(chan))) | ||||
| 				return false; | ||||
| #endif | ||||
| 	} | ||||
| 	/* send list of channel members to client */ | ||||
| 	if (!IRC_Send_NAMES(Client, chan)) | ||||
| 		return false; | ||||
| 	return IRC_WriteStrClient(Client, RPL_ENDOFNAMES_MSG, Client_ID(Client), Channel_Name(chan)); | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| IRC_JOIN( CLIENT *Client, REQUEST *Req ) | ||||
| { | ||||
| 	char *channame, *channame_ptr, *key, *key_ptr, *flags, *topic, modes[8]; | ||||
| 	bool is_new_chan, is_invited, is_banned; | ||||
| 	char *channame, *channame_ptr, *key, *key_ptr, *flags; | ||||
| 	CLIENT *target; | ||||
| 	CHANNEL *chan; | ||||
| 	 | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Req != NULL ); | ||||
|  | ||||
| 	/* Bad number of arguments? */ | ||||
| 	if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); | ||||
| 	if (Req->argc < 1 || Req->argc > 2) | ||||
| 		return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, | ||||
| 					  Client_ID(Client), Req->command); | ||||
|  | ||||
| 	/* Who is the sender? */ | ||||
| 	if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix ); | ||||
| 	else target = Client; | ||||
| 	if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix ); | ||||
| 	if (Client_Type(Client) == CLIENT_SERVER) | ||||
| 		target = Client_Search(Req->prefix); | ||||
| 	else | ||||
| 		target = Client; | ||||
|  | ||||
| 	if (!target) | ||||
| 		return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, Client_ID(Client), Req->prefix); | ||||
|  | ||||
| 	/* Is argument "0"? */ | ||||
| 	if (Req->argc == 1 && !strncmp("0", Req->argv[0], 2)) | ||||
| 		return part_from_all_channels(Client, target); | ||||
|  | ||||
| 	/* Are channel keys given? */ | ||||
| 	if (Req->argc > 1) { | ||||
| 		key = Req->argv[1]; | ||||
| 		key_ptr = strchr(key, ','); | ||||
| 		if (key_ptr) *key_ptr = '\0'; | ||||
| 	} | ||||
| 	else | ||||
| 	} else { | ||||
| 		key = key_ptr = NULL; | ||||
|  | ||||
| 	} | ||||
| 	channame = Req->argv[0]; | ||||
| 	channame_ptr = strchr(channame, ','); | ||||
| 	if (channame_ptr) *channame_ptr = '\0'; | ||||
|  | ||||
| 	/* Channel-Namen durchgehen */ | ||||
| 	while (channame) | ||||
| 	{ | ||||
| 		chan = NULL; flags = NULL; | ||||
| 	while (channame) { | ||||
| 		flags = NULL; | ||||
|  | ||||
| 		/* wird der Channel neu angelegt? */ | ||||
| 		if( Channel_Search( channame )) is_new_chan = false; | ||||
| 		else is_new_chan = true; | ||||
|  | ||||
| 		/* Hat ein Server Channel-User-Modes uebergeben? */ | ||||
| 		if( Client_Type( Client ) == CLIENT_SERVER ) | ||||
| 		{ | ||||
| 			/* Channel-Flags extrahieren */ | ||||
| 			flags = strchr( channame, 0x7 ); | ||||
| 			if( flags ) | ||||
| 			{ | ||||
| 		/* Did the server include channel-user-modes? */ | ||||
| 		if (Client_Type(Client) == CLIENT_SERVER) { | ||||
| 			flags = strchr(channame, 0x7); | ||||
| 			if (flags) { | ||||
| 				*flags = '\0'; | ||||
| 				flags++; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		/* Local client? */ | ||||
| 		if( Client_Type( Client ) == CLIENT_USER ) | ||||
| 		{ | ||||
| 			/* Test if the user has reached his maximum channel count */ | ||||
| 			if(( Conf_MaxJoins > 0 ) && ( Channel_CountForUser( Client ) >= Conf_MaxJoins )) | ||||
| 				return IRC_WriteStrClient( Client, ERR_TOOMANYCHANNELS_MSG, | ||||
| 							Client_ID( Client ), channame ); | ||||
|  | ||||
| 			/* Existiert der Channel bereits, oder wird er im Moment neu erzeugt? */ | ||||
| 			if( is_new_chan ) | ||||
| 			{ | ||||
| 				/* Erster User im Channel: Operator-Flag setzen */ | ||||
| 				flags = "o"; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				/* Existierenden Channel suchen */ | ||||
| 				chan = Channel_Search( channame ); | ||||
| 				assert( chan != NULL ); | ||||
|  | ||||
| 				is_banned = Lists_CheckBanned( target, chan ); | ||||
| 				is_invited = Lists_CheckInvited( target, chan ); | ||||
|  | ||||
| 				/* Testen, ob Client gebanned ist */ | ||||
| 				if(( is_banned == true) &&  ( is_invited == false )) | ||||
| 				{ | ||||
| 					/* Client ist gebanned (und nicht invited): */ | ||||
| 					IRC_WriteStrClient( Client, ERR_BANNEDFROMCHAN_MSG, Client_ID( Client ), channame ); | ||||
|  | ||||
| 					/* Try next name, if any */ | ||||
| 					channame = strtok( NULL, "," ); | ||||
| 					continue; | ||||
| 				} | ||||
|  | ||||
| 				/* Ist der Channel "invite-only"? */ | ||||
| 				if(( strchr( Channel_Modes( chan ), 'i' )) && ( is_invited == false )) | ||||
| 				{ | ||||
| 					/* Channel ist "invite-only" und Client wurde nicht invited: */ | ||||
| 					IRC_WriteStrClient( Client, ERR_INVITEONLYCHAN_MSG, Client_ID( Client ), channame ); | ||||
|  | ||||
| 					/* Try next name, if any */ | ||||
| 					channame = strtok( NULL, "," ); | ||||
| 					continue; | ||||
| 				} | ||||
|  | ||||
| 				/* Is the channel protected by a key? */ | ||||
| 				if(( strchr( Channel_Modes( chan ), 'k' )) && ( strcmp( Channel_Key( chan ), key ? key : "" ) != 0 )) | ||||
| 				{ | ||||
| 					/* Bad channel key! */ | ||||
| 					IRC_WriteStrClient( Client, ERR_BADCHANNELKEY_MSG, Client_ID( Client ), channame ); | ||||
|  | ||||
| 					/* Try next name, if any */ | ||||
| 					channame = strtok( NULL, "," ); | ||||
| 					continue; | ||||
| 				} | ||||
|  | ||||
| 				/* Are there already too many members? */ | ||||
| 				if(( strchr( Channel_Modes( chan ), 'l' )) && ( Channel_MaxUsers( chan ) <= Channel_MemberCount( chan ))) | ||||
| 				{ | ||||
| 					/* Bad channel key! */ | ||||
| 					IRC_WriteStrClient( Client, ERR_CHANNELISFULL_MSG, Client_ID( Client ), channame ); | ||||
|  | ||||
| 					/* Try next name, if any */ | ||||
| 					channame = strtok( NULL, "," ); | ||||
| 					continue; | ||||
| 				} | ||||
| 			} | ||||
| 		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; | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
|  | ||||
| 		/* Local client? */ | ||||
| 		if (Client_Type(Client) == CLIENT_USER) { | ||||
| 			/* Test if the user has reached his maximum channel count */ | ||||
| 			if ((Conf_MaxJoins > 0) && (Channel_CountForUser(Client) >= Conf_MaxJoins)) | ||||
| 				return IRC_WriteStrClient(Client, ERR_TOOMANYCHANNELS_MSG, | ||||
| 							Client_ID(Client), channame); | ||||
| 			if (!chan) /* New Channel: first user will be channel operator */ | ||||
| 				flags = "o"; | ||||
| 			else | ||||
| 				if (!join_allowed(Client, target, chan, channame, key)) | ||||
| 					break; | ||||
| 		} else { | ||||
| 			/* Remote server: we don't need to know whether the | ||||
| 			 * client is invited or not, but we have to make sure | ||||
| 			 * that the "one shot" entries (generated by INVITE | ||||
| 			 * commands) in this list become deleted when a user | ||||
| 			 * joins a channel this way. */ | ||||
| 			chan = Channel_Search( channame ); | ||||
| 			if( chan != NULL ) (void)Lists_CheckInvited( target, chan ); | ||||
| 			if (chan) (void)Lists_Check(Channel_GetListInvites(chan), target); | ||||
| 		} | ||||
|  | ||||
| 		/* Channel joinen (und ggf. anlegen) */ | ||||
| 		if( ! Channel_Join( target, channame )) | ||||
| 		{ | ||||
| 			/* naechsten Namen ermitteln */ | ||||
| 			channame = strtok( NULL, "," ); | ||||
| 			continue; | ||||
| 		} | ||||
| 		if( ! chan ) chan = Channel_Search( channame ); | ||||
| 		assert( chan != NULL ); | ||||
| 		/* Join channel (and create channel if it doesn't exist) */ | ||||
| 		if (!Channel_Join(target, channame)) | ||||
| 			break; | ||||
|  | ||||
| 		/* Modes setzen (wenn vorhanden) */ | ||||
| 		while( flags && *flags ) | ||||
| 		{ | ||||
| 			Channel_UserModeAdd( chan, target, *flags ); | ||||
| 			flags++; | ||||
| 		} | ||||
| 		if (!chan) /* channel is new; it has been created above */ | ||||
| 			chan = Channel_Search(channame); | ||||
| 		assert(chan != NULL); | ||||
|  | ||||
| 		/* Wenn persistenter Channel und IRC-Operator: zum Channel-OP machen */ | ||||
| 		if(( strchr( Channel_Modes( chan ), 'P' )) && ( strchr( Client_Modes( target ), 'o' ))) Channel_UserModeAdd( chan, target, 'o' ); | ||||
| 		join_set_channelmodes(chan, target, flags); | ||||
|  | ||||
| 		/* Muessen Modes an andere Server gemeldet werden? */ | ||||
| 		strlcpy( &modes[1], Channel_UserModes( chan, target ), sizeof( modes ) - 1 ); | ||||
| 		if( modes[1] ) modes[0] = 0x7; | ||||
| 		else modes[0] = '\0'; | ||||
| 		join_forward(Client, target, chan, channame); | ||||
|  | ||||
| 		/* An andere Server weiterleiten */ | ||||
| 		IRC_WriteStrServersPrefix( Client, target, "JOIN :%s%s", channame, modes ); | ||||
|  | ||||
| 		/* im Channel bekannt machen */ | ||||
| 		IRC_WriteStrChannelPrefix( Client, chan, target, false, "JOIN :%s", channame ); | ||||
| 		if( modes[1] ) | ||||
| 		{ | ||||
| 			/* Modes im Channel bekannt machen */ | ||||
| 			IRC_WriteStrChannelPrefix( Client, chan, target, false, "MODE %s +%s %s", channame, &modes[1], Client_ID( target )); | ||||
| 		} | ||||
|  | ||||
| 		if( Client_Type( Client ) == CLIENT_USER ) | ||||
| 		{ | ||||
| 			/* an Client bestaetigen */ | ||||
| 			IRC_WriteStrClientPrefix( Client, target, "JOIN :%s", channame ); | ||||
|  | ||||
| 			/* Send topic to client, if any */ | ||||
| 			topic = Channel_Topic(chan); | ||||
| 			if (*topic) { | ||||
| 				IRC_WriteStrClient(Client, RPL_TOPIC_MSG, | ||||
| 					Client_ID(Client), channame, topic); | ||||
| #ifndef STRICT_RFC | ||||
| 				IRC_WriteStrClient(Client, RPL_TOPICSETBY_MSG, | ||||
| 					Client_ID(Client), channame, | ||||
| 					Channel_TopicWho(chan), | ||||
| 					Channel_TopicTime(chan)); | ||||
| #endif | ||||
| 			} | ||||
|  | ||||
| 			/* Mitglieder an Client Melden */ | ||||
| 			IRC_Send_NAMES( Client, chan ); | ||||
| 			IRC_WriteStrClient( Client, RPL_ENDOFNAMES_MSG, Client_ID( Client ), Channel_Name( chan )); | ||||
| 		} | ||||
| 		if (!join_send_topic(Client, target, chan, channame)) | ||||
| 			break; /* write error */ | ||||
|  | ||||
| 		/* next channel? */ | ||||
| 		channame = channame_ptr; | ||||
| @@ -249,36 +286,37 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req ) | ||||
| } /* IRC_JOIN */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Handler for the IRC "PART" command. | ||||
|  */ | ||||
| GLOBAL bool | ||||
| IRC_PART( CLIENT *Client, REQUEST *Req ) | ||||
| IRC_PART(CLIENT * Client, REQUEST * Req) | ||||
| { | ||||
| 	CLIENT *target; | ||||
| 	char *chan; | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Req != NULL ); | ||||
| 	assert(Client != NULL); | ||||
| 	assert(Req != NULL); | ||||
|  | ||||
| 	/* Falsche Anzahl Parameter? */ | ||||
| 	if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); | ||||
| 	if (Req->argc < 1 || Req->argc > 2) | ||||
| 		return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, | ||||
| 					  Client_ID(Client), Req->command); | ||||
|  | ||||
| 	/* 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 ); | ||||
| 	/* Get the sender */ | ||||
| 	if (Client_Type(Client) == CLIENT_SERVER) | ||||
| 		target = Client_Search(Req->prefix); | ||||
| 	else | ||||
| 		target = Client; | ||||
| 	if (!target) | ||||
| 		return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, | ||||
| 					  Client_ID(Client), Req->prefix); | ||||
|  | ||||
| 	/* Channel-Namen durchgehen */ | ||||
| 	chan = strtok( Req->argv[0], "," ); | ||||
| 	while( chan ) | ||||
| 	{ | ||||
| 		if( ! Channel_Part( target, Client, chan, Req->argc > 1 ? Req->argv[1] : Client_ID( target ))) | ||||
| 		{ | ||||
| 			/* naechsten Namen ermitteln */ | ||||
| 			chan = strtok( NULL, "," ); | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		/* naechsten Namen ermitteln */ | ||||
| 		chan = strtok( NULL, "," ); | ||||
| 	/* Loop over all the given channel names */ | ||||
| 	chan = strtok(Req->argv[0], ","); | ||||
| 	while (chan) { | ||||
| 		Channel_Part(target, Client, chan, | ||||
| 			     Req->argc > 1 ? Req->argv[1] : Client_ID(target)); | ||||
| 		chan = strtok(NULL, ","); | ||||
| 	} | ||||
| 	return CONNECTED; | ||||
| } /* IRC_PART */ | ||||
| @@ -491,7 +529,7 @@ IRC_CHANINFO( CLIENT *Client, REQUEST *Req ) | ||||
| 			{ | ||||
| 				if( *ptr == 'l' ) | ||||
| 				{ | ||||
| 					snprintf( l, sizeof( l ), " %ld", Channel_MaxUsers( chan )); | ||||
| 					snprintf( l, sizeof( l ), " %lu", Channel_MaxUsers( chan )); | ||||
| 					strlcat( modes_add, l, sizeof( modes_add )); | ||||
| 				} | ||||
| 				if( *ptr == 'k' ) | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  * ngIRCd -- The Next Generation IRC Daemon | ||||
|  * Copyright (c)2001-2005 Alexander Barton (alex@barton.de) | ||||
|  * Copyright (c)2001-2008 Alexander Barton (alex@barton.de) | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
| @@ -14,8 +14,6 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: irc-info.c,v 1.33 2006/05/10 21:24:01 alex Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| #include <errno.h> | ||||
| @@ -25,7 +23,6 @@ static char UNUSED id[] = "$Id: irc-info.c,v 1.33 2006/05/10 21:24:01 alex Exp $ | ||||
| #include <strings.h> | ||||
|  | ||||
| #include "ngircd.h" | ||||
| #include "cvs-version.h" | ||||
| #include "conn-func.h" | ||||
| #include "conn-zip.h" | ||||
| #include "client.h" | ||||
| @@ -35,6 +32,7 @@ static char UNUSED id[] = "$Id: irc-info.c,v 1.33 2006/05/10 21:24:01 alex Exp $ | ||||
| #include "defines.h" | ||||
| #include "log.h" | ||||
| #include "messages.h" | ||||
| #include "match.h" | ||||
| #include "tool.h" | ||||
| #include "parse.h" | ||||
| #include "irc-write.h" | ||||
| @@ -84,6 +82,71 @@ IRC_ADMIN(CLIENT *Client, REQUEST *Req ) | ||||
| } /* IRC_ADMIN */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Handler for the IRC command "INFO". | ||||
|  * See RFC 2812 section 3.4.10. | ||||
|  */ | ||||
| GLOBAL bool | ||||
| IRC_INFO(CLIENT * Client, REQUEST * Req) | ||||
| { | ||||
| 	CLIENT *target, *prefix; | ||||
| 	char msg[510]; | ||||
|  | ||||
| 	assert(Client != NULL); | ||||
| 	assert(Req != NULL); | ||||
|  | ||||
| 	/* Wrong number of parameters? */ | ||||
| 	if (Req->argc > 1) | ||||
| 		return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, | ||||
| 					  Client_ID(Client), Req->command); | ||||
|  | ||||
| 	/* Determine prefix */ | ||||
| 	if (Client_Type(Client) == CLIENT_SERVER) | ||||
| 		prefix = Client_Search(Req->prefix); | ||||
| 	else | ||||
| 		prefix = Client; | ||||
| 	if (!prefix) | ||||
| 		return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, | ||||
| 					  Client_ID(Client), Req->prefix); | ||||
|  | ||||
| 	/* Look for a target */ | ||||
| 	if (Req->argc > 0) | ||||
| 		target = Client_Search(Req->argv[0]); | ||||
| 	else | ||||
| 		target = Client_ThisServer(); | ||||
| 	 | ||||
| 	/* Make sure that the target is a server */ | ||||
| 	if (target && Client_Type(target) != CLIENT_SERVER) | ||||
| 		target = Client_Introducer(target); | ||||
|  | ||||
| 	if (!target) | ||||
| 		return IRC_WriteStrClient(prefix, ERR_NOSUCHSERVER_MSG, | ||||
| 					  Client_ID(prefix), Req->argv[0]); | ||||
|  | ||||
| 	/* Pass on to another server? */ | ||||
| 	if (target != Client_ThisServer()) { | ||||
| 		IRC_WriteStrClientPrefix(target, prefix, "INFO %s", | ||||
| 					 Req->argv[0]); | ||||
| 		return CONNECTED; | ||||
| 	} | ||||
|  | ||||
| 	if (!IRC_WriteStrClient(Client, RPL_INFO_MSG, Client_ID(prefix), | ||||
| 				NGIRCd_Version)) | ||||
| 		return DISCONNECTED; | ||||
| 	 | ||||
| 	strlcpy(msg, "Server has been started ", sizeof(msg)); | ||||
| 	strlcat(msg, NGIRCd_StartStr, sizeof(msg)); | ||||
| 	if (!IRC_WriteStrClient(Client, RPL_INFO_MSG, Client_ID(prefix), msg)) | ||||
| 		return DISCONNECTED; | ||||
|  | ||||
| 	if (!IRC_WriteStrClient(Client, RPL_ENDOFINFO_MSG, Client_ID(prefix))) | ||||
| 		return DISCONNECTED; | ||||
|  | ||||
| 	IRC_SetPenalty(Client, 2); | ||||
| 	return CONNECTED; | ||||
| } /* IRC_INFO */ | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| IRC_ISON( CLIENT *Client, REQUEST *Req ) | ||||
| { | ||||
| @@ -335,6 +398,41 @@ IRC_NAMES( CLIENT *Client, REQUEST *Req ) | ||||
| } /* IRC_NAMES */ | ||||
|  | ||||
|  | ||||
| static unsigned int | ||||
| t_diff(time_t *t, const time_t div) | ||||
| { | ||||
| 	time_t diff, remain; | ||||
|  | ||||
| 	diff = *t / div; | ||||
|  | ||||
| 	remain = diff * div; | ||||
| 	*t -= remain; | ||||
|  | ||||
| 	return diff; | ||||
| } | ||||
|  | ||||
|  | ||||
| static unsigned int | ||||
| uptime_days(time_t *now) | ||||
| { | ||||
| 	return t_diff(now, 60 * 60 * 24); | ||||
| } | ||||
|  | ||||
|  | ||||
| static unsigned int | ||||
| uptime_hrs(time_t *now) | ||||
| { | ||||
| 	return t_diff(now, 60 * 60); | ||||
| } | ||||
|  | ||||
|  | ||||
| static unsigned int | ||||
| uptime_mins(time_t *now) | ||||
| { | ||||
| 	 return t_diff(now, 60); | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| IRC_STATS( CLIENT *Client, REQUEST *Req ) | ||||
| { | ||||
| @@ -342,78 +440,110 @@ IRC_STATS( CLIENT *Client, REQUEST *Req ) | ||||
| 	CONN_ID con; | ||||
| 	char query; | ||||
| 	COMMAND *cmd; | ||||
| 	time_t time_now; | ||||
| 	unsigned int days, hrs, mins; | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Req != NULL ); | ||||
|  | ||||
| 	/* Falsche Anzahl Parameter? */ | ||||
| 	if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); | ||||
| 	if (Req->argc > 2) | ||||
| 		return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, Client_ID(Client), Req->command); | ||||
|  | ||||
| 	/* From aus Prefix ermitteln */ | ||||
| 	if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix ); | ||||
| 	else from = Client; | ||||
| 	if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix ); | ||||
| 	if (Client_Type(Client) == CLIENT_SERVER) | ||||
| 		from = Client_Search(Req->prefix); | ||||
| 	else | ||||
| 		from = Client; | ||||
|  | ||||
| 	if( Req->argc == 2 ) | ||||
| 	{ | ||||
| 	if (! from) | ||||
| 		return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix); | ||||
|  | ||||
| 	if (Req->argc == 2) { | ||||
| 		/* an anderen Server forwarden */ | ||||
| 		target = Client_Search( Req->argv[1] ); | ||||
| 		if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[1] ); | ||||
| 		if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) | ||||
| 			return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[1] ); | ||||
|  | ||||
| 		if( target != Client_ThisServer( )) | ||||
| 		{ | ||||
| 		if( target != Client_ThisServer()) { | ||||
| 			/* Ok, anderer Server ist das Ziel: forwarden */ | ||||
| 			return IRC_WriteStrClientPrefix( target, from, "STATS %s %s", Req->argv[0], Req->argv[1] ); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if( Req->argc > 0 ) query = Req->argv[0][0] ? Req->argv[0][0] : '*'; | ||||
| 	else query = '*'; | ||||
| 	if (Req->argc > 0) | ||||
| 		query = Req->argv[0][0] ? Req->argv[0][0] : '*'; | ||||
| 	else | ||||
| 		query = '*'; | ||||
|  | ||||
| 	switch ( query ) | ||||
| 	{ | ||||
| 	switch (query) { | ||||
| 		case 'l':	/* Links */ | ||||
| 		case 'L': | ||||
| 			con = Conn_First( ); | ||||
| 			while( con != NONE ) | ||||
| 			{ | ||||
| 				cl = Conn_GetClient( con ); | ||||
| 				if( cl && (( Client_Type( cl ) == CLIENT_SERVER ) || ( cl == Client ))) | ||||
| 				{ | ||||
| 			time_now = time(NULL); | ||||
| 			for (con = Conn_First(); con != NONE ;con = Conn_Next(con)) { | ||||
| 				cl = Conn_GetClient(con); | ||||
| 				if (!cl) | ||||
| 					continue; | ||||
| 				if ((Client_Type(cl) == CLIENT_SERVER) || (cl == Client)) { | ||||
| 					/* Server link or our own connection */ | ||||
| #ifdef ZLIB | ||||
| 					if( Conn_Options( con ) & CONN_ZIP ) | ||||
| 					{ | ||||
| 						if( ! IRC_WriteStrClient( from, RPL_STATSLINKINFOZIP_MSG, Client_ID( from ), Client_Mask( cl ), Conn_SendQ( con ), Conn_SendMsg( con ), Zip_SendBytes( con ), Conn_SendBytes( con ), Conn_RecvMsg( con ), Zip_RecvBytes( con ), Conn_RecvBytes( con ), (long)( time( NULL ) - Conn_StartTime( con )))) return DISCONNECTED; | ||||
| 					if (Conn_Options(con) & CONN_ZIP) { | ||||
| 						if (!IRC_WriteStrClient(from, RPL_STATSLINKINFOZIP_MSG, | ||||
| 							Client_ID(from), Client_Mask(cl), Conn_SendQ(con), | ||||
| 							Conn_SendMsg(con), Zip_SendBytes(con), Conn_SendBytes(con), | ||||
| 							Conn_RecvMsg(con), Zip_RecvBytes(con), Conn_RecvBytes(con), (long)(time_now - Conn_StartTime(con)))) | ||||
| 								return DISCONNECTED; | ||||
| 						continue; | ||||
| 					} | ||||
| 					else | ||||
| #endif | ||||
| 					{ | ||||
| 						if( ! IRC_WriteStrClient( from, RPL_STATSLINKINFO_MSG, Client_ID( from ), Client_Mask( cl ), Conn_SendQ( con ), Conn_SendMsg( con ), Conn_SendBytes( con ), Conn_RecvMsg( con ), Conn_RecvBytes( con ), (long)( time( NULL ) - Conn_StartTime( con )))) return DISCONNECTED; | ||||
| 					} | ||||
| 					if (!IRC_WriteStrClient(from, RPL_STATSLINKINFO_MSG, Client_ID(from), | ||||
| 						Client_Mask(cl), Conn_SendQ(con), Conn_SendMsg(con), Conn_SendBytes(con), | ||||
| 						Conn_RecvMsg(con), Conn_RecvBytes(con), (long)(time_now - Conn_StartTime(con)))) | ||||
| 							return DISCONNECTED; | ||||
| 				} | ||||
| 				con = Conn_Next( con ); | ||||
| 			} | ||||
| 			break; | ||||
| 		case 'm':	/* IRC-Befehle */ | ||||
| 		case 'm':	/* IRC-Commands */ | ||||
| 		case 'M': | ||||
| 			cmd = Parse_GetCommandStruct( ); | ||||
| 			while( cmd->name ) | ||||
| 			{ | ||||
| 				if( cmd->lcount > 0 || cmd->rcount > 0 ) | ||||
| 				{ | ||||
| 					if( ! IRC_WriteStrClient( from, RPL_STATSCOMMANDS_MSG, Client_ID( from ), cmd->name, cmd->lcount, cmd->bytes, cmd->rcount )) return DISCONNECTED; | ||||
| 				} | ||||
| 				cmd++; | ||||
| 			for (; cmd->name ; cmd++) { | ||||
| 				if (cmd->lcount == 0 && cmd->rcount == 0) | ||||
| 					continue; | ||||
| 				if (!IRC_WriteStrClient(from, RPL_STATSCOMMANDS_MSG, Client_ID(from), | ||||
| 						cmd->name, cmd->lcount, cmd->bytes, cmd->rcount)) | ||||
| 							return DISCONNECTED; | ||||
| 			} | ||||
| 			break; | ||||
| 		case 'u':	/* server uptime */ | ||||
| 		case 'U': | ||||
| 			time_now = time(NULL) - NGIRCd_Start; | ||||
| 			days = uptime_days(&time_now); | ||||
| 			hrs = uptime_hrs(&time_now); | ||||
| 			mins = uptime_mins(&time_now); | ||||
| 			if (!IRC_WriteStrClient(from, RPL_STATSUPTIME, Client_ID(from), | ||||
| 					days, hrs, mins, (unsigned int) time_now)) | ||||
| 						return DISCONNECTED; | ||||
| 			break; | ||||
| 	} | ||||
|  | ||||
| 	IRC_SetPenalty( from, 2 ); | ||||
| 	return IRC_WriteStrClient( from, RPL_ENDOFSTATS_MSG, Client_ID( from ), query ); | ||||
| 	IRC_SetPenalty(from, 2); | ||||
| 	return IRC_WriteStrClient(from, RPL_ENDOFSTATS_MSG, Client_ID(from), query); | ||||
| } /* IRC_STATS */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Handler for the IRC command "SUMMON". | ||||
|  * See RFC 2812 section 4.5. ngIRCd doesn't implement this functionality and | ||||
|  * therefore answers with ERR_SUMMONDISABLED. | ||||
|  */ | ||||
| GLOBAL bool | ||||
| IRC_SUMMON(CLIENT * Client, REQUEST * Req) | ||||
| { | ||||
| 	return IRC_WriteStrClient(Client, ERR_SUMMONDISABLED_MSG, | ||||
| 				  Client_ID(Client), Req->command); | ||||
| } /* IRC_SUMMON */ | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| IRC_TIME( CLIENT *Client, REQUEST *Req ) | ||||
| { | ||||
| @@ -491,13 +621,22 @@ IRC_USERHOST( CLIENT *Client, REQUEST *Req ) | ||||
| } /* IRC_USERHOST */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Handler for the IRC command "USERS". | ||||
|  * See RFC 2812 section 4.6. As suggested there the command is disabled. | ||||
|  */ | ||||
| GLOBAL bool | ||||
| IRC_USERS(CLIENT * Client, REQUEST * Req) | ||||
| { | ||||
| 	return IRC_WriteStrClient(Client, ERR_USERSDISABLED_MSG, | ||||
| 				  Client_ID(Client), Req->command); | ||||
| } /* IRC_USERS */ | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| IRC_VERSION( CLIENT *Client, REQUEST *Req ) | ||||
| { | ||||
| 	CLIENT *target, *prefix; | ||||
| #ifdef CVSDATE | ||||
| 	char ver[12], vertxt[30]; | ||||
| #endif | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Req != NULL ); | ||||
| @@ -524,25 +663,110 @@ IRC_VERSION( CLIENT *Client, REQUEST *Req ) | ||||
| 		return CONNECTED; | ||||
| 	} | ||||
|  | ||||
| 	/* mit Versionsinfo antworten */ | ||||
| 	IRC_SetPenalty( Client, 1 ); | ||||
| #ifdef CVSDATE | ||||
| 	strlcpy( ver, CVSDATE, sizeof( ver )); | ||||
| 	strncpy( ver + 4, ver + 5, 2 ); | ||||
| 	strncpy( ver + 6, ver + 8, 3 ); | ||||
| 	snprintf( vertxt, sizeof( vertxt ), "%s(%s)", PACKAGE_VERSION, ver ); | ||||
| 	return IRC_WriteStrClient( Client, RPL_VERSION_MSG, Client_ID( prefix ), PACKAGE_NAME, vertxt, NGIRCd_DebugLevel, Conf_ServerName, NGIRCd_VersionAddition ); | ||||
| #else | ||||
| 	return IRC_WriteStrClient( Client, RPL_VERSION_MSG, Client_ID( prefix ), PACKAGE_NAME, PACKAGE_VERSION, NGIRCd_DebugLevel, Conf_ServerName, NGIRCd_VersionAddition ); | ||||
| #endif | ||||
| 	/* send version information */ | ||||
| 	IRC_SetPenalty(Client, 1); | ||||
| 	return IRC_WriteStrClient(Client, RPL_VERSION_MSG, Client_ID(prefix), | ||||
| 				  PACKAGE_NAME, PACKAGE_VERSION, | ||||
| 				  NGIRCd_DebugLevel, Conf_ServerName, | ||||
| 				  NGIRCd_VersionAddition); | ||||
| } /* IRC_VERSION */ | ||||
|  | ||||
|  | ||||
| static bool | ||||
| write_whoreply(CLIENT *Client, CLIENT *c, const char *channelname, const char *flags) | ||||
| { | ||||
| 	return IRC_WriteStrClient(Client, RPL_WHOREPLY_MSG, Client_ID(Client), channelname, | ||||
| 			Client_User(c), Client_Hostname(c), Client_ID(Client_Introducer(c)), Client_ID(c), | ||||
| 			flags, Client_Hops(c), Client_Info(c)); | ||||
| } | ||||
|  | ||||
|  | ||||
| static const char * | ||||
| who_flags_status(const char *client_modes) | ||||
| { | ||||
| 	if (strchr(client_modes, 'a')) | ||||
| 		return "G"; /* away */ | ||||
| 	return "H"; | ||||
| } | ||||
|  | ||||
|  | ||||
| static const char * | ||||
| who_flags_qualifier(const char *chan_user_modes) | ||||
| { | ||||
| 	if (strchr(chan_user_modes, 'o')) | ||||
| 		return "@"; | ||||
| 	else if (strchr(chan_user_modes, 'v')) | ||||
| 		return "+"; | ||||
| 	return ""; | ||||
| } | ||||
|  | ||||
|  | ||||
| static bool | ||||
| IRC_Send_WHO(CLIENT *Client, CHANNEL *Chan, bool OnlyOps) | ||||
| { | ||||
| 	bool is_visible, is_member, is_ircop; | ||||
| 	CL2CHAN *cl2chan; | ||||
| 	const char *client_modes; | ||||
| 	const char *chan_user_modes; | ||||
| 	char flags[8]; | ||||
| 	CLIENT *c; | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Chan != NULL ); | ||||
|  | ||||
| 	is_member = Channel_IsMemberOf(Chan, Client); | ||||
|  | ||||
| 	/* Secret channel? */ | ||||
| 	if (!is_member && strchr(Channel_Modes(Chan), 's')) | ||||
| 		return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), Channel_Name(Chan)); | ||||
|  | ||||
| 	cl2chan = Channel_FirstMember(Chan); | ||||
| 	for (; cl2chan ; cl2chan = Channel_NextMember(Chan, cl2chan)) { | ||||
| 		c = Channel_GetClient(cl2chan); | ||||
|  | ||||
| 		client_modes = Client_Modes(c); | ||||
| 		is_ircop = strchr(client_modes, 'o') != NULL; | ||||
| 		if (OnlyOps && !is_ircop) | ||||
| 			continue; | ||||
|  | ||||
| 		is_visible = strchr(client_modes, 'i') == NULL; | ||||
| 		if (is_member || is_visible) { | ||||
| 			strcpy(flags, who_flags_status(client_modes)); | ||||
| 			if (is_ircop) | ||||
| 				strlcat(flags, "*", sizeof(flags)); | ||||
|  | ||||
| 			chan_user_modes = Channel_UserModes(Chan, c); | ||||
| 			strlcat(flags, who_flags_qualifier(chan_user_modes), sizeof(flags)); | ||||
|  | ||||
| 			if (!write_whoreply(Client, c, Channel_Name(Chan), flags)) | ||||
| 				return DISCONNECTED; | ||||
| 		} | ||||
| 	} | ||||
| 	return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), Channel_Name(Chan)); | ||||
| } /* IRC_Send_WHO */ | ||||
|  | ||||
|  | ||||
|  | ||||
| static bool | ||||
| MatchCaseInsensitive(const char *pattern, const char *searchme) | ||||
| { | ||||
| 	char haystack[COMMAND_LEN]; | ||||
|  | ||||
| 	strlcpy(haystack, searchme, sizeof(haystack)); | ||||
|  | ||||
| 	ngt_LowerStr(haystack); | ||||
|  | ||||
| 	return Match(pattern, haystack); | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| IRC_WHO( CLIENT *Client, REQUEST *Req ) | ||||
| { | ||||
| 	bool ok, only_ops; | ||||
| 	char flags[8], *ptr; | ||||
| 	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; | ||||
| @@ -550,78 +774,102 @@ IRC_WHO( CLIENT *Client, REQUEST *Req ) | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Req != NULL ); | ||||
|  | ||||
| 	/* Falsche Anzahl Parameter? */ | ||||
| 	if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); | ||||
| 	if (Req->argc > 2) | ||||
| 		return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); | ||||
|  | ||||
| 	only_ops = false; | ||||
| 	chan = NULL; | ||||
| 	have_arg = false; | ||||
|  | ||||
| 	if( Req->argc == 2 ) | ||||
| 	{ | ||||
| 		/* Nur OPs anzeigen? */ | ||||
| 		if( strcmp( Req->argv[1], "o" ) == 0 ) only_ops = true; | ||||
| 	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 | ||||
| 	} | ||||
|  | ||||
| 	if( Req->argc >= 1 ) | ||||
| 	{ | ||||
| 		/* wurde ein Channel oder Nick-Mask angegeben? */ | ||||
| 		chan = Channel_Search( Req->argv[0] ); | ||||
| 	IRC_SetPenalty(Client, 1); | ||||
| 	if (Req->argc >= 1) { /* Channel or Mask. */ | ||||
| 		chan = Channel_Search(Req->argv[0]); | ||||
| 		if (chan) | ||||
| 			return IRC_Send_WHO(Client, chan, only_ops); | ||||
| 		if (strcmp(Req->argv[0], "0") != 0) { /* RFC stupidity, same as no arguments */ | ||||
| 			have_arg = true; | ||||
| 			strlcpy(pattern, Req->argv[0], sizeof(pattern)); | ||||
| 			ngt_LowerStr(pattern); | ||||
| 			IRC_SetPenalty(Client, 3); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if( chan ) | ||||
| 	{ | ||||
| 		/* User eines Channels ausgeben */ | ||||
| 		if( ! IRC_Send_WHO( Client, chan, only_ops )) return DISCONNECTED; | ||||
| 	} | ||||
| 	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; | ||||
|  | ||||
| 	c = Client_First( ); | ||||
| 	while( c ) | ||||
| 	{ | ||||
| 		if(( Client_Type( c ) == CLIENT_USER ) && ( ! strchr( Client_Modes( c ), 'i' ))) | ||||
| 		{ | ||||
| 			ok = false; | ||||
| 			if( Req->argc == 0 ) ok = true; | ||||
| 			else | ||||
| 			{ | ||||
| 				if( strcasecmp( Req->argv[0], Client_ID( c )) == 0 ) ok = true; | ||||
| 				else if( strcmp( Req->argv[0], "0" ) == 0 ) ok = true; | ||||
| 			} | ||||
| 		if (only_ops && !strchr(client_modes, 'o')) | ||||
| 			continue; | ||||
|  | ||||
| 			if( ok && (( ! only_ops ) || ( strchr( Client_Modes( c ), 'o' )))) | ||||
| 			{ | ||||
| 				/* Get flags */ | ||||
| 				strcpy( flags, "H" ); | ||||
| 				if( strchr( Client_Modes( c ), 'o' )) strlcat( flags, "*", sizeof( flags )); | ||||
| 		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 */ | ||||
|  | ||||
| 				/* Search suitable channel */ | ||||
| 				cl2chan = Channel_FirstChannelOf( c ); | ||||
| 				while( cl2chan ) | ||||
| 				{ | ||||
| 					cn = Channel_GetChannel( cl2chan ); | ||||
| 					if( Channel_IsMemberOf( cn, Client ) || | ||||
| 					    ! strchr( Channel_Modes( cn ), 's' )) | ||||
| 					{ | ||||
| 						ptr = Channel_Name( cn ); | ||||
| 						break; | ||||
| 					} | ||||
| 					cl2chan = Channel_NextChannelOf( c, cl2chan ); | ||||
| 				} | ||||
| 				if( ! cl2chan ) ptr = "*"; | ||||
|  | ||||
| 				if( ! IRC_WriteStrClient( Client, RPL_WHOREPLY_MSG, Client_ID( Client ), ptr, Client_User( c ), Client_Hostname( c ), Client_ID( Client_Introducer( c )), Client_ID( c ), flags, Client_Hops( c ), Client_Info( c ))) return DISCONNECTED; | ||||
| 			} | ||||
| 			if (!client_match) /* This isn't the client you're looking for */ | ||||
| 				continue; | ||||
| 		} | ||||
|  | ||||
| 		/* naechster Client */ | ||||
| 		c = Client_Next( c ); | ||||
| 		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( chan ) return IRC_WriteStrClient( Client, RPL_ENDOFWHO_MSG, Client_ID( Client ), Channel_Name( chan )); | ||||
| 	else if( Req->argc == 0 ) return IRC_WriteStrClient( Client, RPL_ENDOFWHO_MSG, Client_ID( Client ), "*" ); | ||||
| 	else return IRC_WriteStrClient( Client, RPL_ENDOFWHO_MSG, Client_ID( Client ), Req->argv[0] ); | ||||
| 	if (Req->argc > 0) | ||||
| 		channelname = Req->argv[0]; | ||||
| 	else | ||||
| 		channelname = "*"; | ||||
|  | ||||
| 	return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), channelname); | ||||
| } /* IRC_WHO */ | ||||
|  | ||||
|  | ||||
| @@ -706,10 +954,13 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req ) | ||||
| 		if( ! IRC_WriteStrClient( from, RPL_WHOISOPERATOR_MSG, Client_ID( from ), Client_ID( c ))) return DISCONNECTED; | ||||
| 	} | ||||
|  | ||||
| 	/* Idle (only local clients) */ | ||||
| 	if( Client_Conn( c ) > NONE ) | ||||
| 	{ | ||||
| 		if( ! IRC_WriteStrClient( from, RPL_WHOISIDLE_MSG, Client_ID( from ), Client_ID( c ), Conn_GetIdle( Client_Conn ( c )))) return DISCONNECTED; | ||||
| 	/* Idle and signon time (local clients only!) */ | ||||
| 	if (Client_Conn(c) > NONE ) { | ||||
| 		if (! IRC_WriteStrClient(from, RPL_WHOISIDLE_MSG, | ||||
| 			Client_ID(from), Client_ID(c), | ||||
| 			(unsigned long)Conn_GetIdle(Client_Conn(c)), | ||||
| 			(unsigned long)Conn_GetSignon(Client_Conn(c)))) | ||||
| 				return DISCONNECTED; | ||||
| 	} | ||||
|  | ||||
| 	/* Away? */ | ||||
| @@ -832,7 +1083,10 @@ IRC_WHOWAS( CLIENT *Client, REQUEST *Req ) | ||||
| GLOBAL bool | ||||
| IRC_Send_LUSERS( CLIENT *Client ) | ||||
| { | ||||
| 	long cnt; | ||||
| 	unsigned long cnt; | ||||
| #ifndef STRICT_RFC | ||||
| 	unsigned long max; | ||||
| #endif | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
|  | ||||
| @@ -861,27 +1115,38 @@ IRC_Send_LUSERS( CLIENT *Client ) | ||||
|  | ||||
| #ifndef STRICT_RFC | ||||
| 	/* Maximum number of local users */ | ||||
| 	if( ! IRC_WriteStrClient( Client, RPL_LOCALUSERS_MSG, Client_ID( Client ), Client_MyUserCount( ), Client_MyMaxUserCount( ))) return DISCONNECTED; | ||||
| 	cnt = Client_MyUserCount(); | ||||
| 	max = Client_MyMaxUserCount(); | ||||
| 	if (! IRC_WriteStrClient(Client, RPL_LOCALUSERS_MSG, Client_ID(Client), | ||||
| 			cnt, max, cnt, max)) | ||||
| 		return DISCONNECTED; | ||||
| 	/* Maximum number of users in the network */ | ||||
| 	if( ! IRC_WriteStrClient( Client, RPL_NETUSERS_MSG, Client_ID( Client ), Client_UserCount( ), Client_MaxUserCount( ))) return DISCONNECTED; | ||||
| 	cnt = Client_UserCount(); | ||||
| 	max = Client_MaxUserCount(); | ||||
| 	if(! IRC_WriteStrClient(Client, RPL_NETUSERS_MSG, Client_ID(Client), | ||||
| 			cnt, max, cnt, max)) | ||||
| 		return DISCONNECTED; | ||||
| #endif | ||||
| 	 | ||||
| 	return CONNECTED; | ||||
| } /* IRC_Send_LUSERS */ | ||||
|  | ||||
|  | ||||
| static bool Show_MOTD_Start(CLIENT *Client) | ||||
| static bool | ||||
| Show_MOTD_Start(CLIENT *Client) | ||||
| { | ||||
| 	return IRC_WriteStrClient(Client, RPL_MOTDSTART_MSG, | ||||
| 		Client_ID( Client ), Client_ID( Client_ThisServer( ))); | ||||
| } | ||||
|  | ||||
| static bool Show_MOTD_Sendline(CLIENT *Client, const char *msg) | ||||
| static bool | ||||
| Show_MOTD_Sendline(CLIENT *Client, const char *msg) | ||||
| { | ||||
| 	return IRC_WriteStrClient(Client, RPL_MOTD_MSG, Client_ID( Client ), msg); | ||||
| } | ||||
|  | ||||
| static bool Show_MOTD_End(CLIENT *Client) | ||||
| static bool | ||||
| Show_MOTD_End(CLIENT *Client) | ||||
| { | ||||
| 	return IRC_WriteStrClient( Client, RPL_ENDOFMOTD_MSG, Client_ID( Client )); | ||||
| } | ||||
| @@ -910,8 +1175,10 @@ IRC_Show_MOTD( CLIENT *Client ) | ||||
| 		return IRC_WriteStrClient( Client, ERR_NOMOTD_MSG, Client_ID( Client ) ); | ||||
| 	} | ||||
|  | ||||
| 	if (!Show_MOTD_Start( Client )) | ||||
| 		return DISCONNECTED; | ||||
| 	if (!Show_MOTD_Start( Client )) { | ||||
| 		fclose(fd); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	while (fgets( line, (int)sizeof line, fd )) { | ||||
| 		ngt_TrimLastChr( line, '\n'); | ||||
| @@ -982,52 +1249,23 @@ IRC_Send_NAMES( CLIENT *Client, CHANNEL *Chan ) | ||||
| } /* IRC_Send_NAMES */ | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Send the ISUPPORT numeric (005). | ||||
|  * This numeric indicates the features that are supported by this server. | ||||
|  * See <http://www.irc.org/tech_docs/005.html> for details. | ||||
|  */ | ||||
| GLOBAL bool | ||||
| IRC_Send_WHO( CLIENT *Client, CHANNEL *Chan, bool OnlyOps ) | ||||
| IRC_Send_ISUPPORT PARAMS((CLIENT * Client)) | ||||
| { | ||||
| 	bool is_visible, is_member; | ||||
| 	CL2CHAN *cl2chan; | ||||
| 	char flags[8]; | ||||
| 	CLIENT *c; | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Chan != NULL ); | ||||
|  | ||||
| 	if( Channel_IsMemberOf( Chan, Client )) is_member = true; | ||||
| 	else is_member = false; | ||||
|  | ||||
| 	/* Secret channel? */ | ||||
| 	if( ! is_member && strchr( Channel_Modes( Chan ), 's' )) return CONNECTED; | ||||
|  | ||||
| 	/* Alle Mitglieder suchen */ | ||||
| 	cl2chan = Channel_FirstMember( Chan ); | ||||
| 	while( cl2chan ) | ||||
| 	{ | ||||
| 		c = Channel_GetClient( cl2chan ); | ||||
|  | ||||
| 		if( strchr( Client_Modes( c ), 'i' )) is_visible = false; | ||||
| 		else is_visible = true; | ||||
|  | ||||
| 		if( is_member || is_visible ) | ||||
| 		{ | ||||
| 			/* Flags zusammenbasteln */ | ||||
| 			strcpy( flags, "H" ); | ||||
| 			if( strchr( Client_Modes( c ), 'o' )) strlcat( flags, "*", sizeof( flags )); | ||||
| 			if( strchr( Channel_UserModes( Chan, c ), 'o' )) strlcat( flags, "@", sizeof( flags )); | ||||
| 			else if( strchr( Channel_UserModes( Chan, c ), 'v' )) strlcat( flags, "+", sizeof( flags )); | ||||
|  | ||||
| 			/* ausgeben */ | ||||
| 			if(( ! OnlyOps ) || ( strchr( Client_Modes( c ), 'o' ))) | ||||
| 			{ | ||||
| 				if( ! IRC_WriteStrClient( Client, RPL_WHOREPLY_MSG, Client_ID( Client ), Channel_Name( Chan ), Client_User( c ), Client_Hostname( c ), Client_ID( Client_Introducer( c )), Client_ID( c ), flags, Client_Hops( c ), Client_Info( c ))) return DISCONNECTED; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		/* naechstes Mitglied suchen */ | ||||
| 		cl2chan = Channel_NextMember( Chan, cl2chan ); | ||||
| 	} | ||||
| 	return CONNECTED; | ||||
| } /* IRC_Send_WHO */ | ||||
| 	if (!IRC_WriteStrClient(Client, RPL_ISUPPORT1_MSG, Client_ID(Client), | ||||
| 				Conf_MaxJoins)) | ||||
| 		return DISCONNECTED; | ||||
| 	return IRC_WriteStrClient(Client, RPL_ISUPPORT2_MSG, Client_ID(Client), | ||||
| 				  CHANNEL_NAME_LEN - 1, Conf_MaxNickLength - 1, | ||||
| 				  COMMAND_LEN - 23, CLIENT_AWAY_LEN - 1, | ||||
| 				  COMMAND_LEN - 113); | ||||
| } /* IRC_Send_ISUPPORT */ | ||||
|  | ||||
|  | ||||
| /* -eof- */ | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: irc-info.h,v 1.3 2005/03/19 18:43:48 fw Exp $ | ||||
|  * $Id: irc-info.h,v 1.6 2008/02/17 13:26:42 alex Exp $ | ||||
|  * | ||||
|  * IRC info commands (header) | ||||
|  */ | ||||
| @@ -19,14 +19,17 @@ | ||||
|  | ||||
|  | ||||
| GLOBAL bool IRC_ADMIN PARAMS(( CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_INFO PARAMS(( CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_ISON PARAMS(( CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_LINKS PARAMS(( CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_LUSERS PARAMS(( CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_MOTD PARAMS(( CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_NAMES PARAMS(( CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_STATS PARAMS(( CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_SUMMON PARAMS(( CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_TIME PARAMS(( CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_USERHOST PARAMS(( CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_USERS PARAMS(( CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_VERSION PARAMS(( CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_WHO PARAMS(( CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_WHOIS PARAMS(( CLIENT *Client, REQUEST *Req )); | ||||
| @@ -35,7 +38,7 @@ GLOBAL bool IRC_WHOWAS PARAMS(( CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_Send_LUSERS PARAMS(( CLIENT *Client )); | ||||
| GLOBAL bool IRC_Send_NAMES PARAMS(( CLIENT *Client, CHANNEL *Chan )); | ||||
| GLOBAL bool IRC_Show_MOTD PARAMS(( CLIENT *Client )); | ||||
| GLOBAL bool IRC_Send_WHO PARAMS(( CLIENT *Client, CHANNEL *Chan, bool OnlyOps )); | ||||
| GLOBAL bool IRC_Send_ISUPPORT PARAMS(( CLIENT *Client )); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  * ngIRCd -- The Next Generation IRC Daemon | ||||
|  * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) | ||||
|  * Copyright (c)2001-2008 Alexander Barton (alex@barton.de) | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
| @@ -14,8 +14,6 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: irc-login.c,v 1.49 2005/09/01 10:51:24 alex Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| #include <stdio.h> | ||||
| @@ -35,7 +33,6 @@ static char UNUSED id[] = "$Id: irc-login.c,v 1.49 2005/09/01 10:51:24 alex Exp | ||||
| #include "irc.h" | ||||
| #include "irc-info.h" | ||||
| #include "irc-write.h" | ||||
| #include "cvs-version.h" | ||||
|  | ||||
| #include "exp.h" | ||||
| #include "irc-login.h" | ||||
| @@ -45,101 +42,119 @@ static bool Hello_User PARAMS(( CLIENT *Client )); | ||||
| static void Kill_Nick PARAMS(( char *Nick, char *Reason )); | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Handler for the IRC command "PASS". | ||||
|  * See RFC 2813 section 4.1.1, and RFC 2812 section 3.1.1. | ||||
|  */ | ||||
| GLOBAL bool | ||||
| IRC_PASS( CLIENT *Client, REQUEST *Req ) | ||||
| { | ||||
| 	char *type, *orig_flags; | ||||
| 	int protohigh, protolow; | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Req != NULL ); | ||||
|  | ||||
| 	/* Fehler liefern, wenn kein lokaler Client */ | ||||
| 	if( Client_Conn( Client ) <= NONE ) return IRC_WriteStrClient( Client, ERR_UNKNOWNCOMMAND_MSG, Client_ID( Client ), Req->command ); | ||||
| 	/* Return an error if this is not a local client */ | ||||
| 	if (Client_Conn(Client) <= NONE) | ||||
| 		return IRC_WriteStrClient(Client, ERR_UNKNOWNCOMMAND_MSG, | ||||
| 					  Client_ID(Client), Req->command); | ||||
| 	 | ||||
| 	if(( Client_Type( Client ) == CLIENT_UNKNOWN ) && ( Req->argc == 1)) | ||||
| 	{ | ||||
| 		/* noch nicht registrierte unbekannte Verbindung */ | ||||
| 		Log( LOG_DEBUG, "Connection %d: got PASS command ...", Client_Conn( Client )); | ||||
|  | ||||
| 		/* Passwort speichern */ | ||||
| 		Client_SetPassword( Client, Req->argv[0] ); | ||||
|  | ||||
| 		Client_SetType( Client, CLIENT_GOTPASS ); | ||||
| 		return CONNECTED; | ||||
| 	if (Client_Type(Client) == CLIENT_UNKNOWN && Req->argc == 1) { | ||||
| 		/* Not yet registered "unknown" connection, PASS with one | ||||
| 		 * argument: either a regular client, service, or server | ||||
| 		 * using the old RFC 1459 section 4.1.1 syntax. */ | ||||
| 		LogDebug("Connection %d: got PASS command ...", | ||||
| 			 Client_Conn(Client)); | ||||
| 	} else if ((Client_Type(Client) == CLIENT_UNKNOWN || | ||||
| 		    Client_Type(Client) == CLIENT_UNKNOWNSERVER) && | ||||
| 		   (Req->argc == 3 || Req->argc == 4)) { | ||||
| 		/* Not yet registered "unknown" connection or outgoing server | ||||
| 		 * link, PASS with three or four argument: server using the | ||||
| 		 * RFC 2813 section 4.1.1 syntax. */ | ||||
| 		LogDebug("Connection %d: got PASS command (new server link) ...", | ||||
| 			 Client_Conn(Client)); | ||||
| 	} else if (Client_Type(Client) == CLIENT_UNKNOWN || | ||||
| 		   Client_Type(Client) == CLIENT_UNKNOWNSERVER) { | ||||
| 		/* Unregistered connection, but wrong number of arguments: */ | ||||
| 		return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, | ||||
| 					  Client_ID(Client), Req->command); | ||||
| 	} else { | ||||
| 		/* Registered connection, PASS command is not allowed! */ | ||||
| 		return IRC_WriteStrClient(Client, ERR_ALREADYREGISTRED_MSG, | ||||
| 					  Client_ID(Client)); | ||||
| 	} | ||||
| 	else if((( Client_Type( Client ) == CLIENT_UNKNOWN ) || ( Client_Type( Client ) == CLIENT_UNKNOWNSERVER )) && (( Req->argc == 3 ) || ( Req->argc == 4 ))) | ||||
| 	{ | ||||
| 		char c2, c4, *type, *impl, *serverver, *flags, *ptr, *ircflags; | ||||
| 		int protohigh, protolow; | ||||
|  | ||||
| 		/* noch nicht registrierte Server-Verbindung */ | ||||
| 		Log( LOG_DEBUG, "Connection %d: got PASS command (new server link) ...", Client_Conn( Client )); | ||||
| 	Client_SetPassword(Client, Req->argv[0]); | ||||
| 	Client_SetType(Client, CLIENT_GOTPASS); | ||||
|  | ||||
| 		/* Passwort speichern */ | ||||
| 		Client_SetPassword( Client, Req->argv[0] ); | ||||
| 	/* Protocol version */ | ||||
| 	if (Req->argc >= 2 && strlen(Req->argv[1]) >= 4) { | ||||
| 		int c2, c4; | ||||
|  | ||||
| 		/* Protokollversion ermitteln */ | ||||
| 		if( strlen( Req->argv[1] ) >= 4 ) | ||||
| 		{ | ||||
| 			c2 = Req->argv[1][2]; | ||||
| 			c4 = Req->argv[1][4]; | ||||
| 		c2 = Req->argv[1][2]; | ||||
| 		c4 = Req->argv[1][4]; | ||||
|  | ||||
| 			Req->argv[1][4] = '\0'; | ||||
| 			protolow = atoi( &Req->argv[1][2] ); | ||||
| 			Req->argv[1][2] = '\0'; | ||||
| 			protohigh = atoi( Req->argv[1] ); | ||||
| 		Req->argv[1][4] = '\0'; | ||||
| 		protolow = atoi(&Req->argv[1][2]); | ||||
| 		Req->argv[1][2] = '\0'; | ||||
| 		protohigh = atoi(Req->argv[1]); | ||||
| 			 | ||||
| 			Req->argv[1][2] = c2; | ||||
| 			Req->argv[1][4] = c4; | ||||
| 		}			 | ||||
| 		else protohigh = protolow = 0; | ||||
| 		Req->argv[1][2] = c2; | ||||
| 		Req->argv[1][4] = c4; | ||||
| 	} else | ||||
| 		protohigh = protolow = 0; | ||||
|  | ||||
| 		/* Protokoll-Typ */ | ||||
| 		if( strlen( Req->argv[1] ) > 4 ) type = &Req->argv[1][4]; | ||||
| 		else type = NULL; | ||||
| 	/* Protocol type, see doc/Protocol.txt */ | ||||
| 	if (Req->argc >= 2 && strlen(Req->argv[1]) > 4) | ||||
| 		type = &Req->argv[1][4]; | ||||
| 	else | ||||
| 		type = NULL; | ||||
| 	 | ||||
| 	/* Protocol flags/options */ | ||||
| 	if (Req->argc >= 4) | ||||
| 		orig_flags = Req->argv[3]; | ||||
| 	else | ||||
| 		orig_flags = ""; | ||||
|  | ||||
| 		/* IRC-Flags (nach RFC 2813) */ | ||||
| 		if( Req->argc >= 4 ) ircflags = Req->argv[3]; | ||||
| 		else ircflags = ""; | ||||
| 	/* Implementation, version and IRC+ flags */ | ||||
| 	if (Req->argc >= 3) { | ||||
| 		char *impl, *ptr, *serverver, *flags; | ||||
|  | ||||
| 		/* Implementation, Version und ngIRCd-Flags */ | ||||
| 		impl = Req->argv[2]; | ||||
| 		ptr = strchr( impl, '|' ); | ||||
| 		if( ptr ) *ptr = '\0'; | ||||
| 		ptr = strchr(impl, '|'); | ||||
| 		if (ptr) | ||||
| 			*ptr = '\0'; | ||||
|  | ||||
| 		if( type && ( strcmp( type, PROTOIRCPLUS ) == 0 )) | ||||
| 		{ | ||||
| 			/* auf der anderen Seite laeuft ein Server, der | ||||
| 			 * ebenfalls das IRC+-Protokoll versteht */ | ||||
| 		if (type && strcmp(type, PROTOIRCPLUS) == 0) { | ||||
| 			/* The peer seems to be a server which supports the | ||||
| 			 * IRC+ protocol (see doc/Protocol.txt). */ | ||||
| 			serverver = ptr + 1; | ||||
| 			flags = strchr( serverver, ':' ); | ||||
| 			if( flags ) | ||||
| 			{ | ||||
| 			flags = strchr(serverver, ':'); | ||||
| 			if (flags) { | ||||
| 				*flags = '\0'; | ||||
| 				flags++; | ||||
| 			} | ||||
| 			else flags = ""; | ||||
| 			Log( LOG_INFO, "Peer announces itself as %s-%s using protocol %d.%d/IRC+ (flags: \"%s\").", impl, serverver, protohigh, protolow, flags ); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			/* auf der anderen Seite laeuft ein Server, der | ||||
| 			 * nur das Originalprotokoll unterstuetzt */ | ||||
| 			} else | ||||
| 				flags = ""; | ||||
| 			Log(LOG_INFO, | ||||
| 			    "Peer announces itself as %s-%s using protocol %d.%d/IRC+ (flags: \"%s\").", | ||||
| 			    impl, serverver, protohigh, protolow, flags); | ||||
| 		} else { | ||||
| 			/* The peer seems to be a server supporting the | ||||
| 			 * "original" IRC protocol (RFC 2813). */ | ||||
| 			serverver = ""; | ||||
| 			if( strchr( ircflags, 'Z' )) flags = "Z"; | ||||
| 			else flags = ""; | ||||
| 			Log( LOG_INFO, "Peer announces itself as \"%s\" using protocol %d.%d (flags: \"%s\").", impl, protohigh, protolow, flags ); | ||||
| 			if (strchr(orig_flags, 'Z')) | ||||
| 				flags = "Z"; | ||||
| 			else | ||||
| 				flags = ""; | ||||
| 			Log(LOG_INFO, | ||||
| 			    "Peer announces itself as \"%s\" using protocol %d.%d (flags: \"%s\").", | ||||
| 			    impl, protohigh, protolow, flags); | ||||
| 		} | ||||
|  | ||||
| 		Client_SetType( Client, CLIENT_GOTPASSSERVER ); | ||||
| 		Client_SetFlags( Client, flags ); | ||||
|  | ||||
| 		return CONNECTED; | ||||
| 		Client_SetFlags(Client, flags); | ||||
| 	} | ||||
| 	else if(( Client_Type( Client ) == CLIENT_UNKNOWN  ) || ( Client_Type( Client ) == CLIENT_UNKNOWNSERVER )) | ||||
| 	{ | ||||
| 		/* Falsche Anzahl Parameter? */ | ||||
| 		return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); | ||||
| 	} | ||||
| 	else return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client )); | ||||
|  | ||||
| 	return CONNECTED; | ||||
| } /* IRC_PASS */ | ||||
|  | ||||
|  | ||||
| @@ -268,13 +283,13 @@ IRC_NICK( CLIENT *Client, REQUEST *Req ) | ||||
| 						   "NICK :%s", Req->argv[0] ); | ||||
| 			IRC_WriteStrRelatedPrefix( target, target, false, | ||||
| 						   "NICK :%s", Req->argv[0] ); | ||||
| 			 | ||||
|  | ||||
| 			/* Register old nickname for WHOWAS queries */ | ||||
| 			Client_RegisterWhowas( target ); | ||||
| 				 | ||||
|  | ||||
| 			/* Save new nickname */ | ||||
| 			Client_SetID( target, Req->argv[0] ); | ||||
| 			 | ||||
|  | ||||
| 			IRC_SetPenalty( target, 2 ); | ||||
| 		} | ||||
|  | ||||
| @@ -489,7 +504,7 @@ IRC_PING(CLIENT *Client, REQUEST *Req) | ||||
| 		Client_ID(from), Client_ID(Client)); | ||||
| #else | ||||
| 	/* Some clients depend on the argument being returned in the PONG | ||||
|          * reply (not mentioned in any RFC, though) */ | ||||
| 	 * reply (not mentioned in any RFC, though) */ | ||||
| 	return IRC_WriteStrClient(Client, "PONG %s :%s", | ||||
| 		Client_ID(from), Req->argv[0]); | ||||
| #endif | ||||
| @@ -555,60 +570,60 @@ IRC_PONG(CLIENT *Client, REQUEST *Req) | ||||
|  | ||||
|  | ||||
| static bool | ||||
| Hello_User( CLIENT *Client ) | ||||
| Hello_User(CLIENT * Client) | ||||
| { | ||||
| #ifdef CVSDATE | ||||
| 	char ver[12], vertxt[30]; | ||||
| #endif | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert(Client != NULL); | ||||
|  | ||||
| 	/* Check password ... */ | ||||
| 	if( strcmp( Client_Password( Client ), Conf_ServerPwd ) != 0 ) | ||||
| 	{ | ||||
| 	if (strcmp(Client_Password(Client), Conf_ServerPwd) != 0) { | ||||
| 		/* Bad password! */ | ||||
| 		Log( LOG_ERR, "User \"%s\" rejected (connection %d): Bad password!", Client_Mask( Client ), Client_Conn( Client )); | ||||
| 		Conn_Close( Client_Conn( Client ), NULL, "Bad password", true); | ||||
| 		Log(LOG_ERR, | ||||
| 		    "User \"%s\" rejected (connection %d): Bad password!", | ||||
| 		    Client_Mask(Client), Client_Conn(Client)); | ||||
| 		Conn_Close(Client_Conn(Client), NULL, "Bad password", true); | ||||
| 		return DISCONNECTED; | ||||
| 	} | ||||
|  | ||||
| 	Log( LOG_NOTICE, "User \"%s\" registered (connection %d).", Client_Mask( Client ), Client_Conn( Client )); | ||||
| 	Log(LOG_NOTICE, "User \"%s\" registered (connection %d).", | ||||
| 	    Client_Mask(Client), Client_Conn(Client)); | ||||
|  | ||||
| 	/* Inform other servers */ | ||||
| 	IRC_WriteStrServers( NULL, "NICK %s 1 %s %s 1 +%s :%s", Client_ID( Client ), Client_User( Client ), Client_Hostname( Client ), Client_Modes( Client ), Client_Info( Client )); | ||||
| 	IRC_WriteStrServers(NULL, "NICK %s 1 %s %s 1 +%s :%s", | ||||
| 			    Client_ID(Client), Client_User(Client), | ||||
| 			    Client_Hostname(Client), Client_Modes(Client), | ||||
| 			    Client_Info(Client)); | ||||
|  | ||||
| 	/* Welcome :-) */ | ||||
| 	if( ! IRC_WriteStrClient( Client, RPL_WELCOME_MSG, Client_ID( Client ), Client_Mask( Client ))) return false; | ||||
| 	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; | ||||
|  | ||||
| 	/* Version and system type */ | ||||
| #ifdef CVSDATE | ||||
| 	strlcpy( ver, CVSDATE, sizeof( ver )); | ||||
| 	strncpy( ver + 4, ver + 5, 2 ); | ||||
| 	strncpy( ver + 6, ver + 8, 3 ); | ||||
| 	snprintf( vertxt, sizeof( vertxt ), "%s(%s)", PACKAGE_VERSION, ver ); | ||||
| 	if( ! IRC_WriteStrClient( Client, RPL_YOURHOST_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), vertxt, TARGET_CPU, TARGET_VENDOR, TARGET_OS )) return false; | ||||
| #else | ||||
| 	if( ! IRC_WriteStrClient( Client, RPL_YOURHOST_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), PACKAGE_VERSION, TARGET_CPU, TARGET_VENDOR, TARGET_OS )) return false; | ||||
| #endif | ||||
| 	/* 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_WriteStrClient( Client, RPL_CREATED_MSG, Client_ID( Client ), NGIRCd_StartStr )) return false; | ||||
| #ifdef CVSDATE | ||||
| 	if( ! IRC_WriteStrClient( Client, RPL_MYINFO_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), vertxt, USERMODES, CHANMODES )) return false;	 | ||||
| #else | ||||
| 	if( ! IRC_WriteStrClient( Client, RPL_MYINFO_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), PACKAGE_VERSION, USERMODES, CHANMODES )) return false; | ||||
| #endif | ||||
| 	Client_SetType(Client, CLIENT_USER); | ||||
|  | ||||
| 	/* Features */ | ||||
| 	if( ! IRC_WriteStrClient( Client, RPL_ISUPPORT_MSG, Client_ID( Client ), CLIENT_NICK_LEN - 1, | ||||
| 			COMMAND_LEN - 23, CLIENT_AWAY_LEN - 1, Conf_MaxJoins )) return DISCONNECTED; | ||||
|  | ||||
| 	Client_SetType( Client, CLIENT_USER ); | ||||
|  | ||||
| 	if( ! IRC_Send_LUSERS( Client )) return DISCONNECTED; | ||||
| 	if( ! IRC_Show_MOTD( Client )) return DISCONNECTED; | ||||
| 	if (!IRC_Send_LUSERS(Client)) | ||||
| 		return DISCONNECTED; | ||||
| 	if (!IRC_Show_MOTD(Client)) | ||||
| 		return DISCONNECTED; | ||||
|  | ||||
| 	/* Suspend the client for a second ... */ | ||||
| 	IRC_SetPenalty( Client, 1 ); | ||||
| 	IRC_SetPenalty(Client, 1); | ||||
|  | ||||
| 	return CONNECTED; | ||||
| } /* Hello_User */ | ||||
|   | ||||
| @@ -14,8 +14,6 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: irc-mode.c,v 1.45 2006/05/10 21:24:01 alex Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| #include <stdio.h> | ||||
| @@ -41,13 +39,10 @@ static char UNUSED id[] = "$Id: irc-mode.c,v 1.45 2006/05/10 21:24:01 alex Exp $ | ||||
| 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_Invite PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )); | ||||
| static bool Add_Ban PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )); | ||||
| static bool 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 Del_Invite PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )); | ||||
| static bool Del_Ban PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )); | ||||
|  | ||||
| static bool Send_ListChange PARAMS(( char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Mask )); | ||||
| static bool Send_ListChange PARAMS(( char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Mask )); | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| @@ -69,7 +64,7 @@ IRC_MODE( CLIENT *Client, REQUEST *Req ) | ||||
| 		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; | ||||
| 	if (Client_IsValidNick(Req->argv[0])) | ||||
| @@ -164,6 +159,7 @@ Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) | ||||
| 		{ | ||||
| 			case 'i': /* Invisible */ | ||||
| 			case 's': /* Server messages */ | ||||
| 			case 'w': /* Wallops messages */ | ||||
| 				x[0] = *mode_ptr; | ||||
| 				break; | ||||
|  | ||||
| @@ -241,123 +237,140 @@ client_exit: | ||||
| } /* Client_Mode */ | ||||
|  | ||||
|  | ||||
| static bool | ||||
| Channel_Mode_Answer_Request(CLIENT *Origin, CHANNEL *Channel) | ||||
| { | ||||
| 	char the_modes[COMMAND_LEN], the_args[COMMAND_LEN], argadd[CLIENT_PASS_LEN]; | ||||
| 	const char *mode_ptr; | ||||
|  | ||||
| 	/* Member or not? -- That's the question! */ | ||||
| 	if (!Channel_IsMemberOf(Channel, Origin)) | ||||
| 		return IRC_WriteStrClient(Origin, RPL_CHANNELMODEIS_MSG, | ||||
| 			Client_ID(Origin), Channel_Name(Channel), Channel_Modes(Channel)); | ||||
|  | ||||
| 	/* The sender is a member: generate extended reply */ | ||||
| 	strlcpy(the_modes, Channel_Modes(Channel), sizeof(the_modes)); | ||||
| 	mode_ptr = the_modes; | ||||
| 	the_args[0] = '\0'; | ||||
|  | ||||
| 	while(*mode_ptr) { | ||||
| 		switch(*mode_ptr) { | ||||
| 		case 'l': | ||||
| 			snprintf(argadd, sizeof(argadd), " %lu", Channel_MaxUsers(Channel)); | ||||
| 			strlcat(the_args, argadd, sizeof(the_args)); | ||||
| 			break; | ||||
| 		case 'k': | ||||
| 			strlcat(the_args, " ", sizeof(the_args)); | ||||
| 			strlcat(the_args, Channel_Key(Channel), sizeof(the_args)); | ||||
| 			break; | ||||
| 		} | ||||
| 		mode_ptr++; | ||||
| 	} | ||||
| 	if (the_args[0]) | ||||
| 		strlcat(the_modes, the_args, sizeof(the_modes)); | ||||
|  | ||||
| 	return IRC_WriteStrClient(Origin, RPL_CHANNELMODEIS_MSG, | ||||
| 		Client_ID(Origin), Channel_Name(Channel), the_modes); | ||||
| } | ||||
|  | ||||
|  | ||||
| static bool | ||||
| Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ) | ||||
| { | ||||
| 	/* Handle channel and channel-user modes */ | ||||
|  | ||||
| 	char the_modes[COMMAND_LEN], the_args[COMMAND_LEN], x[2], argadd[CLIENT_PASS_LEN], *mode_ptr; | ||||
| 	bool ok, set, modeok = false, skiponce, use_servermode = false; | ||||
| 	bool ok, set, modeok = true, skiponce, use_servermode = false, retval; | ||||
| 	int mode_arg, arg_arg; | ||||
| 	CLIENT *client; | ||||
| 	long l; | ||||
| 	size_t len; | ||||
|  | ||||
| 	/* Mode request: let's answer it :-) */ | ||||
| 	if( Req->argc == 1 ) | ||||
| 	{ | ||||
| 		/* Member or not? -- That's the question! */ | ||||
| 		if( ! Channel_IsMemberOf( Channel, Origin )) return IRC_WriteStrClient( Origin, RPL_CHANNELMODEIS_MSG, Client_ID( Origin ), Channel_Name( Channel ), Channel_Modes( Channel )); | ||||
|  | ||||
| 		/* The sender is a member: generate extended reply */ | ||||
| 		strlcpy( the_modes, Channel_Modes( Channel ), sizeof( the_modes )); | ||||
| 		mode_ptr = the_modes; | ||||
| 		the_args[0] = '\0'; | ||||
| 		while( *mode_ptr ) | ||||
| 		{ | ||||
| 			switch( *mode_ptr ) | ||||
| 			{ | ||||
| 				case 'l': | ||||
| 					snprintf( argadd, sizeof( argadd ), " %ld", Channel_MaxUsers( Channel )); | ||||
| 					strlcat( the_args, argadd, sizeof( the_args )); | ||||
| 					break; | ||||
| 				case 'k': | ||||
| 					strlcat( the_args, " ", sizeof( the_args )); | ||||
| 					strlcat( the_args, Channel_Key( Channel ), sizeof( the_args )); | ||||
| 					break; | ||||
| 			} | ||||
| 			mode_ptr++; | ||||
| 		} | ||||
| 		if( the_args[0] ) strlcat( the_modes, the_args, sizeof( the_modes )); | ||||
|  | ||||
| 		return IRC_WriteStrClient( Origin, RPL_CHANNELMODEIS_MSG, Client_ID( Origin ), Channel_Name( Channel ), the_modes ); | ||||
| 	} | ||||
| 	if (Req->argc <= 1) | ||||
| 		return Channel_Mode_Answer_Request(Origin, Channel); | ||||
|  | ||||
| 	/* Is the user allowed to change modes? */ | ||||
| 	if( Client_Type( Client ) == CLIENT_USER ) | ||||
| 	{ | ||||
| 	if (Client_Type(Client) == CLIENT_USER) { | ||||
| 		/* Is the originating user on that channel? */ | ||||
| 		if( ! Channel_IsMemberOf( Channel, Origin )) return IRC_WriteStrClient( Origin, ERR_NOTONCHANNEL_MSG, Client_ID( Origin ), Channel_Name( Channel )); | ||||
|  | ||||
| 		/* Is he channel operator? */ | ||||
| 		if( strchr( Channel_UserModes( Channel, Origin ), 'o' )) modeok = true; | ||||
| 		else if( Conf_OperCanMode ) | ||||
| 		{ | ||||
| 		if (!Channel_IsMemberOf(Channel, Origin)) | ||||
| 			return IRC_WriteStrClient(Origin, ERR_NOTONCHANNEL_MSG, | ||||
| 				Client_ID(Origin), Channel_Name(Channel)); | ||||
| 		modeok = false; | ||||
| 		/* channel operator? */ | ||||
| 		if (strchr(Channel_UserModes(Channel, Origin), 'o')) | ||||
| 			modeok = true; | ||||
| 		else if(Conf_OperCanMode) { | ||||
| 			/* IRC-Operators can use MODE as well */ | ||||
| 			if( Client_OperByMe( Origin )) { | ||||
| 			if (Client_OperByMe(Origin)) { | ||||
| 				modeok = true; | ||||
| 				if ( Conf_OperServerMode ) use_servermode = true; /* Change Origin to Server */ | ||||
| 				if (Conf_OperServerMode) | ||||
| 					use_servermode = true; /* Change Origin to Server */ | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	else modeok = true; | ||||
|  | ||||
| 	mode_arg = 1; | ||||
| 	mode_ptr = Req->argv[mode_arg]; | ||||
| 	if( Req->argc > mode_arg + 1 ) arg_arg = mode_arg + 1; | ||||
| 	else arg_arg = -1; | ||||
| 	if (Req->argc > mode_arg + 1) | ||||
| 		arg_arg = mode_arg + 1; | ||||
| 	else | ||||
| 		arg_arg = -1; | ||||
|  | ||||
| 	/* Initial state: set or unset modes? */ | ||||
| 	skiponce = false; | ||||
| 	if( *mode_ptr == '-' ) set = false; | ||||
| 	else if( *mode_ptr == '+' ) set = true; | ||||
| 	else set = skiponce = true; | ||||
| 	switch (*mode_ptr) { | ||||
| 	case '-': set = false; break; | ||||
| 	case '+': set = true; break; | ||||
| 	default: | ||||
| 		set = true; | ||||
| 		skiponce = true; | ||||
| 	} | ||||
|  | ||||
| 	/* Prepare reply string */ | ||||
| 	if( set ) strcpy( the_modes, "+" ); | ||||
| 	else strcpy( the_modes, "-" ); | ||||
| 	strcpy( the_args, " " ); | ||||
| 	strcpy(the_modes, set ? "+" : "-"); | ||||
| 	the_args[0] = '\0'; | ||||
|  | ||||
| 	x[1] = '\0'; | ||||
| 	ok = CONNECTED; | ||||
| 	while( mode_ptr ) | ||||
| 	{ | ||||
| 		if( ! skiponce ) mode_ptr++; | ||||
| 		if( ! *mode_ptr ) | ||||
| 		{ | ||||
| 	while (mode_ptr) { | ||||
| 		if (! skiponce) | ||||
| 			mode_ptr++; | ||||
| 		if (!*mode_ptr) { | ||||
| 			/* Try next argument if there's any */ | ||||
| 			if( arg_arg > mode_arg ) mode_arg = arg_arg; | ||||
| 			else mode_arg++; | ||||
| 			if( mode_arg < Req->argc ) mode_ptr = Req->argv[mode_arg]; | ||||
| 			else break; | ||||
| 			if( Req->argc > mode_arg + 1 ) arg_arg = mode_arg + 1; | ||||
| 			else arg_arg = -1; | ||||
| 			if (arg_arg > mode_arg) | ||||
| 				mode_arg = arg_arg; | ||||
| 			else | ||||
| 				mode_arg++; | ||||
|  | ||||
| 			if (mode_arg >= Req->argc) | ||||
| 				break; | ||||
| 			mode_ptr = Req->argv[mode_arg]; | ||||
|  | ||||
| 			if (Req->argc > mode_arg + 1) | ||||
| 				arg_arg = mode_arg + 1; | ||||
| 			else | ||||
| 				arg_arg = -1; | ||||
| 		} | ||||
| 		skiponce = false; | ||||
|  | ||||
| 		switch( *mode_ptr ) | ||||
| 		{ | ||||
| 			case '+': | ||||
| 			case '-': | ||||
| 				if((( *mode_ptr == '+' ) && ( ! set )) || (( *mode_ptr == '-' ) && ( set ))) | ||||
| 				{ | ||||
| 					/* Action modifier ("+"/"-") must be changed ... */ | ||||
| 					len = strlen( the_modes ) - 1; | ||||
| 					if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' )) | ||||
| 					{ | ||||
| 						/* Adjust last action modifier in result */ | ||||
| 						the_modes[len] = *mode_ptr; | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						/* Append modifier character to result string */ | ||||
| 						x[0] = *mode_ptr; | ||||
| 						strlcat( the_modes, x, sizeof( the_modes )); | ||||
| 					} | ||||
| 					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] == '-')) { | ||||
| 					/* 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)); | ||||
| 				} | ||||
| 				continue; | ||||
| 				set = *mode_ptr == '+'; | ||||
| 			} | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		/* Are there arguments left? */ | ||||
| @@ -367,240 +380,194 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ) | ||||
| 		x[0] = '\0'; | ||||
| 		argadd[0] = '\0'; | ||||
| 		client = NULL; | ||||
| 		switch( *mode_ptr ) | ||||
| 		{ | ||||
| 			/* --- Channel modes --- */ | ||||
|  | ||||
| 			case 'i': /* Invite only */ | ||||
| 			case 'm': /* Moderated */ | ||||
| 			case 'n': /* Only members can write */ | ||||
| 			case 's': /* Secret channel */ | ||||
| 			case 't': /* Topic locked */ | ||||
| 				if( modeok ) x[0] = *mode_ptr; | ||||
| 				else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); | ||||
| 		switch (*mode_ptr) { | ||||
| 		/* --- Channel modes --- */ | ||||
| 		case 'i': /* Invite only */ | ||||
| 		case 'm': /* Moderated */ | ||||
| 		case 'n': /* Only members can write */ | ||||
| 		case 's': /* Secret channel */ | ||||
| 		case 't': /* Topic locked */ | ||||
| 			if (modeok) | ||||
| 				x[0] = *mode_ptr; | ||||
| 			else | ||||
| 				ok = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(Origin), Channel_Name(Channel)); | ||||
| 			break; | ||||
| 		case 'k': /* Channel key */ | ||||
| 			if (! set) { | ||||
| 				if (modeok) | ||||
| 					x[0] = *mode_ptr; | ||||
| 				else | ||||
| 					ok = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(Origin), Channel_Name(Channel)); | ||||
| 				break; | ||||
|  | ||||
| 			case 'k': /* Channel key */ | ||||
| 				if( ! set ) | ||||
| 				{ | ||||
| 					if( modeok ) x[0] = *mode_ptr; | ||||
| 					else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); | ||||
| 					break; | ||||
| 			} | ||||
| 			if (arg_arg > mode_arg) { | ||||
| 				if (modeok) { | ||||
| 					Channel_ModeDel(Channel, 'k'); | ||||
| 					Channel_SetKey(Channel, Req->argv[arg_arg]); | ||||
| 					strlcpy(argadd, Channel_Key(Channel), sizeof(argadd)); | ||||
| 					x[0] = *mode_ptr; | ||||
| 				} else { | ||||
| 					ok = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(Origin), Channel_Name(Channel)); | ||||
| 				} | ||||
| 				if( arg_arg > mode_arg ) | ||||
| 				{ | ||||
| 					if( modeok ) | ||||
| 					{ | ||||
| 						Channel_ModeDel( Channel, 'k' ); | ||||
| 						Channel_SetKey( Channel, Req->argv[arg_arg] ); | ||||
| 						strlcpy( argadd, Channel_Key( Channel ), sizeof( argadd )); | ||||
| 				Req->argv[arg_arg][0] = '\0'; | ||||
| 				arg_arg++; | ||||
| 			} else { | ||||
| 				ok = IRC_WriteStrClient(Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID(Origin), Req->command); | ||||
| 			} | ||||
| 			break; | ||||
| 		case 'l': /* Member limit */ | ||||
| 			if (!set) { | ||||
| 				if (modeok) | ||||
| 					x[0] = *mode_ptr; | ||||
| 				else | ||||
| 					ok = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(Origin), Channel_Name(Channel)); | ||||
| 				break; | ||||
| 			} | ||||
| 			if (arg_arg > mode_arg) { | ||||
| 				if (modeok) { | ||||
| 					l = atol(Req->argv[arg_arg]); | ||||
| 					if (l > 0 && l < 0xFFFF) { | ||||
| 						Channel_ModeDel(Channel, 'l'); | ||||
| 						Channel_SetMaxUsers(Channel, l); | ||||
| 						snprintf(argadd, sizeof(argadd), "%ld", l); | ||||
| 						x[0] = *mode_ptr; | ||||
| 					} | ||||
| 					else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); | ||||
| 					Req->argv[arg_arg][0] = '\0'; | ||||
| 					arg_arg++; | ||||
| 				} else { | ||||
| 					ok = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(Origin), Channel_Name(Channel)); | ||||
| 				} | ||||
| 				else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command ); | ||||
| 				break; | ||||
|  | ||||
| 			case 'l': /* Member limit */ | ||||
| 				if( ! set ) | ||||
| 				{ | ||||
| 					if( modeok ) x[0] = *mode_ptr; | ||||
| 					else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); | ||||
| 					break; | ||||
| 				Req->argv[arg_arg][0] = '\0'; | ||||
| 				arg_arg++; | ||||
| 			} else { | ||||
| 				ok = IRC_WriteStrClient(Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID(Origin), Req->command); | ||||
| 			} | ||||
| 			break; | ||||
| 		case 'P': /* Persistent channel */ | ||||
| 			if (modeok) { | ||||
| 				/* Only IRC operators are allowed to | ||||
| 				 * set the 'P' channel mode! */ | ||||
| 				if (set && !(Client_OperByMe(Client) || Client_Type(Client) == CLIENT_SERVER)) | ||||
| 					ok = IRC_WriteStrClient(Origin, ERR_NOPRIVILEGES_MSG, Client_ID(Origin)); | ||||
| 				else | ||||
| 						x[0] = 'P'; | ||||
| 			} else | ||||
| 				ok = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(Origin), Channel_Name(Channel)); | ||||
| 			break; | ||||
| 		/* --- Channel user modes --- */ | ||||
| 		case 'o': /* Channel operator */ | ||||
| 		case 'v': /* Voice */ | ||||
| 			if (arg_arg > mode_arg) { | ||||
| 				if (modeok) { | ||||
| 					client = Client_Search(Req->argv[arg_arg]); | ||||
| 					if (client) | ||||
| 						x[0] = *mode_ptr; | ||||
| 					else | ||||
| 						ok = IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, Client_ID(Client), Req->argv[arg_arg]); | ||||
| 				} else { | ||||
| 					ok = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID(Origin), Channel_Name(Channel)); | ||||
| 				} | ||||
| 				if( arg_arg > mode_arg ) | ||||
| 				{ | ||||
| 					if( modeok ) | ||||
| 					{ | ||||
| 						l = atol( Req->argv[arg_arg] ); | ||||
| 						if( l > 0 && l < 0xFFFF ) | ||||
| 						{ | ||||
| 							Channel_ModeDel( Channel, 'l' ); | ||||
| 							Channel_SetMaxUsers( Channel, l ); | ||||
| 							snprintf( argadd, sizeof( argadd ), "%ld", l ); | ||||
| 							x[0] = *mode_ptr; | ||||
| 						} | ||||
| 					} | ||||
| 					else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); | ||||
| 					Req->argv[arg_arg][0] = '\0'; | ||||
| 					arg_arg++; | ||||
| 				Req->argv[arg_arg][0] = '\0'; | ||||
| 				arg_arg++; | ||||
| 			} else { | ||||
| 				ok = IRC_WriteStrClient(Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID(Origin), Req->command); | ||||
| 			} | ||||
| 			break; | ||||
| 		/* --- Channel lists --- */ | ||||
| 		case 'I': /* Invite lists */ | ||||
| 		case 'b': /* Ban lists */ | ||||
| 			if (arg_arg > mode_arg) { | ||||
| 				/* modify list */ | ||||
| 				if (modeok) { | ||||
| 					ok = set ? Add_Ban_Invite(*mode_ptr, Origin, Client, Channel, Req->argv[arg_arg]) | ||||
| 						 : Del_Ban_Invite(*mode_ptr, Origin, Client, Channel, Req->argv[arg_arg]); | ||||
| 				} else { | ||||
| 					ok = IRC_WriteStrClient(Origin, ERR_CHANOPRIVSNEEDED_MSG, | ||||
| 							Client_ID(Origin), Channel_Name(Channel)); | ||||
| 				} | ||||
| 				else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command ); | ||||
| 				break; | ||||
| 				Req->argv[arg_arg][0] = '\0'; | ||||
| 				arg_arg++; | ||||
| 			} else { | ||||
| 				if (*mode_ptr == 'I') | ||||
| 					Channel_ShowInvites(Origin, Channel); | ||||
| 				else | ||||
| 					Channel_ShowBans(Origin, Channel); | ||||
| 			} | ||||
| 			break; | ||||
| 		default: | ||||
| 			Log(LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\" on %s!?", | ||||
| 				set ? '+' : '-', *mode_ptr, Client_ID(Origin), Channel_Name(Channel)); | ||||
| 			if (Client_Type(Client) != CLIENT_SERVER) | ||||
| 				ok = IRC_WriteStrClient(Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID(Origin), set ? '+' : '-', *mode_ptr); | ||||
| 			x[0] = '\0'; | ||||
| 			goto chan_exit; | ||||
| 		} /* switch() */ | ||||
|  | ||||
| 			case 'P': /* Persistent channel */ | ||||
| 				if( modeok ) | ||||
| 				{ | ||||
| 					if( set && ( ! Client_OperByMe( Client ))) | ||||
| 					{ | ||||
| 						/* Only IRC operators are allowed to set P mode */ | ||||
| 						ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin )); | ||||
| 					} | ||||
| 					else x[0] = 'P'; | ||||
| 				} | ||||
| 				else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); | ||||
| 				break; | ||||
|  | ||||
| 			/* --- Channel user modes --- */ | ||||
|  | ||||
| 			case 'o': /* Channel operator */ | ||||
| 			case 'v': /* Voice */ | ||||
| 				if( arg_arg > mode_arg ) | ||||
| 				{ | ||||
| 					if( modeok ) | ||||
| 					{ | ||||
| 						client = Client_Search( Req->argv[arg_arg] ); | ||||
| 						if( client ) x[0] = *mode_ptr; | ||||
| 						else ok = IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[arg_arg] ); | ||||
| 					} | ||||
| 					else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); | ||||
| 					Req->argv[arg_arg][0] = '\0'; | ||||
| 					arg_arg++; | ||||
| 				} | ||||
| 				else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command ); | ||||
| 				break; | ||||
|  | ||||
| 			/* --- Channel lists --- */ | ||||
|  | ||||
| 			case 'I': /* Invite lists */ | ||||
| 				if( arg_arg > mode_arg ) | ||||
| 				{ | ||||
| 					/* modify list */ | ||||
| 					if( modeok ) | ||||
| 					{ | ||||
| 						if( set ) Add_Invite( Origin, Client, Channel, Req->argv[arg_arg] ); | ||||
| 						else Del_Invite( Origin, Client, Channel, Req->argv[arg_arg] ); | ||||
| 					} | ||||
| 					else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); | ||||
| 					Req->argv[arg_arg][0] = '\0'; | ||||
| 					arg_arg++; | ||||
| 				} | ||||
| 				else Lists_ShowInvites( Origin, Channel ); | ||||
| 				break; | ||||
|  | ||||
| 			case 'b': /* Ban lists */ | ||||
| 				if( arg_arg > mode_arg ) | ||||
| 				{ | ||||
| 					/* modify list */ | ||||
| 					if( modeok ) | ||||
| 					{ | ||||
| 						if( set ) Add_Ban( Origin, Client, Channel, Req->argv[arg_arg] ); | ||||
| 						else Del_Ban( Origin, Client, Channel, Req->argv[arg_arg] ); | ||||
| 					} | ||||
| 					else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); | ||||
| 					Req->argv[arg_arg][0] = '\0'; | ||||
| 					arg_arg++; | ||||
| 				} | ||||
| 				else Lists_ShowBans( Origin, Channel ); | ||||
| 				break; | ||||
|  | ||||
| 			default: | ||||
| 				Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\" on %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Origin ), Channel_Name( Channel )); | ||||
| 				if( Client_Type( Client ) != CLIENT_SERVER ) ok = IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Origin ), set ? '+' : '-', *mode_ptr ); | ||||
| 				x[0] = '\0'; | ||||
| 				goto chan_exit; | ||||
| 		} | ||||
| 		if( ! ok ) break; | ||||
| 		if (!ok) | ||||
| 			break; | ||||
|  | ||||
| 		/* Is there a valid mode change? */ | ||||
| 		if( ! x[0] ) continue; | ||||
| 		if (!x[0]) | ||||
| 			continue; | ||||
|  | ||||
| 		/* Validate target client */ | ||||
| 		if( client && ( ! Channel_IsMemberOf( Channel, client ))) | ||||
| 		{ | ||||
| 			if( ! IRC_WriteStrClient( Origin, ERR_USERNOTINCHANNEL_MSG, Client_ID( Origin ), Client_ID( client ), Channel_Name( Channel ))) break; | ||||
| 		if (client && (!Channel_IsMemberOf(Channel, client))) { | ||||
| 			if (!IRC_WriteStrClient(Origin, ERR_USERNOTINCHANNEL_MSG, | ||||
| 				Client_ID(Origin), Client_ID(client), Channel_Name(Channel))) | ||||
| 					break; | ||||
|  | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		if( set ) | ||||
| 		{ | ||||
| 			/* Set mode */ | ||||
| 			if( client ) | ||||
| 			{ | ||||
| 				/* Channel-User-Mode */ | ||||
| 				if( Channel_UserModeAdd( Channel, client, x[0] )) | ||||
| 				{ | ||||
| 					strlcat( the_args, Client_ID( client ), sizeof( the_args )); | ||||
| 					strlcat( the_args, " ", sizeof( the_args )); | ||||
| 					strlcat( the_modes, x, sizeof( the_modes )); | ||||
| 					Log( LOG_DEBUG, "User \"%s\": Mode change on %s, now \"%s\"", Client_Mask( client ), Channel_Name( Channel ), Channel_UserModes( Channel, client )); | ||||
| 				} | ||||
| 		if (client) { | ||||
| 			/* Channel-User-Mode */ | ||||
| 			retval = set ? Channel_UserModeAdd(Channel, client, x[0]) : Channel_UserModeDel(Channel, client, x[0]); | ||||
| 			if (retval) { | ||||
| 				strlcat(the_args, " ", sizeof(the_args)); | ||||
| 				strlcat(the_args, Client_ID(client), sizeof(the_args)); | ||||
| 				strlcat(the_modes, x, sizeof(the_modes)); | ||||
| 				Log(LOG_DEBUG, "User \"%s\": Mode change on %s, now \"%s\"", | ||||
| 					Client_Mask(client), Channel_Name(Channel), Channel_UserModes(Channel, client)); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				/* Channel-Mode */ | ||||
| 				if( Channel_ModeAdd( Channel, x[0] )) | ||||
| 				{ | ||||
| 					strlcat( the_modes, x, sizeof( the_modes )); | ||||
| 					Log( LOG_DEBUG, "Channel %s: Mode change, now \"%s\".", Channel_Name( Channel ), Channel_Modes( Channel )); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			/* Unset mode */ | ||||
| 			if( client ) | ||||
| 			{ | ||||
| 				/* Channel-User-Mode */ | ||||
| 				if( Channel_UserModeDel( Channel, client, x[0] )) | ||||
| 				{ | ||||
| 					strlcat( the_args, Client_ID( client ), sizeof( the_args )); | ||||
| 					strlcat( the_args, " ", sizeof( the_args )); | ||||
| 					strlcat( the_modes, x, sizeof( the_modes )); | ||||
| 					Log( LOG_DEBUG, "User \"%s\": Mode change on %s, now \"%s\"", Client_Mask( client ), Channel_Name( Channel ), Channel_UserModes( Channel, client )); | ||||
| 				} | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				/* Channel-Mode */ | ||||
| 				if( Channel_ModeDel( Channel, x[0] )) | ||||
| 				{ | ||||
| 					strlcat( the_modes, x, sizeof( the_modes )); | ||||
| 					Log( LOG_DEBUG, "Channel %s: Mode change, now \"%s\".", Channel_Name( Channel ), Channel_Modes( Channel )); | ||||
| 				} | ||||
| 		} else { | ||||
| 			/* Channel-Mode */ | ||||
| 			retval = set ? Channel_ModeAdd(Channel, x[0]) : Channel_ModeDel(Channel, x[0]); | ||||
| 			if (retval) { | ||||
| 				strlcat(the_modes, x, sizeof(the_modes)); | ||||
| 				Log(LOG_DEBUG, "Channel %s: Mode change, now \"%s\".", Channel_Name(Channel), Channel_Modes(Channel)); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		/* Are there additional arguments to add? */ | ||||
| 		if( argadd[0] ) | ||||
| 		{ | ||||
| 			len = strlen( the_args ) - 1; | ||||
| 			if( the_args[len] != ' ' ) strlcat( the_args, " ", sizeof( the_args )); | ||||
| 			strlcat( the_args, argadd, sizeof( the_args )); | ||||
| 		if (argadd[0]) { | ||||
| 			strlcat(the_args, " ", sizeof(the_args)); | ||||
| 			strlcat(the_args, argadd, sizeof(the_args)); | ||||
| 		} | ||||
| 	} | ||||
| chan_exit: | ||||
|  | ||||
| 	/* Are there changed modes? */ | ||||
| 	if( the_modes[1] ) | ||||
| 	{ | ||||
| 	if (the_modes[1]) { | ||||
| 		/* Clean up mode string */ | ||||
| 		len = strlen( the_modes ) - 1; | ||||
| 		if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' )) the_modes[len] = '\0'; | ||||
| 		len = strlen(the_modes) - 1; | ||||
| 		if ((the_modes[len] == '+') || (the_modes[len] == '-')) | ||||
| 			the_modes[len] = '\0'; | ||||
|  | ||||
| 		/* Clean up argument string if there are none */ | ||||
| 		if( ! the_args[1] ) the_args[0] = '\0'; | ||||
|  | ||||
| 		if( Client_Type( Client ) == CLIENT_SERVER ) | ||||
| 		{ | ||||
| 		if (Client_Type(Client) == CLIENT_SERVER) { | ||||
| 			/* Forward mode changes to channel users and other servers */ | ||||
| 			IRC_WriteStrServersPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args ); | ||||
| 			IRC_WriteStrChannelPrefix( Client, Channel, Origin, false, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args ); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			if ( use_servermode ) Origin = Client_ThisServer(); | ||||
|  | ||||
| 			IRC_WriteStrServersPrefix(Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args); | ||||
| 			IRC_WriteStrChannelPrefix(Client, Channel, Origin, false, "MODE %s %s%s", Channel_Name(Channel), the_modes, the_args); | ||||
| 		} else { | ||||
| 			if (use_servermode) | ||||
| 				Origin = Client_ThisServer(); | ||||
| 			/* Send reply to client and inform other servers and channel users */ | ||||
| 			ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args ); | ||||
| 			IRC_WriteStrServersPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args ); | ||||
| 			IRC_WriteStrChannelPrefix( Client, Channel, Origin, false, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args ); | ||||
| 			ok = IRC_WriteStrClientPrefix(Client, Origin, "MODE %s %s%s", | ||||
| 					Channel_Name(Channel), the_modes, the_args); | ||||
| 			IRC_WriteStrServersPrefix(Client, Origin, "MODE %s %s%s", | ||||
| 					Channel_Name(Channel), the_modes, the_args); | ||||
| 			IRC_WriteStrChannelPrefix(Client, Channel, Origin, false, "MODE %s %s%s", | ||||
| 						Channel_Name(Channel), the_modes, the_args); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	IRC_SetPenalty( Client, 1 ); | ||||
| 	IRC_SetPenalty(Client, 1); | ||||
| 	return CONNECTED; | ||||
| } /* Channel_Mode */ | ||||
|  | ||||
| @@ -633,81 +600,64 @@ IRC_AWAY( CLIENT *Client, REQUEST *Req ) | ||||
|  | ||||
|  | ||||
| static bool | ||||
| Add_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ) | ||||
| Add_Ban_Invite(int what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Pattern) | ||||
| { | ||||
| 	char *mask; | ||||
| 	const char *mask; | ||||
| 	bool already; | ||||
| 	bool ret; | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Channel != NULL ); | ||||
| 	assert( Pattern != NULL ); | ||||
| 	assert(what == 'I' || what == 'b'); | ||||
|  | ||||
| 	mask = Lists_MakeMask( Pattern ); | ||||
| 	mask = Lists_MakeMask(Pattern); | ||||
|  | ||||
| 	already = Lists_IsInviteEntry( mask, Channel ); | ||||
| 	 | ||||
| 	if( ! Lists_AddInvited( mask, Channel, false )) return CONNECTED; | ||||
| 	 | ||||
| 	if(( Client_Type( Prefix ) == CLIENT_SERVER ) && ( already == true)) return CONNECTED; | ||||
| 	already = Lists_CheckDupeMask(Channel_GetListInvites(Channel), mask); | ||||
| 	if (!already) { | ||||
| 		if (what == 'I') | ||||
| 			ret = Channel_AddInvite(Channel, mask, false); | ||||
| 		else | ||||
| 			ret = Channel_AddBan(Channel, mask); | ||||
| 		if (!ret) | ||||
| 			return CONNECTED; | ||||
| 	} | ||||
| 	if (already && (Client_Type(Prefix) == CLIENT_SERVER)) | ||||
| 		return CONNECTED; | ||||
|  | ||||
| 	return Send_ListChange( "+I", Prefix, Client, Channel, mask ); | ||||
| } /* Add_Invite */ | ||||
| 	if (what == 'I') | ||||
| 		return Send_ListChange("+I", Prefix, Client, Channel, mask); | ||||
| 	return Send_ListChange("+b", Prefix, Client, Channel, mask); | ||||
| } | ||||
|  | ||||
|  | ||||
| static bool | ||||
| Add_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ) | ||||
| Del_Ban_Invite(int what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Pattern) | ||||
| { | ||||
| 	char *mask; | ||||
| 	bool already; | ||||
| 	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 ); | ||||
|  | ||||
| 	already = Lists_IsBanEntry( mask, Channel ); | ||||
| 	if (what == 'I') | ||||
| 		list = Channel_GetListInvites(Channel); | ||||
| 	else | ||||
| 		list = Channel_GetListBans(Channel); | ||||
|  | ||||
| 	if( ! Lists_AddBanned( mask, Channel )) return CONNECTED; | ||||
|  | ||||
| 	if(( Client_Type( Prefix ) == CLIENT_SERVER ) && ( already == true)) return CONNECTED; | ||||
|  | ||||
| 	return Send_ListChange( "+b", Prefix, Client, Channel, mask ); | ||||
| } /* Add_Ban */ | ||||
|  | ||||
|  | ||||
| static bool | ||||
| Del_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ) | ||||
| { | ||||
| 	char *mask; | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Channel != NULL ); | ||||
| 	assert( Pattern != NULL ); | ||||
|  | ||||
| 	mask = Lists_MakeMask( Pattern ); | ||||
| 	Lists_DelInvited( mask, Channel ); | ||||
| 	return Send_ListChange( "-I", Prefix, Client, Channel, mask ); | ||||
| } /* Del_Invite */ | ||||
|  | ||||
|  | ||||
| static bool | ||||
| Del_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern ) | ||||
| { | ||||
| 	char *mask; | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Channel != NULL ); | ||||
| 	assert( Pattern != NULL ); | ||||
|  | ||||
| 	mask = Lists_MakeMask( Pattern ); | ||||
| 	Lists_DelBanned( mask, Channel ); | ||||
| 	Lists_Del(list, mask); | ||||
| 	if (what == 'I') | ||||
| 		return Send_ListChange( "-I", Prefix, Client, Channel, mask ); | ||||
| 	return Send_ListChange( "-b", Prefix, Client, Channel, mask ); | ||||
| } /* Del_Ban */ | ||||
| } | ||||
|  | ||||
|  | ||||
| static bool | ||||
| Send_ListChange( char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Mask ) | ||||
| Send_ListChange( char *Mode, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Mask ) | ||||
| { | ||||
| 	/* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */ | ||||
|  | ||||
|   | ||||
| @@ -14,7 +14,7 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: irc-op.c,v 1.15 2005/04/27 07:39:18 alex Exp $"; | ||||
| static char UNUSED id[] = "$Id: irc-op.c,v 1.17 2006/12/07 17:57:20 fw Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| @@ -99,17 +99,17 @@ IRC_INVITE( CLIENT *Client, REQUEST *Req ) | ||||
| 		if( Channel_IsMemberOf( chan, target )) return IRC_WriteStrClient( from, ERR_USERONCHANNEL_MSG, Client_ID( from ), Req->argv[0], Req->argv[1] ); | ||||
|  | ||||
| 		/* If the target user is banned on that channel: remember invite */ | ||||
| 		if( Lists_CheckBanned( target, chan )) remember = true; | ||||
| 		if( Lists_Check(Channel_GetListBans(chan), target )) remember = true; | ||||
|  | ||||
| 		if( remember ) | ||||
| 		{ | ||||
| 			/* We must memember this invite */ | ||||
| 			if( ! Lists_AddInvited( Client_Mask( target ), chan, true)) return CONNECTED; | ||||
| 		if (remember) { | ||||
| 			/* We must remember this invite */ | ||||
| 			if( ! Channel_AddInvite(chan, Client_Mask( target ), true)) | ||||
| 				return CONNECTED; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	Log( LOG_DEBUG, "User \"%s\" invites \"%s\" to \"%s\" ...", Client_Mask( from ), Req->argv[0], Req->argv[1] ); | ||||
| 	 | ||||
| 	LogDebug("User \"%s\" invites \"%s\" to \"%s\" ...", Client_Mask(from), Req->argv[0], Req->argv[1]); | ||||
|  | ||||
| 	/* Inform target client */ | ||||
| 	IRC_WriteStrClientPrefix( target, from, "INVITE %s %s", Req->argv[0], Req->argv[1] ); | ||||
|  | ||||
|   | ||||
| @@ -14,7 +14,7 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: irc-oper.c,v 1.27 2006/07/23 15:43:18 alex Exp $"; | ||||
| static char UNUSED id[] = "$Id: irc-oper.c,v 1.29 2007/08/02 10:14:26 fw Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| @@ -191,12 +191,12 @@ IRC_CONNECT(CLIENT * Client, REQUEST * Req) | ||||
| 					  Client_ID(Client)); | ||||
|  | ||||
| 	/* Bad number of parameters? */ | ||||
| 	if ((Req->argc != 2) && (Req->argc != 5)) | ||||
| 	if ((Req->argc != 1) && (Req->argc != 2) && (Req->argc != 5)) | ||||
| 		return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, | ||||
| 					  Client_ID(Client), Req->command); | ||||
|  | ||||
| 	/* Invalid port number? */ | ||||
| 	if (atoi(Req->argv[1]) < 1) | ||||
| 	if ((Req->argc > 1) && atoi(Req->argv[1]) < 1) | ||||
| 		return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, | ||||
| 					  Client_ID(Client), Req->command); | ||||
|  | ||||
| @@ -204,14 +204,22 @@ IRC_CONNECT(CLIENT * Client, REQUEST * Req) | ||||
| 	    "Got CONNECT command from \"%s\" for \"%s\".", Client_Mask(Client), | ||||
| 	    Req->argv[0]); | ||||
|  | ||||
| 	if (Req->argc == 2) { | ||||
| 	switch (Req->argc) { | ||||
| 	case 1: | ||||
| 		if (!Conf_EnablePassiveServer(Req->argv[0])) | ||||
| 			return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG, | ||||
| 						  Client_ID(Client), | ||||
| 						  Req->argv[0]); | ||||
| 	break; | ||||
| 	case 2: | ||||
| 		/* Connect configured server */ | ||||
| 		if (!Conf_EnableServer | ||||
| 		    (Req->argv[0], (UINT16) atoi(Req->argv[1]))) | ||||
| 			return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG, | ||||
| 						  Client_ID(Client), | ||||
| 						  Req->argv[0]); | ||||
| 	} else { | ||||
| 	break; | ||||
| 	default: | ||||
| 		/* Add server */ | ||||
| 		if (!Conf_AddServer | ||||
| 		    (Req->argv[0], (UINT16) atoi(Req->argv[1]), Req->argv[2], | ||||
| @@ -255,4 +263,54 @@ IRC_DISCONNECT(CLIENT *Client, REQUEST *Req ) | ||||
| } /* IRC_CONNECT */ | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| IRC_WALLOPS( CLIENT *Client, REQUEST *Req ) | ||||
| { | ||||
| 	CLIENT *to, *from; | ||||
| 	int client_type; | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Req != NULL ); | ||||
|  | ||||
| 	if (Req->argc != 1) | ||||
| 		return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, Client_ID(Client), Req->command); | ||||
|  | ||||
| 	client_type = Client_Type(Client); | ||||
| 	switch (client_type) { | ||||
| 	case CLIENT_USER: | ||||
| 		if (!Client_OperByMe(Client)) | ||||
| 			return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG, Client_ID(Client)); | ||||
| 		from = Client; | ||||
| 		break; | ||||
| 	case CLIENT_SERVER: | ||||
| 		from = Client_Search(Req->prefix); | ||||
| 		break; | ||||
| 	default: | ||||
| 		return CONNECTED; | ||||
| 	} | ||||
|  | ||||
| 	if (!from) | ||||
| 		return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, Client_ID(Client), Req->prefix); | ||||
|  | ||||
| 	for (to=Client_First(); to != NULL; to=Client_Next(to)) { | ||||
| 		if (Client_Conn(to) < 0) /* no local connection or WALLOPS origin */ | ||||
| 			continue; | ||||
|  | ||||
| 		client_type = Client_Type(to); | ||||
| 		switch (client_type) { | ||||
| 		case CLIENT_USER: | ||||
| 			if (Client_HasMode(to, 'w')) | ||||
| 				IRC_WriteStrClientPrefix(to, from, "WALLOPS :%s", Req->argv[0]); | ||||
| 			break; | ||||
| 		case CLIENT_SERVER: | ||||
| 			if (to != Client) | ||||
| 				IRC_WriteStrClientPrefix(to, from, "WALLOPS :%s", Req->argv[0]); | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| 	return CONNECTED; | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| /* -eof- */ | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: irc-oper.h,v 1.11 2005/03/19 18:43:48 fw Exp $ | ||||
|  * $Id: irc-oper.h,v 1.12 2007/08/02 10:14:26 fw Exp $ | ||||
|  * | ||||
|  * IRC operator commands (header) | ||||
|  */ | ||||
| @@ -24,6 +24,7 @@ GLOBAL bool IRC_REHASH PARAMS((CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_RESTART PARAMS((CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_CONNECT PARAMS((CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_DISCONNECT PARAMS((CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_WALLOPS PARAMS(( CLIENT *Client, REQUEST *Req )); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  * ngIRCd -- The Next Generation IRC Daemon | ||||
|  * Copyright (c)2001-2006 Alexander Barton (alex@barton.de) | ||||
|  * Copyright (c)2001-2007 Alexander Barton (alex@barton.de) | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
| @@ -14,7 +14,7 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: irc-server.c,v 1.39 2006/04/30 21:31:43 alex Exp $"; | ||||
| static char UNUSED id[] = "$Id: irc-server.c,v 1.46 2007/11/21 12:16:36 alex Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| @@ -35,33 +35,40 @@ static char UNUSED id[] = "$Id: irc-server.c,v 1.39 2006/04/30 21:31:43 alex Exp | ||||
| #include "log.h" | ||||
| #include "messages.h" | ||||
| #include "parse.h" | ||||
| #include "numeric.h" | ||||
| #include "ngircd.h" | ||||
| #include "irc-info.h" | ||||
|  | ||||
| #include "exp.h" | ||||
| #include "irc-server.h" | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Handler for the IRC command "SERVER". | ||||
|  * See RFC 2813 section 4.1.2. | ||||
|  */ | ||||
| GLOBAL bool | ||||
| IRC_SERVER( CLIENT *Client, REQUEST *Req ) | ||||
| { | ||||
| 	char str[LINE_LEN], *ptr, *modes, *topic; | ||||
| 	CLIENT *from, *c, *cl; | ||||
| 	CL2CHAN *cl2chan; | ||||
| 	int max_hops, i; | ||||
| 	CHANNEL *chan; | ||||
| 	char str[LINE_LEN], *ptr; | ||||
| 	CLIENT *from, *c; | ||||
| 	bool ok; | ||||
| 	int i; | ||||
| 	CONN_ID con; | ||||
| 	 | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Req != NULL ); | ||||
|  | ||||
| 	/* Fehler liefern, wenn kein lokaler Client */ | ||||
| 	if( Client_Conn( Client ) <= NONE ) return IRC_WriteStrClient( Client, ERR_UNKNOWNCOMMAND_MSG, Client_ID( Client ), Req->command ); | ||||
| 	/* Return an error if this is not a local client */ | ||||
| 	if (Client_Conn(Client) <= NONE) | ||||
| 		return IRC_WriteStrClient(Client, ERR_UNKNOWNCOMMAND_MSG, | ||||
| 					  Client_ID(Client), Req->command); | ||||
|  | ||||
| 	if( Client_Type( Client ) == CLIENT_GOTPASSSERVER ) | ||||
| 	{ | ||||
| 		/* Verbindung soll als Server-Server-Verbindung registriert werden */ | ||||
| 		Log( LOG_DEBUG, "Connection %d: got SERVER command (new server link) ...", Client_Conn( Client )); | ||||
| 	if (Client_Type(Client) == CLIENT_GOTPASS) { | ||||
| 		/* We got a PASS command from the peer, and now a SERVER | ||||
| 		 * command: the peer tries to register itself as a server. */ | ||||
| 		LogDebug("Connection %d: got SERVER command (new server link) ...", | ||||
| 			Client_Conn(Client)); | ||||
|  | ||||
| 		/* Falsche Anzahl Parameter? */ | ||||
| 		if(( Req->argc != 2 ) && ( Req->argc != 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); | ||||
| @@ -115,10 +122,10 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req ) | ||||
| 			Client_SetToken( Client, atoi( Req->argv[1] )); | ||||
| 		} | ||||
|  | ||||
| 		Log( LOG_NOTICE|LOG_snotice, "Server \"%s\" registered (connection %d, 1 hop - direct link).", Client_ID( Client ), con ); | ||||
|  | ||||
| 		Client_SetType( Client, CLIENT_SERVER ); | ||||
| 		Conf_SetServer( i, con ); | ||||
| 		/* Mark this connection as belonging to an configured server */ | ||||
| 		Conf_SetServer(i, con); | ||||
| 		 | ||||
| 		Client_SetType(Client, CLIENT_UNKNOWNSERVER); | ||||
|  | ||||
| #ifdef ZLIB | ||||
| 		/* Kompression initialisieren, wenn erforderlich */ | ||||
| @@ -133,136 +140,23 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req ) | ||||
| 		} | ||||
| #endif | ||||
|  | ||||
| 		/* maximalen Hop Count ermitteln */ | ||||
| 		max_hops = 0; | ||||
| 		c = Client_First( ); | ||||
| 		while( c ) | ||||
| 		{ | ||||
| 			if( Client_Hops( c ) > max_hops ) max_hops = Client_Hops( c ); | ||||
| 			c = Client_Next( c ); | ||||
| 		} | ||||
| 		 | ||||
| 		/* Alle bisherigen Server dem neuen Server bekannt machen, | ||||
| 		 * die bisherigen Server ueber den neuen informierenn */ | ||||
| 		for( i = 0; i < ( max_hops + 1 ); i++ ) | ||||
| 		{ | ||||
| 			c = Client_First( ); | ||||
| 			while( c ) | ||||
| 			{ | ||||
| 				if(( Client_Type( c ) == CLIENT_SERVER ) && ( c != Client ) && ( c != Client_ThisServer( )) && ( Client_Hops( c ) == i )) | ||||
| 				{ | ||||
| 					if( Client_Conn( c ) > NONE ) | ||||
| 					{ | ||||
| 						/* Dem gefundenen Server gleich den neuen | ||||
| 						 * Server bekannt machen */ | ||||
| 						if( ! IRC_WriteStrClient( c, "SERVER %s %d %d :%s", Client_ID( Client ), Client_Hops( Client ) + 1, Client_MyToken( Client ), Client_Info( Client ))) return DISCONNECTED; | ||||
| 					} | ||||
| 					 | ||||
| 					/* Den neuen Server ueber den alten informieren */ | ||||
| 					if( ! IRC_WriteStrClientPrefix( Client, Client_Hops( c ) == 1 ? Client_ThisServer( ) : Client_Introducer( c ), "SERVER %s %d %d :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_MyToken( c ), Client_Info( c ))) return DISCONNECTED; | ||||
| 				} | ||||
| 				c = Client_Next( c ); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		/* alle User dem neuen Server bekannt machen */ | ||||
| 		c = Client_First( ); | ||||
| 		while( c ) | ||||
| 		{ | ||||
| 			if( Client_Type( c ) == CLIENT_USER ) | ||||
| 			{ | ||||
| 				/* User an neuen Server melden */ | ||||
| 				if( ! IRC_WriteStrClient( Client, "NICK %s %d %s %s %d +%s :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_User( c ), Client_Hostname( c ), Client_MyToken( Client_Introducer( c )), Client_Modes( c ), Client_Info( c ))) return DISCONNECTED; | ||||
| 			} | ||||
| 			c = Client_Next( c ); | ||||
| 		} | ||||
|  | ||||
| 		/* Channels dem neuen Server bekannt machen */ | ||||
| 		chan = Channel_First( ); | ||||
| 		while( chan ) | ||||
| 		{ | ||||
| #ifdef IRCPLUS | ||||
| 			/* Send CHANINFO if the peer supports it */ | ||||
| 			if( strchr( Client_Flags( Client ), 'C' )) | ||||
| 			{ | ||||
| #ifdef DEBUG | ||||
| 				Log( LOG_DEBUG, "Sending CHANINFO commands ..." ); | ||||
| 		if (strchr(Client_Flags(Client), 'H')) { | ||||
| 			LogDebug("Peer supports IRC+ extended server handshake ..."); | ||||
| 			if (!IRC_Send_ISUPPORT(Client)) | ||||
| 				return DISCONNECTED; | ||||
| 			return IRC_WriteStrClient(Client, RPL_ENDOFMOTD_MSG, | ||||
| 						  Client_ID(Client)); | ||||
| 		} else { | ||||
| #endif | ||||
| 				modes = Channel_Modes( chan ); | ||||
| 				topic = Channel_Topic( chan ); | ||||
|  | ||||
| 				if( *modes || *topic ) | ||||
| 				{ | ||||
| 					/* send CHANINFO */ | ||||
| 					if(( ! strchr( Channel_Modes( chan ), 'k' )) && ( ! strchr( Channel_Modes( chan ), 'l' )) && ( ! *topic )) | ||||
| 					{ | ||||
| 						/* "CHANINFO <chan> +<modes>" */ | ||||
| 						if( ! IRC_WriteStrClient( Client, "CHANINFO %s +%s", Channel_Name( chan ), modes )) return DISCONNECTED; | ||||
| 					} | ||||
| 					else if(( ! strchr( Channel_Modes( chan ), 'k' )) && ( ! strchr( Channel_Modes( chan ), 'l' ))) | ||||
| 					{ | ||||
| 						/* "CHANINFO <chan> +<modes> :<topic>" */ | ||||
| 						if( ! IRC_WriteStrClient( Client, "CHANINFO %s +%s :%s", Channel_Name( chan ), modes, topic )) return DISCONNECTED; | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						/* "CHANINFO <chan> +<modes> <key> <limit> :<topic>" */ | ||||
| 						if( ! IRC_WriteStrClient( Client, "CHANINFO %s +%s %s %ld :%s", Channel_Name( chan ), modes, strchr( Channel_Modes( chan ), 'k' ) ? Channel_Key( chan ) : "*", strchr( Channel_Modes( chan ), 'l' ) ? Channel_MaxUsers( chan ) : 0L, topic )) return DISCONNECTED; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| #endif | ||||
|  | ||||
| 			/* alle Member suchen */ | ||||
| 			cl2chan = Channel_FirstMember( chan ); | ||||
| 			snprintf( str, sizeof( str ), "NJOIN %s :", Channel_Name( chan )); | ||||
| 			while( cl2chan ) | ||||
| 			{ | ||||
| 				cl = Channel_GetClient( cl2chan ); | ||||
| 				assert( cl != NULL ); | ||||
|  | ||||
| 				/* Nick, ggf. mit Modes, anhaengen */ | ||||
| 				if( str[strlen( str ) - 1] != ':' ) strlcat( str, ",", sizeof( str )); | ||||
| 				if( strchr( Channel_UserModes( chan, cl ), 'v' )) strlcat( str, "+", sizeof( str )); | ||||
| 				if( strchr( Channel_UserModes( chan, cl ), 'o' )) strlcat( str, "@", sizeof( str )); | ||||
| 				strlcat( str, Client_ID( cl ), sizeof( str )); | ||||
|  | ||||
| 				if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 8 )) | ||||
| 				{ | ||||
| 					/* Zeile senden */ | ||||
| 					if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED; | ||||
| 					snprintf( str, sizeof( str ), "NJOIN %s :", Channel_Name( chan )); | ||||
| 				} | ||||
| 				 | ||||
| 				cl2chan = Channel_NextMember( chan, cl2chan ); | ||||
| 			} | ||||
|  | ||||
| 			/* noch Daten da? */ | ||||
| 			if( str[strlen( str ) - 1] != ':') | ||||
| 			{ | ||||
| 				/* Ja; Also senden ... */ | ||||
| 				if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED; | ||||
| 			} | ||||
|  | ||||
| 			/* Get next channel ... */ | ||||
| 			chan = Channel_Next(chan); | ||||
| 		} | ||||
|  | ||||
| 			if (Conf_MaxNickLength != CLIENT_NICK_LEN_DEFAULT) | ||||
| 				Log(LOG_CRIT, | ||||
| 				    "Attention: this server uses a non-standard nick length, but the peer doesn't support the IRC+ extended server handshake!"); | ||||
| #ifdef IRCPLUS | ||||
| 		if (strchr(Client_Flags(Client), 'L')) { | ||||
| #ifdef DEBUG | ||||
| 			Log(LOG_DEBUG, | ||||
| 			    "Synchronizing INVITE- and BAN-lists ..."); | ||||
| #endif | ||||
| 			/* Synchronize INVITE- and BAN-lists */ | ||||
| 			if (! Lists_SendInvites(Client)) | ||||
| 				return DISCONNECTED; | ||||
| 			if (! Lists_SendBans(Client)) | ||||
| 				return DISCONNECTED; | ||||
| 		} | ||||
| #endif | ||||
|  | ||||
| 		return CONNECTED; | ||||
| 		return IRC_Num_ENDOFMOTD(Client, Req); | ||||
| 	} | ||||
| 	else if( Client_Type( Client ) == CLIENT_SERVER ) | ||||
| 	{ | ||||
| @@ -306,8 +200,9 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req ) | ||||
| 		IRC_WriteStrServersPrefix( Client, from, "SERVER %s %d %d :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_MyToken( c ), Client_Info( c )); | ||||
|  | ||||
| 		return CONNECTED; | ||||
| 	} | ||||
| 	else return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); | ||||
| 	} else | ||||
| 		return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, | ||||
| 					  Client_ID(Client), Req->command); | ||||
| } /* IRC_SERVER */ | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: irc-server.h,v 1.5 2005/03/19 18:43:49 fw Exp $ | ||||
|  * $Id: irc-server.h,v 1.6 2007/11/21 12:16:36 alex Exp $ | ||||
|  * | ||||
|  * IRC commands for server links (header) | ||||
|  */ | ||||
| @@ -22,6 +22,8 @@ GLOBAL bool IRC_SERVER PARAMS((CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_NJOIN PARAMS((CLIENT *Client, REQUEST *Req )); | ||||
| GLOBAL bool IRC_SQUIT PARAMS((CLIENT *Client, REQUEST *Req )); | ||||
|  | ||||
| GLOBAL bool IRC_ENDOFMOTD_Server PARAMS((CLIENT *Client)); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|  | ||||
|   | ||||
| @@ -14,7 +14,7 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: irc-write.c,v 1.20 2006/05/10 21:24:01 alex Exp $"; | ||||
| static char UNUSED id[] = "$Id: irc-write.c,v 1.21 2006/08/12 11:56:24 fw Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| @@ -378,7 +378,7 @@ va_dcl | ||||
| 			} | ||||
| 			cl2chan = Channel_NextMember( chan, cl2chan ); | ||||
| 		} | ||||
| 		 | ||||
|  | ||||
| 		/* naechsten Channel */ | ||||
| 		chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan ); | ||||
| 	} | ||||
| @@ -403,12 +403,12 @@ GLOBAL void | ||||
| IRC_SetPenalty( CLIENT *Client, time_t Seconds ) | ||||
| { | ||||
| 	CONN_ID c; | ||||
| 	 | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Seconds > 0 ); | ||||
| 	 | ||||
|  | ||||
| 	if( Client_Type( Client ) == CLIENT_SERVER ) return; | ||||
| 	 | ||||
|  | ||||
| 	c = Client_Conn( Client ); | ||||
| 	if (c > NONE) | ||||
| 		Conn_SetPenalty(c, Seconds); | ||||
|   | ||||
| @@ -14,7 +14,7 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: irc.c,v 1.131 2006/07/23 14:55:40 alex Exp $"; | ||||
| static char UNUSED id[] = "$Id: irc.c,v 1.132 2008/01/15 22:28:14 fw Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| @@ -170,6 +170,7 @@ GLOBAL bool | ||||
| IRC_NOTICE( CLIENT *Client, REQUEST *Req ) | ||||
| { | ||||
| 	CLIENT *to, *from; | ||||
| 	CHANNEL *chan; | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Req != NULL ); | ||||
| @@ -189,7 +190,14 @@ IRC_NOTICE( CLIENT *Client, REQUEST *Req ) | ||||
| 		/* Okay, Ziel ist ein User */ | ||||
| 		return IRC_WriteStrClientPrefix( to, from, "NOTICE %s :%s", Client_ID( to ), Req->argv[1] ); | ||||
| 	} | ||||
| 	else return CONNECTED; | ||||
| 	else | ||||
| 	{ | ||||
| 		chan = Channel_Search(Req->argv[0]); | ||||
| 		if (chan) | ||||
| 			return Channel_Notice(chan, from, Client, Req->argv[1]); | ||||
| 	} | ||||
|  | ||||
| 	return CONNECTED; | ||||
| } /* IRC_NOTICE */ | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -14,8 +14,6 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: lists.c,v 1.18 2005/07/31 20:13:08 alex Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
|  | ||||
| @@ -35,330 +33,135 @@ static char UNUSED id[] = "$Id: lists.c,v 1.18 2005/07/31 20:13:08 alex Exp $"; | ||||
| #include "exp.h" | ||||
| #include "lists.h" | ||||
|  | ||||
| #define MASK_LEN	(2*CLIENT_HOST_LEN) | ||||
|  | ||||
| #define MASK_LEN 2*CLIENT_HOST_LEN | ||||
|  | ||||
|  | ||||
| typedef struct _C2C | ||||
| { | ||||
| 	struct _C2C *next; | ||||
| struct list_elem { | ||||
| 	struct list_elem *next; | ||||
| 	char mask[MASK_LEN]; | ||||
| 	CHANNEL *channel; | ||||
| 	bool onlyonce; | ||||
| } C2C; | ||||
| }; | ||||
|  | ||||
|  | ||||
| static C2C *My_Invites, *My_Bans; | ||||
|  | ||||
|  | ||||
| static C2C *New_C2C PARAMS(( char *Mask, CHANNEL *Chan, bool OnlyOnce )); | ||||
|  | ||||
| static bool Check_List PARAMS(( C2C **Cl2Chan, CLIENT *Client, CHANNEL *Chan )); | ||||
| static bool Already_Registered PARAMS(( C2C *Cl2Chan, char *Mask, CHANNEL *Chan )); | ||||
|  | ||||
|  | ||||
|  | ||||
| GLOBAL void | ||||
| Lists_Init( void ) | ||||
| GLOBAL const char * | ||||
| Lists_GetMask(const struct list_elem *e) | ||||
| { | ||||
| 	/* Modul initialisieren */ | ||||
|  | ||||
| 	My_Invites = My_Bans = NULL; | ||||
| } /* Lists_Init */ | ||||
| 	return e->mask; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL void | ||||
| Lists_Exit( void ) | ||||
| GLOBAL struct list_elem* | ||||
| Lists_GetFirst(const struct list_head *h) | ||||
| { | ||||
| 	/* Modul abmelden */ | ||||
|  | ||||
| 	C2C *c2c, *next; | ||||
|  | ||||
| 	/* Invite-Lists freigeben */ | ||||
| 	c2c = My_Invites; | ||||
| 	while( c2c ) | ||||
| 	{ | ||||
| 		next = c2c->next; | ||||
| 		free( c2c ); | ||||
| 		c2c = next; | ||||
| 	} | ||||
|  | ||||
| 	/* Ban-Lists freigeben */ | ||||
| 	c2c = My_Bans; | ||||
| 	while( c2c ) | ||||
| 	{ | ||||
| 		next = c2c->next; | ||||
| 		free( c2c ); | ||||
| 		c2c = next; | ||||
| 	} | ||||
| } /* Lists_Exit */ | ||||
| 	return h->first; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Lists_CheckInvited( CLIENT *Client, CHANNEL *Chan ) | ||||
| GLOBAL struct list_elem* | ||||
| Lists_GetNext(const struct list_elem *e) | ||||
| { | ||||
| 	return Check_List( &My_Invites, Client, Chan ); | ||||
| } /* Lists_CheckInvited */ | ||||
| 	return e->next; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Lists_IsInviteEntry( char *Mask, CHANNEL *Chan ) | ||||
| bool | ||||
| Lists_Add(struct list_head *header, const char *Mask, bool OnlyOnce ) | ||||
| { | ||||
| 	struct list_elem *e, *newelem; | ||||
|  | ||||
| 	assert( header != NULL ); | ||||
| 	assert( Mask != NULL ); | ||||
| 	assert( Chan != NULL ); | ||||
| 	 | ||||
| 	return Already_Registered( My_Invites, Mask, Chan ); | ||||
| } /* Lists_IsInviteEntry */ | ||||
|  | ||||
| 	if (Lists_CheckDupeMask(header, Mask )) return true; | ||||
|  | ||||
| GLOBAL bool | ||||
| Lists_AddInvited( char *Mask, CHANNEL *Chan, bool OnlyOnce ) | ||||
| { | ||||
| 	C2C *c2c; | ||||
| 	e = Lists_GetFirst(header); | ||||
|  | ||||
| 	assert( Mask != NULL ); | ||||
| 	assert( Chan != NULL ); | ||||
|  | ||||
| 	if( Already_Registered( My_Invites, Mask, Chan )) return true; | ||||
| 	 | ||||
| 	c2c = New_C2C( Mask, Chan, OnlyOnce ); | ||||
| 	if( ! c2c ) | ||||
| 	{ | ||||
| 		Log( LOG_ERR, "Can't add new invite list entry!" ); | ||||
| 	newelem = malloc(sizeof(struct list_elem)); | ||||
| 	if( ! newelem ) { | ||||
| 		Log( LOG_EMERG, "Can't allocate memory for new Ban/Invite entry!" ); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	/* verketten */ | ||||
| 	c2c->next = My_Invites; | ||||
| 	My_Invites = c2c; | ||||
| 	strlcpy( newelem->mask, Mask, sizeof( newelem->mask )); | ||||
| 	newelem->onlyonce = OnlyOnce; | ||||
| 	newelem->next = e; | ||||
| 	header->first = newelem; | ||||
|  | ||||
| 	Log( LOG_DEBUG, "Added \"%s\" to invite list for \"%s\".", Mask, Channel_Name( Chan )); | ||||
| 	LogDebug("Added \"%s\" to invite list", Mask); | ||||
| 	return true; | ||||
| } /* Lists_AddInvited */ | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| Lists_Unlink(struct list_head *header, struct list_elem *p, struct list_elem *victim) | ||||
| { | ||||
| 	assert(victim != NULL); | ||||
| 	assert(header != NULL); | ||||
|  | ||||
| 	if (p) p->next = victim->next; | ||||
| 	else header->first = victim->next; | ||||
|  | ||||
| 	free(victim); | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL void | ||||
| Lists_DelInvited( char *Mask, CHANNEL *Chan ) | ||||
| Lists_Del(struct list_head *header, const char *Mask) | ||||
| { | ||||
| 	C2C *c2c, *last, *next; | ||||
| 	struct list_elem *e, *last, *victim; | ||||
|  | ||||
| 	assert( header != NULL ); | ||||
| 	assert( Mask != NULL ); | ||||
| 	assert( Chan != NULL ); | ||||
|  | ||||
| 	last = NULL; | ||||
| 	c2c = My_Invites; | ||||
| 	while( c2c ) | ||||
| 	{ | ||||
| 		next = c2c->next; | ||||
| 		if(( c2c->channel == Chan ) && ( strcasecmp( c2c->mask, Mask ) == 0 )) | ||||
| 		{ | ||||
| 			/* dieser Eintrag muss geloescht werden */ | ||||
| 			Log( LOG_DEBUG, "Deleted \"%s\" from invite list for \"%s\"." , c2c->mask, Channel_Name( Chan )); | ||||
| 			if( last ) last->next = next; | ||||
| 			else My_Invites = next; | ||||
| 			free( c2c ); | ||||
| 	e = Lists_GetFirst(header); | ||||
| 	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); | ||||
| 			continue; | ||||
| 		} | ||||
| 		else last = c2c; | ||||
| 		c2c = next; | ||||
| 		last = e; | ||||
| 		e = e->next; | ||||
| 	} | ||||
| } /* Lists_DelInvited */ | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Lists_ShowInvites( CLIENT *Client, CHANNEL *Channel ) | ||||
| { | ||||
| 	C2C *c2c; | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Channel != NULL ); | ||||
|  | ||||
| 	c2c = My_Invites; | ||||
| 	while( c2c ) | ||||
| 	{ | ||||
| 		if( c2c->channel == Channel ) | ||||
| 		{ | ||||
| 			/* Eintrag fuer Channel gefunden; ausgeben: */ | ||||
| 			if( ! IRC_WriteStrClient( Client, RPL_INVITELIST_MSG, Client_ID( Client ), Channel_Name( Channel ), c2c->mask )) return DISCONNECTED; | ||||
| 		} | ||||
| 		c2c = c2c->next; | ||||
| 	} | ||||
| 	return IRC_WriteStrClient( Client, RPL_ENDOFINVITELIST_MSG, Client_ID( Client ), Channel_Name( Channel )); | ||||
| } /* Lists_ShowInvites */ | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Lists_SendInvites( CLIENT *Client ) | ||||
| { | ||||
| 	C2C *c2c; | ||||
| 	 | ||||
| 	assert( Client != NULL ); | ||||
| 	 | ||||
| 	c2c = My_Invites; | ||||
| 	while( c2c ) | ||||
| 	{ | ||||
| 		if( ! IRC_WriteStrClient( Client, "MODE %s +I %s", Channel_Name( c2c->channel ), c2c->mask )) return DISCONNECTED; | ||||
| 		c2c = c2c->next; | ||||
| 	} | ||||
| 	return CONNECTED; | ||||
| } /* Lists_SendInvites */ | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Lists_SendBans( CLIENT *Client ) | ||||
| { | ||||
| 	C2C *c2c; | ||||
| 	 | ||||
| 	assert( Client != NULL ); | ||||
| 	 | ||||
| 	c2c = My_Bans; | ||||
| 	while( c2c ) | ||||
| 	{ | ||||
| 		if( ! IRC_WriteStrClient( Client, "MODE %s +b %s", Channel_Name( c2c->channel ), c2c->mask )) return DISCONNECTED; | ||||
| 		c2c = c2c->next; | ||||
| 	} | ||||
| 	return CONNECTED; | ||||
| } /* Lists_SendBans */ | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Lists_CheckBanned( CLIENT *Client, CHANNEL *Chan ) | ||||
| { | ||||
| 	return Check_List( &My_Bans, Client, Chan ); | ||||
| } /* Lists_CheckBanned */ | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Lists_IsBanEntry( char *Mask, CHANNEL *Chan ) | ||||
| { | ||||
| 	assert( Mask != NULL ); | ||||
| 	assert( Chan != NULL ); | ||||
| 	 | ||||
| 	return Already_Registered( My_Bans, Mask, Chan ); | ||||
| } /* Lists_IsBanEntry */ | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Lists_AddBanned( char *Mask, CHANNEL *Chan ) | ||||
| { | ||||
| 	C2C *c2c; | ||||
|  | ||||
| 	assert( Mask != NULL ); | ||||
| 	assert( Chan != NULL ); | ||||
|  | ||||
| 	if( Already_Registered( My_Bans, Mask, Chan )) return true; | ||||
|  | ||||
| 	c2c = New_C2C( Mask, Chan, false ); | ||||
| 	if( ! c2c ) | ||||
| 	{ | ||||
| 		Log( LOG_ERR, "Can't add new ban list entry!" ); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	/* verketten */ | ||||
| 	c2c->next = My_Bans; | ||||
| 	My_Bans = c2c; | ||||
|  | ||||
| 	Log( LOG_DEBUG, "Added \"%s\" to ban list for \"%s\".", Mask, Channel_Name( Chan )); | ||||
| 	return true; | ||||
| } /* Lists_AddBanned */ | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL void | ||||
| Lists_DelBanned( char *Mask, CHANNEL *Chan ) | ||||
| Lists_Free(struct list_head *head) | ||||
| { | ||||
| 	C2C *c2c, *last, *next; | ||||
| 	struct list_elem *e, *victim; | ||||
|  | ||||
| 	assert( Mask != NULL ); | ||||
| 	assert( Chan != NULL ); | ||||
| 	assert(head != NULL); | ||||
|  | ||||
| 	last = NULL; | ||||
| 	c2c = My_Bans; | ||||
| 	while( c2c ) | ||||
| 	{ | ||||
| 		next = c2c->next; | ||||
| 		if(( c2c->channel == Chan ) && ( strcasecmp( c2c->mask, Mask ) == 0 )) | ||||
| 		{ | ||||
| 			/* dieser Eintrag muss geloescht werden */ | ||||
| 			Log( LOG_DEBUG, "Deleted \"%s\" from ban list for \"%s\"." , c2c->mask, Channel_Name( Chan )); | ||||
| 			if( last ) last->next = next; | ||||
| 			else My_Bans = next; | ||||
| 			free( c2c ); | ||||
| 		} | ||||
| 		else last = c2c; | ||||
| 		c2c = next; | ||||
| 	e = head->first; | ||||
| 	head->first = NULL; | ||||
| 	while (e) { | ||||
| 		LogDebug("Deleted \"%s\" from invite list" , e->mask); | ||||
| 		victim = e; | ||||
| 		e = e->next; | ||||
| 		free( victim ); | ||||
| 	} | ||||
| } /* Lists_DelBanned */ | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Lists_ShowBans( CLIENT *Client, CHANNEL *Channel ) | ||||
| Lists_CheckDupeMask(const struct list_head *h, const char *Mask ) | ||||
| { | ||||
| 	C2C *c2c; | ||||
|  | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Channel != NULL ); | ||||
|  | ||||
| 	c2c = My_Bans; | ||||
| 	while( c2c ) | ||||
| 	{ | ||||
| 		if( c2c->channel == Channel ) | ||||
| 		{ | ||||
| 			/* Eintrag fuer Channel gefunden; ausgeben: */ | ||||
| 			if( ! IRC_WriteStrClient( Client, RPL_BANLIST_MSG, Client_ID( Client ), Channel_Name( Channel ), c2c->mask )) return DISCONNECTED; | ||||
| 		} | ||||
| 		c2c = c2c->next; | ||||
| 	struct list_elem *e; | ||||
| 	e = h->first; | ||||
| 	while (e) { | ||||
| 		if (strcasecmp( e->mask, Mask ) == 0 ) | ||||
| 			return true; | ||||
| 		e = e->next; | ||||
| 	} | ||||
| 	return IRC_WriteStrClient( Client, RPL_ENDOFBANLIST_MSG, Client_ID( Client ), Channel_Name( Channel )); | ||||
| } /* Lists_ShowBans */ | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
|  | ||||
| GLOBAL void | ||||
| Lists_DeleteChannel( CHANNEL *Chan ) | ||||
| { | ||||
| 	/* Channel wurde geloescht, Invite- und Ban-Lists aufraeumen */ | ||||
|  | ||||
| 	C2C *c2c, *last, *next; | ||||
|  | ||||
| 	/* Invite-List */ | ||||
| 	last = NULL; | ||||
| 	c2c = My_Invites; | ||||
| 	while( c2c ) | ||||
| 	{ | ||||
| 		next = c2c->next; | ||||
| 		if( c2c->channel == Chan ) | ||||
| 		{ | ||||
| 			/* dieser Eintrag muss geloescht werden */ | ||||
| 			Log( LOG_DEBUG, "Deleted \"%s\" from invite list for \"%s\"." , c2c->mask, Channel_Name( Chan )); | ||||
| 			if( last ) last->next = next; | ||||
| 			else My_Invites = next; | ||||
| 			free( c2c ); | ||||
| 		} | ||||
| 		else last = c2c; | ||||
| 		c2c = next; | ||||
| 	} | ||||
|  | ||||
| 	/* Ban-List */ | ||||
| 	last = NULL; | ||||
| 	c2c = My_Bans; | ||||
| 	while( c2c ) | ||||
| 	{ | ||||
| 		next = c2c->next; | ||||
| 		if( c2c->channel == Chan ) | ||||
| 		{ | ||||
| 			/* dieser Eintrag muss geloescht werden */ | ||||
| 			Log( LOG_DEBUG, "Deleted \"%s\" from ban list for \"%s\"." , c2c->mask, Channel_Name( Chan )); | ||||
| 			if( last ) last->next = next; | ||||
| 			else My_Bans = next; | ||||
| 			free( c2c ); | ||||
| 		} | ||||
| 		else last = c2c; | ||||
| 		c2c = next; | ||||
| 	} | ||||
| } /* Lists_DeleteChannel */ | ||||
|  | ||||
|  | ||||
| GLOBAL char * | ||||
| Lists_MakeMask( char *Pattern ) | ||||
| 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(), | ||||
| @@ -407,82 +210,30 @@ Lists_MakeMask( char *Pattern ) | ||||
| } /* Lists_MakeMask */ | ||||
|  | ||||
|  | ||||
| static C2C * | ||||
| New_C2C( char *Mask, CHANNEL *Chan, bool OnlyOnce ) | ||||
|  | ||||
| bool | ||||
| Lists_Check( struct list_head *header, CLIENT *Client) | ||||
| { | ||||
| 	C2C *c2c; | ||||
| 	 | ||||
| 	assert( Mask != NULL ); | ||||
| 	assert( Chan != NULL ); | ||||
| 	struct list_elem *e, *last; | ||||
|  | ||||
| 	/* Speicher fuer Eintrag anfordern */ | ||||
| 	c2c = (C2C *)malloc( sizeof( C2C )); | ||||
| 	if( ! c2c ) | ||||
| 	{ | ||||
| 		Log( LOG_EMERG, "Can't allocate memory! [New_C2C]" ); | ||||
| 		return NULL; | ||||
| 	} | ||||
| 	assert( header != NULL ); | ||||
|  | ||||
| 	strlcpy( c2c->mask, Mask, sizeof( c2c->mask )); | ||||
| 	c2c->channel = Chan; | ||||
| 	c2c->onlyonce = OnlyOnce; | ||||
|  | ||||
| 	return c2c; | ||||
| } /* New_C2C */ | ||||
|  | ||||
|  | ||||
| static bool | ||||
| Check_List( C2C **Cl2Chan, CLIENT *Client, CHANNEL *Chan ) | ||||
| { | ||||
| 	C2C *c2c, *last; | ||||
|  | ||||
| 	assert( Cl2Chan != NULL ); | ||||
| 	assert( Client != NULL ); | ||||
| 	assert( Chan != NULL ); | ||||
|  | ||||
| 	c2c = *Cl2Chan; | ||||
| 	e = header->first; | ||||
| 	last = NULL; | ||||
|  | ||||
| 	while( c2c ) | ||||
| 	{ | ||||
| 		if( c2c->channel == Chan ) | ||||
| 		{ | ||||
| 			/* Ok, richtiger Channel. Passt die Maske? */ | ||||
| 			if( Match( c2c->mask, Client_Mask( Client ))) | ||||
| 			{ | ||||
| 				/* Treffer! */ | ||||
| 				if( c2c->onlyonce ) | ||||
| 				{ | ||||
| 					/* Eintrag loeschen */ | ||||
| 					Log( LOG_DEBUG, "Deleted \"%s\" from %s list for \"%s\".", c2c->mask, *Cl2Chan == My_Invites ? "invite" : "ban", Channel_Name( Chan )); | ||||
| 					if( last ) last->next = c2c->next; | ||||
| 					else *Cl2Chan = c2c->next; | ||||
| 					free( c2c ); | ||||
| 				} | ||||
| 				return true; | ||||
| 	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); | ||||
| 			} | ||||
| 			return true; | ||||
| 		} | ||||
| 		last = c2c; | ||||
| 		c2c = c2c->next; | ||||
| 		last = e; | ||||
| 		e = e->next; | ||||
| 	} | ||||
|  | ||||
| 	return false; | ||||
| } /* Check_List */ | ||||
|  | ||||
|  | ||||
| static bool | ||||
| Already_Registered( C2C *List, char *Mask, CHANNEL *Chan ) | ||||
| { | ||||
| 	C2C *c2c; | ||||
|  | ||||
| 	c2c = List; | ||||
| 	while( c2c ) | ||||
| 	{ | ||||
| 		if(( c2c->channel == Chan ) && ( strcasecmp( c2c->mask, Mask ) == 0 )) return true; | ||||
| 		c2c = c2c->next; | ||||
| 	} | ||||
| 	return false; | ||||
| } /* Already_Registered */ | ||||
|  | ||||
| } | ||||
|  | ||||
| /* -eof- */ | ||||
|   | ||||
| @@ -8,39 +8,37 @@ | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: lists.h,v 1.12 2005/03/19 18:43:49 fw Exp $ | ||||
|  * | ||||
|  * Management of IRC lists: ban, invite, ... (header) | ||||
|  */ | ||||
|  | ||||
|  | ||||
| #ifndef __lists_h__ | ||||
| #define __lists_h__ | ||||
| #include "portab.h" | ||||
| #include "client.h" | ||||
|  | ||||
| struct list_elem; | ||||
|  | ||||
| struct list_head { | ||||
| 	struct list_elem *first; | ||||
| }; | ||||
|  | ||||
|  | ||||
| GLOBAL void Lists_Init PARAMS(( void )); | ||||
| GLOBAL void Lists_Exit PARAMS(( void )); | ||||
| 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_CheckInvited PARAMS(( CLIENT *Client, CHANNEL *Chan )); | ||||
| GLOBAL bool Lists_AddInvited PARAMS(( char *Mask, CHANNEL *Chan, bool OnlyOnce )); | ||||
| GLOBAL void Lists_DelInvited PARAMS(( char *Mask, CHANNEL *Chan )); | ||||
| GLOBAL bool Lists_ShowInvites PARAMS(( CLIENT *Client, CHANNEL *Channel )); | ||||
| GLOBAL bool Lists_SendInvites PARAMS(( CLIENT *Client )); | ||||
| GLOBAL bool Lists_IsInviteEntry PARAMS(( char *Mask, CHANNEL *Chan )); | ||||
| 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_CheckBanned PARAMS(( CLIENT *Client, CHANNEL *Chan )); | ||||
| GLOBAL bool Lists_AddBanned PARAMS(( char *Mask, CHANNEL *Chan )); | ||||
| GLOBAL void Lists_DelBanned PARAMS(( char *Mask, CHANNEL *Chan )); | ||||
| GLOBAL bool Lists_ShowBans PARAMS(( CLIENT *Client, CHANNEL *Channel )); | ||||
| GLOBAL bool Lists_SendBans PARAMS(( CLIENT *Client )); | ||||
| GLOBAL bool Lists_IsBanEntry PARAMS(( char *Mask, CHANNEL *Chan )); | ||||
| 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 void Lists_DeleteChannel PARAMS(( CHANNEL *Chan )); | ||||
| GLOBAL bool Lists_AlreadyRegistered PARAMS(( const struct list_head *head, const char *Mask)); | ||||
|  | ||||
| GLOBAL char *Lists_MakeMask PARAMS(( char *Pattern )); | ||||
| 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 )); | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
| /* -eof- */ | ||||
|   | ||||
| @@ -14,7 +14,7 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: log.c,v 1.61 2006/07/23 23:23:45 alex Exp $"; | ||||
| static char UNUSED id[] = "$Id: log.c,v 1.62 2006/08/05 09:16:21 fw Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| @@ -166,25 +166,21 @@ Log_Exit( void ) | ||||
|  * Log function for debug messages. | ||||
|  * This function is only functional when the program is compiled with debug | ||||
|  * code enabled; otherwise it is an empty function which the compiler will | ||||
|  * hopefully mangle down to "nothing". Therefore you should use LogDebug(...) | ||||
|  * in favor to Log(LOG_DEBUG, ...). | ||||
|  * hopefully mangle down to "nothing" (see log.h). Therefore you should use | ||||
|  * LogDebug(...) in favor to Log(LOG_DEBUG, ...). | ||||
|  * @param Format Format string like printf(). | ||||
|  * @param ... Further arguments. | ||||
|  */ | ||||
| #ifdef DEBUG | ||||
| # ifdef PROTOTYPES | ||||
| GLOBAL void | ||||
| #ifdef DEBUG | ||||
| LogDebug( const char *Format, ... ) | ||||
| #else | ||||
| LogDebug( UNUSED const char *Format, ... ) | ||||
| #endif /* DEBUG */ | ||||
| # else | ||||
| GLOBAL void | ||||
| LogDebug( Format, va_alist ) | ||||
| const char *Format; | ||||
| va_dcl | ||||
| # endif /* PROTOTYPES */ | ||||
| #ifdef DEBUG | ||||
| { | ||||
| 	char msg[MAX_LOG_MSG_LEN]; | ||||
| 	va_list ap; | ||||
| @@ -199,14 +195,9 @@ va_dcl | ||||
| 	va_end( ap ); | ||||
| 	Log(LOG_DEBUG, "%s", msg); | ||||
| } | ||||
| #else | ||||
| { | ||||
| 	/* Do nothing. | ||||
| 	 * The compiler should optimize this out, please ;-) */ | ||||
| } | ||||
| #endif	/* DEBUG */ | ||||
|  | ||||
| 	 | ||||
|  | ||||
| /** | ||||
|  * Logging function of ngIRCd. | ||||
|  * This function logs messages to the console and/or syslog, whichever is | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: log.h,v 1.19 2006/02/08 17:33:28 fw Exp $ | ||||
|  * $Id: log.h,v 1.20 2006/08/05 09:16:21 fw Exp $ | ||||
|  * | ||||
|  * Logging functions (header) | ||||
|  */ | ||||
| @@ -39,7 +39,13 @@ GLOBAL void Log_Init PARAMS(( bool Daemon_Mode )); | ||||
| GLOBAL void Log_Exit PARAMS(( void )); | ||||
|  | ||||
| GLOBAL void Log PARAMS(( int Level, const char *Format, ... )); | ||||
|  | ||||
| #ifdef DEBUG | ||||
| GLOBAL void LogDebug PARAMS(( const char *Format, ... )); | ||||
| #else | ||||
| static inline void LogDebug PARAMS(( UNUSED const char *Format, ... )){/* Do nothing. The compiler should optimize this out, please ;-) */} | ||||
| #endif | ||||
|  | ||||
|  | ||||
| GLOBAL void Log_Init_Resolver PARAMS(( void )); | ||||
| GLOBAL void Log_Exit_Resolver PARAMS(( void )); | ||||
|   | ||||
| @@ -14,7 +14,7 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: match.c,v 1.4 2005/07/31 20:13:08 alex Exp $"; | ||||
| static char UNUSED id[] = "$Id: match.c,v 1.5 2006/10/06 21:23:47 fw Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| @@ -32,8 +32,8 @@ static char UNUSED id[] = "$Id: match.c,v 1.4 2005/07/31 20:13:08 alex Exp $"; | ||||
|  */ | ||||
|  | ||||
|  | ||||
| static int Matche PARAMS(( char *p, char *t )); | ||||
| static int Matche_After_Star PARAMS(( char *p, char *t )); | ||||
| static int Matche PARAMS(( const char *p, const char *t )); | ||||
| static int Matche_After_Star PARAMS(( const char *p, const char *t )); | ||||
|  | ||||
|  | ||||
| #define MATCH_PATTERN	6	/* bad pattern */ | ||||
| @@ -45,7 +45,7 @@ static int Matche_After_Star PARAMS(( char *p, char *t )); | ||||
|  | ||||
|  | ||||
| GLOBAL bool | ||||
| Match( char *Pattern, char *String ) | ||||
| Match( const char *Pattern, const char *String ) | ||||
| { | ||||
| 	/* Pattern mit String vergleichen */ | ||||
| 	if( Matche( Pattern, String ) == MATCH_VALID ) return true; | ||||
| @@ -54,7 +54,7 @@ Match( char *Pattern, char *String ) | ||||
|  | ||||
|  | ||||
| static int | ||||
| Matche( char *p, char *t ) | ||||
| Matche( const char *p, const char *t ) | ||||
| { | ||||
| 	register char range_start, range_end; | ||||
| 	bool invert; | ||||
| @@ -201,7 +201,7 @@ Matche( char *p, char *t ) | ||||
|  | ||||
|  | ||||
| static int | ||||
| Matche_After_Star( char *p, char *t ) | ||||
| Matche_After_Star( const char *p, const char *t ) | ||||
| { | ||||
| 	register int nextp, match = 0; | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: match.h,v 1.3 2005/03/19 18:43:49 fw Exp $ | ||||
|  * $Id: match.h,v 1.4 2006/10/06 21:23:47 fw Exp $ | ||||
|  * | ||||
|  * Wildcard pattern matching (header) | ||||
|  */ | ||||
| @@ -18,7 +18,7 @@ | ||||
| #define __match_h__ | ||||
|  | ||||
|  | ||||
| GLOBAL bool Match PARAMS(( char *Pattern, char *String )); | ||||
| GLOBAL bool Match PARAMS(( const char *Pattern, const char *String )); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: messages.h,v 1.67 2005/09/02 12:50:25 alex Exp $ | ||||
|  * $Id: messages.h,v 1.75 2008/02/17 13:26:42 alex Exp $ | ||||
|  * | ||||
|  * IRC numerics (Header) | ||||
|  */ | ||||
| @@ -22,7 +22,8 @@ | ||||
| #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_ISUPPORT_MSG		"005 %s NICKLEN=%d TOPICLEN=%d AWAYLEN=%d MAXCHANNELS=%d :are supported on this server" | ||||
| #define RPL_ISUPPORT1_MSG		"005 %s RFC2812 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_TRACELINK_MSG		"200 %s Link %s-%s %s %s V%s %ld %d %d" | ||||
| #define RPL_TRACEOPERATOR_MSG		"204 %s Oper 2 :%s" | ||||
| @@ -31,18 +32,19 @@ | ||||
| #define RPL_STATSCOMMANDS_MSG		"212 %s %s %ld %ld %ld" | ||||
| #define RPL_ENDOFSTATS_MSG		"219 %s %c :End of STATS report" | ||||
| #define RPL_UMODEIS_MSG			"221 %s +%s" | ||||
| #define RPL_STATSUPTIME			"242 %s :Server Up %u days %u:%02u:%02u" | ||||
| #define RPL_LUSERCLIENT_MSG		"251 %s :There are %ld users and %ld services on %ld servers" | ||||
| #define RPL_LUSEROP_MSG			"252 %s %ld :operator(s) online" | ||||
| #define RPL_LUSERUNKNOWN_MSG		"253 %s %ld :unknown connection(s)" | ||||
| #define RPL_LUSERCHANNELS_MSG		"254 %s %ld :channels formed" | ||||
| #define RPL_LUSERME_MSG			"255 %s :I have %ld users, %ld services and %ld servers" | ||||
| #define RPL_LUSEROP_MSG			"252 %s %lu :operator(s) online" | ||||
| #define RPL_LUSERUNKNOWN_MSG		"253 %s %lu :unknown connection(s)" | ||||
| #define RPL_LUSERCHANNELS_MSG		"254 %s %lu :channels formed" | ||||
| #define RPL_LUSERME_MSG			"255 %s :I have %lu users, %lu services and %lu servers" | ||||
| #define RPL_ADMINME_MSG			"256 %s %s :Administrative info" | ||||
| #define RPL_ADMINLOC1_MSG		"257 %s :%s" | ||||
| #define RPL_ADMINLOC2_MSG		"258 %s :%s" | ||||
| #define RPL_ADMINEMAIL_MSG		"259 %s :%s" | ||||
| #define RPL_TRACEEND_MSG		"262 %s %s %s-%s.%s :End of TRACE" | ||||
| #define RPL_LOCALUSERS_MSG		"265 %s :Current local users: %ld, Max: %ld" | ||||
| #define RPL_NETUSERS_MSG		"266 %s :Current global users: %ld, Max: %ld" | ||||
| #define RPL_LOCALUSERS_MSG		"265 %s %lu %lu :Current local users: %lu, Max: %lu" | ||||
| #define RPL_NETUSERS_MSG		"266 %s %lu %lu :Current global users: %lu, Max: %lu" | ||||
|  | ||||
| #define RPL_AWAY_MSG			"301 %s %s :%s" | ||||
| #define RPL_USERHOST_MSG		"302 %s :" | ||||
| @@ -54,7 +56,7 @@ | ||||
| #define RPL_WHOISOPERATOR_MSG		"313 %s %s :is an IRC operator" | ||||
| #define RPL_WHOWASUSER_MSG		"314 %s %s %s %s * :%s" | ||||
| #define RPL_ENDOFWHO_MSG		"315 %s %s :End of WHO list" | ||||
| #define RPL_WHOISIDLE_MSG		"317 %s %s %ld :seconds idle" | ||||
| #define RPL_WHOISIDLE_MSG		"317 %s %s %lu %lu :seconds idle, signon time" | ||||
| #define RPL_ENDOFWHOIS_MSG		"318 %s %s :End of WHOIS list" | ||||
| #define RPL_WHOISCHANNELS_MSG		"319 %s %s :" | ||||
| #define RPL_LIST_MSG			"322 %s %s %ld :%s" | ||||
| @@ -75,6 +77,8 @@ | ||||
| #define RPL_BANLIST_MSG			"367 %s %s %s" | ||||
| #define RPL_ENDOFBANLIST_MSG		"368 %s %s :End of channel ban list" | ||||
| #define RPL_ENDOFWHOWAS_MSG		"369 %s %s :End of WHOWAS list" | ||||
| #define RPL_INFO_MSG    		"371 %s :%s" | ||||
| #define RPL_ENDOFINFO_MSG    		"374 %s :End of INFO list" | ||||
| #define RPL_MOTD_MSG			"372 %s :- %s" | ||||
| #define RPL_MOTDSTART_MSG		"375 %s :- %s message of the day" | ||||
| #define RPL_ENDOFMOTD_MSG		"376 %s :End of MOTD command" | ||||
| @@ -98,6 +102,8 @@ | ||||
| #define ERR_USERNOTINCHANNEL_MSG	"441 %s %s %s :They aren't on that channel" | ||||
| #define ERR_NOTONCHANNEL_MSG		"442 %s %s :You are not on that channel" | ||||
| #define ERR_USERONCHANNEL_MSG		"443 %s %s %s :is already on channel" | ||||
| #define ERR_SUMMONDISABLED_MSG		"445 %s %s :SUMMON has been disabled" | ||||
| #define ERR_USERSDISABLED_MSG		"446 %s %s :USERS has been disabled" | ||||
| #define ERR_NOTREGISTERED_MSG		"451 %s :Connection not registered" | ||||
| #define ERR_NOTREGISTEREDSERVER_MSG	"451 %s :Connection not registered as server link" | ||||
| #define ERR_NEEDMOREPARAMS_MSG		"461 %s %s :Syntax error" | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| /* | ||||
|  * ngIRCd -- The Next Generation IRC Daemon | ||||
|  * Copyright (c)2001-2006 Alexander Barton (alex@barton.de). | ||||
|  * Copyright (c)2001-2008 Alexander Barton (alex@barton.de). | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
| @@ -12,8 +12,6 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: ngircd.c,v 1.113 2006/07/23 12:07:33 alex Exp $"; | ||||
|  | ||||
| /** | ||||
|  * @file | ||||
|  * The main program, including the C function main() which is called | ||||
| @@ -42,7 +40,6 @@ static char UNUSED id[] = "$Id: ngircd.c,v 1.113 2006/07/23 12:07:33 alex Exp $" | ||||
| #include "client.h" | ||||
| #include "channel.h" | ||||
| #include "conf.h" | ||||
| #include "cvs-version.h" | ||||
| #include "lists.h" | ||||
| #include "log.h" | ||||
| #include "parse.h" | ||||
| @@ -271,7 +268,6 @@ main( int argc, const char *argv[] ) | ||||
|  | ||||
| 		/* Initialize modules, part II: these functions are eventually | ||||
| 		 * called with already dropped privileges ... */ | ||||
| 		Lists_Init( ); | ||||
| 		Channel_Init( ); | ||||
| 		Client_Init( ); | ||||
| #ifdef ZEROCONF | ||||
| @@ -328,7 +324,6 @@ main( int argc, const char *argv[] ) | ||||
| #endif | ||||
| 		Client_Exit( ); | ||||
| 		Channel_Exit( ); | ||||
| 		Lists_Exit( ); | ||||
| 		Log_Exit( ); | ||||
| 	} | ||||
| 	Pidfile_Delete( ); | ||||
| @@ -399,7 +394,12 @@ Fill_Version( void ) | ||||
|  | ||||
| 	strlcat( NGIRCd_VersionAddition, "IRCPLUS", sizeof NGIRCd_VersionAddition ); | ||||
| #endif | ||||
| #ifdef WANT_IPV6 | ||||
| 	if (NGIRCd_VersionAddition[0]) | ||||
| 		strlcat(NGIRCd_VersionAddition, "+", sizeof(NGIRCd_VersionAddition)); | ||||
|  | ||||
| 	strlcat(NGIRCd_VersionAddition, "IPv6", sizeof(NGIRCd_VersionAddition)); | ||||
| #endif | ||||
| 	if( NGIRCd_VersionAddition[0] ) | ||||
| 		strlcat( NGIRCd_VersionAddition, "-", sizeof( NGIRCd_VersionAddition )); | ||||
|  | ||||
| @@ -409,12 +409,9 @@ Fill_Version( void ) | ||||
| 	strlcat( NGIRCd_VersionAddition, "/", sizeof( NGIRCd_VersionAddition )); | ||||
| 	strlcat( NGIRCd_VersionAddition, TARGET_OS, sizeof( NGIRCd_VersionAddition )); | ||||
|  | ||||
| #ifdef CVSDATE | ||||
| 	snprintf( NGIRCd_Version, sizeof NGIRCd_Version,"%s %s(%s)-%s", PACKAGE_NAME, PACKAGE_VERSION, CVSDATE, NGIRCd_VersionAddition); | ||||
| #else | ||||
| 	snprintf( NGIRCd_Version, sizeof NGIRCd_Version, "%s %s-%s", PACKAGE_NAME, PACKAGE_VERSION, NGIRCd_VersionAddition); | ||||
| #endif | ||||
| } /* Fill_Version */ | ||||
| 	snprintf(NGIRCd_Version, sizeof NGIRCd_Version, "%s %s-%s", | ||||
| 		 PACKAGE_NAME, PACKAGE_VERSION, NGIRCd_VersionAddition); | ||||
| 	} /* Fill_Version */ | ||||
|  | ||||
|  | ||||
| /** | ||||
| @@ -424,24 +421,31 @@ GLOBAL void | ||||
| NGIRCd_Rehash( void ) | ||||
| { | ||||
| 	char old_name[CLIENT_ID_LEN]; | ||||
| 	unsigned old_nicklen; | ||||
|  | ||||
| 	Log( LOG_NOTICE|LOG_snotice, "Re-reading configuration NOW!" ); | ||||
| 	NGIRCd_SignalRehash = false; | ||||
|  | ||||
| 	/* Remember old server name and nick name length */ | ||||
| 	strlcpy( old_name, Conf_ServerName, sizeof old_name ); | ||||
| 	old_nicklen = Conf_MaxNickLength; | ||||
|  | ||||
| 	/* Re-read configuration ... */ | ||||
| 	if (!Conf_Rehash( )) | ||||
| 		return; | ||||
|  | ||||
| 	/* Close down all listening sockets */ | ||||
| 	Conn_ExitListeners( ); | ||||
|  | ||||
| 	/* Remember old server name */ | ||||
| 	strlcpy( old_name, Conf_ServerName, sizeof old_name ); | ||||
|  | ||||
| 	/* Re-read configuration ... */ | ||||
| 	Conf_Rehash( ); | ||||
|  | ||||
| 	/* Recover old server name: it can't be changed during run-time */ | ||||
| 	if( strcmp( old_name, Conf_ServerName ) != 0 ) | ||||
| 	{ | ||||
| 		strlcpy( Conf_ServerName, old_name, sizeof Conf_ServerName ); | ||||
| 		Log( LOG_ERR, "Can't change \"ServerName\" on runtime! Ignored new name." ); | ||||
| 	/* Recover old server name and nick name length: these values can't | ||||
| 	 * be changed during run-time */ | ||||
| 	if (strcmp(old_name, Conf_ServerName) != 0 ) { | ||||
| 		strlcpy(Conf_ServerName, old_name, sizeof Conf_ServerName); | ||||
| 		Log(LOG_ERR, "Can't change \"ServerName\" on runtime! Ignored new name."); | ||||
| 	} | ||||
| 	if (old_nicklen != Conf_MaxNickLength) { | ||||
| 		Conf_MaxNickLength = old_nicklen; | ||||
| 		Log(LOG_ERR, "Can't change \"MaxNickLength\" on runtime! Ignored new value."); | ||||
| 	} | ||||
|  | ||||
| 	/* Create new pre-defined channels */ | ||||
| @@ -548,7 +552,7 @@ static void | ||||
| Show_Version( void ) | ||||
| { | ||||
| 	puts( NGIRCd_Version ); | ||||
| 	puts( "Copyright (c)2001-2006 Alexander Barton (<alex@barton.de>) and Contributors." ); | ||||
| 	puts( "Copyright (c)2001-2008 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." ); | ||||
| @@ -799,7 +803,7 @@ NGIRCd_Init( bool NGIRCd_NoDaemon ) | ||||
| 			if( chdir( pwd->pw_dir ) == 0 )  | ||||
| 				Log( LOG_DEBUG, "Changed working directory to \"%s\" ...", pwd->pw_dir ); | ||||
| 			else  | ||||
| 				Log( LOG_ERR, "Can't change working directory to \"%s\": %s", | ||||
| 				Log( LOG_INFO, "Notice: Can't change working directory to \"%s\": %s", | ||||
| 								pwd->pw_dir, strerror( errno )); | ||||
| 		} | ||||
| 	} else { | ||||
|   | ||||
							
								
								
									
										334
									
								
								src/ngircd/numeric.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										334
									
								
								src/ngircd/numeric.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,334 @@ | ||||
| /* | ||||
|  * ngIRCd -- The Next Generation IRC Daemon | ||||
|  * Copyright (c)2001-2007 Alexander Barton (alex@barton.de) | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * Handlers for IRC numerics sent to the server | ||||
|  */ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: numeric.c,v 1.1 2007/11/21 12:20:32 alex Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "defines.h" | ||||
| #include "resolve.h" | ||||
| #include "conn.h" | ||||
| #include "conf.h" | ||||
| #include "conn.h" | ||||
| #include "client.h" | ||||
| #include "channel.h" | ||||
| #include "irc-write.h" | ||||
| #include "lists.h" | ||||
| #include "log.h" | ||||
| #include "messages.h" | ||||
| #include "parse.h" | ||||
|  | ||||
| #include "exp.h" | ||||
| #include "numeric.h" | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Announce new server in the network | ||||
|  * @param Client New server | ||||
|  * @param Server Existing server in the network | ||||
|  */ | ||||
| static bool | ||||
| Announce_Server(CLIENT * Client, CLIENT * Server) | ||||
| { | ||||
| 	CLIENT *c; | ||||
|  | ||||
| 	if (Client_Conn(Server) > NONE) { | ||||
| 		/* Announce the new server to the one already registered | ||||
| 		 * which is directly connected to the local server */ | ||||
| 		if (!IRC_WriteStrClient | ||||
| 		    (Server, "SERVER %s %d %d :%s", Client_ID(Client), | ||||
| 		     Client_Hops(Client) + 1, Client_MyToken(Client), | ||||
| 		     Client_Info(Client))) | ||||
| 			return DISCONNECTED; | ||||
| 	} | ||||
|  | ||||
| 	if (Client_Hops(Server) == 1) | ||||
| 		c = Client_ThisServer(); | ||||
| 	else | ||||
| 		c = Client_Introducer(Server); | ||||
|  | ||||
| 	/* Inform new server about the one already registered in the network */ | ||||
| 	return IRC_WriteStrClientPrefix(Client, c, "SERVER %s %d %d :%s", | ||||
| 		Client_ID(Server), Client_Hops(Server) + 1, | ||||
| 		Client_MyToken(Server), Client_Info(Server)); | ||||
| } /* Announce_Server */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Announce existing user to a new server | ||||
|  * @param Client New server | ||||
|  * @param User Existing user in the network | ||||
|  */ | ||||
| static bool | ||||
| Announce_User(CLIENT * Client, CLIENT * User) | ||||
| { | ||||
| 	return IRC_WriteStrClient(Client, "NICK %s %d %s %s %d +%s :%s", | ||||
| 		Client_ID(User), Client_Hops(User) + 1, Client_User(User), | ||||
| 		Client_Hostname(User), Client_MyToken(Client_Introducer(User)), | ||||
| 		Client_Modes(User), Client_Info(User)); | ||||
| } /* Announce_User */ | ||||
|  | ||||
|  | ||||
| #ifdef IRCPLUS | ||||
|  | ||||
| /** | ||||
|  * Synchronize invite and ban lists between servers | ||||
|  * @param Client New server | ||||
|  */ | ||||
| static bool | ||||
| Synchronize_Lists(CLIENT * Client) | ||||
| { | ||||
| 	CHANNEL *c; | ||||
| 	struct list_head *head; | ||||
| 	struct list_elem *elem; | ||||
|  | ||||
| 	assert(Client != NULL); | ||||
|  | ||||
| 	c = Channel_First(); | ||||
| 	while (c) { | ||||
| 		/* ban list */ | ||||
| 		head = Channel_GetListBans(c); | ||||
| 		elem = Lists_GetFirst(head); | ||||
| 		while (elem) { | ||||
| 			if (!IRC_WriteStrClient(Client, "MODE %s +b %s", | ||||
| 						Channel_Name(c), | ||||
| 						Lists_GetMask(elem))) { | ||||
| 				return DISCONNECTED; | ||||
| 			} | ||||
| 			elem = Lists_GetNext(elem); | ||||
| 		} | ||||
|  | ||||
| 		/* invite list */ | ||||
| 		head = Channel_GetListInvites(c); | ||||
| 		elem = Lists_GetFirst(head); | ||||
| 		while (elem) { | ||||
| 			if (!IRC_WriteStrClient(Client, "MODE %s +I %s", | ||||
| 						Channel_Name(c), | ||||
| 						Lists_GetMask(elem))) { | ||||
| 				return DISCONNECTED; | ||||
| 			} | ||||
| 			elem = Lists_GetNext(elem); | ||||
| 		} | ||||
|  | ||||
| 		c = Channel_Next(c); | ||||
| 	} | ||||
| 	return CONNECTED; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Send CHANINFO commands to a new server (inform it about existing channels). | ||||
|  * @param Client New server | ||||
|  * @param Chan Channel | ||||
|  */ | ||||
| static bool | ||||
| Send_CHANINFO(CLIENT * Client, CHANNEL * Chan) | ||||
| { | ||||
| 	char *modes, *topic; | ||||
| 	bool has_k, has_l; | ||||
| 	 | ||||
| #ifdef DEBUG | ||||
| 	Log(LOG_DEBUG, "Sending CHANINFO commands ..."); | ||||
| #endif | ||||
| 	 | ||||
| 	modes = Channel_Modes(Chan); | ||||
| 	topic = Channel_Topic(Chan); | ||||
| 	 | ||||
| 	if (!*modes && !*topic) | ||||
| 		return CONNECTED; | ||||
| 	 | ||||
| 	has_k = strchr(modes, 'k') != NULL; | ||||
| 	has_l = strchr(modes, 'l') != NULL; | ||||
| 	 | ||||
| 	/* send CHANINFO */ | ||||
| 	if (!has_k && !has_l) { | ||||
| 		if (!*topic) { | ||||
| 			/* "CHANINFO <chan> +<modes>" */ | ||||
| 			return IRC_WriteStrClient(Client, "CHANINFO %s +%s", | ||||
| 						  Channel_Name(Chan), modes); | ||||
| 		} | ||||
| 		/* "CHANINFO <chan> +<modes> :<topic>" */ | ||||
| 		return IRC_WriteStrClient(Client, "CHANINFO %s +%s :%s", | ||||
| 					  Channel_Name(Chan), modes, topic); | ||||
| 	} | ||||
| 	/* "CHANINFO <chan> +<modes> <key> <limit> :<topic>" */ | ||||
| 	return IRC_WriteStrClient(Client, "CHANINFO %s +%s %s %lu :%s", | ||||
| 				  Channel_Name(Chan), modes, | ||||
| 				  has_k ? Channel_Key(Chan) : "*", | ||||
| 				  has_l ? Channel_MaxUsers(Chan) : 0, topic); | ||||
| } /* Send_CHANINFO */ | ||||
|  | ||||
| #endif /* IRCPLUS */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Handle ENDOFMOTD (376) numeric and login remote server. | ||||
|  * The peer is either an IRC server (no IRC+ protocol), or we got the | ||||
|  * ENDOFMOTD numeric from an IRC+ server. We have to register the new server. | ||||
|  */ | ||||
| GLOBAL bool | ||||
| IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req) | ||||
| { | ||||
| 	char str[LINE_LEN]; | ||||
| 	int max_hops, i; | ||||
| 	CLIENT *c, *cl; | ||||
| 	CHANNEL *chan; | ||||
| 	CL2CHAN *cl2chan; | ||||
|  | ||||
| 	Client_SetType(Client, CLIENT_SERVER); | ||||
|  | ||||
| 	Log(LOG_NOTICE | LOG_snotice, | ||||
| 	    "Server \"%s\" registered (connection %d, 1 hop - direct link).", | ||||
| 	    Client_ID(Client), Client_Conn(Client)); | ||||
|  | ||||
| 	/* Get highest hop count */ | ||||
| 	max_hops = 0; | ||||
| 	c = Client_First(); | ||||
| 	while (c) { | ||||
| 		if (Client_Hops(c) > max_hops) | ||||
| 			max_hops = Client_Hops(c); | ||||
| 		c = Client_Next(c); | ||||
| 	} | ||||
|  | ||||
| 	/* Inform the new server about all other servers, and announce the | ||||
| 	 * new server to all the already registered ones. Important: we have | ||||
| 	 * to do this "in order" and can't introduce servers of which the | ||||
| 	 * "toplevel server" isn't known already. */ | ||||
| 	for (i = 0; i < (max_hops + 1); i++) { | ||||
| 		for (c = Client_First(); c != NULL; c = Client_Next(c)) { | ||||
| 			if (Client_Type(c) != CLIENT_SERVER) | ||||
| 				continue;	/* not a server */ | ||||
| 			if (Client_Hops(c) != i) | ||||
| 				continue;	/* not actual "nesting level" */ | ||||
| 			if (c == Client || c == Client_ThisServer()) | ||||
| 				continue;	/* that's us or the peer! */ | ||||
|  | ||||
| 			if (!Announce_Server(Client, c)) | ||||
| 				return DISCONNECTED; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* Announce all the users to the new server */ | ||||
| 	c = Client_First(); | ||||
| 	while (c) { | ||||
| 		if (Client_Type(c) == CLIENT_USER) { | ||||
| 			if (!Announce_User(Client, c)) | ||||
| 				return DISCONNECTED; | ||||
| 		} | ||||
| 		c = Client_Next(c); | ||||
| 	} | ||||
|  | ||||
| 	/* Announce all channels to the new server */ | ||||
| 	chan = Channel_First(); | ||||
| 	while (chan) { | ||||
| #ifdef IRCPLUS | ||||
| 		/* Send CHANINFO if the peer supports it */ | ||||
| 		if (strchr(Client_Flags(Client), 'C')) { | ||||
| 			if (!Send_CHANINFO(Client, chan)) | ||||
| 				return DISCONNECTED; | ||||
| 		} | ||||
| #endif | ||||
|  | ||||
| 		/* Get all the members of this channel */ | ||||
| 		cl2chan = Channel_FirstMember(chan); | ||||
| 		snprintf(str, sizeof(str), "NJOIN %s :", Channel_Name(chan)); | ||||
| 		while (cl2chan) { | ||||
| 			cl = Channel_GetClient(cl2chan); | ||||
| 			assert(cl != NULL); | ||||
|  | ||||
| 			/* Nick name, with modes (if applicable) */ | ||||
| 			if (str[strlen(str) - 1] != ':') | ||||
| 				strlcat(str, ",", sizeof(str)); | ||||
| 			if (strchr(Channel_UserModes(chan, cl), 'v')) | ||||
| 				strlcat(str, "+", sizeof(str)); | ||||
| 			if (strchr(Channel_UserModes(chan, cl), 'o')) | ||||
| 				strlcat(str, "@", sizeof(str)); | ||||
| 			strlcat(str, Client_ID(cl), sizeof(str)); | ||||
|  | ||||
| 			/* Send the data if the buffer is "full" */ | ||||
| 			if (strlen(str) > (LINE_LEN - CLIENT_NICK_LEN - 8)) { | ||||
| 				if (!IRC_WriteStrClient(Client, "%s", str)) | ||||
| 					return DISCONNECTED; | ||||
| 				snprintf(str, sizeof(str), "NJOIN %s :", | ||||
| 					 Channel_Name(chan)); | ||||
| 			} | ||||
|  | ||||
| 			cl2chan = Channel_NextMember(chan, cl2chan); | ||||
| 		} | ||||
|  | ||||
| 		/* Data left in the buffer? */ | ||||
| 		if (str[strlen(str) - 1] != ':') { | ||||
| 			/* Yes, send it ... */ | ||||
| 			if (!IRC_WriteStrClient(Client, "%s", str)) | ||||
| 				return DISCONNECTED; | ||||
| 		} | ||||
|  | ||||
| 		/* Get next channel ... */ | ||||
| 		chan = Channel_Next(chan); | ||||
| 	} | ||||
|  | ||||
| #ifdef IRCPLUS | ||||
| 	if (strchr(Client_Flags(Client), 'L')) { | ||||
| 		LogDebug("Synchronizing INVITE- and BAN-lists ..."); | ||||
| 		if (!Synchronize_Lists(Client)) | ||||
| 			return DISCONNECTED; | ||||
| 	} | ||||
| #endif | ||||
|  | ||||
| 	return CONNECTED; | ||||
| } /* IRC_Num_ENDOFMOTD */ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Handle ISUPPORT (005) numeric. | ||||
|  */ | ||||
| GLOBAL bool | ||||
| IRC_Num_ISUPPORT(CLIENT * Client, REQUEST * Req) | ||||
| { | ||||
| 	int i; | ||||
| 	char *key, *value; | ||||
|  | ||||
| 	for (i = 1; i < Req->argc - 1; i++) { | ||||
| 		key = Req->argv[i]; | ||||
| 		value = strchr(key, '='); | ||||
| 		if (value) | ||||
| 			*value++ = '\0'; | ||||
| 		else | ||||
| 			value = ""; | ||||
|  | ||||
| 		if (strcmp("NICKLEN", key) == 0) { | ||||
| 			if ((unsigned int)atol(value) == Conf_MaxNickLength - 1) | ||||
| 				continue; | ||||
|  | ||||
| 			/* Nick name length settings are different! */ | ||||
| 			Log(LOG_ERR, | ||||
| 			    "Peer uses incompatible nick name length (%d/%d)! Disconnecting ...", | ||||
| 			    Conf_MaxNickLength - 1, atoi(value)); | ||||
| 			Conn_Close(Client_Conn(Client), | ||||
| 				   "Incompatible nick name length", | ||||
| 				   NULL, false); | ||||
| 			return DISCONNECTED; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return CONNECTED; | ||||
| } /* IRC_Num_ISUPPORT */ | ||||
|  | ||||
|  | ||||
| /* -eof- */ | ||||
							
								
								
									
										24
									
								
								src/ngircd/numeric.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/ngircd/numeric.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| /* | ||||
|  * ngIRCd -- The Next Generation IRC Daemon | ||||
|  * Copyright (c)2001-2007 by Alexander Barton (alex@barton.de) | ||||
|  * | ||||
|  * This program is free software; you can redistribute it and/or modify | ||||
|  * it under the terms of the GNU General Public License as published by | ||||
|  * the Free Software Foundation; either version 2 of the License, or | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: numeric.h,v 1.1 2007/11/21 12:20:32 alex Exp $ | ||||
|  * | ||||
|  * Handlers for IRC numerics sent to the server (header) | ||||
|  */ | ||||
|  | ||||
| #ifndef __numeric_h__ | ||||
| #define __numeric_h__ | ||||
|  | ||||
| GLOBAL bool IRC_Num_ENDOFMOTD PARAMS((CLIENT *Client, UNUSED REQUEST *Req)); | ||||
| GLOBAL bool IRC_Num_ISUPPORT PARAMS((CLIENT *Client, REQUEST *Req)); | ||||
|  | ||||
| #endif | ||||
|  | ||||
| /* -eof- */ | ||||
| @@ -12,7 +12,7 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: parse.c,v 1.67 2006/04/23 10:37:27 fw Exp $"; | ||||
| static char UNUSED id[] = "$Id: parse.c,v 1.72 2008/02/17 13:26:42 alex Exp $"; | ||||
|  | ||||
| /** | ||||
|  * @file | ||||
| @@ -48,11 +48,17 @@ static char UNUSED id[] = "$Id: parse.c,v 1.67 2006/04/23 10:37:27 fw Exp $"; | ||||
| #include "irc-oper.h" | ||||
| #include "irc-server.h" | ||||
| #include "irc-write.h" | ||||
| #include "numeric.h" | ||||
|  | ||||
| #include "exp.h" | ||||
|  | ||||
| struct _NUMERIC { | ||||
| 	int numeric; | ||||
| 	bool (*function) PARAMS(( CLIENT *Client, REQUEST *Request )); | ||||
| }; | ||||
|  | ||||
| COMMAND My_Commands[] = | ||||
|  | ||||
| static COMMAND My_Commands[] = | ||||
| { | ||||
| 	{ "ADMIN", IRC_ADMIN, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, | ||||
| 	{ "AWAY", IRC_AWAY, CLIENT_USER, 0, 0, 0 }, | ||||
| @@ -61,6 +67,7 @@ COMMAND My_Commands[] = | ||||
| 	{ "DISCONNECT", IRC_DISCONNECT, CLIENT_USER, 0, 0, 0 }, | ||||
| 	{ "ERROR", IRC_ERROR, 0xFFFF, 0, 0, 0 }, | ||||
| 	{ "HELP", IRC_HELP, CLIENT_USER, 0, 0, 0 }, | ||||
| 	{ "INFO", IRC_INFO, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, | ||||
| 	{ "INVITE", IRC_INVITE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, | ||||
| 	{ "ISON", IRC_ISON, CLIENT_USER, 0, 0, 0 }, | ||||
| 	{ "JOIN", IRC_JOIN, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, | ||||
| @@ -87,12 +94,15 @@ COMMAND My_Commands[] = | ||||
| 	{ "SERVER", IRC_SERVER, 0xFFFF, 0, 0, 0 }, | ||||
| 	{ "SQUIT", IRC_SQUIT, CLIENT_SERVER, 0, 0, 0 }, | ||||
| 	{ "STATS", IRC_STATS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, | ||||
| 	{ "SUMMON", IRC_SUMMON, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, | ||||
| 	{ "TIME", IRC_TIME, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, | ||||
| 	{ "TOPIC", IRC_TOPIC, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, | ||||
| 	{ "TRACE", IRC_TRACE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, | ||||
| 	{ "USER", IRC_USER, 0xFFFF, 0, 0, 0 }, | ||||
| 	{ "USERHOST", IRC_USERHOST, CLIENT_USER, 0, 0, 0 }, | ||||
| 	{ "USERS", IRC_USERS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, | ||||
| 	{ "VERSION", IRC_VERSION, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, | ||||
| 	{ "WALLOPS", IRC_WALLOPS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, | ||||
| 	{ "WHO", IRC_WHO, CLIENT_USER, 0, 0, 0 }, | ||||
| 	{ "WHOIS", IRC_WHOIS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, | ||||
| 	{ "WHOWAS", IRC_WHOWAS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, | ||||
| @@ -102,7 +112,6 @@ COMMAND My_Commands[] = | ||||
| 	{ NULL, NULL, 0x0, 0, 0, 0 } /* Ende-Marke */ | ||||
| }; | ||||
|  | ||||
|  | ||||
| static void Init_Request PARAMS(( REQUEST *Req )); | ||||
|  | ||||
| static bool Validate_Prefix PARAMS(( CONN_ID Idx, REQUEST *Req, bool *Closed )); | ||||
| @@ -111,6 +120,7 @@ static bool Validate_Args PARAMS(( CONN_ID Idx, REQUEST *Req, bool *Closed )); | ||||
|  | ||||
| static bool Handle_Request PARAMS(( CONN_ID Idx, REQUEST *Req )); | ||||
|  | ||||
| #define ARRAY_SIZE(x)	(sizeof(x)/sizeof((x)[0])) | ||||
|  | ||||
| /** | ||||
|  * Return the pointer to the global "IRC command structure". | ||||
| @@ -338,17 +348,84 @@ Validate_Args( UNUSED CONN_ID Idx, UNUSED REQUEST *Req, bool *Closed ) | ||||
| } /* Validate_Args */ | ||||
|  | ||||
|  | ||||
| /* Command is a status code ("numeric") from another server */ | ||||
| static bool | ||||
| Handle_Numeric(CLIENT *client, REQUEST *Req) | ||||
| { | ||||
| 	static const struct _NUMERIC Numerics[] = { | ||||
| 		{ 005, IRC_Num_ISUPPORT }, | ||||
| 		{ 376, IRC_Num_ENDOFMOTD } | ||||
| 	}; | ||||
| 	int i, num; | ||||
| 	char str[LINE_LEN]; | ||||
| 	CLIENT *prefix, *target = NULL; | ||||
|  | ||||
| 	/* Determine target */ | ||||
| 	if (Req->argc > 0) | ||||
| 		target = Client_Search(Req->argv[0]); | ||||
|  | ||||
| 	if (!target) { | ||||
| 		/* Status code without target!? */ | ||||
| 		if (Req->argc > 0) | ||||
| 			Log(LOG_WARNING, | ||||
| 			    "Unknown target for status code %s: \"%s\"", | ||||
| 			    Req->command, Req->argv[0]); | ||||
| 		else | ||||
| 			Log(LOG_WARNING, | ||||
| 			    "Unknown target for status code %s!", | ||||
| 			    Req->command); | ||||
| 		return true; | ||||
| 	} | ||||
| 	if (target == Client_ThisServer()) { | ||||
| 		/* This server is the target of the numeric */ | ||||
| 		num = atoi(Req->command); | ||||
|  | ||||
| 		for (i = 0; i < (int) ARRAY_SIZE(Numerics); i++) { | ||||
| 			if (num == Numerics[i].numeric) | ||||
| 				return Numerics[i].function(client, Req); | ||||
| 		} | ||||
|  | ||||
| 		LogDebug("Ignored status code %s from \"%s\".", | ||||
| 			 Req->command, Client_ID(client)); | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	/* Determine source */ | ||||
| 	if (! Req->prefix[0]) { | ||||
| 		/* Oops, no prefix!? */ | ||||
| 		Log(LOG_WARNING, "Got status code %s from \"%s\" without prefix!?", | ||||
| 						Req->command, Client_ID(client)); | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	prefix = Client_Search(Req->prefix); | ||||
| 	if (! prefix) { /* Oops, unknown prefix!? */ | ||||
| 		Log(LOG_WARNING, "Got status code %s from unknown source: \"%s\"", Req->command, Req->prefix); | ||||
| 		return true; | ||||
| 	} | ||||
|  | ||||
| 	/* Forward status code */ | ||||
| 	strlcpy(str, Req->command, sizeof(str)); | ||||
| 	for (i = 0; i < Req->argc; i++) { | ||||
| 		if (i < Req->argc - 1) | ||||
| 			strlcat(str, " ", sizeof(str)); | ||||
| 		else | ||||
| 			strlcat(str, " :", sizeof(str)); | ||||
| 		strlcat(str, Req->argv[i], sizeof(str)); | ||||
| 	} | ||||
| 	return IRC_WriteStrClientPrefix(target, prefix, "%s", str); | ||||
| } | ||||
|  | ||||
|  | ||||
| static bool | ||||
| Handle_Request( CONN_ID Idx, REQUEST *Req ) | ||||
| { | ||||
| 	/* Client-Request verarbeiten. Bei einem schwerwiegenden Fehler | ||||
| 	 * wird die Verbindung geschlossen und false geliefert. */ | ||||
|  | ||||
| 	CLIENT *client, *target, *prefix; | ||||
| 	char str[LINE_LEN]; | ||||
| 	bool result; | ||||
| 	CLIENT *client; | ||||
| 	bool result = true; | ||||
| 	int client_type; | ||||
| 	COMMAND *cmd; | ||||
| 	int i; | ||||
|  | ||||
| 	assert( Idx >= 0 ); | ||||
| 	assert( Req != NULL ); | ||||
| @@ -357,90 +434,44 @@ Handle_Request( CONN_ID Idx, REQUEST *Req ) | ||||
| 	client = Conn_GetClient( Idx ); | ||||
| 	assert( client != NULL ); | ||||
|  | ||||
| 	/* Statuscode? */ | ||||
| 	if(( Client_Type( client ) == CLIENT_SERVER ) && ( strlen( Req->command ) == 3 ) && ( atoi( Req->command ) > 100 )) | ||||
| 	{ | ||||
| 		/* Command is a status code from an other server */ | ||||
|  | ||||
| 		/* Determine target */ | ||||
| 		if( Req->argc > 0 ) target = Client_Search( Req->argv[0] ); | ||||
| 		else target = NULL; | ||||
| 		if( ! target ) | ||||
| 		{ | ||||
| 			/* Status code without target!? */ | ||||
| 			if( Req->argc > 0 ) Log( LOG_WARNING, "Unknown target for status code %s: \"%s\"", Req->command, Req->argv[0] ); | ||||
| 			else Log( LOG_WARNING, "Unknown target for status code %s!", Req->command ); | ||||
| 			return true; | ||||
| 		} | ||||
| 		if( target == Client_ThisServer( )) | ||||
| 		{ | ||||
| 			/* This server is the target, ignore it */ | ||||
| 			Log( LOG_DEBUG, "Ignored status code %s from \"%s\".", Req->command, Client_ID( client )); | ||||
| 			return true; | ||||
| 		} | ||||
|  | ||||
| 		/* Determine source */ | ||||
| 		if( ! Req->prefix[0] ) | ||||
| 		{ | ||||
| 			/* Oops, no prefix!? */ | ||||
| 			Log( LOG_WARNING, "Got status code %s from \"%s\" without prefix!?", Req->command, Client_ID( client )); | ||||
| 			return true; | ||||
| 		} | ||||
| 		else prefix = Client_Search( Req->prefix ); | ||||
| 		if( ! prefix ) | ||||
| 		{ | ||||
| 			/* Oops, unknown prefix!? */ | ||||
| 			Log( LOG_WARNING, "Got status code %s from unknown source: \"%s\"", Req->command, Req->prefix ); | ||||
| 			return true; | ||||
| 		} | ||||
|  | ||||
| 		/* Forward status code */ | ||||
| 		strlcpy( str, Req->command, sizeof( str )); | ||||
| 		for( i = 0; i < Req->argc; i++ ) | ||||
| 		{ | ||||
| 			if( i < Req->argc - 1 ) strlcat( str, " ", sizeof( str )); | ||||
| 			else strlcat( str, " :", sizeof( str )); | ||||
| 			strlcat( str, Req->argv[i], sizeof( str )); | ||||
| 		} | ||||
| 		return IRC_WriteStrClientPrefix( target, prefix, "%s", str ); | ||||
| 	} | ||||
| 	/* Numeric? */ | ||||
| 	client_type = Client_Type(client); | ||||
| 	if ((client_type == CLIENT_SERVER || | ||||
| 	     client_type == CLIENT_UNKNOWNSERVER) | ||||
| 	    && strlen(Req->command) == 3 && atoi(Req->command) > 1) | ||||
| 		return Handle_Numeric(client, Req); | ||||
|  | ||||
| 	cmd = My_Commands; | ||||
| 	while( cmd->name ) | ||||
| 	{ | ||||
| 	while (cmd->name) { | ||||
| 		/* Befehl suchen */ | ||||
| 		if( strcasecmp( Req->command, cmd->name ) != 0 ) | ||||
| 		{ | ||||
| 			cmd++; continue; | ||||
| 		if (strcasecmp(Req->command, cmd->name) != 0) { | ||||
| 			cmd++; | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		if( Client_Type( client ) & cmd->type ) | ||||
| 		{ | ||||
| 			/* Command is allowed for this client: call it and count produced bytes */ | ||||
| 			Conn_ResetWCounter( ); | ||||
| 			result = (cmd->function)( client, Req ); | ||||
| 			cmd->bytes += Conn_WCounter( ); | ||||
| 		if (!(client_type & cmd->type)) | ||||
| 			return IRC_WriteStrClient(client, ERR_NOTREGISTERED_MSG, Client_ID(client)); | ||||
|  | ||||
| 			/* Adjust counters */ | ||||
| 			if( Client_Type( client ) != CLIENT_SERVER ) cmd->lcount++; | ||||
| 			else cmd->rcount++; | ||||
| 		/* Command is allowed for this client: call it and count produced bytes */ | ||||
| 		Conn_ResetWCounter(); | ||||
| 		result = (cmd->function)(client, Req); | ||||
| 		cmd->bytes += Conn_WCounter(); | ||||
|  | ||||
| 			return result; | ||||
| 		} | ||||
| 		/* Adjust counters */ | ||||
| 		if (client_type != CLIENT_SERVER) | ||||
| 			cmd->lcount++; | ||||
| 		else | ||||
| 		{ | ||||
| 			/* Befehl ist fuer diesen Client-Typ nicht erlaubt! */ | ||||
| 			return IRC_WriteStrClient( client, ERR_NOTREGISTERED_MSG, Client_ID( client )); | ||||
| 		} | ||||
| 			cmd->rcount++; | ||||
| 		return result; | ||||
| 	} | ||||
|  | ||||
| 	if( Client_Type( client ) != CLIENT_USER && | ||||
| 	    Client_Type( client ) != CLIENT_SERVER && | ||||
| 	    Client_Type( client ) != CLIENT_SERVICE ) | ||||
| 	if (client_type != CLIENT_USER && | ||||
| 	    client_type != CLIENT_SERVER && | ||||
| 	    client_type != CLIENT_SERVICE ) | ||||
| 		return true; | ||||
| 	 | ||||
|  | ||||
| 	/* Unknown command and registered connection: generate error: */ | ||||
| 	Log( LOG_DEBUG, "Connection %d: Unknown command \"%s\", %d %s,%s prefix.", | ||||
| 	LogDebug("Connection %d: Unknown command \"%s\", %d %s,%s prefix.", | ||||
| 			Client_Conn( client ), Req->command, Req->argc, | ||||
| 			Req->argc == 1 ? "parameter" : "parameters", | ||||
| 			Req->prefix ? "" : " no" ); | ||||
| @@ -449,10 +480,8 @@ Handle_Request( CONN_ID Idx, REQUEST *Req ) | ||||
| 		result = IRC_WriteStrClient(client, ERR_UNKNOWNCOMMAND_MSG, | ||||
| 				Client_ID(client), Req->command); | ||||
| 		Conn_SetPenalty(Idx, 1); | ||||
| 		return result; | ||||
| 	} | ||||
|  | ||||
| 	return true; | ||||
| 	return result; | ||||
| } /* Handle_Request */ | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: parse.h,v 1.11 2005/03/19 18:43:49 fw Exp $ | ||||
|  * $Id: parse.h,v 1.13 2008/01/13 16:12:49 fw Exp $ | ||||
|  * | ||||
|  * IRC command parser and validator (header) | ||||
|  */ | ||||
| @@ -33,8 +33,8 @@ typedef struct _COMMAND | ||||
| 	char *name;			/* command name */ | ||||
| 	bool (*function) PARAMS(( CLIENT *Client, REQUEST *Request )); | ||||
| 	CLIENT_TYPE type;		/* valid client types (bit mask) */ | ||||
| 	long lcount, rcount;	/* number of local and remote calls */ | ||||
| 	long bytes;		/* number of bytes created */ | ||||
| 	long lcount, rcount;		/* number of local and remote calls */ | ||||
| 	long bytes;			/* number of bytes created */ | ||||
| } COMMAND; | ||||
|  | ||||
|  | ||||
| @@ -42,7 +42,6 @@ GLOBAL bool Parse_Request PARAMS((CONN_ID Idx, char *Request )); | ||||
|  | ||||
| GLOBAL COMMAND *Parse_GetCommandStruct PARAMS(( void )); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -14,7 +14,7 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: resolve.c,v 1.24 2006/05/10 21:24:01 alex Exp $"; | ||||
| static char UNUSED id[] = "$Id: resolve.c,v 1.29 2008/02/26 22:04:17 fw Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| @@ -24,7 +24,6 @@ static char UNUSED id[] = "$Id: resolve.c,v 1.24 2006/05/10 21:24:01 alex Exp $" | ||||
| #include <unistd.h> | ||||
| #include <sys/socket.h> | ||||
| #include <netinet/in.h> | ||||
| #include <arpa/inet.h> | ||||
| #include <netdb.h> | ||||
|  | ||||
| #ifdef IDENTAUTH | ||||
| @@ -42,12 +41,13 @@ static char UNUSED id[] = "$Id: resolve.c,v 1.24 2006/05/10 21:24:01 alex Exp $" | ||||
| #include "io.h" | ||||
|  | ||||
|  | ||||
| static void Do_ResolveAddr PARAMS(( struct sockaddr_in *Addr, int Sock, int w_fd )); | ||||
| static void Do_ResolveAddr PARAMS(( const ng_ipaddr_t *Addr, int Sock, int w_fd )); | ||||
| static void Do_ResolveName PARAMS(( const char *Host, int w_fd )); | ||||
| static bool register_callback PARAMS((RES_STAT *s, void (*cbfunc)(int, short))); | ||||
|  | ||||
| #ifdef h_errno | ||||
| static char *Get_Error PARAMS(( int H_Error )); | ||||
| #ifdef WANT_IPV6 | ||||
| extern bool Conf_ConnectIPv4; | ||||
| extern bool Conf_ConnectIPv6; | ||||
| #endif | ||||
|  | ||||
| static pid_t | ||||
| @@ -82,7 +82,7 @@ Resolver_fork(int *pipefds) | ||||
|  * Resolve IP (asynchronous!). | ||||
|  */ | ||||
| GLOBAL bool | ||||
| Resolve_Addr(RES_STAT * s, struct sockaddr_in *Addr, int identsock, | ||||
| Resolve_Addr(RES_STAT * s, const ng_ipaddr_t *Addr, int identsock, | ||||
| 	     void (*cbfunc) (int, short)) | ||||
| { | ||||
| 	int pipefd[2]; | ||||
| @@ -92,9 +92,8 @@ Resolve_Addr(RES_STAT * s, struct sockaddr_in *Addr, int identsock, | ||||
|  | ||||
| 	pid = Resolver_fork(pipefd); | ||||
| 	if (pid > 0) { | ||||
| #ifdef DEBUG | ||||
| 		Log( LOG_DEBUG, "Resolver for %s created (PID %d).", inet_ntoa( Addr->sin_addr ), pid ); | ||||
| #endif | ||||
| 		Log(LOG_DEBUG, "Resolver for %s created (PID %d).", ng_ipaddr_tostr(Addr), pid); | ||||
|  | ||||
| 		s->pid = pid; | ||||
| 		s->resolver_fd = pipefd[0]; | ||||
| 		return register_callback(s, cbfunc); | ||||
| @@ -147,92 +146,302 @@ Resolve_Init(RES_STAT *s) | ||||
| } | ||||
|  | ||||
|  | ||||
| #ifndef WANT_IPV6 | ||||
| #ifdef h_errno | ||||
| static char * | ||||
| Get_Error( int H_Error ) | ||||
| { | ||||
| 	/* Get error message for H_Error */ | ||||
| 	switch( H_Error ) { | ||||
| 	case HOST_NOT_FOUND: | ||||
| 		return "host not found"; | ||||
| 	case NO_DATA: | ||||
| 		return "name valid but no IP address defined"; | ||||
| 	case NO_RECOVERY: | ||||
| 		return "name server error"; | ||||
| 	case TRY_AGAIN: | ||||
| 		return "name server temporary not available"; | ||||
| 	} | ||||
| 	return "unknown error"; | ||||
| } | ||||
| #endif /* h_errno */ | ||||
| #endif /* WANT_IPV6 */ | ||||
|  | ||||
|  | ||||
| /* Do "IDENT" (aka "AUTH") lookup and append result to resolved_addr array */ | ||||
| static void | ||||
| Do_ResolveAddr( struct sockaddr_in *Addr, int identsock, int w_fd ) | ||||
| Do_IdentQuery(int identsock, array *resolved_addr) | ||||
| { | ||||
| #ifdef IDENTAUTH | ||||
| 	char *res; | ||||
|  | ||||
| 	assert(identsock >= 0); | ||||
|  | ||||
| #ifdef DEBUG | ||||
| 	Log_Resolver(LOG_DEBUG, "Doing IDENT lookup on socket %d ...", identsock); | ||||
| #endif | ||||
| 	if (identsock < 0) | ||||
| 		return; | ||||
| 	res = ident_id( identsock, 10 ); | ||||
| #ifdef DEBUG | ||||
| 	Log_Resolver(LOG_DEBUG, "Ok, IDENT lookup on socket %d done: \"%s\"", | ||||
| 						identsock, res ? res : "(NULL)" ); | ||||
| #endif | ||||
| 	if (!res) /* no result */ | ||||
| 		return; | ||||
| 	if (!array_cats(resolved_addr, res)) | ||||
| 		Log_Resolver(LOG_WARNING, "Resolver: Cannot copy IDENT result: %s!", strerror(errno)); | ||||
|  | ||||
| 	free(res); | ||||
| #else | ||||
| 	(void) identsock; | ||||
| 	(void) resolved_addr; | ||||
| #endif | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * perform reverse DNS lookup and put result string into resbuf. | ||||
|  * If no hostname could be obtained, this function stores the string representation of | ||||
|  * the IP address in resbuf and returns false. | ||||
|  * @param IpAddr ip address to resolve | ||||
|  * @param resbuf result buffer to store DNS name/string representation of ip address | ||||
|  * @reslen size of result buffer (must be >= NGT_INET_ADDRSTRLEN) | ||||
|  * @return true if reverse lookup successful, false otherwise | ||||
|  */ | ||||
| static bool | ||||
| ReverseLookup(const ng_ipaddr_t *IpAddr, char *resbuf, size_t reslen) | ||||
| { | ||||
| 	char tmp_ip_str[NG_INET_ADDRSTRLEN]; | ||||
| 	const char *errmsg; | ||||
| #ifdef HAVE_GETNAMEINFO | ||||
| 	static const char funcname[]="getnameinfo"; | ||||
| 	int res; | ||||
|  | ||||
| 	*resbuf = 0; | ||||
|  | ||||
| 	res = getnameinfo((struct sockaddr *) IpAddr, ng_ipaddr_salen(IpAddr), | ||||
| 				resbuf, reslen, NULL, 0, NI_NAMEREQD); | ||||
| 	if (res == 0) | ||||
| 		return true; | ||||
|  | ||||
| 	if (res == EAI_SYSTEM) | ||||
| 		errmsg = strerror(errno); | ||||
| 	else | ||||
| 		errmsg = gai_strerror(res); | ||||
| #else | ||||
| 	const struct sockaddr_in *Addr = (const struct sockaddr_in *) IpAddr; | ||||
| 	struct hostent *h; | ||||
| 	static const char funcname[]="gethostbyaddr"; | ||||
|  | ||||
| 	h = gethostbyaddr((char *)&Addr->sin_addr, sizeof(Addr->sin_addr), AF_INET); | ||||
| 	if (h) { | ||||
| 		if (strlcpy(resbuf, h->h_name, reslen) < reslen) | ||||
| 			return true; | ||||
| 		errmsg = "hostname too long"; | ||||
| 	} else { | ||||
| # ifdef h_errno | ||||
| 		errmsg = Get_Error(h_errno); | ||||
| # else | ||||
| 		errmsg = "unknown error"; | ||||
| # endif /* h_errno */ | ||||
| 	} | ||||
| #endif	/* HAVE_GETNAMEINFO */ | ||||
|  | ||||
| 	assert(errmsg); | ||||
| 	assert(reslen >= NG_INET_ADDRSTRLEN); | ||||
| 	ng_ipaddr_tostr_r(IpAddr, tmp_ip_str); | ||||
|  | ||||
| 	Log_Resolver(LOG_WARNING, "%s: Can't resolve address \"%s\": %s", | ||||
| 				funcname, tmp_ip_str, errmsg); | ||||
| 	strlcpy(resbuf, tmp_ip_str, reslen); | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * perform DNS lookup of given host name and fill IpAddr with a list of | ||||
|  * ip addresses associated with that name. | ||||
|  * ip addresses found are stored in the "array *IpAddr" argument (type ng_ipaddr_t) | ||||
|  * @param hostname The domain name to look up. | ||||
|  * @param IpAddr pointer to empty and initialized array to store results | ||||
|  * @return true if lookup successful, false if domain name not found | ||||
|  */ | ||||
| static bool | ||||
| ForwardLookup(const char *hostname, array *IpAddr) | ||||
| { | ||||
| 	ng_ipaddr_t addr; | ||||
| #ifdef HAVE_GETADDRINFO | ||||
| 	int res; | ||||
| 	struct addrinfo *a, *ai_results; | ||||
| 	static struct addrinfo hints = { | ||||
| #ifndef WANT_IPV6 | ||||
| 		.ai_family = AF_INET, | ||||
| #endif | ||||
| #ifdef AI_ADDRCONFIG	/* glibc has this, but not e.g. netbsd 4.0 */ | ||||
| 		.ai_flags = AI_ADDRCONFIG, | ||||
| #endif | ||||
| 		.ai_socktype = SOCK_STREAM, | ||||
| 		.ai_protocol = IPPROTO_TCP | ||||
| 	}; | ||||
| #ifdef WANT_IPV6 | ||||
| 	assert(Conf_ConnectIPv6 || Conf_ConnectIPv4); | ||||
|  | ||||
| 	if (!Conf_ConnectIPv6) | ||||
| 		hints.ai_family = AF_INET; | ||||
| 	if (!Conf_ConnectIPv4) | ||||
| 		hints.ai_family = AF_INET6; | ||||
| #endif | ||||
| 	res = getaddrinfo(hostname, NULL, &hints, &ai_results); | ||||
| 	switch (res) { | ||||
| 	case 0:	break; | ||||
| 	case EAI_SYSTEM: | ||||
| 		Log_Resolver(LOG_WARNING, "Can't resolve \"%s\": %s", hostname, strerror(errno)); | ||||
| 		return false; | ||||
| 	default: | ||||
| 		Log_Resolver(LOG_WARNING, "Can't resolve \"%s\": %s", hostname, gai_strerror(res)); | ||||
| 		return false; | ||||
| 	} | ||||
|  | ||||
| 	for (a = ai_results; a != NULL; a = a->ai_next) { | ||||
| 		assert(a->ai_addrlen <= sizeof(addr)); | ||||
|  | ||||
| 		if (a->ai_addrlen > sizeof(addr)) | ||||
| 			continue; | ||||
|  | ||||
| 		memcpy(&addr, a->ai_addr, a->ai_addrlen); | ||||
|  | ||||
| 		if (!array_catb(IpAddr, (char *)&addr, sizeof(addr))) | ||||
| 			break; | ||||
| 	} | ||||
|  | ||||
| 	freeaddrinfo(ai_results); | ||||
| 	return a == NULL; | ||||
| #else | ||||
| 	struct hostent *h = gethostbyname(hostname); | ||||
|  | ||||
| 	if (!h) { | ||||
| #ifdef h_errno | ||||
| 		Log_Resolver(LOG_WARNING, "Can't resolve \"%s\": %s", hostname, Get_Error(h_errno)); | ||||
| #else | ||||
| 		Log_Resolver(LOG_WARNING, "Can't resolve \"%s\"", hostname); | ||||
| #endif | ||||
| 		return false; | ||||
| 	} | ||||
| 	memset(&addr, 0, sizeof(addr)); | ||||
|  | ||||
| 	addr.sin4.sin_family = AF_INET; | ||||
| 	memcpy(&addr.sin4.sin_addr, h->h_addr, sizeof(struct in_addr)); | ||||
|  | ||||
| 	return array_copyb(IpAddr, (char *)&addr, sizeof(addr)); | ||||
| #endif /* HAVE_GETADDRINFO */ | ||||
| } | ||||
|  | ||||
|  | ||||
| static bool | ||||
| Addr_in_list(const array *resolved_addr, const ng_ipaddr_t *Addr) | ||||
| { | ||||
| 	char tmp_ip_str[NG_INET_ADDRSTRLEN]; | ||||
| 	const ng_ipaddr_t *tmpAddrs = array_start(resolved_addr); | ||||
| 	size_t len = array_length(resolved_addr, sizeof(*tmpAddrs)); | ||||
|  | ||||
| 	assert(len > 0); | ||||
| 	assert(tmpAddrs); | ||||
|  | ||||
| 	while (len > 0) { | ||||
| 		if (ng_ipaddr_ipequal(Addr, tmpAddrs)) | ||||
| 			return true; | ||||
| 		tmpAddrs++; | ||||
| 		len--; | ||||
| 	} | ||||
| 	/* failed; print list of addresses */ | ||||
| 	ng_ipaddr_tostr_r(Addr, tmp_ip_str); | ||||
| 	len = array_length(resolved_addr, sizeof(*tmpAddrs)); | ||||
| 	tmpAddrs = array_start(resolved_addr); | ||||
|  | ||||
| 	while (len > 0) { | ||||
| 		Log_Resolver(LOG_WARNING, "Address mismatch: %s != %s", | ||||
| 			tmp_ip_str, ng_ipaddr_tostr(tmpAddrs)); | ||||
| 		tmpAddrs++; | ||||
| 		len--; | ||||
| 	} | ||||
|  | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| Log_Forgery_NoIP(const char *ip, const char *host) | ||||
| { | ||||
| 	Log_Resolver(LOG_WARNING, "Possible forgery: %s resolved to %s " | ||||
| 		"(which has no ip address)", ip, host); | ||||
| } | ||||
|  | ||||
| static void | ||||
| Log_Forgery_WrongIP(const char *ip, const char *host) | ||||
| { | ||||
| 	Log_Resolver(LOG_WARNING,"Possible forgery: %s resolved to %s " | ||||
| 		"(which points to different address)", ip, host); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| ArrayWrite(int fd, const array *a) | ||||
| { | ||||
| 	size_t len = array_bytes(a); | ||||
| 	const char *data = array_start(a); | ||||
|  | ||||
| 	assert(data); | ||||
|  | ||||
| 	if( (size_t)write(fd, data, len) != len ) | ||||
| 		Log_Resolver( LOG_CRIT, "Resolver: Can't write to parent: %s!", | ||||
| 							strerror(errno)); | ||||
| } | ||||
|  | ||||
|  | ||||
| static void | ||||
| Do_ResolveAddr(const ng_ipaddr_t *Addr, int identsock, int w_fd) | ||||
| { | ||||
| 	/* Resolver sub-process: resolve IP address and write result into | ||||
| 	 * pipe to parent. */ | ||||
|  | ||||
| 	char hostname[HOST_LEN]; | ||||
| 	char ipstr[HOST_LEN]; | ||||
| 	struct hostent *h; | ||||
| 	char hostname[CLIENT_HOST_LEN]; | ||||
| 	char tmp_ip_str[NG_INET_ADDRSTRLEN]; | ||||
| 	size_t len; | ||||
| 	struct in_addr *addr; | ||||
| 	char *ntoaptr; | ||||
| 	array resolved_addr; | ||||
| #ifdef IDENTAUTH | ||||
| 	char *res; | ||||
| #endif | ||||
|  | ||||
| 	array_init(&resolved_addr); | ||||
| 	/* Resolve IP address */ | ||||
| 	ng_ipaddr_tostr_r(Addr, tmp_ip_str); | ||||
| #ifdef DEBUG | ||||
| 	Log_Resolver( LOG_DEBUG, "Now resolving %s ...", inet_ntoa( Addr->sin_addr )); | ||||
| 	Log_Resolver(LOG_DEBUG, "Now resolving %s ...", tmp_ip_str); | ||||
| #endif | ||||
| 	h = gethostbyaddr( (char *)&Addr->sin_addr, sizeof( Addr->sin_addr ), AF_INET ); | ||||
| 	if (!h) { | ||||
| #ifdef h_errno | ||||
| 		Log_Resolver( LOG_WARNING, "Can't resolve address \"%s\": %s!", inet_ntoa( Addr->sin_addr ), Get_Error( h_errno )); | ||||
| #else | ||||
| 		Log_Resolver( LOG_WARNING, "Can't resolve address \"%s\"!", inet_ntoa( Addr->sin_addr )); | ||||
| #endif	 | ||||
| 		strlcpy( hostname, inet_ntoa( Addr->sin_addr ), sizeof( hostname )); | ||||
| 	} else { | ||||
|  		strlcpy( hostname, h->h_name, sizeof( hostname )); | ||||
| 	if (!ReverseLookup(Addr, hostname, sizeof(hostname))) | ||||
| 		goto dns_done; | ||||
|  | ||||
| 		h = gethostbyname( hostname ); | ||||
| 		if ( h ) { | ||||
| 			if (memcmp(h->h_addr, &Addr->sin_addr, sizeof (struct in_addr))) { | ||||
| 				addr = (struct in_addr*) h->h_addr; | ||||
| 				strlcpy(ipstr, inet_ntoa(*addr), sizeof ipstr);  | ||||
| 				ntoaptr = inet_ntoa( Addr->sin_addr ); | ||||
| 				Log(LOG_WARNING,"Possible forgery: %s resolved to %s (which is at ip %s!)", | ||||
| 										ntoaptr, hostname, ipstr); | ||||
| 				strlcpy( hostname, ntoaptr, sizeof hostname); | ||||
| 			} | ||||
| 		} else { | ||||
| 			ntoaptr = inet_ntoa( Addr->sin_addr ); | ||||
| 			Log(LOG_WARNING, "Possible forgery: %s resolved to %s (which has no ip address)", | ||||
| 											ntoaptr, hostname); | ||||
| 			strlcpy( hostname, ntoaptr, sizeof hostname); | ||||
| 	if (ForwardLookup(hostname, &resolved_addr)) { | ||||
| 		if (!Addr_in_list(&resolved_addr, Addr)) { | ||||
| 			Log_Forgery_WrongIP(tmp_ip_str, hostname); | ||||
| 			strlcpy(hostname, tmp_ip_str, sizeof(hostname)); | ||||
| 		} | ||||
| 	} else { | ||||
| 		Log_Forgery_NoIP(tmp_ip_str, hostname); | ||||
| 		strlcpy(hostname, tmp_ip_str, sizeof(hostname)); | ||||
| 	} | ||||
| 	Log_Resolver( LOG_DEBUG, "Ok, translated %s to \"%s\".", inet_ntoa( Addr->sin_addr ), hostname ); | ||||
|  | ||||
| 	len = strlen( hostname );  | ||||
| 	hostname[len] = '\n'; len++; | ||||
| 	if (!array_copyb(&resolved_addr, hostname, len )) { | ||||
| 		Log_Resolver( LOG_CRIT, "Resolver: Can't copy resolved name: %s!", strerror( errno )); | ||||
| 		close( w_fd ); | ||||
| #ifdef DEBUG | ||||
| 	Log_Resolver(LOG_DEBUG, "Ok, translated %s to \"%s\".", tmp_ip_str, hostname); | ||||
| #endif | ||||
|  dns_done: | ||||
| 	len = strlen(hostname); | ||||
| 	hostname[len] = '\n'; | ||||
| 	if (!array_copyb(&resolved_addr, hostname, ++len)) { | ||||
| 		Log_Resolver(LOG_CRIT, "Resolver: Can't copy resolved name: %s!", strerror(errno)); | ||||
| 		array_free(&resolved_addr); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| #ifdef IDENTAUTH | ||||
| 	assert(identsock >= 0); | ||||
| 	if (identsock >= 0) { | ||||
| 		/* Do "IDENT" (aka "AUTH") lookup and append result to resolved_addr array */ | ||||
| #ifdef DEBUG | ||||
| 		Log_Resolver( LOG_DEBUG, "Doing IDENT lookup on socket %d ...", identsock ); | ||||
| #endif | ||||
| 		res = ident_id( identsock, 10 ); | ||||
| #ifdef DEBUG | ||||
| 		Log_Resolver(LOG_DEBUG, "Ok, IDENT lookup on socket %d done: \"%s\"", | ||||
| 							identsock, res ? res : "(NULL)" ); | ||||
| #endif | ||||
| 		if (res && !array_cats(&resolved_addr, res)) { | ||||
| 			Log_Resolver(LOG_WARNING, "Resolver: Cannot copy IDENT result: %s!", strerror(errno)); | ||||
| 			/* omit ident and return hostname only */  | ||||
| 		} | ||||
| 	Do_IdentQuery(identsock, &resolved_addr); | ||||
|  | ||||
| 		if (res) free(res); | ||||
| 	} | ||||
| #else | ||||
| 	(void)identsock; | ||||
| #endif | ||||
| 	len = array_bytes(&resolved_addr); | ||||
| 	if( (size_t)write( w_fd, array_start(&resolved_addr), len) != len ) | ||||
| 		Log_Resolver( LOG_CRIT, "Resolver: Can't write result to parent: %s!", strerror( errno )); | ||||
| 	ArrayWrite(w_fd, &resolved_addr); | ||||
|  | ||||
| 	close(w_fd); | ||||
| 	array_free(&resolved_addr); | ||||
| } /* Do_ResolveAddr */ | ||||
|  | ||||
| @@ -242,65 +451,36 @@ Do_ResolveName( const char *Host, int w_fd ) | ||||
| { | ||||
| 	/* Resolver sub-process: resolve name and write result into pipe | ||||
| 	 * to parent. */ | ||||
|  | ||||
| 	char ip[16]; | ||||
| 	struct hostent *h; | ||||
| 	struct in_addr *addr; | ||||
| 	array IpAddrs; | ||||
| #ifdef DEBUG | ||||
| 	ng_ipaddr_t *addr; | ||||
| 	size_t len; | ||||
|  | ||||
| 	Log_Resolver( LOG_DEBUG, "Now resolving \"%s\" ...", Host ); | ||||
|  | ||||
| 	/* Resolve hostname */ | ||||
| 	h = gethostbyname( Host ); | ||||
| 	if( h ) { | ||||
| 		addr = (struct in_addr *)h->h_addr; | ||||
| 		strlcpy( ip, inet_ntoa( *addr ), sizeof( ip )); | ||||
| 	} else { | ||||
| #ifdef h_errno | ||||
| 		Log_Resolver( LOG_WARNING, "Can't resolve \"%s\": %s!", Host, Get_Error( h_errno )); | ||||
| #else | ||||
| 		Log_Resolver( LOG_WARNING, "Can't resolve \"%s\"!", Host ); | ||||
| #endif | ||||
| 	Log_Resolver(LOG_DEBUG, "Now resolving \"%s\" ...", Host); | ||||
|  | ||||
| 	array_init(&IpAddrs); | ||||
| 	/* Resolve hostname */ | ||||
| 	if (!ForwardLookup(Host, &IpAddrs)) { | ||||
| 		close(w_fd); | ||||
| 		return; | ||||
| 	} | ||||
| #ifdef DEBUG | ||||
| 	Log_Resolver( LOG_DEBUG, "Ok, translated \"%s\" to %s.", Host, ip ); | ||||
| 	len = array_length(&IpAddrs, sizeof(*addr)); | ||||
| 	assert(len > 0); | ||||
| 	addr = array_start(&IpAddrs); | ||||
| 	assert(addr); | ||||
| 	for (; len > 0; --len,addr++) { | ||||
| 		Log_Resolver(LOG_DEBUG, "translated \"%s\" to %s.", | ||||
| 					Host, ng_ipaddr_tostr(addr)); | ||||
| 	} | ||||
| #endif | ||||
| 	/* Write result into pipe to parent */ | ||||
| 	len = strlen( ip ); | ||||
| 	if ((size_t)write( w_fd, ip, len ) != len) { | ||||
| 		Log_Resolver( LOG_CRIT, "Resolver: Can't write to parent: %s!", strerror( errno )); | ||||
| 		close( w_fd ); | ||||
| 	} | ||||
| 	ArrayWrite(w_fd, &IpAddrs); | ||||
|  | ||||
| 	array_free(&IpAddrs); | ||||
| } /* Do_ResolveName */ | ||||
|  | ||||
|  | ||||
| #ifdef h_errno | ||||
|  | ||||
| static char * | ||||
| Get_Error( int H_Error ) | ||||
| { | ||||
| 	/* Get error message for H_Error */ | ||||
|  | ||||
| 	switch( H_Error ) | ||||
| 	{ | ||||
| 		case HOST_NOT_FOUND: | ||||
| 			return "host not found"; | ||||
| 		case NO_DATA: | ||||
| 			return "name valid but no IP address defined"; | ||||
| 		case NO_RECOVERY: | ||||
| 			return "name server error"; | ||||
| 		case TRY_AGAIN: | ||||
| 			return "name server temporary not available"; | ||||
| 		default: | ||||
| 			return "unknown error"; | ||||
| 	} | ||||
| } /* Get_Error */ | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
| static bool | ||||
| register_callback( RES_STAT *s, void (*cbfunc)(int, short)) | ||||
| { | ||||
| @@ -313,7 +493,8 @@ register_callback( RES_STAT *s, void (*cbfunc)(int, short)) | ||||
| 			return true; | ||||
|  | ||||
| 	Log( LOG_CRIT, "Resolver: Could not register callback function: %s!", strerror(errno)); | ||||
| 	Resolve_Shutdown(s); | ||||
| 	close(s->resolver_fd); | ||||
| 	Resolve_Init(s); | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| @@ -333,40 +514,31 @@ Resolve_Shutdown( RES_STAT *s) | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
|                  | ||||
|  | ||||
| /** | ||||
|  * Read result of resolver sub-process from pipe | ||||
|  */ | ||||
| GLOBAL size_t | ||||
| Resolve_Read( RES_STAT *s, void* readbuf, size_t buflen) | ||||
| { | ||||
| 	int err; | ||||
| 	ssize_t bytes_read; | ||||
|  | ||||
| 	assert(buflen > 0); | ||||
|  | ||||
| 	/* Read result from pipe */ | ||||
| 	errno = 0; | ||||
| 	bytes_read = read(s->resolver_fd, readbuf, buflen); | ||||
| 	if (bytes_read < 0) { | ||||
| 		if (errno != EAGAIN) { | ||||
| 			err = errno; | ||||
| 			Log( LOG_CRIT, "Resolver: Can't read result: %s!", strerror(err)); | ||||
| 			Resolve_Shutdown(s); | ||||
| 			errno = err; | ||||
| 		if (errno == EAGAIN) | ||||
| 			return 0; | ||||
| 		} | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	Resolve_Shutdown(s); | ||||
| 	if (bytes_read == 0) {	/* EOF: lookup failed */ | ||||
| 		Log( LOG_CRIT, "Resolver: Can't read result: %s!", strerror(errno)); | ||||
| 		bytes_read = 0; | ||||
| 	} | ||||
| #ifdef DEBUG | ||||
| 	else if (bytes_read == 0) | ||||
| 		Log( LOG_DEBUG, "Resolver: Can't read result: EOF"); | ||||
| #endif | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	Resolve_Shutdown(s); | ||||
| 	return (size_t)bytes_read; | ||||
| } | ||||
| /* -eof- */ | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: resolve.h,v 1.13 2006/05/10 21:24:02 alex Exp $ | ||||
|  * $Id: resolve.h,v 1.14 2008/02/26 22:04:17 fw Exp $ | ||||
|  * | ||||
|  * Asynchronous resolver (header) | ||||
|  */ | ||||
| @@ -18,6 +18,8 @@ | ||||
| #define __resolve_h__ | ||||
|  | ||||
| #include "array.h" | ||||
| #include "tool.h" | ||||
| #include "ng_ipaddr.h" | ||||
| #include <netinet/in.h> | ||||
|  | ||||
| /* This struct must not be accessed directly */ | ||||
| @@ -30,7 +32,7 @@ typedef struct _Res_Stat { | ||||
| #define Resolve_Getfd(x)		((x)->resolver_fd) | ||||
| #define Resolve_INPROGRESS(x)		((x)->resolver_fd >= 0) | ||||
|  | ||||
| GLOBAL bool Resolve_Addr PARAMS(( RES_STAT *s, struct sockaddr_in *Addr, int identsock, void (*cbfunc)(int, short))); | ||||
| GLOBAL bool Resolve_Addr PARAMS(( RES_STAT *s, const ng_ipaddr_t *Addr, int identsock, void (*cbfunc)(int, short))); | ||||
| GLOBAL bool Resolve_Name PARAMS(( RES_STAT *s, const char *Host, void (*cbfunc)(int, short) )); | ||||
| GLOBAL size_t Resolve_Read PARAMS(( RES_STAT *s, void *buf, size_t buflen)); | ||||
| GLOBAL void Resolve_Init PARAMS(( RES_STAT *s)); | ||||
|   | ||||
							
								
								
									
										1
									
								
								src/portab/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/portab/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| portabtest | ||||
							
								
								
									
										10
									
								
								src/testsuite/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/testsuite/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| T-ngircd | ||||
| channel-test | ||||
| connect-test | ||||
| misc-test | ||||
| mode-test | ||||
| who-test | ||||
| ngircd-test.log | ||||
| ngircd-test.motd | ||||
| logs | ||||
| tests | ||||
| @@ -9,7 +9,7 @@ | ||||
| # Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste | ||||
| # der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. | ||||
| # | ||||
| # $Id: Makefile.am,v 1.14 2004/09/08 09:40:51 alex Exp $ | ||||
| # $Id: Makefile.am,v 1.18 2008/02/17 13:26:42 alex Exp $ | ||||
| # | ||||
|  | ||||
| AUTOMAKE_OPTIONS = ../portab/ansi2knr | ||||
| @@ -20,8 +20,8 @@ EXTRA_DIST = \ | ||||
| 	README functions.inc getpid.sh \ | ||||
| 	start-server.sh stop-server.sh tests.sh stress-server.sh \ | ||||
| 	test-loop.sh wait-tests.sh \ | ||||
| 	connect-test.e channel-test.e mode-test.e \ | ||||
| 	stress-A.e stress-B.e check-idle.e \ | ||||
| 	channel-test.e connect-test.e check-idle.e misc-test.e mode-test.e \ | ||||
| 	who-test.e stress-A.e stress-B.e \ | ||||
| 	ngircd-test.conf | ||||
|  | ||||
| all: | ||||
| @@ -40,18 +40,31 @@ ngircd-TEST-Binary: | ||||
| 	[ -f getpid.sh ] || ln -s $(srcdir)/getpid.sh . | ||||
|  | ||||
| connect-test: tests.sh | ||||
| 	rm -f connect-test | ||||
| 	ln -s $(srcdir)/tests.sh connect-test | ||||
|  | ||||
| channel-test: tests.sh | ||||
| 	rm -f channel-test | ||||
| 	ln -s $(srcdir)/tests.sh channel-test | ||||
|  | ||||
| who-test: tests.sh | ||||
| 	rm -f who-test | ||||
| 	ln -s $(srcdir)/tests.sh who-test | ||||
|  | ||||
| misc-test: tests.sh | ||||
| 	rm -f misc-test | ||||
| 	ln -s $(srcdir)/tests.sh misc-test | ||||
|  | ||||
| mode-test: tests.sh | ||||
| 	rm -f mode-test | ||||
| 	ln -s $(srcdir)/tests.sh mode-test | ||||
|  | ||||
| TESTS = start-server.sh \ | ||||
| 	connect-test \ | ||||
| 	channel-test \ | ||||
| 	misc-test \ | ||||
| 	mode-test \ | ||||
| 	who-test \ | ||||
| 	stress-server.sh \ | ||||
| 	stop-server.sh | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| # $Id: channel-test.e,v 1.3 2003/12/27 13:01:12 alex Exp $ | ||||
| # $Id: channel-test.e,v 1.4 2008/02/05 13:31:51 fw Exp $ | ||||
|  | ||||
| spawn telnet localhost 6789 | ||||
| expect { | ||||
| @@ -69,6 +69,36 @@ expect { | ||||
| 	"@* PART #channel :nick" | ||||
| } | ||||
|  | ||||
| send "join #channel\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"@* JOIN :#channel" | ||||
| } | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"366" | ||||
| } | ||||
|  | ||||
| send "join #channel2\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"@* JOIN :#channel2" | ||||
| } | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"366" | ||||
| } | ||||
|  | ||||
| send "join 0\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"@* PART #channel2 :nick" | ||||
| } | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"@* PART #channel :nick" | ||||
| } | ||||
|  | ||||
| send "quit\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
|   | ||||
| @@ -1,16 +1,17 @@ | ||||
| #!/bin/sh | ||||
| # ngIRCd Test Suite | ||||
| # $Id: getpid.sh,v 1.4 2003/08/22 11:31:18 alex Exp $ | ||||
| # $Id: getpid.sh,v 1.5 2006/08/05 00:15:28 alex Exp $ | ||||
|  | ||||
| # did we get a name? | ||||
| [ $# -ne 1 ] && exit 1 | ||||
|  | ||||
| # detect flags for "ps" and "head" | ||||
| if [ `uname` = "FreeBSD" ]; then | ||||
| UNAME=`uname` | ||||
| if [ $UNAME = "FreeBSD" -o $UNAME = "SunOS" ]; then | ||||
|   PS_FLAGS="-a"; PS_PIDCOL="1"; HEAD_FLAGS="-n 1" | ||||
| elif [ `uname` = "A/UX" ]; then | ||||
| elif [ $UNAME = "A/UX" ]; then | ||||
|   PS_FLAGS="-ae"; PS_PIDCOL="1"; HEAD_FLAGS="-1" | ||||
| elif [ `uname` = "GNU" ]; then | ||||
| elif [ $UNAME = "GNU" ]; then | ||||
|   PS_FLAGS="-ax"; PS_PIDCOL="2"; HEAD_FLAGS="-n 1" | ||||
| else | ||||
|   PS_FLAGS="-f"; PS_PIDCOL="2"; HEAD_FLAGS="-n 1" | ||||
| @@ -19,13 +20,17 @@ else | ||||
| fi | ||||
|  | ||||
| # debug output | ||||
| #echo "$0: UNAME=$UNAME" | ||||
| #echo "$0: PS_FLAGS=$PS_FLAGS" | ||||
| #echo "$0: PS_PIDCOL=$PS_PIDCOL" | ||||
| #echo "$0: HEAD_FLAGS=$HEAD_FLAGS" | ||||
|  | ||||
| # search PID | ||||
| ps $PS_FLAGS > procs.tmp | ||||
| cat procs.tmp | grep -v "$0" | grep "$1" | awk "{print \$$PS_PIDCOL}" | sort -n > pids.tmp | ||||
| cat procs.tmp | \ | ||||
|   grep -v "$0" | grep "$1" | \ | ||||
|   awk "{print \$$PS_PIDCOL}" | \ | ||||
|   sort -n > pids.tmp | ||||
| pid=`head $HEAD_FLAGS pids.tmp` | ||||
| rm -rf procs.tmp pids.tmp | ||||
|  | ||||
|   | ||||
							
								
								
									
										44
									
								
								src/testsuite/misc-test.e
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/testsuite/misc-test.e
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| # $Id: misc-test.e,v 1.2 2008/02/17 13:51:00 alex Exp $ | ||||
|  | ||||
| spawn telnet localhost 6789 | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"Connected" | ||||
| } | ||||
|  | ||||
| send "nick nick\r" | ||||
| send "user user . . :User\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"376" | ||||
| } | ||||
|  | ||||
| send "summon\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"445" | ||||
| } | ||||
|  | ||||
| send "users\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"446" | ||||
| } | ||||
|  | ||||
| send "info\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"371" | ||||
| } | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"374" | ||||
| } | ||||
|  | ||||
| send "quit\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"ERROR" | ||||
| } | ||||
|  | ||||
| # -eof- | ||||
| @@ -1,4 +1,4 @@ | ||||
| # $Id: mode-test.e,v 1.6 2004/03/10 20:40:06 alex Exp $ | ||||
| # $Id: mode-test.e,v 1.7 2008/02/16 11:27:49 fw Exp $ | ||||
|  | ||||
| spawn telnet localhost 6789 | ||||
| expect { | ||||
| @@ -72,7 +72,7 @@ expect { | ||||
| send "mode #channel +v nick\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"@* MODE #channel +v nick" | ||||
| 	"@* MODE #channel +v nick\r" | ||||
| } | ||||
|  | ||||
| send "mode #channel +I nick1\r" | ||||
| @@ -96,7 +96,7 @@ expect { | ||||
| send "mode #channel -vo nick nick\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"@* MODE #channel -vo nick nick" | ||||
| 	"@* MODE #channel -vo nick nick\r" | ||||
| } | ||||
|  | ||||
| send "quit\r" | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| # $Id: ngircd-test.conf,v 1.4 2003/11/05 23:31:43 alex Exp $ | ||||
| # $Id: ngircd-test.conf,v 1.6 2008/02/17 00:00:13 fw Exp $ | ||||
|  | ||||
| [Global] | ||||
| 	Name = ngircd.test.server | ||||
| @@ -7,6 +7,7 @@ | ||||
| 	MotdFile = ngircd-test.motd | ||||
| 	AdminEMail = admin@irc.server | ||||
| 	MaxConnectionsIP = 0 | ||||
| 	OperCanUseMode = yes | ||||
|  | ||||
| [Operator] | ||||
| 	Name = TestOp | ||||
|   | ||||
							
								
								
									
										162
									
								
								src/testsuite/who-test.e
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								src/testsuite/who-test.e
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,162 @@ | ||||
| spawn telnet localhost 6789 | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"Connected" | ||||
| } | ||||
|  | ||||
| send "nick nick\r" | ||||
| send "user user . . :Real Name\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"376" | ||||
| } | ||||
|  | ||||
| send "who\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	":ngircd.test.server 352 nick \* ~user localhost ngircd.test.server nick H :0 Real Name" | ||||
| } | ||||
|  | ||||
| send "join #channel\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"@* JOIN :#channel" | ||||
| } | ||||
|  | ||||
| send "who 0\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	":ngircd.test.server 352 nick #channel ~user localhost ngircd.test.server nick H@ :0 Real Name" | ||||
| } | ||||
|  | ||||
| send "away :testing\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"306 nick" | ||||
| } | ||||
|  | ||||
| send "who *\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	":ngircd.test.server 352 nick #channel ~user localhost ngircd.test.server nick G@ :0 Real Name" | ||||
| } | ||||
|  | ||||
| send "mode #channel +v nick\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"@* MODE #channel +v nick\r" | ||||
| } | ||||
|  | ||||
| send "who localhost\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	":ngircd.test.server 352 nick #channel ~user localhost ngircd.test.server nick G@ :0 Real Name" | ||||
| } | ||||
|  | ||||
| send "mode #channel -o nick\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"@* MODE #channel -o nick\r" | ||||
| } | ||||
|  | ||||
| send "who ngircd.test.server\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	":ngircd.test.server 352 nick #channel ~user localhost ngircd.test.server nick G+ :0 Real Name" | ||||
| } | ||||
|  | ||||
| send "part #channel\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"@* PART #channel :nick" | ||||
| } | ||||
|  | ||||
| send "who Real?Name\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	":ngircd.test.server 352 nick \* ~user localhost ngircd.test.server nick G :0 Real Name" | ||||
| } | ||||
|  | ||||
| send "oper TestOp 123\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"MODE nick :+o" | ||||
| } | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"381 nick" | ||||
| } | ||||
|  | ||||
| send "who 0 o\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	":ngircd.test.server 352 nick \* ~user localhost ngircd.test.server nick G* :0 Real Name" | ||||
| } | ||||
|  | ||||
| send "away\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"305 nick" | ||||
| } | ||||
|  | ||||
| send "who *cal*ho??\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	":ngircd.test.server 352 nick \* ~user localhost ngircd.test.server nick H* :0 Real Name" | ||||
| } | ||||
|  | ||||
| send "join #opers\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"@* JOIN :#opers" | ||||
| } | ||||
|  | ||||
| send "who #opers\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	":ngircd.test.server 352 nick #opers ~user localhost ngircd.test.server nick H*@ :0 Real Name" | ||||
| } | ||||
|  | ||||
| send "mode #opers -o nick\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"@* MODE #opers -o nick\r" | ||||
| } | ||||
|  | ||||
| send "who *.server\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	":ngircd.test.server 352 nick #opers ~user localhost ngircd.test.server nick H* :0 Real Name" | ||||
| } | ||||
|  | ||||
| send "mode #opers +v nick\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"@* MODE #opers +v nick\r" | ||||
| } | ||||
|  | ||||
| send "who Real*me\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	":ngircd.test.server 352 nick #opers ~user localhost ngircd.test.server nick H*+ :0 Real Name" | ||||
| } | ||||
|  | ||||
| send "mode #opers +s\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"@* MODE #opers +s\r" | ||||
| } | ||||
|  | ||||
| send "who n?c?\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	":ngircd.test.server 352 nick \* ~user localhost ngircd.test.server nick H* :0 Real Name" | ||||
| } | ||||
|  | ||||
| send "quit\r" | ||||
| expect { | ||||
| 	timeout { exit 1 } | ||||
| 	"Connection closed" | ||||
| } | ||||
|  | ||||
| # -eof- | ||||
| @@ -14,7 +14,7 @@ | ||||
|  | ||||
| #include "portab.h" | ||||
|  | ||||
| static char UNUSED id[] = "$Id: tool.c,v 1.6 2006/04/09 12:53:07 alex Exp $"; | ||||
| static char UNUSED id[] = "$Id: tool.c,v 1.9 2008/02/26 22:04:18 fw Exp $"; | ||||
|  | ||||
| #include "imp.h" | ||||
| #include <assert.h> | ||||
| @@ -22,6 +22,8 @@ static char UNUSED id[] = "$Id: tool.c,v 1.6 2006/04/09 12:53:07 alex Exp $"; | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include <netinet/in.h> | ||||
|  | ||||
| #include "exp.h" | ||||
| #include "tool.h" | ||||
|  | ||||
| @@ -104,5 +106,4 @@ ngt_TrimLastChr( char *String, const char Chr) | ||||
| 	if( String[len] == Chr ) String[len] = '\0'; | ||||
| } /* ngt_TrimLastChr */ | ||||
|  | ||||
|  | ||||
| /* -eof- */ | ||||
|   | ||||
| @@ -8,7 +8,7 @@ | ||||
|  * (at your option) any later version. | ||||
|  * Please read the file COPYING, README and AUTHORS for more information. | ||||
|  * | ||||
|  * $Id: tool.h,v 1.3 2005/03/19 18:43:53 fw Exp $ | ||||
|  * $Id: tool.h,v 1.6 2008/02/26 22:04:18 fw Exp $ | ||||
|  * | ||||
|  * Tool functions (Header) | ||||
|  */ | ||||
| @@ -16,15 +16,19 @@ | ||||
|  | ||||
| #ifndef __tool_h__ | ||||
| #define __tool_h__ | ||||
| #include "portab.h" | ||||
|  | ||||
| #ifdef HAVE_ARPA_INET_H | ||||
| # include <arpa/inet.h> | ||||
| #else | ||||
| # define PF_INET AF_INET | ||||
| #endif | ||||
|  | ||||
| GLOBAL void ngt_TrimLastChr PARAMS((char *String, const char Chr )); | ||||
|  | ||||
| GLOBAL void ngt_TrimStr PARAMS((char *String )); | ||||
|  | ||||
| GLOBAL char *ngt_LowerStr PARAMS((char *String )); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user