1 |
<?xml version="1.0" encoding="ISO-8859-1"?> |
2 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11-strict.dtd"> |
3 |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"> |
4 |
<head> |
5 |
<meta http-equiv="Content-Style-Type" content="text/css"/> |
6 |
<style type="text/css">@import "style.css";</style> |
7 |
<title>IRC Services Technical Reference Manual - 5. IRC server interface</title> |
8 |
</head> |
9 |
|
10 |
<body> |
11 |
<h1 class="title" id="top">IRC Services Technical Reference Manual</h1> |
12 |
|
13 |
<h2 class="section-title">5. IRC server interface</h2> |
14 |
|
15 |
<p class="section-toc"> |
16 |
5-1. <a href="#s1">Protocol modules: the IRC protocol bridge</a> |
17 |
<br/>5-2. <a href="#s2">Specifying protocol features</a> |
18 |
<br/>5-3. <a href="#s3">Sending messages to the network</a> |
19 |
<br/> 5-3-1. <a href="#s3-1">Required functionality</a> |
20 |
<br/> 5-3-2. <a href="#s3-2">Optional functionality</a> |
21 |
<br/>5-4. <a href="#s4">Receiving messages from the network</a> |
22 |
<br/> 5-4-1. <a href="#s4-1">Required functionality</a> |
23 |
<br/> 5-4-2. <a href="#s4-2">Optional functionality</a> |
24 |
<br/>5-5. <a href="#s5">Other functions of protocol modules</a> |
25 |
<br/>5-6. <a href="#s6">Specific protocol module details</a> |
26 |
<br/> 5-6-1. <a href="#s6-1"><tt>protocol/rfc1459</tt></a> |
27 |
<br/> 5-6-2. <a href="#s6-2"><tt>protocol/ts8</tt></a> |
28 |
<br/> 5-6-3. <a href="#s6-3"><tt>protocol/dalnet</tt></a> |
29 |
<br/> 5-6-4. <a href="#s6-4"><tt>protocol/dreamforge</tt></a> |
30 |
<br/> 5-6-5. <a href="#s6-5"><tt>protocol/bahamut</tt></a> |
31 |
<br/> 5-6-6. <a href="#s6-6"><tt>protocol/hybrid</tt></a> |
32 |
<br/> 5-6-7. <a href="#s6-7"><tt>protocol/inspircd</tt></a> |
33 |
<br/> 5-6-8. <a href="#s6-8"><tt>protocol/monkey</tt></a> |
34 |
<br/> 5-6-9. <a href="#s6-9"><tt>protocol/ptlink</tt></a> |
35 |
<br/> 5-6-10. <a href="#s6-10"><tt>protocol/ratbox</tt></a> |
36 |
<br/> 5-6-11. <a href="#s6-11"><tt>protocol/solidircd</tt></a> |
37 |
<br/> 5-6-12. <a href="#s6-12"><tt>protocol/trircd</tt></a> |
38 |
<br/> 5-6-13. <a href="#s6-13"><tt>protocol/undernet-p9</tt></a> |
39 |
<br/> 5-6-14. <a href="#s6-14"><tt>protocol/unreal</tt></a> |
40 |
<br/> 5-6-14-1. <a href="#s6-14-1">Module prologue</a> |
41 |
<br/> 5-6-14-2. <a href="#s6-14-2">Message receiving</a> |
42 |
<br/> 5-6-14-3. <a href="#s6-14-3">Message sending</a> |
43 |
<br/> 5-6-14-4. <a href="#s6-14-4">Module initialization and cleanup</a> |
44 |
<br/>5-7. <a href="#s7">Auxiliary source file details</a> |
45 |
<br/> 5-7-1. <a href="#s7-1"><tt>banexcept.c</tt>, <tt>banexcept.h</tt></a> |
46 |
<br/> 5-7-2. <a href="#s7-2"><tt>chanprot.c</tt>, <tt>chanprot.h</tt></a> |
47 |
<br/> 5-7-3. <a href="#s7-3"><tt>halfop.c</tt>, <tt>halfop.h</tt></a> |
48 |
<br/> 5-7-4. <a href="#s7-4"><tt>invitemask.c</tt>, <tt>invitemask.h</tt></a> |
49 |
<br/> 5-7-5. <a href="#s7-5"><tt>sjoin.c</tt>, <tt>sjoin.h</tt></a> |
50 |
<br/> 5-7-6. <a href="#s7-6"><tt>svsnick.c</tt>, <tt>svsnick.h</tt></a> |
51 |
<br/> 5-7-7. <a href="#s7-7"><tt>token.c</tt>, <tt>token.h</tt></a> |
52 |
</p> |
53 |
|
54 |
<p class="backlink"><a href="4.html">Previous section: The module system</a> | |
55 |
<a href="index.html">Table of Contents</a> | |
56 |
<a href="6.html">Next section: Database handling</a></p> |
57 |
|
58 |
<!------------------------------------------------------------------------> |
59 |
<hr/> |
60 |
|
61 |
<h3 class="subsection-title" id="s1">5-1. Protocol modules: the IRC protocol bridge</h3> |
62 |
|
63 |
<p>While the "official" IRC protocol is defined in the document |
64 |
<a href="http://www.ietf.org/rfc/rfc1459.txt">RFC 1459</a> |
65 |
<span class="remotehost">[www.ietf.org]</span>, modern IRC servers have |
66 |
added many extensions to this base protocol over the years, and the current |
67 |
state of IRC software is such that it is rare to find an IRC server |
68 |
implementation that can communicate with a different implementation. This |
69 |
makes the job of Services considerably more difficult, as it must |
70 |
communicate with servers in order to perform its job, and there is no |
71 |
telling what implementation a particular network administrator will choose.</p> |
72 |
|
73 |
<p>In order to overcome these differences in protocol, Services makes use |
74 |
of <i>protocol modules</i>, a class of modules which interface between the |
75 |
generic IRC server implemented by the Services core and the specific |
76 |
protocols used by different IRC server implementations. While there are |
77 |
some basic assumptions made by the core code about the protocol—for |
78 |
example, that the protocol uses lines of text terminated by a CR/LF |
79 |
pair—most differences seen in current IRC servers can be handled by |
80 |
protocol modules.</p> |
81 |
|
82 |
<p>The standard protocol modules distributed in Services are located in the |
83 |
<tt>modules/protocol</tt> directory, along with auxiliary source and header |
84 |
files that implement functionality common to multiple protocols. This |
85 |
location is not a requirement, however; third-party modules can be located |
86 |
in different directories, provided that they implement the required |
87 |
functionality described in this section.</p> |
88 |
|
89 |
<p>Note that, in order to simplify the module initialization process, |
90 |
Services requires that a protocol module be loaded before any other |
91 |
modules; this requirement is enforced by the <tt>load_module()</tt> |
92 |
routine, as discussed in <a href="4.html#s3-1">section 4-3-1</a>. A number |
93 |
of pseudoclient modules alter their behavior depending on features of the |
94 |
IRC protocol in use, such as maximum nickname length or support of certain |
95 |
nonstandard IRC messages, and this requirement allows such modules to |
96 |
simply check the protocol information without having to ensure that a |
97 |
protocol module has been loaded (and subsequently watch for protocol module |
98 |
loads and unloads). <i>Implementation note: Although <tt>load_module()</tt> |
99 |
ensures that a protocol module is loaded first, <tt>unload_module()</tt> |
100 |
does <b>not</b> prevent protocol modules from being unloaded! Protocol |
101 |
modules should therefore use an <tt>exit_module()</tt> routine that returns |
102 |
zero on any unload attempt, except during shutdown. The modules included |
103 |
with Services all exhibit this behavior.</i></p> |
104 |
|
105 |
<p class="backlink"><a href="#top">Back to top</a></p> |
106 |
|
107 |
<!------------------------------------------------------------------------> |
108 |
<hr/> |
109 |
|
110 |
<h3 class="subsection-title" id="s2">5-2. Specifying protocol features</h3> |
111 |
|
112 |
<p>In addition to providing the functionality listed in subsequent |
113 |
sections, protocol modules must inform Services of certain information |
114 |
about the protocol in use. This is done by setting the following global |
115 |
variables (defined in <tt>send.c</tt>) in the module's <tt>module_init()</tt> |
116 |
routine:</p> |
117 |
|
118 |
<dl> |
119 |
<dt><tt>const char *protocol_name</tt></dt> |
120 |
<dd>Specifies the name of the protocol supported by the module. This |
121 |
variable is provided for informational purposes only. (The current |
122 |
core code does not make any use of the variable.)</dd> |
123 |
|
124 |
<dt><tt>const char *protocol_version</tt></dt> |
125 |
<dd>Specifies the version(s) of the protocol supported by the module, |
126 |
if applicable (the variable may be left unset if there is only one |
127 |
version of the protocol). This variable is provided for |
128 |
informational purposes only.</dd> |
129 |
|
130 |
<dt><tt>int32 protocol_features</tt></dt> |
131 |
<dd>Specifies particular features supported by the protocol. The value |
132 |
should be a combination (bitwise OR) of zero or more of the |
133 |
following flags: |
134 |
<ul> |
135 |
<li><b><tt>PF_HALFOP</tt>:</b> Supports a "half-op" channel |
136 |
user mode (such as <tt>+h</tt> as used with the Unreal |
137 |
protocol).</li> |
138 |
<li><b><tt>PF_CHANPROT</tt>:</b> Supports a "protected" channel |
139 |
user mode (such as <tt>+a</tt> as used with the Unreal |
140 |
protocol).</li> |
141 |
<li><b><tt>PF_BANEXCEPT</tt>:</b> Supports channel ban |
142 |
exceptions.</li> |
143 |
<li><b><tt>PF_SZLINE</tt>:</b> Supports an <tt>SZLINE</tt> or |
144 |
similar server-to-server command to ban an IP address from |
145 |
connecting to any server on the network.</li> |
146 |
<li><b><tt>PF_NOQUIT</tt>:</b> Uses "NOQUIT" mode, in which |
147 |
servers do not send <tt>QUIT</tt> messages for affected |
148 |
clients when a netsplit occurs (see, for example, |
149 |
<a href="#s6-5">section 5-6-5</a>).</li> |
150 |
<li><b><tt>PF_SVSJOIN</tt>:</b> Supports an <tt>SVSJOIN</tt> or |
151 |
similar server-to-server command to force a client to join a |
152 |
channel.</li> |
153 |
<li><b><tt>PF_CHANGENICK</tt>:</b> Supports a method through |
154 |
which a server can forcibly change a client's nickname.</li> |
155 |
<li><b><tt>PF_AKILL_EXCL</tt>:</b> Supports autokill exclusions |
156 |
(exceptions to network-wide bans as set by the OperServ |
157 |
<tt>AKILL</tt> command).</li> |
158 |
<li><b><tt>PF_MODETS_FIRST</tt>:</b> Sends the timestamp in a |
159 |
channel <tt>MODE</tt> message immediately after the channel |
160 |
name, rather than at the end of the message.</li> |
161 |
<li><b><tt>PF_INVITEMASK</tt>:</b> Supports channel invite |
162 |
masks (masks allowing users who match to join an |
163 |
invite-only channel without being invited, such as the |
164 |
<tt>+i</tt> channel mode as used with the Unreal |
165 |
protocol).</li> |
166 |
</ul> |
167 |
Note that <tt>protocol_features</tt> is initialized to a value of |
168 |
<tt>PF_UNSET</tt> to detect whether its value has been changed, so |
169 |
the protocol module should use a direct assignment (rather than an |
170 |
OR-assignment) to set the value.</dd> |
171 |
|
172 |
<dt><tt>int protocol_nickmax</tt></dt> |
173 |
<dd>Specifies the maximum number of characters (bytes) allowed in a |
174 |
nickname.</dd> |
175 |
</dl> |
176 |
|
177 |
<p><tt>send.c</tt> hooks into the "<tt>load module</tt>" callback to check |
178 |
that these variables, as well as the functions listed in |
179 |
<a href="#s3-1">section 5-3-1</a>, are appropriately set when a protocol |
180 |
module is loaded, generating a fatal error if not. <i>Implementation note: |
181 |
As mentioned in <a href="2.html#s5-1">section 2-5-1</a>, there is nothing |
182 |
to mark a protocol module as being such, so the callback function simply |
183 |
assumes that the first module loaded is a protocol module.</i></p> |
184 |
|
185 |
<p>There are also three variables which can be optionally set as needed:</p> |
186 |
|
187 |
<dl> |
188 |
<dt><tt>const char *pseudoclient_modes</tt></dt> |
189 |
<dd>Specifies the user modes, if any, that should be set on any newly |
190 |
introduced pseudoclient; a leading "<tt>+</tt>" should <i>not</i> |
191 |
be added. For example, if a protocol includes a user mode |
192 |
specifically for pseudoclients, that mode should be set here. |
193 |
Defaults to the empty string (no modes). Note that mode |
194 |
<tt>o</tt> (operator privilege) should <i>not</i> be specified even |
195 |
if some pseudoclients need operator privileges to perform their |
196 |
functions; use <tt>pseudoclient_oper</tt> for that instead (see |
197 |
below).</dd> |
198 |
|
199 |
<dt><tt>const char *enforcer_modes</tt></dt> |
200 |
<dd>Specifies the user modes, if any, that should be set on |
201 |
pseudoclients used as nickname enforcers. Defaults to the empty |
202 |
string (no modes).</dd> |
203 |
|
204 |
<dt><tt>int pseudoclient_oper</tt></dt> |
205 |
<dd>Indicates whether pseudoclients which perform actions restricted to |
206 |
IRC operators need the IRC operator user mode (<tt>+o</tt>) set. |
207 |
Defaults to 1, causing this mode to be set (0 disables |
208 |
<tt>+o</tt>).</dd> |
209 |
</dl> |
210 |
|
211 |
<p class="backlink"><a href="#top">Back to top</a></p> |
212 |
|
213 |
<!------------------------------------------------------------------------> |
214 |
<hr/> |
215 |
|
216 |
<h3 class="subsection-title" id="s3">5-3. Sending messages to the network</h3> |
217 |
|
218 |
<p>The bulk of a protocol module consists of routines to send messages to |
219 |
and process messages from the network, handling any peculiarites of the |
220 |
particular protocol in use.</p> |
221 |
|
222 |
<p class="backlink"><a href="#top">Back to top</a></p> |
223 |
|
224 |
|
225 |
<h4 class="subsubsection-title" id="s3-1">5-3-1. Required functionality</h4> |
226 |
|
227 |
<p>A number of the common message sending operations defined in |
228 |
<tt>send.c</tt> are defined as function pointers, which the protocol |
229 |
module must set to point to appropriate functions (by default, they point |
230 |
to a placeholder function which generates a fatal error). These function |
231 |
pointers (see <a href="2.html#s5-1">section 2-5-1</a> for descriptions of |
232 |
the functions) are:</p> |
233 |
|
234 |
<ul> |
235 |
<li><tt>void (*<b>send_nick</b>)(const char *<i>nick</i>, |
236 |
const char *<i>user</i>, const char *<i>host</i>, |
237 |
const char *<i>server</i>, const cahr *<i>name</i>, |
238 |
const char *<i>modes</i>)</tt></li> |
239 |
<li><tt>void (*<b>send_nickchange</b>)(const char *<i>nick</i>, const char *<i>newnick</i>)</tt></li> |
240 |
<li><tt>void (*<b>send_namechange</b>)(const char *<i>name</i>, const char *<i>newname</i>)</tt></li> |
241 |
<li><tt>void (*<b>send_server</b>)()</tt></li> |
242 |
<li><tt>void (*<b>send_server_remote</b>)(const char *<i>server</i>, const char *<i>desc</i>)</tt></li> |
243 |
<li><tt>void (*<b>wallops</b>)(const char *<i>source</i>, const char *<i>fmt</i>, ...)</tt></li> |
244 |
<li><tt>void (*<b>notice_all</b>)(const char *<i>source</i>, const char *<i>fmt</i>, ...)</tt></li> |
245 |
<li><tt>void (*<b>send_channel_cmd</b>)(const char *<i>source</i>, const char *<i>fmt</i>, ...)</tt></li> |
246 |
</ul> |
247 |
|
248 |
<p>Protocol modules must also provide a handler for the "<tt>set |
249 |
topic</tt>" callback. The callback function should have the following |
250 |
signature:</p> |
251 |
|
252 |
<div class="code">int set_topic_handler(const char *<i>source</i>, |
253 |
Channel *<i>c</i>, |
254 |
const char *<i>topic</i>, |
255 |
const char *<i>setter</i>, |
256 |
time_t <i>t</i>)</div> |
257 |
|
258 |
<p>This callback is called twice for each time the topic is set. The first |
259 |
call is made before the <tt>Channel</tt> structure is changed, and |
260 |
<tt><i>topic</i></tt>, <tt><i>setter</i></tt>, and <tt><i>t</i></tt> are |
261 |
filled in with the new topic text, the nickname to be used as the topic |
262 |
setter, and the timestamp for the topic. The second call is made after |
263 |
the <tt>topic</tt> and <tt>topic_setter</tt> fields of the <tt>Channel</tt> |
264 |
structure have been set to the new values, and the corresponding parameters |
265 |
to the callback (<tt><i>topic</i></tt> and <tt><i>setter</i></tt>) are |
266 |
<tt>NULL</tt> for this call. Note that the <tt>topic_time</tt> field is |
267 |
<i>not</i> set by the core, and must be set appropriately by the callback |
268 |
function; this is because some protocols require that the timestamp of a |
269 |
channel topic must be newer or older than the current topic's timestamp for |
270 |
the new topic to be accepted.</p> |
271 |
|
272 |
<p class="backlink"><a href="#top">Back to top</a></p> |
273 |
|
274 |
|
275 |
<h4 class="subsubsection-title" id="s3-2">5-3-2. Optional functionality</h4> |
276 |
|
277 |
<p>In addition to the functions listed above, the OperServ modules |
278 |
implementing the autokill and S-line functionality (see sections |
279 |
<a href="7.html#s2-2-2">7-2-2-2</a> and <a href="7.html#s2-2-3">7-2-2-3</a>) |
280 |
register message-sending callbacks which they expect the protocol module to |
281 |
hook into if it supports the relevant messages. These callbacks (see |
282 |
<a href="c.html#s3">Appendix C</a> for details) are:</p> |
283 |
|
284 |
<ul> |
285 |
<li><tt><b>send_akill</b></tt>: Sends an autokill to the network.</li> |
286 |
<li><tt><b>cancel_akill</b></tt>: Clears an autokill from the network.</li> |
287 |
<li><tt><b>send_exclude</b></tt>: Sends an autokill exclusion to the network.</li> |
288 |
<li><tt><b>cancel_exclude</b></tt>: Clears an autokill exclusion from the network.</li> |
289 |
<li><tt><b>send_sgline</b></tt>: Sends an SGline to the network.</li> |
290 |
<li><tt><b>cancel_sgline</b></tt>: Clears an SGline from the network.</li> |
291 |
<li><tt><b>send_sqline</b></tt>: Sends an SQline to the network.</li> |
292 |
<li><tt><b>cancel_sqline</b></tt>: Clears an SQline from the network.</li> |
293 |
<li><tt><b>send_szline</b></tt>: Sends an SZline to the network.</li> |
294 |
<li><tt><b>cancel_szline</b></tt>: Clears an SZline from the network.</li> |
295 |
</ul> |
296 |
|
297 |
<p>If any of the callbacks are left unsupported, Services will simply send |
298 |
a <tt>KILL</tt> or other appropriate message each time the autokill or |
299 |
S-line is triggered. (However, hooking into a "send" callback but not the |
300 |
corresponding "cancel" callback can have undesirable consequences!)</p> |
301 |
|
302 |
<p class="backlink"><a href="#top">Back to top</a></p> |
303 |
|
304 |
<!------------------------------------------------------------------------> |
305 |
<hr/> |
306 |
|
307 |
<h3 class="subsection-title" id="s4">5-4. Receiving messages from the network</h3> |
308 |
|
309 |
<p>While basic message parsing and processing is handled by the Services |
310 |
core, it is up to protocol modules to handle details of the particular |
311 |
protocol as well as additional messages used by the protocol.</p> |
312 |
|
313 |
<p>In Services, processing of received messages is handled using tables of |
314 |
message names and corresponding processing routines, as described in |
315 |
<a href="2.html#s5-3">section 2-5-3</a>. Protocol modules will typically |
316 |
define a message table for messages handled by the module, and call |
317 |
<tt>register_messages()</tt> to register the message table during module |
318 |
initialization.</p> |
319 |
|
320 |
<p class="backlink"><a href="#top">Back to top</a></p> |
321 |
|
322 |
|
323 |
<h4 class="subsubsection-title" id="s4-1">5-4-1. Required functionality</h4> |
324 |
|
325 |
<p>The only functionality required in protocol modules is the ability to |
326 |
recognize new clients connecting to the network and clients changing |
327 |
nicknames. As described in <a href="2.html#s5-3">section 2-5-3</a>, the |
328 |
<tt>NICK</tt> and <tt>USER</tt> messages are not supported by the Services |
329 |
core because of the differences between protocols in handling them; thus, |
330 |
the protocol module must supply its own handler routines for these |
331 |
messages, or whatever other messages may be used in their place.</p> |
332 |
|
333 |
<p>However, in many protocols there are other messages which must be |
334 |
handled properly to maintain the network state. These, of course, must be |
335 |
processed accordingly as well.</p> |
336 |
|
337 |
<p class="backlink"><a href="#top">Back to top</a></p> |
338 |
|
339 |
|
340 |
<h4 class="subsubsection-title" id="s4-2">5-4-2. Optional functionality</h4> |
341 |
|
342 |
<p>As described above, modules can add support for additional messages |
343 |
through a message table; the default processing for core-handled messages |
344 |
can be changed the same way, if (for example) a message takes a different |
345 |
set of parameters than the "standard" server assumed by the core code.</p> |
346 |
|
347 |
<p>There are some types of functionality shared among several servers, such |
348 |
as the <tt>SJOIN</tt> message used in protocols such as Bahamut and Unreal |
349 |
to update a channel's state with one message, or the "token" systems used |
350 |
by some protocols to reduce the bandwidth and processing required for |
351 |
inter-server messages. These are implemented by separate source files, |
352 |
which can be included in the module's source to implement the particular |
353 |
functionality. These are described in <a href="#s7">section 5-7</a>.</p> |
354 |
|
355 |
<p class="backlink"><a href="#top">Back to top</a></p> |
356 |
|
357 |
<!------------------------------------------------------------------------> |
358 |
<hr/> |
359 |
|
360 |
<h3 class="subsection-title" id="s5">5-5. Other functions of protocol modules</h3> |
361 |
|
362 |
<p>Aside from handling the sending and receiving of messages particular to |
363 |
the protocol, protocol modules must handle any other aspect of |
364 |
server-to-server communication that is not done in the core. Chief among |
365 |
these is the handling of protocol-specific modes.</p> |
366 |
|
367 |
<p>Many IRC server implementations add new modes to the basic set; the |
368 |
module must be able to recognize and process these modes appropriately. |
369 |
This can be done using the core mode-handling facility (see |
370 |
<a href="2.html#s6-4">section 2-6-4</a>), or by hooking into the |
371 |
<tt>MODE</tt> message callbacks "<tt>user MODE</tt>" and |
372 |
"<tt>channel MODE</tt>" (in the case of modes that take parameters, it is |
373 |
usually necessary to use the latter method in order to store the parameter |
374 |
values in the channel structure). The module may also need to hook into |
375 |
various pseudoclient callbacks; see the relevant parts of |
376 |
<a href="7.html">section 7</a>, or see the description of the Unreal |
377 |
protocol module, which uses most of these callbacks, in |
378 |
<a href="#s6-14">section 5-6-14</a> below.</p> |
379 |
|
380 |
<p class="backlink"><a href="#top">Back to top</a></p> |
381 |
|
382 |
<!------------------------------------------------------------------------> |
383 |
<hr/> |
384 |
|
385 |
<h3 class="subsection-title" id="s6">5-6. Specific protocol module details</h3> |
386 |
<p>This section describes each of the protocol modules supplied with |
387 |
Services. In addition to the source file for the module itself, some |
388 |
protocol modules make use of auxiliary source files in the same directory; |
389 |
these files are described in detail in <a href="#s7">section 5-7</a>. For |
390 |
the most part, each subsection only covers details unique to that |
391 |
particular module, but the <tt>protocol/unreal</tt> module |
392 |
(<a href="#s6-14">section 5-6-14</a>), which makes use of almost all |
393 |
protocol-related functionality, is discussed in more detail.</p> |
394 |
|
395 |
<p class="backlink"><a href="#top">Back to top</a></p> |
396 |
|
397 |
|
398 |
<h4 class="subsubsection-title" id="s6-1">5-6-1. <tt>protocol/rfc1459</tt></h4> |
399 |
|
400 |
<p>The <tt>protocol/rfc1459</tt> module provides an interface for servers |
401 |
which strictly follow the standard IRC protocol, as defined in RFC 1459. |
402 |
While few if any such servers still remain in operation, this module serves |
403 |
as a reference implementation for Services.</p> |
404 |
|
405 |
<p>Since the generic IRC server implemented by Services is very similar to |
406 |
the RFC 1459 standard, this module is rather straightforward. In a format |
407 |
shared by the other standard protocol modules as well, the module is |
408 |
divided into four major parts: routines to process received IRC messages, |
409 |
routines to send IRC messages, callback functions, and module-related |
410 |
functions and variables.</p> |
411 |
|
412 |
<p>The only received messages which need special processing are the |
413 |
<tt>NICK</tt> and <tt>USER</tt> messages used for introducing clients. |
414 |
The module ignores the <tt>NICK</tt> message, assuming that the remote |
415 |
server will take care of checking for collisions with the nicknames of any |
416 |
pseudoclients introduced by Services, and uses the parameters to the |
417 |
<tt>USER</tt> message to initialize the client's data record. Before |
418 |
calling <tt>do_nick()</tt> to perform this action, the handler for the |
419 |
<tt>USER</tt> message, <tt>m_user()</tt>, sets up a new parameter list |
420 |
with the parameters in the order <tt>do_nick()</tt> expects them, filling |
421 |
in default values for parameters unavailable in the RFC 1459 protocol. |
422 |
(Technically, the hop count parameter is available from the <tt>NICK</tt> |
423 |
message, but since it would take considerable extra effort to save this |
424 |
value until the <tt>USER</tt> message arrived, and since the hop count is |
425 |
not used by Services anyway, this field is simply discarded and a default |
426 |
value of 0 used.)</p> |
427 |
|
428 |
<p>The message-sending routines are likewise simple, for the most part. |
429 |
The only routine that deserves special mention is the |
430 |
<tt>do_notice_all()</tt> routine, which implements the <tt>notice_all()</tt> |
431 |
function of <tt>send.c</tt>. Since the RFC 1459 protocol does not permit a |
432 |
wildcard target of a <tt>NOTICE</tt> (or <tt>PRIVMSG</tt>) to be a simple |
433 |
"<tt>*</tt>", which would target all clients on the network, the module |
434 |
uses the <tt>NetworkDomain</tt> configuration setting, if available, to |
435 |
create a more-specific server wildcard mask which will still target all |
436 |
clients on the network. If this setting is not available, the routine |
437 |
iterates through some common top-level domains (<tt>.com</tt>, |
438 |
<tt>.net</tt>, <tt>.org</tt>, and <tt>.edu</tt>) in an attempt to reach as |
439 |
many clients as possible.</p> |
440 |
|
441 |
<p>There is only one callback function defined by the module; it hooks into |
442 |
the "<tt>set topic</tt>" callback, used for setting channel topics |
443 |
(see <a href="2.html#s6-5">section 2-6-5</a>). Since RFC 1459 places no |
444 |
restrictions on topic-changing messages from servers, the callback simply |
445 |
sends out a <tt>TOPIC</tt> message on the first call, ignoring the second.</p> |
446 |
|
447 |
<p>The module initialization routine sets the protocol-specific variables |
448 |
(<tt>protocol_name</tt>, <tt>protocol_version</tt>, and so on—since |
449 |
there are no "versions" associated with RFC 1459, the version string is |
450 |
left empty), installs the handlers for the <tt>NICK</tt> and <tt>USER</tt> |
451 |
messages, adds the topic-setting routine to the "<tt>set topic</tt>" |
452 |
callback, and installs the function pointers for the various message |
453 |
sending operations. Of these, the module cleanup routine removes the |
454 |
callback function and message handlers, but it leaves the protocol |
455 |
variables and message sending function pointers alone; this is a shortcut |
456 |
based on the assumption that the module will never be unloaded at runtime |
457 |
(this assumption is enforced by returning zero to refuse unloading if the |
458 |
<tt><i>shutdown</i></tt> parameter to the cleanup function is false).</p> |
459 |
|
460 |
<p class="backlink"><a href="#top">Back to top</a></p> |
461 |
|
462 |
|
463 |
<h4 class="subsubsection-title" id="s6-2">5-6-2. <tt>protocol/ts8</tt></h4> |
464 |
|
465 |
<p>TS8 was one of the earliest additions made to the IRC protocol, and |
466 |
includes timestamp (often called TS) values with many messages to indicate |
467 |
the time at which certain actions took place. The addition of timestamps |
468 |
allowed, among other things, less disruption of the network during |
469 |
netjoins; in the case of a nickname collision, for example, timestamps made |
470 |
it possible to determine which user was the first claimant on a nickname |
471 |
and kill only the second user, rather than killing both of them as the |
472 |
original protocol called for.</p> |
473 |
|
474 |
<p>Other than the addition of timestamps into some IRC messages, the |
475 |
<tt>protocol/ts8</tt> module, which supports TS8 as used in the |
476 |
<tt>ircd-2.8</tt> series of IRC servers (specifically tested with |
477 |
<tt>ircd-2.8.21+TS8</tt>), is very similar to the <tt>protocol/rfc1459</tt> |
478 |
module. The one difference worth noting is in the operation of the |
479 |
"<tt>set topic</tt>" callback. Under TS8, a server receiving a |
480 |
<tt>TOPIC</tt> message from another server will give preference to the |
481 |
topic with the older timestamp, ignoring the <tt>TOPIC</tt> message if it |
482 |
specifies a timestamp newer than that of the topic currently set on the |
483 |
channel; thus, in order to ensure that the topic gets set correctly, the |
484 |
callback function modifies the caller's topic timestamp to be one second |
485 |
earlier than the timestamp of the channel's current topic if a topic is |
486 |
set. This same approach is used in other protocol modules as well to |
487 |
ensure that changes made by Services are given priority over the current |
488 |
network state regardless of timestamps.</p> |
489 |
|
490 |
<p class="backlink"><a href="#top">Back to top</a></p> |
491 |
|
492 |
|
493 |
<h4 class="subsubsection-title" id="s6-3">5-6-3. <tt>protocol/dalnet</tt></h4> |
494 |
|
495 |
<p>The <tt>protocol/dalnet</tt> module supports the IRC server released by |
496 |
(and used on) the DALnet IRC network, <tt>ircd.dal</tt>, through version |
497 |
4.4.13. This server is, incidentally, the server for which Services was |
498 |
originally designed, and as such, the module is nearly as concise as those |
499 |
for the simpler RFC 1459 and TS8 protocols.</p> |
500 |
|
501 |
<p>The DALnet IRC server introduced several additions to the standard IRC |
502 |
protocol. Most notable, from the point of view of the protocol module, is |
503 |
the addition of the <tt>AKILL</tt> and <tt>RAKILL</tt> messages for adding |
504 |
and removing network-wide client bans, and the OperServ <tt>AKILL</tt> |
505 |
command derives its name from these messages. The module includes callback |
506 |
functions for OperServ's "<tt>send_akill</tt>" and "<tt>cancel_akill</tt>" |
507 |
callbacks; it also includes entries in the message table for these |
508 |
messages, but since there is no need to process <tt>AKILL</tt> messages |
509 |
from the network, the handlers for these are <tt>NULL</tt>, along with |
510 |
several other messages not recognized by the core message processing code. |
511 |
(These messages are included simply to avoid warnings in the log file when |
512 |
such messages are received.)</p> |
513 |
|
514 |
<p>Other changes made to the server-to-server protocol in the DALnet server |
515 |
are the unification of the <tt>NICK</tt> and <tt>USER</tt> messages into a |
516 |
single <tt>NICK</tt> message, and the addition of the <tt>GLOBOPS</tt> |
517 |
message, a <tt>WALLOPS</tt>-like message that cannot be seen by |
518 |
non-operators (and which is used for the implementation of the |
519 |
<tt>wallops()</tt> routine in preference to <tt>WALLOPS</tt>).</p> |
520 |
|
521 |
<p>In order to ensure that the <tt>AKILL</tt>-related callbacks mentioned |
522 |
above are added when the appropriate OperServ module |
523 |
(<tt>operserv/akill</tt>) is loaded, this module also hooks into the |
524 |
<tt>"load module"</tt> callback. An "<tt>unload module</tt>" |
525 |
callback is also included for completeness, though it does nothing in this |
526 |
module.</p> |
527 |
|
528 |
<p>A close look at the module initialization routine, |
529 |
<tt>module_init()</tt>, will show another difference in the DALnet |
530 |
protocol. The RFC 1459 standard specifies that the three characters |
531 |
<tt>[ \ ]</tt> are to be interepreted as equivalent to |
532 |
<tt>{ | }</tt> in nicknames and channel names; this is a holdover |
533 |
from the Scandinavian character set which was used by the creators of the |
534 |
IRC protocol. DALnet does away with this holdover, and treats |
535 |
<tt>[ \ ]</tt> as distinct from <tt>{ | }</tt> when |
536 |
doing such string comparisons. By default, however, Services uses the RFC |
537 |
1459 rules for comparing nicknames and channel names, so in order to change |
538 |
this behavior, the <tt>module_init()</tt> routine modifies the global |
539 |
<tt>irc_lowertable[]</tt> array. There are also two changes made to the |
540 |
<tt>valid_chan_table[]</tt> array, to accommodate the fact that the DALnet |
541 |
protocol allows channel names to begin with "<tt>+</tt>" and does not allow |
542 |
colons in channel names.</p> |
543 |
|
544 |
<p>There is also a <tt>mapstring()</tt> call in the initialization routine |
545 |
to change the <tt>OPER_BOUNCY_MODES</tt> message to |
546 |
<tt>OPER_BOUNCY_MODES_U_LINE</tt>; this latter message includes a specific |
547 |
reference to "U: lines", a type of entry in the DALnet server configuration |
548 |
file that indicates servers (like Services) that are allowed to change |
549 |
channel modes arbitrarily. Failure to set this correctly on all servers |
550 |
can result in the "bouncy modes" phenomenon, where a server reverses mode |
551 |
changes made by Services, causing Services to resubmit those changes in an |
552 |
infinite loop (see <a href="2.html#s6-3">section 2-6-3</a> for details).</p> |
553 |
|
554 |
<p>One other piece of code not present in the <tt>rfc1459</tt> or |
555 |
<tt>ts8</tt> modules is the mode initialization code. The DALnet protocol |
556 |
adds two user modes to the standard mode set: <tt>+g</tt>, indicating |
557 |
whether the client wants to receive <tt>GLOBOPS</tt> messages, and |
558 |
<tt>+h</tt>, indicating whether the user is identified as a "help-op". |
559 |
Neither of these have any effect on the operation of Services, but for |
560 |
completeness, they are added to the global mode tables as described in |
561 |
<a href="2.html#s6-4">section 2-6-4</a>. The method used for adding the |
562 |
modes (the three arrays <tt>new_usermodes[]</tt>, <tt>new_chanmodes[]</tt>, |
563 |
and <tt>new_chanusermodes[]</tt>, and the local initialization function |
564 |
<tt>init_modes()</tt>, called from <tt>init_module()</tt>) is shared by |
565 |
other protocol modules are well.</p> |
566 |
|
567 |
<p class="backlink"><a href="#top">Back to top</a></p> |
568 |
|
569 |
|
570 |
<h4 class="subsubsection-title" id="s6-4">5-6-4. <tt>protocol/dreamforge</tt></h4> |
571 |
|
572 |
<p>The <tt>protocol/dreamforge</tt> module supports the Dreamforge server |
573 |
protocol. Dreamforge is the name given to versions 4.4.15 and later of the |
574 |
DALnet IRC server, and as such, this protocol is a direct successor to the |
575 |
<tt>dalnet</tt> protocol.</p> |
576 |
|
577 |
<p>The major difference between the classic DALnet protocol and the |
578 |
Dreamforge protocol is the addition of features designed to improve the |
579 |
integration of Services-like programs with the network. Chief among these |
580 |
is the "Services timestamp" or "servicestamp", a timestamp-like value |
581 |
associated with each client which is set by Services and retained by all |
582 |
servers as long as the client is connected. This value, or 0 if it has not |
583 |
been set, is sent as part of the <tt>NICK</tt> message when announcing a |
584 |
new client to the network. Services can set the servicestamp to a unique |
585 |
value, and use that value to distinguish clients with certainty, avoiding |
586 |
problems arising from servers with out-of-sync clocks or clients that |
587 |
connect to the network at the same time. There are also new user and |
588 |
channel modes added to identify registered nicknames and channels, and to |
589 |
prevent clients with unregistered nicknames from joining a channel.</p> |
590 |
|
591 |
<p>Most of these changes are handled in the <tt>NICK</tt> message handler, |
592 |
<tt>m_nick()</tt>, and the callback functions |
593 |
<tt>do_user_servicestamp_change()</tt>, <tt>do_user_mode()</tt>, and |
594 |
<tt>do_nick_identified()</tt>. The <tt>do_user_mode()</tt> callback |
595 |
function ensures that no other server on the network attempts to change a |
596 |
user's servicestamp (note that this can cause mode floods if two copies of |
597 |
Services are run on the same network!) or registered-nickname status. The |
598 |
function also sets the "Services administrator" (<tt>+a</tt>) user mode if |
599 |
the user is known to be a Services administrator, and clears the mode |
600 |
otherwise.</p> |
601 |
|
602 |
<p>In order to check whether a user is a Services administrator, the module |
603 |
has to call the <tt>is_services_admin()</tt> function in the |
604 |
<tt>operserv/main</tt> module; however, this module may not be loaded. To |
605 |
avoid having to check for the module and symbol at every location in the |
606 |
code where the function is called, a local helper function, |
607 |
<tt>local_is_services_admin()</tt>, is defined at the top of the source |
608 |
file, and <tt>is_services_admin()</tt> is redefined (via <tt>#define</tt>) |
609 |
to point to this local function. The function itself only checks a cache |
610 |
variable to determine whether <tt>is_services_admin()</tt> is available; |
611 |
this cache variable is set by the "<tt>load module</tt>" callback |
612 |
function when the <tt>operserv/main</tt> module is loaded (and cleared |
613 |
again by the "<tt>unload module</tt>" if <tt>operserv/main</tt> is |
614 |
unloaded).</p> |
615 |
|
616 |
<p>The final new aspect to this module's source code is the use of the |
617 |
<tt>svsnick.c</tt> auxiliary source file (see <a href="#s7-6">section |
618 |
5-7-6</a> for details on this particular file), to support the |
619 |
<tt>SVSNICK</tt> message used to forcibly change a client's nickname. In |
620 |
order to avoid complexities resulting from compiling the source file |
621 |
separately and linking it into the module (in particular, identifier |
622 |
collisions during static linking), the <tt>svsnick.c</tt> source file is |
623 |
included directly into the module's main source file, <tt>dreamforge.c</tt>. |
624 |
<tt>svsnick.c</tt> includes its own initialization and cleanup routines, |
625 |
<tt>init_svsnick()</tt> and <tt>exit_svsnick()</tt>, which are called by |
626 |
<tt>init_module()</tt> and <tt>exit_module()</tt> respectively.</p> |
627 |
|
628 |
<p>With respect to server registration, Dreamforge includes a new |
629 |
<tt>PROTOCTL</tt> message type, used to inform the remote server about the |
630 |
sending server's capabilities; this allows changes and additions to be made |
631 |
to the protocol that can be enabled or disabled depending on whether the |
632 |
remote server supports them. Services does not make use of any such |
633 |
optional features in Dreamforge, however, so the <tt>PROTOCOL</tt> message |
634 |
is given a <tt>NULL</tt> handler.</p> |
635 |
|
636 |
<p class="backlink"><a href="#top">Back to top</a></p> |
637 |
|
638 |
|
639 |
<h4 class="subsubsection-title" id="s6-5">5-6-5. <tt>protocol/bahamut</tt></h4> |
640 |
|
641 |
<p>Bahamut is the successor to the Dreamforge IRC server, and is the server |
642 |
currently (2006/8) used on the DALnet IRC network. The |
643 |
<tt>protocol/bahamut</tt> module handles versions of Bahamut from 1.8.0 |
644 |
onward.</p> |
645 |
|
646 |
<p>In addition to the <tt>SVSNICK</tt> feature introduced in Dreamforge, |
647 |
Bahamut includes <i>ban exceptions</i> for channels (clients matching a ban |
648 |
exception mask can join the channel even if they also match a ban mask), |
649 |
supported by the auxiliary source file <tt>banexcept.c</tt>; <i>invite |
650 |
masks</i> for channels (clients matching an invite mask can join an |
651 |
invite-only channel without having to be explicitly invited), supported by |
652 |
<tt>invitemask.c</tt>; and a channel-join message for server-to-server |
653 |
communications, <tt>SJOIN</tt> (which reduces bandwidth use by allowing |
654 |
multiple users and channel modes to be sent in a single message), supported |
655 |
by <tt>sjoin.c</tt>. With respect to the latter file, <tt>bahamut.c</tt> |
656 |
defines the <tt>BAHAMUT_HACK</tt> symbol before including the file; this is |
657 |
to select the Bahamut mode of operation for <tt>SJOIN</tt>, as described in |
658 |
<a href="#s7-5">section 5-7-5</a>.</p> |
659 |
|
660 |
<p>Bahamut includes a <tt>CAPAB</tt> message that functions like |
661 |
Dreamforge's <tt>PROTOCTL</tt> to inform the remote server about supported |
662 |
protocol features. Services checks for one token in the <tt>CAPAB</tt> |
663 |
message: "<tt>NOQUIT</tt>", an extension suppressing (on server-to-server |
664 |
links) the client <tt>QUIT</tt> messages generated when a netsplit occurs. |
665 |
Services always advertises the <tt>NOQUIT</tt> capability, and sets the |
666 |
<tt>PF_NOQUIT</tt> protocol flag if the remote server also supports |
667 |
<tt>NOQUIT</tt>.</p> |
668 |
|
669 |
<p>One difficulty that can arise when using the Bahamut server is that the |
670 |
server to which Services connects is configured as a "Services hub" (the |
671 |
configuration option "<tt>servtype serviceshub</tt>"). While this |
672 |
seems logical from the name, this option is intended only for the custom |
673 |
Services program that DALnet uses, and is not compatible with this program, |
674 |
Services for IRC Networks. The DALnet Services program is customized to |
675 |
work specifically with the Bahamut server and the DALnet network, and as |
676 |
such takes certain shortcuts; the "Services hub" option causes the Bahamut |
677 |
server to take advantage of these shortcuts, reducing network bandwidth. |
678 |
In particular, activating this option causes messages to pseudoclients such |
679 |
as NickServ to be sent in an abbreviated form (the <tt>NS</tt>, <tt>CS</tt> |
680 |
and similar commands defined under the dummy |
681 |
<tt>#ifdef ALLOW_BAHAMUT_SERVICESHUB</tt>, referring to a macro not |
682 |
defined anywhere). As Services for IRC Networks cannot assume that these |
683 |
clients have particular nicknames, or even that they exist, the |
684 |
<tt>protocol/bahamut</tt> module reports an error and aborts the program if |
685 |
any of these abbreviated messages are seen. <i>Implementation note: It |
686 |
might be feasible to support these if the module exported a |
687 |
<tt>register_pseudoclient()</tt> routine, which took a constant indicating |
688 |
the pseudoclient, like <tt>BAHAMUT_NS</tt>, and the pseudoclient's nickname |
689 |
and stored the nickname locally for processing the given message.</i> The |
690 |
"Services hub" option also prevents channel topics and client <tt>AWAY</tt> |
691 |
messages from reaching Services, causing channel topic retention and |
692 |
MemoServ unaway checking to break.</p> |
693 |
|
694 |
<p>The Bahamut-specific channel mode <tt>+j</tt> is used to limit the rate |
695 |
at which clients can join a channel. It takes the form |
696 |
<tt>+j <i>num1</i>:<i>num2</i></tt>, where <tt><i>num1</i></tt> and |
697 |
<tt><i>num2</i></tt> are positive integers that set the exact limits on |
698 |
joining. Internally, these are stored in the <tt><i>joinrate1</i></tt> and |
699 |
<tt><i>joinrate2</i></tt> fields of the <tt>Channel</tt> structure as well |
700 |
as the locked-mode set of a registered channel (see |
701 |
<a href="7.html#s4-1-1">section 7-4-1-1</a>), and values of 0 in these |
702 |
fields indicate that the mode is not set; values of -1 in the locked-mode |
703 |
structure indicate that the mode is locked off.</p> |
704 |
|
705 |
<p>Unlike RFC 1459, Bahamut does not allow control characters in a channel |
706 |
name. It also does not allow ASCII 160 (0xA0), presumably because this |
707 |
corresponds to an "unbreakable space" in the ISO 8859-1 character set and |
708 |
could be confused with an ordinary space by users. The initialization |
709 |
routine adjusts the <tt>valid_chan_table[]</tt> array to account for this.</p> |
710 |
|
711 |
<p class="backlink"><a href="#top">Back to top</a></p> |
712 |
|
713 |
|
714 |
<h4 class="subsubsection-title" id="s6-6">5-6-6. <tt>protocol/hybrid</tt></h4> |
715 |
|
716 |
<p>The <tt>protocol/hybrid</tt> module supports versions 7.0 and later of |
717 |
the ircd-hybrid IRC server. Hybrid has a fairly simple design compared to |
718 |
other servers, and only supports a few features above the standard set.</p> |
719 |
|
720 |
<p>The Hybrid server does not ordinarily send channel topics during the |
721 |
initial net burst when a server connects, and only allows the channel topic |
722 |
to be set by a <tt>TOPIC</tt> message from a client currently in the |
723 |
channel. This prevents the ChanServ topic-related functions from working, |
724 |
since ChanServ does not join the channel when setting a topic. There is, |
725 |
however, a module available for Hybrid which restores the synchronization |
726 |
of channel topics on a server link as well as the ability of a server to |
727 |
set topics arbitrarily: the "topic burst" module, <tt>m_tburst.so</tt>. To |
728 |
simplify processing, the <tt>protocol/hybrid</tt> module requires that its |
729 |
uplink server support this topic bursting, and will abort the program if |
730 |
that support is missing (as determined by the <tt>CAPAB</tt> message |
731 |
received on connection).</p> |
732 |
|
733 |
<p class="backlink"><a href="#top">Back to top</a></p> |
734 |
|
735 |
|
736 |
<h4 class="subsubsection-title" id="s6-7">5-6-7. <tt>protocol/inspircd</tt></h4> |
737 |
|
738 |
<p>The <tt>protocol/inspircd</tt> supports the InspIRCd IRC server. This |
739 |
server shares a number of features with the Unreal server (see |
740 |
<a href="#s6-14">section 5-6-14</a>, but was created from scratch, rather |
741 |
than by modifying the source code of an existing IRC server as in the case |
742 |
of most other servers.</p> |
743 |
|
744 |
<p>The <tt>inspircd</tt> module uses the <tt>banexcept.c</tt>, |
745 |
<tt>invitemask.c</tt>, and <tt>svsnick.c</tt> auxiliary source files |
746 |
mentioned above, as well as the <tt>chanprot.c</tt> and <tt>halfop.c</tt> |
747 |
files, which are used to implement two additional channel user modes |
748 |
supported by InspIRCd: <tt>+a</tt> (protection) and <tt>+h</tt> (half-op). |
749 |
A user with <tt>+a</tt> set cannot be kicked by a channel operator unless |
750 |
that operator also has <tt>+a</tt> set. Half-op privilege is an extra |
751 |
privilege level between <tt>+v</tt> (voiced) and <tt>+o</tt> (channel |
752 |
operator); half-ops can set the channel topic and give <tt>+v</tt> to other |
753 |
users, but cannot change channel modes or perform other actions that |
754 |
ordinary channel operators can do. InspIRCd also has a condensed channel |
755 |
join message (<tt>FJOIN</tt>) similar to Bahamut's <tt>SJOIN</tt>, but its |
756 |
syntax is different enough that a message handler is included in the module |
757 |
itself rather than using the handler in <tt>sjoin.c</tt>.</p> |
758 |
|
759 |
<p>In addition to autokills and S-lines, InspIRCd supports autokill |
760 |
exclusions, similar to channels' ban exceptions but applying to |
761 |
network-wide autokill masks. As described in detail in |
762 |
<a href="7.html#s2-2-2">section 7-2-2-2</a>, the <tt>operserv/akill</tt> |
763 |
module can take advantage of this to implement autokill exclusions without |
764 |
having to send <tt>KILL</tt> messages for all autokilled users manually.</p> |
765 |
|
766 |
<p>Another feature of the InspIRCd protocol is the removal of the |
767 |
restriction on sending network-wide messages; as such, the |
768 |
<tt>protocol/inspircd</tt> module does not require a <tt>NetworkDomain</tt> |
769 |
configuration setting for global messages to be correctly sent.</p> |
770 |
|
771 |
<p class="backlink"><a href="#top">Back to top</a></p> |
772 |
|
773 |
|
774 |
<h4 class="subsubsection-title" id="s6-8">5-6-8. <tt>protocol/monkey</tt></h4> |
775 |
|
776 |
<p>The <tt>protocol/monkey</tt> module supports the Chunky Monkey IRCD |
777 |
server. This server is based on an earlier version of Bahamut; the primary |
778 |
Services-visible change is the addition of the half-op (<tt>+h</tt>) |
779 |
channel user mode. Features like ban exceptions and invite masks, added to |
780 |
Bahamut in later versions, are not present. Other than these differences, |
781 |
this module is essentially the same as the <tt>bahamut</tt> module.</p> |
782 |
|
783 |
<p class="backlink"><a href="#top">Back to top</a></p> |
784 |
|
785 |
|
786 |
<h4 class="subsubsection-title" id="s6-9">5-6-9. <tt>protocol/ptlink</tt></h4> |
787 |
|
788 |
<p>The <tt>protocol/ptlink</tt> module supports the PTlink IRCd server, |
789 |
version 6.10.0 and later. This server is based on ircd-hybrid-6, and was |
790 |
originally developed for the PTlink IRC network, from which it takes its |
791 |
name.</p> |
792 |
|
793 |
<p>In PTlink, autokills are set and removed using the <tt>GLINE</tt> |
794 |
message. Since this can also be used by IRC operators to set and remove |
795 |
autokills, Services uses a constant string (defined as <tt>GLINE_WHO</tt> |
796 |
at the top of the source file) as the "nickname" associated with the entry. |
797 |
Services can then check this value when receiving a <tt>GLINE</tt> message |
798 |
from the network, in order to avoid removing entries set by IRC operators. |
799 |
(However, nicknames are not stored with <tt>SGLINE</tt> and <tt>SQLINE</tt> |
800 |
entries, so operator-set entries will be deleted if they do not match a |
801 |
record in Services' databases.) See under the <tt>TKL</tt> message |
802 |
handler in <a href="#s6-14">section 5-6-14</a>, which discusses the Unreal |
803 |
server, for an explanation of why these entries need to be cleared when |
804 |
received from the network.</p> |
805 |
|
806 |
<p class="backlink"><a href="#top">Back to top</a></p> |
807 |
|
808 |
|
809 |
<h4 class="subsubsection-title" id="s6-10">5-6-10. <tt>protocol/ratbox</tt></h4> |
810 |
|
811 |
<p>The <tt>protocol/ratbox</tt> module supports the ircd-ratbox server. |
812 |
This server is derived from ircd-hybrid, and the <tt>ratbox</tt> module is |
813 |
likewise very similar to the <tt>hybrid</tt> module.</p> |
814 |
|
815 |
<p>Like Hybrid, ircd-ratbox does not normally allow servers like Services |
816 |
to arbitrarily change channel topics, but this behavior can be changed with |
817 |
a similar "topic burst" function. In the case of ircd-ratbox, this |
818 |
functionality is built into the server (rather than being a separate |
819 |
module), and need only be enabled through the appropriate flag |
820 |
("<tt>topicburst</tt>" in the connect block for Services). If this flag is |
821 |
not enabled, Services will abort at connection time, as for Hybrid.</p> |
822 |
|
823 |
<p class="backlink"><a href="#top">Back to top</a></p> |
824 |
|
825 |
|
826 |
<h4 class="subsubsection-title" id="s6-11">5-6-11. <tt>protocol/solidircd</tt></h4> |
827 |
|
828 |
<p>The <tt>protocol/solidircd</tt> module supports the solid-ircd server. |
829 |
This server is based on an earlier version of the Bahamut server, with |
830 |
several additions and changes.</p> |
831 |
|
832 |
<p>One new feature supported by solid-ircd is encrypted connections. If a |
833 |
client connects to the server via SSL, the client is given user mode |
834 |
<tt>+z</tt>; a new channel mode, <tt>+S</tt>, is also available to prevent |
835 |
clients without <tt>+z</tt> from entering the channel. This presents a |
836 |
problem when <tt>+S</tt> is mode-locked on: since the channel does not |
837 |
exist when it is empty, the IRC server will not know to stop a <tt>-z</tt> |
838 |
user from entering the channel, and even if Services then sets <tt>+S</tt> |
839 |
on the channel, the non-secure user will already be in the channel. In |
840 |
order to work around this, Services hooks into the ChanServ |
841 |
"<tt>check_kick</tt>" callback, and if a non-secure user tries to join an |
842 |
empty channel that is registered and mode-locked <tt>+S</tt>, the user is |
843 |
kicked out just as if on the autokick list.</p> |
844 |
|
845 |
<p class="backlink"><a href="#top">Back to top</a></p> |
846 |
|
847 |
|
848 |
<h4 class="subsubsection-title" id="s6-12">5-6-12. <tt>protocol/trircd</tt></h4> |
849 |
|
850 |
<p>The <tt>protocol/trircd</tt> module supports the tr-ircd server, |
851 |
version 5.5 and later. tr-ircd was originally based on the Bahamut server, |
852 |
but has been rewritten from scratch since version 5.0.</p> |
853 |
|
854 |
<p>One feature unique to tr-ircd is the availability of a user mode |
855 |
(<tt>+L</tt>)bindicating the language in which the client desires to |
856 |
receive server messages. For users with registered nicknames, Services |
857 |
sets this to the language selected by the user for their nickname (if |
858 |
that language is also supported by tr-ircd) when the user identifies. |
859 |
<i>Implementation node: It would also be theoretically possible to use the |
860 |
mode's value as a default for sending messages unregistered nicknames, as |
861 |
well as the initial language setting of a newly-registered nickname, but |
862 |
this is difficult to accomplish without adding the concept of a language |
863 |
mode for clients to the Services core.</i> The list of languages supported |
864 |
by tr-ircd, taken from the tr-ircd source code, can be found at the top of |
865 |
the <tt>trircd.c</tt> module source file (<tt>langhash_init[]</tt>); the |
866 |
actual values used in the user mode are hashes created from the language |
867 |
name strings, and these hashes are computed and stored in the |
868 |
<tt>langhash[]</tt> array by the <tt>init_langhash()</tt> function, called |
869 |
at module initialization time.</p> |
870 |
|
871 |
<p>tr-ircd also supports "channel linking"; this is the ability to make one |
872 |
channel into an "alias" for another. When this mode (coincidentally also |
873 |
<tt>+L</tt>) is set for a channel <tt>#A</tt> with a parameter of |
874 |
<tt>#B</tt>, for example, a user who attempts to join channel <tt>#A</tt> |
875 |
will be sent to channel <tt>#B</tt> instead. As a side effect of this, the |
876 |
IRC server keeps track of channels which have <tt>+L</tt> set, and does not |
877 |
delete them even after the last client leaves. Since Services treats a |
878 |
channel with no users as nonexistent, the <tt>trircd</tt> module must hook |
879 |
into the low-level "<tt>receive message</tt>" callback to watch for |
880 |
<tt>+L</tt> or <tt>-L</tt> messages for empty channels and process them |
881 |
accordingly.</p> |
882 |
|
883 |
<p>At the server-to-server communication level, tr-ircd has the ability to |
884 |
send message names as one- or two-character tokens rather than the full |
885 |
message names; for example, "<tt>PRIVMSG</tt>" becomes simply "<tt>P</tt>", |
886 |
both reducing bandwidth (albeit minimally) and enabling faster lookup of |
887 |
commands. These tokens are defined in the <tt>trircd_tokens[]</tt> array, |
888 |
and processing is handled by the <tt>token.c</tt> auxiliary source file, |
889 |
discussed in <a href="#s7-7">section 5-7-7</a>.</p> |
890 |
|
891 |
<p class="backlink"><a href="#top">Back to top</a></p> |
892 |
|
893 |
|
894 |
<h4 class="subsubsection-title" id="s6-13">5-6-13. <tt>protocol/undernet-p9</tt></h4> |
895 |
|
896 |
<p>The <tt>protocol/undernet-p9</tt> supports version 2.9 of the Undernet |
897 |
IRC server (ircu). This is a fairly old server, derived from the original |
898 |
ircd-2.8 server with TS8 additions; the only additional features it |
899 |
includes are autokills (set using the <tt>GLINE</tt> message, and not |
900 |
propogated in the connection burst) and the merging of the <tt>USER</tt> |
901 |
and <tt>NICK</tt> messages into a single <tt>NICK</tt> message.</p> |
902 |
|
903 |
<p class="backlink"><a href="#top">Back to top</a></p> |
904 |
|
905 |
|
906 |
<h4 class="subsubsection-title" id="s6-14">5-6-14. <tt>protocol/unreal</tt></h4> |
907 |
|
908 |
<p>The <tt>protocol/unreal</tt> module supports version 3.1.1 and later of |
909 |
the UnrealIRCd server. Unreal is originally derived from Dreamforge, |
910 |
but has made numerous additions, and is one of the most feature-rich IRC |
911 |
servers currently in use. This of course means that the protocol module |
912 |
is similarly complex; Unreal makes use of nearly all protocol-related |
913 |
routines, as well as all seven auxiliary source files. For this reason, the |
914 |
<tt>unreal</tt> module's source code is the most heavily commented of the |
915 |
protocol modules, and can be seen as a model for how the various parts of |
916 |
protocol modules work.</p> |
917 |
|
918 |
<p class="backlink"><a href="#top">Back to top</a></p> |
919 |
|
920 |
|
921 |
<h5 class="subsubsubsection-title" id="s6-14-1">5-6-14-1. Module prologue</h5> |
922 |
|
923 |
<p>After including appropriate header files and the auxiliary source files |
924 |
that implement certain protocol-related functions, the module defines a |
925 |
number of local variables:</p> |
926 |
<ul> |
927 |
<li class="spaced"><tt>module_chanserv</tt>, <tt>module_operserv</tt>: |
928 |
Module handles used for accessing external symbols (see below).</li> |
929 |
<li class="spaced"><tt>ServerNumeric</tt>, <tt>SetServerTimes</tt>, |
930 |
<tt>SVSTIMEFrequency</tt>: Variables to hold values set in the |
931 |
configuration file.</li> |
932 |
<li class="spaced"><tt>to_svstime</tt>: The timeout (see |
933 |
<a href="2.html#s7">section 2-7</a>) used to send <tt>SVSTIME</tt> |
934 |
messages at periodic intervals.</li> |
935 |
<li class="spaced"><tt>usermode_admin</tt>, <tt>usermode_secure</tt>, |
936 |
<tt>usermode_hiding</tt>, <tt>chanmode_admins_only</tt>, |
937 |
<tt>chanmode_secure_only</tt>, <tt>chanmode_no_hiding</tt>: |
938 |
Bitmasks corresponding to certain sets of modes, used to determine |
939 |
whether a client is allowed to enter a particular empty |
940 |
channel.</li> |
941 |
<li class="spaced"><tt>unreal_version</tt>: Set to the protocol version |
942 |
number sent by the remote server at connection registration time, |
943 |
and used to determine whether certain protocol features are |
944 |
available.</li> |
945 |
<li class="spaced"><tt>has_nickip</tt>: Set to nonzero if the remote server |
946 |
supports the <tt>NICKIP</tt> feature, used to implement |
947 |
SZlines.</li> |
948 |
</ul> |
949 |
|
950 |
<p>These are followed by <tt>#define</tt>s and local variables used to |
951 |
access the <tt>s_ChanServ</tt> variable in the ChanServ module, containing |
952 |
the nickname of the ChanServ pseudoclient, and the |
953 |
<tt>is_services_admin()</tt> function in the OperServ module, returning |
954 |
whether the given user is a Services administrator. As described in the |
955 |
comments, <tt>#define</tt> macros are used to substitute an access to the |
956 |
symbol pointer every time the symbol is used, in order to simplify the |
957 |
code.</p> |
958 |
|
959 |
<p>The next section of the file contains a list of user, channel, and |
960 |
channel user modes supported by the Unreal server. In order to register |
961 |
these with the core mode processing facility (see |
962 |
<a href="2.html#s6-4">section 2-6-4</a>), <tt>unreal.c</tt> defines three |
963 |
arrays, one for each mode type, containing the mode characters to be added |
964 |
and the corresponding <tt>ModeInfo</tt> structure for each mode. The |
965 |
module also defines six local mode flags, corresponding to the mode bitmask |
966 |
variables listed above; these flags are ignored by the mode processing |
967 |
facility, but the mode setup code uses them to set the bitmask |
968 |
variables.</p> |
969 |
|
970 |
<p>The setup code itself is located in the <tt>init_modes()</tt> routine, |
971 |
called during module initialization. This routine iterates through each of |
972 |
the arrays, storing the mode data in the arrays exported by the mode |
973 |
processing facility. For the user and channel modes, it also checks for |
974 |
the locally-defined <tt>ModeInfo</tt> flags, and if a given mode has a flag |
975 |
set, the mode's bitmask is added to the appropriate bitmask variable.</p> |
976 |
|
977 |
<p class="backlink"><a href="#top">Back to top</a></p> |
978 |
|
979 |
|
980 |
<h5 class="subsubsubsection-title" id="s6-14-2">5-6-14-2. Message receiving</h5> |
981 |
|
982 |
<p>After this comes the first major portion of the actual processing code, |
983 |
the message handlers. Aside from the mandatory client registration |
984 |
handler (the <tt>NICK</tt> message in Unreal), Unreal includes several |
985 |
additional messages not supported by the core processing code. The |
986 |
messages handled are as follows (each message is handled by a routine |
987 |
named <tt>m_<i>message-name</i></tt>, for example the <tt>NICK</tt> |
988 |
message is handled by <tt>m_nick()</tt>):</p> |
989 |
|
990 |
<dl> |
991 |
<dt><b><tt>NICK</tt></b></dt> |
992 |
<dd>This is the standard client registration message (Unreal merges |
993 |
the dual <tt>NICK</tt> and <tt>USER</tt> of RFC 1459 into a single |
994 |
<tt>NICK</tt> message at the server level, as most other server |
995 |
protocols do). The message is also used for existing clients |
996 |
changing nicknames; in that case (where the message has a prefix |
997 |
indicating that it came from an existing client), control is |
998 |
simply handed off to the <tt>do_nick()</tt> routine from the |
999 |
core's client handling code. In the case of a new client, |
1000 |
however, <tt>do_nick()</tt> expects the parameters in a slightly |
1001 |
different order than Unreal sends them in, so this rearrangement is |
1002 |
performed before calling <tt>do_nick()</tt>. Additionally, on |
1003 |
servers supporting <tt>NICKIP</tt> (the sending of IP addresses in |
1004 |
the <tt>NICK</tt> message), the message will include an extra |
1005 |
parameter containing the binary representation of the client's IP |
1006 |
address, encoded using base64 encoding; this is decoded, checked |
1007 |
for consistency, and passed to <tt>do_nick()</tt> as well. (If |
1008 |
<tt>NICKIP</tt> is not supported, a <tt>NULL</tt> parameter is |
1009 |
passed, indicating that the IP address is not available.)</dd> |
1010 |
|
1011 |
<dt><b><tt>PROTOCTL</tt></b></dt> |
1012 |
<dd>Unreal uses this message to send information about features |
1013 |
supported by the server. Services checks the list of parameters |
1014 |
for recognized keywords, and sets appropriate variables to reflect |
1015 |
their presence or absence. The recognized feature tokens are: |
1016 |
<ul> |
1017 |
<li><b><tt>NICKv2</tt>:</b> A new format for the <tt>NICK</tt> |
1018 |
message, compared to earlier versions of Unreal. The local |
1019 |
variable <tt>got_nickv2</tt> is set when this token is |
1020 |
found; if the variable is not set at the end of the |
1021 |
function, a fatal error is generated. <i>Implementation |
1022 |
note: The variable is declared <tt>static</tt> because |
1023 |
Unreal can send more than one <tt>PROTOCTL</tt> message |
1024 |
when registering (such as when the parameter list is too |
1025 |
long). It would be more robust to use a file-global |
1026 |
variable that is checked at the first <tt>NICK</tt> |
1027 |
message, but current versions of Unreal always send |
1028 |
<tt>NICKv2</tt> in the first message, so this is not |
1029 |
currently a problem.</i></li> |
1030 |
<li><b><tt>NOQUIT</tt>:</b> The <tt>NOQUIT</tt> feature found in |
1031 |
other servers such as Bahamut, in which servers generate |
1032 |
client <tt>QUIT</tt> messages for netsplits on their own |
1033 |
rather than relaying them through the network.</li> |
1034 |
<li><b><tt>NICKIP</tt>:</b> Indicates that IP addresses are sent |
1035 |
with client registration messages.</li> |
1036 |
<li><b><tt>NICKCHARS</tt>:</b> Specifies additional characters |
1037 |
allowed to be used in nicknames. The specification is |
1038 |
done by language code; the current version of the module |
1039 |
uses the language codes and character sets defined in |
1040 |
Unreal 3.2.3.</li> |
1041 |
</ul></dd> |
1042 |
|
1043 |
<dt><b><tt>UMODE2</tt></b></dt> |
1044 |
<dd>This is equivalent to the <tt>MODE</tt> message for clients, but |
1045 |
omits the nickname parameter (so, for example, "<tt>:<i>nickname</i> |
1046 |
MODE <i>nickname</i> -o</tt>" becomes "<tt>:<i>nickname</i> UMODE2 |
1047 |
-o</tt>").</dd> |
1048 |
|
1049 |
<dt><b><tt>SETHOST</tt>, <tt>CHGHOST</tt></b></dt> |
1050 |
<dd>These allow setting changing the "fake hostname", the hostname |
1051 |
seen in a <tt>WHO</tt> or <tt>WHOIS</tt> reply by non-operators, |
1052 |
for a client. <tt>SETHOST</tt> is used by a client to change its |
1053 |
own hostname, while <tt>CHGHOST</tt> is used by operators (or |
1054 |
servers, such as Services, though Services does not use this at |
1055 |
present) to change another client's hostname.</dd> |
1056 |
|
1057 |
<dt><b><tt>SETIDENT</tt>, <tt>CHGIDENT</tt></b></dt> |
1058 |
<dd>These are like <tt>SETHOST</tt> and <tt>CHGHOST</tt> above, but |
1059 |
change the client's username (the part of the |
1060 |
<tt><i>user</i>@<i>host</i></tt> mask before the <tt>@</tt>).</dd> |
1061 |
|
1062 |
<dt><b><tt>SETNAME</tt>, <tt>CHGNAME</tt></b></dt> |
1063 |
<dd>These are like <tt>SETHOST</tt> and <tt>CHGHOST</tt> above, but |
1064 |
change the client's "real name" (also called "gecos").</dd> |
1065 |
|
1066 |
<dt><b><tt>SJOIN</tt></b></dt> |
1067 |
<dd>This is a server-to-server message used both to add a user to a |
1068 |
channel and to send a channel's state to the network. The message |
1069 |
takes a channel name, timestamp, mode string, optional mode |
1070 |
parameters, and a space-separated list of nicknames of clients |
1071 |
joining the channel. Nicknames in the nickname list are prefixed |
1072 |
with the prefix character(s) for the channel user mode of the |
1073 |
client, if any (for example, a channel operator would be listed |
1074 |
as <tt>@<i>nickname</i></tt>. Recent versions of Unreal also add |
1075 |
channel bans and ban exceptions to the nickname list as well, with |
1076 |
prefix characters of <tt>&</tt> and <tt>"</tt> respectively.</dd> |
1077 |
|
1078 |
<dt><b><tt>SVSMODE</tt>, <tt>SVS2MODE</tt></b></dt> |
1079 |
<dd>These messages are used to remotely change a client's modes or |
1080 |
to remove all bans on a channel which match a client. In the |
1081 |
former case, the messages operate identically to the <tt>MODE</tt> |
1082 |
message, except that the source and target client may be different. |
1083 |
In the latter case, each server checks the channel's ban list and |
1084 |
removes all bans corresponding to that user; Services does this by |
1085 |
calling <tt>clear_channel()</tt>, which sends out explicit |
1086 |
<tt>MODE</tt> messages to remove the bans, but this is mostly |
1087 |
harmless (other than taking up a small amount of bandwidth). The |
1088 |
only difference between SVSMODE and SVS2MODE is that, when used to |
1089 |
set client modes, the latter sends a <tt>MODE</tt> message to the |
1090 |
target client, while the former does not.</dd> |
1091 |
|
1092 |
<dt><b><tt>SVSNLINE</tt></b></dt> |
1093 |
<dd>This message is used for managing what Services refers to as the |
1094 |
SGline list, and takes one of two formats: |
1095 |
<ul> |
1096 |
<li><tt>SVSNLINE + <i>reason</i> :<i>mask</i></tt></li> |
1097 |
<li><tt>SVSNLINE - :<i>mask</i></tt></li> |
1098 |
</ul> |
1099 |
Unlike other access control lists, which are handled by the |
1100 |
<tt>TKL</tt> message (discussed below), masks for <tt>SVSNLINE</tt> |
1101 |
messages may contain spaces, and thus must be the last parameter of |
1102 |
the message. As a corollary, the <tt><i>reason</i></tt> parameter |
1103 |
cannot contain spaces. In Services, any spaces in the reason are |
1104 |
converted to underscores when an <tt>SVSNLINE +</tt> message is |
1105 |
sent.</dd> |
1106 |
|
1107 |
<dt><b><tt>TKL</tt></b></dt> |
1108 |
<dd>This message is used for managing network-wide global connection |
1109 |
control lists (autokills and S-lines). The message takes as |
1110 |
parameters: |
1111 |
<ul> |
1112 |
<li>A <tt>+</tt> or <tt>-</tt> indicating whether the mask is being |
1113 |
added or removed.</li> |
1114 |
<li>The type of the mask (a single character, such as <tt>Z</tt> |
1115 |
for SZlines).</li> |
1116 |
<li>The username part of the mask.</li> |
1117 |
<li>The hostname part of the mask.</li> |
1118 |
<li>The entity (client or server) responsible for the action.</li> |
1119 |
<li><i>(add only)</i> Timestamp (in Unix <tt>time()</tt> style) |
1120 |
for when the mask expires, or 0 if it should not expire.</li> |
1121 |
<li><i>(add only)</i> Timestamp at which the mask was added.</li> |
1122 |
<li><i>(add only)</i> Reason string associated with the mask.</li> |
1123 |
</ul> |
1124 |
When a new server connects to the network, all active <tt>TKL</tt> |
1125 |
masks are forwarded to the server. This can cause problems if a |
1126 |
mask is removed while a server is split from the network; when the |
1127 |
split server reconnects, it will send the mask back to the network, |
1128 |
causing it to reappear. While there is nothing that Services can |
1129 |
do about this in the general case, it does watch for new masks |
1130 |
added that give Services itself as the adder (Services uses its own |
1131 |
server name as the entity adding the mask, and this is preserved |
1132 |
when other servers forward the mask). When it sees such a mask |
1133 |
sent from the network, it checks whether that mask actually exists |
1134 |
in the current databases, and if not, it sends a <tt>TKL -</tt> |
1135 |
message to remove the mask, assuming that a split server has |
1136 |
rejoined the network and reintroduced an old mask.</dd> |
1137 |
</dl> |
1138 |
|
1139 |
<p>The extra messages in Unreal along with their handlers are listed in the |
1140 |
<tt>unreal_messages[]</tt> table, which is registered at initialization |
1141 |
time using <tt>register_messages()</tt> (see <a href="2.html#s5-3">section |
1142 |
2-5-3</a>). Some additional messages are also listed with <tt>NULL</tt> |
1143 |
handlers in order to prevent warning messages from being written to the log |
1144 |
when those messages are received.</p> |
1145 |
|
1146 |
<p>Unreal also supports the concept of <i>tokens</i>, short names for |
1147 |
messages used in server-to-server communication. These slightly reduce the |
1148 |
bandwidth needed for messages, but more importantly speed up message |
1149 |
lookups, since only one or two characters need to be checked rather than a |
1150 |
longer text string. The list of tokens used by Unreal is in the |
1151 |
<tt>tokens[]</tt> array; this array is passed to <tt>init_tokens()</tt>, |
1152 |
the initialization routine defined in the <tt>tokens.c</tt> auxiliary |
1153 |
source file (see <a href="#s7-7">section 5-7-7</a>).</p> |
1154 |
|
1155 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1156 |
|
1157 |
|
1158 |
<h5 class="subsubsubsection-title" id="s6-14-3">5-6-14-3. Message sending</h5> |
1159 |
|
1160 |
<p>Most of the remainder of the source file consists of various routines |
1161 |
which send messages to the network. These include the required |
1162 |
functionality listed in <a href="#s3-1">section 5-3-1</a>, as well as a |
1163 |
number of callback functions which send messages to the network in response |
1164 |
to certain events. The routines are as follows:</p> |
1165 |
|
1166 |
<dl> |
1167 |
<dt><tt><b>do_send_svstime()</b></tt></dt> |
1168 |
<dd>Sends a <tt>TSCTL SVSTIME</tt> message to the network to |
1169 |
synchronize servers' clocks. Used for periodic time |
1170 |
synchronization when requested via the <tt>SetServerTimes</tt> |
1171 |
configuration directive.</dd> |
1172 |
|
1173 |
<dt><tt><b>do_send_nick()</b></tt> |
1174 |
<br/><tt><b>do_send_nickchange()</b></tt> |
1175 |
<br/><tt><b>do_send_namechange()</b></tt> |
1176 |
<br/><tt><b>do_send_server()</b></tt> |
1177 |
<br/><tt><b>do_send_server_remote()</b></tt> |
1178 |
<br/><tt><b>do_wallops()</b></tt> |
1179 |
<br/><tt><b>do_notice_all()</b></tt> |
1180 |
<br/><tt><b>do_send_channel_cmd()</b></tt></dt> |
1181 |
<dd>Implement the corresponding required message routines.</dd> |
1182 |
|
1183 |
<dt><tt><b>do_receive_message()</b></tt></dt> |
1184 |
<dd>Performs special actions on received messages. This callback |
1185 |
function has two purposes; one is to watch for and reverse |
1186 |
improper servicestamp changes, and the other is to parse the |
1187 |
protocol version embedded in the remote server's <tt>SERVER</tt> |
1188 |
message at connection registration time. In both of these |
1189 |
cases, we do not want to override the standard behavior for the |
1190 |
messages, but the current message framework does not allow for |
1191 |
this, so we watch for the messages at this lowest level and |
1192 |
perform the necessary processing there. With respect to the |
1193 |
former case specifically, it would in theory be possible to |
1194 |
handle servicestamp changes in <tt>do_user_mode()</tt>, |
1195 |
described below, but poor design in Unreal resulted in Services |
1196 |
stamps sharing a mode letter (<tt>+d</tt>) with "deaf" mode, so |
1197 |
"+d <i>stamp</i>" needs to be treated separately from other |
1198 |
mode changes.</dd> |
1199 |
|
1200 |
<dt><tt><b>do_user_create()</b></tt></dt> |
1201 |
<dd>Called when a new <tt>User</tt> structure is created in response |
1202 |
to a <tt>NICK</tt> message, this routine stores the "fake hostname" |
1203 |
parameter (not handled by <tt>do_nick()</tt>) in the corresponding |
1204 |
field in the <tt>User</tt> structure.</dd> |
1205 |
|
1206 |
<dt><tt><b>do_user_servicestamp_change()</b></tt></dt> |
1207 |
<dd>Called when a client is assigned a servicestamp to send the new |
1208 |
stamp out to the network.</dd> |
1209 |
|
1210 |
<dt><tt><b>do_user_mode()</b></tt></dt> |
1211 |
<dd>Called when a client's user modes are being changed. Services |
1212 |
handles two user modes exclusively: <tt>+r</tt>, indicating that |
1213 |
the client's nickname is registered (and the client is in fact the |
1214 |
owner of the nickname), and <tt>+a</tt>, indicating that the client |
1215 |
is a Services administrator. If another server tries to change |
1216 |
either of these modes, Services reverses the change. This routine |
1217 |
also watches for users with Services administrator privilege who |
1218 |
newly gain IRC operator status, and sets <tt>+a</tt> on them.</dd> |
1219 |
|
1220 |
<dt><tt><b>do_channel_mode()</b></tt></dt> |
1221 |
<dd>Called when a channel's modes are being changed. This routine |
1222 |
takes care of storing the <tt>+L</tt> (channel link), <tt>+f</tt> |
1223 |
(flood protection), and <tt>+j</tt> (join rate limiting) parameters |
1224 |
in the <tt>Channel</tt> structure.</dd> |
1225 |
|
1226 |
<dt><tt><b>do_clear_channel()</b></tt></dt> |
1227 |
<dd>Handles requests to clear bans and exceptions from a channel. |
1228 |
Ordinarily, <tt>clear_channel()</tt> will handle bans itself and |
1229 |
ban exceptions are handled by the <tt>banexcept.c</tt> auxiliary |
1230 |
source file, but Unreal has a feature called "extended ban types", |
1231 |
in which a prefix like <tt>~r:</tt> changes the meaning of the ban |
1232 |
or exception mask. In order to process these bans correctly, |
1233 |
the <tt>protocol/unreal</tt> module has to intervene via the |
1234 |
"<tt>clear_channel</tt>" callback and process ban and exception |
1235 |
clear requests itself. The actual work is done by |
1236 |
<tt>unreal_clear_bans_excepts()</tt>, which calls |
1237 |
<tt>unreal_match_ban()</tt> to determine whether a particular mask |
1238 |
matches a given client.</dd> |
1239 |
|
1240 |
<dt><tt><b>do_nick_identified()</b></tt></dt> |
1241 |
<dd>Called when a client identifies for its nickname, and sets the |
1242 |
<tt>+a</tt> user mode on the client if it has Services |
1243 |
administrator (and IRC operator) privileges.</dd> |
1244 |
|
1245 |
<dt><tt><b>do_set_topic()</b></tt></dt> |
1246 |
<dd>Called when setting a topic on a channel (see |
1247 |
<a href="#s3-1">section 5-3-1</a>). Unreal ignores topic changes |
1248 |
if the topic timestamp is earlier than that of the channel's |
1249 |
current topic, so if necessary, the supplied timestamp is advanced |
1250 |
to force the topic to be changed.</dd> |
1251 |
|
1252 |
<dt><tt><b>do_check_modes()</b></tt></dt> |
1253 |
<dd>Called when checking the validity of a mode change on a registered |
1254 |
channel; ensures that the <tt>+L</tt>, <tt>+f</tt>, and <tt>+j</tt> |
1255 |
modes are set properly according to the mode lock data. (The "off" |
1256 |
versions, <tt>-L</tt> and so on, do not require parameters and thus |
1257 |
can be handled by the standard ChanServ code.)</dd> |
1258 |
|
1259 |
<dt><tt><b>do_check_chan_user_modes()</b></tt></dt> |
1260 |
<dd>Called when checking whether to modify a client's channel user |
1261 |
modes. This routine watches for and excludes from the check two |
1262 |
classes of clients: other service-type pseudoclients (with user |
1263 |
mode <tt>+S</tt> set), since they generally should not be subject |
1264 |
to the same restrictions as ordinary clients, and "hiding" users |
1265 |
(<tt>+I</tt>), whose presence would be revealed by a mode change.</dd> |
1266 |
|
1267 |
<dt><tt><b>do_check_kick()</b></tt></dt> |
1268 |
<dd>Called when checking whether to allow a user to join a channel. |
1269 |
This routine watches for users entering administrator-only, |
1270 |
secure-only, or no-hiding channels, and kicks them out if their |
1271 |
user modes are incompatible with the channel. (Normally the IRC |
1272 |
server will take care of this and Services will never see the join |
1273 |
attempt, but when joining a registered channel which is empty, the |
1274 |
server will not know anything about the channel's locked modes, so |
1275 |
Services must perform the check.)</dd> |
1276 |
|
1277 |
<dt><tt><b>do_set_mlock()</b></tt></dt> |
1278 |
<dd>Called when setting a new mode lock on a registered channel. |
1279 |
This routine takes care of setting the aforementioned <tt>+L</tt>, |
1280 |
<tt>+f</tt>, and <tt>+j</tt> mode parameters in the mode lock |
1281 |
structure, and also ensures that the new mode lock is consistent |
1282 |
(<tt>+K</tt> requires <tt>+i</tt> to be set, and <tt>+L</tt> |
1283 |
requires <tt>+l</tt>).</dd> |
1284 |
|
1285 |
<dt><tt><b>do_send_svsjoin()</b></tt></dt> |
1286 |
<dd>Called to send a message which forces a user to join a channel. |
1287 |
In Unreal, the message is called <tt>SVSJOIN</tt>.</dd> |
1288 |
|
1289 |
<dt><tt><b>do_send_akill()</b></tt> |
1290 |
<br/><tt><b>do_cancel_akill()</b></tt> |
1291 |
<br/><tt><b>do_send_exclude()</b></tt> |
1292 |
<br/><tt><b>do_cancel_exclude()</b></tt> |
1293 |
<br/><tt><b>do_send_sgline()</b></tt> |
1294 |
<br/><tt><b>do_send_sqline()</b></tt> |
1295 |
<br/><tt><b>do_send_szline()</b></tt> |
1296 |
<br/><tt><b>do_cancel_sgline()</b></tt> |
1297 |
<br/><tt><b>do_cancel_sqline()</b></tt> |
1298 |
<br/><tt><b>do_cancel_szline()</b></tt> |
1299 |
</dt> |
1300 |
<dd>Called to add or remove autokill, autokill exclusion, or S-line |
1301 |
masks.</dd> |
1302 |
</dl> |
1303 |
|
1304 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1305 |
|
1306 |
|
1307 |
<h5 class="subsubsubsection-title" id="s6-14-4">5-6-14-4. Module initialization and cleanup</h5> |
1308 |
|
1309 |
<p>The final part of the module source file is the module framework, used |
1310 |
by the core module subsystem when loading and unloading the module, along |
1311 |
with callback functions to monitor loading and unloading of relevant |
1312 |
modules and set appropriate callbacks and local variables.</p> |
1313 |
|
1314 |
<p>The module's configuration data is stored in the exported array |
1315 |
<tt>module_config[]</tt>. The <tt>protocol/unreal</tt> module includes two |
1316 |
Unreal-specific configuration options: <tt>ServerNumeric</tt>, to assign |
1317 |
Services a "numeric" value to be used with Unreal servers, and |
1318 |
<tt>SetServerTimes</tt>, which sets whether and how often Services should |
1319 |
synchronize other servers' clocks. The array also includes configuration |
1320 |
data from the <tt>SJOIN</tt> handler (defined in <tt>sjoin.h</tt>).</p> |
1321 |
|
1322 |
<p>The <tt>do_load_module()</tt> and <tt>do_unload_module()</tt> routines |
1323 |
watch for various pseudoclient-related modules to be loaded or unloaded. |
1324 |
For modules that provide callbacks which the <tt>protocol/unreal</tt> |
1325 |
module hooks into, the appropriate callback functions are added here. |
1326 |
Additionally, the handles for the <tt>operserv/main</tt> and |
1327 |
<tt>chanserv/main</tt> modules, as well as the values (addresses) of the |
1328 |
symbols <tt>is_services_admin</tt> and <tt>s_ChanServ</tt>, are saved when |
1329 |
the relevant module is loaded and cleared when it is unloaded (see |
1330 |
<a href="#s6-14-1">section 5-6-14-1</a>).</p> |
1331 |
|
1332 |
<p>Finally, the initialization and cleanup functions call the appropriate |
1333 |
subroutines in a fairly arbitrary order (except that cleanup is performed |
1334 |
in the opposite order of initialization). The initialization and cleanup |
1335 |
for the auxiliary source files is also handled here.</p> |
1336 |
|
1337 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1338 |
|
1339 |
<!------------------------------------------------------------------------> |
1340 |
<hr/> |
1341 |
|
1342 |
<h3 class="subsection-title" id="s7">5-7. Auxiliary source file details</h3> |
1343 |
|
1344 |
<p>In addition to the main protocol files described in |
1345 |
<a href="#s6">section 5-6</a>, there are several auxiliary source files |
1346 |
which implement functions common to two or more protocols. These are |
1347 |
listed below. The source files are all designed to be included directly |
1348 |
into the modules which use them; this is to avoid symbol clashes caused by |
1349 |
linking the same object file into two or more modules when compiling |
1350 |
modules statically. (Each source file also has a corresponding header |
1351 |
file, but as this is included by the source file, modules do not need to |
1352 |
include the header files separately.)</p> |
1353 |
|
1354 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1355 |
|
1356 |
|
1357 |
<h4 class="subsubsection-title" id="s7-1">5-7-1. <tt>banexcept.c</tt>, <tt>banexcept.h</tt></h4> |
1358 |
|
1359 |
<p>The <tt>banexcept.c</tt> source file implements support for <i>ban |
1360 |
exceptions</i>, masks specifying clients which are not subject to channel |
1361 |
bans. The channel mode for exceptions is assumed to be <tt>+e</tt>.</p> |
1362 |
|
1363 |
<p>In addition to handling the actual setting and clearing of ban |
1364 |
exceptions (adding or removing masks on the channel's ban exception array), |
1365 |
the file also implements a handler for clearing ban exceptions using the |
1366 |
<tt>CLEAR_EXCEPTS</tt> flag to <tt>clear_channel()</tt>, as well as a |
1367 |
callback function for the ChanServ <tt>CLEAR</tt> command allowing |
1368 |
<tt>CLEAR EXCEPTIONS</tt> to be used. Since the latter function is part |
1369 |
of the <tt>chanserv/main</tt> module rather than the core, this |
1370 |
necessitates the use of "<tt>load module</tt>" and |
1371 |
"<tt>unload module</tt>" callbacks to watch for that module being |
1372 |
loaded and unloaded.</p> |
1373 |
|
1374 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1375 |
|
1376 |
|
1377 |
<h4 class="subsubsection-title" id="s7-2">5-7-2. <tt>chanprot.c</tt>, <tt>chanprot.h</tt></h4> |
1378 |
|
1379 |
<p>The <tt>chanprot.c</tt> source file implements support for a "protected" |
1380 |
channel user mode, preventing ordinary channel operators from kicking a |
1381 |
user with that mode. However, the only "support" required is the |
1382 |
modification of one language string, which is modified by the |
1383 |
initialization routine and restored to its original value by the cleanup |
1384 |
routine.</p> |
1385 |
|
1386 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1387 |
|
1388 |
|
1389 |
<h4 class="subsubsection-title" id="s7-3">5-7-3. <tt>halfop.c</tt>, <tt>halfop.h</tt></h4> |
1390 |
|
1391 |
<p>The <tt>halfop.c</tt> source file implements support for a "half-op" |
1392 |
channel user mode, assumed to be <tt>+h</tt>. Half-ops occupy a privilege |
1393 |
level between voiced users (<tt>+v</tt>) and channel operators |
1394 |
(<tt>+o</tt>); typically, they can set <tt>+v</tt> on users and change the |
1395 |
channel topic, but cannot change channel modes or kick channel operators. |
1396 |
In addition to updating several language strings, the source file adds a |
1397 |
callback function for the ChanServ <tt>CLEAR</tt> command allowing |
1398 |
<tt>CLEAR HALFOPS</tt> to be used. As with <tt>banexcept.c</tt>, this |
1399 |
necessitates the use of load/unload-module callback functions to watch for |
1400 |
the ChanServ module being loaded or unloaded.</p> |
1401 |
|
1402 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1403 |
|
1404 |
|
1405 |
<h4 class="subsubsection-title" id="s7-4">5-7-4. <tt>invitemask.c</tt>, <tt>invitemask.h</tt></h4> |
1406 |
|
1407 |
<p>The <tt>invitemask.c</tt> source file implements support for <i>invite |
1408 |
masks</i>, masks specifying clients which are allowed to join a <tt>+i</tt> |
1409 |
channel without being explicitly invited into the channel. The channel |
1410 |
mode for exceptions is assumed to be <tt>+I</tt>. Except for the actual |
1411 |
mode character used and structure fields modified, this source file is |
1412 |
identical to <tt>banexcept.c</tt>.</p> |
1413 |
|
1414 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1415 |
|
1416 |
|
1417 |
<h4 class="subsubsection-title" id="s7-5">5-7-5. <tt>sjoin.c</tt>, <tt>sjoin.h</tt></h4> |
1418 |
|
1419 |
<p>The <tt>sjoin.c</tt> source file implements support for the |
1420 |
<tt>SJOIN</tt> message used in IRC servers such as Bahamut and Unreal. |
1421 |
This is easily the most complex of the auxiliary source files.</p> |
1422 |
|
1423 |
<p>The basic idea of the <tt>SJOIN</tt> message is to condense several |
1424 |
types of channel information—channel creation time, channel modes, |
1425 |
and users on the channel—into a single message, reducing the |
1426 |
bandwidth required to send channel state across the network and reducing |
1427 |
the potential for race conditions. There are a few slightly different |
1428 |
message formats used, as noted in the source code comments, but in general |
1429 |
the message takes the channel name, channel creation time, mode string, |
1430 |
(optional) mode parameters, and finally (in a colon-prefixed parameter) the |
1431 |
list of clients (nicknames) on the channel. In this last parameter, each |
1432 |
client's nickname is prefixed with characters indicating the client's |
1433 |
channel user modes; for example, if <tt><i>Nickname</i></tt> is a channel |
1434 |
operator on the channel, the client will be listed as |
1435 |
<tt>@<i>NickName</i></tt> in the message.</p> |
1436 |
|
1437 |
<p>Processing of the <tt>SJOIN</tt> message is handled by the |
1438 |
<tt>do_sjoin()</tt> routine; the module should call this routine when in |
1439 |
receives an <tt>SJOIN</tt> message. <tt>do_sjoin()</tt> looks at the |
1440 |
parameters to determine the message's format, then walks through the list |
1441 |
of nicknames (and possibly bans and exceptions), adding each one to the |
1442 |
channel. If any users actually joined the channel, then the channel modes |
1443 |
and timestamp are set afterwards.</p> |
1444 |
|
1445 |
<p>The <tt>SJOIN</tt> message can also be used as a shortcut to remove all |
1446 |
users from a channel with one command. By sending an <tt>SJOIN</tt> with |
1447 |
a channel timestamp older than the channel's current timestamp, the remote |
1448 |
server will treat Services' <tt>SJOIN</tt> as authoritative. If that |
1449 |
message indicates that no users are in the channel (an empty last |
1450 |
parameter), then the IRC server will automatically kick all the users |
1451 |
currently on the channel, saving Services the trouble of having to send |
1452 |
<tt>KICK</tt> messages for all users.</p> |
1453 |
|
1454 |
<p>Additionally, since <tt>SJOIN</tt> includes the channel's creation time |
1455 |
as a parameter, it is possible to use a dummy <tt>SJOIN</tt> message to |
1456 |
deliberately set the creation timestamp of a registered channel to the time |
1457 |
the channel was registered, ensuring that the channel will always be |
1458 |
considered the "canonical" one even if the same channel is created on a |
1459 |
split server.. The configuration option <tt>CSSetChannelTime</tt> |
1460 |
activates this behavior. (This configuration option is defined in a macro, |
1461 |
<tt>SJOIN_CONFIG</tt>, in <tt>sjoin.h</tt>; the module should include this |
1462 |
macro as part of its <tt>module_config[]</tt> array.) The actual setting |
1463 |
of the channel creation time is done using the "<tt>channel create</tt>" |
1464 |
callback; when a user first enters an empty channel, Services sends an |
1465 |
<tt>SJOIN</tt> message to the network with the altered channel creation |
1466 |
time, including the newly-joining user in the user list; this results in |
1467 |
the channel creation time being updated without any other changes being |
1468 |
made to the channel.</p> |
1469 |
|
1470 |
<p>Unfortunately, both of the major IRC servers using <tt>SJOIN</tt>, |
1471 |
Bahamut and Unreal, have idiosyncrasies that prevent this behavior from |
1472 |
working exactly as designed; Bahamut ignores any channel user modes set on |
1473 |
clients who are not behind the sending server, causing the client to lose |
1474 |
channel operator privileges, while Unreal interprets an empty mode string |
1475 |
(a single "<tt>+</tt>") to mean "clear all channel modes". To work around |
1476 |
this, if the module defines the preprocessor symbol <tt>BAHAMUT_HACK</tt> |
1477 |
before including this source file, this processing will be modified to set |
1478 |
<tt>+o</tt> again on the newly-joining client if it was <tt>+o</tt> before |
1479 |
the Services <tt>SJOIN</tt> was sent; this restores the original channel |
1480 |
state, at the cost of having an unsightly <tt>MODE -o</tt> and |
1481 |
<tt>MODE +o</tt> in quick succession when a user first enters a |
1482 |
registered channel. Likewise, defining <tt>UNREAL_HACK</tt> will work |
1483 |
around the Unreal problem by using the channel mode parameter to set |
1484 |
<tt>+o</tt> on the user rather than listing the user in the final |
1485 |
parameter.</p> |
1486 |
|
1487 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1488 |
|
1489 |
|
1490 |
<h4 class="subsubsection-title" id="s7-6">5-7-6. <tt>svsnick.c</tt>, <tt>svsnick.h</tt></h4> |
1491 |
|
1492 |
<p>The <tt>svsnick.c</tt> source file implements support for forced |
1493 |
changing of clients' nicknames; this is used, for example, by NickServ to |
1494 |
change a client's nickname to a "guest" nickname rather than disconnecting |
1495 |
the client outright. The implementation itself simply consists of setting |
1496 |
the <tt>PF_CHANGENICK</tt> protocol feature flag and assigning a function |
1497 |
to the <tt>send_nickchange_remote()</tt> function pointer. However, unlike |
1498 |
most other auxiliary source files, the initialization function |
1499 |
<tt>init_svsnick()</tt> takes a parameter; this is so that the protocol |
1500 |
module can specify the name of the message used, in case it is not |
1501 |
<tt>SVSNICK</tt>.</p> |
1502 |
|
1503 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1504 |
|
1505 |
|
1506 |
<h4 class="subsubsection-title" id="s7-7">5-7-7. <tt>token.c</tt>, <tt>token.h</tt></h4> |
1507 |
|
1508 |
<p>The <tt>token.c</tt> source file implements the use of one- or |
1509 |
two-character <i>tokens</i> to substitute for full message names in |
1510 |
server-to-server communications. The mapping of tokens to message names |
1511 |
is given by a <tt>TokenInfo</tt> array passed to <tt>init_tokens()</tt>, |
1512 |
terminated by an entry with the <tt>token</tt> field of the structure set |
1513 |
to <tt>NULL</tt>. The initialization routine uses this mapping array to |
1514 |
generate a 65,536-entry lookup table, indexed by the two characters of the |
1515 |
token taken as a 16-bit value with the first character in the high eight |
1516 |
bits (a value of zero is used for the second character in the case of a |
1517 |
one-character token). The values in the lookup table point directly to |
1518 |
the handler functions; this eliminates the necessity to search through |
1519 |
the message table, but also means that any later changes to the message |
1520 |
table will not be seen.</p> |
1521 |
|
1522 |
<p>The actual processing of the tokens is done by a callback function added |
1523 |
to the "<tt>receive message</tt>" callback. The function checks |
1524 |
whether the message name is two characters long or less and whether there |
1525 |
is a function in the table corresponding to the one- or two-character |
1526 |
message name; if so, that function is called, and the ordinary message |
1527 |
processing is skipped.</p> |
1528 |
|
1529 |
|
1530 |
<p class="backlink"><a href="#top">Back to top</a></p> |
1531 |
|
1532 |
<!------------------------------------------------------------------------> |
1533 |
<hr/> |
1534 |
|
1535 |
<p class="backlink"><a href="4.html">Previous section: The module system</a> | |
1536 |
<a href="index.html">Table of Contents</a> | |
1537 |
<a href="6.html">Next section: Database handling</a></p> |
1538 |
|
1539 |
</body> |
1540 |
</html> |