mirror of
https://github.com/osmarks/ngircd.git
synced 2025-09-28 23:14:04 +00:00
Compare commits
159 Commits
rel-18
...
rel-19-rc1
Author | SHA1 | Date | |
---|---|---|---|
![]() |
8e3c56e5b2 | ||
![]() |
e1026d5dd1 | ||
![]() |
f7bdee5f13 | ||
![]() |
391aa8d1f7 | ||
![]() |
89d99e2ff9 | ||
![]() |
c16133c5ee | ||
![]() |
4888984429 | ||
![]() |
44bb22d23e | ||
![]() |
c7dd5ea0ba | ||
![]() |
871760583c | ||
![]() |
bc20f9ec10 | ||
![]() |
5a200e1543 | ||
![]() |
d2df7396a8 | ||
![]() |
3d27073d61 | ||
![]() |
b6f19ea8fe | ||
![]() |
8c46067b34 | ||
![]() |
594fdd02aa | ||
![]() |
6a308fcb42 | ||
![]() |
1537c79132 | ||
![]() |
e0c9931ad8 | ||
![]() |
eba95bb0d2 | ||
![]() |
51a6a33056 | ||
![]() |
6e28f4a7d1 | ||
![]() |
9882e578e9 | ||
![]() |
73781c1b38 | ||
![]() |
f2fa1045e2 | ||
![]() |
33a165721b | ||
![]() |
a3a4b5f696 | ||
![]() |
39412d6486 | ||
![]() |
c1656256df | ||
![]() |
1f4711a547 | ||
![]() |
4d0069c3a8 | ||
![]() |
12c60a670e | ||
![]() |
2f7d0c0839 | ||
![]() |
1afbf71236 | ||
![]() |
7ed08f01ef | ||
![]() |
81cc5f82b5 | ||
![]() |
78a3b4c7d6 | ||
![]() |
39d630c00d | ||
![]() |
4fe6b42c53 | ||
![]() |
d4d8102fc9 | ||
![]() |
77f68b4fd1 | ||
![]() |
2f8877ded4 | ||
![]() |
4bff3daf92 | ||
![]() |
c5beca8aab | ||
![]() |
f8405b1a4f | ||
![]() |
fdfc27265e | ||
![]() |
a4d1e6007f | ||
![]() |
9260759cec | ||
![]() |
c2ac1ad3ba | ||
![]() |
470d2e2362 | ||
![]() |
888664435a | ||
![]() |
98493077a2 | ||
![]() |
1fa2af5b3a | ||
![]() |
05cc9bf9b0 | ||
![]() |
cc06e1ff89 | ||
![]() |
9fbf592924 | ||
![]() |
adf92302bf | ||
![]() |
566a451299 | ||
![]() |
e0f8ce093a | ||
![]() |
5e3449a241 | ||
![]() |
762b0325df | ||
![]() |
6b62a5ec4f | ||
![]() |
b24d645ca1 | ||
![]() |
1bb2fbedcc | ||
![]() |
3193d5477c | ||
![]() |
edab86e0f8 | ||
![]() |
e4006a93e3 | ||
![]() |
9069380ddf | ||
![]() |
ab188c1486 | ||
![]() |
5eb9f2e717 | ||
![]() |
abfc5c6e27 | ||
![]() |
565523cbb4 | ||
![]() |
013298d4c6 | ||
![]() |
af13732ec7 | ||
![]() |
408a74b865 | ||
![]() |
f47904bf95 | ||
![]() |
70eb8219f5 | ||
![]() |
9e5b9ddad0 | ||
![]() |
56b7e67307 | ||
![]() |
b681aa5b9f | ||
![]() |
b32f3b76e9 | ||
![]() |
1a5ed654b4 | ||
![]() |
9cbb8f3bb8 | ||
![]() |
e19ce437ca | ||
![]() |
4e550bf9ef | ||
![]() |
1d29a59f7e | ||
![]() |
765c2f26ea | ||
![]() |
69fa6f268a | ||
![]() |
43509fd22c | ||
![]() |
a71abfef4b | ||
![]() |
8a8e8a3a23 | ||
![]() |
65befdafaa | ||
![]() |
15fec92ed7 | ||
![]() |
1e4a00f94f | ||
![]() |
338758799d | ||
![]() |
164e15b8c6 | ||
![]() |
32bfafafd9 | ||
![]() |
6ef20e0f9a | ||
![]() |
e86e193e01 | ||
![]() |
ae5ebfb9f0 | ||
![]() |
e9e6224aae | ||
![]() |
e23f025dd6 | ||
![]() |
3ca8703309 | ||
![]() |
fc82efc3e8 | ||
![]() |
dc9fcb0fb2 | ||
![]() |
2b95c69ea1 | ||
![]() |
af70c3dbc9 | ||
![]() |
1e054e0b82 | ||
![]() |
06a20b87c4 | ||
![]() |
fea2194fc0 | ||
![]() |
872dc5042d | ||
![]() |
e1315f30fd | ||
![]() |
0a85c58878 | ||
![]() |
ee21490887 | ||
![]() |
8fa92f0a24 | ||
![]() |
8e193df973 | ||
![]() |
9d348d00d9 | ||
![]() |
9e48f3f8f8 | ||
![]() |
e4a06844a3 | ||
![]() |
20ccc1bba7 | ||
![]() |
13d9e0c5a7 | ||
![]() |
a7911e35af | ||
![]() |
60812b6fdf | ||
![]() |
1ea6811616 | ||
![]() |
d2f54abbed | ||
![]() |
07dbb73c92 | ||
![]() |
30796698a9 | ||
![]() |
f173a974be | ||
![]() |
8aac366802 | ||
![]() |
69803d6ff1 | ||
![]() |
be6994aece | ||
![]() |
1361b3742d | ||
![]() |
d3036c74e9 | ||
![]() |
553e8b6aa3 | ||
![]() |
51d7674ee7 | ||
![]() |
1189200d4a | ||
![]() |
7795b07c53 | ||
![]() |
d9325e8030 | ||
![]() |
641045249c | ||
![]() |
69f81a359a | ||
![]() |
be03bc672c | ||
![]() |
160c52400f | ||
![]() |
0b8acf1205 | ||
![]() |
88f6fc5fd8 | ||
![]() |
da897a2a14 | ||
![]() |
989c9fa531 | ||
![]() |
2fd42667c2 | ||
![]() |
2dfa24d2fa | ||
![]() |
1ed602eb47 | ||
![]() |
ea725b99b7 | ||
![]() |
3dc3a03538 | ||
![]() |
95f0e4033c | ||
![]() |
409b2c86c8 | ||
![]() |
d692286d7a | ||
![]() |
456e55921d | ||
![]() |
9f3690c39c | ||
![]() |
6cbe13085d | ||
![]() |
b7780e3f2a |
9
AUTHORS
9
AUTHORS
@@ -2,7 +2,7 @@
|
||||
ngIRCd - Next Generation IRC Server
|
||||
http://ngircd.barton.de/
|
||||
|
||||
(c)2001-2011 Alexander Barton and Contributors.
|
||||
(c)2001-2012 Alexander Barton and Contributors.
|
||||
ngIRCd is free software and published under the
|
||||
terms of the GNU General Public License.
|
||||
|
||||
@@ -10,9 +10,10 @@
|
||||
|
||||
|
||||
Note: If you have critics, patches or something else, please feel free to
|
||||
post a mail to the ngIRCd mailing list: <ngircd-ml@arthur.ath.cx> (please see
|
||||
<http://ngircd.barton.de/#ml> for details). Don't mail the contributors
|
||||
directly, if possible!
|
||||
post a mail to the ngIRCd mailing list: <ngircd-ml@arthur.barton.de> (please
|
||||
see <http://ngircd.barton.de/#ml> for details).
|
||||
|
||||
Don't mail the people listed here directly, if possible!
|
||||
|
||||
|
||||
Main Authors
|
||||
|
39
COPYING
39
COPYING
@@ -1,12 +1,12 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
@@ -15,7 +15,7 @@ software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
the GNU Lesser General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
@@ -55,8 +55,8 @@ patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
@@ -110,7 +110,7 @@ above, provided that you also meet all of these conditions:
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
@@ -168,7 +168,7 @@ access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
@@ -225,7 +225,7 @@ impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
@@ -255,7 +255,7 @@ make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
@@ -277,9 +277,9 @@ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
@@ -303,10 +303,9 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
@@ -336,5 +335,5 @@ necessary. Here is a sample; alter the names:
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License.
|
||||
|
149
ChangeLog
149
ChangeLog
@@ -2,13 +2,152 @@
|
||||
ngIRCd - Next Generation IRC Server
|
||||
http://ngircd.barton.de/
|
||||
|
||||
(c)2001-2011 Alexander Barton and Contributors.
|
||||
(c)2001-2012 Alexander Barton and Contributors.
|
||||
ngIRCd is free software and published under the
|
||||
terms of the GNU General Public License.
|
||||
|
||||
-- ChangeLog --
|
||||
|
||||
|
||||
ngIRCd Release 19
|
||||
|
||||
ngIRCd 19~rc1 (2012-02-12)
|
||||
- Enhance command limits for server links: the limit now is dependent
|
||||
on the number of users connected in the network and higher while
|
||||
servers are joining the network to make the login of servers faster.
|
||||
- Log more information about server synchronization.
|
||||
- Update preliminary ngIRCd protocol module for Anope 1.9.6, which now
|
||||
is the only supported version.
|
||||
- New numeric RPL_WHOISHOST_MSG(378), which returns the DNS hostname
|
||||
(if available) and the IP address of a client in the WHOIS reply.
|
||||
Only the user itself and local IRC operators get this numeric.
|
||||
- Implement channel exception list (mode 'e'). This allows a channel
|
||||
operator to define exception masks that allow users to join the
|
||||
channel even when a "ban" would match and prevent them from joining:
|
||||
the exception list (e) overrides the ban list (b).
|
||||
- PRIVMSG and NOTICE: Handle nick!user@host masks case-insensitive.
|
||||
- Implement user mode 'C': If the target user of a PRIVMSG or NOTICE
|
||||
command has the user mode 'C' set, it is required that both sender
|
||||
and receiver are on the same channel. This prevents private flooding
|
||||
by completely unknown clients.
|
||||
- New RPL_WHOISREGNICK_MSG(307) numeric in WHOIS command replies: it
|
||||
indicates if a nick name is registered (if user mode 'R' set).
|
||||
- Limit channel invite, ban, and exception lists to 50 entries and fix
|
||||
duplicate check and error messages when adding already listed entries
|
||||
or deleting no (longer) existing ones.
|
||||
- Fix both ERR_SUMMONDISABLED(445) and ERR_USERSDISABLED(446) replies.
|
||||
- MODE command: correctly return ERR_UNKNOWNMODE(472) numeric for
|
||||
unknown channel modes, instead of ERR_UMODEUNKNOWNFLAG(501).
|
||||
- ISUPPORT(005) numeric: add "O", "R", and "z" modes to "CHANMODES",
|
||||
add "EXCEPTS=e" and "INVEX=I", add "MAXLIST=beI:50".
|
||||
- Limit the number of list items in the reply of LIST (100), WHO (25),
|
||||
WHOIS (10), and WHOWAS (25) commands.
|
||||
- LIST command: compare pattern case insensitive.
|
||||
- Limit the MODE command to handle a maximum number of 5 channel modes
|
||||
that require an argument (+Ibkl) per call and report this number
|
||||
in the ISUPPORT(005) numeric: "MODES=5".
|
||||
- Fix handling of channel mode sequence with/without arguments.
|
||||
For example, don't generate wrong error messages when handling
|
||||
"MODE #chan +IIIIItn *!aa@b *!bb@c *!cc@d *!dd@e *!ee@f".
|
||||
- When sending data on a connection, only try to get the type of
|
||||
the client if there still is one assigned. This could trigger an
|
||||
assertion and end the daemon in some error paths.
|
||||
- Don't try to close already closed/invalid sockets to forked child
|
||||
processes. This could potentially crash the daemon in some cases
|
||||
with IDENT lookups enabled.
|
||||
- WHOIS command: make sure that the reply ends with RPL_ENDOFWHOIS,
|
||||
don't answer queries for IRC servers, make sure mask matching is
|
||||
case-insensitive, and that RPL_ENDOFWHOIS numeric is sent with the
|
||||
unmodified mask (like it has been received from the client).
|
||||
- LINKS command: support <mask> parameter to limit the reply.
|
||||
- Add 1 second penalty for every further target on PRIVMSG/NOTICE
|
||||
commands: this reduces the possibility of flooding channels with
|
||||
commands like "PRIVMSG/NOTICE #a,#n,#c,... :message" a little bit.
|
||||
Problem noticed by Cahata, thanks!
|
||||
- Display correct error message when "Server{UID|GID}" variabe in the
|
||||
configuration file is invalid (not a number and no existing user).
|
||||
- Update Copyright notices for 2012 :-)
|
||||
- JOIN command: don't stop handling of channel lists when a single
|
||||
channel cannot be joined (because of bad name, wrong key or channel
|
||||
limit reached), but report an error and continue. And don't check
|
||||
the channel limit and don't report with "too many channels" when
|
||||
trying to join a channel that the client already is a member of.
|
||||
- ISON command: reply with the correct upper-/lowercase nick names.
|
||||
- New configuration option "PAMIsOptional": when set, clients not
|
||||
sending a password are still allowed to connect: they won't become
|
||||
"identified" and keep the "~" character prepended to their supplied
|
||||
user name. See "man 5 ngircd.conf" for details.
|
||||
- Fixed handling of WHO commands. This fixes two bugs: "WHO <nick>"
|
||||
returned nothing at all if the user was "+i" (reported by Cahata,
|
||||
thanks) and "WHO <nick|nickmask>" returned channel names instead
|
||||
of "*" when the user was member of a (visible) channel.
|
||||
- Fixed some spelling errors in documentation and code comments
|
||||
(Thanks to Christoph Biedl).
|
||||
- contrib/Debian/control: Update and complete "Build-Depends" and
|
||||
update our Debian package descriptions with "official" ones.
|
||||
- Fixed typo in two error messages.
|
||||
- LUSERS reply: only count channels that are visible to the requesting
|
||||
client, so the existence of secret channels is no longer revealed by
|
||||
using LUSERS. Reported by Cahata, thanks!
|
||||
- Unknown user and channel modes no longer stop the mode parser, but
|
||||
are simply ignored. Therefore modes after the unknown one are now
|
||||
handled. This is how ircd2.10/ircd2.11/ircd-seven behave, at least.
|
||||
Reported by Cahata, thanks!
|
||||
- README: Update list of implemented commands.
|
||||
- Log better error messages when rejecting clients.
|
||||
- Implement IRC commands "GLINE" and "KLINE" to ban users. G-Lines are
|
||||
synchronized between server on peering, K-Lines are local only.
|
||||
If you use "*!<user>@<host>" or "*!*@<host>" masks, these connections
|
||||
are blocked even before the user is fully logged in (before PASS,
|
||||
NICK, and USER commands have been processed) and before the child
|
||||
processes for authentication are forked, so resource usage is smaller.
|
||||
- Xcode: update project file for Xcode 4.2 and define HAVE_GAI_STRERROR
|
||||
for Mac OS X Xcode builds.
|
||||
- ./configure: Fix logic and quoting of poll() detection code: only use
|
||||
poll() when poll.h exists as well.
|
||||
- Suppress 'Can't create pre-defined channel: invalid name: ""' message.
|
||||
- whois-test: handle local hostname = "localhost.localdomain" using the
|
||||
pattern "localhost*" for valid local hostnames.
|
||||
- sample-ngircd.conf: show correct default for "PAM" variable: The
|
||||
default of "PAM" is "yes" when ngIRCd has been configured to use it,
|
||||
so show the correct default value in the sample configuration file.
|
||||
(Closes #119)
|
||||
- Update GPL 2 license text to current version.
|
||||
- Only close "unrelated" sockets in forked child processes: This fixes
|
||||
the problem that ngIRCd can't do any IDENT lookups because of the
|
||||
socket has already been closed in the child process.
|
||||
The bug has been introduced starting with ngIRCd 17 ... :-(
|
||||
(commit ID 6ebb31ab35e)
|
||||
- Added doc/Modes.txt: document modes supported by ngIRCd.
|
||||
- Implement user mode "R": indicates that the nick name of this user
|
||||
is "registered". This mode isn't handled by ngIRCd itself, but must
|
||||
be set and unset by IRC services like Anope.
|
||||
- Implement channel mode "R": only registered users (having the user
|
||||
mode "R" set) are allowed to join this channel.
|
||||
- Test suite: bind to loopback (127.0.0.1) interface only.
|
||||
- New 2nd message "Nickname too long" for error code 432.
|
||||
- Xcode: Mac OS X config.h: support 10.5 as well as 10.6/10.7 SDK.
|
||||
- Xcode: exclude more Xcode 4 specific directories in ".gitignore".
|
||||
- Disconnect directly linked servers sending QUIT. Without this,
|
||||
the server becomes removed from the network and the client list,
|
||||
but the connection isn't shut down at all ...
|
||||
- contrib/ngindent: detect "gindent" as GNU indent.
|
||||
- Handle unknown user and channel modes: these modes are saved and
|
||||
forwarded to other servers, but ignored otherwise.
|
||||
- Handle channel user modes 'a', 'h', and 'q' from remote servers.
|
||||
These channel user modes aren't used for anything at the moment,
|
||||
but ngIRCd knows that these three modes are "channel user modes"
|
||||
and not "channel modes", that is that these modes take an "nick name"
|
||||
argument. Like unknown user and channel modes, these modes are saved
|
||||
and forwarded to other servers, but ignored otherwise.
|
||||
- Correctly inform clients when other servers change their user modes.
|
||||
This is required for some services to work correctly.
|
||||
- Test suite: make getpid.sh work even when run as root.
|
||||
- Spoofed prefixes: close connection on non-server links only.
|
||||
On server-links, spoofed prefixes can happen because of the
|
||||
asynchronous nature of the IRC protocol. So don't break server-
|
||||
links, only log a message and ignore the command. (Closes #113)
|
||||
|
||||
ngIRCd Release 18 (2011-07-10)
|
||||
|
||||
- Update timestamp of ngircd(8) manual page.
|
||||
@@ -797,7 +936,7 @@ ngIRCd 0.6.0, 2002-12-24
|
||||
werden (beide Server versuchen sich dann gegenseitig zu connectieren).
|
||||
- Test-Suite und Dokumentation an A/UX angepasst.
|
||||
- unter HP-UX definiert das configure-Script nun _XOPEN_SOURCE_EXTENDED.
|
||||
- Server identifizieren sich nun mit asyncronen Passwoertern, d.h. das
|
||||
- Server identifizieren sich nun mit asynchronen Passwoertern, d.h. das
|
||||
Passwort, welches A an B schickt, kann ein anderes sein als das, welches
|
||||
B als Antwort an A sendet. In der Konfig.-Datei, Abschnitt "Server",
|
||||
wurde "Password" dazu durch "MyPassword" und "PeerPassword" ersetzt.
|
||||
@@ -927,7 +1066,7 @@ ngIRCd 0.5.0, 20.09.2002
|
||||
- Protokoll- und Server-ID bei PASS-Befehlen auf neues Format umgestellt;
|
||||
bei empfangenen PASS-Befehlen werden diese zudem nun auch ausgewertet.
|
||||
Die unterstuetzten Flags sind in doc/Protocol.txt beschrieben.
|
||||
- mit dem neuen Befehl CHANINFO syncronisieren Server, die das IRC+-
|
||||
- mit dem neuen Befehl CHANINFO synchronisieren Server, die das IRC+-
|
||||
Protokoll unterstuetzen, Channel-Modes und Topics.
|
||||
- neue Option "--disable-ircplus" fuer das configure-Script, um das
|
||||
IRC+-Protokoll abzuschalten (per Default ist es aktiviert).
|
||||
@@ -1032,7 +1171,7 @@ ngIRCd 0.3.0, 02.03.2002
|
||||
- PRIVMSG beachtet nun die Channel-Modes "n" und "m".
|
||||
- AWAY implementiert. PRIVMSG, MODE, USERHOST und WHOIS angepasst.
|
||||
- der ngIRCd unterstuetzt nun Channel-Topics (TOPIC-Befehl).
|
||||
- ausgehende Server-Verbindungen werden nun asyncron connectiert und
|
||||
- ausgehende Server-Verbindungen werden nun asynchron connectiert und
|
||||
blockieren nicht mehr den ganzen Server, wenn die Gegenseite nicht
|
||||
erreicht werden kann (bis zum Timeout konnten Minuten vergehen!).
|
||||
- Wert der Konfigurations-Variable "ConnectRetry" wird besser beachtet.
|
||||
@@ -1111,7 +1250,7 @@ ngIRCd 0.0.2, 06.01.2002
|
||||
- NICK kann nun die Gross- und Kleinschreibung eines Nicks aendern.
|
||||
- ein Server-Passwort ist nun konfigurierbar.
|
||||
- neue Befehle: ERROR, SERVER, NJOIN (nur als "Fake"), SQUIT.
|
||||
- Asyncroner Resolver Hostname->IP implementiert.
|
||||
- Asynchroner Resolver Hostname->IP implementiert.
|
||||
- Server-Links teilweise implementiert: bisher kann der ngIRCd jedoch
|
||||
nur "leafed server" sein, d.h. keine "Client-Server" haben. Einige
|
||||
Befehle sind auch noch nicht (optimal) angepasst: PRIVMSG funktioniert
|
||||
|
2
INSTALL
2
INSTALL
@@ -2,7 +2,7 @@
|
||||
ngIRCd - Next Generation IRC Server
|
||||
http://ngircd.barton.de/
|
||||
|
||||
(c)2001-2011 Alexander Barton and Contributors.
|
||||
(c)2001-2012 Alexander Barton and Contributors.
|
||||
ngIRCd is free software and published under the
|
||||
terms of the GNU General Public License.
|
||||
|
||||
|
78
NEWS
78
NEWS
@@ -2,12 +2,80 @@
|
||||
ngIRCd - Next Generation IRC Server
|
||||
http://ngircd.barton.de/
|
||||
|
||||
(c)2001-2011 Alexander Barton and Contributors.
|
||||
(c)2001-2012 Alexander Barton and Contributors.
|
||||
ngIRCd is free software and published under the
|
||||
terms of the GNU General Public License.
|
||||
|
||||
-- NEWS --
|
||||
|
||||
ngIRCd Release 19
|
||||
|
||||
ngIRCd 19~rc1 (2012-02-12)
|
||||
- Update preliminary ngIRCd protocol module for Anope 1.9.6, which now
|
||||
is the only supported version.
|
||||
- New numeric RPL_WHOISHOST_MSG(378), which returns the DNS hostname
|
||||
(if available) and the IP address of a client in the WHOIS reply.
|
||||
Only the user itself and local IRC operators get this numeric.
|
||||
- Implement channel exception list (mode 'e'). This allows a channel
|
||||
operator to define exception masks that allow users to join the
|
||||
channel even when a "ban" would match and prevent them from joining:
|
||||
the exception list (e) overrides the ban list (b).
|
||||
- Implement user mode 'C': If the target user of a PRIVMSG or NOTICE
|
||||
command has the user mode 'C' set, it is required that both sender
|
||||
and receiver are on the same channel. This prevents private flooding
|
||||
by completely unknown clients.
|
||||
- New RPL_WHOISREGNICK_MSG(307) numeric in WHOIS command replies: it
|
||||
indicates if a nick name is registered (if user mode 'R' set).
|
||||
- Limit channel invite, ban, and exception lists to 50 entries and fix
|
||||
duplicate check and error messages when adding already listed entries
|
||||
or deleting no (longer) existing ones.
|
||||
- Limit the number of list items in the reply of LIST (100), WHO (25),
|
||||
WHOIS (10), and WHOWAS (25) commands.
|
||||
- Limit the MODE command to handle a maximum number of 5 channel modes
|
||||
that require an argument (+Ibkl) per call and report this number
|
||||
in the ISUPPORT(005) numeric: "MODES=5".
|
||||
- LINKS command: support <mask> parameter to limit the reply.
|
||||
- Add 1 second penalty for every further target on PRIVMSG/NOTICE
|
||||
commands: this reduces the possibility of flooding channels with
|
||||
commands like "PRIVMSG/NOTICE #a,#n,#c,... :message" a little bit.
|
||||
Problem noticed by Cahata, thanks!
|
||||
- New configuration option "PAMIsOptional": when set, clients not
|
||||
sending a password are still allowed to connect: they won't become
|
||||
"identified" and keep the "~" character prepended to their supplied
|
||||
user name. See "man 5 ngircd.conf" for details.
|
||||
- Fixed handling of WHO commands. This fixes two bugs: "WHO <nick>"
|
||||
returned nothing at all if the user was "+i" (reported by Cahata,
|
||||
thanks) and "WHO <nick|nickmask>" returned channel names instead
|
||||
of "*" when the user was member of a (visible) channel.
|
||||
- LUSERS reply: only count channels that are visible to the requesting
|
||||
client, so the existence of secret channels is no longer revealed by
|
||||
using LUSERS. Reported by Cahata, thanks!
|
||||
- Unknown user and channel modes no longer stop the mode parser, but
|
||||
are simply ignored. Therefore modes after the unknown one are now
|
||||
handled. This is how ircd2.10/ircd2.11/ircd-seven behave, at least.
|
||||
Reported by Cahata, thanks!
|
||||
- Implement IRC commands "GLINE" and "KLINE" to ban users. G-Lines are
|
||||
synchronized between server on peering, K-Lines are local only.
|
||||
If you use "*!<user>@<host>" or "*!*@<host>" masks, these connections
|
||||
are blocked even before the user is fully logged in (before PASS,
|
||||
NICK, and USER commands have been processed) and before the child
|
||||
processes for authentication are forked, so resource usage is smaller.
|
||||
- Added doc/Modes.txt: document modes supported by ngIRCd.
|
||||
- Implement user mode "R": indicates that the nick name of this user
|
||||
is "registered". This mode isn't handled by ngIRCd itself, but must
|
||||
be set and unset by IRC services like Anope.
|
||||
- Implement channel mode "R": only registered users (having the user
|
||||
mode "R" set) are allowed to join this channel.
|
||||
- Test suite: bind to loopback (127.0.0.1) interface only.
|
||||
- Handle unknown user and channel modes: these modes are saved and
|
||||
forwarded to other servers, but ignored otherwise.
|
||||
- Handle channel user modes 'a', 'h', and 'q' from remote servers.
|
||||
These channel user modes aren't used for anything at the moment,
|
||||
but ngIRCd knows that these three modes are "channel user modes"
|
||||
and not "channel modes", that is that these modes take an "nick name"
|
||||
argument. Like unknown user and channel modes, these modes are saved
|
||||
and forwarded to other servers, but ignored otherwise.
|
||||
|
||||
ngIRCd Release 18 (2011-07-10)
|
||||
|
||||
- Add preliminary ngIRCd protocol module for Anope 1.9 to contrib/Anope/.
|
||||
@@ -351,7 +419,7 @@ ngIRCd 0.6.0, 2002-12-24
|
||||
ausgehende Verbindung zu diesem auufzubauen. Dadurch kann nun auf beiden
|
||||
Servern in der Konfiguration ein Port fuer den Connect konfiguriert
|
||||
werden (beide Server versuchen sich dann gegenseitig zu connectieren).
|
||||
- Server identifizieren sich nun mit asyncronen Passwoertern, d.h. das
|
||||
- Server identifizieren sich nun mit asynchronen Passwoertern, d.h. das
|
||||
Passwort, welches A an B schickt, kann ein anderes sein als das, welches
|
||||
B als Antwort an A sendet. In der Konfig.-Datei, Abschnitt "Server",
|
||||
wurde "Password" dazu durch "MyPassword" und "PeerPassword" ersetzt.
|
||||
@@ -377,7 +445,7 @@ ngIRCd 0.5.0, 20.09.2002
|
||||
Konfiguration "sample-ngircd.conf") und bleiben auch dann bestehen,
|
||||
wenn kein User mehr im Channel ist.
|
||||
- neue IRC-Befehle: KICK, INVITE, ADMIN, CHANINFO; LIST wurde erweitert.
|
||||
Mit dem neuen Befehl CHANINFO syncronisieren Server, die das IRC+-
|
||||
Mit dem neuen Befehl CHANINFO synchronisieren Server, die das IRC+-
|
||||
Protokoll unterstuetzen, Channel-Modes und Topics. Fuer den ADMIN-Befehl
|
||||
gibt es neue Konfigurationsoptionen (Sektion "Global"): "AdminInfo1",
|
||||
"AdminInfo2" und "AdminEMail".
|
||||
@@ -463,7 +531,3 @@ ngIRCd 0.0.2, 06.01.2002
|
||||
ngIRCd 0.0.1, 31.12.2001
|
||||
|
||||
- erste oeffentliche Version von ngIRCd als "public preview" :-)
|
||||
|
||||
|
||||
--
|
||||
$Id: NEWS,v 1.88 2008/02/26 22:05:42 fw Exp $
|
||||
|
38
README
38
README
@@ -2,7 +2,7 @@
|
||||
ngIRCd - Next Generation IRC Server
|
||||
http://ngircd.barton.de/
|
||||
|
||||
(c)2001-2011 Alexander Barton and Contributors.
|
||||
(c)2001-2012 Alexander Barton and Contributors.
|
||||
ngIRCd is free software and published under the
|
||||
terms of the GNU General Public License.
|
||||
|
||||
@@ -14,9 +14,10 @@ I. Introduction
|
||||
|
||||
ngIRCd is an Open Source server for the Internet Relay Chat (IRC), which
|
||||
is developed and published under the terms of the GNU General Public
|
||||
Licence (URL: http://www.gnu.org/licenses/gpl.html). ngIRCd means "next
|
||||
generation IRC daemon", it's written from scratch and not deduced from the
|
||||
"grandfather of IRC daemons", the daemon of the IRCNet.
|
||||
Licence, see the file COPYING for details. ngIRCd means "next generation
|
||||
IRC daemon" (which is a little bit exaggerated, "lightweight Internet Relay
|
||||
Chat server" would be better), it's written from scratch and not deduced
|
||||
from the "grandfather of IRC daemons", the daemon of the IRCNet.
|
||||
|
||||
Please see the INSTALL document for installation and upgrade information!
|
||||
|
||||
@@ -33,22 +34,24 @@ used in real IRC networks.
|
||||
|
||||
Implemented IRC-commands are:
|
||||
|
||||
ADMIN, AWAY, CHANINFO, CONNECT, DIE, DISCONNECT, ERROR, HELP, INFO, INVITE,
|
||||
ISON, JOIN, KICK, KILL, LINKS, LIST, LUSERS, MODE, MOTD, NAMES, NICK, NJOIN,
|
||||
NOTICE, OPER, PART, PASS, PING, PONG, PRIVMSG, QUIT, REHASH, RESTART, SERVER,
|
||||
SERVICE, SERVLIST, SQUERY, SQUIT, STATS, SUMMON, TIME, TOPIC, TRACE, USER,
|
||||
USERHOST, USERS, VERSION, WALLOPS, WEBIRC, WHO, WHOIS, WHOWAS.
|
||||
|
||||
ADMIN, AWAY, CHANINFO, CONNECT, DIE, DISCONNECT, ERROR, GLINE, HELP, INFO,
|
||||
INVITE, ISON, JOIN, KICK, KILL, KLINE, LINKS, LIST, LUSERS, MODE, MOTD,
|
||||
NAMES, NICK, NJOIN, NOTICE, OPER, PART, PASS, PING, PONG, PRIVMSG, QUIT,
|
||||
REHASH, RESTART, SERVER, SERVICE, SERVLIST, SQUERY, SQUIT, STATS, SUMMON,
|
||||
TIME, TOPIC, TRACE, USER, USERHOST, USERS, VERSION, WALLOPS, WEBIRC, WHO,
|
||||
WHOIS, WHOWAS.
|
||||
|
||||
III. Features (or: why use ngIRCd?)
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
- no problems with servers which have dynamic IP addresses
|
||||
- simple, easy understandable configuration file,
|
||||
- freely published open-source C source code,
|
||||
- ngIRCd will be developed on in the future.
|
||||
- well arranged (lean) configuration file
|
||||
- simple to build/install, configure and maintain
|
||||
- supports IPv6 and SSL
|
||||
- no problems with servers that have dynamic IP addresses
|
||||
- freely available, modern, portable and tidy C-source
|
||||
- wide field of supported platforms, including AIX, A/UX, FreeBSD, HP-UX,
|
||||
IRIX, Linux, Mac OS X, NetBSD, OpenBSD, Solaris, and Windows with Cygwin.
|
||||
- ngIRCd is being actively developed since 2001.
|
||||
|
||||
|
||||
IV. Documentation
|
||||
@@ -68,7 +71,7 @@ releases there.
|
||||
If you are interested in the latest development versions (which are not
|
||||
always stable), then please read the section about "GIT" on the homepage and
|
||||
the file "doc/GIT.txt" which describes the use of GIT, the version control
|
||||
system used by ngIRCd (homepage: http://git.or.cz/).
|
||||
system used by ngIRCd (homepage: http://git-scm.com/).
|
||||
|
||||
|
||||
VI. Bugs
|
||||
@@ -82,5 +85,6 @@ them at the following URL:
|
||||
There you can read about known bugs and limitations, too.
|
||||
|
||||
If you have critics, patches or something else, please feel free to post a
|
||||
mail to the ngIRCd mailing list: <ngircd-ml@arthur.ath.cx> (please see
|
||||
<http://ngircd.barton.de/support.php#ml> for details).
|
||||
mail to the ngIRCd mailing list: <ngircd-ml@arthur.barton.de> (please see
|
||||
<http://ngircd.barton.de/support.php#ml> for details) or join the ngIRCd
|
||||
IRC channel: <irc://irc.barton.de/ngircd>.
|
||||
|
24
configure.in
24
configure.in
@@ -160,10 +160,12 @@ AC_FUNC_STRFTIME
|
||||
|
||||
AC_CHECK_FUNCS([ \
|
||||
bind gethostbyaddr gethostbyname gethostname inet_ntoa \
|
||||
setsid setsockopt socket strcasecmp waitpid],,AC_MSG_ERROR([required function missing!]))
|
||||
setsid setsockopt socket strcasecmp waitpid],,
|
||||
AC_MSG_ERROR([required function missing!]))
|
||||
|
||||
AC_CHECK_FUNCS(getaddrinfo getnameinfo inet_aton sigaction sigprocmask snprintf \
|
||||
vsnprintf strdup strlcpy strlcat strtok_r)
|
||||
AC_CHECK_FUNCS([ \
|
||||
gai_strerror getaddrinfo getnameinfo inet_aton sigaction \
|
||||
sigprocmask snprintf vsnprintf strdup strlcpy strlcat strtok_r])
|
||||
|
||||
# -- Configuration options --
|
||||
|
||||
@@ -250,13 +252,21 @@ AC_ARG_WITH(poll,
|
||||
CPPFLAGS="-I$withval/include $CPPFLAGS"
|
||||
LDFLAGS="-L$withval/lib $LDFLAGS"
|
||||
fi
|
||||
AC_CHECK_FUNCS(poll, x_io_backend=poll\(\),
|
||||
AC_CHECK_FUNCS(poll, [
|
||||
AC_CHECK_HEADERS(poll.h,
|
||||
x_io_backend=poll\(\),
|
||||
AC_MSG_ERROR(
|
||||
[Can't enable poll IO support!])
|
||||
)
|
||||
], [
|
||||
AC_MSG_ERROR([Can't enable poll IO support!])
|
||||
)
|
||||
])
|
||||
fi
|
||||
],
|
||||
[
|
||||
AC_CHECK_FUNCS(poll, x_io_backend=poll\(\))
|
||||
AC_CHECK_FUNCS(poll, [
|
||||
AC_CHECK_HEADERS(poll.h, x_io_backend=poll\(\))
|
||||
])
|
||||
]
|
||||
)
|
||||
|
||||
@@ -330,7 +340,7 @@ else
|
||||
fi
|
||||
|
||||
if test "$x_io_backend" = "none"; then
|
||||
AC_MSG_ERROR([No useabe IO API activated/found!?])
|
||||
AC_MSG_ERROR([No useable IO API activated/found!?])
|
||||
fi
|
||||
|
||||
# use SSL?
|
||||
|
@@ -0,0 +1,128 @@
|
||||
From d8eddbeaadc7d161865b5342d59748b80266533c Mon Sep 17 00:00:00 2001
|
||||
From: DukePyrolator <DukePyrolator@anope.org>
|
||||
Date: Mon, 22 Aug 2011 14:53:37 +0200
|
||||
Subject: [PATCH 03/16] Update ngIRCd protocol module for current Anope 1.9
|
||||
GIT
|
||||
|
||||
---
|
||||
modules/protocol/ngircd.cpp | 37 ++++++++++++++++++-------------------
|
||||
1 files changed, 18 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
|
||||
index e546d05..790b8f4 100644
|
||||
--- a/modules/protocol/ngircd.cpp
|
||||
+++ b/modules/protocol/ngircd.cpp
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
#include "services.h"
|
||||
#include "modules.h"
|
||||
+#include "nickserv.h"
|
||||
+#include "oper.h"
|
||||
|
||||
IRCDVar myIrcd[] = {
|
||||
{"ngIRCd", /* ircd name */
|
||||
@@ -45,14 +47,7 @@ class ngIRCdProto : public IRCDProto
|
||||
{
|
||||
void SendAkill(User *u, const XLine *x)
|
||||
{
|
||||
- if (SGLine && u == NULL)
|
||||
- for (Anope::insensitive_map<User *>::iterator it = UserListByNick.begin(); it != UserListByNick.end();)
|
||||
- {
|
||||
- u = it->second;
|
||||
- ++it;
|
||||
- if (SGLine->Check(u) != NULL)
|
||||
- break;
|
||||
- }
|
||||
+ // TODO: ADD SOME CODE
|
||||
}
|
||||
|
||||
void SendAkillDel(const XLine*) { }
|
||||
@@ -62,13 +57,16 @@ class ngIRCdProto : public IRCDProto
|
||||
send_cmd(source ? source->nick : Config->ServerName, "WALLOPS :%s", buf.c_str());
|
||||
}
|
||||
|
||||
- void SendJoin(BotInfo *user, Channel *c, const ChannelStatus *status)
|
||||
+ void SendJoin(User *user, Channel *c, const ChannelStatus *status)
|
||||
{
|
||||
send_cmd(user->nick, "JOIN %s", c->name.c_str());
|
||||
if (status)
|
||||
+ {
|
||||
+ BotInfo *setter = findbot(user->nick);
|
||||
for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i)
|
||||
if (status->HasFlag(ModeManager::ChannelModes[i]->Name))
|
||||
- c->SetMode(user, ModeManager::ChannelModes[i], user->nick, false);
|
||||
+ c->SetMode(setter, ModeManager::ChannelModes[i], user->nick, false);
|
||||
+ }
|
||||
}
|
||||
|
||||
void SendSVSKillInternal(const BotInfo *source, const User *user, const Anope::string &buf)
|
||||
@@ -84,7 +82,7 @@ class ngIRCdProto : public IRCDProto
|
||||
|
||||
void SendConnect()
|
||||
{
|
||||
- send_cmd("", "PASS %s 0210-IRC+ Anope|%s:CLHSo P", uplink_server->password.c_str(), Anope::VersionShort().c_str());
|
||||
+ send_cmd("", "PASS %s 0210-IRC+ Anope|%s:CLHSo P", Config->Uplinks[CurrentUplink]->password.c_str(), Anope::VersionShort().c_str());
|
||||
/* Make myself known to myself in the serverlist */
|
||||
SendServer(Me);
|
||||
/* finish the enhanced server handshake and register the connection */
|
||||
@@ -92,9 +90,11 @@ class ngIRCdProto : public IRCDProto
|
||||
}
|
||||
|
||||
// Received: :dev.anope.de NICK DukeP 1 ~DukePyro p57ABF9C9.dip.t-dialin.net 1 +i :DukePyrolator
|
||||
- void SendClientIntroduction(const User *u, const Anope::string &modes)
|
||||
+ void SendClientIntroduction(const User *u)
|
||||
{
|
||||
- EnforceQlinedNick(u->nick, "");
|
||||
+ Anope::string modes = "+" + u->GetModes();
|
||||
+ XLine x(u->nick, "Reserved for services");
|
||||
+ ircdproto->SendSQLine(NULL, &x);
|
||||
send_cmd(Config->ServerName, "NICK %s 1 %s %s 1 %s :%s", u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str(), modes.c_str(), u->realname.c_str());
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ class ngIRCdProto : public IRCDProto
|
||||
|
||||
void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf)
|
||||
{
|
||||
- send_cmd(source ? source->nick : Config->s_ChanServ, "NOTICE @%s :%s", dest->name.c_str(), buf.c_str());
|
||||
+ send_cmd(source->nick, "NOTICE @%s :%s", dest->name.c_str(), buf.c_str());
|
||||
}
|
||||
|
||||
/* INVITE */
|
||||
@@ -196,8 +196,8 @@ class ngIRCdIRCdMessage : public IRCdMessage
|
||||
{
|
||||
// a new user is connecting to the network
|
||||
User *user = do_nick("", params[0], params[2], params[3], source, params[6], Anope::CurTime, "", "", "", params[5]);
|
||||
- if (user)
|
||||
- validate_user(user);
|
||||
+ if (user && nickserv)
|
||||
+ nickserv->Validate(user);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -433,7 +433,7 @@ class ProtongIRCd : public Module
|
||||
ModeManager::AddUserMode(new UserMode(UMODE_CLOAK, 'x'));
|
||||
|
||||
/* b/e/I */
|
||||
- ModeManager::AddChannelMode(new ChannelModeBan(CMODE_BAN, 'b'));
|
||||
+ ModeManager::AddChannelMode(new ChannelModeList(CMODE_BAN, 'b'));
|
||||
ModeManager::AddChannelMode(new ChannelModeList(CMODE_INVITEOVERRIDE, 'I'));
|
||||
|
||||
/* v/h/o/a/q */
|
||||
@@ -454,13 +454,12 @@ class ProtongIRCd : public Module
|
||||
}
|
||||
|
||||
public:
|
||||
- ProtongIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator),
|
||||
+ ProtongIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL),
|
||||
message_kick("KICK", event_kick), message_pass("PASS", event_pass),
|
||||
message_njoin("NJOIN", event_njoin), message_chaninfo("CHANINFO", event_chaninfo),
|
||||
message_005("005", event_005), message_442("442", event_442), message_376("376", event_376)
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
- this->SetType(PROTOCOL);
|
||||
|
||||
Capab.SetFlag(CAPAB_QS);
|
||||
|
||||
--
|
||||
1.7.8.3
|
||||
|
@@ -0,0 +1,93 @@
|
||||
From 88b2b14a76b8ee053b1f6ea64139350260590043 Mon Sep 17 00:00:00 2001
|
||||
From: DukePyrolator <DukePyrolator@anope.org>
|
||||
Date: Mon, 22 Aug 2011 14:55:07 +0200
|
||||
Subject: [PATCH 04/16] ngircd: Do PING-PONG on server burst to "sync servers"
|
||||
|
||||
Imagine we had three servers, A, B & C linked like so: A<->B<->C:
|
||||
|
||||
If Anope is linked to A and B splits from A and then reconnects B
|
||||
introduces itself, introduces C, sends EOS for C, introduces B's clients
|
||||
introduces C's clients, sends EOS for B. This causes all of C's clients
|
||||
to be introduced with their server "not syncing".
|
||||
|
||||
We now send a PING immediately when receiving a new server and then
|
||||
finish sync once we get a pong back from that server.
|
||||
---
|
||||
modules/protocol/ngircd.cpp | 28 ++++++++++++++++++++++++++--
|
||||
1 files changed, 26 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
|
||||
index 790b8f4..89aecfd 100644
|
||||
--- a/modules/protocol/ngircd.cpp
|
||||
+++ b/modules/protocol/ngircd.cpp
|
||||
@@ -108,11 +108,13 @@ class ngIRCdProto : public IRCDProto
|
||||
|
||||
void SendModeInternal(const BotInfo *bi, const Channel *dest, const Anope::string &buf)
|
||||
{
|
||||
+Log(LOG_DEBUG) << "SendModeInternal 1";
|
||||
send_cmd(bi ? bi->nick : Config->ServerName, "MODE %s %s", dest->name.c_str(), buf.c_str());
|
||||
}
|
||||
|
||||
void SendModeInternal(const BotInfo *bi, const User *u, const Anope::string &buf)
|
||||
{
|
||||
+Log(LOG_DEBUG) << "SendModeInternal 2";
|
||||
send_cmd(bi ? bi->nick : Config->ServerName, "MODE %s %s", u->nick.c_str(), buf.c_str());
|
||||
}
|
||||
|
||||
@@ -212,6 +214,8 @@ class ngIRCdIRCdMessage : public IRCdMessage
|
||||
do_server("", params[0], 0, params[2], params[1]);
|
||||
else
|
||||
do_server(source, params[0], params[1].is_pos_number_only() ? convertTo<unsigned>(params[1]) : 0, params[3], params[2]);
|
||||
+
|
||||
+ ircdproto->SendPing(Config->ServerName, params[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -253,6 +257,25 @@ class ngIRCdIRCdMessage : public IRCdMessage
|
||||
}
|
||||
};
|
||||
|
||||
+/** This is here because:
|
||||
+ *
|
||||
+ * If we had three servers, A, B & C linked like so: A<->B<->C
|
||||
+ * If Anope is linked to A and B splits from A and then reconnects
|
||||
+ * B introduces itself, introduces C, sends EOS for C, introduces Bs clients
|
||||
+ * introduces Cs clients, sends EOS for B. This causes all of Cs clients to be introduced
|
||||
+ * with their server "not syncing". We now send a PING immediately when receiving a new server
|
||||
+ * and then finish sync once we get a pong back from that server.
|
||||
+ */
|
||||
+bool event_pong(const Anope::string &source, const std::vector<Anope::string> ¶ms)
|
||||
+{
|
||||
+ Server *s = Server::Find(source);
|
||||
+ if (s && !s->IsSynced())
|
||||
+ s->Sync(false);
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+
|
||||
/*
|
||||
* CHANINFO <chan> +<modes>
|
||||
* CHANINFO <chan> +<modes> :<topic>
|
||||
@@ -416,7 +439,7 @@ bool event_376(const Anope::string &source, const std::vector<Anope::string> &pa
|
||||
class ProtongIRCd : public Module
|
||||
{
|
||||
Message message_kick, message_pass, message_njoin, message_chaninfo, message_005,
|
||||
- message_442, message_376;
|
||||
+ message_442, message_376, message_pong;
|
||||
|
||||
ngIRCdProto ircd_proto;
|
||||
ngIRCdIRCdMessage ircd_message;
|
||||
@@ -457,7 +480,8 @@ class ProtongIRCd : public Module
|
||||
ProtongIRCd(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, PROTOCOL),
|
||||
message_kick("KICK", event_kick), message_pass("PASS", event_pass),
|
||||
message_njoin("NJOIN", event_njoin), message_chaninfo("CHANINFO", event_chaninfo),
|
||||
- message_005("005", event_005), message_442("442", event_442), message_376("376", event_376)
|
||||
+ message_005("005", event_005), message_442("442", event_442), message_376("376", event_376),
|
||||
+ message_pong("PONG", event_pong)
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
--
|
||||
1.7.8.3
|
||||
|
@@ -0,0 +1,29 @@
|
||||
From 0d83f8f9ca0de651d664eca6f467f36df0417f7d Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Barton <alex@barton.de>
|
||||
Date: Mon, 22 Aug 2011 14:59:49 +0200
|
||||
Subject: [PATCH 05/16] ngircd: always prefix modes in CHANINFO with "+"
|
||||
|
||||
---
|
||||
modules/protocol/ngircd.cpp | 6 ++----
|
||||
1 files changed, 2 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
|
||||
index 89aecfd..3e5beb3 100644
|
||||
--- a/modules/protocol/ngircd.cpp
|
||||
+++ b/modules/protocol/ngircd.cpp
|
||||
@@ -139,10 +139,8 @@ Log(LOG_DEBUG) << "SendModeInternal 2";
|
||||
|
||||
void SendChannel(Channel *c)
|
||||
{
|
||||
- Anope::string mlock_modes = get_mlock_modes(c->ci, true);
|
||||
- if (mlock_modes.empty())
|
||||
- mlock_modes = "+";
|
||||
- send_cmd(Config->ServerName, "CHANINFO %s %s", c->name.c_str(), mlock_modes.c_str());
|
||||
+ Anope::string modes = c->GetModes(true, true);
|
||||
+ send_cmd(Config->ServerName, "CHANINFO %s +%s", c->name.c_str(), modes.c_str());
|
||||
}
|
||||
void SendTopic(BotInfo *bi, Channel *c)
|
||||
{
|
||||
--
|
||||
1.7.8.3
|
||||
|
@@ -0,0 +1,47 @@
|
||||
From 1914a36b83b1fc6b4678ef261a1a06eefab9a0ca Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Barton <alex@barton.de>
|
||||
Date: Fri, 26 Aug 2011 17:51:37 +0200
|
||||
Subject: [PATCH 06/16] ngircd: support user mode "R" and channel mode "R"
|
||||
|
||||
---
|
||||
modules/protocol/ngircd.cpp | 7 ++++---
|
||||
1 files changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
|
||||
index 3e5beb3..7f4186e 100644
|
||||
--- a/modules/protocol/ngircd.cpp
|
||||
+++ b/modules/protocol/ngircd.cpp
|
||||
@@ -449,26 +449,27 @@ class ProtongIRCd : public Module
|
||||
ModeManager::AddUserMode(new UserMode(UMODE_INVIS, 'i'));
|
||||
ModeManager::AddUserMode(new UserMode(UMODE_OPER, 'o'));
|
||||
ModeManager::AddUserMode(new UserMode(UMODE_RESTRICTED, 'r'));
|
||||
+ ModeManager::AddUserMode(new UserMode(UMODE_REGISTERED, 'R'));
|
||||
ModeManager::AddUserMode(new UserMode(UMODE_SNOMASK, 's'));
|
||||
ModeManager::AddUserMode(new UserMode(UMODE_WALLOPS, 'w'));
|
||||
ModeManager::AddUserMode(new UserMode(UMODE_CLOAK, 'x'));
|
||||
|
||||
- /* b/e/I */
|
||||
+ /* Add modes for ban and invite lists */
|
||||
ModeManager::AddChannelMode(new ChannelModeList(CMODE_BAN, 'b'));
|
||||
ModeManager::AddChannelMode(new ChannelModeList(CMODE_INVITEOVERRIDE, 'I'));
|
||||
|
||||
- /* v/h/o/a/q */
|
||||
+ /* Add channel user modes */
|
||||
ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_VOICE, 'v', '+'));
|
||||
ModeManager::AddChannelMode(new ChannelModeStatus(CMODE_OP, 'o', '@'));
|
||||
|
||||
/* Add channel modes */
|
||||
- // channel modes: biIklmnoPstvz
|
||||
ModeManager::AddChannelMode(new ChannelMode(CMODE_INVITE, 'i'));
|
||||
ModeManager::AddChannelMode(new ChannelModeKey('k'));
|
||||
ModeManager::AddChannelMode(new ChannelModeParam(CMODE_LIMIT, 'l'));
|
||||
ModeManager::AddChannelMode(new ChannelMode(CMODE_MODERATED, 'm'));
|
||||
ModeManager::AddChannelMode(new ChannelMode(CMODE_NOEXTERNAL, 'n'));
|
||||
ModeManager::AddChannelMode(new ChannelMode(CMODE_PERM, 'P'));
|
||||
+ ModeManager::AddChannelMode(new ChannelMode(CMODE_REGISTEREDONLY, 'R'));
|
||||
ModeManager::AddChannelMode(new ChannelMode(CMODE_SECRET, 's'));
|
||||
ModeManager::AddChannelMode(new ChannelMode(CMODE_TOPIC, 't'));
|
||||
ModeManager::AddChannelMode(new ChannelMode(CMODE_SSL, 'z'));
|
||||
--
|
||||
1.7.8.3
|
||||
|
@@ -0,0 +1,96 @@
|
||||
From 4c9300ede35310ee5642f34e5ac227bd96fc7384 Mon Sep 17 00:00:00 2001
|
||||
From: DukePyrolator <DukePyrolator@anope.org>
|
||||
Date: Sun, 4 Sep 2011 15:08:55 +0200
|
||||
Subject: [PATCH 07/16] ngircd: Fix handling of JOIN commands
|
||||
|
||||
---
|
||||
modules/protocol/ngircd.cpp | 60 +++++++++++++++++++++++++++++++++++++++---
|
||||
1 files changed, 55 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
|
||||
index 7f4186e..3024fdd 100644
|
||||
--- a/modules/protocol/ngircd.cpp
|
||||
+++ b/modules/protocol/ngircd.cpp
|
||||
@@ -240,16 +240,58 @@ class ngIRCdIRCdMessage : public IRCdMessage
|
||||
{
|
||||
if (!params.empty())
|
||||
{
|
||||
+ Anope::string channel, mode;
|
||||
size_t pos = params[0].find('\7');
|
||||
if (pos != Anope::string::npos)
|
||||
{
|
||||
- Anope::string channel = params[0].substr(0, pos);
|
||||
- Anope::string mode = '+' + params[0].substr(pos, params[0].length()) + " " + source;
|
||||
- do_join(source, channel, "");
|
||||
- do_cmode(source, channel, mode, "");
|
||||
+ channel = params[0].substr(0, pos);
|
||||
+ mode = '+' + params[0].substr(pos+1, params[0].length()) + " " + source;
|
||||
}
|
||||
else
|
||||
- do_join(source, params[0], "");
|
||||
+ channel = params[0];
|
||||
+
|
||||
+ Channel *c = findchan(channel);
|
||||
+
|
||||
+ if (!c)
|
||||
+ {
|
||||
+ c = new Channel(channel, Anope::CurTime);
|
||||
+ c->SetFlag(CH_SYNCING);
|
||||
+ }
|
||||
+
|
||||
+ User *u = finduser(source);
|
||||
+
|
||||
+ if (!u)
|
||||
+ {
|
||||
+ Log(LOG_DEBUG) << "JOIN for nonexistant user " << source << " on " << channel;
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ EventReturn MOD_RESULT;
|
||||
+ FOREACH_RESULT(I_OnPreJoinChannel, OnPreJoinChannel(u, c));
|
||||
+
|
||||
+ /* Add the user to the channel */
|
||||
+ c->JoinUser(u);
|
||||
+
|
||||
+ /* set the usermodes to the channel */
|
||||
+ do_cmode(source, channel, mode, "");
|
||||
+
|
||||
+ /* Now set whatever modes this user is allowed to have on the channel */
|
||||
+ chan_set_correct_modes(u, c, 1);
|
||||
+
|
||||
+ /* Check to see if modules want the user to join, if they do
|
||||
+ * check to see if they are allowed to join (CheckKick will kick/ban them)
|
||||
+ * Don't trigger OnJoinChannel event then as the user will be destroyed
|
||||
+ */
|
||||
+ if (MOD_RESULT != EVENT_STOP && c->ci && c->ci->CheckKick(u))
|
||||
+ return false;
|
||||
+
|
||||
+ FOREACH_MOD(I_OnJoinChannel, OnJoinChannel(u, c));
|
||||
+
|
||||
+ if (c->HasFlag(CH_SYNCING))
|
||||
+ {
|
||||
+ c->UnsetFlag(CH_SYNCING);
|
||||
+ c->Sync();
|
||||
+ }
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -491,7 +533,15 @@ class ProtongIRCd : public Module
|
||||
pmodule_ircd_message(&this->ircd_message);
|
||||
|
||||
this->AddModes();
|
||||
+
|
||||
+ ModuleManager::Attach(I_OnUserNickChange, this);
|
||||
}
|
||||
+
|
||||
+ void OnUserNickChange(User *u, const Anope::string &)
|
||||
+ {
|
||||
+ u->RemoveModeInternal(ModeManager::FindUserModeByName(UMODE_REGISTERED));
|
||||
+ }
|
||||
+
|
||||
};
|
||||
|
||||
MODULE_INIT(ProtongIRCd)
|
||||
--
|
||||
1.7.8.3
|
||||
|
@@ -0,0 +1,38 @@
|
||||
From d363ebd841ea7e1db3c62730023759d69520e0d8 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Barton <alex@barton.de>
|
||||
Date: Tue, 27 Sep 2011 15:08:09 +0200
|
||||
Subject: [PATCH 08/16] ngircd: Allow setting modes by clients on burst
|
||||
|
||||
This change is required by commit 43201ead9575a for the ngIRCd protocol
|
||||
module as well.
|
||||
---
|
||||
modules/protocol/ngircd.cpp | 7 +++++--
|
||||
1 files changed, 5 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
|
||||
index 3024fdd..2774168 100644
|
||||
--- a/modules/protocol/ngircd.cpp
|
||||
+++ b/modules/protocol/ngircd.cpp
|
||||
@@ -57,14 +57,17 @@ class ngIRCdProto : public IRCDProto
|
||||
send_cmd(source ? source->nick : Config->ServerName, "WALLOPS :%s", buf.c_str());
|
||||
}
|
||||
|
||||
- void SendJoin(User *user, Channel *c, const ChannelStatus *status)
|
||||
+ void SendJoin(User *user, Channel *c, ChannelStatus *status)
|
||||
{
|
||||
send_cmd(user->nick, "JOIN %s", c->name.c_str());
|
||||
if (status)
|
||||
{
|
||||
+ ChannelStatus cs = *status;
|
||||
+ status->ClearFlags();
|
||||
+
|
||||
BotInfo *setter = findbot(user->nick);
|
||||
for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i)
|
||||
- if (status->HasFlag(ModeManager::ChannelModes[i]->Name))
|
||||
+ if (cs.HasFlag(ModeManager::ChannelModes[i]->Name))
|
||||
c->SetMode(setter, ModeManager::ChannelModes[i], user->nick, false);
|
||||
}
|
||||
}
|
||||
--
|
||||
1.7.8.3
|
||||
|
@@ -0,0 +1,143 @@
|
||||
From e74a5303f2357f4a9915bb91038a2e326323db3c Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Barton <alex@barton.de>
|
||||
Date: Fri, 25 Nov 2011 19:16:37 +0100
|
||||
Subject: [PATCH 09/16] ngircd: Update protocol module for current Anope 1.9
|
||||
GIT
|
||||
|
||||
This changes are rquired by:
|
||||
|
||||
- b14f5ea88: Fixed accidentally clearing botmodes when joins are sent
|
||||
- cef3eb78d: Remove send_cmd and replace it with a stringstream
|
||||
- ddc3c2f38: Added options:nonicknameownership config option
|
||||
---
|
||||
modules/protocol/ngircd.cpp | 54 ++++++++++++++++++++++--------------------
|
||||
1 files changed, 28 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
|
||||
index 2774168..55cb8d7 100644
|
||||
--- a/modules/protocol/ngircd.cpp
|
||||
+++ b/modules/protocol/ngircd.cpp
|
||||
@@ -54,16 +54,22 @@ class ngIRCdProto : public IRCDProto
|
||||
|
||||
void SendGlobopsInternal(const BotInfo *source, const Anope::string &buf)
|
||||
{
|
||||
- send_cmd(source ? source->nick : Config->ServerName, "WALLOPS :%s", buf.c_str());
|
||||
+ UplinkSocket::Message(source ? source->nick : Config->ServerName) << "WALLOPS :" << buf;
|
||||
}
|
||||
|
||||
- void SendJoin(User *user, Channel *c, ChannelStatus *status)
|
||||
+ void SendJoin(User *user, Channel *c, const ChannelStatus *status)
|
||||
{
|
||||
- send_cmd(user->nick, "JOIN %s", c->name.c_str());
|
||||
+ UplinkSocket::Message(user->nick) << "JOIN " << c->name;
|
||||
if (status)
|
||||
{
|
||||
+ /* First save the channel status incase uc->Status == status */
|
||||
ChannelStatus cs = *status;
|
||||
- status->ClearFlags();
|
||||
+ /* If the user is internally on the channel with flags, kill them so that
|
||||
+ * the stacker will allow this.
|
||||
+ */
|
||||
+ UserContainer *uc = c->FindUser(user);
|
||||
+ if (uc != NULL)
|
||||
+ uc->Status->ClearFlags();
|
||||
|
||||
BotInfo *setter = findbot(user->nick);
|
||||
for (unsigned i = 0; i < ModeManager::ChannelModes.size(); ++i)
|
||||
@@ -74,18 +80,18 @@ class ngIRCdProto : public IRCDProto
|
||||
|
||||
void SendSVSKillInternal(const BotInfo *source, const User *user, const Anope::string &buf)
|
||||
{
|
||||
- send_cmd(source ? source->nick : Config->ServerName, "KILL %s :%s", user->nick.c_str(), buf.c_str());
|
||||
+ UplinkSocket::Message(source ? source->nick : Config->ServerName) << "KILL " << user->nick << " :" << buf;
|
||||
}
|
||||
|
||||
/* SERVER name hop descript */
|
||||
void SendServer(const Server *server)
|
||||
{
|
||||
- send_cmd("", "SERVER %s %d :%s", server->GetName().c_str(), server->GetHops(), server->GetDescription().c_str());
|
||||
+ UplinkSocket::Message() << "SERVER " << server->GetName() << " " << server->GetHops() << " :" << server->GetDescription();
|
||||
}
|
||||
|
||||
void SendConnect()
|
||||
{
|
||||
- send_cmd("", "PASS %s 0210-IRC+ Anope|%s:CLHSo P", Config->Uplinks[CurrentUplink]->password.c_str(), Anope::VersionShort().c_str());
|
||||
+ UplinkSocket::Message() << "PASS " << Config->Uplinks[CurrentUplink]->password << " 0210-IRC+ Anope|" << Anope::VersionShort() << ":CLHSo P";
|
||||
/* Make myself known to myself in the serverlist */
|
||||
SendServer(Me);
|
||||
/* finish the enhanced server handshake and register the connection */
|
||||
@@ -98,56 +104,52 @@ class ngIRCdProto : public IRCDProto
|
||||
Anope::string modes = "+" + u->GetModes();
|
||||
XLine x(u->nick, "Reserved for services");
|
||||
ircdproto->SendSQLine(NULL, &x);
|
||||
- send_cmd(Config->ServerName, "NICK %s 1 %s %s 1 %s :%s", u->nick.c_str(), u->GetIdent().c_str(), u->host.c_str(), modes.c_str(), u->realname.c_str());
|
||||
+ UplinkSocket::Message(Config->ServerName) << "NICK " << u->nick << " 1 " << u->GetIdent() << " " << u->host << " 1 " << modes << " :" << u->realname;
|
||||
}
|
||||
|
||||
void SendPartInternal(const BotInfo *bi, const Channel *chan, const Anope::string &buf)
|
||||
{
|
||||
if (!buf.empty())
|
||||
- send_cmd(bi->nick, "PART %s :%s", chan->name.c_str(), buf.c_str());
|
||||
+ UplinkSocket::Message(bi->nick) << "PART " << chan->name << " :" << buf;
|
||||
else
|
||||
- send_cmd(bi->nick, "PART %s", chan->name.c_str());
|
||||
+ UplinkSocket::Message(bi->nick) << "PART " << chan->name;
|
||||
}
|
||||
|
||||
void SendModeInternal(const BotInfo *bi, const Channel *dest, const Anope::string &buf)
|
||||
{
|
||||
-Log(LOG_DEBUG) << "SendModeInternal 1";
|
||||
- send_cmd(bi ? bi->nick : Config->ServerName, "MODE %s %s", dest->name.c_str(), buf.c_str());
|
||||
+ UplinkSocket::Message(bi ? bi->nick : Config->ServerName) << "MODE " << dest->name << " " << buf;
|
||||
}
|
||||
|
||||
void SendModeInternal(const BotInfo *bi, const User *u, const Anope::string &buf)
|
||||
{
|
||||
-Log(LOG_DEBUG) << "SendModeInternal 2";
|
||||
- send_cmd(bi ? bi->nick : Config->ServerName, "MODE %s %s", u->nick.c_str(), buf.c_str());
|
||||
+ UplinkSocket::Message(bi ? bi->nick : Config->ServerName) << "MODE " << u->nick << " " << buf;
|
||||
}
|
||||
|
||||
void SendKickInternal(const BotInfo *bi, const Channel *chan, const User *user, const Anope::string &buf)
|
||||
{
|
||||
if (!buf.empty())
|
||||
- send_cmd(bi->nick, "KICK %s %s :%s", chan->name.c_str(), user->nick.c_str(), buf.c_str());
|
||||
+ UplinkSocket::Message(bi->nick) << "KICK " << chan->name << " " << user->nick << " :" << buf;
|
||||
else
|
||||
- send_cmd(bi->nick, "KICK %s %s", chan->name.c_str(), user->nick.c_str());
|
||||
+ UplinkSocket::Message(bi->nick) << "KICK " << chan->name << " " << user->nick;
|
||||
}
|
||||
|
||||
- void SendNoticeChanopsInternal(const BotInfo *source, const Channel *dest, const Anope::string &buf)
|
||||
+ void SendChannel(Channel *c)
|
||||
{
|
||||
- send_cmd(source->nick, "NOTICE @%s :%s", dest->name.c_str(), buf.c_str());
|
||||
+ Anope::string modes = c->GetModes(true, true);
|
||||
+ UplinkSocket::Message(Config->ServerName) << "CHANINFO " << c->name << " +" << modes;
|
||||
}
|
||||
|
||||
- /* INVITE */
|
||||
- void SendInvite(BotInfo *source, const Anope::string &chan, const Anope::string &nick)
|
||||
+ void SendTopic(BotInfo *bi, Channel *c)
|
||||
{
|
||||
- send_cmd(source->nick, "INVITE %s %s", nick.c_str(), chan.c_str());
|
||||
+ UplinkSocket::Message(bi->nick) << "TOPIC " << c->name << " :" << c->topic;
|
||||
}
|
||||
|
||||
- void SendChannel(Channel *c)
|
||||
+ void SendLogin(User *u)
|
||||
{
|
||||
- Anope::string modes = c->GetModes(true, true);
|
||||
- send_cmd(Config->ServerName, "CHANINFO %s +%s", c->name.c_str(), modes.c_str());
|
||||
}
|
||||
- void SendTopic(BotInfo *bi, Channel *c)
|
||||
+
|
||||
+ void SendLogout(User *u)
|
||||
{
|
||||
- send_cmd(bi->nick, "TOPIC %s :%s", c->name.c_str(), c->topic.c_str());
|
||||
}
|
||||
};
|
||||
|
||||
--
|
||||
1.7.8.3
|
||||
|
57
contrib/Anope/0010-ngircd-Add-ProtongIRCd.patch
Normal file
57
contrib/Anope/0010-ngircd-Add-ProtongIRCd.patch
Normal file
@@ -0,0 +1,57 @@
|
||||
From d2c45d7c578ec684d3b471020f631847316de196 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Barton <alex@barton.de>
|
||||
Date: Fri, 25 Nov 2011 19:17:19 +0100
|
||||
Subject: [PATCH 10/16] ngircd: Add ~ProtongIRCd()
|
||||
|
||||
---
|
||||
modules/protocol/ngircd.cpp | 13 ++++++++-----
|
||||
1 files changed, 8 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
|
||||
index 55cb8d7..5fd62db 100644
|
||||
--- a/modules/protocol/ngircd.cpp
|
||||
+++ b/modules/protocol/ngircd.cpp
|
||||
@@ -302,8 +302,7 @@ class ngIRCdIRCdMessage : public IRCdMessage
|
||||
}
|
||||
};
|
||||
|
||||
-/** This is here because:
|
||||
- *
|
||||
+/*
|
||||
* If we had three servers, A, B & C linked like so: A<->B<->C
|
||||
* If Anope is linked to A and B splits from A and then reconnects
|
||||
* B introduces itself, introduces C, sends EOS for C, introduces Bs clients
|
||||
@@ -319,8 +318,6 @@ bool event_pong(const Anope::string &source, const std::vector<Anope::string> &p
|
||||
return true;
|
||||
}
|
||||
|
||||
-
|
||||
-
|
||||
/*
|
||||
* CHANINFO <chan> +<modes>
|
||||
* CHANINFO <chan> +<modes> :<topic>
|
||||
@@ -480,7 +477,6 @@ bool event_376(const Anope::string &source, const std::vector<Anope::string> &pa
|
||||
return true;
|
||||
}
|
||||
|
||||
-
|
||||
class ProtongIRCd : public Module
|
||||
{
|
||||
Message message_kick, message_pass, message_njoin, message_chaninfo, message_005,
|
||||
@@ -542,6 +538,13 @@ class ProtongIRCd : public Module
|
||||
ModuleManager::Attach(I_OnUserNickChange, this);
|
||||
}
|
||||
|
||||
+ ~ProtongIRCd()
|
||||
+ {
|
||||
+ pmodule_ircd_var(NULL);
|
||||
+ pmodule_ircd_proto(NULL);
|
||||
+ pmodule_ircd_message(NULL);
|
||||
+ }
|
||||
+
|
||||
void OnUserNickChange(User *u, const Anope::string &)
|
||||
{
|
||||
u->RemoveModeInternal(ModeManager::FindUserModeByName(UMODE_REGISTERED));
|
||||
--
|
||||
1.7.8.3
|
||||
|
@@ -0,0 +1,29 @@
|
||||
From 4dc5a3d3e2fbb218461d9459bff1c0a392a75881 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Barton <alex@barton.de>
|
||||
Date: Sat, 31 Dec 2011 16:12:52 +0100
|
||||
Subject: [PATCH 11/16] ngircd: Update protocol module for current Anope 1.9
|
||||
GIT
|
||||
|
||||
This changes are rquired by:
|
||||
|
||||
- 150831c1a: Made capab management a bit simplier
|
||||
---
|
||||
modules/protocol/ngircd.cpp | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
|
||||
index 5fd62db..9c26ec8 100644
|
||||
--- a/modules/protocol/ngircd.cpp
|
||||
+++ b/modules/protocol/ngircd.cpp
|
||||
@@ -527,7 +527,7 @@ class ProtongIRCd : public Module
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
- Capab.SetFlag(CAPAB_QS);
|
||||
+ Capab.insert("QS");
|
||||
|
||||
pmodule_ircd_var(myIrcd);
|
||||
pmodule_ircd_proto(&this->ircd_proto);
|
||||
--
|
||||
1.7.8.3
|
||||
|
@@ -0,0 +1,25 @@
|
||||
From 99c18cafdee28bfb17fad5f0526b3ed5d1f5f312 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Barton <alex@barton.de>
|
||||
Date: Sat, 31 Dec 2011 16:17:50 +0100
|
||||
Subject: [PATCH 12/16] ngircd: let Anope know that channel mode "r" is
|
||||
supported
|
||||
|
||||
---
|
||||
modules/protocol/ngircd.cpp | 1 +
|
||||
1 files changed, 1 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
|
||||
index 9c26ec8..6155667 100644
|
||||
--- a/modules/protocol/ngircd.cpp
|
||||
+++ b/modules/protocol/ngircd.cpp
|
||||
@@ -512,6 +512,7 @@ class ProtongIRCd : public Module
|
||||
ModeManager::AddChannelMode(new ChannelMode(CMODE_MODERATED, 'm'));
|
||||
ModeManager::AddChannelMode(new ChannelMode(CMODE_NOEXTERNAL, 'n'));
|
||||
ModeManager::AddChannelMode(new ChannelMode(CMODE_PERM, 'P'));
|
||||
+ ModeManager::AddChannelMode(new ChannelModeRegistered('r'));
|
||||
ModeManager::AddChannelMode(new ChannelMode(CMODE_REGISTEREDONLY, 'R'));
|
||||
ModeManager::AddChannelMode(new ChannelMode(CMODE_SECRET, 's'));
|
||||
ModeManager::AddChannelMode(new ChannelMode(CMODE_TOPIC, 't'));
|
||||
--
|
||||
1.7.8.3
|
||||
|
28
contrib/Anope/0013-ngircd-Update-copyright-notice.patch
Normal file
28
contrib/Anope/0013-ngircd-Update-copyright-notice.patch
Normal file
@@ -0,0 +1,28 @@
|
||||
From 5a19b69f0daceb5b12ec751bc919519a7f712f2d Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Barton <alex@barton.de>
|
||||
Date: Sun, 15 Jan 2012 13:36:14 +0100
|
||||
Subject: [PATCH 13/16] ngircd: Update copyright notice
|
||||
|
||||
---
|
||||
modules/protocol/ngircd.cpp | 7 ++++---
|
||||
1 files changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
|
||||
index 6155667..024c61d 100644
|
||||
--- a/modules/protocol/ngircd.cpp
|
||||
+++ b/modules/protocol/ngircd.cpp
|
||||
@@ -1,7 +1,8 @@
|
||||
-/* ngIRCd IRCD functions
|
||||
+/*
|
||||
+ * ngIRCd Protocol module for Anope IRC Services
|
||||
*
|
||||
- * (C) 2003-2011 Anope Team
|
||||
- * Contact us at team@anope.org
|
||||
+ * (C) 2011-2012 Alexander Barton <alex@barton.de>
|
||||
+ * (C) 2011 Anope Team <team@anope.org>
|
||||
*
|
||||
* Please read COPYING and README for further details.
|
||||
*
|
||||
--
|
||||
1.7.8.3
|
||||
|
@@ -0,0 +1,35 @@
|
||||
From acc24a7f4488f6ef0fb240a76766db4220b62d53 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Barton <alex@barton.de>
|
||||
Date: Sun, 22 Jan 2012 19:05:28 +0100
|
||||
Subject: [PATCH 14/16] ngircd: set/unset GLINE's on AKILL commands
|
||||
|
||||
---
|
||||
modules/protocol/ngircd.cpp | 10 ++++++++--
|
||||
1 files changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
|
||||
index 024c61d..3bc3812 100644
|
||||
--- a/modules/protocol/ngircd.cpp
|
||||
+++ b/modules/protocol/ngircd.cpp
|
||||
@@ -48,10 +48,16 @@ class ngIRCdProto : public IRCDProto
|
||||
{
|
||||
void SendAkill(User *u, const XLine *x)
|
||||
{
|
||||
- // TODO: ADD SOME CODE
|
||||
+ // Calculate the time left before this would expire, capping it at 2 days
|
||||
+ time_t timeleft = x->Expires - Anope::CurTime;
|
||||
+ if (timeleft > 172800 || !x->Expires)
|
||||
+ timeleft = 172800;
|
||||
+ UplinkSocket::Message(Config->ServerName) << "GLINE " << x->Mask << " " << timeleft << " :" << x->Reason << " (" << x->By << ")";
|
||||
}
|
||||
|
||||
- void SendAkillDel(const XLine*) { }
|
||||
+ void SendAkillDel(const XLine *x) {
|
||||
+ UplinkSocket::Message(Config->ServerName) << "GLINE " << x->Mask;
|
||||
+ }
|
||||
|
||||
void SendGlobopsInternal(const BotInfo *source, const Anope::string &buf)
|
||||
{
|
||||
--
|
||||
1.7.8.3
|
||||
|
@@ -0,0 +1,27 @@
|
||||
From 3a61b190db79848d4519296432ebb2ab714c42b7 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Barton <alex@barton.de>
|
||||
Date: Sun, 22 Jan 2012 19:06:34 +0100
|
||||
Subject: [PATCH 15/16] ngircd: ngIRCd supports channel mode 'e' now
|
||||
|
||||
---
|
||||
modules/protocol/ngircd.cpp | 3 ++-
|
||||
1 files changed, 2 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
|
||||
index 3bc3812..0f87cbd 100644
|
||||
--- a/modules/protocol/ngircd.cpp
|
||||
+++ b/modules/protocol/ngircd.cpp
|
||||
@@ -504,8 +504,9 @@ class ProtongIRCd : public Module
|
||||
ModeManager::AddUserMode(new UserMode(UMODE_WALLOPS, 'w'));
|
||||
ModeManager::AddUserMode(new UserMode(UMODE_CLOAK, 'x'));
|
||||
|
||||
- /* Add modes for ban and invite lists */
|
||||
+ /* Add modes for ban, exception, and invite lists */
|
||||
ModeManager::AddChannelMode(new ChannelModeList(CMODE_BAN, 'b'));
|
||||
+ ModeManager::AddChannelMode(new ChannelModeList(CMODE_EXCEPT, 'e'));
|
||||
ModeManager::AddChannelMode(new ChannelModeList(CMODE_INVITEOVERRIDE, 'I'));
|
||||
|
||||
/* Add channel user modes */
|
||||
--
|
||||
1.7.8.3
|
||||
|
35
contrib/Anope/0016-ngircd-support-SQUERY-command.patch
Normal file
35
contrib/Anope/0016-ngircd-support-SQUERY-command.patch
Normal file
@@ -0,0 +1,35 @@
|
||||
From a7c48fcf47af757cf1b4eeaa6bcc96f4ae1f7410 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Barton <alex@barton.de>
|
||||
Date: Sat, 4 Feb 2012 11:13:36 +0100
|
||||
Subject: [PATCH 16/16] ngircd: support SQUERY command
|
||||
|
||||
Thanks to DukePyrolator for explaining these changes to me.
|
||||
---
|
||||
modules/protocol/ngircd.cpp | 4 ++--
|
||||
1 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/modules/protocol/ngircd.cpp b/modules/protocol/ngircd.cpp
|
||||
index 0f87cbd..530686e 100644
|
||||
--- a/modules/protocol/ngircd.cpp
|
||||
+++ b/modules/protocol/ngircd.cpp
|
||||
@@ -487,7 +487,7 @@ bool event_376(const Anope::string &source, const std::vector<Anope::string> &pa
|
||||
class ProtongIRCd : public Module
|
||||
{
|
||||
Message message_kick, message_pass, message_njoin, message_chaninfo, message_005,
|
||||
- message_442, message_376, message_pong;
|
||||
+ message_442, message_376, message_pong, message_squery;
|
||||
|
||||
ngIRCdProto ircd_proto;
|
||||
ngIRCdIRCdMessage ircd_message;
|
||||
@@ -532,7 +532,7 @@ class ProtongIRCd : public Module
|
||||
message_kick("KICK", event_kick), message_pass("PASS", event_pass),
|
||||
message_njoin("NJOIN", event_njoin), message_chaninfo("CHANINFO", event_chaninfo),
|
||||
message_005("005", event_005), message_442("442", event_442), message_376("376", event_376),
|
||||
- message_pong("PONG", event_pong)
|
||||
+ message_pong("PONG", event_pong), message_squery("SQUERY", ::OnPrivmsg)
|
||||
{
|
||||
this->SetAuthor("Anope");
|
||||
|
||||
--
|
||||
1.7.8.3
|
||||
|
@@ -2,7 +2,7 @@
|
||||
ngIRCd - Next Generation IRC Server
|
||||
http://ngircd.barton.de/
|
||||
|
||||
(c)2001-2011 Alexander Barton and Contributors.
|
||||
(c)2001-2012 Alexander Barton and Contributors.
|
||||
ngIRCd is free software and published under the
|
||||
terms of the GNU General Public License.
|
||||
|
||||
@@ -11,22 +11,21 @@
|
||||
|
||||
This directory contains two preliminary patches that (re-) add a ngIRCd
|
||||
protocol module to the Anope 1.9 development branch. It has been tested
|
||||
with Anope 1.9.4, there is no guarantee that it will work with other
|
||||
with Anope 1.9.6, there is no guarantee that it will work with other
|
||||
versions as Anope 1.9.x is under heavy development ...
|
||||
|
||||
To build this Anope protocol module, you have to
|
||||
|
||||
- Download the Anope 1.9.x sources (tested with 1.9.4),
|
||||
- Download the Anope 1.9.x sources (only tested with 1.9.6!),
|
||||
- Patch in the ngIRCd protocol module,
|
||||
- Build and install Anope as usual,
|
||||
- Configure Anope as usual, use "ngircd" as protocol module.
|
||||
|
||||
So the command sequence can be something like this:
|
||||
|
||||
$ tar xzf anope-1.9.4-source.tar.gz
|
||||
$ cd anope-1.9.4-source
|
||||
$ patch -p1 < .../ngircd/contrib/Anope/0001-Revert-Removed-ngircd.patch
|
||||
$ patch -p1 < .../ngircd/contrib/Anope/0002-ngircd-whitespace-fixes.patch
|
||||
$ tar xzf anope-1.9.6-source.tar.gz
|
||||
$ cd anope-1.9.6-source
|
||||
$ for p in .../ngircd/contrib/Anope/*.patch ; do patch -p1 < $p ; done
|
||||
$ ./Config
|
||||
$ cd build
|
||||
$ make
|
||||
|
@@ -1,3 +1,9 @@
|
||||
ngircd (19~rc1-0ab1) unstable; urgency=low
|
||||
|
||||
* New "upstream" release candidate 1 for ngIRCd Release 19.
|
||||
|
||||
-- Alexander Barton <alex@barton.de> Sun, 12 Feb 2012 17:47:51 +0100
|
||||
|
||||
ngircd (18-0ab1) unstable; urgency=low
|
||||
|
||||
* New "upstream" release: ngIRCd 18.
|
||||
|
@@ -2,64 +2,60 @@ Source: ngircd
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Alexander Barton <alex@barton.de>
|
||||
Build-Depends: debhelper (>> 4.0.0), libz-dev, libwrap0-dev, libident-dev, libgnutls-dev, libpam0g-dev
|
||||
Build-Depends: debhelper (>> 4.0.0),
|
||||
autotools-dev,
|
||||
expect,
|
||||
libz-dev,
|
||||
libwrap0-dev,
|
||||
libident-dev,
|
||||
libgnutls-dev,
|
||||
libpam0g-dev,
|
||||
telnet,
|
||||
Standards-Version: 3.9.1
|
||||
|
||||
Package: ngircd
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Provides: ircd
|
||||
Description: A lightweight daemon for the Internet Relay Chat (IRC)
|
||||
ngIRCd is a free open source daemon for the Internet Relay Chat (IRC)
|
||||
network. It is written from scratch and is not based upon the original
|
||||
IRCd like many others.
|
||||
Description: lightweight Internet Relay Chat server
|
||||
This package provides ngIRCd, a lightweight Internet Relay Chat
|
||||
server for small or private networks. It is simple to configure, can
|
||||
cope with dynamic IP addresses, and supports IPv6 as well as SSL. It
|
||||
is written from scratch, not based on the original IRCd and quite
|
||||
portable.
|
||||
.
|
||||
This package contains the "standard distribution", including support for
|
||||
syslog logging and compressed server-links using zlib. Please have a look
|
||||
at the "ngircd-full" package if you need advanced functionality like support
|
||||
for IPv6 or SSL.
|
||||
.
|
||||
Advantages of ngIRCd:
|
||||
- no problems with servers using changing/non-static IP addresses.
|
||||
- small and lean configuration file.
|
||||
- free, modern and open source C code.
|
||||
- still under active development.
|
||||
.
|
||||
ngIRCd is compatible to the "original" ircd 2.10.3p3, so you can run
|
||||
mixed networks.
|
||||
|
||||
Package: ngircd-full
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Provides: ircd
|
||||
Conflicts: ngircd, ngircd-dbg
|
||||
Description: A lightweight daemon for the Internet Relay Chat (IRC)
|
||||
ngIRCd is a free open source daemon for the Internet Relay Chat (IRC)
|
||||
network. It is written from scratch and is not based upon the original
|
||||
IRCd like many others.
|
||||
Description: lightweight Internet Relay Chat server
|
||||
This package provides ngIRCd, a lightweight Internet Relay Chat
|
||||
server for small or private networks. It is simple to configure, can
|
||||
cope with dynamic IP addresses, and supports IPv6 as well as SSL. It
|
||||
is written from scratch, not based on the original IRCd and quite
|
||||
portable.
|
||||
.
|
||||
In addition to the features of the "standard package", this package
|
||||
includes support for TCP wrappers, IDENT requests, the IPv6 protocol and
|
||||
SSL encrypted client and server links.
|
||||
.
|
||||
Advantages of ngIRCd:
|
||||
- no problems with servers using changing/non-static IP addresses.
|
||||
- small and lean configuration file.
|
||||
- free, modern and open source C code.
|
||||
- still under active development.
|
||||
.
|
||||
ngIRCd is compatible to the "original" ircd 2.10.3p3, so you can run
|
||||
mixed networks.
|
||||
|
||||
Package: ngircd-full-dbg
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||
Provides: ircd
|
||||
Conflicts: ngircd, ngircd-full
|
||||
Description: A lightweight daemon for the Internet Relay Chat (IRC)
|
||||
ngIRCd is a free open source daemon for the Internet Relay Chat (IRC)
|
||||
network. It is written from scratch and is not based upon the original
|
||||
IRCd like many others.
|
||||
Description: lightweight Internet Relay Chat server
|
||||
This package provides ngIRCd, a lightweight Internet Relay Chat
|
||||
server for small or private networks. It is simple to configure, can
|
||||
cope with dynamic IP addresses, and supports IPv6 as well as SSL. It
|
||||
is written from scratch, not based on the original IRCd and quite
|
||||
portable.
|
||||
.
|
||||
In addition to the features of the "standard package", this package
|
||||
includes support for TCP wrappers, IDENT requests, the IPv6 protocol and
|
||||
@@ -67,12 +63,3 @@ Description: A lightweight daemon for the Internet Relay Chat (IRC)
|
||||
.
|
||||
And in addition to the "full" variant, the binaries contained in this
|
||||
package are build with debug code and contain debug symbols.
|
||||
.
|
||||
Advantages of ngIRCd:
|
||||
- no problems with servers using changing/non-static IP addresses.
|
||||
- small and lean configuration file.
|
||||
- free, modern and open source C code.
|
||||
- still under active development.
|
||||
.
|
||||
ngIRCd is compatible to the "original" ircd 2.10.3p3, so you can run
|
||||
mixed networks.
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2010 Alexander Barton (alex@barton.de).
|
||||
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -74,6 +74,8 @@
|
||||
/* Define to 1 if you have the <netinet/ip.h> header file. */
|
||||
#define HAVE_NETINET_IP_H 1
|
||||
|
||||
/* Define to 1 if you have the `gai_strerror' function. */
|
||||
#define HAVE_GAI_STRERROR 1
|
||||
/* Define to 1 if you have the `kqueue' function. */
|
||||
#define HAVE_KQUEUE 1
|
||||
/* Define to 1 if you have the `inet_ntoa' function. */
|
||||
@@ -103,10 +105,15 @@
|
||||
#ifdef PAM
|
||||
/* Define to 1 if you have the `pam_authenticate' function. */
|
||||
#define HAVE_PAM_AUTHENTICATE 1
|
||||
#if (__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ < 1060)
|
||||
/* Define to 1 if you have the <pam/pam_appl.h> header file. */
|
||||
#define HAVE_PAM_PAM_APPL_H 1
|
||||
/* Mac OS X <10.6 doesn't have pam_fail_delay() */
|
||||
#define NO_PAM_FAIL_DELAY 1
|
||||
#else
|
||||
/* Define to 1 if you have the <security/pam_appl.h> header file. */
|
||||
#define HAVE_SECURITY_PAM_APPL_H 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* -eof- */
|
||||
|
2
contrib/MacOSX/ngIRCd.xcodeproj/.gitignore
vendored
2
contrib/MacOSX/ngIRCd.xcodeproj/.gitignore
vendored
@@ -1,2 +1,4 @@
|
||||
project.xcworkspace
|
||||
xcuserdata
|
||||
*.mode1v3
|
||||
*.pbxuser
|
||||
|
@@ -3,7 +3,7 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 44;
|
||||
objectVersion = 46;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
@@ -40,6 +40,7 @@
|
||||
FA99428C10E82A27007F27ED /* proc.c in Sources */ = {isa = PBXBuildFile; fileRef = FA99428B10E82A27007F27ED /* proc.c */; };
|
||||
FAA3D27B0F139CDC00B2447E /* conn-ssl.c in Sources */ = {isa = PBXBuildFile; fileRef = FAA3D2790F139CDC00B2447E /* conn-ssl.c */; };
|
||||
FAA97C57124A271400D5BBA9 /* sighandlers.c in Sources */ = {isa = PBXBuildFile; fileRef = FAA97C55124A271400D5BBA9 /* sighandlers.c */; };
|
||||
FAACD5F514A6099C006ED74F /* class.c in Sources */ = {isa = PBXBuildFile; fileRef = FAACD5F314A6099C006ED74F /* class.c */; };
|
||||
FAE5CC2E0CF2308A007D69B6 /* numeric.c in Sources */ = {isa = PBXBuildFile; fileRef = FAE5CC2D0CF2308A007D69B6 /* numeric.c */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@@ -170,7 +171,6 @@
|
||||
FA322D8E0CEF7523001761B3 /* ngIRCd.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = ngIRCd.xcodeproj; sourceTree = "<group>"; };
|
||||
FA322D910CEF7523001761B3 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
|
||||
FA322D920CEF7523001761B3 /* ngindent */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = ngindent; sourceTree = "<group>"; };
|
||||
FA322D930CEF7523001761B3 /* ngircd.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = ngircd.sh; sourceTree = "<group>"; };
|
||||
FA322D940CEF7523001761B3 /* ngircd.spec */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = ngircd.spec; sourceTree = "<group>"; };
|
||||
FA322D950CEF7523001761B3 /* README */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
|
||||
FA322D960CEF7523001761B3 /* systrace.policy */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = systrace.policy; sourceTree = "<group>"; };
|
||||
@@ -196,6 +196,10 @@
|
||||
FA407F2C0DB159F400271AF1 /* ng_ipaddr.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = ng_ipaddr.c; path = ipaddr/ng_ipaddr.c; sourceTree = "<group>"; };
|
||||
FA407F2D0DB159F400271AF1 /* ng_ipaddr.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; name = ng_ipaddr.h; path = ipaddr/ng_ipaddr.h; sourceTree = "<group>"; };
|
||||
FA407F380DB15AC700271AF1 /* GIT.txt */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text; path = GIT.txt; sourceTree = "<group>"; };
|
||||
FA4B08E513E7F8FB00765BA3 /* ngircd-bsd.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "ngircd-bsd.sh"; sourceTree = "<group>"; };
|
||||
FA4B08E613E7F91700765BA3 /* ngIRCd-Logo.gif */ = {isa = PBXFileReference; lastKnownFileType = image.gif; path = "ngIRCd-Logo.gif"; sourceTree = "<group>"; };
|
||||
FA4B08E713E7F91700765BA3 /* ngircd-redhat.init */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = "ngircd-redhat.init"; sourceTree = "<group>"; };
|
||||
FA4B08E813E7F91C00765BA3 /* platformtest.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = platformtest.sh; sourceTree = "<group>"; };
|
||||
FA77849A133FB9FF00740057 /* sample-ngircd.conf.tmpl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "sample-ngircd.conf.tmpl"; sourceTree = "<group>"; };
|
||||
FA85178A0FA061EC006A1F5A /* op.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = op.h; sourceTree = "<group>"; };
|
||||
FA85178B0FA061EC006A1F5A /* op.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = op.c; sourceTree = "<group>"; };
|
||||
@@ -225,6 +229,8 @@
|
||||
FAA3D28B0F139D2E00B2447E /* preinstall.sh */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = text.script.sh; path = preinstall.sh; sourceTree = "<group>"; };
|
||||
FAA97C55124A271400D5BBA9 /* sighandlers.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; path = sighandlers.c; sourceTree = "<group>"; };
|
||||
FAA97C56124A271400D5BBA9 /* sighandlers.h */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.h; path = sighandlers.h; sourceTree = "<group>"; };
|
||||
FAACD5F314A6099C006ED74F /* class.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = class.c; sourceTree = "<group>"; };
|
||||
FAACD5F414A6099C006ED74F /* class.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = class.h; sourceTree = "<group>"; };
|
||||
FAE5CC2C0CF2308A007D69B6 /* numeric.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = numeric.h; sourceTree = "<group>"; };
|
||||
FAE5CC2D0CF2308A007D69B6 /* numeric.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = numeric.c; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
@@ -292,17 +298,19 @@
|
||||
FA322CD70CEF74B1001761B3 /* ngircd */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FAA3D2780F139CDC00B2447E /* conf-ssl.h */,
|
||||
FAA3D2790F139CDC00B2447E /* conn-ssl.c */,
|
||||
FAA3D27A0F139CDC00B2447E /* conn-ssl.h */,
|
||||
FA322CD90CEF74B1001761B3 /* array.c */,
|
||||
FA322CDA0CEF74B1001761B3 /* array.h */,
|
||||
FA322CDB0CEF74B1001761B3 /* channel.c */,
|
||||
FA322CDC0CEF74B1001761B3 /* channel.h */,
|
||||
FAACD5F314A6099C006ED74F /* class.c */,
|
||||
FAACD5F414A6099C006ED74F /* class.h */,
|
||||
FA322CDD0CEF74B1001761B3 /* client.c */,
|
||||
FA322CDE0CEF74B1001761B3 /* client.h */,
|
||||
FA322CDF0CEF74B1001761B3 /* conf.c */,
|
||||
FA322CE00CEF74B1001761B3 /* conf.h */,
|
||||
FAA3D2780F139CDC00B2447E /* conf-ssl.h */,
|
||||
FA322CE10CEF74B1001761B3 /* conn-func.c */,
|
||||
FA322CE20CEF74B1001761B3 /* conn-func.h */,
|
||||
FA322CE30CEF74B1001761B3 /* conn-zip.c */,
|
||||
@@ -346,6 +354,8 @@
|
||||
FAE5CC2C0CF2308A007D69B6 /* numeric.h */,
|
||||
FA85178B0FA061EC006A1F5A /* op.c */,
|
||||
FA85178A0FA061EC006A1F5A /* op.h */,
|
||||
FA2D564911EA158B00D37A35 /* pam.c */,
|
||||
FA2D564811EA158B00D37A35 /* pam.h */,
|
||||
FA322D080CEF74B1001761B3 /* parse.c */,
|
||||
FA322D090CEF74B1001761B3 /* parse.h */,
|
||||
FA99428B10E82A27007F27ED /* proc.c */,
|
||||
@@ -354,8 +364,6 @@
|
||||
FA322D0D0CEF74B1001761B3 /* resolve.h */,
|
||||
FAA97C55124A271400D5BBA9 /* sighandlers.c */,
|
||||
FAA97C56124A271400D5BBA9 /* sighandlers.h */,
|
||||
FA2D564811EA158B00D37A35 /* pam.h */,
|
||||
FA2D564911EA158B00D37A35 /* pam.c */,
|
||||
);
|
||||
path = ngircd;
|
||||
sourceTree = "<group>";
|
||||
@@ -432,8 +440,11 @@
|
||||
FA322D730CEF7523001761B3 /* MacOSX */,
|
||||
FA322D910CEF7523001761B3 /* Makefile.am */,
|
||||
FA322D920CEF7523001761B3 /* ngindent */,
|
||||
FA322D930CEF7523001761B3 /* ngircd.sh */,
|
||||
FA4B08E513E7F8FB00765BA3 /* ngircd-bsd.sh */,
|
||||
FA4B08E613E7F91700765BA3 /* ngIRCd-Logo.gif */,
|
||||
FA4B08E713E7F91700765BA3 /* ngircd-redhat.init */,
|
||||
FA322D940CEF7523001761B3 /* ngircd.spec */,
|
||||
FA4B08E813E7F91C00765BA3 /* platformtest.sh */,
|
||||
FA322D950CEF7523001761B3 /* README */,
|
||||
FA322D960CEF7523001761B3 /* systrace.policy */,
|
||||
);
|
||||
@@ -641,8 +652,11 @@
|
||||
/* Begin PBXProject section */
|
||||
08FB7793FE84155DC02AAC07 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0420;
|
||||
};
|
||||
buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "ngIRCd" */;
|
||||
compatibilityVersion = "Xcode 3.0";
|
||||
compatibilityVersion = "Xcode 3.2";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 1;
|
||||
knownRegions = (
|
||||
@@ -703,6 +717,7 @@
|
||||
FA99428C10E82A27007F27ED /* proc.c in Sources */,
|
||||
FA2D564A11EA158B00D37A35 /* pam.c in Sources */,
|
||||
FAA97C57124A271400D5BBA9 /* sighandlers.c in Sources */,
|
||||
FAACD5F514A6099C006ED74F /* class.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -713,6 +728,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
@@ -738,13 +754,11 @@
|
||||
1DEB928B08733DD80010E9CD /* Default */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1)";
|
||||
ARCHS_STANDARD_32_64_BIT_PRE_XCODE_3_1 = "x86_64 i386 ppc";
|
||||
GCC_VERSION = 4.0;
|
||||
ARCHS = "$(ARCHS_STANDARD_32_64_BIT)";
|
||||
GCC_VERSION = 4.2;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
PREBINDING = NO;
|
||||
SDKROOT = "$(DEVELOPER_SDK_DIR)/MacOSX10.5.sdk";
|
||||
SDKROOT = macosx10.6;
|
||||
};
|
||||
name = Default;
|
||||
};
|
||||
@@ -754,12 +768,11 @@
|
||||
ARCHS = "$(NATIVE_ARCH_ACTUAL)";
|
||||
GCC_DEBUGGING_SYMBOLS = full;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_VERSION = 4.0;
|
||||
GCC_VERSION = 4.2;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
PREBINDING = NO;
|
||||
SDKROOT = "";
|
||||
SDKROOT = macosx;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -767,6 +780,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
|
||||
GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
|
||||
GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
|
||||
|
@@ -4,6 +4,7 @@ INDENTARGS="-kr -i8 -ts8 -l80 -c3 -cd41 -ss -ncs -psl"
|
||||
|
||||
# check if indent(1) is available
|
||||
type indent >/dev/null 2>&1 && INDENT="indent"
|
||||
type gindent >/dev/null 2>&1 && INDENT="gindent"
|
||||
type gnuindent >/dev/null 2>&1 && INDENT="gnuindent"
|
||||
|
||||
if [ -z "$INDENT" ]; then
|
||||
|
@@ -1,5 +1,5 @@
|
||||
%define name ngircd
|
||||
%define version 18
|
||||
%define version 19~rc1
|
||||
%define release 1
|
||||
%define prefix %{_prefix}
|
||||
|
||||
@@ -15,18 +15,19 @@ BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
BuildRequires: zlib-devel, openssl-devel
|
||||
|
||||
%description
|
||||
ngIRCd is a free open source daemon for the Internet Relay Chat (IRC),
|
||||
developed under the GNU General Public License (GPL). It's written from
|
||||
scratch and is not based upon the original IRCd like many others.
|
||||
This package provides ngIRCd, a lightweight Internet Relay Chat
|
||||
server for small or private networks. It is simple to configure, can
|
||||
cope with dynamic IP addresses, and supports IPv6 as well as SSL. It
|
||||
is written from scratch, not based on the original IRCd and quite
|
||||
portable.
|
||||
|
||||
Advantages:
|
||||
- no problems with servers using changing/non-static IP addresses.
|
||||
- small and lean configuration file.
|
||||
- free, modern and open source C code.
|
||||
- still under active development.
|
||||
|
||||
ngIRCd is compatible to the "original" ircd 2.10.3p3, so you can run
|
||||
mixed networks.
|
||||
- well arranged (lean) configuration file
|
||||
- simple to build/install, configure and maintain
|
||||
- supports IPv6 and SSL
|
||||
- no problems with servers that have dynamic IP addresses
|
||||
- freely available, modern, portable and tidy C-source
|
||||
- ngIRCd is being actively developed since 11 years.
|
||||
|
||||
%prep
|
||||
%setup -q
|
||||
|
37
doc/GIT.txt
37
doc/GIT.txt
@@ -9,13 +9,23 @@
|
||||
-- GIT.txt --
|
||||
|
||||
|
||||
The source code of ngIRCd is maintained using git, the stupid content
|
||||
tracker.
|
||||
The source code of ngIRCd is maintained using GIT, an distributed version
|
||||
control system. Homepage including documentation: <http://git-scm.com/>.
|
||||
|
||||
|
||||
I. Getting the source code
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
To access the source tree anonymously, run:
|
||||
I. Viewing the source code online
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The ngIRCd "GITweb" interface allows you to browse the GIT repository and
|
||||
to see all individual files, tags, branches, commits etc.:
|
||||
|
||||
<http://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd.git>
|
||||
|
||||
|
||||
II. Getting the source code
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
To access (copy, clone) the source tree repository anonymously, run:
|
||||
|
||||
$ git clone git://ngircd.barton.de/ngircd.git
|
||||
|
||||
@@ -23,23 +33,23 @@ Thereby a new folder "ngircd" will be created containing all the individual
|
||||
source files.
|
||||
|
||||
The newly created directory ("ngircd") is the "working directory", all
|
||||
git commands will be executed from within this directory in the future.
|
||||
GIT commands will be executed from within this directory in the future.
|
||||
|
||||
Please note: When checking out a fresh copy of ngIRCd using git, the
|
||||
Please note: When checking out a fresh copy of ngIRCd using GIT, the
|
||||
configure script doesn't exist; you have to run the autogen.sh shell script
|
||||
(which is included in the source tree) to generate it. This requires you to
|
||||
have GNU automake and GNU autoconf installed on your system. Please see the
|
||||
file INSTALL for details!
|
||||
|
||||
To update the git tree:
|
||||
To update the local GIT repository:
|
||||
|
||||
$ git pull
|
||||
|
||||
This retrieves all changes and merges them into the current branch.
|
||||
|
||||
|
||||
II. Contributing
|
||||
~~~~~~~~~~~~~~~~
|
||||
III. Contributing
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Patches should be sent to the ngircd mailing list. List homepage:
|
||||
http://arthur.barton.de/mailman/listinfo/ngircd-ml
|
||||
@@ -48,7 +58,8 @@ If you do not want to send them to the list, you can also mail them
|
||||
to Alex Barton, <alex@barton.de>.
|
||||
|
||||
|
||||
III. Write Access
|
||||
~~~~~~~~~~~~~~~~~
|
||||
If you want to contribute a couple of patches and write access to the git
|
||||
IV. Write Access
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
If you want to contribute a couple of patches and write access to the GIT
|
||||
repository would be handy, please contact Alex Barton, <alex@barton.de>.
|
||||
|
@@ -1,13 +1,12 @@
|
||||
#
|
||||
# ngIRCd -- The Next Generation IRC Daemon
|
||||
# Copyright (c)2001-2010 Alexander Barton (alex@barton.de)
|
||||
# Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors
|
||||
#
|
||||
# Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen
|
||||
# der GNU General Public License (GPL), wie von der Free Software Foundation
|
||||
# herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2
|
||||
# der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version.
|
||||
# Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
|
||||
# der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
# Please read the file COPYING, README and AUTHORS for more information.
|
||||
#
|
||||
|
||||
.tmpl:
|
||||
@@ -17,9 +16,9 @@
|
||||
|
||||
SUFFIXES = .tmpl
|
||||
|
||||
static_docs = Bopm.txt FAQ.txt GIT.txt HowToRelease.txt PAM.txt Platforms.txt \
|
||||
Protocol.txt README-AUX.txt README-BeOS.txt README-Interix.txt RFC.txt \
|
||||
SSL.txt Services.txt
|
||||
static_docs = Bopm.txt FAQ.txt GIT.txt HowToRelease.txt Modes.txt PAM.txt \
|
||||
Platforms.txt Protocol.txt README-AUX.txt README-BeOS.txt \
|
||||
README-Interix.txt RFC.txt SSL.txt Services.txt
|
||||
|
||||
doc_templates = sample-ngircd.conf.tmpl
|
||||
|
||||
|
76
doc/Modes.txt
Normal file
76
doc/Modes.txt
Normal file
@@ -0,0 +1,76 @@
|
||||
|
||||
ngIRCd - Next Generation IRC Server
|
||||
http://ngircd.barton.de/
|
||||
|
||||
(c)2001-2011 Alexander Barton and Contributors.
|
||||
ngIRCd is free software and published under the
|
||||
terms of the GNU General Public License.
|
||||
|
||||
-- Modes.txt --
|
||||
|
||||
|
||||
This document lists the different user modes, channel modes, and channel
|
||||
user modes that ngIRCd supports.
|
||||
|
||||
|
||||
I. User Modes
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
User modes are attributes a user has in the network, regardless of the
|
||||
channels he is using at the moment.
|
||||
|
||||
mode since description
|
||||
|
||||
a 0.3.0 User is away.
|
||||
c 17 IRC operator wants to receive connect/disconnect NOTICEs.
|
||||
C 19 Only users that share a channel are allowed to send messages.
|
||||
i 0.0.1 User is "invisible".
|
||||
o 0.0.1 User is IRC operator.
|
||||
r 0.0.1 User is restricted.
|
||||
R (1) 19 User is registered (e.g. by NickServ).
|
||||
s 0.4.0 User wants to receive server notices.
|
||||
w 0.11.0 User wants to receive WALLOPS messages.
|
||||
x 17 Hostname of this user is "cloaked".
|
||||
|
||||
II. Channel Modes
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
Channel modes are attributes of specific channels which are valid for all
|
||||
users joined (or trying to join) to this channel. Some modes add and remove
|
||||
users to lists (e.g. "invite list", "ban list"), others have parameters
|
||||
(like "channel key"), most are simple flags (like "moderated").
|
||||
|
||||
mode since description
|
||||
|
||||
b 0.5.0 Add/remove a host mask to the ban list.
|
||||
i 0.5.0 Channel is "invite only".
|
||||
I 0.5.0 Add/remove a host mask to the invite list.
|
||||
k 0.6.0 Channel has a "key" (a password).
|
||||
l 0.6.0 Channel has a user limit.
|
||||
m 0.3.0 Channel is moderated, only "voiced" users can send messages.
|
||||
n 0.3.0 Channel doesn't allow messages of users not being members.
|
||||
O 18 Only IRC operators are allowed to join this channel.
|
||||
P 0.5.0 Channel is "persistent".
|
||||
r (1) 19 Channel is "registered" (e.g. by ChanServ).
|
||||
R 19 Only registered users are allowed to join this channel.
|
||||
s 0.9.0 Channel is "secret".
|
||||
t 0.3.0 Only ChanOps are allowed to modify the channel topic.
|
||||
z 16 Only users connected via SSL are allowed to join the channel.
|
||||
|
||||
III. Channel User Modes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Channel user modes are attributes that a particular user has in a specific
|
||||
channel of which he is a member.
|
||||
|
||||
mode since description
|
||||
|
||||
o 0.2.0 User is channel operator and can op/kick/... other members.
|
||||
v 0.2.0 User is "voiced" and can speak even if channel is moderated.
|
||||
|
||||
|
||||
Notes
|
||||
~~~~~
|
||||
|
||||
(1) This mode is not set by ngIRCd itself but by services. ngIRCd handles
|
||||
the mode transparently and possibly adjusts its behaviour.
|
@@ -35,9 +35,10 @@ i386/apple/darwin10.7.0 gcc 4.2.1 18 11-07-05 alex Y Y Y Y (3)
|
||||
i386/apple/darwin11.0.0 gcc 4.2.1 18 11-07-02 alex Y Y Y Y (3)
|
||||
i386/pc/solaris2.9 gcc 3.2.2 CVSHEAD 04-02-24 alex Y Y Y Y
|
||||
i386/pc/solaris2.11 gcc 3.4.3 18 11-07-10 alex Y Y N Y (4)
|
||||
i386/pc/solaris2.11 gcc 4.2.3 18 11-08-17 goetz Y Y Y Y (4)
|
||||
i386/unknown/freebsd5.2.1 gcc 3.3.3 0.8.0 04-05-30 alex Y Y Y Y
|
||||
i386/unknown/freebsd6.2 gcc 3.4.6 18 11-07-10 alex Y Y Y Y (3)
|
||||
i386/unknown/freebsd7.3 gcc 4.2.1 18 11-07-1ß alex Y Y Y Y (3)
|
||||
i386/unknown/freebsd7.3 gcc 4.2.1 18 11-07-10 alex Y Y Y Y (3)
|
||||
i686/unknown/gnu0.3 gcc 4.4.5 18 11-07-10 alex Y Y Y Y
|
||||
i686/unkn./kfreebsd7.2-gnu gcc 4.3.4 15 09-12-02 alex Y Y Y Y (3)
|
||||
i386/unknown/netbsdelf1.6.2 gcc 2.95.3 18 11-07-10 goetz Y Y Y Y
|
||||
@@ -59,6 +60,7 @@ m68k/apple/aux3.1.1 Orig. A/UX 18 11-07-02 alex Y Y N Y (2)
|
||||
m68k/hp/hp-ux9.10 Orig. HPUX 0.7.x-CVS 03-04-30 goetz Y Y Y Y
|
||||
m88k/dg/dgux5.4R3.10 gcc 2.5.8 CVSHEAD 04-03-15 alex Y Y ? ?
|
||||
mipsel/unknown/linux-gnu gcc 4.1.2 18 11-07-05 goetz Y Y N Y (1)
|
||||
mipsel/unknown/linux-gnu gcc 4.4.5 18 11-07-30 goetz Y Y Y Y (1)
|
||||
powerpc/apple/darwin6.5 gcc 3.1 0.7.x-CVS 03-04-23 alex Y Y Y Y
|
||||
powerpc/apple/darwin7.9.0 gcc 3.3 CVSHEAD 06-05-07 fw Y Y Y Y (3)
|
||||
powerpc/apple/darwin8.11.0 gcc 4.0.1 18 11-07-02 goetz Y Y Y Y (3)
|
||||
@@ -75,7 +77,7 @@ x86_64/unknown/openbsd4.7 gcc 3.3.5 18 11-07-10 alex Y Y Y Y (3)
|
||||
Notes
|
||||
~~~~~
|
||||
|
||||
(1) i686/pc/linux-gnu & x86_64/unknown/linux-gnu:
|
||||
(1) */*/linux-gnu (Linux platforms):
|
||||
ngIRCd has been tested with various Linux distributions, such as SuSE,
|
||||
RedHat, Debian, and Gentoo using Kernels 2.2.x, 2.4.x and 2.6.x with
|
||||
various versions of the GNU C compiler (starting with 2.95.x and up to
|
||||
|
@@ -140,6 +140,8 @@
|
||||
;DNS = yes
|
||||
|
||||
# Do IDENT lookups if ngIRCd has been compiled with support for it.
|
||||
# Users identified using IDENT are registered without the "~" character
|
||||
# prepended to their user name.
|
||||
;Ident = yes
|
||||
|
||||
# Enhance user privacy slightly (useful for IRC server on TOR or I2P)
|
||||
@@ -160,7 +162,22 @@
|
||||
;OperServerMode = no
|
||||
|
||||
# Use PAM if ngIRCd has been compiled with support for it.
|
||||
;PAM = no
|
||||
# Users identified using PAM are registered without the "~" character
|
||||
# prepended to their user name.
|
||||
;PAM = yes
|
||||
|
||||
# When PAM is enabled, all clients are required to be authenticated
|
||||
# using PAM; connecting to the server without successful PAM
|
||||
# authentication isn't possible.
|
||||
# If this option is set, clients not sending a password are still
|
||||
# allowed to connect: they won't become "identified" and keep the "~"
|
||||
# character prepended to their supplied user name.
|
||||
# Please note: To make some use of this behavior, it most probably
|
||||
# isn't useful to enable "Ident", "PAM" and "PAMIsOptional" at the
|
||||
# same time, because you wouldn't be able to distinguish between
|
||||
# Ident'ified and PAM-authenticated users: both don't have a "~"
|
||||
# character prepended to their respective user names!
|
||||
;PAMIsOptional = no
|
||||
|
||||
# Allow Pre-Defined Channels only (see Section [Channels])
|
||||
;PredefChannelsOnly = no
|
||||
|
@@ -132,9 +132,8 @@ the pidfile resides in must be writable by the ngIRCd user and exist in the
|
||||
chroot directory (if configured, see above).
|
||||
.TP
|
||||
\fBPorts\fR (list of numbers)
|
||||
Ports on which the server should listen. There may be more than one port,
|
||||
separated with commas (","). Default: 6667, unless \fBSSL_Ports\fR are also
|
||||
specified.
|
||||
Ports on which the server should listen for unencrypted connections. There
|
||||
may be more than one port, separated with commas (","). Default: 6667.
|
||||
.TP
|
||||
\fBServerGID\fR (string or number)
|
||||
Group ID under which the ngIRCd should run; you can use the name of the
|
||||
@@ -244,6 +243,8 @@ Default: yes.
|
||||
\fBIdent\fR (boolean)
|
||||
If ngIRCd is compiled with IDENT support this can be used to disable IDENT
|
||||
lookups at run time.
|
||||
Users identified using IDENT are registered without the "~" character
|
||||
prepended to their user name.
|
||||
Default: yes.
|
||||
.TP
|
||||
\fBMorePrivacy\fR (boolean)
|
||||
@@ -274,8 +275,23 @@ only enable it if you have ircd-irc2 servers in your IRC network.
|
||||
If ngIRCd is compiled with PAM support this can be used to disable all calls
|
||||
to the PAM library at runtime; all users connecting without password are
|
||||
allowed to connect, all passwords given will fail.
|
||||
Users identified using PAM are registered without the "~" character
|
||||
prepended to their user name.
|
||||
Default: yes.
|
||||
.TP
|
||||
\fBPAMIsOptional\fR (boolean)
|
||||
When PAM is enabled, all clients are required to be authenticated using PAM;
|
||||
connecting to the server without successful PAM authentication isn't possible.
|
||||
If this option is set, clients not sending a password are still allowed to
|
||||
connect: they won't become "identified" and keep the "~" character prepended
|
||||
to their supplied user name.
|
||||
Please note:
|
||||
To make some use of this behavior, it most probably isn't useful to enable
|
||||
"Ident", "PAM" and "PAMIsOptional" at the same time, because you wouldn't be
|
||||
able to distinguish between Ident'ified and PAM-authenticated users: both
|
||||
don't have a "~" character prepended to their respective user names!
|
||||
Default: no.
|
||||
.TP
|
||||
\fBPredefChannelsOnly\fR (boolean)
|
||||
If enabled, no new channels can be created. Useful if you do not want to have
|
||||
other channels than those defined in [Channel] sections in the configuration
|
||||
|
@@ -32,7 +32,9 @@ ng_ipaddr_init(ng_ipaddr_t *addr, const char *ip_str, UINT16 port)
|
||||
assert(ip_str);
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
#ifdef AI_NUMERICHOST
|
||||
hints.ai_flags = AI_NUMERICHOST;
|
||||
#endif
|
||||
#ifndef WANT_IPV6 /* do not convert ipv6 addresses */
|
||||
hints.ai_family = AF_INET;
|
||||
#endif
|
||||
|
@@ -18,20 +18,21 @@ LINTARGS = -weak -warnunixlib +unixlib -booltype BOOLEAN \
|
||||
|
||||
sbin_PROGRAMS = ngircd
|
||||
|
||||
ngircd_SOURCES = ngircd.c array.c channel.c client.c conf.c conn.c conn-func.c \
|
||||
conn-ssl.c conn-zip.c hash.c io.c irc.c irc-channel.c irc-info.c irc-login.c \
|
||||
irc-mode.c irc-op.c irc-oper.c irc-server.c irc-write.c lists.c log.c \
|
||||
match.c op.c numeric.c pam.c parse.c proc.c resolve.c sighandlers.c
|
||||
ngircd_SOURCES = ngircd.c array.c channel.c class.c client.c conf.c conn.c \
|
||||
conn-func.c conn-ssl.c conn-zip.c hash.c io.c irc.c irc-channel.c \
|
||||
irc-info.c irc-login.c irc-mode.c irc-op.c irc-oper.c irc-server.c \
|
||||
irc-write.c lists.c log.c match.c op.c numeric.c pam.c parse.c \
|
||||
proc.c resolve.c sighandlers.c
|
||||
|
||||
ngircd_LDFLAGS = -L../portab -L../tool -L../ipaddr
|
||||
|
||||
ngircd_LDADD = -lngportab -lngtool -lngipaddr
|
||||
|
||||
noinst_HEADERS = ngircd.h array.h channel.h client.h conf.h conf-ssl.h conn.h \
|
||||
conn-func.h conn-ssl.h conn-zip.h hash.h io.h irc.h irc-channel.h \
|
||||
irc-info.h irc-login.h irc-mode.h irc-op.h irc-oper.h irc-server.h \
|
||||
irc-write.h lists.h log.h match.h numeric.h op.h pam.h parse.h proc.h \
|
||||
resolve.h sighandlers.h defines.h messages.h
|
||||
noinst_HEADERS = ngircd.h array.h channel.h class.h client.h conf.h \
|
||||
conf-ssl.h conn.h conn-func.h conn-ssl.h conn-zip.h hash.h io.h \
|
||||
irc.h irc-channel.h irc-info.h irc-login.h irc-mode.h irc-op.h \
|
||||
irc-oper.h irc-server.h irc-write.h lists.h log.h match.h numeric.h \
|
||||
op.h pam.h parse.h proc.h resolve.h sighandlers.h defines.h messages.h
|
||||
|
||||
clean-local:
|
||||
rm -f check-version check-help lint.out
|
||||
|
@@ -84,7 +84,7 @@ extern void* array_get PARAMS((array* a, size_t membersize, size_t pos));
|
||||
/* free the contents of this array. */
|
||||
extern void array_free PARAMS((array* a));
|
||||
|
||||
/* overwrite array with zeroes before free */
|
||||
/* overwrite array with zeros before free */
|
||||
extern void array_free_wipe PARAMS((array* a));
|
||||
|
||||
/* return pointer to first element in this array */
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
|
||||
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -87,6 +87,14 @@ Channel_GetListBans(CHANNEL *c)
|
||||
}
|
||||
|
||||
|
||||
GLOBAL struct list_head *
|
||||
Channel_GetListExcepts(CHANNEL *c)
|
||||
{
|
||||
assert(c != NULL);
|
||||
return &c->list_excepts;
|
||||
}
|
||||
|
||||
|
||||
GLOBAL struct list_head *
|
||||
Channel_GetListInvites(CHANNEL *c)
|
||||
{
|
||||
@@ -110,9 +118,12 @@ Channel_InitPredefined( void )
|
||||
assert(channel_count == 0 || conf_chan != NULL);
|
||||
|
||||
for (i = 0; i < channel_count; i++, conf_chan++) {
|
||||
if (!conf_chan->name[0] || !Channel_IsValidName(conf_chan->name)) {
|
||||
Log(LOG_ERR, "Can't create pre-defined channel: invalid name: \"%s\"",
|
||||
conf_chan->name);
|
||||
if (!conf_chan->name[0])
|
||||
continue;
|
||||
if (!Channel_IsValidName(conf_chan->name)) {
|
||||
Log(LOG_ERR,
|
||||
"Can't create pre-defined channel: invalid name: \"%s\"",
|
||||
conf_chan->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -158,6 +169,7 @@ Free_Channel(CHANNEL *chan)
|
||||
array_free(&chan->topic);
|
||||
array_free(&chan->keyfile);
|
||||
Lists_Free(&chan->list_bans);
|
||||
Lists_Free(&chan->list_excepts);
|
||||
Lists_Free(&chan->list_invites);
|
||||
|
||||
free(chan);
|
||||
@@ -349,20 +361,31 @@ Channel_Quit( CLIENT *Client, const char *Reason )
|
||||
} /* Channel_Quit */
|
||||
|
||||
|
||||
/**
|
||||
* Get number of channels this server knows and that are "visible" to
|
||||
* the given client. If no client is given, all channels will be counted.
|
||||
*
|
||||
* @param Client The client to check or NULL.
|
||||
* @return Number of channels visible to the client.
|
||||
*/
|
||||
GLOBAL unsigned long
|
||||
Channel_Count( void )
|
||||
Channel_CountVisible (CLIENT *Client)
|
||||
{
|
||||
CHANNEL *c;
|
||||
unsigned long count = 0;
|
||||
|
||||
c = My_Channels;
|
||||
while( c )
|
||||
{
|
||||
count++;
|
||||
while(c) {
|
||||
if (Client) {
|
||||
if (!strchr(Channel_Modes(c), 's')
|
||||
|| Channel_IsMemberOf(c, Client))
|
||||
count++;
|
||||
} else
|
||||
count++;
|
||||
c = c->next;
|
||||
}
|
||||
return count;
|
||||
} /* Channel_Count */
|
||||
}
|
||||
|
||||
|
||||
GLOBAL unsigned long
|
||||
@@ -774,6 +797,13 @@ Channel_SetMaxUsers(CHANNEL *Chan, unsigned long Count)
|
||||
} /* Channel_SetMaxUsers */
|
||||
|
||||
|
||||
/**
|
||||
* Check if a client is allowed to send to a specific channel.
|
||||
*
|
||||
* @param Chan The channel to check.
|
||||
* @param From The client that wants to send.
|
||||
* @return true if the client is allowed to send, false otherwise.
|
||||
*/
|
||||
static bool
|
||||
Can_Send_To_Channel(CHANNEL *Chan, CLIENT *From)
|
||||
{
|
||||
@@ -808,6 +838,9 @@ Can_Send_To_Channel(CHANNEL *Chan, CLIENT *From)
|
||||
if (strchr(Channel_Modes(Chan), 'm'))
|
||||
return false;
|
||||
|
||||
if (Lists_Check(&Chan->list_excepts, From))
|
||||
return true;
|
||||
|
||||
return !Lists_Check(&Chan->list_bans, From);
|
||||
}
|
||||
|
||||
@@ -999,8 +1032,17 @@ GLOBAL bool
|
||||
Channel_AddBan(CHANNEL *c, const char *mask )
|
||||
{
|
||||
struct list_head *h = Channel_GetListBans(c);
|
||||
LogDebug("Adding \"%s\" to \"%s\" %s list", mask, Channel_Name(c), "ban");
|
||||
return Lists_Add(h, mask, false);
|
||||
LogDebug("Adding \"%s\" to \"%s\" ban list", mask, Channel_Name(c));
|
||||
return Lists_Add(h, mask, false, NULL);
|
||||
}
|
||||
|
||||
|
||||
GLOBAL bool
|
||||
Channel_AddExcept(CHANNEL *c, const char *mask )
|
||||
{
|
||||
struct list_head *h = Channel_GetListExcepts(c);
|
||||
LogDebug("Adding \"%s\" to \"%s\" exception list", mask, Channel_Name(c));
|
||||
return Lists_Add(h, mask, false, NULL);
|
||||
}
|
||||
|
||||
|
||||
@@ -1008,30 +1050,31 @@ GLOBAL bool
|
||||
Channel_AddInvite(CHANNEL *c, const char *mask, bool onlyonce)
|
||||
{
|
||||
struct list_head *h = Channel_GetListInvites(c);
|
||||
LogDebug("Adding \"%s\" to \"%s\" %s list", mask, Channel_Name(c), "invite");
|
||||
return Lists_Add(h, mask, onlyonce);
|
||||
LogDebug("Adding \"%s\" to \"%s\" invite list", mask, Channel_Name(c));
|
||||
return Lists_Add(h, mask, onlyonce, NULL);
|
||||
}
|
||||
|
||||
|
||||
static bool
|
||||
ShowInvitesBans(struct list_head *head, CLIENT *Client, CHANNEL *Channel, bool invite)
|
||||
ShowChannelList(struct list_head *head, CLIENT *Client, CHANNEL *Channel,
|
||||
char *msg, char *msg_end)
|
||||
{
|
||||
struct list_elem *e;
|
||||
char *msg = invite ? RPL_INVITELIST_MSG : RPL_BANLIST_MSG;
|
||||
char *msg_end;
|
||||
|
||||
assert( Client != NULL );
|
||||
assert( Channel != NULL );
|
||||
assert (Client != NULL);
|
||||
assert (Channel != NULL);
|
||||
|
||||
e = Lists_GetFirst(head);
|
||||
while (e) {
|
||||
if( ! IRC_WriteStrClient( Client, msg, Client_ID( Client ),
|
||||
Channel_Name( Channel ), Lists_GetMask(e) )) return DISCONNECTED;
|
||||
if (!IRC_WriteStrClient(Client, msg, Client_ID(Client),
|
||||
Channel_Name(Channel),
|
||||
Lists_GetMask(e)))
|
||||
return DISCONNECTED;
|
||||
e = Lists_GetNext(e);
|
||||
}
|
||||
|
||||
msg_end = invite ? RPL_ENDOFINVITELIST_MSG : RPL_ENDOFBANLIST_MSG;
|
||||
return IRC_WriteStrClient( Client, msg_end, Client_ID( Client ), Channel_Name( Channel ));
|
||||
return IRC_WriteStrClient(Client, msg_end, Client_ID(Client),
|
||||
Channel_Name(Channel));
|
||||
}
|
||||
|
||||
|
||||
@@ -1043,7 +1086,21 @@ Channel_ShowBans( CLIENT *Client, CHANNEL *Channel )
|
||||
assert( Channel != NULL );
|
||||
|
||||
h = Channel_GetListBans(Channel);
|
||||
return ShowInvitesBans(h, Client, Channel, false);
|
||||
return ShowChannelList(h, Client, Channel, RPL_BANLIST_MSG,
|
||||
RPL_ENDOFBANLIST_MSG);
|
||||
}
|
||||
|
||||
|
||||
GLOBAL bool
|
||||
Channel_ShowExcepts( CLIENT *Client, CHANNEL *Channel )
|
||||
{
|
||||
struct list_head *h;
|
||||
|
||||
assert( Channel != NULL );
|
||||
|
||||
h = Channel_GetListExcepts(Channel);
|
||||
return ShowChannelList(h, Client, Channel, RPL_EXCEPTLIST_MSG,
|
||||
RPL_ENDOFEXCEPTLIST_MSG);
|
||||
}
|
||||
|
||||
|
||||
@@ -1055,7 +1112,8 @@ Channel_ShowInvites( CLIENT *Client, CHANNEL *Channel )
|
||||
assert( Channel != NULL );
|
||||
|
||||
h = Channel_GetListInvites(Channel);
|
||||
return ShowInvitesBans(h, Client, Channel, true);
|
||||
return ShowChannelList(h, Client, Channel, RPL_INVITELIST_MSG,
|
||||
RPL_ENDOFINVITELIST_MSG);
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
|
||||
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -38,6 +38,7 @@ typedef struct _CHANNEL
|
||||
char key[CLIENT_PASS_LEN]; /* Channel key ("password", mode "k" ) */
|
||||
unsigned long maxusers; /* Maximum number of members (mode "l") */
|
||||
struct list_head list_bans; /* list head of banned users */
|
||||
struct list_head list_excepts; /* list head of (ban) exception list */
|
||||
struct list_head list_invites; /* list head of invited users */
|
||||
array keyfile; /* Name of the channel key file */
|
||||
} CHANNEL;
|
||||
@@ -58,6 +59,7 @@ typedef POINTER CL2CHAN;
|
||||
#endif
|
||||
|
||||
GLOBAL struct list_head *Channel_GetListBans PARAMS((CHANNEL *c));
|
||||
GLOBAL struct list_head *Channel_GetListExcepts PARAMS((CHANNEL *c));
|
||||
GLOBAL struct list_head *Channel_GetListInvites PARAMS((CHANNEL *c));
|
||||
|
||||
GLOBAL void Channel_Init PARAMS(( void ));
|
||||
@@ -72,7 +74,7 @@ GLOBAL void Channel_Quit PARAMS(( CLIENT *Client, const char *Reason ));
|
||||
GLOBAL void Channel_Kick PARAMS((CLIENT *Peer, CLIENT *Target, CLIENT *Origin,
|
||||
const char *Name, const char *Reason));
|
||||
|
||||
GLOBAL unsigned long Channel_Count PARAMS(( void ));
|
||||
GLOBAL unsigned long Channel_CountVisible PARAMS((CLIENT *Client));
|
||||
GLOBAL unsigned long Channel_MemberCount PARAMS(( CHANNEL *Chan ));
|
||||
GLOBAL int Channel_CountForUser PARAMS(( CLIENT *Client ));
|
||||
|
||||
@@ -123,10 +125,13 @@ GLOBAL char *Channel_TopicWho PARAMS(( CHANNEL *Chan ));
|
||||
GLOBAL unsigned int Channel_CreationTime PARAMS(( CHANNEL *Chan ));
|
||||
#endif
|
||||
|
||||
GLOBAL bool Channel_AddInvite PARAMS((CHANNEL *c, const char *Mask, bool OnlyOnce ));
|
||||
GLOBAL bool Channel_AddBan PARAMS((CHANNEL *c, const char *Mask ));
|
||||
GLOBAL bool Channel_AddBan PARAMS((CHANNEL *c, const char *Mask));
|
||||
GLOBAL bool Channel_AddExcept PARAMS((CHANNEL *c, const char *Mask));
|
||||
GLOBAL bool Channel_AddInvite PARAMS((CHANNEL *c, const char *Mask,
|
||||
bool OnlyOnce));
|
||||
|
||||
GLOBAL bool Channel_ShowBans PARAMS((CLIENT *client, CHANNEL *c));
|
||||
GLOBAL bool Channel_ShowExcepts PARAMS((CLIENT *client, CHANNEL *c));
|
||||
GLOBAL bool Channel_ShowInvites PARAMS((CLIENT *client, CHANNEL *c));
|
||||
|
||||
GLOBAL void Channel_LogServer PARAMS((const char *msg));
|
||||
|
143
src/ngircd/class.c
Normal file
143
src/ngircd/class.c
Normal file
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* Please read the file COPYING, README and AUTHORS for more information.
|
||||
*/
|
||||
|
||||
#include "portab.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* User class management.
|
||||
*/
|
||||
|
||||
#include "imp.h"
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "defines.h"
|
||||
#include "array.h"
|
||||
#include "conn.h"
|
||||
#include "client.h"
|
||||
#include "lists.h"
|
||||
#include "match.h"
|
||||
#include "stdio.h"
|
||||
|
||||
#include "exp.h"
|
||||
#include "class.h"
|
||||
|
||||
struct list_head My_Classes[CLASS_COUNT];
|
||||
|
||||
char Reject_Reason[COMMAND_LEN];
|
||||
|
||||
GLOBAL void
|
||||
Class_Init(void)
|
||||
{
|
||||
memset(My_Classes, 0, sizeof(My_Classes));
|
||||
}
|
||||
|
||||
GLOBAL void
|
||||
Class_Exit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < CLASS_COUNT; Lists_Free(&My_Classes[i++]));
|
||||
}
|
||||
|
||||
GLOBAL char *
|
||||
Class_GetMemberReason(const int Class, CLIENT *Client)
|
||||
{
|
||||
char *reason;
|
||||
|
||||
assert(Class < CLASS_COUNT);
|
||||
assert(Client != NULL);
|
||||
|
||||
reason = Lists_CheckReason(&My_Classes[Class], Client);
|
||||
if (!reason)
|
||||
return NULL;
|
||||
|
||||
if (!*reason)
|
||||
reason = "listed";
|
||||
|
||||
switch(Class) {
|
||||
case CLASS_GLINE:
|
||||
snprintf(Reject_Reason, sizeof(Reject_Reason),
|
||||
"\"%s\" (G-Line)", reason);
|
||||
return Reject_Reason;
|
||||
case CLASS_KLINE:
|
||||
snprintf(Reject_Reason, sizeof(Reject_Reason),
|
||||
"\"%s\" (K-Line)", reason);
|
||||
return Reject_Reason;
|
||||
}
|
||||
return reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a client is banned from this server: GLINE, KLINE.
|
||||
*
|
||||
* If a client isn't allowed to connect, it will be disconnected again.
|
||||
*
|
||||
* @param Client The client to check.
|
||||
* @return CONNECTED if client is allowed to join, DISCONNECTED if not.
|
||||
*/
|
||||
GLOBAL bool
|
||||
Class_HandleServerBans(CLIENT *Client)
|
||||
{
|
||||
char *rejectptr;
|
||||
|
||||
assert(Client != NULL);
|
||||
|
||||
rejectptr = Class_GetMemberReason(CLASS_GLINE, Client);
|
||||
if (!rejectptr)
|
||||
rejectptr = Class_GetMemberReason(CLASS_KLINE, Client);
|
||||
if (rejectptr) {
|
||||
Client_Reject(Client, rejectptr, true);
|
||||
return DISCONNECTED;
|
||||
}
|
||||
|
||||
return CONNECTED;
|
||||
}
|
||||
|
||||
|
||||
GLOBAL bool
|
||||
Class_AddMask(const int Class, const char *Mask, time_t ValidUntil,
|
||||
const char *Reason)
|
||||
{
|
||||
assert(Class < CLASS_COUNT);
|
||||
assert(Mask != NULL);
|
||||
assert(Reason != NULL);
|
||||
|
||||
return Lists_Add(&My_Classes[Class], Lists_MakeMask(Mask),
|
||||
ValidUntil, Reason);
|
||||
}
|
||||
|
||||
GLOBAL void
|
||||
Class_DeleteMask(const int Class, const char *Mask)
|
||||
{
|
||||
assert(Class < CLASS_COUNT);
|
||||
assert(Mask != NULL);
|
||||
|
||||
Lists_Del(&My_Classes[Class], Lists_MakeMask(Mask));
|
||||
}
|
||||
|
||||
GLOBAL struct list_head *
|
||||
Class_GetList(const int Class)
|
||||
{
|
||||
assert(Class < CLASS_COUNT);
|
||||
|
||||
return &My_Classes[Class];
|
||||
}
|
||||
|
||||
GLOBAL void
|
||||
Class_Expire(void)
|
||||
{
|
||||
Lists_Expire(&My_Classes[CLASS_GLINE], "G-Line");
|
||||
Lists_Expire(&My_Classes[CLASS_KLINE], "K-Line");
|
||||
}
|
||||
|
||||
/* -eof- */
|
41
src/ngircd/class.h
Normal file
41
src/ngircd/class.h
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
* Please read the file COPYING, README and AUTHORS for more information.
|
||||
*/
|
||||
|
||||
#ifndef __class_h__
|
||||
#define __class_h__
|
||||
|
||||
/**
|
||||
* @file
|
||||
* User class management.
|
||||
*/
|
||||
|
||||
#define CLASS_KLINE 0
|
||||
#define CLASS_GLINE 1
|
||||
|
||||
#define CLASS_COUNT 2
|
||||
|
||||
GLOBAL void Class_Init PARAMS((void));
|
||||
GLOBAL void Class_Exit PARAMS((void));
|
||||
|
||||
GLOBAL bool Class_AddMask PARAMS((const int Class, const char *Mask,
|
||||
const time_t ValidUntil, const char *Reason));
|
||||
GLOBAL void Class_DeleteMask PARAMS((const int Class, const char *Mask));
|
||||
|
||||
GLOBAL char *Class_GetMemberReason PARAMS((const int Class, CLIENT *Client));
|
||||
GLOBAL bool Class_HandleServerBans PARAMS((CLIENT *Client));
|
||||
|
||||
GLOBAL struct list_head *Class_GetList PARAMS((const int Class));
|
||||
|
||||
GLOBAL void Class_Expire PARAMS((void));
|
||||
|
||||
#endif /* __class_h__ */
|
||||
|
||||
/* -eof- */
|
@@ -186,7 +186,6 @@ Init_New_Client(CONN_ID Idx, CLIENT *Introducer, CLIENT *TopServer,
|
||||
|
||||
assert(Idx >= NONE);
|
||||
assert(Introducer != NULL);
|
||||
assert(Hostname != NULL);
|
||||
|
||||
client = New_Client_Struct();
|
||||
if (!client)
|
||||
@@ -313,16 +312,29 @@ Client_Destroy( CLIENT *Client, const char *LogMsg, const char *FwdMsg, bool Sen
|
||||
} /* Client_Destroy */
|
||||
|
||||
|
||||
/**
|
||||
* Set client hostname.
|
||||
*
|
||||
* If global hostname cloaking is in effect, don't set the real hostname
|
||||
* but the configured one.
|
||||
*
|
||||
* @param Client The client of which the hostname should be set.
|
||||
* @param Hostname The new hostname.
|
||||
*/
|
||||
GLOBAL void
|
||||
Client_SetHostname( CLIENT *Client, const char *Hostname )
|
||||
{
|
||||
assert( Client != NULL );
|
||||
assert( Hostname != NULL );
|
||||
assert(Client != NULL);
|
||||
assert(Hostname != NULL);
|
||||
|
||||
if (strlen(Conf_CloakHost)) {
|
||||
strlcpy( Client->host, Conf_CloakHost, sizeof( Client->host ));
|
||||
LogDebug("Updating hostname of \"%s\": \"%s\" -> \"%s\"",
|
||||
Client_ID(Client), Client->host, Conf_CloakHost);
|
||||
strlcpy(Client->host, Conf_CloakHost, sizeof(Client->host));
|
||||
} else {
|
||||
strlcpy( Client->host, Hostname, sizeof( Client->host ));
|
||||
LogDebug("Updating hostname of \"%s\": \"%s\" -> \"%s\"",
|
||||
Client_ID(Client), Client->host, Hostname);
|
||||
strlcpy(Client->host, Hostname, sizeof(Client->host));
|
||||
}
|
||||
} /* Client_SetHostname */
|
||||
|
||||
@@ -768,7 +780,7 @@ Client_NextHop( CLIENT *Client )
|
||||
* Return ID of a client: "client!user@host"
|
||||
* This client ID is used for IRC prefixes, for example.
|
||||
* Please note that this function uses a global static buffer, so you can't
|
||||
* nest invocations without overwriting erlier results!
|
||||
* nest invocations without overwriting earlier results!
|
||||
* @param Client Pointer to client structure
|
||||
* @return Pointer to global buffer containing the client ID
|
||||
*/
|
||||
@@ -793,7 +805,7 @@ Client_Mask( CLIENT *Client )
|
||||
* Return ID of a client with cloaked hostname: "client!user@server-name"
|
||||
* This client ID is used for IRC prefixes, for example.
|
||||
* Please note that this function uses a global static buffer, so you can't
|
||||
* nest invocations without overwriting erlier results!
|
||||
* nest invocations without overwriting earlier results!
|
||||
* If the client has not enabled cloaking, the real hostname is used.
|
||||
* @param Client Pointer to client structure
|
||||
* @return Pointer to global buffer containing the client ID
|
||||
@@ -847,23 +859,37 @@ Client_Away( CLIENT *Client )
|
||||
} /* Client_Away */
|
||||
|
||||
|
||||
/**
|
||||
* Make sure that a given nickname is valid.
|
||||
*
|
||||
* If the nickname is not valid for the given client, this function sends back
|
||||
* the appropriate error messages.
|
||||
*
|
||||
* @param Client Client that wants to change the nickname.
|
||||
* @param Nick New nick name.
|
||||
* @returns true if nickname is valid, false otherwise.
|
||||
*/
|
||||
GLOBAL bool
|
||||
Client_CheckNick( CLIENT *Client, char *Nick )
|
||||
Client_CheckNick(CLIENT *Client, char *Nick)
|
||||
{
|
||||
assert( Client != NULL );
|
||||
assert( Nick != NULL );
|
||||
assert(Client != NULL);
|
||||
assert(Nick != NULL);
|
||||
|
||||
if (! Client_IsValidNick( Nick ))
|
||||
{
|
||||
IRC_WriteStrClient( Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID( Client ), Nick );
|
||||
if (!Client_IsValidNick(Nick)) {
|
||||
if (strlen(Nick ) >= Conf_MaxNickLength)
|
||||
IRC_WriteStrClient(Client, ERR_NICKNAMETOOLONG_MSG,
|
||||
Client_ID(Client), Nick,
|
||||
Conf_MaxNickLength - 1);
|
||||
else
|
||||
IRC_WriteStrClient(Client, ERR_ERRONEUSNICKNAME_MSG,
|
||||
Client_ID(Client), Nick);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Nick bereits vergeben? */
|
||||
if( Client_Search( Nick ))
|
||||
{
|
||||
/* den Nick gibt es bereits */
|
||||
IRC_WriteStrClient( Client, ERR_NICKNAMEINUSE_MSG, Client_ID( Client ), Nick );
|
||||
/* Nickname already registered? */
|
||||
if (Client_Search(Nick)) {
|
||||
IRC_WriteStrClient(Client, ERR_NICKNAMEINUSE_MSG,
|
||||
Client_ID(Client), Nick);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1019,23 +1045,31 @@ Client_MyMaxUserCount( void )
|
||||
} /* Client_MyMaxUserCount */
|
||||
|
||||
|
||||
/**
|
||||
* Check that a given nickname is valid.
|
||||
*
|
||||
* @param Nick the nickname to check.
|
||||
* @returns true if nickname is valid, false otherwise.
|
||||
*/
|
||||
GLOBAL bool
|
||||
Client_IsValidNick( const char *Nick )
|
||||
Client_IsValidNick(const char *Nick)
|
||||
{
|
||||
const char *ptr;
|
||||
static const char goodchars[] = ";0123456789-";
|
||||
|
||||
assert( Nick != NULL );
|
||||
assert (Nick != NULL);
|
||||
|
||||
if( Nick[0] == '#' ) return false;
|
||||
if( strchr( goodchars, Nick[0] )) return false;
|
||||
if( strlen( Nick ) >= Conf_MaxNickLength) return false;
|
||||
if (strchr(goodchars, Nick[0]))
|
||||
return false;
|
||||
if (strlen(Nick ) >= Conf_MaxNickLength)
|
||||
return false;
|
||||
|
||||
ptr = Nick;
|
||||
while( *ptr )
|
||||
{
|
||||
if (( *ptr < 'A' ) && ( ! strchr( goodchars, *ptr ))) return false;
|
||||
if ( *ptr > '}' ) return false;
|
||||
while (*ptr) {
|
||||
if (*ptr < 'A' && !strchr(goodchars, *ptr ))
|
||||
return false;
|
||||
if (*ptr > '}')
|
||||
return false;
|
||||
ptr++;
|
||||
}
|
||||
|
||||
@@ -1075,6 +1109,39 @@ Client_StartTime(CLIENT *Client)
|
||||
} /* Client_Uptime */
|
||||
|
||||
|
||||
/**
|
||||
* Reject a client when logging in.
|
||||
*
|
||||
* This function is called when a client isn't allowed to connect to this
|
||||
* server. Possible reasons are bad server password, bad PAM password,
|
||||
* or that the client is G/K-Line'd.
|
||||
*
|
||||
* After calling this function, the client isn't connected any more.
|
||||
*
|
||||
* @param Client The client to reject.
|
||||
* @param Reason The reason why the client has been rejected.
|
||||
* @param InformClient If true, send the exact reason to the client.
|
||||
*/
|
||||
GLOBAL void
|
||||
Client_Reject(CLIENT *Client, const char *Reason, bool InformClient)
|
||||
{
|
||||
char info[COMMAND_LEN];
|
||||
|
||||
assert(Client != NULL);
|
||||
assert(Reason != NULL);
|
||||
|
||||
if (InformClient)
|
||||
snprintf(info, sizeof(info), "Access denied: %s", Reason);
|
||||
else
|
||||
strcpy(info, "Access denied: Bad password?");
|
||||
|
||||
Log(LOG_ERR,
|
||||
"User \"%s\" rejected (connection %d): %s!",
|
||||
Client_Mask(Client), Client_Conn(Client), Reason);
|
||||
Conn_Close(Client_Conn(Client), Reason, info, true);
|
||||
}
|
||||
|
||||
|
||||
static unsigned long
|
||||
Count( CLIENT_TYPE Type )
|
||||
{
|
||||
|
@@ -163,6 +163,9 @@ GLOBAL void Client_RegisterWhowas PARAMS(( CLIENT *Client ));
|
||||
|
||||
GLOBAL const char *Client_TypeText PARAMS((CLIENT *Client));
|
||||
|
||||
GLOBAL void Client_Reject PARAMS((CLIENT *Client, const char *Reason,
|
||||
bool InformClient));
|
||||
|
||||
#ifdef DEBUG
|
||||
GLOBAL void Client_DebugDump PARAMS((void));
|
||||
#endif
|
||||
|
@@ -55,8 +55,6 @@ static bool Use_Log = true, Using_MotdFile = true;
|
||||
static CONF_SERVER New_Server;
|
||||
static int New_Server_Idx;
|
||||
|
||||
static size_t Conf_Oper_Count;
|
||||
static size_t Conf_Channel_Count;
|
||||
static char Conf_MotdFile[FNAME_LEN];
|
||||
|
||||
static void Set_Defaults PARAMS(( bool InitServers ));
|
||||
@@ -265,18 +263,18 @@ static void
|
||||
opers_puts(void)
|
||||
{
|
||||
struct Conf_Oper *op;
|
||||
size_t len;
|
||||
size_t count, i;
|
||||
|
||||
len = array_length(&Conf_Opers, sizeof(*op));
|
||||
count = array_length(&Conf_Opers, sizeof(*op));
|
||||
op = array_start(&Conf_Opers);
|
||||
while (len--) {
|
||||
assert(op->name[0]);
|
||||
for (i = 0; i < count; i++, op++) {
|
||||
if (!op->name[0])
|
||||
continue;
|
||||
|
||||
puts("[OPERATOR]");
|
||||
printf(" Name = %s\n", op->name);
|
||||
printf(" Password = %s\n", op->pwd);
|
||||
printf(" Mask = %s\n\n", op->mask ? op->mask : "");
|
||||
op++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -375,6 +373,7 @@ Conf_Test( void )
|
||||
printf(" OperServerMode = %s\n", yesno_to_str(Conf_OperServerMode));
|
||||
#ifdef PAM
|
||||
printf(" PAM = %s\n", yesno_to_str(Conf_PAM));
|
||||
printf(" PAMIsOptional = %s\n", yesno_to_str(Conf_PAMIsOptional));
|
||||
#endif
|
||||
printf(" PredefChannelsOnly = %s\n", yesno_to_str(Conf_PredefChannelsOnly));
|
||||
#ifndef STRICT_RFC
|
||||
@@ -699,6 +698,7 @@ Set_Defaults(bool InitServers)
|
||||
#else
|
||||
Conf_PAM = false;
|
||||
#endif
|
||||
Conf_PAMIsOptional = false;
|
||||
Conf_PredefChannelsOnly = false;
|
||||
#ifdef SYSLOG
|
||||
Conf_ScrubCTCP = false;
|
||||
@@ -709,10 +709,6 @@ Set_Defaults(bool InitServers)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Initialize IRC operators and channels */
|
||||
Conf_Oper_Count = 0;
|
||||
Conf_Channel_Count = 0;
|
||||
|
||||
/* Initialize server configuration structures */
|
||||
if (InitServers) {
|
||||
for (i = 0; i < MAX_SERVERS;
|
||||
@@ -787,6 +783,7 @@ Read_Config( bool ngircd_starting )
|
||||
char section[LINE_LEN], str[LINE_LEN], *var, *arg, *ptr;
|
||||
const UINT16 defaultport = 6667;
|
||||
int line, i, n;
|
||||
size_t count;
|
||||
FILE *fd;
|
||||
|
||||
/* Open configuration file */
|
||||
@@ -887,12 +884,30 @@ Read_Config( bool ngircd_starting )
|
||||
else New_Server_Idx = i;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcasecmp(section, "[CHANNEL]") == 0) {
|
||||
Conf_Channel_Count++;
|
||||
count = array_length(&Conf_Channels,
|
||||
sizeof(struct Conf_Channel));
|
||||
if (!array_alloc(&Conf_Channels,
|
||||
sizeof(struct Conf_Channel),
|
||||
count)) {
|
||||
Config_Error(LOG_ERR,
|
||||
"Could not allocate memory for new operator (line %d)",
|
||||
line);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcasecmp(section, "[OPERATOR]") == 0) {
|
||||
Conf_Oper_Count++;
|
||||
count = array_length(&Conf_Opers,
|
||||
sizeof(struct Conf_Oper));
|
||||
if (!array_alloc(&Conf_Opers,
|
||||
sizeof(struct Conf_Oper),
|
||||
count)) {
|
||||
Config_Error(LOG_ERR,
|
||||
"Could not allocate memory for new channel (line &d)",
|
||||
line);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -978,17 +993,21 @@ Read_Config( bool ngircd_starting )
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether an string argument is true or false.
|
||||
* Check whether a string argument is "true" or "false".
|
||||
*
|
||||
* @param Arg Input string.
|
||||
* @returns true if string has been parsed as "yes"/"true"/"on".
|
||||
* @returns true if the input string has been parsed as "yes", "true"
|
||||
* (case insensitive) or a non-zero integer value.
|
||||
*/
|
||||
static bool
|
||||
Check_ArgIsTrue( const char *Arg )
|
||||
Check_ArgIsTrue(const char *Arg)
|
||||
{
|
||||
if( strcasecmp( Arg, "yes" ) == 0 ) return true;
|
||||
if( strcasecmp( Arg, "true" ) == 0 ) return true;
|
||||
if( atoi( Arg ) != 0 ) return true;
|
||||
if (strcasecmp(Arg, "yes") == 0)
|
||||
return true;
|
||||
if (strcasecmp(Arg, "true") == 0)
|
||||
return true;
|
||||
if (atoi(Arg) != 0)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -1289,7 +1308,9 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
|
||||
else {
|
||||
Conf_GID = (unsigned int)atoi(Arg);
|
||||
if (!Conf_GID && strcmp(Arg, "0"))
|
||||
Config_Error_NaN(Line, Var);
|
||||
Config_Error(LOG_WARNING,
|
||||
"%s, line %d: Value of \"%s\" is not a valid group name or ID!",
|
||||
NGIRCd_ConfFile, Line, Var);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1300,7 +1321,9 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
|
||||
else {
|
||||
Conf_UID = (unsigned int)atoi(Arg);
|
||||
if (!Conf_UID && strcmp(Arg, "0"))
|
||||
Config_Error_NaN(Line, Var);
|
||||
Config_Error(LOG_WARNING,
|
||||
"%s, line %d: Value of \"%s\" is not a valid user name or ID!",
|
||||
NGIRCd_ConfFile, Line, Var);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1483,6 +1506,10 @@ Handle_OPTIONS(int Line, char *Var, char *Arg)
|
||||
WarnPAM(Line);
|
||||
return;
|
||||
}
|
||||
if (strcasecmp(Var, "PAMIsOptional") == 0 ) {
|
||||
Conf_PAMIsOptional = Check_ArgIsTrue(Arg);
|
||||
return;
|
||||
}
|
||||
if (strcasecmp(Var, "PredefChannelsOnly") == 0) {
|
||||
Conf_PredefChannelsOnly = Check_ArgIsTrue(Arg);
|
||||
return;
|
||||
@@ -1580,13 +1607,11 @@ Handle_OPERATOR( int Line, char *Var, char *Arg )
|
||||
assert( Line > 0 );
|
||||
assert( Var != NULL );
|
||||
assert( Arg != NULL );
|
||||
assert( Conf_Oper_Count > 0 );
|
||||
|
||||
op = array_alloc(&Conf_Opers, sizeof(*op), Conf_Oper_Count - 1);
|
||||
if (!op) {
|
||||
Config_Error(LOG_ERR, "Could not allocate memory for operator (%d:%s = %s)", Line, Var, Arg);
|
||||
op = array_get(&Conf_Opers, sizeof(*op),
|
||||
array_length(&Conf_Opers, sizeof(*op)) - 1);
|
||||
if (!op)
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcasecmp(Var, "Name") == 0) {
|
||||
/* Name of IRC operator */
|
||||
@@ -1752,21 +1777,17 @@ static void
|
||||
Handle_CHANNEL(int Line, char *Var, char *Arg)
|
||||
{
|
||||
size_t len;
|
||||
size_t chancount;
|
||||
struct Conf_Channel *chan;
|
||||
|
||||
assert( Line > 0 );
|
||||
assert( Var != NULL );
|
||||
assert( Arg != NULL );
|
||||
assert(Conf_Channel_Count > 0);
|
||||
|
||||
chancount = Conf_Channel_Count - 1;
|
||||
|
||||
chan = array_alloc(&Conf_Channels, sizeof(*chan), chancount);
|
||||
if (!chan) {
|
||||
Config_Error(LOG_ERR, "Could not allocate memory for predefined channel (%d:%s = %s)", Line, Var, Arg);
|
||||
chan = array_get(&Conf_Channels, sizeof(*chan),
|
||||
array_length(&Conf_Channels, sizeof(*chan)) - 1);
|
||||
if (!chan)
|
||||
return;
|
||||
}
|
||||
|
||||
if (strcasecmp(Var, "Name") == 0) {
|
||||
if (!Handle_Channelname(chan, Arg))
|
||||
Config_Error_TooLong(Line, Var);
|
||||
@@ -1913,8 +1934,10 @@ Validate_Config(bool Configtest, bool Rehash)
|
||||
}
|
||||
}
|
||||
Log(LOG_DEBUG,
|
||||
"Configuration: Operators=%d, Servers=%d[%d], Channels=%d",
|
||||
Conf_Oper_Count, servers, servers_once, Conf_Channel_Count);
|
||||
"Configuration: Operators=%ld, Servers=%d[%d], Channels=%ld",
|
||||
array_length(&Conf_Opers, sizeof(struct Conf_Oper)),
|
||||
servers, servers_once,
|
||||
array_length(&Conf_Channels, sizeof(struct Conf_Channel)));
|
||||
#endif
|
||||
|
||||
return config_valid;
|
||||
@@ -2044,7 +2067,7 @@ Init_Server_Struct( CONF_SERVER *Server )
|
||||
|
||||
Proc_InitStruct(&Server->res_stat);
|
||||
Server->conn_id = NONE;
|
||||
memset(&Server->bind_addr, 0, sizeof(&Server->bind_addr));
|
||||
memset(&Server->bind_addr, 0, sizeof(Server->bind_addr));
|
||||
}
|
||||
|
||||
/* -eof- */
|
||||
|
@@ -154,7 +154,7 @@ GLOBAL bool Conf_OperCanMode;
|
||||
/**
|
||||
* If true, mask channel MODE commands of IRC operators to the server.
|
||||
* Background: ircd2 will ignore channel MODE commands if an IRC operator
|
||||
* gives chanel operator privileges to someone without being a channel operator
|
||||
* gives channel operator privileges to someone without being a channel operator
|
||||
* himself. This enables a workaround: it masks the MODE command as coming
|
||||
* from the IRC server and not the IRC operator.
|
||||
*/
|
||||
@@ -184,6 +184,9 @@ GLOBAL bool Conf_NoticeAuth;
|
||||
/** Enable all usage of PAM, even when compiled with support for it */
|
||||
GLOBAL bool Conf_PAM;
|
||||
|
||||
/** Don't require all clients to send a password an to be PAM authenticated */
|
||||
GLOBAL bool Conf_PAMIsOptional;
|
||||
|
||||
/** Disable all CTCP commands except for /me ? */
|
||||
GLOBAL bool Conf_ScrubCTCP;
|
||||
|
||||
|
@@ -30,13 +30,30 @@
|
||||
#include "conn-func.h"
|
||||
|
||||
|
||||
/**
|
||||
* Update "idle timestamp", the time of the last visible user action
|
||||
* (e. g. like sending messages, joining or leaving channels).
|
||||
*
|
||||
* @param Idx Connection index.
|
||||
*/
|
||||
GLOBAL void
|
||||
Conn_UpdateIdle( CONN_ID Idx )
|
||||
Conn_UpdateIdle(CONN_ID Idx)
|
||||
{
|
||||
assert( Idx > NONE );
|
||||
My_Connections[Idx].lastprivmsg = time( NULL );
|
||||
assert(Idx > NONE);
|
||||
My_Connections[Idx].lastprivmsg = time(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update "ping timestamp", the time of the last outgoing PING request.
|
||||
*
|
||||
* @param Idx Connection index.
|
||||
*/
|
||||
GLOBAL void
|
||||
Conn_UpdatePing(CONN_ID Idx)
|
||||
{
|
||||
assert(Idx > NONE);
|
||||
My_Connections[Idx].lastping = time(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get signon time of a connection.
|
||||
@@ -65,35 +82,56 @@ Conn_LastPing( CONN_ID Idx )
|
||||
} /* Conn_LastPing */
|
||||
|
||||
|
||||
/**
|
||||
* Add "penalty time" for a connection.
|
||||
*
|
||||
* During the "penalty time" the socket is ignored completely, no new data
|
||||
* is read. This function only increases the penalty, it is not possible to
|
||||
* decrease the penalty time.
|
||||
*
|
||||
* @param Idex Connection index.
|
||||
* @param Seconds Seconds to add.
|
||||
* @see Conn_ResetPenalty
|
||||
*/
|
||||
GLOBAL void
|
||||
Conn_SetPenalty( CONN_ID Idx, time_t Seconds )
|
||||
Conn_SetPenalty(CONN_ID Idx, time_t Seconds)
|
||||
{
|
||||
/* set Penalty-Delay for a socket.
|
||||
* during the penalty, the socket is ignored completely, no new
|
||||
* data is read. This function only increases the penalty, it is
|
||||
* not possible to decrease the penalty time.
|
||||
*/
|
||||
time_t t;
|
||||
|
||||
assert( Idx > NONE );
|
||||
assert( Seconds >= 0 );
|
||||
|
||||
t = time( NULL ) + Seconds;
|
||||
if (t > My_Connections[Idx].delaytime)
|
||||
assert(Idx > NONE);
|
||||
assert(Seconds >= 0);
|
||||
|
||||
t = time(NULL);
|
||||
if (My_Connections[Idx].delaytime < t)
|
||||
My_Connections[Idx].delaytime = t;
|
||||
|
||||
My_Connections[Idx].delaytime += Seconds;
|
||||
|
||||
#ifdef DEBUG
|
||||
Log(LOG_DEBUG, "Add penalty time on connection %d: %ld second(s).",
|
||||
Idx, (long)Seconds);
|
||||
Log(LOG_DEBUG,
|
||||
"Add penalty time on connection %d: %ld second%s, total %ld second%s.",
|
||||
Idx, (long)Seconds, Seconds != 1 ? "s" : "",
|
||||
My_Connections[Idx].delaytime - t,
|
||||
My_Connections[Idx].delaytime - t != 1 ? "s" : "");
|
||||
#endif
|
||||
} /* Conn_SetPenalty */
|
||||
|
||||
|
||||
/**
|
||||
* Reset the "penalty time" for one connection.
|
||||
*
|
||||
* @param Idx Connection index.
|
||||
* @see Conn_SetPenalty
|
||||
*/
|
||||
GLOBAL void
|
||||
Conn_ResetPenalty( CONN_ID Idx )
|
||||
Conn_ResetPenalty(CONN_ID Idx)
|
||||
{
|
||||
assert( Idx > NONE );
|
||||
assert(Idx > NONE);
|
||||
|
||||
My_Connections[Idx].delaytime = 0;
|
||||
#ifdef DEBUG
|
||||
Log(LOG_DEBUG, "Penalty time on connection %d has been reset.");
|
||||
#endif
|
||||
} /* Conn_ResetPenalty */
|
||||
|
||||
|
||||
|
@@ -29,7 +29,9 @@
|
||||
#endif
|
||||
|
||||
|
||||
GLOBAL void Conn_UpdateIdle PARAMS(( CONN_ID Idx ));
|
||||
GLOBAL void Conn_UpdateIdle PARAMS((CONN_ID Idx));
|
||||
GLOBAL void Conn_UpdatePing PARAMS((CONN_ID Idx));
|
||||
|
||||
GLOBAL time_t Conn_GetSignon PARAMS((CONN_ID Idx));
|
||||
GLOBAL time_t Conn_GetIdle PARAMS(( CONN_ID Idx ));
|
||||
GLOBAL time_t Conn_LastPing PARAMS(( CONN_ID Idx ));
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2010 Alexander Barton <alex@barton.de>
|
||||
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -9,6 +9,8 @@
|
||||
* Please read the file COPYING, README and AUTHORS for more information.
|
||||
*/
|
||||
|
||||
#undef DEBUG_BUFFER
|
||||
|
||||
#define CONN_MODULE
|
||||
|
||||
#include "portab.h"
|
||||
@@ -63,6 +65,7 @@
|
||||
#include "ngircd.h"
|
||||
#include "array.h"
|
||||
#include "client.h"
|
||||
#include "class.h"
|
||||
#include "conf.h"
|
||||
#include "conn-ssl.h"
|
||||
#include "conn-zip.h"
|
||||
@@ -79,8 +82,8 @@
|
||||
#define SERVER_WAIT (NONE - 1)
|
||||
|
||||
#define MAX_COMMANDS 3
|
||||
#define MAX_COMMANDS_SERVER 10
|
||||
#define MAX_COMMANDS_SERVICE MAX_COMMANDS_SERVER
|
||||
#define MAX_COMMANDS_SERVER_MIN 10
|
||||
#define MAX_COMMANDS_SERVICE 10
|
||||
|
||||
|
||||
static bool Handle_Write PARAMS(( CONN_ID Idx ));
|
||||
@@ -367,7 +370,7 @@ cb_clientserver_ssl(int sock, short what)
|
||||
|
||||
|
||||
/**
|
||||
* Initialite connecion module.
|
||||
* Initialize connecion module.
|
||||
*/
|
||||
GLOBAL void
|
||||
Conn_Init( void )
|
||||
@@ -433,12 +436,13 @@ Conn_Exit( void )
|
||||
* they don't hold connections open that the main process wants to close.
|
||||
*/
|
||||
GLOBAL void
|
||||
Conn_CloseAllSockets(void)
|
||||
Conn_CloseAllSockets(int ExceptOf)
|
||||
{
|
||||
CONN_ID idx;
|
||||
|
||||
for(idx = 0; idx < Pool_Size; idx++) {
|
||||
if(My_Connections[idx].sock > NONE)
|
||||
if(My_Connections[idx].sock > NONE &&
|
||||
My_Connections[idx].sock != ExceptOf)
|
||||
close(My_Connections[idx].sock);
|
||||
}
|
||||
}
|
||||
@@ -739,6 +743,9 @@ Conn_Handler(void)
|
||||
Check_Servers();
|
||||
Check_Connections();
|
||||
|
||||
/* Expire outdated class/list items */
|
||||
Class_Expire();
|
||||
|
||||
/* Look for non-empty read buffers ... */
|
||||
for (i = 0; i < Pool_Size; i++) {
|
||||
if ((My_Connections[i].sock > NONE)
|
||||
@@ -929,22 +936,25 @@ Conn_Write( CONN_ID Idx, char *Data, size_t Len )
|
||||
assert( Data != NULL );
|
||||
assert( Len > 0 );
|
||||
|
||||
c = Conn_GetClient(Idx);
|
||||
assert( c != NULL);
|
||||
|
||||
/* Servers do get special write buffer limits, so they can generate
|
||||
* all the messages that are required while peering. */
|
||||
if (Client_Type(c) == CLIENT_SERVER)
|
||||
writebuf_limit = WRITEBUFFER_SLINK_LEN;
|
||||
|
||||
/* Is the socket still open? A previous call to Conn_Write()
|
||||
* may have closed the connection due to a fatal error.
|
||||
* In this case it is sufficient to return an error, as well. */
|
||||
if( My_Connections[Idx].sock <= NONE ) {
|
||||
if (My_Connections[Idx].sock <= NONE) {
|
||||
LogDebug("Skipped write on closed socket (connection %d).", Idx);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Make sure that there still exists a CLIENT structure associated
|
||||
* with this connection and check if this is a server or not: */
|
||||
c = Conn_GetClient(Idx);
|
||||
if (c) {
|
||||
/* Servers do get special write buffer limits, so they can
|
||||
* generate all the messages that are required while peering. */
|
||||
if (Client_Type(c) == CLIENT_SERVER)
|
||||
writebuf_limit = WRITEBUFFER_SLINK_LEN;
|
||||
} else
|
||||
LogDebug("Write on socket without client (connection %d)!?", Idx);
|
||||
|
||||
#ifdef ZLIB
|
||||
if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ZIP )) {
|
||||
/* Compressed link:
|
||||
@@ -1007,7 +1017,7 @@ Conn_Write( CONN_ID Idx, char *Data, size_t Len )
|
||||
GLOBAL void
|
||||
Conn_Close( CONN_ID Idx, const char *LogMsg, const char *FwdMsg, bool InformClient )
|
||||
{
|
||||
/* Close connection. Open pipes of asyncronous resolver
|
||||
/* Close connection. Open pipes of asynchronous resolver
|
||||
* sub-processes are closed down. */
|
||||
|
||||
CLIENT *c;
|
||||
@@ -1216,6 +1226,20 @@ Conn_SyncServerStruct(void)
|
||||
} /* SyncServerStruct */
|
||||
|
||||
|
||||
/**
|
||||
* Get IP address string of a connection.
|
||||
*
|
||||
* @param Idx Connection index.
|
||||
* @return Pointer to a global buffer containing the IP address as string.
|
||||
*/
|
||||
GLOBAL const char *
|
||||
Conn_GetIPAInfo(CONN_ID Idx)
|
||||
{
|
||||
assert(Idx > NONE);
|
||||
return ng_ipaddr_tostr(&My_Connections[Idx].addr);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send out data of write buffer; connect new sockets.
|
||||
*
|
||||
@@ -1255,9 +1279,11 @@ Handle_Write( CONN_ID Idx )
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_BUFFER
|
||||
LogDebug
|
||||
("Handle_Write() called for connection %d, %ld bytes pending ...",
|
||||
Idx, wdatalen);
|
||||
#endif
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_SSL )) {
|
||||
@@ -1326,6 +1352,8 @@ New_Connection(int Sock)
|
||||
|
||||
assert(Sock > NONE);
|
||||
|
||||
LogDebug("Accepting new connection on socket %d ...", Sock);
|
||||
|
||||
new_sock_len = (int)sizeof(new_addr);
|
||||
new_sock = accept(Sock, (struct sockaddr *)&new_addr,
|
||||
(socklen_t *)&new_sock_len);
|
||||
@@ -1410,7 +1438,7 @@ New_Connection(int Sock)
|
||||
return -1;
|
||||
}
|
||||
|
||||
c = Client_NewLocal(new_sock, ip_str, CLIENT_UNKNOWN, false);
|
||||
c = Client_NewLocal(new_sock, NULL, CLIENT_UNKNOWN, false);
|
||||
if (!c) {
|
||||
Log(LOG_ALERT,
|
||||
"Can't accept connection: can't create client structure!");
|
||||
@@ -1561,7 +1589,7 @@ Read_Request( CONN_ID Idx )
|
||||
if (!array_catb(&My_Connections[Idx].zip.rbuf, readbuf,
|
||||
(size_t) len)) {
|
||||
Log(LOG_ERR,
|
||||
"Could not append recieved data to zip input buffer (connn %d): %d bytes!",
|
||||
"Could not append recieved data to zip input buffer (connection %d): %d bytes!",
|
||||
Idx, len);
|
||||
Conn_Close(Idx, "Receive buffer space exhausted", NULL,
|
||||
false);
|
||||
@@ -1571,7 +1599,9 @@ Read_Request( CONN_ID Idx )
|
||||
#endif
|
||||
{
|
||||
if (!array_catb( &My_Connections[Idx].rbuf, readbuf, len)) {
|
||||
Log( LOG_ERR, "Could not append recieved data to input buffer (connn %d): %d bytes!", Idx, len );
|
||||
Log(LOG_ERR,
|
||||
"Could not append recieved data to input buffer (connection %d): %d bytes!",
|
||||
Idx, len);
|
||||
Conn_Close(Idx, "Receive buffer space exhausted", NULL, false );
|
||||
}
|
||||
}
|
||||
@@ -1644,16 +1674,15 @@ Handle_Buffer(CONN_ID Idx)
|
||||
|
||||
assert(c != NULL);
|
||||
|
||||
/* Servers do get special command limits, so they can process
|
||||
* all the messages that are required while peering. */
|
||||
/* Servers get special command limits that depend on the user count */
|
||||
switch (Client_Type(c)) {
|
||||
case CLIENT_SERVER:
|
||||
/* Allow servers to send more commands in the first 10 secods
|
||||
maxcmd = (int)(Client_UserCount() / 5)
|
||||
+ MAX_COMMANDS_SERVER_MIN;
|
||||
/* Allow servers to handle even more commands while peering
|
||||
* to speed up server login and network synchronisation. */
|
||||
if (starttime - Client_StartTime(c) < 10)
|
||||
maxcmd = MAX_COMMANDS_SERVER * 5;
|
||||
else
|
||||
maxcmd = MAX_COMMANDS_SERVER;
|
||||
if (Conn_LastPing(Idx) == 0)
|
||||
maxcmd *= 5;
|
||||
break;
|
||||
case CLIENT_SERVICE:
|
||||
maxcmd = MAX_COMMANDS_SERVICE; break;
|
||||
@@ -1753,8 +1782,10 @@ Handle_Buffer(CONN_ID Idx)
|
||||
return 0; /* error -> connection has been closed */
|
||||
|
||||
array_moveleft(&My_Connections[Idx].rbuf, 1, len);
|
||||
#ifdef DEBUG_BUFFER
|
||||
LogDebug("Connection %d: %d bytes left in read buffer.",
|
||||
Idx, array_bytes(&My_Connections[Idx].rbuf));
|
||||
#endif
|
||||
#ifdef ZLIB
|
||||
if ((!old_z) && (My_Connections[Idx].options & CONN_ZIP) &&
|
||||
(array_bytes(&My_Connections[Idx].rbuf) > 0)) {
|
||||
@@ -1818,7 +1849,7 @@ Check_Connections(void)
|
||||
time(NULL) - Conf_PingTimeout) {
|
||||
/* We need to send a PING ... */
|
||||
LogDebug("Connection %d: sending PING ...", i);
|
||||
My_Connections[i].lastping = time(NULL);
|
||||
Conn_UpdatePing(i);
|
||||
Conn_WriteStr(i, "PING :%s",
|
||||
Client_ID(Client_ThisServer()));
|
||||
}
|
||||
@@ -2051,13 +2082,14 @@ Init_Socket( int Sock )
|
||||
/* Set type of service (TOS) */
|
||||
#if defined(IPPROTO_IP) && defined(IPTOS_LOWDELAY)
|
||||
value = IPTOS_LOWDELAY;
|
||||
LogDebug("Setting IP_TOS on socket %d to IPTOS_LOWDELAY.", Sock);
|
||||
if (setsockopt(Sock, IPPROTO_IP, IP_TOS, &value,
|
||||
(socklen_t) sizeof(value))) {
|
||||
LogDebug("Can't set socket option IP_TOS: %s!",
|
||||
strerror(errno));
|
||||
/* ignore this error */
|
||||
}
|
||||
} else
|
||||
LogDebug("IP_TOS on socket %d has been set to IPTOS_LOWDELAY.",
|
||||
Sock);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
@@ -2098,6 +2130,7 @@ cb_Connect_to_Server(int fd, UNUSED short events)
|
||||
|
||||
/* Read result from pipe */
|
||||
len = Proc_Read(&Conf_Server[i].res_stat, dest_addrs, sizeof(dest_addrs));
|
||||
Proc_Close(&Conf_Server[i].res_stat);
|
||||
if (len == 0) {
|
||||
/* Error resolving hostname: reset server structure */
|
||||
Conf_Server[i].conn_id = NONE;
|
||||
@@ -2157,6 +2190,7 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
|
||||
|
||||
/* Read result from pipe */
|
||||
len = Proc_Read(&My_Connections[i].proc_stat, readbuf, sizeof readbuf -1);
|
||||
Proc_Close(&My_Connections[i].proc_stat);
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
@@ -2204,6 +2238,7 @@ cb_Read_Resolver_Result( int r_fd, UNUSED short events )
|
||||
"NOTICE AUTH :*** No ident response");
|
||||
}
|
||||
#endif
|
||||
Class_HandleServerBans(c);
|
||||
}
|
||||
#ifdef DEBUG
|
||||
else Log( LOG_DEBUG, "Resolver: discarding result for already registered connection %d.", i );
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2010 Alexander Barton <alex@barton.de>
|
||||
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -106,7 +106,7 @@ GLOBAL long WCounter;
|
||||
GLOBAL void Conn_Init PARAMS((void ));
|
||||
GLOBAL void Conn_Exit PARAMS(( void ));
|
||||
|
||||
GLOBAL void Conn_CloseAllSockets PARAMS((void));
|
||||
GLOBAL void Conn_CloseAllSockets PARAMS((int ExceptOf));
|
||||
|
||||
GLOBAL unsigned int Conn_InitListeners PARAMS(( void ));
|
||||
GLOBAL void Conn_ExitListeners PARAMS(( void ));
|
||||
@@ -131,6 +131,8 @@ Conn_UsesSSL(UNUSED CONN_ID Idx)
|
||||
{ return false; }
|
||||
#endif
|
||||
|
||||
GLOBAL const char *Conn_GetIPAInfo PARAMS((CONN_ID Idx));
|
||||
|
||||
GLOBAL long Conn_Count PARAMS((void));
|
||||
GLOBAL long Conn_CountMax PARAMS((void));
|
||||
GLOBAL long Conn_CountAccepted PARAMS((void));
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2010 Alexander Barton (alex@barton.de)
|
||||
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,98 +17,188 @@
|
||||
* Global constants ("#defines") used by the ngIRCd.
|
||||
*/
|
||||
|
||||
|
||||
/* Internal flags */
|
||||
|
||||
/** Flag: there is no connection. */
|
||||
#define NONE -1
|
||||
|
||||
#define FNAME_LEN 256 /* Max. length of file name */
|
||||
/** Flag: connection is (still) established. */
|
||||
#define CONNECTED true
|
||||
|
||||
#define LINE_LEN 256 /* Max. length of a line in the
|
||||
configuration file */
|
||||
|
||||
#define HOST_LEN 256 /* Max. lenght of fully qualified host
|
||||
names (e. g. "abc.domain.tld") */
|
||||
|
||||
#define MAX_SERVERS 16 /* Max. count of configurable servers */
|
||||
|
||||
#define MAX_WHOWAS 64 /* Max. number of WHOWAS items */
|
||||
#define DEFAULT_WHOWAS 5 /* default count for WHOWAS command */
|
||||
|
||||
#define CONNECTION_POOL 100 /* Size of default connection pool */
|
||||
|
||||
#define CLIENT_ID_LEN 64 /* Max. length of an IRC ID; see RFC
|
||||
RFC 2812 section 1.1 and 1.2.1 */
|
||||
#define CLIENT_NICK_LEN_DEFAULT 10 /* Default nick length, see. RFC 2812
|
||||
* section 1.2.1 */
|
||||
#define CLIENT_NICK_LEN 32 /* Maximum nick name length */
|
||||
#define CLIENT_PASS_LEN 21 /* Max. password length */
|
||||
#define CLIENT_USER_LEN 10 /* Max. length of user name ("login")
|
||||
see RFC 2812, section 1.2.1 */
|
||||
#define CLIENT_NAME_LEN 32 /* Max. length of "real names" */
|
||||
#define CLIENT_HOST_LEN 64 /* Max. host name length */
|
||||
#define CLIENT_MODE_LEN 9 /* Max. lenth of all client modes */
|
||||
#define CLIENT_INFO_LEN 64 /* Max. length of server info texts */
|
||||
#define CLIENT_AWAY_LEN 128 /* Max. length of away messages */
|
||||
#define CLIENT_FLAGS_LEN 100 /* Max. length of client flags */
|
||||
|
||||
#define CHANNEL_NAME_LEN 51 /* Max. length of a channel name, see
|
||||
RFC 2812 section 1.3 */
|
||||
#define CHANNEL_MODE_LEN 9 /* Max. length of channel modes */
|
||||
|
||||
#define COMMAND_LEN 513 /* Max. IRC command length, see. RFC
|
||||
2812 section 3.2 */
|
||||
|
||||
#define READBUFFER_LEN 2048 /* Size of the read buffer of a
|
||||
connection in bytes. */
|
||||
#define WRITEBUFFER_FLUSH_LEN 4096 /* Size of a write buffer that triggers
|
||||
buffer flushing if more space is
|
||||
needed for storing data. */
|
||||
#define WRITEBUFFER_MAX_LEN 32768 /* Maximum size of the write buffer of a
|
||||
connection in bytes. */
|
||||
#define WRITEBUFFER_SLINK_LEN 65536 /* Maximum size of the write buffer of a
|
||||
server link connection in bytes. */
|
||||
|
||||
#define PROTOVER "0210" /* Implemented IRC protocol version,
|
||||
see RFC 2813 section 4.1.1. */
|
||||
#define PROTOIRC "-IRC" /* Protocol suffix, see RFC 2813
|
||||
section 4.1.1 */
|
||||
#define PROTOIRCPLUS "-IRC+" /* Protocol suffix used by the IRC+
|
||||
protocol, see doc/Protocol.txt */
|
||||
|
||||
#ifdef IRCPLUS
|
||||
# define IRCPLUSFLAGS "CHLS" /* Standard IRC+ flags */
|
||||
#endif
|
||||
|
||||
#define STARTUP_DELAY 1 /* Delay outgoing connections n seconds
|
||||
after startup. */
|
||||
#define RECONNECT_DELAY 3 /* Time to delay re-connect attempts
|
||||
in seconds. */
|
||||
|
||||
#define USERMODES "aciorswx" /* Supported user modes. */
|
||||
#define CHANMODES "biIklmnoOPstvz" /* Supported channel modes. */
|
||||
|
||||
#define CONNECTED true /* Internal status codes. */
|
||||
/** Flag: connection isn't established (any more). */
|
||||
#define DISCONNECTED false
|
||||
|
||||
#define DEFAULT_AWAY_MSG "Away" /* Away message for users connected to
|
||||
linked servers. */
|
||||
/** Tag for outbound server links. */
|
||||
#define TOKEN_OUTBOUND -2
|
||||
|
||||
#define DEFAULT_TOPIC_ID "-Server-" /* Default ID for "topic owner". */
|
||||
|
||||
#define CONFIG_FILE "/ngircd.conf" /* Configuration file name. */
|
||||
#define MOTD_FILE "/ngircd.motd" /* Name of the MOTD file. */
|
||||
#define CHROOT_DIR "" /* Default chroot() directory. */
|
||||
#define PID_FILE "" /* Default file for the process ID. */
|
||||
/* Generic buffer sizes */
|
||||
|
||||
#define ERROR_DIR "/tmp" /* Error directory used in debug mode */
|
||||
/** Max. length of a line in the configuration file. */
|
||||
#define LINE_LEN 256
|
||||
|
||||
#define MAX_LOG_MSG_LEN 256 /* Max. length of a log message. */
|
||||
/** Max. length of a log message. */
|
||||
#define MAX_LOG_MSG_LEN 256
|
||||
|
||||
#define TOKEN_OUTBOUND -2 /* Tag for outbound server links. */
|
||||
/** Max. length of file name. */
|
||||
#define FNAME_LEN 256
|
||||
|
||||
#define NOTICE_TXTPREFIX "" /* Prefix for NOTICEs from the server
|
||||
to users. Some servers use '*'. */
|
||||
/** Max. lenght of fully qualified host names (e. g. "abc.domain.tld"). */
|
||||
#define HOST_LEN 256
|
||||
|
||||
|
||||
/* Size of structures */
|
||||
|
||||
/** Max. count of configurable servers. */
|
||||
#define MAX_SERVERS 16
|
||||
|
||||
/** Max. number of WHOWAS list items that can be stored. */
|
||||
#define MAX_WHOWAS 64
|
||||
|
||||
/** Size of default connection pool. */
|
||||
#define CONNECTION_POOL 100
|
||||
|
||||
|
||||
/* Hard-coded (default) options */
|
||||
|
||||
/** Delay after startup before outgoing connections are initiated in seconds. */
|
||||
#define STARTUP_DELAY 1
|
||||
|
||||
/** Time to delay re-connect attempts in seconds. */
|
||||
#define RECONNECT_DELAY 3
|
||||
|
||||
/** Configuration file name. */
|
||||
#define CONFIG_FILE "/ngircd.conf"
|
||||
|
||||
/** Name of the MOTD file. */
|
||||
#define MOTD_FILE "/ngircd.motd"
|
||||
|
||||
/** Default chroot() directory. */
|
||||
#define CHROOT_DIR ""
|
||||
|
||||
/** Default file for the process ID. */
|
||||
#define PID_FILE ""
|
||||
|
||||
|
||||
/* Sizes of "IRC elements": nicks, users, ... */
|
||||
|
||||
/** Max. length of an IRC ID (incl. NULL); see RFC 2812 section 1.1 and 1.2.1. */
|
||||
#define CLIENT_ID_LEN 64
|
||||
|
||||
/** Default nick length (including NULL), see. RFC 2812 section 1.2.1. */
|
||||
#define CLIENT_NICK_LEN_DEFAULT 10
|
||||
|
||||
/** Maximum nick name length (including NULL). */
|
||||
#define CLIENT_NICK_LEN 32
|
||||
|
||||
/** Max. password length (including NULL). */
|
||||
#define CLIENT_PASS_LEN 21
|
||||
|
||||
/** Max. length of user name ("login"; incl. NULL), RFC 2812, section 1.2.1. */
|
||||
#define CLIENT_USER_LEN 10
|
||||
|
||||
/** Max. length of "real names" (including NULL). */
|
||||
#define CLIENT_NAME_LEN 32
|
||||
|
||||
/** Max. host name length (including NULL). */
|
||||
#define CLIENT_HOST_LEN 64
|
||||
|
||||
/** Max. length of all client modes (including NULL). */
|
||||
#define CLIENT_MODE_LEN 16
|
||||
|
||||
/** Max. length of server info texts (including NULL). */
|
||||
#define CLIENT_INFO_LEN 64
|
||||
|
||||
/** Max. length of away messages (including NULL). */
|
||||
#define CLIENT_AWAY_LEN 128
|
||||
|
||||
/** Max. length of client flags (including NULL). */
|
||||
#define CLIENT_FLAGS_LEN 16
|
||||
|
||||
/** Max. length of a channel name (including NULL), see RFC 2812 section 1.3. */
|
||||
#define CHANNEL_NAME_LEN 51
|
||||
|
||||
/** Max. length of channel modes (including NULL). */
|
||||
#define CHANNEL_MODE_LEN 9
|
||||
|
||||
/** Max. IRC command length (including NULL), see. RFC 2812 section 3.2. */
|
||||
#define COMMAND_LEN 513
|
||||
|
||||
|
||||
/* Read and write buffer sizes */
|
||||
|
||||
/** Size of the read buffer of a connection in bytes. */
|
||||
#define READBUFFER_LEN 2048
|
||||
|
||||
/** Size that triggers write buffer flushing if more space is needed. */
|
||||
#define WRITEBUFFER_FLUSH_LEN 4096
|
||||
|
||||
/** Maximum size of the write buffer of a connection in bytes. */
|
||||
#define WRITEBUFFER_MAX_LEN 32768
|
||||
|
||||
/** Maximum size of the write buffer of a server link connection in bytes. */
|
||||
#define WRITEBUFFER_SLINK_LEN 65536
|
||||
|
||||
|
||||
/* IRC/IRC+ protocol */
|
||||
|
||||
/** Implemented IRC protocol version, see RFC 2813 section 4.1.1. */
|
||||
#define PROTOVER "0210"
|
||||
|
||||
/** Protocol suffix, see RFC 2813 section 4.1.1. */
|
||||
#define PROTOIRC "-IRC"
|
||||
|
||||
/** Protocol suffix used by the IRC+ protocol, see <doc/Protocol.txt>. */
|
||||
#define PROTOIRCPLUS "-IRC+"
|
||||
|
||||
#ifdef IRCPLUS
|
||||
/** Standard IRC+ flags. */
|
||||
# define IRCPLUSFLAGS "CHLS"
|
||||
#endif
|
||||
|
||||
/** Supported user modes. */
|
||||
#define USERMODES "acCiorRswx"
|
||||
|
||||
/** Supported channel modes. */
|
||||
#define CHANMODES "beiIklmnoOPRstvz"
|
||||
|
||||
/** Away message for users connected to linked servers. */
|
||||
#define DEFAULT_AWAY_MSG "Away"
|
||||
|
||||
/** Default ID for "topic owner". */
|
||||
#define DEFAULT_TOPIC_ID "-Server-"
|
||||
|
||||
/** Prefix for NOTICEs from the server to users. Some servers use '*'. */
|
||||
#define NOTICE_TXTPREFIX ""
|
||||
|
||||
/** Suffix for oversized messages that have been shortened and cut off. */
|
||||
#define CUT_TXTSUFFIX "[CUT]"
|
||||
|
||||
|
||||
/* Defaults and limits for IRC commands */
|
||||
|
||||
/** Max. number of LIST replies. */
|
||||
#define MAX_RPL_LIST 100
|
||||
|
||||
/** Max. number of elemets allowed in channel invite and ban lists. */
|
||||
#define MAX_HNDL_CHANNEL_LISTS 50
|
||||
|
||||
/** Max. number of channel modes with arguments per MODE command. */
|
||||
#define MAX_HNDL_MODES_ARG 5
|
||||
|
||||
/** Max. number of WHO replies. */
|
||||
#define MAX_RPL_WHO 25
|
||||
|
||||
/** Max. number of WHOIS replies. */
|
||||
#define MAX_RPL_WHOIS 10
|
||||
|
||||
/** Default count of WHOWAS command replies. */
|
||||
#define DEF_RPL_WHOWAS 5
|
||||
|
||||
/** Max count of WHOWAS command replies. */
|
||||
#define MAX_RPL_WHOWAS 25
|
||||
|
||||
#define CUT_TXTSUFFIX "[CUT]" /* Suffix for oversized messages that
|
||||
have been shortened and cut off. */
|
||||
|
||||
#endif
|
||||
|
||||
|
157
src/ngircd/io.c
157
src/ngircd/io.c
@@ -41,6 +41,7 @@ typedef struct {
|
||||
|
||||
#define INIT_IOEVENT { NULL, -1, 0, NULL }
|
||||
#define IO_ERROR 4
|
||||
#define MAX_EVENTS 100
|
||||
|
||||
#ifdef HAVE_EPOLL_CREATE
|
||||
# define IO_USE_EPOLL 1
|
||||
@@ -54,7 +55,7 @@ typedef struct {
|
||||
# ifdef HAVE_SYS_DEVPOLL_H
|
||||
# define IO_USE_DEVPOLL 1
|
||||
# else
|
||||
# ifdef HAVE_POLL
|
||||
# if defined(HAVE_POLL) && defined(HAVE_POLL_H)
|
||||
# define IO_USE_POLL 1
|
||||
# else
|
||||
# ifdef HAVE_SELECT
|
||||
@@ -160,39 +161,34 @@ io_dispatch_devpoll(struct timeval *tv)
|
||||
{
|
||||
struct dvpoll dvp;
|
||||
time_t sec = tv->tv_sec * 1000;
|
||||
int i, total, ret, timeout = tv->tv_usec + sec;
|
||||
int i, ret, timeout = tv->tv_usec + sec;
|
||||
short what;
|
||||
struct pollfd p[100];
|
||||
struct pollfd p[MAX_EVENTS];
|
||||
|
||||
if (timeout < 0)
|
||||
timeout = 1000;
|
||||
|
||||
total = 0;
|
||||
do {
|
||||
dvp.dp_timeout = timeout;
|
||||
dvp.dp_nfds = 100;
|
||||
dvp.dp_fds = p;
|
||||
ret = ioctl(io_masterfd, DP_POLL, &dvp);
|
||||
total += ret;
|
||||
if (ret <= 0)
|
||||
return total;
|
||||
for (i=0; i < ret ; i++) {
|
||||
what = 0;
|
||||
if (p[i].revents & (POLLIN|POLLPRI))
|
||||
what = IO_WANTREAD;
|
||||
dvp.dp_timeout = timeout;
|
||||
dvp.dp_nfds = MAX_EVENTS;
|
||||
dvp.dp_fds = p;
|
||||
ret = ioctl(io_masterfd, DP_POLL, &dvp);
|
||||
|
||||
if (p[i].revents & POLLOUT)
|
||||
what |= IO_WANTWRITE;
|
||||
for (i=0; i < ret ; i++) {
|
||||
what = 0;
|
||||
if (p[i].revents & (POLLIN|POLLPRI))
|
||||
what = IO_WANTREAD;
|
||||
|
||||
if (p[i].revents && !what) {
|
||||
/* other flag is set, probably POLLERR */
|
||||
what = IO_ERROR;
|
||||
}
|
||||
io_docallback(p[i].fd, what);
|
||||
if (p[i].revents & POLLOUT)
|
||||
what |= IO_WANTWRITE;
|
||||
|
||||
if (p[i].revents && !what) {
|
||||
/* other flag is set, probably POLLERR */
|
||||
what = IO_ERROR;
|
||||
}
|
||||
} while (ret == 100);
|
||||
io_docallback(p[i].fd, what);
|
||||
}
|
||||
|
||||
return total;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -462,37 +458,30 @@ static int
|
||||
io_dispatch_epoll(struct timeval *tv)
|
||||
{
|
||||
time_t sec = tv->tv_sec * 1000;
|
||||
int i, total = 0, ret, timeout = tv->tv_usec + sec;
|
||||
struct epoll_event epoll_ev[100];
|
||||
int i, ret, timeout = tv->tv_usec + sec;
|
||||
struct epoll_event epoll_ev[MAX_EVENTS];
|
||||
short type;
|
||||
|
||||
if (timeout < 0)
|
||||
timeout = 1000;
|
||||
|
||||
do {
|
||||
ret = epoll_wait(io_masterfd, epoll_ev, 100, timeout);
|
||||
total += ret;
|
||||
if (ret <= 0)
|
||||
return total;
|
||||
ret = epoll_wait(io_masterfd, epoll_ev, MAX_EVENTS, timeout);
|
||||
|
||||
for (i = 0; i < ret; i++) {
|
||||
type = 0;
|
||||
if (epoll_ev[i].events & (EPOLLERR | EPOLLHUP))
|
||||
type = IO_ERROR;
|
||||
for (i = 0; i < ret; i++) {
|
||||
type = 0;
|
||||
if (epoll_ev[i].events & (EPOLLERR | EPOLLHUP))
|
||||
type = IO_ERROR;
|
||||
|
||||
if (epoll_ev[i].events & (EPOLLIN | EPOLLPRI))
|
||||
type |= IO_WANTREAD;
|
||||
if (epoll_ev[i].events & (EPOLLIN | EPOLLPRI))
|
||||
type |= IO_WANTREAD;
|
||||
|
||||
if (epoll_ev[i].events & EPOLLOUT)
|
||||
type |= IO_WANTWRITE;
|
||||
if (epoll_ev[i].events & EPOLLOUT)
|
||||
type |= IO_WANTWRITE;
|
||||
|
||||
io_docallback(epoll_ev[i].data.fd, type);
|
||||
}
|
||||
io_docallback(epoll_ev[i].data.fd, type);
|
||||
}
|
||||
|
||||
timeout = 0;
|
||||
} while (ret == 100);
|
||||
|
||||
return total;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -576,58 +565,50 @@ io_event_change_kqueue(int fd, short what, const int action)
|
||||
static int
|
||||
io_dispatch_kqueue(struct timeval *tv)
|
||||
{
|
||||
int i, total = 0, ret;
|
||||
struct kevent kev[100];
|
||||
int i, ret;
|
||||
struct kevent kev[MAX_EVENTS];
|
||||
struct kevent *newevents;
|
||||
struct timespec ts;
|
||||
int newevents_len;
|
||||
ts.tv_sec = tv->tv_sec;
|
||||
ts.tv_nsec = tv->tv_usec * 1000;
|
||||
|
||||
do {
|
||||
newevents_len = (int) array_length(&io_evcache, sizeof (struct kevent));
|
||||
newevents = (newevents_len > 0) ? array_start(&io_evcache) : NULL;
|
||||
assert(newevents_len >= 0);
|
||||
newevents_len = (int) array_length(&io_evcache, sizeof (struct kevent));
|
||||
newevents = (newevents_len > 0) ? array_start(&io_evcache) : NULL;
|
||||
assert(newevents_len >= 0);
|
||||
|
||||
ret = kevent(io_masterfd, newevents, newevents_len, kev, 100, &ts);
|
||||
if (newevents && ret != -1)
|
||||
array_trunc(&io_evcache);
|
||||
ret = kevent(io_masterfd, newevents, newevents_len, kev, MAX_EVENTS, &ts);
|
||||
if (newevents && ret != -1)
|
||||
array_trunc(&io_evcache);
|
||||
|
||||
total += ret;
|
||||
if (ret <= 0)
|
||||
return total;
|
||||
|
||||
for (i = 0; i < ret; i++) {
|
||||
io_debug("dispatch_kqueue: fd, kev.flags", (int)kev[i].ident, kev[i].flags);
|
||||
if (kev[i].flags & (EV_EOF|EV_ERROR)) {
|
||||
if (kev[i].flags & EV_ERROR)
|
||||
Log(LOG_ERR, "kevent fd %d: EV_ERROR (%s)",
|
||||
(int)kev[i].ident, strerror((int)kev[i].data));
|
||||
io_docallback((int)kev[i].ident, IO_ERROR);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (kev[i].filter) {
|
||||
case EVFILT_READ:
|
||||
io_docallback((int)kev[i].ident, IO_WANTREAD);
|
||||
break;
|
||||
case EVFILT_WRITE:
|
||||
io_docallback((int)kev[i].ident, IO_WANTWRITE);
|
||||
break;
|
||||
default:
|
||||
LogDebug("Unknown kev.filter number %d for fd %d",
|
||||
kev[i].filter, kev[i].ident);
|
||||
/* Fall through */
|
||||
case EV_ERROR:
|
||||
io_docallback((int)kev[i].ident, IO_ERROR);
|
||||
break;
|
||||
}
|
||||
for (i = 0; i < ret; i++) {
|
||||
io_debug("dispatch_kqueue: fd, kev.flags", (int)kev[i].ident, kev[i].flags);
|
||||
if (kev[i].flags & (EV_EOF|EV_ERROR)) {
|
||||
if (kev[i].flags & EV_ERROR)
|
||||
Log(LOG_ERR, "kevent fd %d: EV_ERROR (%s)",
|
||||
(int)kev[i].ident, strerror((int)kev[i].data));
|
||||
io_docallback((int)kev[i].ident, IO_ERROR);
|
||||
continue;
|
||||
}
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec = 0;
|
||||
} while (ret == 100);
|
||||
|
||||
return total;
|
||||
switch (kev[i].filter) {
|
||||
case EVFILT_READ:
|
||||
io_docallback((int)kev[i].ident, IO_WANTREAD);
|
||||
break;
|
||||
case EVFILT_WRITE:
|
||||
io_docallback((int)kev[i].ident, IO_WANTWRITE);
|
||||
break;
|
||||
default:
|
||||
LogDebug("Unknown kev.filter number %d for fd %d",
|
||||
kev[i].filter, kev[i].ident);
|
||||
/* Fall through */
|
||||
case EV_ERROR:
|
||||
io_docallback((int)kev[i].ident, IO_ERROR);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -31,6 +31,7 @@
|
||||
#include "match.h"
|
||||
#include "messages.h"
|
||||
#include "parse.h"
|
||||
#include "irc.h"
|
||||
#include "irc-info.h"
|
||||
#include "irc-write.h"
|
||||
#include "conf.h"
|
||||
@@ -81,7 +82,7 @@ static bool
|
||||
join_allowed(CLIENT *Client, CHANNEL *chan, const char *channame,
|
||||
const char *key)
|
||||
{
|
||||
bool is_invited, is_banned;
|
||||
bool is_invited, is_banned, is_exception;;
|
||||
const char *channel_modes;
|
||||
|
||||
/* Allow IRC operators to overwrite channel limits */
|
||||
@@ -89,9 +90,10 @@ join_allowed(CLIENT *Client, CHANNEL *chan, const char *channame,
|
||||
return true;
|
||||
|
||||
is_banned = Lists_Check(Channel_GetListBans(chan), Client);
|
||||
is_exception = Lists_Check(Channel_GetListExcepts(chan), Client);
|
||||
is_invited = Lists_Check(Channel_GetListInvites(chan), Client);
|
||||
|
||||
if (is_banned && !is_invited) {
|
||||
if (is_banned && !is_invited && !is_exception) {
|
||||
/* Client is banned from channel (and not on invite list) */
|
||||
IRC_WriteStrClient(Client, ERR_BANNEDFROMCHAN_MSG,
|
||||
Client_ID(Client), channame);
|
||||
@@ -137,6 +139,13 @@ join_allowed(CLIENT *Client, CHANNEL *chan, const char *channame,
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strchr(channel_modes, 'R') && !strchr(Client_Modes(Client), 'R')) {
|
||||
/* Only registered users are allowed! */
|
||||
IRC_WriteStrClient(Client, ERR_REGONLYCHANNEL_MSG,
|
||||
Client_ID(Client), channame);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} /* join_allowed */
|
||||
|
||||
@@ -237,7 +246,7 @@ join_forward(CLIENT *Client, CLIENT *target, CHANNEL *chan,
|
||||
IRC_WriteStrChannelPrefix(Client, chan, target, false,
|
||||
"JOIN :%s", channame);
|
||||
|
||||
/* syncronize channel modes */
|
||||
/* synchronize channel modes */
|
||||
if (modes[1]) {
|
||||
IRC_WriteStrChannelPrefix(Client, chan, target, false,
|
||||
"MODE %s +%s %s", channame,
|
||||
@@ -294,9 +303,9 @@ join_send_topic(CLIENT *Client, CLIENT *target, CHANNEL *chan,
|
||||
*
|
||||
* See RFC 2812, 3.2.1 "Join message"; RFC 2813, 4.2.1 "Join message".
|
||||
*
|
||||
* @param Client The client from which this command has been received
|
||||
* @param Req Request structure with prefix and all parameters
|
||||
* @returns CONNECTED or DISCONNECTED
|
||||
* @param Client The client from which this command has been received
|
||||
* @param Req Request structure with prefix and all parameters
|
||||
* @returns CONNECTED or DISCONNECTED
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_JOIN( CLIENT *Client, REQUEST *Req )
|
||||
@@ -305,8 +314,8 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
|
||||
CLIENT *target;
|
||||
CHANNEL *chan;
|
||||
|
||||
assert( Client != NULL );
|
||||
assert( Req != NULL );
|
||||
assert (Client != NULL);
|
||||
assert (Req != NULL);
|
||||
|
||||
/* Bad number of arguments? */
|
||||
if (Req->argc < 1 || Req->argc > 2)
|
||||
@@ -320,7 +329,8 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
|
||||
target = Client;
|
||||
|
||||
if (!target)
|
||||
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, Client_ID(Client), Req->prefix);
|
||||
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
|
||||
Client_ID(Client), Req->prefix);
|
||||
|
||||
/* Is argument "0"? */
|
||||
if (Req->argc == 1 && !strncmp("0", Req->argv[0], 2))
|
||||
@@ -352,24 +362,35 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
|
||||
|
||||
chan = Channel_Search(channame);
|
||||
if (!chan && Conf_PredefChannelsOnly) {
|
||||
/* channel must be created, but server does not allow this */
|
||||
IRC_WriteStrClient(Client, ERR_BANNEDFROMCHAN_MSG, Client_ID(Client), channame);
|
||||
break;
|
||||
/* channel must be created, but forbidden by config */
|
||||
IRC_WriteStrClient(Client, ERR_BANNEDFROMCHAN_MSG,
|
||||
Client_ID(Client), channame);
|
||||
goto join_next;
|
||||
}
|
||||
|
||||
/* Local client? */
|
||||
if (Client_Type(Client) == CLIENT_USER) {
|
||||
if (chan) {
|
||||
/* Already existing channel: already member? */
|
||||
if (Channel_IsMemberOf(chan, Client))
|
||||
goto join_next;
|
||||
}
|
||||
|
||||
/* Test if the user has reached the channel limit */
|
||||
if ((Conf_MaxJoins > 0) &&
|
||||
(Channel_CountForUser(Client) >= Conf_MaxJoins))
|
||||
return IRC_WriteStrClient(Client,
|
||||
(Channel_CountForUser(Client) >= Conf_MaxJoins)) {
|
||||
if (!IRC_WriteStrClient(Client,
|
||||
ERR_TOOMANYCHANNELS_MSG,
|
||||
Client_ID(Client), channame);
|
||||
Client_ID(Client), channame))
|
||||
return DISCONNECTED;
|
||||
goto join_next;
|
||||
}
|
||||
|
||||
if (chan) {
|
||||
/* Already existing channel: check if the
|
||||
* client is allowed to join */
|
||||
if (!join_allowed(Client, chan, channame, key))
|
||||
break;
|
||||
goto join_next;
|
||||
} else {
|
||||
/* New channel: first user will become channel
|
||||
* operator unless this is a modeless channel */
|
||||
@@ -392,7 +413,7 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
|
||||
|
||||
/* Join channel (and create channel if it doesn't exist) */
|
||||
if (!Channel_Join(target, channame))
|
||||
break;
|
||||
goto join_next;
|
||||
|
||||
if (!chan) { /* channel is new; it has been created above */
|
||||
chan = Channel_Search(channame);
|
||||
@@ -411,6 +432,7 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
|
||||
if (!join_send_topic(Client, target, chan, channame))
|
||||
break; /* write error */
|
||||
|
||||
join_next:
|
||||
/* next channel? */
|
||||
channame = strtok_r(NULL, ",", &lastchan);
|
||||
if (channame && key)
|
||||
@@ -582,9 +604,9 @@ IRC_TOPIC( CLIENT *Client, REQUEST *Req )
|
||||
* This implementation handles the local case as well as the forwarding of the
|
||||
* LIST command to other servers in the IRC network.
|
||||
*
|
||||
* @param Client The client from which this command has been received
|
||||
* @param Req Request structure with prefix and all parameters
|
||||
* @returns CONNECTED or DISCONNECTED
|
||||
* @param Client The client from which this command has been received.
|
||||
* @param Req Request structure with prefix and all parameters.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_LIST( CLIENT *Client, REQUEST *Req )
|
||||
@@ -592,79 +614,84 @@ IRC_LIST( CLIENT *Client, REQUEST *Req )
|
||||
char *pattern;
|
||||
CHANNEL *chan;
|
||||
CLIENT *from, *target;
|
||||
int count = 0;
|
||||
|
||||
assert( Client != NULL );
|
||||
assert( Req != NULL );
|
||||
assert(Client != NULL);
|
||||
assert(Req != NULL);
|
||||
|
||||
/* Bad number of prameters? */
|
||||
if( Req->argc > 2 )
|
||||
return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG,
|
||||
Client_ID( Client ), Req->command );
|
||||
if (Req->argc > 2)
|
||||
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
|
||||
Client_ID(Client), Req->command);
|
||||
|
||||
if( Req->argc > 0 )
|
||||
pattern = strtok( Req->argv[0], "," );
|
||||
if (Req->argc > 0)
|
||||
pattern = strtok(Req->argv[0], ",");
|
||||
else
|
||||
pattern = "*";
|
||||
|
||||
/* Get sender from prefix, if any */
|
||||
if( Client_Type( Client ) == CLIENT_SERVER )
|
||||
from = Client_Search( Req->prefix );
|
||||
if (Client_Type(Client) == CLIENT_SERVER)
|
||||
from = Client_Search(Req->prefix);
|
||||
else
|
||||
from = Client;
|
||||
|
||||
if( ! from )
|
||||
return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG,
|
||||
Client_ID( Client ), Req->prefix );
|
||||
if (!from)
|
||||
return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
|
||||
Client_ID(Client), Req->prefix);
|
||||
|
||||
if( Req->argc == 2 )
|
||||
{
|
||||
if (Req->argc == 2) {
|
||||
/* Forward to other server? */
|
||||
target = Client_Search( Req->argv[1] );
|
||||
if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER ))
|
||||
return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG,
|
||||
Client_ID( Client ), Req->argv[1] );
|
||||
target = Client_Search(Req->argv[1]);
|
||||
if (! target || Client_Type(target) != CLIENT_SERVER)
|
||||
return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG,
|
||||
Client_ID(Client),
|
||||
Req->argv[1]);
|
||||
|
||||
if( target != Client_ThisServer( ))
|
||||
{
|
||||
if (target != Client_ThisServer()) {
|
||||
/* Target is indeed an other server, forward it! */
|
||||
return IRC_WriteStrClientPrefix( target, from,
|
||||
"LIST %s :%s", Client_ID( from ),
|
||||
Req->argv[1] );
|
||||
return IRC_WriteStrClientPrefix(target, from,
|
||||
"LIST %s :%s",
|
||||
Req->argv[0],
|
||||
Req->argv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
while( pattern )
|
||||
{
|
||||
while (pattern) {
|
||||
/* Loop through all the channels */
|
||||
chan = Channel_First( );
|
||||
while( chan )
|
||||
{
|
||||
if (Req->argc > 0)
|
||||
ngt_LowerStr(pattern);
|
||||
chan = Channel_First();
|
||||
while (chan) {
|
||||
/* Check search pattern */
|
||||
if( Match( pattern, Channel_Name( chan )))
|
||||
{
|
||||
if (MatchCaseInsensitive(pattern, Channel_Name(chan))) {
|
||||
/* Gotcha! */
|
||||
if( ! strchr( Channel_Modes( chan ), 's' ) ||
|
||||
Channel_IsMemberOf( chan, from ))
|
||||
{
|
||||
if( ! IRC_WriteStrClient( from,
|
||||
RPL_LIST_MSG, Client_ID( from ),
|
||||
Channel_Name( chan ),
|
||||
Channel_MemberCount( chan ),
|
||||
Channel_Topic( chan )))
|
||||
if (!strchr(Channel_Modes(chan), 's')
|
||||
|| Channel_IsMemberOf(chan, from)) {
|
||||
if (IRC_CheckListTooBig(from, count,
|
||||
MAX_RPL_LIST,
|
||||
"LIST"))
|
||||
break;
|
||||
if (!IRC_WriteStrClient(from,
|
||||
RPL_LIST_MSG, Client_ID(from),
|
||||
Channel_Name(chan),
|
||||
Channel_MemberCount(chan),
|
||||
Channel_Topic( chan )))
|
||||
return DISCONNECTED;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
chan = Channel_Next( chan );
|
||||
chan = Channel_Next(chan);
|
||||
}
|
||||
|
||||
/* Get next name ... */
|
||||
if( Req->argc > 0 )
|
||||
pattern = strtok( NULL, "," );
|
||||
if(Req->argc > 0)
|
||||
pattern = strtok(NULL, ",");
|
||||
else
|
||||
pattern = NULL;
|
||||
}
|
||||
|
||||
return IRC_WriteStrClient( from, RPL_LISTEND_MSG, Client_ID( from ));
|
||||
IRC_SetPenalty(from, 2);
|
||||
return IRC_WriteStrClient(from, RPL_LISTEND_MSG, Client_ID(from));
|
||||
} /* IRC_LIST */
|
||||
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
|
||||
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -28,13 +28,16 @@
|
||||
#include "conn-func.h"
|
||||
#include "conn-zip.h"
|
||||
#include "channel.h"
|
||||
#include "class.h"
|
||||
#include "conf.h"
|
||||
#include "defines.h"
|
||||
#include "lists.h"
|
||||
#include "log.h"
|
||||
#include "messages.h"
|
||||
#include "match.h"
|
||||
#include "tool.h"
|
||||
#include "parse.h"
|
||||
#include "irc.h"
|
||||
#include "irc-write.h"
|
||||
|
||||
#include "exp.h"
|
||||
@@ -152,6 +155,15 @@ IRC_INFO(CLIENT * Client, REQUEST * Req)
|
||||
} /* IRC_INFO */
|
||||
|
||||
|
||||
/**
|
||||
* Handler for the IRC "ISON" command.
|
||||
*
|
||||
* See RFC 2812, 4.9 "Ison message".
|
||||
*
|
||||
* @param Client The client from which this command has been received.
|
||||
* @param Req Request structure with prefix and all parameters.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_ISON( CLIENT *Client, REQUEST *Req )
|
||||
{
|
||||
@@ -160,80 +172,103 @@ IRC_ISON( CLIENT *Client, REQUEST *Req )
|
||||
char *ptr;
|
||||
int i;
|
||||
|
||||
assert( Client != NULL );
|
||||
assert( Req != NULL );
|
||||
assert(Client != NULL);
|
||||
assert(Req != NULL);
|
||||
|
||||
/* Falsche Anzahl Parameter? */
|
||||
if(( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
|
||||
/* Bad number of arguments? */
|
||||
if (Req->argc < 1)
|
||||
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
|
||||
Client_ID(Client), Req->command);
|
||||
|
||||
strlcpy( rpl, RPL_ISON_MSG, sizeof rpl );
|
||||
for( i = 0; i < Req->argc; i++ )
|
||||
{
|
||||
ptr = strtok( Req->argv[i], " " );
|
||||
while( ptr )
|
||||
{
|
||||
ngt_TrimStr( ptr );
|
||||
c = Client_Search( ptr );
|
||||
if( c && ( Client_Type( c ) == CLIENT_USER ))
|
||||
{
|
||||
/* Dieser Nick ist "online" */
|
||||
strlcat( rpl, ptr, sizeof( rpl ));
|
||||
strlcat( rpl, " ", sizeof( rpl ));
|
||||
strlcpy(rpl, RPL_ISON_MSG, sizeof rpl);
|
||||
for (i = 0; i < Req->argc; i++) {
|
||||
/* "All" ircd even parse ":<x> <y> ..." arguments and split
|
||||
* them up; so we do the same ... */
|
||||
ptr = strtok(Req->argv[i], " ");
|
||||
while (ptr) {
|
||||
ngt_TrimStr(ptr);
|
||||
c = Client_Search(ptr);
|
||||
if (c && Client_Type(c) == CLIENT_USER) {
|
||||
strlcat(rpl, Client_ID(c), sizeof(rpl));
|
||||
strlcat(rpl, " ", sizeof(rpl));
|
||||
}
|
||||
ptr = strtok( NULL, " " );
|
||||
ptr = strtok(NULL, " ");
|
||||
}
|
||||
}
|
||||
ngt_TrimLastChr(rpl, ' ');
|
||||
|
||||
return IRC_WriteStrClient( Client, rpl, Client_ID( Client ) );
|
||||
return IRC_WriteStrClient(Client, rpl, Client_ID(Client));
|
||||
} /* IRC_ISON */
|
||||
|
||||
|
||||
/**
|
||||
* Handler for the IRC "LINKS" command.
|
||||
*
|
||||
* See RFC 2812, 3.4.5 "Links message".
|
||||
*
|
||||
* @param Client The client from which this command has been received.
|
||||
* @param Req Request structure with prefix and all parameters.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_LINKS( CLIENT *Client, REQUEST *Req )
|
||||
IRC_LINKS(CLIENT *Client, REQUEST *Req)
|
||||
{
|
||||
CLIENT *target, *from, *c;
|
||||
char *mask;
|
||||
|
||||
assert( Client != NULL );
|
||||
assert( Req != NULL );
|
||||
assert(Client != NULL);
|
||||
assert(Req != NULL);
|
||||
|
||||
if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
|
||||
IRC_SetPenalty(Client, 1);
|
||||
|
||||
/* Server-Mask ermitteln */
|
||||
if( Req->argc > 0 ) mask = Req->argv[Req->argc - 1];
|
||||
else mask = "*";
|
||||
if (Req->argc > 2)
|
||||
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
|
||||
Client_ID(Client), Req->command);
|
||||
|
||||
/* Absender ermitteln */
|
||||
if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
|
||||
else from = Client;
|
||||
if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
|
||||
/* Get pointer to server mask or "*", if none given */
|
||||
if (Req->argc > 0)
|
||||
mask = Req->argv[Req->argc - 1];
|
||||
else
|
||||
mask = "*";
|
||||
|
||||
/* An anderen Server forwarden? */
|
||||
if( Req->argc == 2 )
|
||||
{
|
||||
target = Client_Search( Req->argv[0] );
|
||||
if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[0] );
|
||||
else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LINKS %s %s", Req->argv[0], Req->argv[1] );
|
||||
if (Client_Type(Client) == CLIENT_SERVER)
|
||||
from = Client_Search(Req->prefix);
|
||||
else
|
||||
from = Client;
|
||||
if (!from)
|
||||
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
|
||||
Client_ID(Client), Req->prefix);
|
||||
|
||||
/* Forward? */
|
||||
if (Req->argc == 2) {
|
||||
target = Client_Search(Req->argv[0]);
|
||||
if (! target || Client_Type(target) != CLIENT_SERVER)
|
||||
return IRC_WriteStrClient(from, ERR_NOSUCHSERVER_MSG,
|
||||
Client_ID(from),
|
||||
Req->argv[0] );
|
||||
else
|
||||
if (target != Client_ThisServer())
|
||||
return IRC_WriteStrClientPrefix(target, from,
|
||||
"LINKS %s %s", Req->argv[0],
|
||||
Req->argv[1]);
|
||||
}
|
||||
|
||||
/* Wer ist der Absender? */
|
||||
if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix );
|
||||
else target = Client;
|
||||
if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
|
||||
|
||||
c = Client_First( );
|
||||
while( c )
|
||||
{
|
||||
if( Client_Type( c ) == CLIENT_SERVER )
|
||||
{
|
||||
if( ! IRC_WriteStrClient( target, RPL_LINKS_MSG, Client_ID( target ), Client_ID( c ), Client_ID( Client_TopServer( c ) ? Client_TopServer( c ) : Client_ThisServer( )), Client_Hops( c ), Client_Info( c ))) return DISCONNECTED;
|
||||
c = Client_First();
|
||||
while (c) {
|
||||
if (Client_Type(c) == CLIENT_SERVER
|
||||
&& MatchCaseInsensitive(mask, Client_ID(c))) {
|
||||
if (!IRC_WriteStrClient(from, RPL_LINKS_MSG,
|
||||
Client_ID(from), Client_ID(c),
|
||||
Client_ID(Client_TopServer(c)
|
||||
? Client_TopServer(c)
|
||||
: Client_ThisServer()),
|
||||
Client_Hops(c), Client_Info(c)))
|
||||
return DISCONNECTED;
|
||||
}
|
||||
c = Client_Next( c );
|
||||
c = Client_Next(c);
|
||||
}
|
||||
|
||||
IRC_SetPenalty( target, 1 );
|
||||
return IRC_WriteStrClient( target, RPL_ENDOFLINKS_MSG, Client_ID( target ), mask );
|
||||
return IRC_WriteStrClient(from, RPL_ENDOFLINKS_MSG,
|
||||
Client_ID(from), mask);
|
||||
} /* IRC_LINKS */
|
||||
|
||||
|
||||
@@ -478,6 +513,8 @@ IRC_STATS( CLIENT *Client, REQUEST *Req )
|
||||
COMMAND *cmd;
|
||||
time_t time_now;
|
||||
unsigned int days, hrs, mins;
|
||||
struct list_head *list;
|
||||
struct list_elem *list_item;
|
||||
|
||||
assert(Client != NULL);
|
||||
assert(Req != NULL);
|
||||
@@ -516,6 +553,28 @@ IRC_STATS( CLIENT *Client, REQUEST *Req )
|
||||
query = '*';
|
||||
|
||||
switch (query) {
|
||||
case 'g': /* Network-wide bans ("G-Lines") */
|
||||
case 'G':
|
||||
case 'k': /* Server-local bans ("K-Lines") */
|
||||
case 'K':
|
||||
if (!Client_HasMode(from, 'o'))
|
||||
return IRC_WriteStrClient(from, ERR_NOPRIVILEGES_MSG,
|
||||
Client_ID(from));
|
||||
if (query == 'g' || query == 'G')
|
||||
list = Class_GetList(CLASS_GLINE);
|
||||
else
|
||||
list = Class_GetList(CLASS_KLINE);
|
||||
list_item = Lists_GetFirst(list);
|
||||
while (list_item) {
|
||||
if (!IRC_WriteStrClient(from, RPL_STATSXLINE_MSG,
|
||||
Client_ID(from), query,
|
||||
Lists_GetMask(list_item),
|
||||
Lists_GetValidity(list_item),
|
||||
Lists_GetReason(list_item)))
|
||||
return DISCONNECTED;
|
||||
list_item = Lists_GetNext(list_item);
|
||||
}
|
||||
break;
|
||||
case 'l': /* Link status (servers and own link) */
|
||||
case 'L':
|
||||
time_now = time(NULL);
|
||||
@@ -589,10 +648,10 @@ IRC_STATS( CLIENT *Client, REQUEST *Req )
|
||||
* therefore answers with ERR_SUMMONDISABLED.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_SUMMON(CLIENT * Client, REQUEST * Req)
|
||||
IRC_SUMMON(CLIENT * Client, UNUSED REQUEST * Req)
|
||||
{
|
||||
return IRC_WriteStrClient(Client, ERR_SUMMONDISABLED_MSG,
|
||||
Client_ID(Client), Req->command);
|
||||
Client_ID(Client));
|
||||
} /* IRC_SUMMON */
|
||||
|
||||
|
||||
@@ -682,10 +741,10 @@ IRC_USERHOST(CLIENT *Client, REQUEST *Req)
|
||||
* See RFC 2812 section 4.6. As suggested there the command is disabled.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_USERS(CLIENT * Client, REQUEST * Req)
|
||||
IRC_USERS(CLIENT * Client, UNUSED REQUEST * Req)
|
||||
{
|
||||
return IRC_WriteStrClient(Client, ERR_USERSDISABLED_MSG,
|
||||
Client_ID(Client), Req->command);
|
||||
Client_ID(Client));
|
||||
} /* IRC_USERS */
|
||||
|
||||
|
||||
@@ -758,8 +817,16 @@ who_flags_qualifier(const char *chan_user_modes)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send WHO reply for a "channel target" ("WHO #channel").
|
||||
*
|
||||
* @param Client Client requesting the information.
|
||||
* @param Chan Channel being requested.
|
||||
* @param OnlyOps Only display IRC operators.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
static bool
|
||||
IRC_Send_WHO(CLIENT *Client, CHANNEL *Chan, bool OnlyOps)
|
||||
IRC_WHO_Channel(CLIENT *Client, CHANNEL *Chan, bool OnlyOps)
|
||||
{
|
||||
bool is_visible, is_member, is_ircop;
|
||||
CL2CHAN *cl2chan;
|
||||
@@ -767,6 +834,7 @@ IRC_Send_WHO(CLIENT *Client, CHANNEL *Chan, bool OnlyOps)
|
||||
const char *chan_user_modes;
|
||||
char flags[8];
|
||||
CLIENT *c;
|
||||
int count = 0;
|
||||
|
||||
assert( Client != NULL );
|
||||
assert( Chan != NULL );
|
||||
@@ -775,7 +843,8 @@ IRC_Send_WHO(CLIENT *Client, CHANNEL *Chan, bool OnlyOps)
|
||||
|
||||
/* Secret channel? */
|
||||
if (!is_member && strchr(Channel_Modes(Chan), 's'))
|
||||
return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), Channel_Name(Chan));
|
||||
return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG,
|
||||
Client_ID(Client), Channel_Name(Chan));
|
||||
|
||||
cl2chan = Channel_FirstMember(Chan);
|
||||
for (; cl2chan ; cl2chan = Channel_NextMember(Chan, cl2chan)) {
|
||||
@@ -788,141 +857,178 @@ IRC_Send_WHO(CLIENT *Client, CHANNEL *Chan, bool OnlyOps)
|
||||
|
||||
is_visible = strchr(client_modes, 'i') == NULL;
|
||||
if (is_member || is_visible) {
|
||||
if (IRC_CheckListTooBig(Client, count, MAX_RPL_WHO, "WHO"))
|
||||
break;
|
||||
|
||||
strcpy(flags, who_flags_status(client_modes));
|
||||
if (is_ircop)
|
||||
strlcat(flags, "*", sizeof(flags));
|
||||
|
||||
chan_user_modes = Channel_UserModes(Chan, c);
|
||||
strlcat(flags, who_flags_qualifier(chan_user_modes), sizeof(flags));
|
||||
strlcat(flags, who_flags_qualifier(chan_user_modes),
|
||||
sizeof(flags));
|
||||
|
||||
if (!write_whoreply(Client, c, Channel_Name(Chan), flags))
|
||||
if (!write_whoreply(Client, c, Channel_Name(Chan),
|
||||
flags))
|
||||
return DISCONNECTED;
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), Channel_Name(Chan));
|
||||
} /* IRC_Send_WHO */
|
||||
return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client),
|
||||
Channel_Name(Chan));
|
||||
}
|
||||
|
||||
|
||||
GLOBAL bool
|
||||
IRC_WHO( CLIENT *Client, REQUEST *Req )
|
||||
/**
|
||||
* Send WHO reply for a "mask target" ("WHO m*sk").
|
||||
*
|
||||
* @param Client Client requesting the information.
|
||||
* @param Mask Mask being requested or NULL for "all" clients.
|
||||
* @param OnlyOps Only display IRC operators.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
static bool
|
||||
IRC_WHO_Mask(CLIENT *Client, char *Mask, bool OnlyOps)
|
||||
{
|
||||
bool only_ops, have_arg, client_match;
|
||||
const char *channelname, *client_modes, *chan_user_modes;
|
||||
char pattern[COMMAND_LEN];
|
||||
char flags[4];
|
||||
CL2CHAN *cl2chan;
|
||||
CHANNEL *chan, *cn;
|
||||
CLIENT *c;
|
||||
CL2CHAN *cl2chan;
|
||||
CHANNEL *chan;
|
||||
bool client_match, is_visible;
|
||||
char flags[4];
|
||||
int count = 0;
|
||||
|
||||
assert( Client != NULL );
|
||||
assert( Req != NULL );
|
||||
assert (Client != NULL);
|
||||
|
||||
if (Mask)
|
||||
ngt_LowerStr(Mask);
|
||||
|
||||
for (c = Client_First(); c != NULL; c = Client_Next(c)) {
|
||||
if (Client_Type(c) != CLIENT_USER)
|
||||
continue;
|
||||
|
||||
if (OnlyOps && !Client_HasMode(c, 'o'))
|
||||
continue;
|
||||
|
||||
if (Mask) {
|
||||
/* Match pattern against user host/server/name/nick */
|
||||
client_match = MatchCaseInsensitive(Mask,
|
||||
Client_Hostname(c));
|
||||
if (!client_match)
|
||||
client_match = MatchCaseInsensitive(Mask,
|
||||
Client_ID(Client_Introducer(c)));
|
||||
if (!client_match)
|
||||
client_match = MatchCaseInsensitive(Mask,
|
||||
Client_Info(c));
|
||||
if (!client_match)
|
||||
client_match = MatchCaseInsensitive(Mask,
|
||||
Client_ID(c));
|
||||
if (!client_match)
|
||||
continue; /* no match: skip this client */
|
||||
}
|
||||
|
||||
is_visible = !Client_HasMode(c, 'i');
|
||||
|
||||
/* Target client is invisible, but mask matches exactly? */
|
||||
if (!is_visible && Mask && strcasecmp(Client_ID(c), Mask) == 0)
|
||||
is_visible = true;
|
||||
|
||||
/* Target still invisible, but are both on the same channel? */
|
||||
if (!is_visible) {
|
||||
cl2chan = Channel_FirstChannelOf(Client);
|
||||
while (cl2chan && !is_visible) {
|
||||
chan = Channel_GetChannel(cl2chan);
|
||||
if (Channel_IsMemberOf(chan, c))
|
||||
is_visible = true;
|
||||
cl2chan = Channel_NextChannelOf(Client, cl2chan);
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_visible) /* target user is not visible */
|
||||
continue;
|
||||
|
||||
if (IRC_CheckListTooBig(Client, count, MAX_RPL_WHO, "WHO"))
|
||||
break;
|
||||
|
||||
strcpy(flags, who_flags_status(Client_Modes(c)));
|
||||
if (strchr(Client_Modes(c), 'o'))
|
||||
strlcat(flags, "*", sizeof(flags));
|
||||
|
||||
if (!write_whoreply(Client, c, "*", flags))
|
||||
return DISCONNECTED;
|
||||
count++;
|
||||
}
|
||||
|
||||
return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client),
|
||||
Mask ? Mask : "*");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handler for the IRC "WHO" command.
|
||||
*
|
||||
* See RFC 2812, 3.6.1 "Who query".
|
||||
*
|
||||
* @param Client The client from which this command has been received.
|
||||
* @param Req Request structure with prefix and all parameters.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_WHO(CLIENT *Client, REQUEST *Req)
|
||||
{
|
||||
bool only_ops;
|
||||
CHANNEL *chan;
|
||||
|
||||
assert (Client != NULL);
|
||||
assert (Req != NULL);
|
||||
|
||||
if (Req->argc > 2)
|
||||
return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
|
||||
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
|
||||
Client_ID(Client), Req->command);
|
||||
|
||||
only_ops = false;
|
||||
have_arg = false;
|
||||
|
||||
if (Req->argc == 2) {
|
||||
if (strcmp(Req->argv[1], "o") == 0)
|
||||
only_ops = true;
|
||||
#ifdef STRICT_RFC
|
||||
else return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, Client_ID(Client), Req->command);
|
||||
else
|
||||
return IRC_WriteStrClient(Client,
|
||||
ERR_NEEDMOREPARAMS_MSG,
|
||||
Client_ID(Client),
|
||||
Req->command);
|
||||
#endif
|
||||
}
|
||||
|
||||
IRC_SetPenalty(Client, 1);
|
||||
if (Req->argc >= 1) { /* Channel or Mask. */
|
||||
if (Req->argc >= 1) {
|
||||
/* Channel or mask given */
|
||||
chan = Channel_Search(Req->argv[0]);
|
||||
if (chan)
|
||||
return IRC_Send_WHO(Client, chan, only_ops);
|
||||
if (strcmp(Req->argv[0], "0") != 0) { /* RFC stupidity, same as no arguments */
|
||||
have_arg = true;
|
||||
strlcpy(pattern, Req->argv[0], sizeof(pattern));
|
||||
ngt_LowerStr(pattern);
|
||||
if (chan) {
|
||||
/* Members of a channel have been requested */
|
||||
IRC_SetPenalty(Client, 1);
|
||||
return IRC_WHO_Channel(Client, chan, only_ops);
|
||||
}
|
||||
if (strcmp(Req->argv[0], "0") != 0) {
|
||||
/* A mask has been given. But please note this RFC
|
||||
* stupidity: "0" is same as no arguments ... */
|
||||
IRC_SetPenalty(Client, 3);
|
||||
return IRC_WHO_Mask(Client, Req->argv[0], only_ops);
|
||||
}
|
||||
}
|
||||
|
||||
for (c = Client_First(); c != NULL; c = Client_Next(c)) {
|
||||
if (Client_Type(c) != CLIENT_USER)
|
||||
continue;
|
||||
/*
|
||||
* RFC 2812, 3.6.1:
|
||||
* In the absence of the parameter, all visible (users who aren't
|
||||
* invisible (user mode +i) and who don't have a common channel
|
||||
* with the requesting client) are listed.
|
||||
*
|
||||
* The same result can be achieved by using a [sic] of "0"
|
||||
* or any wildcard which will end up matching every visible user.
|
||||
*
|
||||
* The [sic] passed to WHO is matched against users' host, server, real name and
|
||||
* nickname if the channel cannot be found.
|
||||
*/
|
||||
client_modes = Client_Modes(c);
|
||||
if (strchr(client_modes, 'i'))
|
||||
continue;
|
||||
|
||||
if (only_ops && !strchr(client_modes, 'o'))
|
||||
continue;
|
||||
|
||||
if (have_arg) { /* match pattern against user host/server/name/nick */
|
||||
client_match = MatchCaseInsensitive(pattern, Client_Hostname(c)); /* user's host */
|
||||
if (!client_match)
|
||||
client_match = MatchCaseInsensitive(pattern, Client_ID(Client_Introducer(c))); /* server */
|
||||
if (!client_match)
|
||||
client_match = Match(Req->argv[0], Client_Info(c)); /* realname */
|
||||
if (!client_match)
|
||||
client_match = MatchCaseInsensitive(pattern, Client_ID(c)); /* nick name */
|
||||
|
||||
if (!client_match) /* This isn't the client you're looking for */
|
||||
continue;
|
||||
}
|
||||
|
||||
strcpy(flags, who_flags_status(client_modes));
|
||||
|
||||
if (strchr(client_modes, 'o')) /* this client is an operator */
|
||||
strlcat(flags, "*", sizeof(flags));
|
||||
|
||||
/* Search suitable channel */
|
||||
cl2chan = Channel_FirstChannelOf(c);
|
||||
while (cl2chan) {
|
||||
cn = Channel_GetChannel(cl2chan);
|
||||
if (Channel_IsMemberOf(cn, Client) ||
|
||||
!strchr(Channel_Modes(cn), 's'))
|
||||
{
|
||||
channelname = Channel_Name(cn);
|
||||
break;
|
||||
}
|
||||
cl2chan = Channel_NextChannelOf(c, cl2chan);
|
||||
}
|
||||
if (cl2chan) {
|
||||
chan = Channel_GetChannel(cl2chan);
|
||||
chan_user_modes = Channel_UserModes(chan, c);
|
||||
strlcat(flags, who_flags_qualifier(chan_user_modes), sizeof(flags));
|
||||
} else
|
||||
channelname = "*";
|
||||
|
||||
if (!write_whoreply(Client, c, channelname, flags))
|
||||
return DISCONNECTED;
|
||||
}
|
||||
|
||||
if (Req->argc > 0)
|
||||
channelname = Req->argv[0];
|
||||
else
|
||||
channelname = "*";
|
||||
|
||||
return IRC_WriteStrClient(Client, RPL_ENDOFWHO_MSG, Client_ID(Client), channelname);
|
||||
/* No channel or (valid) mask given */
|
||||
IRC_SetPenalty(Client, 2);
|
||||
return IRC_WHO_Mask(Client, NULL, only_ops);
|
||||
} /* IRC_WHO */
|
||||
|
||||
|
||||
/**
|
||||
* Generate WHOIS reply of one actual client.
|
||||
*
|
||||
* @param Client The client from which this command has been received.
|
||||
* @param from The client requesting the information ("originator").
|
||||
* @param c The client of which information should be returned.
|
||||
* @returns CONNECTED or DISCONNECTED.
|
||||
* @param Client The client from which this command has been received.
|
||||
* @param from The client requesting the information ("originator").
|
||||
* @param c The client of which information should be returned.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
static bool
|
||||
IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c)
|
||||
@@ -931,6 +1037,10 @@ IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c)
|
||||
CL2CHAN *cl2chan;
|
||||
CHANNEL *chan;
|
||||
|
||||
assert(Client != NULL);
|
||||
assert(from != NULL);
|
||||
assert(c != NULL);
|
||||
|
||||
/* Nick, user, hostname and client info */
|
||||
if (!IRC_WriteStrClient(from, RPL_WHOISUSER_MSG, Client_ID(from),
|
||||
Client_ID(c), Client_User(c),
|
||||
@@ -988,33 +1098,43 @@ IRC_WHOIS_SendReply(CLIENT *Client, CLIENT *from, CLIENT *c)
|
||||
|
||||
/* IRC-Operator? */
|
||||
if (Client_HasMode(c, 'o') &&
|
||||
!IRC_WriteStrClient(from, RPL_WHOISOPERATOR_MSG,
|
||||
Client_ID(from), Client_ID(c)))
|
||||
return DISCONNECTED;
|
||||
!IRC_WriteStrClient(from, RPL_WHOISOPERATOR_MSG,
|
||||
Client_ID(from), Client_ID(c)))
|
||||
return DISCONNECTED;
|
||||
|
||||
/* Connected using SSL? */
|
||||
if (Conn_UsesSSL(Client_Conn(c)) &&
|
||||
!IRC_WriteStrClient(from, RPL_WHOISSSL_MSG,
|
||||
Client_ID(from), Client_ID(c)))
|
||||
return DISCONNECTED;
|
||||
!IRC_WriteStrClient(from, RPL_WHOISSSL_MSG, Client_ID(from),
|
||||
Client_ID(c)))
|
||||
return DISCONNECTED;
|
||||
|
||||
/* Registered nick name? */
|
||||
if (Client_HasMode(c, 'R') &&
|
||||
!IRC_WriteStrClient(from, RPL_WHOISREGNICK_MSG,
|
||||
Client_ID(from), Client_ID(c)))
|
||||
return DISCONNECTED;
|
||||
|
||||
if (Client_Conn(c) > NONE && (Client_OperByMe(from) || from == c) &&
|
||||
!IRC_WriteStrClient(from, RPL_WHOISHOST_MSG, Client_ID(from),
|
||||
Client_ID(c), Client_Hostname(c),
|
||||
Conn_GetIPAInfo(Client_Conn(c))))
|
||||
return DISCONNECTED;
|
||||
|
||||
/* Idle and signon time (local clients only!) */
|
||||
if (!Conf_MorePrivacy && Client_Conn(c) > NONE &&
|
||||
!IRC_WriteStrClient(from, RPL_WHOISIDLE_MSG,
|
||||
Client_ID(from), Client_ID(c),
|
||||
(unsigned long)Conn_GetIdle(Client_Conn(c)),
|
||||
(unsigned long)Conn_GetSignon(Client_Conn(c))))
|
||||
return DISCONNECTED;
|
||||
!IRC_WriteStrClient(from, RPL_WHOISIDLE_MSG,
|
||||
Client_ID(from), Client_ID(c),
|
||||
(unsigned long)Conn_GetIdle(Client_Conn(c)),
|
||||
(unsigned long)Conn_GetSignon(Client_Conn(c))))
|
||||
return DISCONNECTED;
|
||||
|
||||
/* Away? */
|
||||
if (Client_HasMode(c, 'a') &&
|
||||
!IRC_WriteStrClient(from, RPL_AWAY_MSG,
|
||||
Client_ID(from), Client_ID(c),
|
||||
Client_Away(c)))
|
||||
return DISCONNECTED;
|
||||
!IRC_WriteStrClient(from, RPL_AWAY_MSG,
|
||||
Client_ID(from), Client_ID(c), Client_Away(c)))
|
||||
return DISCONNECTED;
|
||||
|
||||
return IRC_WriteStrClient(from, RPL_ENDOFWHOIS_MSG,
|
||||
Client_ID(from), Client_ID(c));
|
||||
return CONNECTED;
|
||||
} /* IRC_WHOIS_SendReply */
|
||||
|
||||
|
||||
@@ -1034,7 +1154,7 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req )
|
||||
unsigned int match_count = 0, found = 0;
|
||||
bool has_wildcards, is_remote;
|
||||
bool got_wildcard = false;
|
||||
const char *query;
|
||||
char mask[COMMAND_LEN], *query;
|
||||
|
||||
assert( Client != NULL );
|
||||
assert( Req != NULL );
|
||||
@@ -1075,7 +1195,8 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req )
|
||||
Req->argv[0], Req->argv[1]);
|
||||
|
||||
is_remote = Client_Conn(from) < 0;
|
||||
for (query = strtok(Req->argv[Req->argc - 1], ",");
|
||||
strlcpy(mask, Req->argv[Req->argc - 1], sizeof(mask));
|
||||
for (query = strtok(ngt_LowerStr(mask), ",");
|
||||
query && found < 3;
|
||||
query = strtok(NULL, ","), found++)
|
||||
{
|
||||
@@ -1086,11 +1207,11 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req )
|
||||
* - no wildcards for remote clients
|
||||
* - only one wildcard target per local client
|
||||
*
|
||||
* also, at most ten matches are returned.
|
||||
* Also, at most MAX_RPL_WHOIS matches are returned.
|
||||
*/
|
||||
if (!has_wildcards || is_remote) {
|
||||
c = Client_Search(query);
|
||||
if (c) {
|
||||
if (c && Client_Type(c) == CLIENT_USER) {
|
||||
if (!IRC_WHOIS_SendReply(Client, from, c))
|
||||
return DISCONNECTED;
|
||||
} else {
|
||||
@@ -1112,21 +1233,28 @@ IRC_WHOIS( CLIENT *Client, REQUEST *Req )
|
||||
got_wildcard = true;
|
||||
IRC_SetPenalty(Client, 3);
|
||||
|
||||
for (c = Client_First(); c && match_count < 10; c = Client_Next(c)) {
|
||||
for (c = Client_First(); c; c = Client_Next(c)) {
|
||||
if (IRC_CheckListTooBig(Client, match_count,
|
||||
MAX_RPL_WHOIS, "WHOIS"))
|
||||
break;
|
||||
|
||||
if (Client_Type(c) != CLIENT_USER)
|
||||
continue;
|
||||
if (!MatchCaseInsensitive(query, Client_ID(c)))
|
||||
continue;
|
||||
if (!IRC_WHOIS_SendReply(Client, from, c))
|
||||
return DISCONNECTED;
|
||||
|
||||
match_count++;
|
||||
}
|
||||
|
||||
if (match_count == 0)
|
||||
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
|
||||
Client_ID(Client), Req->argv[Req->argc - 1]);
|
||||
IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
|
||||
Client_ID(Client),
|
||||
Req->argv[Req->argc - 1]);
|
||||
}
|
||||
return CONNECTED;
|
||||
return IRC_WriteStrClient(from, RPL_ENDOFWHOIS_MSG,
|
||||
Client_ID(from), Req->argv[Req->argc - 1]);
|
||||
} /* IRC_WHOIS */
|
||||
|
||||
|
||||
@@ -1208,11 +1336,11 @@ IRC_WHOWAS( CLIENT *Client, REQUEST *Req )
|
||||
if (last < 0)
|
||||
last = 0;
|
||||
|
||||
max = DEFAULT_WHOWAS;
|
||||
max = DEF_RPL_WHOWAS;
|
||||
if (Req->argc > 1) {
|
||||
max = atoi(Req->argv[1]);
|
||||
if (max < 1)
|
||||
max = MAX_WHOWAS;
|
||||
max = MAX_RPL_WHOWAS;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1251,38 +1379,55 @@ IRC_WHOWAS( CLIENT *Client, REQUEST *Req )
|
||||
} /* IRC_WHOWAS */
|
||||
|
||||
|
||||
/**
|
||||
* Send LUSERS reply to a client.
|
||||
*
|
||||
* @param Client The receipient of the information.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_Send_LUSERS( CLIENT *Client )
|
||||
IRC_Send_LUSERS(CLIENT *Client)
|
||||
{
|
||||
unsigned long cnt;
|
||||
#ifndef STRICT_RFC
|
||||
unsigned long max;
|
||||
#endif
|
||||
|
||||
assert( Client != NULL );
|
||||
assert(Client != NULL);
|
||||
|
||||
/* Users, services and serevers in the network */
|
||||
if( ! IRC_WriteStrClient( Client, RPL_LUSERCLIENT_MSG, Client_ID( Client ), Client_UserCount( ), Client_ServiceCount( ), Client_ServerCount( ))) return DISCONNECTED;
|
||||
if (!IRC_WriteStrClient(Client, RPL_LUSERCLIENT_MSG, Client_ID(Client),
|
||||
Client_UserCount(), Client_ServiceCount(),
|
||||
Client_ServerCount()))
|
||||
return DISCONNECTED;
|
||||
|
||||
/* Number of IRC operators */
|
||||
cnt = Client_OperCount( );
|
||||
if( cnt > 0 )
|
||||
{
|
||||
if( ! IRC_WriteStrClient( Client, RPL_LUSEROP_MSG, Client_ID( Client ), cnt )) return DISCONNECTED;
|
||||
if (cnt > 0) {
|
||||
if (!IRC_WriteStrClient(Client, RPL_LUSEROP_MSG,
|
||||
Client_ID(Client), cnt))
|
||||
return DISCONNECTED;
|
||||
}
|
||||
|
||||
/* Unknown connections */
|
||||
cnt = Client_UnknownCount( );
|
||||
if( cnt > 0 )
|
||||
{
|
||||
if( ! IRC_WriteStrClient( Client, RPL_LUSERUNKNOWN_MSG, Client_ID( Client ), cnt )) return DISCONNECTED;
|
||||
if (cnt > 0) {
|
||||
if (!IRC_WriteStrClient(Client, RPL_LUSERUNKNOWN_MSG,
|
||||
Client_ID(Client), cnt))
|
||||
return DISCONNECTED;
|
||||
}
|
||||
|
||||
/* Number of created channels */
|
||||
if( ! IRC_WriteStrClient( Client, RPL_LUSERCHANNELS_MSG, Client_ID( Client ), Channel_Count( ))) return DISCONNECTED;
|
||||
if (!IRC_WriteStrClient(Client, RPL_LUSERCHANNELS_MSG,
|
||||
Client_ID(Client),
|
||||
Channel_CountVisible(Client)))
|
||||
return DISCONNECTED;
|
||||
|
||||
/* Number of local users, services and servers */
|
||||
if( ! IRC_WriteStrClient( Client, RPL_LUSERME_MSG, Client_ID( Client ), Client_MyUserCount( ), Client_MyServiceCount( ), Client_MyServerCount( ))) return DISCONNECTED;
|
||||
if (!IRC_WriteStrClient(Client, RPL_LUSERME_MSG, Client_ID(Client),
|
||||
Client_MyUserCount(), Client_MyServiceCount(),
|
||||
Client_MyServerCount()))
|
||||
return DISCONNECTED;
|
||||
|
||||
#ifndef STRICT_RFC
|
||||
/* Maximum number of local users */
|
||||
@@ -1453,7 +1598,8 @@ IRC_Send_ISUPPORT(CLIENT * Client)
|
||||
return IRC_WriteStrClient(Client, RPL_ISUPPORT2_MSG, Client_ID(Client),
|
||||
CHANNEL_NAME_LEN - 1, Conf_MaxNickLength - 1,
|
||||
COMMAND_LEN - 23, CLIENT_AWAY_LEN - 1,
|
||||
COMMAND_LEN - 113);
|
||||
COMMAND_LEN - 113, MAX_HNDL_MODES_ARG,
|
||||
MAX_HNDL_CHANNEL_LISTS);
|
||||
} /* IRC_Send_ISUPPORT */
|
||||
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2010 Alexander Barton (alex@barton.de)
|
||||
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -27,6 +27,7 @@
|
||||
|
||||
#include "ngircd.h"
|
||||
#include "conn-func.h"
|
||||
#include "class.h"
|
||||
#include "conf.h"
|
||||
#include "channel.h"
|
||||
#include "io.h"
|
||||
@@ -46,7 +47,6 @@ static bool Hello_User PARAMS(( CLIENT *Client ));
|
||||
static bool Hello_User_PostAuth PARAMS(( CLIENT *Client ));
|
||||
static void Kill_Nick PARAMS(( char *Nick, char *Reason ));
|
||||
static void Introduce_Client PARAMS((CLIENT *To, CLIENT *Client, int Type));
|
||||
static void Reject_Client PARAMS((CLIENT *Client));
|
||||
|
||||
static void cb_introduceClient PARAMS((CLIENT *Client, CLIENT *Prefix,
|
||||
void *i));
|
||||
@@ -653,32 +653,37 @@ IRC_QUIT( CLIENT *Client, REQUEST *Req )
|
||||
CLIENT *target;
|
||||
char quitmsg[LINE_LEN];
|
||||
|
||||
assert( Client != NULL );
|
||||
assert( Req != NULL );
|
||||
assert(Client != NULL);
|
||||
assert(Req != NULL);
|
||||
|
||||
/* Wrong number of arguments? */
|
||||
if( Req->argc > 1 )
|
||||
return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
|
||||
if (Req->argc > 1)
|
||||
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
|
||||
Client_ID(Client), Req->command);
|
||||
|
||||
if (Req->argc == 1)
|
||||
strlcpy(quitmsg, Req->argv[0], sizeof quitmsg);
|
||||
|
||||
if ( Client_Type( Client ) == CLIENT_SERVER )
|
||||
{
|
||||
if (Client_Type(Client) == CLIENT_SERVER) {
|
||||
/* Server */
|
||||
target = Client_Search( Req->prefix );
|
||||
if( ! target )
|
||||
{
|
||||
Log( LOG_WARNING, "Got QUIT from %s for unknown client!?", Client_ID( Client ));
|
||||
target = Client_Search(Req->prefix);
|
||||
if (!target) {
|
||||
Log(LOG_WARNING,
|
||||
"Got QUIT from %s for unknown client!?",
|
||||
Client_ID(Client));
|
||||
return CONNECTED;
|
||||
}
|
||||
|
||||
Client_Destroy( target, "Got QUIT command.", Req->argc == 1 ? quitmsg : NULL, true);
|
||||
|
||||
return CONNECTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (target != Client) {
|
||||
Client_Destroy(target, "Got QUIT command.",
|
||||
Req->argc == 1 ? quitmsg : NULL, true);
|
||||
return CONNECTED;
|
||||
} else {
|
||||
Conn_Close(Client_Conn(Client), "Got QUIT command.",
|
||||
Req->argc == 1 ? quitmsg : NULL, true);
|
||||
return DISCONNECTED;
|
||||
}
|
||||
} else {
|
||||
if (Req->argc == 1 && quitmsg[0] != '\"') {
|
||||
/* " " to avoid confusion */
|
||||
strlcpy(quitmsg, "\"", sizeof quitmsg);
|
||||
@@ -687,7 +692,8 @@ IRC_QUIT( CLIENT *Client, REQUEST *Req )
|
||||
}
|
||||
|
||||
/* User, Service, or not yet registered */
|
||||
Conn_Close( Client_Conn( Client ), "Got QUIT command.", Req->argc == 1 ? quitmsg : NULL, true);
|
||||
Conn_Close(Client_Conn(Client), "Got QUIT command.",
|
||||
Req->argc == 1 ? quitmsg : NULL, true);
|
||||
|
||||
return DISCONNECTED;
|
||||
}
|
||||
@@ -883,15 +889,16 @@ IRC_PONG(CLIENT *Client, REQUEST *Req)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
if (conn > NONE)
|
||||
Log(LOG_DEBUG,
|
||||
"Connection %d: received PONG. Lag: %ld seconds.", conn,
|
||||
time(NULL) - Conn_LastPing(Client_Conn(Client)));
|
||||
else
|
||||
Log(LOG_DEBUG,
|
||||
"Connection %d: received PONG.", conn);
|
||||
#endif
|
||||
if (Client_Type(Client) == CLIENT_SERVER && Conn_LastPing(conn) == 0) {
|
||||
Log(LOG_INFO,
|
||||
"Synchronization with \"%s\" done (connection %d): %ld seconds [%ld users, %ld channels]",
|
||||
Client_ID(Client), conn, time(NULL) - Conn_GetSignon(conn),
|
||||
Client_UserCount(), Channel_CountVisible(NULL));
|
||||
Conn_UpdatePing(conn);
|
||||
} else
|
||||
LogDebug("Connection %d: received PONG. Lag: %ld seconds.",
|
||||
conn, time(NULL) - Conn_LastPing(conn));
|
||||
|
||||
return CONNECTED;
|
||||
} /* IRC_PONG */
|
||||
|
||||
@@ -938,10 +945,19 @@ Hello_User(CLIENT * Client)
|
||||
* passwords supplied are classified as "wrong". */
|
||||
if(Client_Password(Client)[0] == '\0')
|
||||
return Hello_User_PostAuth(Client);
|
||||
Reject_Client(Client);
|
||||
Client_Reject(Client, "Non-empty password", false);
|
||||
return DISCONNECTED;
|
||||
}
|
||||
|
||||
if (Conf_PAMIsOptional && strcmp(Client_Password(Client), "") == 0) {
|
||||
/* Clients are not required to send a password and to be PAM-
|
||||
* authenticated at all. If not, they won't become "identified"
|
||||
* and keep the "~" in their supplied user name.
|
||||
* Therefore it is sensible to either set Conf_PAMisOptional or
|
||||
* to enable IDENT lookups -- not both. */
|
||||
return Hello_User_PostAuth(Client);
|
||||
}
|
||||
|
||||
/* Fork child process for PAM authentication; and make sure that the
|
||||
* process timeout is set higher than the login timeout! */
|
||||
pid = Proc_Fork(Conn_GetProcStat(conn), pipefd,
|
||||
@@ -953,6 +969,7 @@ Hello_User(CLIENT * Client)
|
||||
} else {
|
||||
/* Sub process */
|
||||
Log_Init_Subprocess("Auth");
|
||||
Conn_CloseAllSockets(NONE);
|
||||
result = PAM_Authenticate(Client);
|
||||
if (write(pipefd[1], &result, sizeof(result)) != sizeof(result))
|
||||
Log_Subprocess(LOG_ERR,
|
||||
@@ -964,7 +981,7 @@ Hello_User(CLIENT * Client)
|
||||
/* Check global server password ... */
|
||||
if (strcmp(Client_Password(Client), Conf_ServerPwd) != 0) {
|
||||
/* Bad password! */
|
||||
Reject_Client(Client);
|
||||
Client_Reject(Client, "Bad server password", false);
|
||||
return DISCONNECTED;
|
||||
}
|
||||
return Hello_User_PostAuth(Client);
|
||||
@@ -1003,12 +1020,13 @@ cb_Read_Auth_Result(int r_fd, UNUSED short events)
|
||||
|
||||
/* Read result from pipe */
|
||||
len = Proc_Read(proc, &result, sizeof(result));
|
||||
Proc_Close(proc);
|
||||
if (len == 0)
|
||||
return;
|
||||
|
||||
if (len != sizeof(result)) {
|
||||
Log(LOG_CRIT, "Auth: Got malformed result!");
|
||||
Reject_Client(client);
|
||||
Client_Reject(client, "Internal error", false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1016,31 +1034,12 @@ cb_Read_Auth_Result(int r_fd, UNUSED short events)
|
||||
Client_SetUser(client, Client_OrigUser(client), true);
|
||||
(void)Hello_User_PostAuth(client);
|
||||
} else
|
||||
Reject_Client(client);
|
||||
Client_Reject(client, "Bad password", false);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* Reject a client because of wrong password.
|
||||
*
|
||||
* This function is called either when the global server password or a password
|
||||
* checked using PAM has been wrong.
|
||||
*
|
||||
* @param Client The client to reject.
|
||||
*/
|
||||
static void
|
||||
Reject_Client(CLIENT *Client)
|
||||
{
|
||||
Log(LOG_ERR,
|
||||
"User \"%s\" rejected (connection %d): Access denied!",
|
||||
Client_Mask(Client), Client_Conn(Client));
|
||||
Conn_Close(Client_Conn(Client), NULL,
|
||||
"Access denied! Bad password?", true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finish client registration.
|
||||
*
|
||||
@@ -1053,6 +1052,11 @@ Reject_Client(CLIENT *Client)
|
||||
static bool
|
||||
Hello_User_PostAuth(CLIENT *Client)
|
||||
{
|
||||
assert(Client != NULL);
|
||||
|
||||
if (Class_HandleServerBans(Client) != CONNECTED)
|
||||
return DISCONNECTED;
|
||||
|
||||
Introduce_Client(NULL, Client, CLIENT_USER);
|
||||
|
||||
if (!IRC_WriteStrClient
|
||||
@@ -1096,20 +1100,22 @@ Hello_User_PostAuth(CLIENT *Client)
|
||||
* @param Reason Reason for the KILL.
|
||||
*/
|
||||
static void
|
||||
Kill_Nick( char *Nick, char *Reason )
|
||||
Kill_Nick(char *Nick, char *Reason)
|
||||
{
|
||||
REQUEST r;
|
||||
|
||||
assert( Nick != NULL );
|
||||
assert( Reason != NULL );
|
||||
assert (Nick != NULL);
|
||||
assert (Reason != NULL);
|
||||
|
||||
r.prefix = (char *)Client_ThisServer( );
|
||||
r.prefix = NULL;
|
||||
r.argv[0] = Nick;
|
||||
r.argv[1] = Reason;
|
||||
r.argc = 2;
|
||||
|
||||
Log( LOG_ERR, "User(s) with nick \"%s\" will be disconnected: %s", Nick, Reason );
|
||||
IRC_KILL( Client_ThisServer( ), &r );
|
||||
Log(LOG_ERR, "User(s) with nick \"%s\" will be disconnected: %s",
|
||||
Nick, Reason);
|
||||
|
||||
IRC_KILL(Client_ThisServer(), &r);
|
||||
} /* Kill_Nick */
|
||||
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
|
||||
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -36,39 +36,54 @@
|
||||
#include "irc-mode.h"
|
||||
|
||||
|
||||
static bool Client_Mode PARAMS(( CLIENT *Client, REQUEST *Req, CLIENT *Origin,
|
||||
CLIENT *Target ));
|
||||
static bool Channel_Mode PARAMS(( CLIENT *Client, REQUEST *Req, CLIENT *Origin,
|
||||
CHANNEL *Channel ));
|
||||
static bool Client_Mode PARAMS((CLIENT *Client, REQUEST *Req, CLIENT *Origin,
|
||||
CLIENT *Target));
|
||||
static bool Channel_Mode PARAMS((CLIENT *Client, REQUEST *Req, CLIENT *Origin,
|
||||
CHANNEL *Channel));
|
||||
|
||||
static bool Add_Ban_Invite PARAMS((int what, CLIENT *Prefix, CLIENT *Client,
|
||||
CHANNEL *Channel, const char *Pattern));
|
||||
static bool Del_Ban_Invite PARAMS((int what, CLIENT *Prefix, CLIENT *Client,
|
||||
CHANNEL *Channel, const char *Pattern));
|
||||
static bool Add_To_List PARAMS((char what, CLIENT *Prefix, CLIENT *Client,
|
||||
CHANNEL *Channel, const char *Pattern));
|
||||
static bool Del_From_List PARAMS((char what, CLIENT *Prefix, CLIENT *Client,
|
||||
CHANNEL *Channel, const char *Pattern));
|
||||
|
||||
static bool Send_ListChange PARAMS((const char *Mode, CLIENT *Prefix,
|
||||
CLIENT *Client, CHANNEL *Channel, const char *Mask));
|
||||
static bool Send_ListChange PARAMS((const bool IsAdd, const char ModeChar,
|
||||
CLIENT *Prefix, CLIENT *Client,
|
||||
CHANNEL *Channel, const char *Mask));
|
||||
|
||||
|
||||
/**
|
||||
* Handler for the IRC "MODE" command.
|
||||
*
|
||||
* See RFC 2812 section 3.1.5 ("user mode message") and section 3.2.3
|
||||
* ("channel mode message"), and RFC 2811 section 4 ("channel modes").
|
||||
*
|
||||
* @param Client The client from which this command has been received.
|
||||
* @param Req Request structure with prefix and all parameters.
|
||||
* @returns CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_MODE( CLIENT *Client, REQUEST *Req )
|
||||
{
|
||||
CLIENT *cl, *origin;
|
||||
CHANNEL *chan;
|
||||
|
||||
assert( Client != NULL );
|
||||
assert( Req != NULL );
|
||||
assert(Client != NULL);
|
||||
assert(Req != NULL);
|
||||
|
||||
/* No parameters? */
|
||||
if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
|
||||
if (Req->argc < 1)
|
||||
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
|
||||
Client_ID(Client), Req->command);
|
||||
|
||||
/* Origin for answers */
|
||||
if( Client_Type( Client ) == CLIENT_SERVER )
|
||||
{
|
||||
origin = Client_Search( Req->prefix );
|
||||
if( ! origin ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
|
||||
}
|
||||
else origin = Client;
|
||||
if (Client_Type(Client) == CLIENT_SERVER) {
|
||||
origin = Client_Search(Req->prefix);
|
||||
if (!origin)
|
||||
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
|
||||
Client_ID(Client),
|
||||
Req->prefix);
|
||||
} else
|
||||
origin = Client;
|
||||
|
||||
/* Channel or user mode? */
|
||||
cl = NULL; chan = NULL;
|
||||
@@ -88,178 +103,242 @@ IRC_MODE( CLIENT *Client, REQUEST *Req )
|
||||
} /* IRC_MODE */
|
||||
|
||||
|
||||
/**
|
||||
* Check if the "mode limit" for a client has been reached.
|
||||
*
|
||||
* This limit doesn't apply for servers or services!
|
||||
*
|
||||
* @param Client The client to check.
|
||||
* @param Count The number of modes already handled.
|
||||
* @return true if the limit has been reached.
|
||||
*/
|
||||
static bool
|
||||
Mode_Limit_Reached(CLIENT *Client, int Count)
|
||||
{
|
||||
if (Client_Type(Client) == CLIENT_SERVER
|
||||
|| Client_Type(Client) == CLIENT_SERVICE)
|
||||
return false;
|
||||
if (Count < MAX_HNDL_MODES_ARG)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Handle client mode requests
|
||||
*
|
||||
* @param Client The client from which this command has been received.
|
||||
* @param Req Request structure with prefix and all parameters.
|
||||
* @param Origin The originator of the MODE command (prefix).
|
||||
* @param Target The target (client) of this MODE command.
|
||||
* @returns CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
static bool
|
||||
Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )
|
||||
{
|
||||
/* Handle client mode requests */
|
||||
|
||||
char the_modes[COMMAND_LEN], x[2], *mode_ptr;
|
||||
bool ok, set;
|
||||
int mode_arg;
|
||||
size_t len;
|
||||
|
||||
/* Is the client allowed to request or change the modes? */
|
||||
if( Client_Type( Client ) == CLIENT_USER )
|
||||
{
|
||||
if (Client_Type(Client) == CLIENT_USER) {
|
||||
/* Users are only allowed to manipulate their own modes! */
|
||||
if( Target != Client ) return IRC_WriteStrClient( Client, ERR_USERSDONTMATCH_MSG, Client_ID( Client ));
|
||||
if (Target != Client)
|
||||
return IRC_WriteStrClient(Client,
|
||||
ERR_USERSDONTMATCH_MSG,
|
||||
Client_ID(Client));
|
||||
}
|
||||
|
||||
/* Mode request: let's answer it :-) */
|
||||
if( Req->argc == 1 ) return IRC_WriteStrClient( Origin, RPL_UMODEIS_MSG, Client_ID( Origin ), Client_Modes( Target ));
|
||||
if (Req->argc == 1)
|
||||
return IRC_WriteStrClient(Origin, RPL_UMODEIS_MSG,
|
||||
Client_ID(Origin),
|
||||
Client_Modes(Target));
|
||||
|
||||
mode_arg = 1;
|
||||
mode_ptr = Req->argv[mode_arg];
|
||||
|
||||
/* Initial state: set or unset modes? */
|
||||
if( *mode_ptr == '+' ) set = true;
|
||||
else if( *mode_ptr == '-' ) set = false;
|
||||
else return IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Origin ));
|
||||
|
||||
/* Prepare reply string */
|
||||
if( set ) strcpy( the_modes, "+" );
|
||||
else strcpy( the_modes, "-" );
|
||||
if (*mode_ptr == '+') {
|
||||
set = true;
|
||||
strcpy(the_modes, "+");
|
||||
} else if (*mode_ptr == '-') {
|
||||
set = false;
|
||||
strcpy(the_modes, "-");
|
||||
} else
|
||||
return IRC_WriteStrClient(Origin, ERR_UMODEUNKNOWNFLAG_MSG,
|
||||
Client_ID(Origin));
|
||||
|
||||
x[1] = '\0';
|
||||
ok = CONNECTED;
|
||||
while( mode_ptr )
|
||||
{
|
||||
while (mode_ptr) {
|
||||
mode_ptr++;
|
||||
if( ! *mode_ptr )
|
||||
{
|
||||
if (!*mode_ptr) {
|
||||
/* Try next argument if there's any */
|
||||
mode_arg++;
|
||||
if( mode_arg < Req->argc ) mode_ptr = Req->argv[mode_arg];
|
||||
else break;
|
||||
if (mode_arg < Req->argc)
|
||||
mode_ptr = Req->argv[mode_arg];
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
switch( *mode_ptr )
|
||||
{
|
||||
case '+':
|
||||
case '-':
|
||||
if((( *mode_ptr == '+' ) && ( ! set )) || (( *mode_ptr == '-' ) && ( set )))
|
||||
{
|
||||
/* Action modifier ("+"/"-") must be changed ... */
|
||||
len = strlen( the_modes ) - 1;
|
||||
if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' ))
|
||||
{
|
||||
/* Adjust last action modifier in result */
|
||||
the_modes[len] = *mode_ptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Append modifier character to result string */
|
||||
x[0] = *mode_ptr;
|
||||
strlcat( the_modes, x, sizeof( the_modes ));
|
||||
}
|
||||
if( *mode_ptr == '+' ) set = true;
|
||||
else set = false;
|
||||
|
||||
switch(*mode_ptr) {
|
||||
case '+':
|
||||
case '-':
|
||||
if ((*mode_ptr == '+' && !set)
|
||||
|| (*mode_ptr == '-' && set)) {
|
||||
/* Action modifier ("+"/"-") must be changed */
|
||||
len = strlen(the_modes) - 1;
|
||||
if (the_modes[len] == '+'
|
||||
|| the_modes[len] == '-') {
|
||||
/* Last character in the "result
|
||||
* string" was an "action", so just
|
||||
* overwrite it with the new action */
|
||||
the_modes[len] = *mode_ptr;
|
||||
} else {
|
||||
/* Append new modifier character to
|
||||
* the resulting mode string */
|
||||
x[0] = *mode_ptr;
|
||||
strlcat(the_modes, x,
|
||||
sizeof(the_modes));
|
||||
}
|
||||
continue;
|
||||
if (*mode_ptr == '+')
|
||||
set = true;
|
||||
else
|
||||
set = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
/* Validate modes */
|
||||
x[0] = '\0';
|
||||
switch( *mode_ptr )
|
||||
{
|
||||
case 'i': /* Invisible */
|
||||
case 's': /* Server messages */
|
||||
case 'w': /* Wallops messages */
|
||||
x[0] = *mode_ptr;
|
||||
break;
|
||||
|
||||
case 'a': /* Away */
|
||||
if( Client_Type( Client ) == CLIENT_SERVER )
|
||||
{
|
||||
x[0] = 'a';
|
||||
Client_SetAway( Origin, DEFAULT_AWAY_MSG );
|
||||
}
|
||||
else ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin ));
|
||||
break;
|
||||
|
||||
case 'c': /* Receive connect notices
|
||||
* (only settable by IRC operators!) */
|
||||
if(!set || Client_OperByMe(Origin)
|
||||
|| Client_Type(Client) == CLIENT_SERVER)
|
||||
x[0] = 'c';
|
||||
else
|
||||
ok = IRC_WriteStrClient(Origin,
|
||||
switch (*mode_ptr) {
|
||||
case 'C': /* Only messages from clients sharing a channel */
|
||||
case 'i': /* Invisible */
|
||||
case 's': /* Server messages */
|
||||
case 'w': /* Wallops messages */
|
||||
x[0] = *mode_ptr;
|
||||
break;
|
||||
case 'a': /* Away */
|
||||
if (Client_Type(Client) == CLIENT_SERVER) {
|
||||
x[0] = 'a';
|
||||
Client_SetAway(Origin, DEFAULT_AWAY_MSG);
|
||||
} else
|
||||
ok = IRC_WriteStrClient(Origin,
|
||||
ERR_NOPRIVILEGES_MSG,
|
||||
Client_ID(Origin));
|
||||
break;
|
||||
|
||||
case 'o': /* IRC operator (only unsettable!) */
|
||||
if(( ! set ) || ( Client_Type( Client ) == CLIENT_SERVER ))
|
||||
{
|
||||
Client_SetOperByMe( Target, false );
|
||||
x[0] = 'o';
|
||||
}
|
||||
else ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin ));
|
||||
break;
|
||||
|
||||
case 'r': /* Restricted (only settable) */
|
||||
if(( set ) || ( Client_Type( Client ) == CLIENT_SERVER )) x[0] = 'r';
|
||||
else ok = IRC_WriteStrClient( Origin, ERR_RESTRICTED_MSG, Client_ID( Origin ));
|
||||
break;
|
||||
|
||||
case 'x': /* Cloak hostname */
|
||||
if (Client_HasMode(Client, 'r'))
|
||||
ok = IRC_WriteStrClient(Origin,
|
||||
ERR_RESTRICTED_MSG,
|
||||
Client_ID(Origin));
|
||||
else
|
||||
x[0] = 'x';
|
||||
break;
|
||||
|
||||
default:
|
||||
Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", set ? '+' : '-', *mode_ptr, Client_ID( Origin ));
|
||||
if( Client_Type( Client ) != CLIENT_SERVER ) ok = IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Origin ), set ? '+' : '-', *mode_ptr );
|
||||
break;
|
||||
case 'c': /* Receive connect notices
|
||||
* (only settable by IRC operators!) */
|
||||
if (!set || Client_Type(Client) == CLIENT_SERVER
|
||||
|| Client_OperByMe(Origin))
|
||||
x[0] = 'c';
|
||||
else
|
||||
ok = IRC_WriteStrClient(Origin,
|
||||
ERR_NOPRIVILEGES_MSG,
|
||||
Client_ID(Origin));
|
||||
break;
|
||||
case 'o': /* IRC operator (only unsettable!) */
|
||||
if (!set || Client_Type(Client) == CLIENT_SERVER) {
|
||||
Client_SetOperByMe(Target, false);
|
||||
x[0] = 'o';
|
||||
} else
|
||||
ok = IRC_WriteStrClient(Origin,
|
||||
ERR_NOPRIVILEGES_MSG,
|
||||
Client_ID(Origin));
|
||||
break;
|
||||
case 'r': /* Restricted (only settable) */
|
||||
if (set || Client_Type(Client) == CLIENT_SERVER)
|
||||
x[0] = 'r';
|
||||
else
|
||||
ok = IRC_WriteStrClient(Origin,
|
||||
ERR_RESTRICTED_MSG,
|
||||
Client_ID(Origin));
|
||||
break;
|
||||
case 'x': /* Cloak hostname */
|
||||
if (Client_HasMode(Client, 'r'))
|
||||
ok = IRC_WriteStrClient(Origin,
|
||||
ERR_RESTRICTED_MSG,
|
||||
Client_ID(Origin));
|
||||
else
|
||||
x[0] = 'x';
|
||||
break;
|
||||
default:
|
||||
if (Client_Type(Client) != CLIENT_SERVER) {
|
||||
Log(LOG_DEBUG,
|
||||
"Unknown mode \"%c%c\" from \"%s\"!?",
|
||||
set ? '+' : '-', *mode_ptr,
|
||||
Client_ID(Origin));
|
||||
ok = IRC_WriteStrClient(Origin,
|
||||
ERR_UMODEUNKNOWNFLAG2_MSG,
|
||||
Client_ID(Origin),
|
||||
set ? '+' : '-',
|
||||
*mode_ptr);
|
||||
x[0] = '\0';
|
||||
goto client_exit;
|
||||
} else {
|
||||
Log(LOG_DEBUG,
|
||||
"Handling unknown mode \"%c%c\" from \"%s\" for \"%s\" ...",
|
||||
set ? '+' : '-', *mode_ptr,
|
||||
Client_ID(Origin), Client_ID(Target));
|
||||
x[0] = *mode_ptr;
|
||||
}
|
||||
}
|
||||
if( ! ok ) break;
|
||||
|
||||
if (!ok)
|
||||
break;
|
||||
|
||||
/* Is there a valid mode change? */
|
||||
if( ! x[0] ) continue;
|
||||
|
||||
if( set )
|
||||
{
|
||||
/* Set mode */
|
||||
if( Client_ModeAdd( Target, x[0] )) strlcat( the_modes, x, sizeof( the_modes ));
|
||||
if (!x[0])
|
||||
continue;
|
||||
|
||||
if (set) {
|
||||
if (Client_ModeAdd(Target, x[0]))
|
||||
strlcat(the_modes, x, sizeof(the_modes));
|
||||
} else {
|
||||
if (Client_ModeDel(Target, x[0]))
|
||||
strlcat(the_modes, x, sizeof(the_modes));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unset mode */
|
||||
if( Client_ModeDel( Target, x[0] )) strlcat( the_modes, x, sizeof( the_modes ));
|
||||
}
|
||||
}
|
||||
client_exit:
|
||||
|
||||
/* Are there changed modes? */
|
||||
if( the_modes[1] )
|
||||
{
|
||||
/* Remoce needless action modifier characters */
|
||||
len = strlen( the_modes ) - 1;
|
||||
if(( the_modes[len] == '+' ) || ( the_modes[len] == '-' )) the_modes[len] = '\0';
|
||||
|
||||
if( Client_Type( Client ) == CLIENT_SERVER )
|
||||
{
|
||||
/* Are there changed modes? */
|
||||
if (the_modes[1]) {
|
||||
/* Remove needless action modifier characters */
|
||||
len = strlen(the_modes) - 1;
|
||||
if (the_modes[len] == '+' || the_modes[len] == '-')
|
||||
the_modes[len] = '\0';
|
||||
|
||||
if (Client_Type(Client) == CLIENT_SERVER) {
|
||||
/* Forward modes to other servers */
|
||||
IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Client_Conn(Target) != NONE) {
|
||||
/* Remote server (service?) changed modes
|
||||
* for one of our clients. Inform it! */
|
||||
IRC_WriteStrClientPrefix(Target, Origin,
|
||||
"MODE %s :%s",
|
||||
Client_ID(Target),
|
||||
the_modes);
|
||||
}
|
||||
IRC_WriteStrServersPrefix(Client, Origin,
|
||||
"MODE %s :%s",
|
||||
Client_ID(Target),
|
||||
the_modes);
|
||||
} else {
|
||||
/* Send reply to client and inform other servers */
|
||||
ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
|
||||
IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes );
|
||||
ok = IRC_WriteStrClientPrefix(Client, Origin,
|
||||
"MODE %s :%s",
|
||||
Client_ID(Target),
|
||||
the_modes);
|
||||
IRC_WriteStrServersPrefix(Client, Origin,
|
||||
"MODE %s :%s",
|
||||
Client_ID(Target),
|
||||
the_modes);
|
||||
}
|
||||
LogDebug("%s \"%s\": Mode change, now \"%s\".",
|
||||
Client_TypeText(Target), Client_Mask(Target),
|
||||
Client_Modes(Target));
|
||||
}
|
||||
|
||||
IRC_SetPenalty( Client, 1 );
|
||||
|
||||
IRC_SetPenalty(Client, 1);
|
||||
return ok;
|
||||
} /* Client_Mode */
|
||||
|
||||
@@ -319,7 +398,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
|
||||
char the_modes[COMMAND_LEN], the_args[COMMAND_LEN], x[2],
|
||||
argadd[CLIENT_PASS_LEN], *mode_ptr;
|
||||
bool connected, set, skiponce, retval, onchannel, modeok, use_servermode;
|
||||
int mode_arg, arg_arg;
|
||||
int mode_arg, arg_arg, mode_arg_count = 0;
|
||||
CLIENT *client;
|
||||
long l;
|
||||
size_t len;
|
||||
@@ -372,6 +451,8 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
|
||||
mode_ptr++;
|
||||
if (!*mode_ptr) {
|
||||
/* Try next argument if there's any */
|
||||
if (arg_arg < 0)
|
||||
break;
|
||||
if (arg_arg > mode_arg)
|
||||
mode_arg = arg_arg;
|
||||
else
|
||||
@@ -421,6 +502,7 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
|
||||
case 'i': /* Invite only */
|
||||
case 'm': /* Moderated */
|
||||
case 'n': /* Only members can write */
|
||||
case 'R': /* Registered users only */
|
||||
case 's': /* Secret channel */
|
||||
case 't': /* Topic locked */
|
||||
case 'z': /* Secure connections only */
|
||||
@@ -432,6 +514,8 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
|
||||
Client_ID(Origin), Channel_Name(Channel));
|
||||
break;
|
||||
case 'k': /* Channel key */
|
||||
if (Mode_Limit_Reached(Client, mode_arg_count++))
|
||||
goto chan_exit;
|
||||
if (!set) {
|
||||
if (modeok)
|
||||
x[0] = *mode_ptr;
|
||||
@@ -466,6 +550,8 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
|
||||
}
|
||||
break;
|
||||
case 'l': /* Member limit */
|
||||
if (Mode_Limit_Reached(Client, mode_arg_count++))
|
||||
goto chan_exit;
|
||||
if (!set) {
|
||||
if (modeok)
|
||||
x[0] = *mode_ptr;
|
||||
@@ -536,6 +622,16 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
|
||||
Channel_Name(Channel));
|
||||
break;
|
||||
/* --- Channel user modes --- */
|
||||
case 'a':
|
||||
case 'h':
|
||||
case 'q':
|
||||
if (Client_Type(Client) != CLIENT_SERVER) {
|
||||
connected = IRC_WriteStrClient(Origin,
|
||||
ERR_CHANOPRIVSNEEDED_MSG,
|
||||
Client_ID(Origin),
|
||||
Channel_Name(Channel));
|
||||
goto chan_exit;
|
||||
}
|
||||
case 'o': /* Channel operator */
|
||||
case 'v': /* Voice */
|
||||
if (arg_arg > mode_arg) {
|
||||
@@ -566,14 +662,17 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
|
||||
/* --- Channel lists --- */
|
||||
case 'I': /* Invite lists */
|
||||
case 'b': /* Ban lists */
|
||||
case 'e': /* Channel exception lists */
|
||||
if (Mode_Limit_Reached(Client, mode_arg_count++))
|
||||
goto chan_exit;
|
||||
if (arg_arg > mode_arg) {
|
||||
/* modify list */
|
||||
if (modeok) {
|
||||
connected = set
|
||||
? Add_Ban_Invite(*mode_ptr, Origin,
|
||||
? Add_To_List(*mode_ptr, Origin,
|
||||
Client, Channel,
|
||||
Req->argv[arg_arg])
|
||||
: Del_Ban_Invite(*mode_ptr, Origin,
|
||||
: Del_From_List(*mode_ptr, Origin,
|
||||
Client, Channel,
|
||||
Req->argv[arg_arg]);
|
||||
} else {
|
||||
@@ -585,25 +684,38 @@ Channel_Mode(CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel)
|
||||
Req->argv[arg_arg][0] = '\0';
|
||||
arg_arg++;
|
||||
} else {
|
||||
if (*mode_ptr == 'I')
|
||||
switch (*mode_ptr) {
|
||||
case 'I':
|
||||
Channel_ShowInvites(Origin, Channel);
|
||||
else
|
||||
break;
|
||||
case 'b':
|
||||
Channel_ShowBans(Origin, Channel);
|
||||
break;
|
||||
case 'e':
|
||||
Channel_ShowExcepts(Origin, Channel);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log(LOG_DEBUG,
|
||||
"Unknown mode \"%c%c\" from \"%s\" on %s!?",
|
||||
set ? '+' : '-', *mode_ptr, Client_ID(Origin),
|
||||
Channel_Name(Channel));
|
||||
if (Client_Type(Client) != CLIENT_SERVER)
|
||||
if (Client_Type(Client) != CLIENT_SERVER) {
|
||||
Log(LOG_DEBUG,
|
||||
"Unknown mode \"%c%c\" from \"%s\" on %s!?",
|
||||
set ? '+' : '-', *mode_ptr,
|
||||
Client_ID(Origin), Channel_Name(Channel));
|
||||
connected = IRC_WriteStrClient(Origin,
|
||||
ERR_UMODEUNKNOWNFLAG2_MSG,
|
||||
Client_ID(Origin),
|
||||
set ? '+' : '-', *mode_ptr);
|
||||
x[0] = '\0';
|
||||
goto chan_exit;
|
||||
} /* switch() */
|
||||
ERR_UNKNOWNMODE_MSG,
|
||||
Client_ID(Origin), *mode_ptr,
|
||||
Channel_Name(Channel));
|
||||
x[0] = '\0';
|
||||
} else {
|
||||
Log(LOG_DEBUG,
|
||||
"Handling unknown mode \"%c%c\" from \"%s\" on %s ...",
|
||||
set ? '+' : '-', *mode_ptr,
|
||||
Client_ID(Origin), Channel_Name(Channel));
|
||||
x[0] = *mode_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!connected)
|
||||
break;
|
||||
@@ -729,82 +841,151 @@ IRC_AWAY( CLIENT *Client, REQUEST *Req )
|
||||
} /* IRC_AWAY */
|
||||
|
||||
|
||||
/**
|
||||
* Add entries to channel invite, ban and exception lists.
|
||||
*
|
||||
* @param what Can be 'I' for invite, 'b' for ban, and 'e' for exception list.
|
||||
* @param Prefix The originator of the command.
|
||||
* @param Client The sender of the command.
|
||||
* @param Channel The channel of which the list should be modified.
|
||||
* @param Pattern The pattern to add to the list.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
static bool
|
||||
Add_Ban_Invite(int what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Pattern)
|
||||
Add_To_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
|
||||
const char *Pattern)
|
||||
{
|
||||
const char *mask;
|
||||
bool already;
|
||||
bool ret;
|
||||
struct list_head *list;
|
||||
long int current_count;
|
||||
|
||||
assert( Client != NULL );
|
||||
assert( Channel != NULL );
|
||||
assert( Pattern != NULL );
|
||||
assert(what == 'I' || what == 'b');
|
||||
assert(Client != NULL);
|
||||
assert(Channel != NULL);
|
||||
assert(Pattern != NULL);
|
||||
assert(what == 'I' || what == 'b' || what == 'e');
|
||||
|
||||
mask = Lists_MakeMask(Pattern);
|
||||
current_count = Lists_Count(Channel_GetListInvites(Channel))
|
||||
+ Lists_Count(Channel_GetListExcepts(Channel))
|
||||
+ Lists_Count(Channel_GetListBans(Channel));
|
||||
|
||||
already = Lists_CheckDupeMask(Channel_GetListInvites(Channel), mask);
|
||||
if (!already) {
|
||||
if (what == 'I')
|
||||
ret = Channel_AddInvite(Channel, mask, false);
|
||||
else
|
||||
ret = Channel_AddBan(Channel, mask);
|
||||
if (!ret)
|
||||
return CONNECTED;
|
||||
switch(what) {
|
||||
case 'I':
|
||||
list = Channel_GetListInvites(Channel);
|
||||
break;
|
||||
case 'b':
|
||||
list = Channel_GetListBans(Channel);
|
||||
break;
|
||||
case 'e':
|
||||
list = Channel_GetListExcepts(Channel);
|
||||
break;
|
||||
}
|
||||
if (already && (Client_Type(Prefix) == CLIENT_SERVER))
|
||||
return CONNECTED;
|
||||
|
||||
if (what == 'I')
|
||||
return Send_ListChange("+I", Prefix, Client, Channel, mask);
|
||||
return Send_ListChange("+b", Prefix, Client, Channel, mask);
|
||||
if (Lists_CheckDupeMask(list, mask))
|
||||
return CONNECTED;
|
||||
if (Client_Type(Client) == CLIENT_USER &&
|
||||
current_count >= MAX_HNDL_CHANNEL_LISTS)
|
||||
return IRC_WriteStrClient(Client, ERR_LISTFULL_MSG,
|
||||
Client_ID(Client),
|
||||
Channel_Name(Channel), mask,
|
||||
MAX_HNDL_CHANNEL_LISTS);
|
||||
|
||||
switch (what) {
|
||||
case 'I':
|
||||
if (!Channel_AddInvite(Channel, mask, false))
|
||||
return CONNECTED;
|
||||
break;
|
||||
case 'b':
|
||||
if (!Channel_AddBan(Channel, mask))
|
||||
return CONNECTED;
|
||||
break;
|
||||
case 'e':
|
||||
if (!Channel_AddExcept(Channel, mask))
|
||||
return CONNECTED;
|
||||
break;
|
||||
}
|
||||
return Send_ListChange(true, what, Prefix, Client, Channel, mask);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete entries from channel invite, ban and exeption lists.
|
||||
*
|
||||
* @param what Can be 'I' for invite, 'b' for ban, and 'e' for exception list.
|
||||
* @param Prefix The originator of the command.
|
||||
* @param Client The sender of the command.
|
||||
* @param Channel The channel of which the list should be modified.
|
||||
* @param Pattern The pattern to add to the list.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
static bool
|
||||
Del_Ban_Invite(int what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, const char *Pattern)
|
||||
Del_From_List(char what, CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel,
|
||||
const char *Pattern)
|
||||
{
|
||||
const char *mask;
|
||||
struct list_head *list;
|
||||
|
||||
assert( Client != NULL );
|
||||
assert( Channel != NULL );
|
||||
assert( Pattern != NULL );
|
||||
assert(what == 'I' || what == 'b');
|
||||
assert(Client != NULL);
|
||||
assert(Channel != NULL);
|
||||
assert(Pattern != NULL);
|
||||
assert(what == 'I' || what == 'b' || what == 'e');
|
||||
|
||||
mask = Lists_MakeMask( Pattern );
|
||||
mask = Lists_MakeMask(Pattern);
|
||||
|
||||
if (what == 'I')
|
||||
list = Channel_GetListInvites(Channel);
|
||||
else
|
||||
list = Channel_GetListBans(Channel);
|
||||
switch (what) {
|
||||
case 'I':
|
||||
list = Channel_GetListInvites(Channel);
|
||||
break;
|
||||
case 'b':
|
||||
list = Channel_GetListBans(Channel);
|
||||
break;
|
||||
case 'e':
|
||||
list = Channel_GetListExcepts(Channel);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!Lists_CheckDupeMask(list, mask))
|
||||
return CONNECTED;
|
||||
Lists_Del(list, mask);
|
||||
if (what == 'I')
|
||||
return Send_ListChange( "-I", Prefix, Client, Channel, mask );
|
||||
return Send_ListChange( "-b", Prefix, Client, Channel, mask );
|
||||
|
||||
return Send_ListChange(false, what, Prefix, Client, Channel, mask);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Send information about changed channel invite/ban/exception lists to clients.
|
||||
*
|
||||
* @param IsAdd true if the list item has been added, false otherwise.
|
||||
* @param ModeChar The mode to use (e. g. 'b' or 'I')
|
||||
* @param Prefix The originator of the mode list change.
|
||||
* @param Client The sender of the command.
|
||||
* @param Channel The channel of which the list has been modified.
|
||||
* @param Mask The mask which has been added or removed.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
static bool
|
||||
Send_ListChange(const char *Mode, CLIENT *Prefix, CLIENT *Client,
|
||||
CHANNEL *Channel, const char *Mask)
|
||||
Send_ListChange(const bool IsAdd, const char ModeChar, CLIENT *Prefix,
|
||||
CLIENT *Client, CHANNEL *Channel, const char *Mask)
|
||||
{
|
||||
bool ok;
|
||||
bool ok = true;
|
||||
|
||||
if( Client_Type( Client ) == CLIENT_USER )
|
||||
{
|
||||
/* send confirmation to client */
|
||||
ok = IRC_WriteStrClientPrefix( Client, Prefix, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
|
||||
}
|
||||
else ok = true;
|
||||
/* Send confirmation to the client */
|
||||
if (Client_Type(Client) == CLIENT_USER)
|
||||
ok = IRC_WriteStrClientPrefix(Client, Prefix, "MODE %s %c%c %s",
|
||||
Channel_Name(Channel),
|
||||
IsAdd ? '+' : '-',
|
||||
ModeChar, Mask);
|
||||
|
||||
/* to other servers */
|
||||
IRC_WriteStrServersPrefix( Client, Prefix, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
|
||||
IRC_WriteStrServersPrefix(Client, Prefix, "MODE %s %c%c %s",
|
||||
Channel_Name(Channel), IsAdd ? '+' : '-',
|
||||
ModeChar, Mask);
|
||||
|
||||
/* and local users in channel */
|
||||
IRC_WriteStrChannelPrefix( Client, Channel, Prefix, false, "MODE %s %s %s", Channel_Name( Channel ), Mode, Mask );
|
||||
|
||||
IRC_WriteStrChannelPrefix(Client, Channel, Prefix, false,
|
||||
"MODE %s %c%c %s", Channel_Name(Channel),
|
||||
IsAdd ? '+' : '-', ModeChar, Mask );
|
||||
|
||||
return ok;
|
||||
} /* Send_ListChange */
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
|
||||
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "conn-func.h"
|
||||
#include "conf.h"
|
||||
#include "channel.h"
|
||||
#include "class.h"
|
||||
#include "irc-write.h"
|
||||
#include "log.h"
|
||||
#include "match.h"
|
||||
@@ -37,7 +38,6 @@
|
||||
#include <exp.h>
|
||||
#include "irc-oper.h"
|
||||
|
||||
|
||||
/**
|
||||
* Handle invalid received OPER command.
|
||||
* Log OPER attempt and send error message to client.
|
||||
@@ -52,7 +52,15 @@ Bad_OperPass(CLIENT *Client, char *errtoken, char *errmsg)
|
||||
Client_ID(Client));
|
||||
} /* Bad_OperPass */
|
||||
|
||||
|
||||
/**
|
||||
* Handler for the IRC "OPER" command.
|
||||
*
|
||||
* See RFC 2812, 3.1.4 "Oper message".
|
||||
*
|
||||
* @param Client The client from which this command has been received.
|
||||
* @param Req Request structure with prefix and all parameters.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_OPER( CLIENT *Client, REQUEST *Req )
|
||||
{
|
||||
@@ -62,7 +70,9 @@ IRC_OPER( CLIENT *Client, REQUEST *Req )
|
||||
assert( Client != NULL );
|
||||
assert( Req != NULL );
|
||||
|
||||
if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
|
||||
if (Req->argc != 2)
|
||||
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
|
||||
Client_ID(Client), Req->command);
|
||||
|
||||
len = array_length(&Conf_Opers, sizeof(*op));
|
||||
op = array_start(&Conf_Opers);
|
||||
@@ -77,20 +87,33 @@ IRC_OPER( CLIENT *Client, REQUEST *Req )
|
||||
if (op[i].mask && (!Match(op[i].mask, Client_Mask(Client))))
|
||||
return Bad_OperPass(Client, op[i].mask, "hostmask check failed");
|
||||
|
||||
if( ! Client_HasMode( Client, 'o' ))
|
||||
{
|
||||
Client_ModeAdd( Client, 'o' );
|
||||
if( ! IRC_WriteStrClient( Client, "MODE %s :+o", Client_ID( Client ))) return DISCONNECTED;
|
||||
IRC_WriteStrServersPrefix( NULL, Client, "MODE %s :+o", Client_ID( Client ));
|
||||
if (!Client_HasMode(Client, 'o')) {
|
||||
Client_ModeAdd(Client, 'o');
|
||||
if (!IRC_WriteStrClient(Client, "MODE %s :+o",
|
||||
Client_ID(Client)))
|
||||
return DISCONNECTED;
|
||||
IRC_WriteStrServersPrefix(NULL, Client, "MODE %s :+o",
|
||||
Client_ID(Client));
|
||||
}
|
||||
|
||||
if( ! Client_OperByMe( Client )) Log( LOG_NOTICE|LOG_snotice, "Got valid OPER from \"%s\", user is an IRC operator now.", Client_Mask( Client ));
|
||||
if (!Client_OperByMe(Client))
|
||||
Log(LOG_NOTICE|LOG_snotice,
|
||||
"Got valid OPER from \"%s\", user is an IRC operator now.",
|
||||
Client_Mask(Client));
|
||||
|
||||
Client_SetOperByMe( Client, true);
|
||||
return IRC_WriteStrClient( Client, RPL_YOUREOPER_MSG, Client_ID( Client ));
|
||||
Client_SetOperByMe(Client, true);
|
||||
return IRC_WriteStrClient(Client, RPL_YOUREOPER_MSG, Client_ID(Client));
|
||||
} /* IRC_OPER */
|
||||
|
||||
|
||||
/**
|
||||
* Handler for the IRC "DIE" command.
|
||||
*
|
||||
* See RFC 2812, 4.3 "Die message".
|
||||
*
|
||||
* @param Client The client from which this command has been received.
|
||||
* @param Req Request structure with prefix and all parameters.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_DIE(CLIENT * Client, REQUEST * Req)
|
||||
{
|
||||
@@ -133,7 +156,15 @@ IRC_DIE(CLIENT * Client, REQUEST * Req)
|
||||
return CONNECTED;
|
||||
} /* IRC_DIE */
|
||||
|
||||
|
||||
/**
|
||||
* Handler for the IRC "REHASH" command.
|
||||
*
|
||||
* See RFC 2812, 4.2 "Rehash message".
|
||||
*
|
||||
* @param Client The client from which this command has been received.
|
||||
* @param Req Request structure with prefix and all parameters.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_REHASH( CLIENT *Client, REQUEST *Req )
|
||||
{
|
||||
@@ -146,15 +177,26 @@ IRC_REHASH( CLIENT *Client, REQUEST *Req )
|
||||
return Op_NoPrivileges(Client, Req);
|
||||
|
||||
/* Bad number of parameters? */
|
||||
if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
|
||||
if (Req->argc != 0)
|
||||
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
|
||||
Client_ID(Client), Req->command );
|
||||
|
||||
Log( LOG_NOTICE|LOG_snotice, "Got REHASH command from \"%s\" ...", Client_Mask( Client ));
|
||||
Log(LOG_NOTICE|LOG_snotice, "Got REHASH command from \"%s\" ...",
|
||||
Client_Mask(Client));
|
||||
raise(SIGHUP);
|
||||
|
||||
return CONNECTED;
|
||||
} /* IRC_REHASH */
|
||||
|
||||
|
||||
/**
|
||||
* Handler for the IRC "RESTART" command.
|
||||
*
|
||||
* See RFC 2812, 4.4 "Restart message".
|
||||
*
|
||||
* @param Client The client from which this command has been received.
|
||||
* @param Req Request structure with prefix and all parameters.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_RESTART( CLIENT *Client, REQUEST *Req )
|
||||
{
|
||||
@@ -167,16 +209,25 @@ IRC_RESTART( CLIENT *Client, REQUEST *Req )
|
||||
return Op_NoPrivileges(Client, Req);
|
||||
|
||||
/* Bad number of parameters? */
|
||||
if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
|
||||
if (Req->argc != 0)
|
||||
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
|
||||
Client_ID(Client), Req->command);
|
||||
|
||||
Log( LOG_NOTICE|LOG_snotice, "Got RESTART command from \"%s\" ...", Client_Mask( Client ));
|
||||
Log(LOG_NOTICE|LOG_snotice, "Got RESTART command from \"%s\" ...",
|
||||
Client_Mask(Client));
|
||||
NGIRCd_SignalRestart = true;
|
||||
|
||||
return CONNECTED;
|
||||
} /* IRC_RESTART */
|
||||
|
||||
|
||||
/**
|
||||
* Connect configured or new server.
|
||||
* Handler for the IRC "CONNECT" command.
|
||||
*
|
||||
* See RFC 2812, 3.4.7 "Connect message".
|
||||
*
|
||||
* @param Client The client from which this command has been received.
|
||||
* @param Req Request structure with prefix and all parameters.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_CONNECT(CLIENT * Client, REQUEST * Req)
|
||||
@@ -272,9 +323,15 @@ IRC_CONNECT(CLIENT * Client, REQUEST * Req)
|
||||
return CONNECTED;
|
||||
} /* IRC_CONNECT */
|
||||
|
||||
|
||||
/**
|
||||
* Disconnect (and disable) configured server.
|
||||
* Handler for the IRC "DISCONNECT" command.
|
||||
*
|
||||
* This command is not specified in the IRC RFCs, it is an extension
|
||||
* of ngIRCd: it shuts down and disables a configured server connection.
|
||||
*
|
||||
* @param Client The client from which this command has been received.
|
||||
* @param Req Request structure with prefix and all parameters.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_DISCONNECT(CLIENT * Client, REQUEST * Req)
|
||||
@@ -315,7 +372,15 @@ IRC_DISCONNECT(CLIENT * Client, REQUEST * Req)
|
||||
return DISCONNECTED;
|
||||
} /* IRC_DISCONNECT */
|
||||
|
||||
|
||||
/**
|
||||
* Handler for the IRC "WALLOPS" command.
|
||||
*
|
||||
* See RFC 2812, 4.7 "Operwall message".
|
||||
*
|
||||
* @param Client The client from which this command has been received.
|
||||
* @param Req Request structure with prefix and all parameters.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_WALLOPS( CLIENT *Client, REQUEST *Req )
|
||||
{
|
||||
@@ -325,12 +390,14 @@ IRC_WALLOPS( CLIENT *Client, REQUEST *Req )
|
||||
assert( Req != NULL );
|
||||
|
||||
if (Req->argc != 1)
|
||||
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG, Client_ID(Client), Req->command);
|
||||
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
|
||||
Client_ID(Client), Req->command);
|
||||
|
||||
switch (Client_Type(Client)) {
|
||||
case CLIENT_USER:
|
||||
if (!Client_OperByMe(Client))
|
||||
return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG, Client_ID(Client));
|
||||
return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG,
|
||||
Client_ID(Client));
|
||||
from = Client;
|
||||
break;
|
||||
case CLIENT_SERVER:
|
||||
@@ -341,11 +408,87 @@ IRC_WALLOPS( CLIENT *Client, REQUEST *Req )
|
||||
}
|
||||
|
||||
if (!from)
|
||||
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG, Client_ID(Client), Req->prefix);
|
||||
return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
|
||||
Client_ID(Client), Req->prefix);
|
||||
|
||||
IRC_SendWallops(Client, from, "%s", Req->argv[0]);
|
||||
return CONNECTED;
|
||||
} /* IRC_WALLOPS */
|
||||
|
||||
/**
|
||||
* Handle <?>LINE commands (GLINE, KLINE).
|
||||
*
|
||||
* @param Client The client from which this command has been received.
|
||||
* @param Req Request structure with prefix and all parameters.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_xLINE(CLIENT *Client, REQUEST *Req)
|
||||
{
|
||||
CLIENT *from;
|
||||
int class;
|
||||
char class_c;
|
||||
|
||||
assert(Client != NULL);
|
||||
assert(Req != NULL);
|
||||
|
||||
from = Op_Check(Client, Req);
|
||||
if (!from)
|
||||
return Op_NoPrivileges(Client, Req);
|
||||
|
||||
/* Bad number of parameters? */
|
||||
if (Req->argc != 1 && Req->argc != 3)
|
||||
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
|
||||
Client_ID(Client), Req->command);
|
||||
|
||||
switch(Req->command[0]) {
|
||||
case 'g':
|
||||
case 'G':
|
||||
class = CLASS_GLINE; class_c = 'G';
|
||||
break;
|
||||
case 'k':
|
||||
case 'K':
|
||||
class = CLASS_KLINE; class_c = 'K';
|
||||
break;
|
||||
default:
|
||||
Log(LOG_CRIT,
|
||||
"IRC_xLINE() called for unknown line: %c!? Ignored.",
|
||||
Req->command[0]);
|
||||
return CONNECTED;
|
||||
}
|
||||
|
||||
if (Req->argc == 1) {
|
||||
/* Delete mask from list */
|
||||
Class_DeleteMask(class, Req->argv[0]);
|
||||
Log(LOG_NOTICE|LOG_snotice,
|
||||
"\"%s\" deleted \"%s\" from %c-Line list.",
|
||||
Client_Mask(from), Req->argv[0], class_c);
|
||||
if (class == CLASS_GLINE) {
|
||||
/* Inform other servers */
|
||||
IRC_WriteStrServersPrefix(Client, from, "%s %s",
|
||||
Req->command, Req->argv[0]);
|
||||
|
||||
}
|
||||
} else {
|
||||
/* Add new mask to list */
|
||||
if (Class_AddMask(class, Req->argv[0],
|
||||
time(NULL) + atol(Req->argv[1]),
|
||||
Req->argv[2])) {
|
||||
Log(LOG_NOTICE|LOG_snotice,
|
||||
"\"%s\" added \"%s\" to %c-Line list: \"%s\" (%ld seconds).",
|
||||
Client_Mask(from), Req->argv[0], class_c,
|
||||
Req->argv[2], atol(Req->argv[1]));
|
||||
if (class == CLASS_GLINE) {
|
||||
/* Inform other servers */
|
||||
IRC_WriteStrServersPrefix(Client, from,
|
||||
"%s %s %s :%s", Req->command,
|
||||
Req->argv[0], Req->argv[1],
|
||||
Req->argv[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CONNECTED;
|
||||
}
|
||||
|
||||
/* -eof- */
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
|
||||
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -25,6 +25,8 @@ GLOBAL bool IRC_CONNECT PARAMS((CLIENT *Client, REQUEST *Req ));
|
||||
GLOBAL bool IRC_DISCONNECT PARAMS((CLIENT *Client, REQUEST *Req ));
|
||||
GLOBAL bool IRC_WALLOPS PARAMS(( CLIENT *Client, REQUEST *Req ));
|
||||
|
||||
GLOBAL bool IRC_xLINE PARAMS((CLIENT *Client, REQUEST *Req));
|
||||
|
||||
#endif
|
||||
|
||||
/* -eof- */
|
||||
|
158
src/ngircd/irc.c
158
src/ngircd/irc.c
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2004 Alexander Barton <alex@barton.de>
|
||||
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -45,6 +45,35 @@ static bool Send_Message_Mask PARAMS((CLIENT *from, char *command,
|
||||
bool SendErrors));
|
||||
|
||||
|
||||
/**
|
||||
* Check if a list limit is reached and inform client accordingly.
|
||||
*
|
||||
* @param From The client.
|
||||
* @param Count Reply item count.
|
||||
* @param Limit Reply limit.
|
||||
* @param Name Name of the list.
|
||||
* @return true if list limit has been reached; false otherwise.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_CheckListTooBig(CLIENT *From, const int Count, const int Limit,
|
||||
const char *Name)
|
||||
{
|
||||
assert(From != NULL);
|
||||
assert(Count >= 0);
|
||||
assert(Limit > 0);
|
||||
assert(Name != NULL);
|
||||
|
||||
if (Count < Limit)
|
||||
return false;
|
||||
|
||||
(void)IRC_WriteStrClient(From,
|
||||
"NOTICE %s :%s list limit (%d) reached!",
|
||||
Client_ID(From), Name, Limit);
|
||||
IRC_SetPenalty(From, 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
GLOBAL bool
|
||||
IRC_ERROR( CLIENT *Client, REQUEST *Req )
|
||||
{
|
||||
@@ -63,13 +92,21 @@ IRC_ERROR( CLIENT *Client, REQUEST *Req )
|
||||
|
||||
|
||||
/**
|
||||
* Kill client on request.
|
||||
* Handler for the IRC "KILL" command.
|
||||
*
|
||||
* This function implements the IRC command "KILL" wich is used to selectively
|
||||
* disconnect clients. It can be used by IRC operators and servers, for example
|
||||
* to "solve" nick collisions after netsplits.
|
||||
* to "solve" nick collisions after netsplits. See RFC 2812 section 3.7.1.
|
||||
*
|
||||
* Please note that this function is also called internally, without a real
|
||||
* KILL command being received over the network! Client is Client_ThisServer()
|
||||
* in this case. */
|
||||
* in this case, and the prefix in Req is NULL.
|
||||
*
|
||||
* @param Client The client from which this command has been received
|
||||
* or Client_ThisServer() when generated interanlly.
|
||||
* @param Req Request structure with prefix and all parameters.
|
||||
* @returns CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
GLOBAL bool
|
||||
IRC_KILL( CLIENT *Client, REQUEST *Req )
|
||||
{
|
||||
@@ -77,55 +114,47 @@ IRC_KILL( CLIENT *Client, REQUEST *Req )
|
||||
char reason[COMMAND_LEN], *msg;
|
||||
CONN_ID my_conn, conn;
|
||||
|
||||
assert( Client != NULL );
|
||||
assert( Req != NULL );
|
||||
assert (Client != NULL);
|
||||
assert (Req != NULL);
|
||||
|
||||
if(( Client_Type( Client ) != CLIENT_SERVER ) &&
|
||||
( ! Client_OperByMe( Client )))
|
||||
{
|
||||
/* The originator of the KILL is neither an IRC operator of
|
||||
* this server nor a server. */
|
||||
return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG,
|
||||
Client_ID( Client ));
|
||||
}
|
||||
if (Client_Type(Client) != CLIENT_SERVER && !Client_OperByMe(Client))
|
||||
return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG,
|
||||
Client_ID(Client));
|
||||
|
||||
if( Req->argc != 2 )
|
||||
{
|
||||
/* This command requires exactly 2 parameters! */
|
||||
return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG,
|
||||
Client_ID( Client ), Req->command );
|
||||
}
|
||||
if (Req->argc != 2)
|
||||
return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
|
||||
Client_ID(Client), Req->command);
|
||||
|
||||
if( Req->prefix ) prefix = Client_Search( Req->prefix );
|
||||
else prefix = Client;
|
||||
if( ! prefix )
|
||||
{
|
||||
Log( LOG_WARNING, "Got KILL with invalid prefix: \"%s\"!",
|
||||
Req->prefix );
|
||||
prefix = Client_ThisServer( );
|
||||
}
|
||||
|
||||
if( Client != Client_ThisServer( ))
|
||||
{
|
||||
/* This is a "real" KILL received from the network. */
|
||||
Log( LOG_NOTICE|LOG_snotice, "Got KILL command from \"%s\" for \"%s\": %s",
|
||||
Client_Mask( prefix ), Req->argv[0], Req->argv[1] );
|
||||
}
|
||||
|
||||
/* Build reason string */
|
||||
if( Client_Type( Client ) == CLIENT_USER )
|
||||
{
|
||||
/* Prefix the "reason" if the originator is a regular user,
|
||||
* so users can't spoof KILLs of servers. */
|
||||
snprintf( reason, sizeof( reason ), "KILLed by %s: %s",
|
||||
Client_ID( Client ), Req->argv[1] );
|
||||
}
|
||||
/* Get prefix (origin); use the client if no prefix is given. */
|
||||
if (Req->prefix)
|
||||
prefix = Client_Search(Req->prefix);
|
||||
else
|
||||
strlcpy( reason, Req->argv[1], sizeof( reason ));
|
||||
prefix = Client;
|
||||
|
||||
/* Log a warning message and use this server as origin when the
|
||||
* prefix (origin) is invalid. */
|
||||
if (!prefix) {
|
||||
Log(LOG_WARNING, "Got KILL with invalid prefix: \"%s\"!",
|
||||
Req->prefix );
|
||||
prefix = Client_ThisServer();
|
||||
}
|
||||
|
||||
if (Client != Client_ThisServer())
|
||||
Log(LOG_NOTICE|LOG_snotice,
|
||||
"Got KILL command from \"%s\" for \"%s\": %s",
|
||||
Client_Mask(prefix), Req->argv[0], Req->argv[1]);
|
||||
|
||||
/* Build reason string: Prefix the "reason" if the originator is a
|
||||
* regular user, so users can't spoof KILLs of servers. */
|
||||
if (Client_Type(Client) == CLIENT_USER)
|
||||
snprintf(reason, sizeof(reason), "KILLed by %s: %s",
|
||||
Client_ID(Client), Req->argv[1]);
|
||||
else
|
||||
strlcpy(reason, Req->argv[1], sizeof(reason));
|
||||
|
||||
/* Inform other servers */
|
||||
IRC_WriteStrServersPrefix( Client, prefix, "KILL %s :%s",
|
||||
Req->argv[0], reason );
|
||||
IRC_WriteStrServersPrefix(Client, prefix, "KILL %s :%s",
|
||||
Req->argv[0], reason);
|
||||
|
||||
/* Save ID of this connection */
|
||||
my_conn = Client_Conn( Client );
|
||||
@@ -320,6 +349,7 @@ static bool
|
||||
Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
|
||||
{
|
||||
CLIENT *cl, *from;
|
||||
CL2CHAN *cl2chan;
|
||||
CHANNEL *chan;
|
||||
char *currentTarget = Req->argv[0];
|
||||
char *lastCurrentTarget = NULL;
|
||||
@@ -410,8 +440,8 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
|
||||
Client_Type(cl) != CLIENT_SERVICE)
|
||||
continue;
|
||||
if (nick != NULL && host != NULL) {
|
||||
if (strcmp(nick, Client_ID(cl)) == 0 &&
|
||||
strcmp(user, Client_User(cl)) == 0 &&
|
||||
if (strcasecmp(nick, Client_ID(cl)) == 0 &&
|
||||
strcasecmp(user, Client_User(cl)) == 0 &&
|
||||
strcasecmp(host, Client_HostnameCloaked(cl)) == 0)
|
||||
break;
|
||||
else
|
||||
@@ -439,11 +469,11 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
|
||||
#else
|
||||
if (Client_Type(cl) != ForceType) {
|
||||
#endif
|
||||
if (!SendErrors)
|
||||
return CONNECTED;
|
||||
return IRC_WriteStrClient(from, ERR_NOSUCHNICK_MSG,
|
||||
Client_ID(from),
|
||||
currentTarget);
|
||||
if (SendErrors && !IRC_WriteStrClient(
|
||||
from, ERR_NOSUCHNICK_MSG,Client_ID(from),
|
||||
currentTarget))
|
||||
return DISCONNECTED;
|
||||
goto send_next_target;
|
||||
}
|
||||
|
||||
#ifndef STRICT_RFC
|
||||
@@ -456,6 +486,23 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (Client_HasMode(cl, 'C')) {
|
||||
cl2chan = Channel_FirstChannelOf(cl);
|
||||
while (cl2chan) {
|
||||
chan = Channel_GetChannel(cl2chan);
|
||||
if (Channel_IsMemberOf(chan, from))
|
||||
break;
|
||||
cl2chan = Channel_NextChannelOf(cl, cl2chan);
|
||||
}
|
||||
if (!cl2chan) {
|
||||
if (SendErrors && !IRC_WriteStrClient(
|
||||
from, ERR_NOTONSAMECHANNEL_MSG,
|
||||
Client_ID(from), Client_ID(cl)))
|
||||
return DISCONNECTED;
|
||||
goto send_next_target;
|
||||
}
|
||||
}
|
||||
|
||||
if (SendErrors && (Client_Type(Client) != CLIENT_SERVER)
|
||||
&& strchr(Client_Modes(cl), 'a')) {
|
||||
/* Target is away */
|
||||
@@ -493,7 +540,10 @@ Send_Message(CLIENT * Client, REQUEST * Req, int ForceType, bool SendErrors)
|
||||
return DISCONNECTED;
|
||||
}
|
||||
|
||||
send_next_target:
|
||||
currentTarget = strtok_r(NULL, ",", &lastCurrentTarget);
|
||||
if (currentTarget)
|
||||
Conn_SetPenalty(Client_Conn(Client), 1);
|
||||
}
|
||||
|
||||
return CONNECTED;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2008 Alexander Barton (alex@barton.de)
|
||||
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -17,6 +17,9 @@
|
||||
* IRC commands (header)
|
||||
*/
|
||||
|
||||
GLOBAL bool IRC_CheckListTooBig PARAMS((CLIENT *From, const int Count,
|
||||
const int Limit, const char *Name));
|
||||
|
||||
GLOBAL bool IRC_ERROR PARAMS((CLIENT *Client, REQUEST *Req));
|
||||
GLOBAL bool IRC_KILL PARAMS((CLIENT *Client, REQUEST *Req));
|
||||
GLOBAL bool IRC_NOTICE PARAMS((CLIENT *Client, REQUEST *Req));
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2005 Alexander Barton (alex@barton.de)
|
||||
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -37,89 +37,178 @@
|
||||
#define MASK_LEN (2*CLIENT_HOST_LEN)
|
||||
|
||||
struct list_elem {
|
||||
struct list_elem *next;
|
||||
char mask[MASK_LEN];
|
||||
bool onlyonce;
|
||||
struct list_elem *next; /** pointer to next list element */
|
||||
char mask[MASK_LEN]; /** IRC mask */
|
||||
char *reason; /** Optional "reason" text */
|
||||
time_t valid_until; /** 0: unlimited; 1: once; t(>1): until t */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Get IRC mask stored in list element.
|
||||
*
|
||||
* @param list_elem List element.
|
||||
* @return Pointer to IRC mask
|
||||
*/
|
||||
GLOBAL const char *
|
||||
Lists_GetMask(const struct list_elem *e)
|
||||
{
|
||||
assert(e != NULL);
|
||||
return e->mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get optional "reason" text stored in list element.
|
||||
*
|
||||
* @param list_elem List element.
|
||||
* @return Pointer to "reason" text or empty string ("").
|
||||
*/
|
||||
GLOBAL const char *
|
||||
Lists_GetReason(const struct list_elem *e)
|
||||
{
|
||||
assert(e != NULL);
|
||||
return e->reason ? e->reason : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get "validity" value stored in list element.
|
||||
*
|
||||
* @param list_elem List element.
|
||||
* @return Validity: 0=unlimited, 1=once, >1 until this time stamp.
|
||||
*/
|
||||
GLOBAL time_t
|
||||
Lists_GetValidity(const struct list_elem *e)
|
||||
{
|
||||
assert(e != NULL);
|
||||
return e->valid_until;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get first list element of a list.
|
||||
*
|
||||
* @param h List head.
|
||||
* @return Pointer to first list element.
|
||||
*/
|
||||
GLOBAL struct list_elem*
|
||||
Lists_GetFirst(const struct list_head *h)
|
||||
{
|
||||
assert(h != NULL);
|
||||
return h->first;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get next list element of a list.
|
||||
*
|
||||
* @param e Current list element.
|
||||
* @return Pointer to next list element.
|
||||
*/
|
||||
GLOBAL struct list_elem*
|
||||
Lists_GetNext(const struct list_elem *e)
|
||||
{
|
||||
assert(e != NULL);
|
||||
return e->next;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a new mask to a list.
|
||||
*
|
||||
* @param h List head.
|
||||
* @param Mask The IRC mask to add to the list.
|
||||
* @param ValidUntil 0: unlimited, 1: only once, t>1: until given time_t.
|
||||
* @param Reason Reason string or NULL, if no reason should be saved.
|
||||
* @return true on success, false otherwise.
|
||||
*/
|
||||
bool
|
||||
Lists_Add(struct list_head *header, const char *Mask, bool OnlyOnce )
|
||||
Lists_Add(struct list_head *h, const char *Mask, time_t ValidUntil,
|
||||
const char *Reason)
|
||||
{
|
||||
struct list_elem *e, *newelem;
|
||||
|
||||
assert( header != NULL );
|
||||
assert( Mask != NULL );
|
||||
assert(h != NULL);
|
||||
assert(Mask != NULL);
|
||||
|
||||
if (Lists_CheckDupeMask(header, Mask )) return true;
|
||||
e = Lists_CheckDupeMask(h, Mask);
|
||||
if (e) {
|
||||
e->valid_until = ValidUntil;
|
||||
if (Reason) {
|
||||
free(e->reason);
|
||||
e->reason = strdup(Reason);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
e = Lists_GetFirst(header);
|
||||
e = Lists_GetFirst(h);
|
||||
|
||||
newelem = malloc(sizeof(struct list_elem));
|
||||
if( ! newelem ) {
|
||||
Log( LOG_EMERG, "Can't allocate memory for new Ban/Invite entry!" );
|
||||
if (!newelem) {
|
||||
Log(LOG_EMERG,
|
||||
"Can't allocate memory for new list entry!");
|
||||
return false;
|
||||
}
|
||||
|
||||
strlcpy( newelem->mask, Mask, sizeof( newelem->mask ));
|
||||
newelem->onlyonce = OnlyOnce;
|
||||
strlcpy(newelem->mask, Mask, sizeof(newelem->mask));
|
||||
if (Reason) {
|
||||
newelem->reason = malloc(strlen(Reason) + 1);
|
||||
if (newelem->reason)
|
||||
strlcpy(newelem->reason, Reason, strlen(Reason) + 1);
|
||||
else
|
||||
Log(LOG_EMERG,
|
||||
"Can't allocate memory for new list reason text!");
|
||||
}
|
||||
else
|
||||
newelem->reason = NULL;
|
||||
newelem->valid_until = ValidUntil;
|
||||
newelem->next = e;
|
||||
header->first = newelem;
|
||||
h->first = newelem;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete a list element from a list.
|
||||
*
|
||||
* @param h List head.
|
||||
* @param p Pointer to previous list element or NULL, if there is none.
|
||||
* @param victim List element to delete.
|
||||
*/
|
||||
static void
|
||||
Lists_Unlink(struct list_head *header, struct list_elem *p, struct list_elem *victim)
|
||||
Lists_Unlink(struct list_head *h, struct list_elem *p, struct list_elem *victim)
|
||||
{
|
||||
assert(victim != NULL);
|
||||
assert(header != NULL);
|
||||
assert(h != NULL);
|
||||
|
||||
if (p) p->next = victim->next;
|
||||
else header->first = victim->next;
|
||||
if (p)
|
||||
p->next = victim->next;
|
||||
else
|
||||
h->first = victim->next;
|
||||
|
||||
if (victim->reason)
|
||||
free(victim->reason);
|
||||
|
||||
free(victim);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete a given IRC mask from a list.
|
||||
*
|
||||
* @param h List head.
|
||||
* @param Mask IRC mask to delete from the list.
|
||||
*/
|
||||
GLOBAL void
|
||||
Lists_Del(struct list_head *header, const char *Mask)
|
||||
Lists_Del(struct list_head *h, const char *Mask)
|
||||
{
|
||||
struct list_elem *e, *last, *victim;
|
||||
|
||||
assert( header != NULL );
|
||||
assert( Mask != NULL );
|
||||
assert(h != NULL);
|
||||
assert(Mask != NULL);
|
||||
|
||||
last = NULL;
|
||||
e = Lists_GetFirst(header);
|
||||
while( e ) {
|
||||
if(strcasecmp( e->mask, Mask ) == 0 ) {
|
||||
e = Lists_GetFirst(h);
|
||||
while (e) {
|
||||
if (strcasecmp(e->mask, Mask) == 0) {
|
||||
LogDebug("Deleted \"%s\" from list", e->mask);
|
||||
victim = e;
|
||||
e = victim->next;
|
||||
Lists_Unlink(header, last, victim);
|
||||
Lists_Unlink(h, last, victim);
|
||||
continue;
|
||||
}
|
||||
last = e;
|
||||
@@ -127,7 +216,11 @@ Lists_Del(struct list_head *header, const char *Mask)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Free a complete list.
|
||||
*
|
||||
* @param head List head.
|
||||
*/
|
||||
GLOBAL void
|
||||
Lists_Free(struct list_head *head)
|
||||
{
|
||||
@@ -138,101 +231,193 @@ Lists_Free(struct list_head *head)
|
||||
e = head->first;
|
||||
head->first = NULL;
|
||||
while (e) {
|
||||
LogDebug("Deleted \"%s\" from invite list" , e->mask);
|
||||
LogDebug("Deleted \"%s\" from list" , e->mask);
|
||||
victim = e;
|
||||
e = e->next;
|
||||
free( victim );
|
||||
if (victim->reason)
|
||||
free(victim->reason);
|
||||
free(victim);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GLOBAL bool
|
||||
/**
|
||||
* Check if an IRC mask is already contained in a list.
|
||||
*
|
||||
* @param h List head.
|
||||
* @param Mask IRC mask to test.
|
||||
* @return true if mask is already stored in the list, false otherwise.
|
||||
*/
|
||||
GLOBAL struct list_elem *
|
||||
Lists_CheckDupeMask(const struct list_head *h, const char *Mask )
|
||||
{
|
||||
struct list_elem *e;
|
||||
e = h->first;
|
||||
while (e) {
|
||||
if (strcasecmp( e->mask, Mask ) == 0 )
|
||||
return true;
|
||||
if (strcasecmp(e->mask, Mask) == 0)
|
||||
return e;
|
||||
e = e->next;
|
||||
}
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate a valid IRC mask from "any" string given.
|
||||
*
|
||||
* Attention: This mask is only valid until the next call to Lists_MakeMask(),
|
||||
* because a single global buffer ist used! You have to copy the generated
|
||||
* mask to some sane location yourself!
|
||||
*
|
||||
* @param Pattern Source string to generate an IRC mask for.
|
||||
* @return Pointer to global result buffer.
|
||||
*/
|
||||
GLOBAL const char *
|
||||
Lists_MakeMask(const char *Pattern)
|
||||
{
|
||||
/* This function generats a valid IRC mask of "any" string. This
|
||||
* mask is only valid until the next call to Lists_MakeMask(),
|
||||
* because a single global buffer is used. You have to copy the
|
||||
* generated mask to some sane location yourself! */
|
||||
|
||||
static char TheMask[MASK_LEN];
|
||||
char *excl, *at;
|
||||
|
||||
assert( Pattern != NULL );
|
||||
assert(Pattern != NULL);
|
||||
|
||||
excl = strchr( Pattern, '!' );
|
||||
at = strchr( Pattern, '@' );
|
||||
excl = strchr(Pattern, '!');
|
||||
at = strchr(Pattern, '@');
|
||||
|
||||
if(( at ) && ( at < excl )) excl = NULL;
|
||||
if (at && at < excl)
|
||||
excl = NULL;
|
||||
|
||||
if(( ! at ) && ( ! excl ))
|
||||
{
|
||||
if (!at && !excl) {
|
||||
/* Neither "!" nor "@" found: use string as nick name */
|
||||
strlcpy( TheMask, Pattern, sizeof( TheMask ) - 5 );
|
||||
strlcat( TheMask, "!*@*", sizeof( TheMask ));
|
||||
strlcpy(TheMask, Pattern, sizeof(TheMask) - 5);
|
||||
strlcat(TheMask, "!*@*", sizeof(TheMask));
|
||||
return TheMask;
|
||||
}
|
||||
|
||||
if(( ! at ) && ( excl ))
|
||||
{
|
||||
if (!at && excl) {
|
||||
/* Domain part is missing */
|
||||
strlcpy( TheMask, Pattern, sizeof( TheMask ) - 3 );
|
||||
strlcat( TheMask, "@*", sizeof( TheMask ));
|
||||
strlcpy(TheMask, Pattern, sizeof(TheMask) - 3);
|
||||
strlcat(TheMask, "@*", sizeof(TheMask));
|
||||
return TheMask;
|
||||
}
|
||||
|
||||
if(( at ) && ( ! excl ))
|
||||
{
|
||||
if (at && !excl) {
|
||||
/* User name is missing */
|
||||
*at = '\0'; at++;
|
||||
strlcpy( TheMask, Pattern, sizeof( TheMask ) - 5 );
|
||||
strlcat( TheMask, "!*@", sizeof( TheMask ));
|
||||
strlcat( TheMask, at, sizeof( TheMask ));
|
||||
strlcpy(TheMask, Pattern, sizeof(TheMask) - 5);
|
||||
strlcat(TheMask, "!*@", sizeof(TheMask));
|
||||
strlcat(TheMask, at, sizeof(TheMask));
|
||||
return TheMask;
|
||||
}
|
||||
|
||||
/* All parts (nick, user and domain name) are given */
|
||||
strlcpy( TheMask, Pattern, sizeof( TheMask ));
|
||||
strlcpy(TheMask, Pattern, sizeof(TheMask));
|
||||
return TheMask;
|
||||
} /* Lists_MakeMask */
|
||||
|
||||
|
||||
/**
|
||||
* Check if a client is listed in a list.
|
||||
*
|
||||
* @param h List head.
|
||||
* @param Client Client to check.
|
||||
* @return true if client is listed, false if not.
|
||||
*/
|
||||
bool
|
||||
Lists_Check( struct list_head *header, CLIENT *Client)
|
||||
Lists_Check(struct list_head *h, CLIENT *Client)
|
||||
{
|
||||
struct list_elem *e, *last;
|
||||
return Lists_CheckReason(h, Client) != NULL;
|
||||
}
|
||||
|
||||
assert( header != NULL );
|
||||
/**
|
||||
* Check if a client is listed in a list and return the "reason".
|
||||
*
|
||||
* @param h List head.
|
||||
* @param Client Client to check.
|
||||
* @return true if client is listed, false if not.
|
||||
*/
|
||||
char *
|
||||
Lists_CheckReason(struct list_head *h, CLIENT *Client)
|
||||
{
|
||||
struct list_elem *e, *last, *next;
|
||||
|
||||
e = header->first;
|
||||
assert(h != NULL);
|
||||
|
||||
e = h->first;
|
||||
last = NULL;
|
||||
|
||||
while( e ) {
|
||||
if( Match( e->mask, Client_Mask( Client ))) {
|
||||
if( e->onlyonce ) { /* delete entry */
|
||||
LogDebug("Deleted \"%s\" from list", e->mask);
|
||||
Lists_Unlink(header, last, e);
|
||||
while (e) {
|
||||
next = e->next;
|
||||
if (Match(e->mask, Client_Mask(Client))) {
|
||||
if (e->valid_until == 1) {
|
||||
/* Entry is valid only once, delete it */
|
||||
LogDebug("Deleted \"%s\" from list (used).",
|
||||
e->mask);
|
||||
Lists_Unlink(h, last, e);
|
||||
}
|
||||
return true;
|
||||
return e->reason ? e->reason : "";
|
||||
}
|
||||
last = e;
|
||||
e = e->next;
|
||||
e = next;
|
||||
}
|
||||
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check list and purge expired entries.
|
||||
*
|
||||
* @param h List head.
|
||||
*/
|
||||
GLOBAL void
|
||||
Lists_Expire(struct list_head *h, const char *ListName)
|
||||
{
|
||||
struct list_elem *e, *last, *next;
|
||||
time_t now;
|
||||
|
||||
assert(h != NULL);
|
||||
|
||||
e = h->first;
|
||||
last = NULL;
|
||||
now = time(NULL);
|
||||
|
||||
while (e) {
|
||||
next = e->next;
|
||||
if (e->valid_until > 1 && e->valid_until < now) {
|
||||
/* Entry is expired, delete it */
|
||||
if (e->reason)
|
||||
Log(LOG_INFO,
|
||||
"Deleted \"%s\" (\"%s\") from %s list (expired).",
|
||||
e->mask, e->reason, ListName);
|
||||
else
|
||||
Log(LOG_INFO,
|
||||
"Deleted \"%s\" from %s list (expired).",
|
||||
e->mask, ListName);
|
||||
Lists_Unlink(h, last, e);
|
||||
e = next;
|
||||
continue;
|
||||
}
|
||||
last = e;
|
||||
e = next;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of entries of a list.
|
||||
*
|
||||
* @param h List head.
|
||||
* @return Number of items.
|
||||
*/
|
||||
GLOBAL unsigned long
|
||||
Lists_Count(struct list_head *h)
|
||||
{
|
||||
struct list_elem *e;
|
||||
unsigned long count = 0;
|
||||
|
||||
assert(h != NULL);
|
||||
|
||||
e = h->first;
|
||||
while (e) {
|
||||
count++;
|
||||
e = e->next;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/* -eof- */
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
|
||||
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -29,18 +29,24 @@ struct list_head {
|
||||
GLOBAL struct list_elem *Lists_GetFirst PARAMS((const struct list_head *));
|
||||
GLOBAL struct list_elem *Lists_GetNext PARAMS((const struct list_elem *));
|
||||
|
||||
GLOBAL bool Lists_Check PARAMS((struct list_head *head, CLIENT *client ));
|
||||
GLOBAL bool Lists_CheckDupeMask PARAMS((const struct list_head *head, const char *mask ));
|
||||
GLOBAL bool Lists_Check PARAMS((struct list_head *head, CLIENT *client));
|
||||
GLOBAL char *Lists_CheckReason PARAMS((struct list_head *head, CLIENT *client));
|
||||
GLOBAL struct list_elem *Lists_CheckDupeMask PARAMS((const struct list_head *head,
|
||||
const char *mask));
|
||||
|
||||
GLOBAL bool Lists_Add PARAMS((struct list_head *header, const char *Mask, bool OnlyOnce ));
|
||||
GLOBAL void Lists_Del PARAMS((struct list_head *head, const char *Mask ));
|
||||
GLOBAL bool Lists_Add PARAMS((struct list_head *h, const char *Mask,
|
||||
time_t ValidUntil, const char *Reason));
|
||||
GLOBAL void Lists_Del PARAMS((struct list_head *head, const char *Mask));
|
||||
GLOBAL unsigned long Lists_Count PARAMS((struct list_head *h));
|
||||
|
||||
GLOBAL bool Lists_AlreadyRegistered PARAMS(( const struct list_head *head, const char *Mask));
|
||||
|
||||
GLOBAL void Lists_Free PARAMS(( struct list_head *head ));
|
||||
GLOBAL void Lists_Free PARAMS((struct list_head *head));
|
||||
|
||||
GLOBAL const char *Lists_MakeMask PARAMS((const char *Pattern));
|
||||
GLOBAL const char *Lists_GetMask PARAMS(( const struct list_elem *e ));
|
||||
GLOBAL const char *Lists_GetMask PARAMS((const struct list_elem *e));
|
||||
GLOBAL const char *Lists_GetReason PARAMS((const struct list_elem *e));
|
||||
GLOBAL time_t Lists_GetValidity PARAMS((const struct list_elem *e));
|
||||
|
||||
GLOBAL void Lists_Expire PARAMS((struct list_head *h, const char *ListName));
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2010 Alexander Barton <alex@barton.de>
|
||||
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -21,14 +21,15 @@
|
||||
#define RPL_YOURHOST_MSG "002 %s :Your host is %s, running version ngircd-%s (%s/%s/%s)"
|
||||
#define RPL_CREATED_MSG "003 %s :This server has been started %s"
|
||||
#define RPL_MYINFO_MSG "004 %s %s ngircd-%s %s %s"
|
||||
#define RPL_ISUPPORT1_MSG "005 %s RFC2812 IRCD=ngIRCd CASEMAPPING=ascii PREFIX=(ov)@+ CHANTYPES=#&+ CHANMODES=bI,k,l,imnPst CHANLIMIT=#&+:%d :are supported on this server"
|
||||
#define RPL_ISUPPORT2_MSG "005 %s CHANNELLEN=%d NICKLEN=%d TOPICLEN=%d AWAYLEN=%d KICKLEN=%d PENALTY :are supported on this server"
|
||||
#define RPL_ISUPPORT1_MSG "005 %s RFC2812 IRCD=ngIRCd CASEMAPPING=ascii PREFIX=(ov)@+ CHANTYPES=#&+ CHANMODES=beI,k,l,imnOPRstz CHANLIMIT=#&+:%d :are supported on this server"
|
||||
#define RPL_ISUPPORT2_MSG "005 %s CHANNELLEN=%d NICKLEN=%d TOPICLEN=%d AWAYLEN=%d KICKLEN=%d MODES=%d MAXLIST=beI:%d EXCEPTS=e INVEX=I PENALTY :are supported on this server"
|
||||
|
||||
#define RPL_TRACELINK_MSG "200 %s Link %s-%s %s %s V%s %ld %d %d"
|
||||
#define RPL_TRACEOPERATOR_MSG "204 %s Oper 2 :%s"
|
||||
#define RPL_TRACESERVER_MSG "206 %s Serv 1 0S 0C %s[%s@%s] *!*@%s :V%s"
|
||||
#define RPL_STATSLINKINFO_MSG "211 %s %s %d %ld %ld %ld %ld :%ld"
|
||||
#define RPL_STATSCOMMANDS_MSG "212 %s %s %ld %ld %ld"
|
||||
#define RPL_STATSXLINE_MSG "216 %s %c %s %ld :%s"
|
||||
#define RPL_ENDOFSTATS_MSG "219 %s %c :End of STATS report"
|
||||
#define RPL_UMODEIS_MSG "221 %s +%s"
|
||||
#define RPL_SERVLIST_MSG "234 %s %s %s %s %d %d :%s"
|
||||
@@ -55,6 +56,7 @@
|
||||
#define RPL_ISON_MSG "303 %s :"
|
||||
#define RPL_UNAWAY_MSG "305 %s :You are no longer marked as being away"
|
||||
#define RPL_NOWAWAY_MSG "306 %s :You have been marked as being away"
|
||||
#define RPL_WHOISREGNICK_MSG "307 %s %s :is a registered nick"
|
||||
#define RPL_WHOISUSER_MSG "311 %s %s %s %s * :%s"
|
||||
#define RPL_WHOISSERVER_MSG "312 %s %s %s :%s"
|
||||
#define RPL_WHOISOPERATOR_MSG "313 %s %s :is an IRC operator"
|
||||
@@ -73,6 +75,8 @@
|
||||
#define RPL_INVITING_MSG "341 %s %s %s%s"
|
||||
#define RPL_INVITELIST_MSG "346 %s %s %s"
|
||||
#define RPL_ENDOFINVITELIST_MSG "347 %s %s :End of channel invite list"
|
||||
#define RPL_EXCEPTLIST_MSG "348 %s %s %s"
|
||||
#define RPL_ENDOFEXCEPTLIST_MSG "349 %s %s :End of channel exception list"
|
||||
#define RPL_VERSION_MSG "351 %s %s-%s.%s %s :%s"
|
||||
#define RPL_WHOREPLY_MSG "352 %s %s %s %s %s %s %s :%d %s"
|
||||
#define RPL_NAMREPLY_MSG "353 %s %s %s :"
|
||||
@@ -87,6 +91,7 @@
|
||||
#define RPL_MOTD_MSG "372 %s :- %s"
|
||||
#define RPL_MOTDSTART_MSG "375 %s :- %s message of the day"
|
||||
#define RPL_ENDOFMOTD_MSG "376 %s :End of MOTD command"
|
||||
#define RPL_WHOISHOST_MSG "378 %s %s :is connecting from *@%s %s"
|
||||
#define RPL_YOUREOPER_MSG "381 %s :You are now an IRC Operator"
|
||||
#define RPL_YOURESERVICE_MSG "383 %s :You are service %s"
|
||||
#define RPL_TIME_MSG "391 %s %s :%s"
|
||||
@@ -105,12 +110,13 @@
|
||||
#define ERR_NOMOTD_MSG "422 %s :MOTD file is missing"
|
||||
#define ERR_NONICKNAMEGIVEN_MSG "431 %s :No nickname given"
|
||||
#define ERR_ERRONEUSNICKNAME_MSG "432 %s %s :Erroneous nickname"
|
||||
#define ERR_NICKNAMETOOLONG_MSG "432 %s %s :Nickname too long, max. %u characters"
|
||||
#define ERR_NICKNAMEINUSE_MSG "433 %s %s :Nickname already in use"
|
||||
#define ERR_USERNOTINCHANNEL_MSG "441 %s %s %s :They aren't on that channel"
|
||||
#define ERR_NOTONCHANNEL_MSG "442 %s %s :You are not on that channel"
|
||||
#define ERR_USERONCHANNEL_MSG "443 %s %s %s :is already on channel"
|
||||
#define ERR_SUMMONDISABLED_MSG "445 %s %s :SUMMON has been disabled"
|
||||
#define ERR_USERSDISABLED_MSG "446 %s %s :USERS has been disabled"
|
||||
#define ERR_SUMMONDISABLED_MSG "445 %s :SUMMON has been disabled"
|
||||
#define ERR_USERSDISABLED_MSG "446 %s :USERS has been disabled"
|
||||
#define ERR_NOTREGISTERED_MSG "451 %s :Connection not registered"
|
||||
#define ERR_NOTREGISTEREDSERVER_MSG "451 %s :Connection not registered as server link"
|
||||
#define ERR_NEEDMOREPARAMS_MSG "461 %s %s :Syntax error"
|
||||
@@ -119,16 +125,19 @@
|
||||
#define ERR_CHANNELISFULL_MSG "471 %s %s :Cannot join channel (+l)"
|
||||
#define ERR_SECURECHANNEL_MSG "471 %s %s :Cannot join channel (+z)"
|
||||
#define ERR_OPONLYCHANNEL_MSG "471 %s %s :Cannot join channel (+O)"
|
||||
#define ERR_UNKNOWNMODE_MSG "472 %s: %c :is unknown mode char for %s"
|
||||
#define ERR_REGONLYCHANNEL_MSG "471 %s %s :Cannot join channel (+R)"
|
||||
#define ERR_UNKNOWNMODE_MSG "472 %s %c :is unknown mode char for %s"
|
||||
#define ERR_INVITEONLYCHAN_MSG "473 %s %s :Cannot join channel (+i)"
|
||||
#define ERR_BANNEDFROMCHAN_MSG "474 %s %s :Cannot join channel (+b)"
|
||||
#define ERR_BADCHANNELKEY_MSG "475 %s %s :Cannot join channel (+k)"
|
||||
#define ERR_NOCHANMODES_MSG "477 %s %s :Channel doesn't support modes"
|
||||
#define ERR_LISTFULL_MSG "478 %s %s %s: Channel list is full (%d)"
|
||||
#define ERR_NOPRIVILEGES_MSG "481 %s :Permission denied"
|
||||
#define ERR_CHANOPRIVSNEEDED_MSG "482 %s %s :You are not channel operator"
|
||||
#define ERR_CANTKILLSERVER_MSG "483 %s :You can't kill a server!"
|
||||
#define ERR_RESTRICTED_MSG "484 %s :Your connection is restricted"
|
||||
#define ERR_NOOPERHOST_MSG "491 %s :Not configured for your host"
|
||||
#define ERR_NOTONSAMECHANNEL_MSG "493 %s :You must share a common channel with %s"
|
||||
|
||||
#define ERR_UMODEUNKNOWNFLAG_MSG "501 %s :Unknown mode"
|
||||
#define ERR_UMODEUNKNOWNFLAG2_MSG "501 %s :Unknown mode \"%c%c\""
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
|
||||
* Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -38,6 +38,7 @@
|
||||
|
||||
#include "defines.h"
|
||||
#include "conn.h"
|
||||
#include "class.h"
|
||||
#include "conf-ssl.h"
|
||||
#include "channel.h"
|
||||
#include "conf.h"
|
||||
@@ -73,12 +74,12 @@ static bool NGIRCd_Init PARAMS(( bool ));
|
||||
* Here all starts: this function is called by the operating system loader,
|
||||
* it is the first portion of code executed of ngIRCd.
|
||||
*
|
||||
* @param argc The number of arguments passed to ngIRCd on the command line.
|
||||
* @param argv An array containing all the arguments passed to ngIRCd.
|
||||
* @return Global exit code of ngIRCd, zero on success.
|
||||
* @param argc The number of arguments passed to ngIRCd on the command line.
|
||||
* @param argv An array containing all the arguments passed to ngIRCd.
|
||||
* @return Global exit code of ngIRCd, zero on success.
|
||||
*/
|
||||
GLOBAL int
|
||||
main( int argc, const char *argv[] )
|
||||
main(int argc, const char *argv[])
|
||||
{
|
||||
bool ok, configtest = false;
|
||||
bool NGIRCd_NoDaemon = false;
|
||||
@@ -91,7 +92,7 @@ main( int argc, const char *argv[] )
|
||||
mtrace();
|
||||
#endif
|
||||
|
||||
umask( 0077 );
|
||||
umask(0077);
|
||||
|
||||
NGIRCd_SignalQuit = NGIRCd_SignalRestart = false;
|
||||
NGIRCd_Passive = false;
|
||||
@@ -101,75 +102,62 @@ main( int argc, const char *argv[] )
|
||||
#ifdef SNIFFER
|
||||
NGIRCd_Sniffer = false;
|
||||
#endif
|
||||
strlcpy( NGIRCd_ConfFile, SYSCONFDIR, sizeof( NGIRCd_ConfFile ));
|
||||
strlcat( NGIRCd_ConfFile, CONFIG_FILE, sizeof( NGIRCd_ConfFile ));
|
||||
strlcpy(NGIRCd_ConfFile, SYSCONFDIR, sizeof(NGIRCd_ConfFile));
|
||||
strlcat(NGIRCd_ConfFile, CONFIG_FILE, sizeof(NGIRCd_ConfFile));
|
||||
|
||||
Fill_Version( );
|
||||
Fill_Version();
|
||||
|
||||
/* parse conmmand line */
|
||||
for( i = 1; i < argc; i++ )
|
||||
{
|
||||
for (i = 1; i < argc; i++) {
|
||||
ok = false;
|
||||
if(( argv[i][0] == '-' ) && ( argv[i][1] == '-' ))
|
||||
{
|
||||
if (argv[i][0] == '-' && argv[i][1] == '-') {
|
||||
/* long option */
|
||||
if( strcmp( argv[i], "--config" ) == 0 )
|
||||
{
|
||||
if( i + 1 < argc )
|
||||
{
|
||||
if (strcmp(argv[i], "--config") == 0) {
|
||||
if (i + 1 < argc) {
|
||||
/* Ok, there's an parameter left */
|
||||
strlcpy( NGIRCd_ConfFile, argv[i + 1], sizeof( NGIRCd_ConfFile ));
|
||||
|
||||
strlcpy(NGIRCd_ConfFile, argv[i+1],
|
||||
sizeof(NGIRCd_ConfFile));
|
||||
/* next parameter */
|
||||
i++; ok = true;
|
||||
}
|
||||
}
|
||||
if( strcmp( argv[i], "--configtest" ) == 0 )
|
||||
{
|
||||
if (strcmp(argv[i], "--configtest") == 0) {
|
||||
configtest = true;
|
||||
ok = true;
|
||||
}
|
||||
#ifdef DEBUG
|
||||
if( strcmp( argv[i], "--debug" ) == 0 )
|
||||
{
|
||||
if (strcmp(argv[i], "--debug") == 0) {
|
||||
NGIRCd_Debug = true;
|
||||
ok = true;
|
||||
}
|
||||
#endif
|
||||
if( strcmp( argv[i], "--help" ) == 0 )
|
||||
{
|
||||
Show_Version( );
|
||||
puts( "" ); Show_Help( ); puts( "" );
|
||||
exit( 1 );
|
||||
if (strcmp(argv[i], "--help") == 0) {
|
||||
Show_Version();
|
||||
puts(""); Show_Help( ); puts( "" );
|
||||
exit(1);
|
||||
}
|
||||
if( strcmp( argv[i], "--nodaemon" ) == 0 )
|
||||
{
|
||||
if (strcmp(argv[i], "--nodaemon") == 0) {
|
||||
NGIRCd_NoDaemon = true;
|
||||
ok = true;
|
||||
}
|
||||
if( strcmp( argv[i], "--passive" ) == 0 )
|
||||
{
|
||||
if (strcmp(argv[i], "--passive") == 0) {
|
||||
NGIRCd_Passive = true;
|
||||
ok = true;
|
||||
}
|
||||
#ifdef SNIFFER
|
||||
if( strcmp( argv[i], "--sniffer" ) == 0 )
|
||||
{
|
||||
if (strcmp(argv[i], "--sniffer") == 0) {
|
||||
NGIRCd_Sniffer = true;
|
||||
ok = true;
|
||||
}
|
||||
#endif
|
||||
if( strcmp( argv[i], "--version" ) == 0 )
|
||||
{
|
||||
Show_Version( );
|
||||
exit( 1 );
|
||||
if (strcmp(argv[i], "--version") == 0) {
|
||||
Show_Version();
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else if(( argv[i][0] == '-' ) && ( argv[i][1] != '-' ))
|
||||
{
|
||||
else if(argv[i][0] == '-' && argv[i][1] != '-') {
|
||||
/* short option */
|
||||
for( n = 1; n < strlen( argv[i] ); n++ )
|
||||
{
|
||||
for (n = 1; n < strlen(argv[i]); n++) {
|
||||
ok = false;
|
||||
#ifdef DEBUG
|
||||
if (argv[i][n] == 'd') {
|
||||
@@ -178,14 +166,14 @@ main( int argc, const char *argv[] )
|
||||
}
|
||||
#endif
|
||||
if (argv[i][n] == 'f') {
|
||||
if(( ! argv[i][n + 1] ) && ( i + 1 < argc ))
|
||||
{
|
||||
if (!argv[i][n+1] && i+1 < argc) {
|
||||
/* Ok, next character is a blank */
|
||||
strlcpy( NGIRCd_ConfFile, argv[i + 1], sizeof( NGIRCd_ConfFile ));
|
||||
strlcpy(NGIRCd_ConfFile, argv[i+1],
|
||||
sizeof(NGIRCd_ConfFile));
|
||||
|
||||
/* go to the following parameter */
|
||||
i++;
|
||||
n = strlen( argv[i] );
|
||||
n = strlen(argv[i]);
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
@@ -220,46 +208,49 @@ main( int argc, const char *argv[] )
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (! ok) {
|
||||
printf( "%s: invalid option \"-%c\"!\n", PACKAGE_NAME, argv[i][n] );
|
||||
printf( "Try \"%s --help\" for more information.\n", PACKAGE_NAME );
|
||||
exit( 1 );
|
||||
if (!ok) {
|
||||
printf("%s: invalid option \"-%c\"!\n",
|
||||
PACKAGE_NAME, argv[i][n]);
|
||||
printf("Try \"%s --help\" for more information.\n",
|
||||
PACKAGE_NAME);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if( ! ok )
|
||||
{
|
||||
printf( "%s: invalid option \"%s\"!\n", PACKAGE_NAME, argv[i] );
|
||||
printf( "Try \"%s --help\" for more information.\n", PACKAGE_NAME );
|
||||
exit( 1 );
|
||||
if (!ok) {
|
||||
printf("%s: invalid option \"%s\"!\n",
|
||||
PACKAGE_NAME, argv[i]);
|
||||
printf("Try \"%s --help\" for more information.\n",
|
||||
PACKAGE_NAME);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Debug level for "VERSION" command */
|
||||
NGIRCd_DebugLevel[0] = '\0';
|
||||
#ifdef DEBUG
|
||||
if( NGIRCd_Debug ) strcpy( NGIRCd_DebugLevel, "1" );
|
||||
if (NGIRCd_Debug)
|
||||
strcpy(NGIRCd_DebugLevel, "1");
|
||||
#endif
|
||||
#ifdef SNIFFER
|
||||
if( NGIRCd_Sniffer )
|
||||
{
|
||||
if (NGIRCd_Sniffer) {
|
||||
NGIRCd_Debug = true;
|
||||
strcpy( NGIRCd_DebugLevel, "2" );
|
||||
strcpy(NGIRCd_DebugLevel, "2");
|
||||
}
|
||||
#endif
|
||||
|
||||
if( configtest )
|
||||
{
|
||||
Show_Version( ); puts( "" );
|
||||
exit( Conf_Test( ));
|
||||
if (configtest) {
|
||||
Show_Version(); puts("");
|
||||
exit(Conf_Test());
|
||||
}
|
||||
|
||||
while( ! NGIRCd_SignalQuit )
|
||||
{
|
||||
|
||||
while (!NGIRCd_SignalQuit) {
|
||||
/* Initialize global variables */
|
||||
NGIRCd_Start = time( NULL );
|
||||
(void)strftime( NGIRCd_StartStr, 64, "%a %b %d %Y at %H:%M:%S (%Z)", localtime( &NGIRCd_Start ));
|
||||
NGIRCd_Start = time(NULL);
|
||||
(void)strftime(NGIRCd_StartStr, 64,
|
||||
"%a %b %d %Y at %H:%M:%S (%Z)",
|
||||
localtime(&NGIRCd_Start));
|
||||
|
||||
NGIRCd_SignalRestart = false;
|
||||
NGIRCd_SignalQuit = false;
|
||||
@@ -267,8 +258,8 @@ main( int argc, const char *argv[] )
|
||||
Random_Init();
|
||||
|
||||
/* Initialize modules, part I */
|
||||
Log_Init( ! NGIRCd_NoDaemon );
|
||||
Conf_Init( );
|
||||
Log_Init(!NGIRCd_NoDaemon);
|
||||
Conf_Init();
|
||||
|
||||
/* Initialize the "main program": chroot environment, user and
|
||||
* group ID, ... */
|
||||
@@ -279,17 +270,22 @@ main( int argc, const char *argv[] )
|
||||
|
||||
/* Initialize modules, part II: these functions are eventually
|
||||
* called with already dropped privileges ... */
|
||||
Channel_Init( );
|
||||
Client_Init( );
|
||||
Conn_Init( );
|
||||
Channel_Init();
|
||||
Client_Init();
|
||||
Conn_Init();
|
||||
Class_Init();
|
||||
|
||||
if (!io_library_init(CONNECTION_POOL)) {
|
||||
Log(LOG_ALERT, "Fatal: Cannot initialize IO routines: %s", strerror(errno));
|
||||
Log(LOG_ALERT,
|
||||
"Fatal: Could not initialize IO routines: %s",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!Signals_Init()) {
|
||||
Log(LOG_ALERT, "Fatal: Could not set up signal handlers: %s", strerror(errno));
|
||||
Log(LOG_ALERT,
|
||||
"Fatal: Could not set up signal handlers: %s",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -297,39 +293,45 @@ main( int argc, const char *argv[] )
|
||||
* used by ngIRCd in PASS commands and the known "extended
|
||||
* flags" are described in doc/Protocol.txt. */
|
||||
#ifdef IRCPLUS
|
||||
snprintf( NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s:%s", PROTOVER, PROTOIRCPLUS, PACKAGE_NAME, PACKAGE_VERSION, IRCPLUSFLAGS );
|
||||
snprintf(NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s:%s",
|
||||
PROTOVER, PROTOIRCPLUS, PACKAGE_NAME, PACKAGE_VERSION,
|
||||
IRCPLUSFLAGS);
|
||||
#ifdef ZLIB
|
||||
strcat( NGIRCd_ProtoID, "Z" );
|
||||
strcat(NGIRCd_ProtoID, "Z");
|
||||
#endif
|
||||
if( Conf_OperCanMode ) strcat( NGIRCd_ProtoID, "o" );
|
||||
#else
|
||||
snprintf( NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s", PROTOVER, PROTOIRC, PACKAGE_NAME, PACKAGE_VERSION );
|
||||
#endif
|
||||
strlcat( NGIRCd_ProtoID, " P", sizeof NGIRCd_ProtoID );
|
||||
if (Conf_OperCanMode)
|
||||
strcat(NGIRCd_ProtoID, "o");
|
||||
#else /* IRCPLUS */
|
||||
snprintf(NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s",
|
||||
PROTOVER, PROTOIRC, PACKAGE_NAME, PACKAGE_VERSION);
|
||||
#endif /* IRCPLUS */
|
||||
strlcat(NGIRCd_ProtoID, " P", sizeof NGIRCd_ProtoID);
|
||||
#ifdef ZLIB
|
||||
strlcat( NGIRCd_ProtoID, "Z", sizeof NGIRCd_ProtoID );
|
||||
strlcat(NGIRCd_ProtoID, "Z", sizeof NGIRCd_ProtoID);
|
||||
#endif
|
||||
LogDebug("Protocol and server ID is \"%s\".", NGIRCd_ProtoID);
|
||||
|
||||
Channel_InitPredefined( );
|
||||
Channel_InitPredefined();
|
||||
|
||||
if( Conn_InitListeners( ) < 1 )
|
||||
{
|
||||
Log( LOG_ALERT, "Server isn't listening on a single port!" );
|
||||
Log( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME );
|
||||
Pidfile_Delete( );
|
||||
exit( 1 );
|
||||
if (Conn_InitListeners() < 1) {
|
||||
Log(LOG_ALERT,
|
||||
"Server isn't listening on a single port!" );
|
||||
Log(LOG_ALERT,
|
||||
"%s exiting due to fatal errors!", PACKAGE_NAME);
|
||||
Pidfile_Delete();
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Main Run Loop */
|
||||
Conn_Handler( );
|
||||
Conn_Handler();
|
||||
|
||||
Conn_Exit( );
|
||||
Client_Exit( );
|
||||
Channel_Exit( );
|
||||
Log_Exit( );
|
||||
Conn_Exit();
|
||||
Client_Exit();
|
||||
Channel_Exit();
|
||||
Class_Exit();
|
||||
Log_Exit();
|
||||
}
|
||||
Pidfile_Delete( );
|
||||
Pidfile_Delete();
|
||||
|
||||
return 0;
|
||||
} /* main */
|
||||
@@ -421,7 +423,7 @@ static void
|
||||
Show_Version( void )
|
||||
{
|
||||
puts( NGIRCd_Version );
|
||||
puts( "Copyright (c)2001-2011 Alexander Barton (<alex@barton.de>) and Contributors." );
|
||||
puts( "Copyright (c)2001-2012 Alexander Barton (<alex@barton.de>) and Contributors." );
|
||||
puts( "Homepage: <http://ngircd.barton.de/>\n" );
|
||||
puts( "This is free software; see the source for copying conditions. There is NO" );
|
||||
puts( "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." );
|
||||
@@ -553,9 +555,10 @@ NGIRCd_getNobodyID(uid_t *uid, gid_t *gid )
|
||||
#endif
|
||||
|
||||
pwd = getpwnam("nobody");
|
||||
if (!pwd) return false;
|
||||
if (!pwd)
|
||||
return false;
|
||||
|
||||
if ( !pwd->pw_uid || !pwd->pw_gid)
|
||||
if (!pwd->pw_uid || !pwd->pw_gid)
|
||||
return false;
|
||||
|
||||
*uid = pwd->pw_uid;
|
||||
@@ -593,19 +596,19 @@ Random_Init(void)
|
||||
return;
|
||||
if (Random_Init_Kern("/dev/arandom"))
|
||||
return;
|
||||
srand(rand() ^ getpid() ^ time(NULL));
|
||||
srand(rand() ^ (unsigned)getpid() ^ (unsigned)time(NULL));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initialize ngIRCd daemon.
|
||||
*
|
||||
* @param NGIRCd_NoDaemon Set to true if ngIRCd should run in the
|
||||
* foreground and not as a daemon.
|
||||
* @return true on success.
|
||||
* @param NGIRCd_NoDaemon Set to true if ngIRCd should run in the
|
||||
* foreground (and not as a daemon).
|
||||
* @return true on success.
|
||||
*/
|
||||
static bool
|
||||
NGIRCd_Init( bool NGIRCd_NoDaemon )
|
||||
NGIRCd_Init(bool NGIRCd_NoDaemon)
|
||||
{
|
||||
static bool initialized;
|
||||
bool chrooted = false;
|
||||
@@ -621,57 +624,74 @@ NGIRCd_Init( bool NGIRCd_NoDaemon )
|
||||
/* open /dev/null before chroot() */
|
||||
fd = open( "/dev/null", O_RDWR);
|
||||
if (fd < 0)
|
||||
Log(LOG_WARNING, "Could not open /dev/null: %s", strerror(errno));
|
||||
Log(LOG_WARNING, "Could not open /dev/null: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
/* SSL initialization */
|
||||
if (!ConnSSL_InitLibrary())
|
||||
Log(LOG_WARNING,
|
||||
"Warning: Error during SSL initialization, continuing ...");
|
||||
|
||||
if( Conf_Chroot[0] ) {
|
||||
if( chdir( Conf_Chroot ) != 0 ) {
|
||||
Log( LOG_ERR, "Can't chdir() in ChrootDir (%s): %s", Conf_Chroot, strerror( errno ));
|
||||
/* Change root */
|
||||
if (Conf_Chroot[0]) {
|
||||
if (chdir(Conf_Chroot) != 0) {
|
||||
Log(LOG_ERR, "Can't chdir() in ChrootDir (%s): %s",
|
||||
Conf_Chroot, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
|
||||
if( chroot( Conf_Chroot ) != 0 ) {
|
||||
if (chroot(Conf_Chroot) != 0) {
|
||||
if (errno != EPERM) {
|
||||
Log( LOG_ERR, "Can't change root directory to \"%s\": %s",
|
||||
Conf_Chroot, strerror( errno ));
|
||||
Log(LOG_ERR,
|
||||
"Can't change root directory to \"%s\": %s",
|
||||
Conf_Chroot, strerror(errno));
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
chrooted = true;
|
||||
Log( LOG_INFO, "Changed root and working directory to \"%s\".", Conf_Chroot );
|
||||
Log(LOG_INFO,
|
||||
"Changed root and working directory to \"%s\".",
|
||||
Conf_Chroot);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check user ID */
|
||||
if (Conf_UID == 0) {
|
||||
Log(LOG_INFO, "ServerUID must not be 0, using \"nobody\" instead.", Conf_UID);
|
||||
|
||||
if (! NGIRCd_getNobodyID(&Conf_UID, &Conf_GID)) {
|
||||
Log(LOG_WARNING, "Could not get user/group ID of user \"nobody\": %s",
|
||||
errno ? strerror(errno) : "not found" );
|
||||
pwd = getpwuid(0);
|
||||
Log(LOG_INFO,
|
||||
"ServerUID must not be %s(0), using \"nobody\" instead.",
|
||||
pwd ? pwd->pw_name : "?");
|
||||
if (!NGIRCd_getNobodyID(&Conf_UID, &Conf_GID)) {
|
||||
Log(LOG_WARNING,
|
||||
"Could not get user/group ID of user \"nobody\": %s",
|
||||
errno ? strerror(errno) : "not found" );
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Change group ID */
|
||||
if (getgid() != Conf_GID) {
|
||||
/* Change group ID */
|
||||
if (setgid(Conf_GID) != 0) {
|
||||
real_errno = errno;
|
||||
Log( LOG_ERR, "Can't change group ID to %u: %s", Conf_GID, strerror( errno ));
|
||||
grp = getgrgid(Conf_GID);
|
||||
Log(LOG_ERR, "Can't change group ID to %s(%u): %s",
|
||||
grp ? grp->gr_name : "?", Conf_GID,
|
||||
strerror(errno));
|
||||
if (real_errno != EPERM)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Change user ID */
|
||||
if (getuid() != Conf_UID) {
|
||||
/* Change user ID */
|
||||
if (setuid(Conf_UID) != 0) {
|
||||
real_errno = errno;
|
||||
Log(LOG_ERR, "Can't change user ID to %u: %s", Conf_UID, strerror(errno));
|
||||
if (real_errno != EPERM)
|
||||
pwd = getpwuid(Conf_UID);
|
||||
Log(LOG_ERR, "Can't change user ID to %s(%u): %s",
|
||||
pwd ? pwd->pw_name : "?", Conf_UID,
|
||||
strerror(errno));
|
||||
if (real_errno != EPERM)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
@@ -681,26 +701,27 @@ NGIRCd_Init( bool NGIRCd_NoDaemon )
|
||||
/* Normally a child process is forked which isn't any longer
|
||||
* connected to ther controlling terminal. Use "--nodaemon"
|
||||
* to disable this "daemon mode" (useful for debugging). */
|
||||
if ( ! NGIRCd_NoDaemon ) {
|
||||
pid = fork( );
|
||||
if( pid > 0 ) {
|
||||
if (!NGIRCd_NoDaemon) {
|
||||
pid = fork();
|
||||
if (pid > 0) {
|
||||
/* "Old" process: exit. */
|
||||
exit( 0 );
|
||||
exit(0);
|
||||
}
|
||||
if( pid < 0 ) {
|
||||
if (pid < 0) {
|
||||
/* Error!? */
|
||||
fprintf( stderr, "%s: Can't fork: %s!\nFatal error, exiting now ...\n",
|
||||
PACKAGE_NAME, strerror( errno ));
|
||||
exit( 1 );
|
||||
fprintf(stderr,
|
||||
"%s: Can't fork: %s!\nFatal error, exiting now ...\n",
|
||||
PACKAGE_NAME, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* New child process */
|
||||
#ifndef NeXT
|
||||
(void)setsid( );
|
||||
(void)setsid();
|
||||
#else
|
||||
setpgrp(0, getpid());
|
||||
#endif
|
||||
if (chdir( "/" ) != 0)
|
||||
if (chdir("/") != 0)
|
||||
Log(LOG_ERR, "Can't change directory to '/': %s",
|
||||
strerror(errno));
|
||||
|
||||
@@ -711,19 +732,19 @@ NGIRCd_Init( bool NGIRCd_NoDaemon )
|
||||
}
|
||||
pid = getpid();
|
||||
|
||||
Pidfile_Create( pid );
|
||||
Pidfile_Create(pid);
|
||||
|
||||
/* Check UID/GID we are running as, can be different from values
|
||||
* configured (e. g. if we were already started with a UID>0. */
|
||||
Conf_UID = getuid();
|
||||
Conf_GID = getgid();
|
||||
|
||||
pwd = getpwuid( Conf_UID );
|
||||
grp = getgrgid( Conf_GID );
|
||||
pwd = getpwuid(Conf_UID);
|
||||
grp = getgrgid(Conf_GID);
|
||||
|
||||
Log(LOG_INFO, "Running as user %s(%ld), group %s(%ld), with PID %ld.",
|
||||
pwd ? pwd->pw_name : "unknown", (long)Conf_UID,
|
||||
grp ? grp->gr_name : "unknown", (long)Conf_GID, (long)pid);
|
||||
pwd ? pwd->pw_name : "unknown", (long)Conf_UID,
|
||||
grp ? grp->gr_name : "unknown", (long)Conf_GID, (long)pid);
|
||||
|
||||
if (chrooted) {
|
||||
Log(LOG_INFO, "Running with root directory \"%s\".",
|
||||
@@ -732,20 +753,23 @@ NGIRCd_Init( bool NGIRCd_NoDaemon )
|
||||
} else
|
||||
Log(LOG_INFO, "Not running with changed root directory.");
|
||||
|
||||
/* Change working directory to home directory of the user
|
||||
* we are running as (only when running in daemon mode and not in chroot) */
|
||||
/* Change working directory to home directory of the user we are
|
||||
* running as (only when running in daemon mode and not in chroot) */
|
||||
|
||||
if (NGIRCd_NoDaemon)
|
||||
return true;
|
||||
|
||||
if (pwd) {
|
||||
if (!NGIRCd_NoDaemon ) {
|
||||
if( chdir( pwd->pw_dir ) == 0 )
|
||||
Log( LOG_DEBUG, "Changed working directory to \"%s\" ...", pwd->pw_dir );
|
||||
else
|
||||
Log( LOG_INFO, "Notice: Can't change working directory to \"%s\": %s",
|
||||
pwd->pw_dir, strerror( errno ));
|
||||
}
|
||||
} else {
|
||||
Log( LOG_ERR, "Can't get user informaton for UID %d!?", Conf_UID );
|
||||
}
|
||||
if (chdir(pwd->pw_dir) == 0)
|
||||
Log(LOG_DEBUG,
|
||||
"Changed working directory to \"%s\" ...",
|
||||
pwd->pw_dir);
|
||||
else
|
||||
Log(LOG_INFO,
|
||||
"Notice: Can't change working directory to \"%s\": %s",
|
||||
pwd->pw_dir, strerror(errno));
|
||||
} else
|
||||
Log(LOG_ERR, "Can't get user informaton for UID %d!?", Conf_UID);
|
||||
|
||||
return true;
|
||||
out:
|
||||
|
@@ -28,6 +28,7 @@
|
||||
#include "conn.h"
|
||||
#include "conn-func.h"
|
||||
#include "channel.h"
|
||||
#include "class.h"
|
||||
#include "irc-write.h"
|
||||
#include "lists.h"
|
||||
#include "log.h"
|
||||
@@ -194,8 +195,10 @@ Announce_User(CLIENT * Client, CLIENT * User)
|
||||
#ifdef IRCPLUS
|
||||
|
||||
/**
|
||||
* Synchronize invite and ban lists between servers
|
||||
* @param Client New server
|
||||
* Synchronize invite, ban, G- and K-Line lists between servers.
|
||||
*
|
||||
* @param Client New server.
|
||||
* @return CONNECTED or DISCONNECTED.
|
||||
*/
|
||||
static bool
|
||||
Synchronize_Lists(CLIENT * Client)
|
||||
@@ -206,6 +209,18 @@ Synchronize_Lists(CLIENT * Client)
|
||||
|
||||
assert(Client != NULL);
|
||||
|
||||
/* g-lines */
|
||||
head = Class_GetList(CLASS_GLINE);
|
||||
elem = Lists_GetFirst(head);
|
||||
while (elem) {
|
||||
if (!IRC_WriteStrClient(Client, "GLINE %s %ld :%s",
|
||||
Lists_GetMask(elem),
|
||||
Lists_GetValidity(elem) - time(NULL),
|
||||
Lists_GetReason(elem)))
|
||||
return DISCONNECTED;
|
||||
elem = Lists_GetNext(elem);
|
||||
}
|
||||
|
||||
c = Channel_First();
|
||||
while (c) {
|
||||
/* ban list */
|
||||
@@ -369,6 +384,10 @@ IRC_Num_ENDOFMOTD(CLIENT * Client, UNUSED REQUEST * Req)
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!IRC_WriteStrClient(Client, "PING :%s",
|
||||
Client_ID(Client_ThisServer())))
|
||||
return DISCONNECTED;
|
||||
|
||||
return CONNECTED;
|
||||
} /* IRC_Num_ENDOFMOTD */
|
||||
|
||||
|
@@ -58,9 +58,15 @@ Op_NoPrivileges(CLIENT * Client, REQUEST * Req)
|
||||
|
||||
|
||||
/**
|
||||
* Check that the client is an IRC operator allowed to administer this server.
|
||||
* Check that the originator of a request is an IRC operator and allowed
|
||||
* to administer this server.
|
||||
*
|
||||
* @param CLient Client from which the command has been received.
|
||||
* @param Req Request structure.
|
||||
* @return CLIENT structure of the client that initiated the command or
|
||||
* NULL if client is not allowed to execute operator commands.
|
||||
*/
|
||||
GLOBAL bool
|
||||
GLOBAL CLIENT *
|
||||
Op_Check(CLIENT * Client, REQUEST * Req)
|
||||
{
|
||||
CLIENT *c;
|
||||
@@ -72,15 +78,20 @@ Op_Check(CLIENT * Client, REQUEST * Req)
|
||||
c = Client_Search(Req->prefix);
|
||||
else
|
||||
c = Client;
|
||||
|
||||
if (!c)
|
||||
return false;
|
||||
return NULL;
|
||||
if (Client_Type(Client) == CLIENT_SERVER
|
||||
&& Client_Type(c) == CLIENT_SERVER)
|
||||
return c;
|
||||
if (!Client_HasMode(c, 'o'))
|
||||
return false;
|
||||
return NULL;
|
||||
if (!Client_OperByMe(c) && !Conf_AllowRemoteOper)
|
||||
return false;
|
||||
return NULL;
|
||||
|
||||
/* The client is an local IRC operator, or this server is configured
|
||||
* to trust remote operators. */
|
||||
return true;
|
||||
return c;
|
||||
} /* Op_Check */
|
||||
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2009 Alexander Barton (alex@barton.de)
|
||||
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -18,7 +18,7 @@
|
||||
*/
|
||||
|
||||
GLOBAL bool Op_NoPrivileges PARAMS((CLIENT * Client, REQUEST * Req));
|
||||
GLOBAL bool Op_Check PARAMS((CLIENT * Client, REQUEST * Req));
|
||||
GLOBAL CLIENT *Op_Check PARAMS((CLIENT * Client, REQUEST * Req));
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -103,7 +103,7 @@ PAM_Authenticate(CLIENT *Client) {
|
||||
if (password)
|
||||
free(password);
|
||||
password = strdup(Client_Password(Client));
|
||||
conv.appdata_ptr = password;
|
||||
conv.appdata_ptr = Client_Password(Client);
|
||||
|
||||
/* Initialize PAM */
|
||||
retval = pam_start("ngircd", Client_OrigUser(Client), &conv, &pam);
|
||||
|
@@ -63,6 +63,7 @@ static COMMAND My_Commands[] =
|
||||
{ "DIE", IRC_DIE, CLIENT_USER, 0, 0, 0 },
|
||||
{ "DISCONNECT", IRC_DISCONNECT, CLIENT_USER, 0, 0, 0 },
|
||||
{ "ERROR", IRC_ERROR, 0xFFFF, 0, 0, 0 },
|
||||
{ "GLINE", IRC_xLINE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
|
||||
{ "HELP", IRC_HELP, CLIENT_USER, 0, 0, 0 },
|
||||
{ "INFO", IRC_INFO, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
|
||||
{ "INVITE", IRC_INVITE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
|
||||
@@ -70,6 +71,7 @@ static COMMAND My_Commands[] =
|
||||
{ "JOIN", IRC_JOIN, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
|
||||
{ "KICK", IRC_KICK, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
|
||||
{ "KILL", IRC_KILL, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
|
||||
{ "KLINE", IRC_xLINE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
|
||||
{ "LINKS", IRC_LINKS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
|
||||
{ "LIST", IRC_LIST, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
|
||||
{ "LUSERS", IRC_LUSERS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 },
|
||||
@@ -325,13 +327,21 @@ Validate_Prefix( CONN_ID Idx, REQUEST *Req, bool *Closed )
|
||||
/* check if the client named in the prefix is expected
|
||||
* to come from that direction */
|
||||
if (Client_NextHop(c) != client) {
|
||||
Log(LOG_ERR,
|
||||
"Spoofed prefix \"%s\" from \"%s\" (connection %d, command \"%s\")!",
|
||||
Req->prefix, Client_Mask(Conn_GetClient(Idx)), Idx,
|
||||
Req->command);
|
||||
Conn_Close(Idx, NULL, "Spoofed prefix", true);
|
||||
*Closed = true;
|
||||
if (Client_Type(c) != CLIENT_SERVER) {
|
||||
Log(LOG_ERR,
|
||||
"Spoofed prefix \"%s\" from \"%s\" (connection %d, command \"%s\")!",
|
||||
Req->prefix, Client_Mask(Conn_GetClient(Idx)), Idx,
|
||||
Req->command);
|
||||
Conn_Close(Idx, NULL, "Spoofed prefix", true);
|
||||
*Closed = true;
|
||||
} else {
|
||||
Log(LOG_INFO,
|
||||
"Ignoring spoofed prefix \"%s\" from \"%s\" (connection %d, command \"%s\").",
|
||||
Req->prefix, Client_Mask(Conn_GetClient(Idx)), Idx,
|
||||
Req->command);
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2010 Alexander Barton (alex@barton.de)
|
||||
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -79,7 +79,6 @@ Proc_Fork(PROC_STAT *proc, int *pipefds, void (*cbfunc)(int, short), int timeout
|
||||
signal(SIGALRM, Proc_GenericSignalHandler);
|
||||
close(pipefds[0]);
|
||||
alarm(timeout);
|
||||
Conn_CloseAllSockets();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -138,14 +137,28 @@ Proc_Read(PROC_STAT *proc, void *buffer, size_t buflen)
|
||||
return 0;
|
||||
Log(LOG_CRIT, "Can't read from child process %ld: %s",
|
||||
proc->pid, strerror(errno));
|
||||
Proc_Close(proc);
|
||||
bytes_read = 0;
|
||||
} else if (bytes_read == 0) {
|
||||
/* EOF: clean up */
|
||||
LogDebug("Child process %ld: EOF reached, closing pipe.",
|
||||
proc->pid);
|
||||
Proc_Close(proc);
|
||||
}
|
||||
#if DEBUG
|
||||
else if (bytes_read == 0)
|
||||
LogDebug("Can't read from child process %ld: EOF", proc->pid);
|
||||
#endif
|
||||
Proc_InitStruct(proc);
|
||||
return (size_t)bytes_read;
|
||||
}
|
||||
|
||||
/**
|
||||
* Close pipe to a forked child process.
|
||||
*/
|
||||
GLOBAL void
|
||||
Proc_Close(PROC_STAT *proc)
|
||||
{
|
||||
/* Close socket, if it exists */
|
||||
if (proc->pipe_fd >= 0)
|
||||
io_close(proc->pipe_fd);
|
||||
|
||||
Proc_InitStruct(proc);
|
||||
}
|
||||
|
||||
/* -eof- */
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2010 Alexander Barton (alex@barton.de)
|
||||
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -38,6 +38,9 @@ GLOBAL void Proc_GenericSignalHandler PARAMS((int Signal));
|
||||
|
||||
GLOBAL size_t Proc_Read PARAMS((PROC_STAT *proc, void *buffer, size_t buflen));
|
||||
|
||||
GLOBAL void Proc_Close PARAMS((PROC_STAT *proc));
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/* -eof- */
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* ngIRCd -- The Next Generation IRC Daemon
|
||||
* Copyright (c)2001-2009 by Alexander Barton (alex@barton.de)
|
||||
* Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -75,7 +75,8 @@ Resolve_Addr(PROC_STAT * s, const ng_ipaddr_t *Addr, int identsock,
|
||||
} else if( pid == 0 ) {
|
||||
/* Sub process */
|
||||
Log_Init_Subprocess("Resolver");
|
||||
Do_ResolveAddr( Addr, identsock, pipefd[1]);
|
||||
Conn_CloseAllSockets(identsock);
|
||||
Do_ResolveAddr(Addr, identsock, pipefd[1]);
|
||||
Log_Exit_Subprocess("Resolver");
|
||||
exit(0);
|
||||
}
|
||||
@@ -104,6 +105,7 @@ Resolve_Name( PROC_STAT *s, const char *Host, void (*cbfunc)(int, short))
|
||||
} else if( pid == 0 ) {
|
||||
/* Sub process */
|
||||
Log_Init_Subprocess("Resolver");
|
||||
Conn_CloseAllSockets(NONE);
|
||||
Do_ResolveName(Host, pipefd[1]);
|
||||
Log_Exit_Subprocess("Resolver");
|
||||
exit(0);
|
||||
|
@@ -164,6 +164,10 @@ extern char * strtok_r PARAMS((char *str, const char *delim, char **saveptr));
|
||||
extern int vsnprintf PARAMS(( char *str, size_t count, const char *fmt, va_list args ));
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_GAI_STRERROR
|
||||
#define gai_strerror(r) "unknown error"
|
||||
#endif
|
||||
|
||||
#ifndef PACKAGE_NAME
|
||||
#define PACKAGE_NAME PACKAGE
|
||||
#endif
|
||||
|
@@ -16,7 +16,7 @@ elif [ $UNAME = "GNU" ]; then
|
||||
elif [ $UNAME = "SunOS" ]; then
|
||||
PS_FLAGS="-af"; PS_PIDCOL=2; HEAD_FLAGS="-n 1"
|
||||
else
|
||||
PS_FLAGS="-f"; PS_PIDCOL="2"; HEAD_FLAGS="-n 1"
|
||||
PS_FLAGS="-af"; PS_PIDCOL="2"; HEAD_FLAGS="-n 1"
|
||||
ps $PS_FLAGS > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then PS_FLAGS="a"; PS_PIDCOL="1"; fi
|
||||
fi
|
||||
|
@@ -35,7 +35,7 @@ expect {
|
||||
"@* PRIVMSG nick :test\r*@* PRIVMSG nick :test"
|
||||
}
|
||||
|
||||
send "privmsg nick,#testChannel,nick :test\r"
|
||||
send "privmsg Nick,#testChannel,nick :test\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
"@* PRIVMSG nick :test\r*401*@* PRIVMSG nick :test"
|
||||
@@ -47,7 +47,7 @@ expect {
|
||||
"401"
|
||||
}
|
||||
|
||||
send "privmsg ~user@ngircd.test.server :test\r"
|
||||
send "privmsg ~UsEr@ngIRCd.Test.Server :test\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
"@* PRIVMSG nick :test"
|
||||
@@ -65,7 +65,7 @@ expect {
|
||||
# "@* PRIVMSG nick :test"
|
||||
#}
|
||||
#
|
||||
#send "privmsg nick!~user@localhost :test\r"
|
||||
#send "privmsg Nick!~User@LocalHost :test\r"
|
||||
#expect {
|
||||
# timeout { exit 1 }
|
||||
# "@* PRIVMSG nick :test"
|
||||
|
@@ -4,6 +4,7 @@
|
||||
[Global]
|
||||
Name = ngircd.test.server
|
||||
Info = ngIRCd Test-Server 1
|
||||
Listen = 127.0.0.1
|
||||
Ports = 6789
|
||||
MotdFile = ngircd-test1.motd
|
||||
AdminEMail = admin@irc.server
|
||||
|
@@ -4,6 +4,7 @@
|
||||
[Global]
|
||||
Name = ngircd.test.server2
|
||||
Info = ngIRCd Test-Server 2
|
||||
Listen = 127.0.0.1
|
||||
Ports = 6790
|
||||
MotdFile = ngircd-test2.motd
|
||||
AdminEMail = admin@irc.server2
|
||||
@@ -23,7 +24,7 @@
|
||||
|
||||
[Server]
|
||||
Name = ngircd.test.server
|
||||
Host = localhost
|
||||
Host = 127.0.0.1
|
||||
Port = 6789
|
||||
MyPassword = pwd2
|
||||
PeerPassword = pwd1
|
||||
|
@@ -14,19 +14,13 @@ expect {
|
||||
send "who\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
":ngircd.test.server 352 nick \* * ngircd.test.server nick H :0 Real Name"
|
||||
}
|
||||
|
||||
send "join #channel\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
"@* JOIN :#channel"
|
||||
":ngircd.test.server 352 nick \* * * ngircd.test.server nick H :0 Real Name"
|
||||
}
|
||||
|
||||
send "who 0\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
":ngircd.test.server 352 nick #channel * ngircd.test.server nick H@ :0 Real Name"
|
||||
":ngircd.test.server 352 nick \* * * ngircd.test.server nick H :0 Real Name"
|
||||
}
|
||||
|
||||
send "away :testing\r"
|
||||
@@ -38,7 +32,19 @@ expect {
|
||||
send "who *\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
":ngircd.test.server 352 nick #channel * ngircd.test.server nick G@ :0 Real Name"
|
||||
":ngircd.test.server 352 nick \* * * ngircd.test.server nick G :0 Real Name"
|
||||
}
|
||||
|
||||
send "join #channel\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
"@* JOIN :#channel"
|
||||
}
|
||||
|
||||
send "who #channel\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
":ngircd.test.server 352 nick #channel * * ngircd.test.server nick G@ :0 Real Name"
|
||||
}
|
||||
|
||||
send "mode #channel +v nick\r"
|
||||
@@ -47,10 +53,16 @@ expect {
|
||||
"@* MODE #channel +v nick\r"
|
||||
}
|
||||
|
||||
send "who #channel\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
":ngircd.test.server 352 nick #channel * * ngircd.test.server nick G@ :0 Real Name"
|
||||
}
|
||||
|
||||
send "who localhos*\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
":ngircd.test.server 352 nick #channel * ngircd.test.server nick G@ :0 Real Name"
|
||||
":ngircd.test.server 352 nick \* * * ngircd.test.server nick G :0 Real Name"
|
||||
}
|
||||
|
||||
send "mode #channel -o nick\r"
|
||||
@@ -59,10 +71,16 @@ expect {
|
||||
"@* MODE #channel -o nick\r"
|
||||
}
|
||||
|
||||
send "who #channel\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
":ngircd.test.server 352 nick #channel * * ngircd.test.server nick G+ :0 Real Name"
|
||||
}
|
||||
|
||||
send "who ngircd.test.server\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
":ngircd.test.server 352 nick #channel * ngircd.test.server nick G+ :0 Real Name"
|
||||
":ngircd.test.server 352 nick \* * * ngircd.test.server nick G :0 Real Name"
|
||||
}
|
||||
|
||||
send "part #channel\r"
|
||||
@@ -74,7 +92,7 @@ expect {
|
||||
send "who Real?Name\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
":ngircd.test.server 352 nick \* * ngircd.test.server nick G :0 Real Name"
|
||||
":ngircd.test.server 352 nick \* * * ngircd.test.server nick G :0 Real Name"
|
||||
}
|
||||
|
||||
send "oper TestOp 123\r"
|
||||
@@ -90,7 +108,7 @@ expect {
|
||||
send "who 0 o\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
":ngircd.test.server 352 nick \* * ngircd.test.server nick G* :0 Real Name"
|
||||
":ngircd.test.server 352 nick \* * * ngircd.test.server nick G* :0 Real Name"
|
||||
}
|
||||
|
||||
send "away\r"
|
||||
@@ -102,7 +120,7 @@ expect {
|
||||
send "who ??cal*ho*\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
":ngircd.test.server 352 nick \* * ngircd.test.server nick H* :0 Real Name"
|
||||
":ngircd.test.server 352 nick \* * * ngircd.test.server nick H* :0 Real Name"
|
||||
}
|
||||
|
||||
send "join #opers\r"
|
||||
@@ -114,7 +132,13 @@ expect {
|
||||
send "who #opers\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
":ngircd.test.server 352 nick #opers * ngircd.test.server nick H*@ :0 Real Name"
|
||||
":ngircd.test.server 352 nick #opers * * ngircd.test.server nick H*@ :0 Real Name"
|
||||
}
|
||||
|
||||
send "who Re*me\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
":ngircd.test.server 352 nick \* * * ngircd.test.server nick H* :0 Real Name"
|
||||
}
|
||||
|
||||
send "mode #opers -o nick\r"
|
||||
@@ -123,10 +147,16 @@ expect {
|
||||
"@* MODE #opers -o nick\r"
|
||||
}
|
||||
|
||||
send "who #opers\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
":ngircd.test.server 352 nick #opers * * ngircd.test.server nick H* :0 Real Name"
|
||||
}
|
||||
|
||||
send "who *.server\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
":ngircd.test.server 352 nick #opers * ngircd.test.server nick H* :0 Real Name"
|
||||
":ngircd.test.server 352 nick \* * * ngircd.test.server nick H* :0 Real Name"
|
||||
}
|
||||
|
||||
send "mode #opers +v nick\r"
|
||||
@@ -135,10 +165,10 @@ expect {
|
||||
"@* MODE #opers +v nick\r"
|
||||
}
|
||||
|
||||
send "who Real*me\r"
|
||||
send "who #opers\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
":ngircd.test.server 352 nick #opers * ngircd.test.server nick H*+ :0 Real Name"
|
||||
":ngircd.test.server 352 nick #opers * * ngircd.test.server nick H*+ :0 Real Name"
|
||||
}
|
||||
|
||||
send "mode #opers +s\r"
|
||||
|
@@ -17,31 +17,31 @@ expect {
|
||||
send "whois nick\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
"311 nick nick ~user localhost \* :Real Name\r"
|
||||
"311 nick nick ~user localhost* \* :Real Name\r"
|
||||
}
|
||||
|
||||
send "whois *\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
"311 nick nick ~user localhost \* :Real Name\r"
|
||||
"311 nick nick ~user localhost* \* :Real Name\r"
|
||||
}
|
||||
|
||||
send "whois n*\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
"311 nick nick ~user localhost \* :Real Name\r"
|
||||
"311 nick nick ~user localhost* \* :Real Name\r"
|
||||
}
|
||||
|
||||
send "whois ?ick\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
"311 nick nick ~user localhost \* :Real Name\r"
|
||||
"311 nick nick ~user localhost* \* :Real Name\r"
|
||||
}
|
||||
|
||||
send "whois ????,n?*k\r"
|
||||
expect {
|
||||
timeout { exit 1 }
|
||||
"311 nick nick ~user localhost \* :Real Name\r"
|
||||
"311 nick nick ~user localhost* \* :Real Name\r"
|
||||
}
|
||||
|
||||
send "quit\r"
|
||||
|
Reference in New Issue
Block a user