ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/vendor/ircservices-5.1.24/docs/tech/7.html
Revision: 3389
Committed: Fri Apr 25 14:12:15 2014 UTC (9 years, 10 months ago) by michael
Content type: text/html
File size: 202921 byte(s)
Log Message:
- Imported ircservices-5.1.24

File Contents

# Content
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 <!-- Annoyingly, <u> has been removed, so replacing it with <span style="text-decoration: underline">, as in 2.html -->
4 <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
5 <head>
6 <meta http-equiv="Content-Style-Type" content="text/css"/>
7 <style type="text/css">@import "style.css";</style>
8 <title>IRC Services Technical Reference Manual - 7. Services pseudoclients</title>
9 </head>
10
11 <body>
12 <h1 class="title" id="top">IRC Services Technical Reference Manual</h1>
13
14 <h2 class="section-title">7. Services pseudoclients</h2>
15
16 <p class="section-toc">
17 7-1. <a href="#s1">Basic features of a pseudoclient</a>
18 <br/>7-2. <a href="#s2">OperServ</a>
19 <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-2-1. <a href="#s2-1">OperServ core functionality</a>
20 <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-2-2. <a href="#s2-2">Usermask-related functions</a>
21 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-2-2-1. <a href="#s2-2-1">Common mask data support</a>
22 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-2-2-2. <a href="#s2-2-2">Autokills</a>
23 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-2-2-3. <a href="#s2-2-3">S-lines</a>
24 <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-2-3. <a href="#s2-3">Session limiting</a>
25 <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-2-4. <a href="#s2-4">News</a>
26 <br/>7-3. <a href="#s3">NickServ</a>
27 <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-3-1. <a href="#s3-1">NickServ core functionality</a>
28 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-3-1-1. <a href="#s3-1-1">Nickname data structures and utility macros</a>
29 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-3-1-2. <a href="#s3-1-2">Overall module structure</a>
30 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-3-1-3. <a href="#s3-1-3">The <tt>SET</tt> and <tt>UNSET</tt> commands</a>
31 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-3-1-4. <a href="#s3-1-4">NickServ utility routines</a>
32 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-3-1-5. <a href="#s3-1-5">Nickname colliding</a>
33 <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-3-2. <a href="#s3-2">Nickname access lists</a>
34 <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-3-3. <a href="#s3-3">Nickname auto-join lists</a>
35 <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-3-4. <a href="#s3-4">Linking and nickname groups</a>
36 <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-3-5. <a href="#s3-5">E-mail address authentication</a>
37 <br/>7-4. <a href="#s4">ChanServ</a>
38 <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-4-1. <a href="#s4-1">ChanServ core functionality</a>
39 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-4-1-1. <a href="#s4-1-1">Channel data structures</a>
40 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-4-1-2. <a href="#s4-1-2">Overall module structure</a>
41 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-4-1-3. <a href="#s4-1-3">Channel status checking and modification</a>
42 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-4-1-4. <a href="#s4-1-4">The <tt>SET</tt> and <tt>UNSET</tt> commands</a>
43 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-4-1-5. <a href="#s4-1-5">ChanServ utility routines</a>
44 <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-4-2. <a href="#s4-2">Channel access list handling</a>
45 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-4-2-1. <a href="#s4-2-1">Access list basics</a>
46 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-4-2-2. <a href="#s4-2-2">Manipulation via <tt>ACCESS</tt> and <tt>LEVELS</tt></a>
47 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-4-2-3. <a href="#s4-2-3">Manipulation via <tt>XOP</tt></a>
48 <br/>7-5. <a href="#s5">MemoServ</a>
49 <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-5-1. <a href="#s5-1">MemoServ core functionality</a>
50 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-5-1-1. <a href="#s5-1-1">Memo data structures</a>
51 <br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7-5-1-2. <a href="#s5-1-2">The <tt>memoserv/main</tt> module</a>
52 <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-5-2. <a href="#s5-2">Memo ignore lists</a>
53 <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-5-3. <a href="#s5-3">Memo forwarding</a>
54 <br/>7-6. <a href="#s6">StatServ</a>
55 <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-6-1. <a href="#s6-1">StatServ data structures</a>
56 <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-6-2. <a href="#s6-2">The StatServ module</a>
57 <br/>7-7. <a href="#s7">Miscellaneous pseudoclients</a>
58 <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-7-1. <a href="#s7-1">HelpServ</a>
59 <br/>&nbsp;&nbsp;&nbsp;&nbsp;7-7-2. <a href="#s7-2">DevNull</a>
60 </p>
61
62 <p class="backlink"><a href="6.html">Previous section: Database handling</a> |
63 <a href="index.html">Table of Contents</a> |
64 <a href="8.html">Next section: Other modules</a></p>
65
66 <!------------------------------------------------------------------------>
67 <hr/>
68
69 <h3 class="subsection-title" id="s1">7-1. Basic features of a pseudoclient</h3>
70
71 <p>Pseudoclients are the user-visible part of Services, providing the
72 actual service functions which IRC users take advantage of. While the
73 details of each pseudoclient differ greatly, all pseudoclients share some
74 common features:</p>
75
76 <ul>
77 <li class="spaced">Register one or more nicknames via the
78 "<tt>introduce_user</tt>" callback, through which the pseudoclient
79 communicates with IRC clients; see below for details.</li>
80 <li class="spaced">Receive commands from IRC clients via <tt>PRIVMSG</tt>
81 messages. (According to RFC 1459, pseudoclients <i>must not</i>
82 respond to <tt>NOTICE</tt> messages, in order to prevent infinite
83 loops in which two pseudoclients repeatedly respond to each others'
84 notices.)</li>
85 <li class="spaced">Communicate to IRC clients via <tt>NOTICE</tt> messages.
86 (While not explicitly mandated by the RFC, this is in order to
87 avoid potential message loops with other pseudoclients. Occasional
88 requests have been made for Services to allow using
89 <tt>PRIVMSG</tt> for communication with users, apparently because
90 some IRC programs do not show <tt>NOTICE</tt> messages to users,
91 but such requests have been intentionally disregarded for the above
92 reason.)</li>
93 <li class="spaced">Provide a set of commands which users can use to invoke
94 the pseudoclient's functions. (The miscellaneous modules described
95 in <a href="#s7">section 7-7</a> are an exception; the HelpServ
96 pseudoclient has only one function with no associated command name,
97 and the DevNull pseudoclient has none.) Each message to a
98 pseudoclient is interpreted as a command name and parameters, each
99 separated by one or more space characters (ASCII 0x20&mdash;note
100 that the tab character is <i>not</i> treated as a separator).</li>
101 </ul>
102
103 <p>The "<tt>introduce_user</tt>" callback mentioned above is called by the
104 same-named function, <tt>introduce_user()</tt>, to request that each module
105 introduce its nickname(s) to the IRC network by calling
106 <tt>send_pseudo_nick()</tt> (in <tt>send.c</tt>). The callback takes a
107 single <tt>const char&nbsp;*</tt> parameter, which is <tt>NULL</tt> when
108 the callback is called at startup, or the nickname seen in a <tt>KILL</tt>
109 message when one is received; accordingly, pseudoclients should introduce
110 their nicknames only when the parameter either is <tt>NULL</tt> or matches
111 (case-insensitively, as determined by <tt>irc_stricmp()</tt>) the nickname
112 to be introduced. <tt>send_pseudo_nick()</tt> takes three parameters: the
113 nickname of the pseudoclient to be introduced, the pseudoclient's "real
114 name" string (usually a description of the pseudoclient), and a flag value,
115 composed of zero or more of the following flags:</p>
116 <ul>
117 <li><tt><b>PSEUDO_OPER</b></tt>: The client requires IRC operator
118 privileges. (This does not necessarily guarantee that the client
119 will be given the <tt>+o</tt> user mode; some IRC servers allow any
120 Services pseudoclient to use IRC operator functions, and
121 <tt>+o</tt> is omitted with such servers.)</li>
122 <li><tt><b>PSEUDO_INVIS</b></tt>: The client should be marked invisible
123 (user mode <tt>+i</tt>).</li>
124 </ul>
125
126 <p>Command processing is typically performed by hooking into the core's
127 "<tt>m_privmsg</tt>" callback, which is intended specifically for this
128 purpose. Depending on the pseudoclient, it may also be necessary to
129 respond to other events on the IRC network, such as channel joins or mode
130 changes; these can typically be handled by hooking into the relevant
131 callback. In extreme cases, it may be necessary to make use of the
132 low-level "<tt>receive message</tt>" callback as well; this should be
133 avoided when possible, however, as it circumvents the standard message
134 processing and can result in network desynchronization.</p>
135
136 <p>For databases maintained by pseudoclients, the following six functions
137 are typically provided by the pseudoclient for other code that needs direct
138 access to the database (<tt><span style="text-decoration: underline"><i>type</i></span></tt> is the record data
139 type, <tt><span style="text-decoration: underline"><i>name</i></span></tt> is a distinguishing name generally
140 derived from <tt><span style="text-decoration: underline"><i>type</i></span></tt>, and <tt><span style="text-decoration: underline"><i>keytype</i></span></tt>
141 is the data type of the key field):</p>
142
143 <dl>
144 <dt><tt><span style="text-decoration: underline"><i>type</i></span> *<b>add_<span style="text-decoration: underline"><i>name</i></span></b>(<span style="text-decoration: underline"><i>type</i></span> *<i>record</i>)</tt></dt>
145 <dd>Adds the given record to the database, returning a pointer to the
146 record structure as stored (which may be different from the pointer
147 passed into the function).</dd>
148
149 <dt><tt>void <b>del_<span style="text-decoration: underline"><i>name</i></span></b>(<span style="text-decoration: underline"><i>type</i></span> *<i>record</i>)</tt></dt>
150 <dd>Deletes the given record from the database. <tt><i>record</i></tt>
151 is assumed to be valid, <i>i.e.</i> a pointer returned by a
152 previous call to another database function.</dd>
153
154 <dt><tt><span style="text-decoration: underline"><i>type</i></span> *<b>get_<span style="text-decoration: underline"><i>name</i></span></b>(<span style="text-decoration: underline"><i>keytype</i></span> *<i>key</i>)</tt></dt>
155 <dd>Returns the record for the given key, or <tt>NULL</tt> if the key
156 is not found in the database.</dd>
157
158 <dt><tt>void <b>put_<span style="text-decoration: underline"><i>name</i></span></b>(<span style="text-decoration: underline"><i>type</i></span> *<i>record</i>)</tt></dt>
159 <dd>Indicates that the given record is no longer in use. Each call to
160 a database's <tt>get()</tt> function must be followed by a
161 <tt>put()</tt> call for the same record, unless the record is
162 deleted first. <i>Implementation note: A <tt>put()</tt> function
163 was first introduced in 5.0 with the intention that it be used for
164 indicating when a record had been updated, for the purpose of
165 storing the updated data into persistent storage such as an
166 SQL-based database. DBMS support never materialized, and the
167 function's purpose was redefined for version 5.1 to keep track of
168 which records are actively in use, but I have no confidence that
169 the code does <tt>put()</tt> calls in all necessary cases and no
170 others; in fact, it appears that <tt>put_nickgroupinfo()</tt> (at
171 least) is called more often than it should be. It may have been
172 better to drop <tt>put()</tt> entirely and use other methods of
173 checking whether records are in use before expiring them.</i></dd>
174
175 <dt><tt><span style="text-decoration: underline"><i>type</i></span> *<b>first_<span style="text-decoration: underline"><i>name</i></span></b>()</tt>
176 <br/><tt><span style="text-decoration: underline"><i>type</i></span> *<b>next_<span style="text-decoration: underline"><i>name</i></span></b>()</tt></dt>
177 <dd>Iterates through the database. <tt>first()</tt> returns the first
178 record in the database, and subsequent <tt>next()</tt> calls return
179 each successive record, finally returning <tt>NULL</tt> when all
180 records have been iterated through (if there are no records at all,
181 both <tt>first()</tt> and <tt>next()</tt> return <tt>NULL</tt>).
182 The order is database-dependent, but no record will be returned
183 more than once from the time <tt>first()</tt> is called to the time
184 <tt>next()</tt> returns <tt>NULL</tt>. It is unspecified whether
185 records added while iterating through the database will be
186 included in the iteration. Note that these functions are
187 <i>not</i> considered a "get" for the purposes of the
188 <tt>put()</tt> function; thus a call to <tt>put()</tt> is not
189 required for simple iteration, but if any other database function
190 is to be called before the following <tt>next()</tt>, then an
191 explicit call to <tt>get()</tt> (and a matching call to
192 <tt>put()</tt>) must be made to prevent the record in use from
193 being deleted.</dd>
194 </dl>
195
196 <p>The following sections describe each of the Services pseudoclients in
197 detail. The reader is assumed to be familiar with the functions of each
198 pseudoclient from a user's point of view, as described in
199 <a href="../3.html">section 3 of the user's manual</a>.</p>
200
201 <p class="backlink"><a href="#top">Back to top</a></p>
202
203 <!------------------------------------------------------------------------>
204 <hr/>
205
206 <h3 class="subsection-title" id="s2">7-2. OperServ</h3>
207
208 <p>The OperServ pseudoclient provides services to IRC operators allowing
209 control of the network and of Services itself. While not seen by most IRC
210 users, this pseudoclient is discussed first since it provides functionality
211 used by most other pseudoclients.</p>
212
213 <p>As with most of the Services pseudoclients, OperServ is composed of one
214 core or "main" module, <tt>operserv/main</tt>, and several optional modules
215 providing additional functionality. These are each discussed in separate
216 sections below.</p>
217
218 <p class="backlink"><a href="#top">Back to top</a></p>
219
220
221 <h4 class="subsubsection-title" id="s2-1">7-2-1. OperServ core functionality</h4>
222
223 <p>The core functionality of OperServ is contained in the
224 <tt>modules/operserv/main.c</tt> source file, compiled into the
225 <tt>operserv/main</tt> module. In addition to the implementation of the
226 core OperServ commands, this file also defines several utility functions
227 used by several other pseudoclient modules; external declarations of these
228 functions and associated constants are located in
229 <tt>modules/operserv/operserv.h</tt>.</p>
230
231 <p><tt>main.c</tt> is written using the same general structure as most
232 module source files. At the top of the file are variable definitions,
233 including configuration variables, which are given the same names as their
234 corresponding configuration directives; these are followed by forward
235 declarations of individual command routines and the command list. Next
236 come database-related structures and routines, followed by the top-level
237 pseudoclient routines (the "<tt>introduce_user</tt>", "<tt>m_privmsg</tt>",
238 and "<tt>m_whois</tt>" callback functions), and finally the actual command
239 routines, along with any utility routines needed.</p>
240
241 <p>For OperServ, the first item of note is the list of several commands and
242 command routines inside <tt>#ifdef DEBUG_COMMANDS</tt>. These are, as the
243 conditional name suggests, commands used for debugging Services, and are
244 only available to the Services super-user; the commands are described in
245 detail below.</p>
246
247 <p>OperServ stores several values to persistent storage, including the
248 maximum client count, the time at which that maximum was reached, and the
249 super-user (<tt>SU</tt> command) password. This data is stored by
250 aggregating the data into a single structure, <tt>operserv_data</tt>, and
251 storing that structure as a single database "record" in a table named
252 "<tt>oper</tt>". Two exported functions, <tt>get_operserv_data()</tt> and
253 <tt>put_operserv_data()</tt>, are also provided to allow external modules,
254 in particular the XML import and export modules (see
255 <a href="8.html#s4">section 8-4</a>), to access the data as well.</p>
256
257 <p>In order to check a client's Services privilege level (Services
258 operator, Services administrator, or Services super-user), OperServ requires
259 access to the nickname data, in which each registered nickname group's
260 privilege level is stored (the <tt>os_priv</tt> member). However, since
261 NickServ requires that OperServ be loaded first, OperServ must look up the
262 symbols for these routines during its normal operation. Six local functions
263 are defined, one for each of the imported routines (<tt>get_nickinfo()</tt>,
264 <tt>put_nickinfo()</tt>, <tt>_get_ngi()</tt>, <tt>put_nickgroupinfo()</tt>,
265 <tt>first_nickgroupinfo()</tt>, and <tt>next_nickgroupinfo()</tt>), taking
266 the same parameters and returning the same values as the real routines; the
267 local versions look up the symbol for each routine and then call the
268 corresponding address, returning an appropriate error value if the symbol
269 cannot be resolved (or NickServ is not loaded).</p>
270
271 <p>The main processing routine itself, <tt>operserv()</tt>, is registered
272 as a callback function for the "<tt>m_privmsg</tt>" callback, called for
273 each <tt>PRIVMSG</tt> received by Services. The routine first checks that
274 the message is intended for OperServ; then it ensures that the client that
275 sent the message is an IRC operator, to avoid any possibility of
276 non-operator clients exploiting a bug in the OperServ code. The message
277 received is then logged in the log file, except that parameters to the
278 <tt>SU</tt> and <tt>SET SUPASS</tt> commands are replaced with a dummy
279 string to avoid leaving the super-user password in the log file. (OperServ
280 has no way to detect if one of these commands is misspelled, so for
281 example, a mistaken <tt>SET SUPSAS</tt> will be logged in full, including
282 the password.) Next, the command name is extracted from the message
283 using the <tt>strtok()</tt> function; this also prepares <tt>strtok()</tt>
284 for the command handler to use in extracting the command parameters (see
285 below). After handling CTCP <tt>PING</tt> messages separately, OperServ
286 calls a "<tt>command</tt>" callback, allowing other modules a chance to
287 process the command first. Finally, if no callback function responds to
288 the command, it is looked up in the command table and the command's handler
289 function is called (if the command is not found, an error message is sent
290 instead).</p>
291
292 <p>Following this and other callback functions are the privilege check
293 functions; <tt>is_services_root()</tt>, <tt>is_services_admin()</tt>, and
294 <tt>is_services_oper()</tt>, which check whether a client has Services
295 super-user, Services administrator, and Services operator privileges
296 respectively (any client with a higher privilege level is treated as
297 having all lower privilege levels as well). The <tt>is_services_root()</tt>
298 function relies on the <tt>ServicesRoot</tt> configuration setting, along
299 with the <tt>UF_SERVROOT</tt> flag in the <tt>User</tt> structure
300 indicating clients which have successfully used the <tt>SU</tt> command;
301 lower privilege levels check the <tt>os_priv</tt> field of the nickname
302 group data structure (see <a href="#s3-1">section 7-3-1</a>) for privilege
303 determination. These routines are exported, and used widely throughout the
304 other pseudoclient modules to perform privilege checks on clients; in
305 particular, they can be used as privilege check functions in the
306 <tt>has_priv</tt> member of a <tt>Command</tt> structure. There is another
307 routine, <tt>nick_is_services_admin()</tt>, which checks if a particular
308 nickname can potentially can Services administrator access, ignoring
309 whether the nickname is actually in use at the time; this is used by
310 NickServ to prevent certain operations from being performed on such
311 nicknames by clients without Services administrator privilege.</p>
312
313 <p>The command routines themselves are fairly straightforward. One thing
314 to note is that the routines all obtain parameters via
315 <tt>strtok(NULL,...)</tt> and <tt>strtok_remaining()</tt>; this relies on
316 the fact that <tt>operserv()</tt> leaves the message string in the
317 <tt>strtok()</tt> buffer after stripping the command name, so that each
318 routine can parse the command's parameters as appropriate for that command.
319 <tt>strtok_remaining()</tt> is used when the full remaining string is
320 desired, such as when sending a global message; this function is preferred
321 to <tt>strtok(NULL,"")</tt> because the latter can leave leading or
322 trailing whitespace in the result.</p>
323
324 <p>The processing for the <tt>HELP</tt> command, in <tt>do_help()</tt>, is
325 somewhat tortuous (although still simpler than in other pseudoclients) in
326 order to give proper help responses depending on how Services is
327 configured. In the case of OperServ, some commands may or may not be
328 available depending on what submodules are loaded; the <tt>COMMANDS</tt>
329 help text, which lists the available commands, is combined from several
330 language strings depending on whether the appropriate modules are available
331 to provide a list of the commands which are actually usable at that
332 particular time. Other modules include more complex processing, such as
333 checking the configuration variable values or protocol features. For
334 commands that do not need such special-casing, the <tt>help_cmd()</tt>
335 routine in the Services core (see <a href="2.html#s10">section 2-10</a>)
336 sends a help message as defined by the <tt>Command</tt> structure.</p>
337
338 <p>The debug commands, defined toward the bottom of <tt>main.c</tt>, are as
339 follows:</p>
340
341 <dl>
342 <dt><tt><b>LISTSERVERS</b></tt> (<tt>send_server_list()</tt>)</dt>
343 <dd>Sends a <tt>NOTICE</tt> for each server in the server list giving
344 the contents of the <tt>Server</tt> structure.</dd>
345
346 <dt><tt><b>LISTCHANS</b></tt> (<tt>send_channel_list()</tt>)</dt>
347 <dd>Sends two <tt>NOTICE</tt>s for each channel in the channel list.
348 The first <tt>NOTICE</tt> gives the channel name, creation time,
349 modes (as a string), limit, key ("<tt>-</tt>") if none, and
350 topic; the second contains each client on the channel along with
351 that client's channel user modes on the channel. Any messages
352 which exceed the maximum length of an IRC line are silently
353 truncated.</dd>
354
355 <dt><tt><b>LISTCHAN</b> <i>channel</i></tt> (<tt>send_channel_info()</tt>)</dt>
356 <dd>Sends a <tt>NOTICE</tt> for each client on the given channel with
357 the client's channel user modes (as a hexadecimal value) and
358 nickname.</dd>
359
360 <dt><tt><b>LISTUSERS</b></tt> (<tt>send_user_list()</tt>)</dt>
361 <dd>Sends a <tt>NOTICE</tt> for each client on the network, giving
362 the client's nickname and usermask, the "fake host" or "<tt>-</tt>"
363 if none, the IP address or "<tt>-</tt>" if none, user modes as a
364 string, signon timestamp (from the remote server), servicestamp,
365 server name, nickname status flags or "<tt>-</tt>" if the nickname
366 is not registered, ignore value, and real name field.</dd>
367
368 <dt><tt><b>LISTUSER</b> <i>nickname</i></tt> (<tt>send_user_info()</tt>)</dt>
369 <dd>Sends three <tt>NOTICE</tt>s describing the state of the given
370 client. The first is identical to the line that <tt>LISTUSERS</tt>
371 would output for the client; the second gives the channels which
372 the client has currently joined; and the third gives the channels
373 which the client has identified to ChanServ for.</dd>
374
375 <dt><tt><b>LISTTIMERS</b></tt> (<tt>send_timeout_list()</tt>, in
376 <tt>timeout.c</tt>)</dt>
377 <dd>Sends a <tt>NOTICE</tt> giving the current time, followed by a
378 <tt>NOTICE</tt> for each timeout currently in the list giving the
379 timeout pointer, timestamp, function pointer, and function
380 argument. This routine is defined in <tt>timeout.c</tt> because
381 the internal timeout fields are hidden from other source
382 files.</dd>
383
384 <dt><tt><b>MATCHWILD</b> <i>pattern</i> <i>string</i> </tt> (<tt>do_matchwild()</tt>)</dt>
385 <dd>Sends a <tt>NOTICE</tt> giving the result of calling
386 <tt>match_wild</tt> with the given parameters.</dd>
387
388 <dt><tt><b>SETCMODE [<i>channel</i> <i>modes</i> <i>mode-params</i>...]</b></tt> (<tt>do_setcmode()</tt>)</dt>
389 <dd>Calls <tt>set_cmode()</tt> with the given parameters, using
390 <tt>ServerName</tt> as the message sender. If no parameters are
391 given, calls <tt>set_cmode(NULL,NULL)</tt> to flush out all
392 pending mode changes. Note that the number of mode parameters
393 (including the mode string itself) is limited by the
394 <tt>SETCMODE_NPARAMS</tt> macro, defined to 10 in the source
395 code.</dd>
396
397 <dt><tt><b>MONITOR-IGNORE</b> [<i>nickname</i>]</tt> (<tt>do_monitor_ignore()</tt>)</dt>
398 <dd>If a nickname is given, starts recording that nickname's ignore
399 value to the log file at 100ms intervals; if no nickname is given,
400 cancels any previous monitoring. Note that in order to ensure
401 sub-second resolution, the <tt>TimeoutCheck</tt> configuration
402 variable is set to 10 (milliseconds) when a nickname is given,
403 potentially causing a reduction in performance; the old value is
404 <i>not</i> restored when the command is given without a
405 nickname.</dd>
406
407 <dt><tt><b>GETSTRING</b> <i>language</i> <i>string</i></tt> (<tt>do_getstring()</tt>)</dt>
408 <dd>Sends a <tt>NOTICE</tt> containing the text corresponding to the
409 given string in the given language. Both <tt><i>language</i></tt>
410 and <tt><i>string</i></tt> can be given as either names or raw
411 numbers.</dd>
412
413 <dt><tt><b>SETSTRING</b> <i>language</i> <i>string</i> [<i>text</i>]</tt> (<tt>do_setstring()</tt>)</dt>
414 <dd>Calls <tt>setstring()</tt> to set the given string in the given
415 language to the given text. If no text is given, the string
416 becomes empty.</dd>
417
418 <dt><tt><b>MAPSTRING</b> <i>old</i> <i>new</i></tt> (<tt>do_mapstring()</tt>)</dt>
419 <dd>Calls <tt>mapstring()</tt> to map one string to another.
420 <tt><i>old</i></tt> and <tt><i>new</i></tt> are string names or
421 numbers.</dd>
422
423 <dt><tt><b>ADDSTRING</b> <i>name</i></tt> (<tt>do_addstring()</tt>)</dt>
424 <dd>Calls <tt>addstring()</tt> to add a string with the given name to
425 the language table. On success, sends a <tt>NOTICE</tt> with the
426 new string number.</dd>
427 </dl>
428
429 <p class="backlink"><a href="#top">Back to top</a></p>
430
431
432 <h4 class="subsubsection-title" id="s2-2">7-2-2. Usermask-related functions</h4>
433
434 <h5 class="subsubsubsection-title" id="s2-2-1">7-2-2-1. Common mask data support</h5>
435
436 <p>One of the major features of OperServ not included in the core module
437 is the autokill and S-line functionality. While these are in fact defined
438 in separate modules, most of the processing for both sets of functions is
439 subsumed under the <tt>MaskData</tt> structure and its generic processing
440 routines included in the core OperServ module, located in
441 <tt>maskdata.c</tt> and <tt>maskdata.h</tt>. This structure contains the
442 elements common to all of these features: a mask string (whose
443 interpretation is left to the particular module), an associated reason
444 string, the nickname of the client that added the mask, the time the mask
445 was added, the time it expires, and the last time the mask was applied to a
446 client; these are stored in the <tt>mask</tt>, <tt>reason</tt>,
447 <tt>who</tt>, <tt>time</tt>, <tt>expires</tt>, and <tt>lastused</tt>
448 fields of the structure, respectively. The remaining fields (other than
449 the record management fields <tt>next</tt>, <tt>prev</tt>, and
450 <tt>usecount</tt>) are: <tt>type</tt>, containing an 8-bit value
451 identifying the type of mask; <tt>num</tt>, giving the user-visible index
452 number for session exception records (see <a href="#s2-3">section
453 7-2-3</a>); and <tt>limit</tt>, used for the session limit in session
454 exception records.</p>
455
456 <p>As mentioned above, each <tt>MaskData</tt> record has an associated
457 type; more accurately, there are multiple sets of <tt>MaskData</tt>
458 records, one set for each type (the <tt>type</tt> field is only used
459 internally for loading and saving data from or to persistent storage, and
460 does not need to be set by the caller). The available types, defined by
461 the <tt>MD_*</tt> constants in <tt>maskdata.h</tt>, are:</p>
462 <ul>
463 <li><b><tt>MD_AKILL</tt>:</b> An autokill record.</li>
464 <li><b><tt>MD_EXCLUDE</tt>:</b> An autokill exclusion record.</li>
465 <li><b><tt>MD_EXCEPTION</tt>:</b> A session exception record.</li>
466 <li><b><tt>MD_SGLINE</tt>:</b> An SGline record.</li>
467 <li><b><tt>MD_SQLINE</tt>:</b> An SQline record.</li>
468 <li><b><tt>MD_SZLINE</tt>:</b> An SZline record.</li>
469 </ul>
470 <p>It is worth noting that (as also mentioned in <a href="#s2-2-3">section
471 7-2-2-3</a> below) the values chosen for <tt>MD_SGLINE</tt>,
472 <tt>MD_SQLINE</tt>, and <tt>MD_SZLINE</tt> are the ASCII values of the
473 characters <tt>G</tt>, <tt>Q</tt>, and <tt>Z</tt> respectively; this was
474 done in order to simplify common code for all three types of S-lines, so
475 that the type value could be used as is in messages sent to clients rather
476 than having to make separate tests to determine the appropriate text to
477 send. (For example, most of the language file messages for S-line actions
478 use "<tt>S%cLINE</tt>" in the format string, where the <tt>%c</tt> is
479 replaced by the type value.)</p>
480
481 <p>One other structure, <tt>MaskDataCmdInfo</tt>, can be found in
482 <tt>maskdata.h</tt>; this structure collects information particular to a
483 single <tt>MaskData</tt> type for use by the common command processing.
484 The bulk of the structure consists of language string indices, which are
485 used in sending responses to commands procesed by the common code. These
486 are preceded by: <tt>name</tt>, the command name (such as "<tt>AKILL</tt>"
487 or "<tt>SGLINE</tt>"); <tt>type</tt>, the record type to be used; and
488 <tt>def_expiry_ptr</tt>, a pointer to a variable containing the default
489 expiration period in seconds (a pointer is used so that any changes to the
490 value can be recognized immediately without having to modify this structure
491 as well). There are also five function pointers, all of which are optional
492 (and should be set to <tt>NULL</tt> if not needed):</p>
493
494 <dl>
495 <dt><tt>void (*<b>mangle_mask</b>)(char *<i>mask</i>)</tt></dt>
496 <dd>Makes any necessary changes to a mask before it is operated on.
497 Any modifications may be made to the mask as long as they do not
498 lengthen it beyond the original string length. Currently, this
499 is used to force case-insensitive masks to lowercase, to avoid the
500 possibility of multiple matching masks with differing case from
501 being added to the database.</dd>
502
503 <dt><tt>int (*<b>check_add_mask</b>)(const User *<i>u</i>, uint8 <i>type</i>, char *<i>mask</i>, time_t *<i>expiry_ptr</i>)</tt></dt>
504 <dd>Checks whether the given mask of the given type is allowed to be
505 added with the given expiration time (in seconds from the present
506 time, passed as a pointer); returns nonzero to allow the mask to be
507 added, zero to deny it. The mask and expiration time may be
508 modified by the function, provided that the mask is not lengthened
509 beyond the original string length.</dd>
510
511 <dt><tt>void (*<b>do_add_mask</b>)(const User *<i>u</i>, uint8 <i>type</i>, MaskData *<i>md</i>)</tt></dt>
512 <dd>Performs any extra actions necessary when a mask is added to the
513 database, such as sending that mask to the network.</dd>
514
515 <dt><tt>void (*<b>do_del_mask</b>)(const User *<i>u</i>, uint8 <i>type</i>, MaskData *<i>md</i>)</tt></dt>
516 <dd>Performs any extra actions necessary when a mask is removed from
517 the database.</dd>
518
519 <dt><tt>int (*<b>do_unknown_cmd</b>)(const User *<i>u</i>, const char *<i>cmd</i>, char *<i>mask</i>)</tt></dt>
520 <dd>Processes an unknown subcommand for the associated command,
521 returning nonzero if the subcommand was handled, zero otherwise.</dd>
522 </dl>
523
524 <p>The function which implements the mask-related command support is
525 <tt>do_maskdata_cmd()</tt>, defined below the database support functions in
526 <tt>maskdata.c</tt>. This function behaves in the same way as a standard
527 pseudoclient command handler, taking a single <tt>User&nbsp;*</tt>
528 parameter giving the client that sent the command, and retrieving command
529 parameters via <tt>strtok(NULL,...)</tt>. After obtaining the subcommand
530 name and its parameters (with double-quote processing for masks), the
531 routine checks for the known subcommands <tt>ADD</tt>, <tt>DEL</tt>,
532 <tt>CLEAR</tt>, <tt>LIST</tt>, <tt>VIEW</tt>, <tt>CHECK</tt>, and
533 <tt>COUNT</tt>, processing each appropriately. If the subcommand is not
534 one of these, it is passed to the command's <tt>do_unknown_cmd()</tt>
535 function; if that function returns zero or does not exist, an error is
536 sent to the client.</p>
537
538 <p>The subcommands themselves are implemented by local routines:
539 <tt>do_maskdata_add()</tt>, <tt>do_maskdata_del()</tt>, and so on. These
540 check the validity of the parameters for the particular subcommand and
541 perform the appropriate action, using the language string indices in the
542 <tt>MaskDataCmdInfo</tt> structure to send replies to the client that
543 issued the command.</p>
544
545 <p>There are also three utility functions defined after the command
546 handler routines:</p>
547
548 <dl>
549 <dt><tt>void *<b>new_maskdata</b>()</tt></dt>
550 <dd>Allocates, initializes, and returns a new <tt>MaskData</tt>
551 structure. (The return value is <tt>void&nbsp;*</tt> to avoid a
552 type warning in the database table declaration.)</dd>
553
554 <dt><tt>void <b>free_maskdata</b>(void *<i>record</i>)</tt></dt>
555 <dd>Frees the <tt>MaskData</tt> structure pointed to by
556 <tt><i>record</i></tt>, Does nothing if <tt><i>record</i></tt> is
557 <tt>NULL</tt>.</dd>
558
559 <dt><tt>char *<b>make_reason</b>(const char *<i>format</i>, const MaskData *<i>data</i>)</tt></dt>
560 <dd>Returns the reason string for the given mask and format string.
561 If <tt><i>format</i></tt> contains a "<tt>%s</tt>", it will be
562 replaced by the mask's reason string in the return value;
563 otherwise, the returned string is identical to
564 <tt><i>format</i></tt>. The result string is stored in a static
565 buffer, which is overwritten by subsequent calls to
566 <tt>make_reason()</tt>.</dd>
567 </dl>
568
569 <p>With respect to the database management routines, <tt>MaskData</tt>
570 records are stored in variable-length arrays, one array for each of the 256
571 possible mask types. (Arrays were chosen over hash tables for simplicity;
572 since the most common use of these records is searching all records of a
573 particular type for one that matches a given string, there would be little
574 benefit to the use of a hash table.) The <tt>next</tt> and <tt>prev</tt>
575 fields are not ordinarily required for array handling, but the code stores
576 the (integer) array index value in the <tt>next</tt> field via a cast to
577 <tt>void&nbsp;*</tt>, allowing the code to know where in the array a given
578 record is located without having to search through the array every time
579 (note that the <tt>num</tt> field is used for a different
580 purpose&mdash;index numbers for session exceptions&mdash;and is not
581 available). Aside from the standard database operations, which take a
582 <tt>uint8 <i>type</i></tt> parameter in addition to the mask record itself,
583 the following functions are included:</p>
584
585 <dl>
586 <dt><tt>MaskData *<b>get_matching_maskdata</b>(uint8 <i>type</i>, const char *<i>str</i>)</tt></dt>
587 <dd>Searches for and returns (in the same manner as
588 <tt>get_maskdata()</tt>, including expiration checks) a mask which
589 matches the wildcard pattern given by <tt><i>str</i></tt>. If more
590 than one mask matches, an arbitrary one is returned.</dd>
591
592 <dt><tt>MaskData *<b>get_exception_by_num</b>(int <i>num</i>)</tt></dt>
593 <dd>Retrieves a mask of the <tt>MD_EXCEPTION</tt> (session exception)
594 type by its index number.</dd>
595
596 <dt><tt>MaskData *<b>move_exception</b>(MaskData *<i>except</i>, int <i>newnum</i>)</tt></dt>
597 <dd>Changes the index number of the given <tt>MD_EXCEPTION</tt> mask.
598 (Internally, this reorders the mask array so that entries remain in
599 order by index number.)</dd>
600 </dl>
601
602 <p class="backlink"><a href="#top">Back to top</a></p>
603
604
605 <h5 class="subsubsubsection-title" id="s2-2-2">7-2-2-2. Autokills</h5>
606
607 <p>As mentioned above, one of the main uses of this mask data code is the
608 autokill module, <tt>operserv/akill</tt>, defined in <tt>akill.c</tt> and
609 <tt>akill.h</tt>. While support for the OperServ <tt>AKILL</tt> and
610 <tt>EXCLUDE</tt> commands simply makes use of the aforementioned
611 <tt>do_maskdata_cmd()</tt> function, handling for the actual autokills and
612 autokill exclusions themselves is defined within the autokill module. This
613 includes:</p>
614
615 <ul>
616 <li class="spaced"><tt>send_akill()</tt> and <tt>cancel_akill()</tt>, and
617 their autokill exclusion companions <tt>send_exclude()</tt> and
618 <tt>cancel_exclude()</tt>, which (via callbacks hooked into by
619 protocol modules) take care of adding and removing autokills and
620 exclusions on the network. Note that <tt>cancel_akill()</tt> and
621 <tt>cancel_exclude()</tt> destroy their <tt>char&nbsp;*</tt>
622 parameters, but as they are only called when deleting a record,
623 this is not a problem.</li>
624
625 <li class="spaced"><tt>do_user_check()</tt>, which hooks into the
626 "<tt>user check</tt>" callback to check whether a newly connecting
627 client matches any active autokills or exclusions and take
628 appropriate action.</li>
629
630 <li class="spaced"><tt>create_akill()</tt>, an exported function which
631 creates a new autokill record given the usermask, reason, setter
632 nickname, and time to expiration. (There is currently no
633 equivalent function for autokill exclusions.)</li>
634
635 <li class="spaced">The data structure and helper functions for
636 <tt>do_maskdata_cmd()</tt>. In particular, <tt>check_add_akill</tt>
637 uses simple heuristics to check for masks that are so general that
638 they would match any conceivable combination of username and
639 hostname (for example, "<tt>*@*</tt>" or "<tt>?*@*?.*?*</tt>") and
640 disallow such masks, in order to avoid situations where no one
641 could connect to the network because every client matched the
642 autokill.</li>
643
644 <li class="spaced">The <tt>AKILLCHAN</tt> command implementation,
645 <tt>do_akillchan()</tt>. It is worth noting that (as commented in
646 the code) there is a race condition that can allow the client to
647 reconnect in the miniscule interval between disconnecting the
648 client with a <tt>KILL</tt> command and adding an autokill for that
649 client; this negligible risk was taken in light of the fact that
650 doing it the other way (sending the autokill first) causes some IRC
651 servers to automatically kill the client, and OperServ's
652 <tt>KILL</tt> would cause a "user not found" message to be logged
653 (which did in fact generate some complaints from users). However,
654 once the client is killed, the username and hostname from the
655 <tt>User</tt> structure are no longer available, so they must be
656 saved ahead of time (the code at one point failed to do this,
657 predictably resulting in crashes&mdash;hence the vitriolic comment
658 about that mistake).</li>
659
660 <li class="spaced">The "<tt>connect</tt>" callback function, which sends
661 all autokills to the network on initial connection.</li>
662
663 <li class="spaced">The "<tt>expire_maskdata</tt>" timeout function, which
664 checks for autokill expiration. In order to prevent flooding of
665 IRC operators, for example when autokills set by an
666 <tt>AKILLCHAN</tt> command expire, expiration announcements via
667 <tt>WALLOPS</tt> are (if enabled) only sent at the rate of one per
668 second, and any further expirations are merged into a single
669 "<i>nnn</i> more autokills have expired" message sent after all
670 expirations are complete.</li>
671
672 <li class="spaced">The OperServ "<tt>HELP</tt>" callback function, which
673 is required to display the <tt>AKILL</tt> help message correctly.</li>
674
675 <li class="spaced">The OperServ "<tt>STATS ALL</tt>" callback function,
676 used to calculate and display autokill memory usage in response to
677 a <tt>STATS ALL</tt> command.</li>
678 </ul>
679
680 <p>One item of interest in the module setup code at the bottom of the
681 source file is the handling of the <tt>EXCLUDE</tt> command.
682 <tt>EXCLUDE</tt> can be enabled or disabled via a configuration file
683 option (<tt>EnableExclude</tt>), for reasons discussed below. Rather than
684 create two command tables, one with <tt>EXCLUDE</tt> and one without, the
685 code simply modifies the <tt>EXCLUDE</tt> entry to have an empty command
686 name if the command is disabled; since command names parsed by OperServ
687 cannot be empty, the command will never be found. (In order to locate the
688 entry again once the name has been cleared, a static variable is used, set
689 during module initialization to point to the proper element of the command
690 array. The name is restored during module cleanup so that a subsequent
691 initialization will likewise be able to find it.)</p>
692
693 <p>The handling of autokill exclusions is trickier than it may seem at
694 first glance, due to protocols which support network-wide autokill masks
695 but not exclusion masks. If one takes the naive approach of simply adding
696 autokill masks as usual, one will find that the effectiveness of the
697 autokill exclusions is severely limited. For example, consider a network
698 with an autokill for <tt>*@*.example.com</tt> and an exclusion for
699 <tt>*@oper.example.com</tt>. As long as the only users in the
700 <tt>example.com</tt> domain to connect are from the
701 <tt>oper.example.com</tt> host, the exclusion will function as expected.
702 However, as soon as a user from another <tt>example.com</tt> host connects,
703 the autokill will be triggered and sent out to the network&mdash;with the
704 unintended result that even users from <tt>oper.example.com</tt> are
705 prevented from connecting, since Services has no way to inform other
706 servers on the network about the autokill exclusion.</p>
707
708 <p>In order to avoid this problem, the <tt>operserv/akill</tt> module will
709 not make use of a protocol's autokill features if that protocol does not
710 also support autokill exclusions, and will simply send out a <tt>KILL</tt>
711 message for each user to be disconnected from the network. However, this
712 may not be desirable for networks that have no intention of using the
713 autokill exclusion functionality. For this reason, the
714 <tt>EnableExclude</tt> configuration option was added, allowing such
715 networks to choose between taking advantage of the protocol's autokill
716 feature and using exclusions with autokills.</p>
717
718 <p class="backlink"><a href="#top">Back to top</a></p>
719
720
721 <h5 class="subsubsubsection-title" id="s2-2-3">7-2-2-3. S-lines</h5>
722
723 <p>S-lines are the other primary user of the mask data code. These sets of
724 client restriction masks (SGlines, SQlines, and SZlines) are implemented by
725 the <tt>operserv/sline</tt> module, defined in <tt>sline.c</tt> and
726 <tt>sline.h</tt>.</p>
727
728 <p>The S-line module is very similar to the autokill module, both
729 functionally and internally (in fact, <tt>sline.c</tt> started out as a
730 copy of <tt>akill.c</tt>). The primary difference is in the sharing of
731 data and code between the three mask types. Since the command names differ
732 only in a single character, the code takes the shortcut of using that
733 character as the mask type for use with the <tt>MaskData</tt> support
734 functions&mdash;this is the reason for the warning comment in
735 <tt>maskdata.h</tt> about changing the type values&mdash;and including a
736 <tt>%c</tt> token in relevant messages which is replaced by the mask type.
737 This enables a single message, such as "<tt>%d masks on the S%cLINE
738 list.</tt>", to be shared by code for all three sets of masks. Several
739 functions are likewise shared by the three mask types, taking a type
740 parameter to select which data set to operate on.</p>
741
742 <p>Naturally, each type of mask is interpreted differently, so the actual
743 processing for each type is handled separately. SQlines, in particular,
744 are checked by the utility routine <tt>check_sqline()</tt>, called from the
745 callback functions <tt>do_user_check()</tt> and
746 <tt>do_user_nickchange_after()</tt>, because there are several possible
747 ways of handling a match:</p>
748
749 <ul>
750 <li class="spaced">If the client is an IRC operator and the
751 <tt>SQlineIgnoreOpers</tt> configuration option is enabled, then
752 SQlines are not checked at all. (The <tt><i>new_oper</i></tt>
753 parameter is required because, when called from
754 <tt>do_user_check()</tt>, the <tt>User</tt> record will not yet
755 have been created.)</li>
756
757 <li class="spaced">If the SQline is for a guest nick, the client is left
758 alone, though the SQline itself is sent to the network.</li>
759
760 <li class="spaced">If the <tt>SQlineKill</tt> configuration option is
761 <i>not</i> set and the protocol in use supports forced nickname
762 changing, the client's nickname is changed to a guest nickname, and
763 the SQline is sent to the network.</li>
764
765 <li class="spaced">Otherwise, the client is killed, and the SQline is sent
766 to the network.</li>
767 </ul>
768
769 <p class="backlink"><a href="#top">Back to top</a></p>
770
771
772 <h4 class="subsubsection-title" id="s2-3">7-2-3. Session limiting</h4>
773
774 <p>The last method of client control, session limiting, is implemented by
775 the <tt>operserv/sessions</tt> module, defined in <tt>sessions.c</tt>. The
776 module consists of two major parts: the actual session maintenance and
777 limiting code, and session exception mask management via the
778 <tt>EXCEPTION</tt> command.</p>
779
780 <p>The session maintenance functionality is contained within the
781 <tt>add_session()</tt> and <tt>del_session()</tt> routines, called from
782 callback functions when clients join or leave the network, respectively.
783 These routines keep track of each host with one or more clients on the
784 network by means of a hash table containing <tt>Session</tt> structures,
785 one per host. When <tt>add_session</tt> is called, it looks up the
786 <tt>Session</tt> record for the new client's hostname, creating a new
787 record with a count of zero if no record for that host already exists, then
788 increments the host's client count by one; conversely,
789 <tt>del_session()</tt> decrements the host's client count, deleting the
790 <tt>Session</tt> structure when the count reaches zero.</p>
791
792 <p>The "limiting" part of session limiting is a check in
793 <tt>add_session()</tt> to determine whether the host has "too many"
794 clients on the network. Here, "too many" is defined by either the limit
795 given in an exception record (see below) or the default limit given in the
796 <tt>DefSessionLimit</tt> configuration directive; if adding the new client
797 would cause the host's client count to exceed the relevant limit, then the
798 client is killed (any clients already connected are left alone). An
799 autokill can also be added for thte host depending on the configuration
800 settings.</p>
801
802 <p>The module also provides a <tt>SESSION</tt> command to allow Services
803 operators to view the contents of the session list; this can be used to
804 find hosts from which a large number of clients are connecting. The
805 <tt>SESSION</tt> command is available even if actual limiting of sessions
806 is disabled (by setting <tt>DefSessionLimit</tt> to zero).</p>
807
808 <p>The second part of the module, session exceptions, allows fine-tuning of
809 the default limit on client connections. For example, it may be desirable
810 to allow extra connections from a particular host known to be used by IRC
811 operators. Such exceptions to the default session limit are stored using
812 <tt>MaskData</tt> structures with the <tt>MD_EXCEPTION</tt> type; each
813 record is treated as a wildcard pattern against which a connecting client's
814 hostname is matched, and if a match is found, that limit is used instead of
815 the default, as described above. If more than one matching session
816 exception exists, the first one in the list (from a user's point of view,
817 the one with the lowest index number) is used.</p>
818
819 <p>Session exceptions are maintained using the <tt>EXCEPTION</tt> command.
820 The processing for this command, in <tt>do_exception()</tt> and its
821 subroutines, is very similar to other mask-type commands like
822 <tt>AKILL</tt>; however, session exceptions require a limit value in
823 addition to the mask, and it was considered simpler to keep the handling
824 for <tt>EXCEPTION</tt> separate rather than modify
825 <tt>do_maskdata_cmd()</tt> to handle both command formats. The
826 <tt>EXCEPTION</tt> command also includes a <tt>MOVE</tt> subcommand,
827 allowing one record to be moved relative to another within the list (so,
828 for example, a newly-added exception can be moved earlier in the list to
829 take precedence over other exceptions).</p>
830
831 <p>A careful look at the initialization code will show that the
832 "<tt>user check</tt>" callback function, <tt>check_sessions()</tt> (which
833 in turn calls <tt>add_session()</tt>), is added at a priority of -10. This
834 is in order to ensure that the function is called after all other checks
835 have been performed, as described in <a href="4.html#s5-2">section
836 4-5-2</a> (and is a poor design choice for the reasons described there).</p>
837
838 <p class="backlink"><a href="#top">Back to top</a></p>
839
840
841 <h4 class="subsubsection-title" id="s2-4">7-2-4. News</h4>
842
843 <p>The last OperServ submodule is the <tt>operserv/news</tt> module,
844 defined in <tt>news.c</tt> and <tt>news.h</tt>. This is a fairly simple
845 module, containing routines to handle news item storage and implement the
846 <tt>LOGONNEWS</tt> and <tt>OPERNEWS</tt> commands.</p>
847
848 <p>News items are stored in a single variable-length array of
849 <tt>News</tt> structures, <tt>newslist</tt>. The <tt>News</tt> structure
850 contains, aside from the text of the news item itself, the news type
851 (<tt>NEWS_LOGON</tt> or <tt>NEWS_OPER</tt>), an index number used when
852 deleting the item, the nickname of the client that added the item, and the
853 time the item was added. As with <tt>MaskData</tt> structures,
854 <tt>next</tt> and <tt>prev</tt> fields are included only to mirror other
855 structures, and the array index is stored in the <tt>next</tt> field.</p>
856
857 <p>The two news commands, <tt>LOGONNEWS</tt> and <tt>OPERNEWS</tt>, share
858 the same code, <tt>do_news()</tt>; this routine is called by the actual
859 command handlers with one of the news type codes, either
860 <tt>NEWS_LOGON</tt> or <tt>NEWS_OPER</tt>, and accesses an array of
861 language string indices (<tt>msgarray[]</tt>) to return proper messages
862 for each command, similar to <tt>do_maskdata_cmd()</tt>. Unlike most other
863 commands (but like the <tt>OPER</tt> and <tt>ADMIN</tt> commands in the
864 OperServ core), the news commands include a <tt>LIST</tt> command available
865 to all IRC operators, and other subcommands (<tt>ADD</tt> and <tt>DEL</tt>)
866 restricted to Services operators; thus, the command handler must perform
867 privilege checks on its own rather than specifying a privilege check
868 routine in the command table.</p>
869
870 <p class="backlink"><a href="#top">Back to top</a></p>
871
872 <!------------------------------------------------------------------------>
873 <hr/>
874
875 <h3 class="subsection-title" id="s3">7-3. NickServ</h3>
876
877 <p>NickServ is typically the first pseudoclient IRC users interact with.
878 It was also the first pseudoclient created during Services' initial design,
879 on which all other pseudoclients were based. The current NickServ is
880 divided into a core module and four submodules implementing additional
881 features; each module is described in its own section below.</p>
882
883 <p class="backlink"><a href="#top">Back to top</a></p>
884
885
886 <h4 class="subsubsection-title" id="s3-1">7-3-1. NickServ core functionality</h4>
887
888 <p>The core NickServ functionality is implemented by the
889 <tt>nickserv/main</tt> module. Alongside the primary module source file,
890 <tt>main.c</tt>, the module makes use of three additional source files:
891 <tt>collide.c</tt>, handling the disconnection or forced removal of clients
892 using unauthorized nicknames; <tt>set.c</tt>, implementing the <tt>SET</tt>
893 command and its subcommands; and <tt>util.c</tt>, containing various
894 utility routines used by NickServ.</p>
895
896 <p>NickServ makes use of two distinct header files. One,
897 <tt>nickserv.h</tt>, defines the data structures used for storing nickname
898 information (<tt>NickInfo</tt> and <tt>NickGroupInfo</tt>, described below)
899 along with declarations of exported routines and macros used with nickname
900 records. The other, <tt>ns-local.h</tt>, contains declarations of routines
901 used within NickServ, necessarily declared <tt>extern</tt> because they
902 reside in separate source files but not intended to be used outside the
903 NickServ modules.</p>
904
905 <p class="backlink"><a href="#top">Back to top</a></p>
906
907
908 <h5 class="subsubsubsection-title" id="s3-1-1">7-3-1-1. Nickname data structures and utility macros</h5>
909
910 <p>Two separate structures are used to store nickname data; this is to
911 facilitate the implementation of nickname links, as described in
912 <a href="#s3-4">section 7-3-4</a>. One structure, <tt>NickInfo</tt>,
913 contains data that is distinct for each individual nickname; the other,
914 <tt>NickGroupInfo</tt>, contains data that is shared among each group of
915 linked nicknames.</p>
916
917 <p>The <tt>NickInfo</tt> structure includes the following data:</p>
918
919 <dl>
920 <dt><tt>NickInfo *<b>next</b>, *<b>prev</b></tt></dt>
921 <dd>Used to link records together in the internal hash table.</dd>
922
923 <dt><tt>int <b>usecount</b></tt></dt>
924 <dd>The record's usage count (number of gets minus number of puts).
925 <i>(Implementation note: As noted in <a href="#s1">section 7-1</a>,
926 this field currently serves no actual purpose.)</i></dd>
927
928 <dt><tt>char <b>nick</b>[NICKMAX]</tt></dt>
929 <dd>The actual nickname. Capitalization is as used when the nickname
930 was registered, and does not change due to later actions. The
931 buffer size, <tt>NICKMAX</tt>, is defined in the global header
932 file <tt>defs.h</tt>.</dd>
933
934 <dt><tt>int16 <b>status</b></tt></dt>
935 <dd>The nickname's status. This is a combination of zero or more of
936 the following flags:
937 <ul>
938 <li><b><tt>NS_VERBOTEN</tt>:</b> The nickname is a forbidden
939 nickname set with the <tt>FORBID</tt> command. ("Verboten"
940 is German for "forbidden", but there is no particular
941 meaning behind this choice other than a whim of the
942 developer as he was writing the code.)</li>
943 <li><b><tt>NS_NOEXPIRE</tt>:</b> The nickname is not to be expired
944 regardless of how long it remains unused (<tt>SET
945 NOEXPIRE</tt>).</li>
946 <li><b><tt>NS_KILL_HELD</tt>:</b> The nickname is currently being
947 held by an "enforcer" pseudoclient after killing (or
948 changing the nickname of) a client that was using the
949 nickname without permission.</li>
950 <li><b><tt>NS_GUESTED</tt>:</b> An IRC message has been sent to
951 change the nickname of the client using the nickname, but
952 the nickname change has not yet occurred.</li>
953 </ul>
954 Of these flags, <tt>NS_VERBOTEN</tt> and <tt>NS_NOEXPIRE</tt> are
955 "permanent" flags (collected in the <tt>NS_PERMANENT</tt> mask),
956 which are retained across restarts of Services, while
957 <tt>NS_KILL_HELD</tt> and <tt>NS_GUESTED</tt> are "temporary" flags
958 (collected in the <tt>NS_TEMPORARY</tt> mask), which are cleared
959 each time the database is loaded from persistent storage. Note
960 that the value 0x0001 (bit 0) is not used because it served a
961 separate purpose in previous versions of Services.</dd>
962
963 <dt><tt>char *<b>last_usermask</b></tt></dt>
964 <dd>The last <tt><i>user</i>@<i>host</i></tt> mask used by the owner
965 of the nickname (<i>i.e.,</i> a client authorized to use the
966 nickname). If the owner is currently online, that client's
967 <tt><i>user</i>@<i>host</i></tt> mask is used. On IRC networks
968 where a "fake hostname" is available, that hostname is used
969 instead of the client's actual hostname.</dd>
970
971 <dt><tt>char *<b>last_realmask</b></tt></dt>
972 <dd>Like <tt>last_usermask</tt>, but uses the real hostname instead of
973 any "fake hostname". On networks without such a fake hostname,
974 this field is identical to <tt>last_usermask</tt>.</dd>
975
976 <dt><tt>char *<b>last_realname</b></tt></dt>
977 <dd>The last "real name" string used by the owner of the nickname.</dd>
978
979 <dt><tt>char *<b>last_quit</b></tt></dt>
980 <dd>The message used the last time the owner quit IRC. <tt>NULL</tt>
981 if not available, such as for newly-registered nicknames.</dd>
982
983 <dt><tt>time_t <b>time_registered</b></tt></dt>
984 <dd>The timestamp when the nickname was registered.</dd>
985
986 <dt><tt>time_t <b>last_seen</b></tt></dt>
987 <dd>The timestamp at which the owner most recently used the nickname.
988 Only updated when the owner stops using the nickname; if the
989 nickname is currently in use, this field should not be relied on.</dd>
990
991 <dt><tt>uint32 <b>nickgroup</b></tt></dt>
992 <dd>The ID of the nickname group with which this nickname is associated
993 (see below).</dd>
994
995 <dt><tt>uint32 <b>id_stamp</b></tt></dt>
996 <dd>The servicestamp of the client that last identified for the
997 nickname. Used to retain identification status across Services
998 restarts.</dd>
999
1000 <dt><tt>User *<b>user</b></tt></dt>
1001 <dd><i>Not saved to persistent storage.</i> A pointer to the
1002 <tt>User</tt> structure for the client currently using the
1003 nickname, or <tt>NULL</tt> if the nickname is not currently in
1004 used.</dd>
1005
1006 <dt><tt>int16 <b>authstat</b></tt></dt>
1007 <dd><i>Not saved to persistent storage.</i> Zero or more of the
1008 following flags, indicating the nickname's authentication status:
1009 <ul>
1010 <li><b><tt>NA_IDENTIFIED</tt>:</b> The current user of the nickname
1011 has identified by password as the nickname's owner.
1012 Mutually exclusive with <tt>NA_IDENT_NOEMAIL</tt>.</li>
1013 <li><b><tt>NA_IDENT_NOMAIL</tt>:</b> The current user of the
1014 nickname has identified by password as the nickname's
1015 owner, but has not registered an E-mail address with the
1016 nickname when one is required. Mutually exclusive with
1017 <tt>NA_IDENTIFIED</tt>.</li>
1018 <li><b><tt>NA_RECOGNIZED</tt>:</b> The current user of the nickname
1019 is recognized via the nickname access list (see
1020 <a href="#s3-2">section 7-3-2</a>).</li>
1021 </ul></dd>
1022
1023 <dt><tt>int <b>bad_passwords</b></tt></dt>
1024 <dd><i>Not saved to persistent storage.</i> The number of consecutive
1025 failed password identification attempts for the nickname. Used to
1026 determine whether or not to kill a client for attempted password
1027 cracking.</dd>
1028 </dl>
1029
1030 <p>The <tt>NickGroupInfo</tt> structure includes the following data:</p>
1031
1032 <dl>
1033 <dt><tt>NickGroupInfo *<b>next</b>, *<b>prev</b></tt></dt>
1034 <dd>Used to link records together in the internal hash table.</dd>
1035
1036 <dt><tt>int <b>usecount</b></tt></dt>
1037 <dd>The record's usage count (number of gets minus number of puts).
1038 <i>(Implementation note: As noted in <a href="#s1">section 7-1</a>,
1039 this field currently serves no actual purpose.)</i></dd>
1040
1041 <dt><tt>uint32 <b>id</b></tt></dt>
1042 <dd>The nickname group's ID, a unique 32-bit value. Typically, this
1043 value is randomly assigned. The value zero is not allowed (it is
1044 used in <tt>NickInfo</tt> records to indicate the lack of an
1045 associated nickname group, as for forbidden nicknames).</dd>
1046
1047 <dt><tt>nickname_t *<b>nicks</b></tt>
1048 <br/><tt>uint16 <b>nicks_count</b></tt></dt>
1049 <dd><i>Not saved to persistent storage.</i> A variable-length array
1050 containing the nicknames associated with this nickname group. Used
1051 for convenience, to avoid having to search through the nickname
1052 database every time a list of nicknames is needed.</dd>
1053
1054 <dt><tt>uint16 <b>mainnick</b></tt></dt>
1055 <dd>The "main nickname" for the group, used to represent the nickname
1056 group in things such as channel access lists. Specified as an
1057 index into the <tt>nicks[]</tt> array.</dd>
1058
1059 <dt><tt>Password <b>pass</b></tt></dt>
1060 <dd>The password used for identification for the nickname group.</dd>
1061
1062 <dt><tt>char *<b>url</b></tt></dt>
1063 <dd>A URL associated with the nickname group. Can be arbitrarily set
1064 by the owner.</dd>
1065
1066 <dt><tt>char *<b>email</b></tt></dt>
1067 <dd>An E-mail address associated with the nickname group. Can be
1068 arbitrarily set by the owner, and may be required at registration
1069 time by setting the <tt>NSRequireEmail</tt> configuration option.</dd>
1070
1071 <dt><tt>char *<b>last_email</b></tt></dt>
1072 <dd>When mail-based authentication (see <a href="#s3-5">section
1073 7-3-5</a>) is in use, this field is set to the previous contents
1074 of the <tt>email</tt> field when the owner changes the E-mail
1075 address, and is cleared when the new address is authenticated; this
1076 allows the <tt>RESTOREMAIL</tt> command to function.</dd>
1077
1078 <dt><tt>char *<b>info</b></tt></dt>
1079 <dd>A free-form text string associated with the nickname group. Can be
1080 arbitrarily set by the owner.</dd>
1081
1082 <dt><tt>int32 <b>flags</b></tt></dt>
1083 <dd>A bitmask containing zero or more of the following nickname group
1084 flags:
1085 <ul>
1086 <li><b><tt>NF_KILLPROTECT</tt>:</b> NickServ should prevent other
1087 clients from using the nickname by either killing them or
1088 changing their nicknames, depending on the IRC protocol in
1089 use (<tt>SET KILL ON/QUICK/IMMED</tt>).</li>
1090 <li><b><tt>NF_SECURE</tt>:</b> NickServ should require password
1091 identification for the nickname even if the client is on
1092 the nickname's access list (<tt>SET SECURE</tt>).</li>
1093 <li><b><tt>NF_MEMO_HARDMAX</tt>:</b> The client is not permitted to
1094 change the nickname's memo limit (MemoServ <tt>SET LIMIT
1095 HARD</tt>).</li>
1096 <li><b><tt>NF_MEMO_SIGNON</tt>:</b> MemoServ should inform the
1097 client of new memos at signon (MemoServ <tt>SET NOTIFY
1098 ON/LOGON</tt>).</li>
1099 <li><b><tt>NF_MEMO_RECEIVE</tt>:</b> MemoServ should inform the
1100 client of new memos when they are sent (MemoServ <tt>SET
1101 NOTIFY ON/NEW</tt>).</li>
1102 <li><b><tt>NF_PRIVATE</tt>:</b> The nickname is hidden from the
1103 <tt>LIST</tt> and <tt>LISTEMAIL</tt> command output, except
1104 when used by Services administrators (<tt>SET
1105 PRIVATE</tt>).</li>
1106 <li><b><tt>NF_HIDE_EMAIL</tt>:</b> The nickname's E-mail address is
1107 hidden from the <tt>INFO</tt> and <tt>LISTEMAIL</tt>
1108 command output, except when used by Services administrators
1109 (<tt>SET HIDE EMAIL</tt>).</li>
1110 <li><b><tt>NF_HIDE_MASK</tt>:</b> The nickname's
1111 <tt><i>user</i>@<i>host</i></tt> mask is hidden from the
1112 <tt>INFO</tt> and <tt>LIST</tt> command output, except when
1113 used by Services administrators (<tt>SET HIDE
1114 USERMASK</tt>).</li>
1115 <li><b><tt>NF_HIDE_QUIT</tt>:</b> The nickname's last quit message
1116 is hidden from the <tt>INFO</tt> command output, except
1117 when used by Services administrators (<tt>SET HIDE
1118 QUIT</tt>).</li>
1119 <li><b><tt>NF_KILL_QUICK</tt>:</b> NickServ should allow only 20
1120 seconds instead of 60 for an unauthorized client to change
1121 nickname (<tt>SET KILL QUICK/IMMED</tt>).</li>
1122 <li><b><tt>NF_KILL_IMMED</tt>:</b> NickServ should kill or
1123 nickchange unauthorized clients immediately with no grace
1124 period (<tt>SET KILL IMMED</tt>).</li>
1125 <li><b><tt>NF_MEMO_FWD</tt>:</b> MemoServ should forward received
1126 memos to the nickname's E-mail address (MemoServ <tt>SET
1127 FORWARD ON/COPY</tt>).</li>
1128 <li><b><tt>NF_MEMO_FWDCOPY</tt>:</b> MemoServ should save copies of
1129 forwarded memos (MemoServ <tt>SET FORWARD COPY</tt>).</li>
1130 <li><b><tt>NF_SUSPENDED</tt>:</b> The nickname group is suspended
1131 (<tt>SUSPEND</tt>).</li>
1132 <li><b><tt>NF_NOOP</tt>:</b> ChanServ should prevent the nickname
1133 from being added to channel access lists (<tt>SET
1134 NOOP</tt>).</li>
1135 </ul>
1136 Note that the value 0x00000004 (bit 2) is not included in the above
1137 flags because it served a separate purpose in previous versions of
1138 Services. Instead, this value is used as a temporary flag
1139 (<tt>NF_NOGROUP</tt>) when loading databases from earlier versions
1140 of Services, to indicate that a nickname group does not yet have an
1141 ID value assigned.</dd>
1142
1143 <dt><tt>int16 <b>os_priv</b></tt></dt>
1144 <dd>The nickname group's privilege level with respect to OperServ.
1145 Can be any value, but typically either zero (no special
1146 privileges) or one of the following values:
1147 <ul>
1148 <li><b><tt>NP_SERVOPER</tt>:</b> Services operator privilege.</li>
1149 <li><b><tt>NP_SERVADMIN</tt>:</b> Services administrator
1150 privilege.</li>
1151 </ul>
1152 Other values are treated by the OperServ privilege checking code
1153 (see <a href="#s2-1">section 7-2-1</a>) as having the next lowest
1154 recognized value.</dd>
1155
1156 <dt><tt>int32 <b>authcode</b></tt></dt>
1157 <dd>The authentication code set for the nickname group, or zero if no
1158 code is set. See <a href="#s3-5">section 7-3-5</a>.</dd>
1159
1160 <dt><tt>time_t <b>authset</b></tt></dt>
1161 <dd>The timestamp when the nickname group's authentication code was
1162 set (meaningless if no code is set).</dd>
1163
1164 <dt><tt>int16 <b>authreason</b></tt></dt>
1165 <dd>The reason the nickname group's current authentication code was
1166 set (meaningless if no code is set). One of the following
1167 constants:
1168 <ul>
1169 <li><b><tt>NICKAUTH_REGISTER</tt>:</b> The nickname was newly
1170 registered, and the E-mail address provided in the
1171 <tt>REGISTER</tt> command requires authentication.</li>
1172 <li><b><tt>NICKAUTH_SET_EMAIL</tt>:</b> The nickname group's
1173 E-mail address was changed with the <tt>SET EMAIL</tt>
1174 command, and the new address requires authentication.</li>
1175 <li><b><tt>NICKAUTH_SETAUTH</tt>:</b> Authentication is required as
1176 the result of a Services administrator using the
1177 <tt>SETAUTH</tt> command.</li>
1178 <li><b><tt>NICKAUTH_REAUTH</tt>:</b> Authentication is required as
1179 the result of the nickname owner using the <tt>REAUTH</tt>
1180 command.</li>
1181 </ul></dd>
1182
1183 <dt><tt>char <b>suspend_who</b>[NICKMAX]</tt></dt>
1184 <dd>The nickname of the client that suspended the nickname group
1185 (meaningless if the <tt>NF_SUSPENDED</tt> flag is not set).</dd>
1186
1187 <dt><tt>char *<b>suspend_reason</b></tt></dt>
1188 <dd>The reason the nickname group was suspended (meaningless if the
1189 <tt>NF_SUSPENDED</tt> flag is not set).</dd>
1190
1191 <dt><tt>time_t <b>suspend_time</b></tt></dt>
1192 <dd>The timestamp when the nickname group was suspended (meaningless if
1193 the <tt>NF_SUSPENDED</tt> flag is not set).</dd>
1194
1195 <dt><tt>time_t <b>suspend_expires</b></tt></dt>
1196 <dd>The timestamp at which the nickname group's suspension expires
1197 (meaningless if the <tt>NF_SUSPENDED</tt> flag is not set).</dd>
1198
1199 <dt><tt>int16 <b>language</b></tt></dt>
1200 <dd>The language preferred for messages sent to the nickname group.
1201 One of the <tt>LANG_*</tt> constants in the Services core's
1202 <tt>language.h</tt>.</dd>
1203
1204 <dt><tt>int16 <b>timezone</b></tt></dt>
1205 <dd>The time zone offset specified by the nickname group's owner for
1206 use in displaying times. A number of minutes (possibly negative)
1207 to be added to the UTC timestamps, or <tt>TIMEZONE_DEFAULT</tt> to
1208 use the Services process' default.</dd>
1209
1210 <dt><tt>int16 <b>channelmax</b></tt></dt>
1211 <dd>The maximum number of channels the nickname group is allowed to
1212 register, <tt>CHANMAX_UNLIMITED</tt> for no limit, or
1213 <tt>CHANMAX_DEFAULT</tt> for the default limit (set by the
1214 ChanServ <tt>CSMaxReg</tt> configuration setting).</dd>
1215
1216 <dt><tt>char **<b>access</b></tt>
1217 <br/><tt>int <b>access_count</b></tt></dt>
1218 <dd>The nickname group's access list (see <a href="#s3-2">section
1219 7-3-2</a>).</dd>
1220
1221 <dt><tt>char **<b>ajoin</b></tt>
1222 <br/><tt>int <b>ajoin_count</b></tt></dt>
1223 <dd>The nickname group's auto-join list (see <a href="#s3-3">section
1224 7-3-3</a>).</dd>
1225
1226 <dt><tt>char **<b>ignore</b></tt>
1227 <br/><tt>int <b>ignore_count</b></tt></dt>
1228 <dd>The nickname group's memo ignore list (see <a href="#s5-2">section
1229 7-5-2</a>).</dd>
1230
1231 <dt><tt>MemoInfo <b>memos</b></tt></dt>
1232 <dd>The nickname group's stored memos (see <a href="#s5-1">section
1233 7-5-1</a>).</dd>
1234
1235 <dt><tt>channame_t *<b>channels</b></tt>
1236 <br/><tt>int <b>channels_count</b></tt></dt>
1237 <dd><i>Not saved to persistent storage.</i> The names of the channels
1238 currently registered by this nickname group.</dd>
1239
1240 <dt><tt>User **<b>id_users</b></tt>
1241 <br/><tt>int <b>id_users_count</b></tt></dt>
1242 <dd><i>Not saved to persistent storage.</i> Pointers to <tt>User</tt>
1243 structures for clients which have identified for this nickname
1244 group.</dd>
1245
1246 <dt><tt>time_t <b>last_sendauth</b></tt></dt>
1247 <dd><i>Not saved to persistent storage.</i> The timestamp when the
1248 <tt>SENDAUTH</tt> command was last used for this nickname group
1249 (see <a href="#s3-5">section 7-3-5</a>).</dd>
1250
1251 <dt><tt>int <b>bad_auths</b></tt></dt>
1252 <dd><i>Not saved to persistent storage.</i> The number of times the
1253 <tt>AUTH</tt> command has been used with a bad authentication code
1254 for this nickname group (see <a href="#s3-5">section 7-3-5</a>).</dd>
1255 </dl>
1256
1257 <p>In addition, <tt>nickserv.h</tt> declares the following convenience
1258 functions and macros:</p>
1259
1260 <dl>
1261 <dt><tt>int <b>nick_recognized</b>(const NickInfo *<i>ni</i>)</tt>
1262 <br/><tt>int <b>user_recognized</b>(const User *<i>u</i>)</tt></dt>
1263 <dd>Returns whether the given client is recognized via an access list
1264 entry, regardless of whether the client has identified for the
1265 nickname group or not. The client can be specified by either
1266 <tt>NickInfo</tt> or <tt>User</tt> structure. (Nickname
1267 authorization flags are always cleared when a client disconnects
1268 from the network, so the <tt>NickInfo</tt> form will always return
1269 false if used on a nickname not currently in use.)</dd>
1270
1271 <dt><tt>int <b>nick_identified</b>(const NickInfo *<i>ni</i>)</tt>
1272 <br/><tt>int <b>user_identified</b>(const User *<i>u</i>)</tt></dt>
1273 <dd>Returns whether the given client has identified for its nickname.
1274 The client can be specified by either <tt>NickInfo</tt> or
1275 <tt>User</tt> structure.</dd>
1276
1277 <dt><tt>int <b>nick_id_or_rec</b>(const NickInfo *<i>ni</i>)</tt>
1278 <br/><tt>int <b>user_id_or_rec</b>(const User *<i>u</i>)</tt></dt>
1279 <dd>Returns whether the given client is recognized via access list or
1280 has identified for its nickname (or both). The client can be
1281 specified by either <tt>NickInfo</tt> or <tt>User</tt> structure.</dd>
1282
1283 <dt><tt>int <b>nick_ident_nomail</b>(const NickInfo *<i>ni</i>)</tt>
1284 <br/><tt>int <b>user_ident_nomail</b>(const User *<i>u</i>)</tt></dt>
1285 <dd>Returns whether the <tt>NA_IDENT_NOMAIL</tt> flag is set for the
1286 given client; <i>i.e.,</i> evaluates to true when has identified
1287 for its nickname but the nickname lacks a required E-mail address.
1288 The client can be specified by either <tt>NickInfo</tt> or
1289 <tt>User</tt> structure.</dd>
1290
1291 <dt><tt>int <b>ngi_unauthed</b>(const NickGroupInfo *<i>ngi</i>)</tt></dt>
1292 <dd>Returns whether the given nickname group (more accurately, the
1293 nickname group's E-mail address) is unauthenticated. Note that use
1294 of the <tt>REAUTH</tt> command does not cause the nickname group to
1295 lose its authenticated status.</dd>
1296
1297 <dt><tt>int <b>valid_ngi</b>(const NickGroupInfo *<i>ngi</i>)</tt></dt>
1298 <dd>Returns whether the given <tt>NickGroupInfo</tt> structure pointer
1299 is valid; <i>i.e.,</i> evaluates to true when <tt><i>ngi</i></tt>
1300 is neither <tt>NULL</tt> nor <tt>NICKGROUPINFO_INVALID</tt>. (The
1301 latter value is used in <tt>User</tt> structures to indicate that
1302 the client has an associated <tt>NickInfo</tt> structure but no
1303 <tt>NickGroupInfo</tt> structure, as is the case for forbidden
1304 nicknames.)</dd>
1305
1306 <dt><tt>const char *<b>ngi_mainnick</b>(const NickGroupInfo *<i>ngi</i>)</tt></dt>
1307 <dd>Returns the given nickname group's main nickname.</dd>
1308
1309 <dt><tt>NickGroupInfo *<b>get_ngi</b>(const NickInfo *<i>ni</i>)</tt>
1310 <br/><tt>NickGroupInfo *<b>get_ngi_id</b>(uint32 <i>id</i>)</tt></dt>
1311 <dd>Retrieves the <tt>NickGroupInfo</tt> record corresponding to the
1312 given <tt>NickInfo</tt> or ID value; if there is no corresponding
1313 record, a warning message is logged and <tt>NULL</tt> is returned.
1314 (Like any other database "get" routine, the structure must be "put"
1315 with <tt>put_nickgroupinfo()</tt> when no longer needed.)</dd>
1316
1317 <dt><tt>int <b>check_ngi</b>(const NickInfo *<i>ni</i>)</tt>
1318 <br/><tt>int <b>check_ngi_id</b>(uint32 <i>id</i>)</tt></dt>
1319 <dd>Returns whether there is a corresponding <tt>NickGroupInfo</tt>
1320 record for the given <tt>NickInfo</tt> or ID value, logging a
1321 warning message if not. (The
1322 <tt>put_<i>xxx</i>(get_<i>xxx</i>(...))</tt> is a common way of
1323 checking for the existence of a record, since the
1324 <tt>put_<i>xxx</i>()</tt> explicitly allow a <tt>NULL</tt>
1325 parameter.)</dd>
1326 </dl>
1327
1328 <p>The <tt>STANDALONE_NICKSERV</tt> define and (non-macro) utility
1329 functions are discussed in <a href="#s3-1-4">section 7-3-1-4</a>.</p>
1330
1331 <p class="backlink"><a href="#top">Back to top</a></p>
1332
1333
1334 <h5 class="subsubsubsection-title" id="s3-1-2">7-3-1-2. Overall module structure</h5>
1335
1336 <p>The overall structure of the NickServ module generally follows the same
1337 pattern as the OperServ module: variable and command declarations, database
1338 handling, <tt>PRIVMSG</tt> and other callbacks, and command routines.</p>
1339
1340 <p>The <tt>nickserv/main</tt> module uses two separate databases, one for
1341 <tt>NickInfo</tt> records and one for <tt>NickGroupInfo</tt> records. The
1342 database handling code is more or less straightforward, using <tt>hash.h</tt>
1343 to maintain the in-memory tables; however, since most of the record
1344 management routines take additional actions (for example, the "add" and
1345 "get" functions update the record's use count), the base hash functions are
1346 defined with a trailing underscore, like <tt>add_nickinfo_()</tt>, and the
1347 actual functions (like <tt>add_nickinfo()</tt>) are wrapped around these.
1348 NickServ exports all of the <tt>NickInfo</tt> and <tt>NickGroupInfo</tt>
1349 database functions, as well as a "put" function for each record type.</p>
1350
1351 <p>When saving the databases to persistent storage, the <tt>nicks[]</tt>
1352 array and <tt>mainnick</tt> field of <tt>NickGroupInfo</tt> records are not
1353 saved directly; rather, the main nickname itself is saved as a
1354 <tt>NICKMAX</tt>-sized buffer, and the nickname group is initialized with
1355 this nickname when first loaded (the array is subsequently filled in when
1356 the relevant <tt>NickInfo</tt> records are loaded).</p>
1357
1358 <p>NickServ keeps track of clients' status using callback functions for
1359 new clients, clients changing nickname, and disconnecting clients. The
1360 routines that do the actual processing, <tt>validate_user()</tt> (for a
1361 client starting to use a nickname) and <tt>cancel_user()</tt> (for a client
1362 no longer using a nickname), are located in <tt>util.c</tt>, discussed in
1363 <a href="#s3-1-4">section 7-3-1-4</a>.</p>
1364
1365 <p>The NickServ commands themselves tend to be fairly complex, especially
1366 when compared to the OperServ command handlers. This is in part due to the
1367 wide range of features available in NickServ, and in part due to the fact
1368 that NickServ and its system of registered nicknames are the primary way by
1369 which clients authenticate themselves, and as such must handle a variety of
1370 circumstances to maintain security, while other pseudoclients simply rely
1371 on the authorization flags set by NickServ. The following command handlers
1372 are particularly worthy of note:</p>
1373
1374 <dl>
1375 <dt><b><tt>do_help()</tt></b></dt>
1376 <dd>NickServ's commands include a number whose help text changes based
1377 on factors such as the requesting client's IRC operator status,
1378 features available in the IRC protocol in use, and NickServ
1379 configuration settings. The code to handle help requests is
1380 accordingly complex, with many commands unable to rely on the
1381 <tt>help_cmd()</tt> routine.</dd>
1382
1383 <dt><b><tt>do_register()</tt></b></dt>
1384 <dd>Just as NickServ is the gateway to the rest of Services' functions,
1385 the <tt>REGISTER</tt> command is the gateway to NickServ, providing
1386 one of the two methods by which a client can gain access to
1387 Services (the other being authentication to a previously registered
1388 nickname). The <tt>REGISTER</tt> handler must therefore be
1389 particularly careful to guard against abuse, both to prevent
1390 improper access to other Services commands and to prevent the
1391 <tt>REGISTER</tt> command itself from being abused by arbitrary
1392 clients. The command handler takes the following precautions
1393 before allowing a nickname to be registered:
1394 <ul>
1395 <li class="spaced">Prevents the command from being used by any
1396 particular client more than once every <tt>NSRegDelay</tt>
1397 seconds. This stops mass-registration of nicknames by
1398 automated clients, avoiding both the accompanying load on
1399 Services itself (more memory usage, more time spent looking
1400 up nicknames) and any undesirable side effects, such as the
1401 sending of automated E-mail to arbitrary address when mail
1402 authentication is in use (see <a href="#s3-5">section
1403 7-3-5</a>).</li>
1404 <li class="spaced">Prevents the command from being used by a client
1405 within <tt>NSInitialRegDelay</tt> seconds of connecting to
1406 the network. This prevents automated clients from getting
1407 around the <tt>NSRegDelay</tt> limitation by repeatedly
1408 connecting, issuing a <tt>REGISTER</tt> command, and
1409 disconnecting in rapid succession. (It is still possible
1410 to avoid the limitation by connecting a large number of
1411 clients at once, but as a practical matter it is impossible
1412 for NickServ to distinguish such attempts from ordinary
1413 registration requests, and the sudden presence of a large
1414 number of clients on the network should itself be an
1415 indication of trouble.)</li>
1416 <li class="spaced">Prevents "guest" nicknames from being
1417 registered, which could result in unauthenticated clients
1418 suddenly gaining Services access after a forced nickname
1419 change. (The check itself is performed by the
1420 <tt>do_reglink_check()</tt> earlier in <tt>main.c</tt>,
1421 a callback function attached to the "<tt>REGISTER/LINK
1422 check</tt>" callback; <tt>do_register()</tt> calls this
1423 callback via the <tt>reglink_check()</tt> function in
1424 <tt>util.c</tt>.)</li>
1425 <li class="spaced">Ensures that the nickname is not already
1426 registered. Ordinarily, if a nickname is registered then
1427 the client's <tt>User</tt> structure will have a pointer to
1428 the record in its <tt>ni</tt> field, but if the nickname is
1429 missing a corresponding nickname group (a database error
1430 unless the nickname is forbidden), the <tt>ni</tt> field
1431 will be <tt>NULL</tt> and the <tt>ngi</tt> field will be
1432 set to the constant <tt>NICKGROUPINFO_INVALID</tt>, so that
1433 combination is checked for as well. Also, just in case,
1434 <tt>do_register()</tt> performs a final check by accessing
1435 the database directly, to ensure that the nickname is not
1436 registered in duplicate.</li>
1437 <li class="spaced">Checks that the E-mail address, if given, is (1)
1438 syntactically valid and (2) not disallowed due to a
1439 <tt>RejectEmail</tt> configuration directive.</li>
1440 <li class="spaced">Prevents more than <tt>NSRegEmailMax</tt>
1441 nicknames from being registered to the same address, again
1442 to avoid undue load on Services from a registration flood.
1443 This check calls <tt>count_nicks_with_email()</tt> to
1444 actually count nicknames; this routine has to search the
1445 entire nickname database, which can take a significant
1446 amount of time if many nicknames are registered, so this
1447 check is performed last.</li>
1448 <li class="spaced">As an adjunct to the previous check (and
1449 regardless of the setting of <tt>NSRegEmailMax</tt>), also
1450 prevents a nickname from being registered if the E-mail
1451 address given is already in use by another nickname which
1452 is awaiting mail authentication; this acts as a further
1453 guard to prevent a particular mail address from getting
1454 "mailbombed" by multiple registration requests that make it
1455 through the previous checks.</li>
1456 </ul></dd>
1457
1458 <dt><b><tt>do_dropemail()</tt></b>
1459 <br/><b><tt>do_dropemail_confirm()</tt></b></dt>
1460 <dd>The <tt>DROPEMAIL</tt> and <tt>DROPEMAIL-CONFIRM</tt> commands are
1461 the only two commands in Services that require state to be kept
1462 specifically for those commands. Due to the potential for data
1463 loss through an erroneous <tt>DROPEMAIL</tt> command, some form of
1464 confirmation was desired, such as an "Are you sure?" requester in
1465 response to a user deleting a file in a GUI. Since Services'
1466 interface is limited to single-line commands, however, this can
1467 only be accomplished through two commands, the second of which
1468 (<tt>DROPEMAIL-CONFIRM</tt>) serves to confirm the action requested
1469 by the first (<tt>DROPEMAIL</tt>). In order for this to be
1470 effective, the <tt>DROPEMAIL-CONFIRM</tt> handler must know which
1471 commands have been sent by whom, so that clients cannot send
1472 arbitrary <tt>DROPEMAIL-CONFIRM</tt> commands to get around the
1473 confirmation check. This is accomplished through the file-local
1474 <tt>dropemail_buffer[]</tt> array, which holds the most recently
1475 issued, unconfirmed <tt>DROPEMAIL</tt> commands. (A single state
1476 record stored in the <tt>User</tt> structure was another
1477 possibility, but one that was discarded to avoid bloat in that
1478 structure, particularly since the vast majority of clients would
1479 never use the command anyway.) When a valid <tt>DROPEMAIL</tt>
1480 command is given, the client is told the number of nicknames that
1481 would be deleted, and the given mask is stored in the buffer array,
1482 with the oldest unconfirmed mask removed if no slots are empty. A
1483 <tt>DROPEMAIL-CONFIRM</tt> for the same mask will then locate the
1484 appropriate buffer slot, ensure that the same client sent both
1485 commands and that the elapsed time between the two commands is not
1486 too long (as defined by the <tt>NSDropEmailExpire</tt> option), and
1487 performs the actual nickname deletion.</dd>
1488
1489 <dt><tt><b>do_info()</b></tt></dt>
1490 <dd>The <tt>INFO</tt> command has the ability to show extended
1491 information about a nickname with the option <tt>ALL</tt> (only
1492 available to the nickname owner or Services administrators).
1493 However, not all nicknames have any additional information to be
1494 displayed. To prevent the "use <tt>ALL</tt> for more information"
1495 message from being appended if there is not actually anything else
1496 to show, the <tt>INFO</tt> command handler uses a method inspired
1497 by super-user privilege checks in the Linux kernel, which keeps
1498 track of whether a process has taken advantage of those privileges.
1499 When the macro <tt>CHECK_SHOW_ALL</tt> is included in a conditional
1500 test, it will evaluate to true when the <tt>ALL</tt> option is
1501 present (and the client has permission to use it), but a separate
1502 flag variable, <tt>used_all</tt>, will also be set regardless of
1503 the presence of <tt>ALL</tt>; the routine can then determine
1504 whether there were any items that would have been displayed if
1505 <tt>ALL</tt> was given. As noted in the source code comments, the
1506 macro should be the last test in any conditional expression which
1507 uses it, to prevent <tt>used_all</tt> from being set for an item
1508 that will not actually be displayed due to a subsequent test.</dd>
1509
1510 <dt><tt><b>do_set()</b></tt>
1511 <br/><tt><b>do_unset()</b></tt></dt>
1512 <dd>As the <tt>SET</tt> and <tt>UNSET</tt> commands (<tt>SET</tt> in
1513 particular) have a large number of options, they are defined in a
1514 separate source file, <tt>set.c</tt>. See
1515 <a href="#s3-1-3">section 7-3-1-3</a> for details.</dd>
1516 </dl>
1517
1518 <p>NickServ also includes a debug command enabled by the
1519 <tt>DEBUG_COMMANDS</tt> preprocessor symbol: <tt>LISTNICK</tt>, which
1520 displays the <tt>NickInfo</tt> and (if present) <tt>NickGroupInfo</tt> data
1521 for a given nickname.</p>
1522
1523 <p>In addition to the ordinary module setup code, the
1524 <tt>nickserv/main</tt> module supports two command-line options. One,
1525 <tt>-encrypt-all</tt>, is recognized by the Services core; NickServ's
1526 <tt>init_module()</tt> routine checks the corresponding global flag,
1527 <tt>encrypt_all</tt> and, if it is set, encrypts all nicknames using the
1528 encryption type specified by the core's <tt>EncryptionType</tt> setting.
1529 The other option, <tt>-clear-nick-email</tt>, is NickServ-specific, and is
1530 handled by <tt>do_command_line()</tt>, a callback function for the core's
1531 "<tt>command line</tt>" callback; when the option is encountered, the
1532 callback function clears the E-mail address from all nickname groups.</p>
1533
1534 <p>As several messages used by NickServ can change based on configuration
1535 options or the features available in the IRC server, the initialization and
1536 cleanup code (as well as the reconfiguration handler,
1537 <tt>do_reconfigure()</tt>) call <tt>mapstring()</tt> to adjust the messages
1538 appropriately. The commands <tt>REGISTER</tt>,
1539 <tt>DROPEMAIL</tt>/<tt>DROPEMAIL-CONFIRM</tt>, and <tt>GETPASS</tt> can
1540 also be disabled by configuration options; the commands are disabled by
1541 setting the <tt>name</tt> field of the corresponding <tt>Command</tt>
1542 structure to the empty string, so that it will not be found when the
1543 command table is searched. Pointers to the structures are saved in
1544 file-local variables so that the names can be restored at reconfiguration
1545 or module cleanup time.</p>
1546
1547 <p class="backlink"><a href="#top">Back to top</a></p>
1548
1549
1550 <h5 class="subsubsubsection-title" id="s3-1-3">7-3-1-3. The <tt>SET</tt> and <tt>UNSET</tt> commands</h5>
1551
1552 <p>The handlers for the <tt>SET</tt> and <tt>UNSET</tt> commands,
1553 <tt>do_set()</tt> and <tt>do_unset()</tt> in <tt>set.c</tt>, work much like
1554 miniature versions of the top-level NickServ message handler
1555 <tt>nickserv()</tt>, in that they check which option name was used with the
1556 command and call an appropriate subroutine to do the actual work. However,
1557 the <tt>do_set()</tt> routine parses the option parameters itself, rather
1558 than leave such parsing to the individual routines (<tt>UNSET</tt> does not
1559 take any additional parameters, so no such parsing is needed); for this
1560 reason, the setup code in <tt>do_set()</tt> is more complex than that in
1561 <tt>nickserv()</tt>, since the <tt>INFO</tt> option treats the entire line
1562 as a single parameter, <tt>HIDE</tt> takes two single-word parameters
1563 separated by a space, and the other options take a single one-word
1564 parameter.</p>
1565
1566 <p>Additionally, both <tt>SET</tt> and <tt>UNSET</tt> can be used by
1567 Services administrators to set options for other users' nicknames. For
1568 this reason, the individual option-setting routines take both a
1569 <tt>User&nbsp;*</tt> and a <tt>NickInfo&nbsp;*</tt> parameter, where the
1570 <tt>NickInfo&nbsp;*</tt> parameter is the nickname whose options are to be
1571 changed (if the client giving the command is not a Services administrator
1572 or does not give a target nickname, this will simply be equal to the
1573 <tt>ni</tt> field of the <tt>User</tt> structure). <i>Implementation note:
1574 This raises an interesting problem&mdash;how does an option's handler
1575 routine tell the difference between <tt>SET <i>option</i></tt>, <tt>SET
1576 !MyNick <i>option</i></tt>, and <tt>SET !OtherNick <i>option</i></tt> when
1577 sending result messages? The simple answer is that it doesn't: all option
1578 handlers use the "your nick" message style, as mentioned in
1579 <a href="../d.html">Appendix D of the user's manual</a>. If implemented,
1580 it would probably be reasonable to ignore the distinction between the
1581 <tt>SET <i>option</i></tt> and <tt>SET !MyNick <i>option</i></tt> cases,
1582 and simply judge which message to use by comparing the <tt>NickInfo</tt>
1583 parameter with the <tt>ni</tt> field of the client's <tt>User</tt>
1584 structure.</i></p>
1585
1586 <p>The option handlers themselves are simple for the most part, checking
1587 the option value given and setting or clearing the relevant flag or field
1588 in the <tt>NickInfo</tt> structure or its associated <tt>NickGroupInfo</tt>
1589 structure. Routines which deserve special mention are:</p>
1590
1591 <dl>
1592 <dt><b><tt>do_set_password()</tt></b></dt>
1593 <dd>The password setting itself is straightforward (note that the
1594 memory containing the cleartext password and the temporary copy of
1595 the encrypted password is cleared as soon as it is no longer
1596 needed); however, the routine first checks the
1597 <tt>NSSecureAdmins</tt> option, and disallows the change if the
1598 target is a (different) Services administrator and the command
1599 sender is not the Services super-user.</dd>
1600
1601 <dt><b><tt>do_set_email()</tt></b></dt>
1602 <dd>This routine makes several checks mostly related to mail
1603 authentication before allowing the E-mail address to be changed:
1604 <ul>
1605 <li>The address must be a valid E-mail address.</li>
1606 <li>The address must not be rejected by a <tt>RejectEmail</tt>
1607 configuration directive.</li>
1608 <li>The address must not be in use by a nickname awaiting mail
1609 authentication (as with <tt>REGISTER</tt>).</li>
1610 <li>The number of nicknames currently using the address must be
1611 less than <tt>NSRegEmailMax</tt>, if set. (Note that if
1612 the current nickname's group contains other linked
1613 nicknames, the E-mail address change can cause the nickname
1614 total to exceed <tt>NSRegEmailMax</tt>. This is not seen as
1615 a significant problem, and it avoids the opposite problem in
1616 which a user who somehow exceeded the limit would no longer
1617 be able to change their E-mail address at all.)</li>
1618 <li>The time since the last successful <tt>SET EMAIL</tt> must be
1619 at least <tt>NSSetEmailDelay</tt> seconds, if set.</li>
1620 </ul>
1621 If the above checks all pass, the change is performed, and if the
1622 client used to have the <tt>NA_IDENT_NOMAIL</tt> status and an
1623 E-mail address was set, the status is changed to
1624 <tt>NA_IDENTIFIED</tt>. The routine also features its own
1625 callback, "<tt>SET EMAIL</tt>", used by the mail authentication
1626 code. Note that this routine does <i>not</i> check the
1627 <tt>NSRequireEmail</tt> configuration option, and assumes that if
1628 it is passed a <tt>NULL</tt> value, indicating that the address
1629 should be unset, then that is valid. (In fact, <tt>do_unset()</tt>
1630 checks <tt>NSRequireEmail</tt> before calling
1631 <tt>do_set_email()</tt>.)</dd>
1632
1633 <dt><b><tt>do_set_timezone()</tt></b></dt>
1634 <dd><tt>SET TIMEZONE</tt> allows the time zone to be specified as
1635 either a literal time offset (-5, +6:30, etc.) or a time zone
1636 name. Time zone names (other than "GMT+/-<i>n</i>" and
1637 "UTC+/-<i>n</i>", which are treated as literal offsets) are parsed
1638 using the <tt>timezones[]</tt> table defined just above the
1639 <tt>do_set_timezone()</tt> routine itself, which (hopefully)
1640 includes most common time zones; the table can of course be
1641 modified to include other time zones as particular networks
1642 desire. Once the the time zone has been set, a message is sent to
1643 the calling client giving the current time in the resulting time
1644 zone; however, this is tricky if the calling client is a Services
1645 administrator changing the setting for another nickname, because
1646 <tt>strftime_lang()</tt> always uses the time zone setting of the
1647 nickname used to select the language. To get around this, the
1648 routine determines the difference between the calling nickname's
1649 time zone and the target nickname's time zone, adjusting the
1650 timestamp passed to <tt>strftime_lang()</tt> by that amount
1651 (multiplied by 60, since the <tt>timezone</tt> field is specified
1652 in minutes). Incidentally, support for "daylight saving time"
1653 as used in some countries was deliberately omitted, partly due to
1654 the difficulty of supporting the various systems used in different
1655 countries, and partly because the details of such systems are
1656 highly dependent upon each country's political landscape and can
1657 change at any time (witness the abrupt extension to DST proposed,
1658 and eventually implemented, in the United States of America in
1659 2006).</dd>
1660 </dl>
1661
1662 <p class="backlink"><a href="#top">Back to top</a></p>
1663
1664
1665 <h5 class="subsubsubsection-title" id="s3-1-4">7-3-1-4. NickServ utility routines</h5>
1666
1667 <p>Most of the utility routines used by NickServ are collected in the file
1668 <tt>util.c</tt>. This file has two functions: aside from providing utility
1669 functions to NickServ itself (several of which are exported for use by
1670 other modules), it can also be <tt>#include</tt>'d in an external source
1671 file to provide definitions of the four routines <tt>new_nickinfo()</tt>,
1672 <tt>free_nickinfo()</tt>, <tt>new_nickgroupinfo()</tt>, and
1673 <tt>free_nickgroupinfo()</tt>, so that such files do not have to define
1674 similar routines themselves. This latter mode is activated by defining
1675 the <tt>STANDALONE_NICKSERV</tt> preprocessor symbol, as documented in the
1676 comments at the top of <tt>util.c</tt>. In this case, only the four
1677 routines mentioned above are defined, with the rest of the file commented
1678 out using <tt>#ifndef</tt>; additionally, the <tt>new_nickgroupinfo()</tt>
1679 routine does not check for the presence of the nickname group IDs it
1680 generates, as it cannot assume that <tt>get_nickgroupinfo()</tt> is
1681 available.</p>
1682
1683 <p>With respect to its primary use as part of NickServ, <tt>util.c</tt>
1684 defines the following routines:</p>
1685
1686 <dl>
1687 <dt><tt>NickInfo *<b>new_nickinfo</b>()</tt></dt>
1688 <dd>Returns a pointer to a newly-allocated and initialized
1689 <tt>NickInfo</tt> structure. (For creating a new record in the
1690 database, <tt>makenick()</tt> is preferred; see below.)</dd>
1691
1692 <dt><tt>void <b>free_nickinfo</b>(NickInfo *<i>ni</i>)</tt></dt>
1693 <dd>Frees the given <tt>NickInfo</tt> structure and all associated
1694 data. (See <tt>delnick()</tt> below for removing a nickname
1695 record from the database.)</dd>
1696
1697 <dt><tt>NickGroupInfo *<b>new_nickgroupinfo</b>(const char *<i>seed</i>)</tt></dt>
1698 <dd>Returns a pointer to a newly-allocated and initialized
1699 <tt>NickGroupInfo</tt> structure. If <tt><i>seed</i></tt> is not
1700 <tt>NULL</tt>, then it is used to generate an initial ID value for
1701 the nickname group; if that ID value is used, new values are
1702 randomly generated until an unused one is found. (If the code
1703 loops <tt>NEWNICKGROUP_TRIES</tt> times without finding an unused
1704 value, an error is returned; assuming a good random number
1705 generator, the default value of 1000 should ensure success on
1706 typical databases. <tt>NEWNICKGROUP_TRIES</tt> is defined in
1707 <tt>ns-local.h</tt>.) If <tt><i>seed</i></tt> is <tt>NULL</tt>,
1708 then the new nickname group's ID is left at zero.</dd>
1709
1710 <dt><tt>void <b>free_nickgroupinfo</b>(NickGroupInfo *<i>ngi</i>)</tt></dt>
1711 <dd>Frees the given <tt>NickGroupInfo</tt> structure and all associated
1712 data. (See <tt>delgroup()</tt> below for removing a nickname group
1713 and all its nicknames from the database.)</dd>
1714
1715 <dt><tt>NickGroupInfo *<b>_get_ngi</b>(NickInfo *<i>ni</i>,
1716 const char *<i>file</i>, int <i>line</i>)</tt>
1717 <br/><tt>NickGroupInfo *<b>_get_ngi_id</b>(uint32 <i>id</i>,
1718 const char *<i>file</i>, int <i>line</i>)</tt></dt>
1719 <dd>Implement the <tt>get_ngi()</tt> and <tt>get_ngi_id()</tt> macros,
1720 respectively. <tt><i>file</i></tt> and <tt><i>line</i></tt> are
1721 the source file and line from which the function was called, and
1722 are filled in by the corresponding macro with <tt>__FILE__</tt> and
1723 <tt>__LINE__</tt>.</dd>
1724
1725 <dt><tt>int <b>has_identified_nick</b>(const User *<i>u</i>, uint32 <i>group</i>)</tt></dt>
1726 <dd>Returns whether the given client has identified for the nickname
1727 group indicated by <tt><i>group</i></tt>.</dd>
1728
1729 <dt><tt>int <b>reglink_check</b>(User *<i>u</i>, const char *<i>nick</i>,
1730 char *<i>password</i>, char *<i>email</i>)</tt></dt>
1731 <dd>Calls the "<tt>REGISTER/LINK check</tt>" callback and returns its
1732 result. (A utility function is used rather than directly calling
1733 <tt>call_callback_4()</tt> because the <tt>nickserv/link</tt>
1734 module needs to make use of the callback as well, and the module
1735 system does not allow one module to call another's callbacks (which
1736 would be bad design in any case).</dd>
1737
1738 <dt><tt>void <b>update_userinfo</b>(const User *<i>u</i>)</tt></dt>
1739 <dd>Updates the user information for the client's nickname. The
1740 <tt>NickInfo</tt> fields <tt>last_usermask</tt>,
1741 <tt>last_realmask</tt>, and <tt>last_realname</tt> are set from
1742 the corresponding fields of the <tt>User</tt> structure, and the
1743 <tt>last_seen</tt> field is set to the current time.
1744 <tt><i>u</i>-&gt;ni</tt> is assumed to be non-<tt>NULL</tt>.</dd>
1745
1746 <dt><tt>int <b>validate_user</b>(User *<i>u</i>)</tt></dt>
1747 <dd>Sets the <tt>ni</tt> and <tt>ngi</tt> fields of the <tt>User</tt>
1748 structure to point to the <tt>NickInfo</tt> and associated
1749 <tt>NickGroupInfo</tt>, if any, for the client's nickname (if an
1750 error occurs looking up the nickname group, <tt><i>u</i>-&gt;ni</tt>
1751 is set to <tt>NULL</tt> and <tt><i>u</i>-&gt;ngi</tt> is set to
1752 <tt>NICKGROUP_INVALID</tt>); then compares the client's information
1753 with the nickname data and determines what level of access for the
1754 nickname should be granted to the client. Returns 1 if the client
1755 is granted either <tt>NA_IDENTIFIED</tt> or <tt>NA_RECOGNIZED</tt>
1756 access, otherwise zero.
1757
1758 <p>This routine, along with the <tt>REGISTER</tt> command handler,
1759 is one of the two "points of entry" into Services, and as such is a
1760 critical point for Services security. This is particularly
1761 relevant for the section of code conditionally granting full
1762 (<tt>NA_IDENTIFIED</tt>) nickname access; while
1763 <tt>has_identified_nick()</tt>, mentioned above, operates purely on
1764 data which has been seen since Services started (specifically, the
1765 list of nicknames the client is known to have become identified
1766 for, maintained by <tt>set_identified()</tt>) and is comparatively
1767 safe, the second check, which matches the servicestamp, username,
1768 and hostname of the last client to identify with those of the
1769 current client, needs special attention to ensure that it does not
1770 allow clients to gain improper access. As noted in the comments in
1771 that section of code, the servicestamp provides a fairly high level
1772 of protection on servers which support it natively, while that
1773 level is reduced for servers which do not (such servers are rare
1774 nowadays). The entire section of code can be disabled with the
1775 <tt>NoSplitRecovery</tt> configuration option for added security.</p>
1776
1777 <p>If the client is determined not to have identified for the
1778 nickname previously, the routine continues, determining whether to
1779 give <tt>NA_RECOGNIZED</tt> access. "Recognized" status is only
1780 implemented by access lists (see <a href="#s3-2">section 7-3-2</a>),
1781 and if the corresponding module is not loaded, the
1782 <tt>NA_RECOGNIZED</tt> flag will never be set on any nickname,
1783 except when set along with <tt>NA_IDENTIFIED</tt>. Likewise, if a
1784 nickname's <tt>NF_SECURE</tt> flag is set, then
1785 <tt>NA_RECOGNIZED</tt> will not be set (and zero will be returned
1786 from the routine) even if the client is in fact recognized.</p>
1787
1788 <p>If the client is not identified or recognized for the nickname,
1789 <tt>validate_user()</tt> checks whether the client should be
1790 killed or nick-changed, setting an appropriate timeout or calling
1791 the collide routines (see <a href="#s3-1-5">section 7-3-1-5</a>
1792 below) depending on the nickname group settings. However, if the
1793 client was recognized (which will only be true if the nickname has
1794 the <tt>SECURE</tt> option set and thus <tt>NA_RECOGNIZED</tt> was
1795 not set), the kill checks are not performed, allowing the client to
1796 identify at its leisure.</p>
1797
1798 <p>Finally, the routine checks the nickname's expiration time, and
1799 if it is due to expire "soon" (as defined by the
1800 <tt>NSExpireWarning</tt> configuration option), a warning notice is
1801 sent to the client.</p></dd>
1802
1803 <dt><tt>void <b>cancel_user</b>(User *<i>u</i>)</tt></dt>
1804 <dd>Updates a client's nickname data when the client stops using the
1805 nickname. The <tt>last_seen</tt> field is updated if the client
1806 was either identified or recognized; the <tt>authstat</tt> field
1807 is cleared along with temporary status flags in the <tt>status</tt>
1808 field; an enforcer is introduced if the client was killed or
1809 nick-changed (see <a href="#s3-1-5">section 7-3-1-5</a>); the
1810 <tt>cancel user</tt>" callback is called; and any active nick
1811 collide timeouts are removed. The <tt>ni</tt> and <tt>ngi</tt>
1812 fields of the client's <tt>User</tt> structure are also reset to
1813 <tt>NULL</tt>.</dd>
1814
1815 <dt><tt>void <b>set_identified</b>(User *<i>u</i>)</tt></dt>
1816 <dd>Marks the given client as having identified for the nickname it is
1817 currently using. In addition to setting the authentication status
1818 to <tt>NA_IDENTIFIED&nbsp;| NA_RECOGNIZED</tt> and updating the
1819 nickname's <tt>id_stamp</tt> field, the routine adds the nickname
1820 group ID to the list of nickname groups for which the client has
1821 identified, stored in the <tt>User</tt> structure and checked by
1822 <tt>has_identified_nick()</tt>.</dd>
1823
1824 <dt><tt>NickInfo *<b>makenick</b>(const char *<i>nick</i>,
1825 NickGroupInfo **<i>nickgroup_ret</i>)</tt></dt>
1826 <dd>Creates a new <tt>NickInfo</tt> record with the given nickname,
1827 adds it to the database, and returns a pointer to the new record.
1828 If <tt><i>nickgroup_ret</i></tt> is not <tt>NULL</tt>, then a new
1829 <tt>NickGroupInfo</tt> record is also created for the nickname,
1830 the nickname's <tt>nickgroup</tt> field is set accordingly, and a
1831 pointer to the <tt>NickGroupInfo</tt> record (which is also added
1832 to the database) is stored in the variable pointed to by
1833 <tt><i>nickgroup_ret</i></tt>. Returns <tt>NULL</tt> on error.</dd>
1834
1835 <dt><tt>int <b>delnick</b>(NickInfo *<i>ni</i>)</tt></dt>
1836 <dd>Removes the given nickname from the database and frees all
1837 resources used by the <tt>NickInfo</tt> structure. If the nickname
1838 was the last of its group, then the nickname group is deleted as
1839 well. Returns nonzero on success, zero on error.</dd>
1840
1841 <dt><tt>int <b>delgroup</b>(NickGroupInfo *<i>ngi</i>)</tt></dt>
1842 <dd>Removes the given nickname group from the database, along with all
1843 associated nicknames. Returns nonzero on success, zero on error.</dd>
1844
1845 <dt><tt>int <b>drop_nickgroup</b>(NickGroupInfo *<i>ngi</i>,
1846 const User *<i>u</i>, const char *<i>dropemail</i>)</tt></dt>
1847 <dd>Removes the given nickname group from the database, like
1848 <tt>delgroup()</tt>, but first log information about the nicknames
1849 to be deleted. <tt><i>u</i></tt> is the <tt>User</tt> structure
1850 for the client that sent the command resulting in the deletion.
1851 <tt><i>dropemail</i></tt> should be:
1852 <ul>
1853 <li><tt>NULL</tt> if the call is because of a <tt>DROP</tt> command
1854 from the nickname owner;</li>
1855 <li><tt>PTR_INVALID</tt> if the call is because of a <tt>DROPNICK</tt>
1856 command from a Services administrator;</li>
1857 <li>for a <tt>DROPEMAIL</tt> command, the parameter (address
1858 wildcard) used with the command.</li>
1859 </ul></dd>
1860
1861 <dt><tt>void <b>suspend_nick</b>(NickGroupInfo *<i>ngi</i>,
1862 const char *<i>reason</i>, const char *<i>who</i>,
1863 const time_t <i>expires</i>)</tt></dt>
1864 <dd>Suspends the given nickname group, copying the parameters
1865 <tt><i>reason</i></tt>, <tt><i>who</i></tt>, and
1866 <tt><i>expires</i></tt> into the suspension data fields. (If
1867 <tt><i>expires</i></tt> is zero, then the suspension will not
1868 expire.)</dd>
1869
1870 <dt><tt>void <b>unsuspend_nick</b>(NickGroupInfo *<i>ngi</i>, int <i>set_time</i>)</tt></dt>
1871 <dd>Cancels the suspension on the given nickname group. If
1872 <tt><i>set_time</i></tt> is nonzero, the last-seen time of each
1873 nickname in the group will be updated according to
1874 <tt>NSSuspendGrace</tt> to prevent the nickname from expiring for
1875 that length of time (if <tt>NSSuspendGrace</tt> or <tt>NSExpire</tt>
1876 are not set, or if the nickname already has enough time before
1877 expiration, the last-seen time will not be changed).</dd>
1878
1879 <dt><tt>int <b>nick_check_password</b>(User *<i>u</i>, NickInfo *<i>ni</i>,
1880 const char *<i>password</i>, const char *<i>command</i>,
1881 int <i>failure_msg</i>)</tt></dt>
1882 <dd>Performs a password check for a nickname as part of a NickServ
1883 command. If the password is incorrect or an error occurs when
1884 checking, a notice will be sent to the client; a <tt>WALLOPS</tt>
1885 will also be sent for repeated bad password attempts on the same
1886 nickname. <tt><i>u</i></tt> is the <tt>User</tt> structure for
1887 the client that issued the command; <tt><i>ni</i></tt> is the
1888 <tt>NickInfo</tt> structure for the nickname whose password is
1889 being checked; <tt><i>password</i></tt> is the password given by
1890 the client, <tt><i>command</i></tt> is the name of the command
1891 being executed; and <tt><i>failure_msg</i></tt> is the index of the
1892 message (language string) to be sent if an error occurs when
1893 checking the password.</dd>
1894
1895 <dt><tt>int <b>count_nicks_with_email</b>(const char *<i>email</i>)</tt></dt>
1896 <dd>Counts and returns the number of registered nicknames with the
1897 given E-mail address. If a nickname has the given address but it
1898 is awaiting mail authentication, the value returned is negative;
1899 for example, if there are five nicknames using a given address but
1900 the address is not authenticated, -5 would be returned. Note that
1901 this function must scan through the entire nickname database, so
1902 care should be taken not to call it too frequently.</dd>
1903 </dl>
1904
1905 <p><tt>util.c</tt> also defines initialization and cleanup routines,
1906 <tt>init_util()</tt> and <tt>exit_util()</tt>, which take care of
1907 registering and unregistering the callbacks used by various utility
1908 functions. The routines are called as part of the <tt>nickserv/main</tt>
1909 module iniitialization and cleanup.</p>
1910
1911 <p class="backlink"><a href="#top">Back to top</a></p>
1912
1913
1914 <h5 class="subsubsubsection-title" id="s3-1-5">7-3-1-5. Nickname colliding</h5>
1915
1916 <p>In the general sense, a "nickname collision" is what happens when a
1917 client on an IRC network attempts to use a nickname that is already in use
1918 by another client. The original (RFC 1459) solution to this was to kill
1919 both clients, but with the advent of timestamps, most modern servers only
1920 kill one or the other depending on the timestamps of the two colliding
1921 clients. Early versions of Services took advantage of this behavior to
1922 implement kill protection: by introducing an "enforcer" pseudoclient with
1923 an appropriate timestamp, the old client would be killed and would not be
1924 able to reconnect with the same nickname.</p>
1925
1926 <p>With respect to Services, then, "nickname colliding" is the act of
1927 forcing a client to stop using a particular nickname. While the nickname
1928 collision method itself has been abandoned, both to avoid depending on
1929 particular collision semantics and to provide a more meaningful disconnect
1930 message to the client ("Nick kill enforced" rather than an arbitrary server
1931 collision message), and although many modern IRC servers allow Services to
1932 forcibly change a client's nickname without going as far as disconnecting
1933 the client altogether, the term "colliding" is still used to refer to this
1934 set of actions.</p>
1935
1936 <p>Nickname colliding functionality is provided by the file
1937 <tt>collide.c</tt>. This file provides two methods of colliding nicknames:
1938 directly, or via timeouts. The nickname colliding code also has its own
1939 initialization and cleanup functions (<tt>init_collide()</tt> and
1940 <tt>exit_collide()</tt>), which are called from the <tt>nickserv/main</tt>
1941 module initialization and cleanup routines.</p>
1942
1943 <p>The following routines are used when colliding nicknames directly:</p>
1944
1945 <dl>
1946 <dt><tt>void <b>collide_nick</b>(NickInfo *<i>ni</i>, int <i>from_timeout</i>)</tt></dt>
1947 <dd>Collides the given nickname, either killing the client using the
1948 nickname or forcibly changing the client's nickname to a "guest"
1949 nickname depending on configuration settings.
1950 <tt><i>from_timeout</i></tt> is used internally with collide
1951 timeouts, and should always be zero when called externally. This
1952 routine automatically calls <tt>introduce_enforcer()</tt> after
1953 the client has been killed or nick-changed (in the case of a
1954 forced nickname change, the enforcer is introduced by
1955 <tt>cancel_user()</tt> upon receipt of the <tt>NICK</tt> message
1956 indicating that the client's nickname has been changed). Any
1957 pending nickname collide or "433" timeouts (see below) on the
1958 nickname are cancelled by thie routine.</dd>
1959
1960 <dt><tt>void <b>introduce_enforcer</b>(NickInfo *<i>ni</i>)</tt></dt>
1961 <dd>Introduces an enforcer pseudoclient for the given nickname, to
1962 prevent other clients from using the nickname. This routine
1963 automatically adds a timeout to call <tt>release_nick()</tt> after
1964 <tt>NSReleaseTimeout</tt> seconds have passed.</dd>
1965
1966 <dt><tt>void <b>release_nick</b>(NickInfo *<i>ni</i>, int <i>from_timeout</i>)</tt></dt>
1967 <dd>Removes the enforcer pseudoclient for the given nickname, allowing
1968 other clients to use it again. As with <tt>collide_nick()</tt>,
1969 <tt><i>from_timeout</i></tt> is used internally with collide
1970 timeouts, and should always be zero when called externally. Any
1971 pending release timeouts on the nickname are cancelled by this
1972 routine.</dd>
1973 </dl>
1974
1975 <p>Callers can also establish timeouts to collide or release a nick after
1976 a certain time. To avoid each caller having to include its own timeout
1977 handlers, <tt>collide.c</tt> provides two wrapper routines around the
1978 generic timeout functions:</p>
1979
1980 <dl>
1981 <dt><tt>void <b>add_ns_timeout</b>(NickInfo *<i>ni</i>, int <i>type</i>,
1982 time_t <i>delay</i>)</tt></dt>
1983 <dd>Adds a timeout of the given type on the given nickname to occur in
1984 <tt><i>delay</i></tt> seconds. <tt><i>type</i></tt> can be any of
1985 the following:
1986 <ul>
1987 <li><b><tt>TO_COLLIDE</tt>:</b> A timeout for colliding a nickname
1988 (<tt>collide_nick()</tt> will be called).</li>
1989 <li><b><tt>TO_RELEASE</tt>:</b> A timeout for releasing the hold on
1990 a nickname (<tt>release_nick()</tt> will be called).</li>
1991 <li><b><tt>TO_SEND_433</tt>:</b> A timeout for sending the client
1992 using the nickname a "433" error message. (433 is the code
1993 for the <tt>ERR_NICKCOLLISION</tt> reply to a <tt>NICK</tt>
1994 message, and will cause most interactive client software to
1995 request a new nickname from the user. However, some server
1996 software has been known to disallow servers from sending
1997 433 replies to remote clients.)</li>
1998 </ul></dd>
1999
2000 <dt><tt>void <b>rem_ns_timeout</b>(NickInfo *<i>ni</i>, int <i>type</i>,
2001 int <i>del_to</i>)</tt></dt>
2002 <dd>Removes any timeout of the given type on the given nickname;
2003 <tt><i>ni</i></tt> can be <tt>NULL</tt> to cause timeouts on all
2004 nicknames (of the given type) to be removed. <tt><i>type</i></tt>
2005 can be any of the type values used with <tt>add_ns_timeout()</tt>,
2006 or -1 to remove timeouts of all types. <tt><i>del_to</i></tt>
2007 should always be nonzero when called externally (the parameter is
2008 used for calling from within a timeout function, where it is not
2009 necessary to delete the <tt>Timeout</tt> structure as well).</dd>
2010 </dl>
2011
2012 <p>Each of the three timeout types has its own timeout function:
2013 <tt>timeout_collide()</tt>, <tt>timeout_release()</tt>, and
2014 <tt>timeout_send_433()</tt>. The timeout functions check for any change
2015 in status (such as identification for the nickname) before performing
2016 their respective functions.</p>
2017
2018 <p class="backlink"><a href="#top">Back to top</a></p>
2019
2020
2021 <h4 class="subsubsection-title" id="s3-2">7-3-2. Nickname access lists</h4>
2022
2023 <p>Nickname access lists are managed by the <tt>nickserv/access</tt>
2024 module, defined in <tt>access.c</tt>. The module is quite simple,
2025 consisting of a database table, two callback functions, and a NickServ
2026 command (<tt>ACCESS</tt>). For simplicity, the module (along with other
2027 NickServ submodules) assumes the presence of the <tt>nickserv/main</tt>
2028 module rather than explicitly importing every required NickServ symbol,
2029 although the module's initialization does look up the
2030 <tt>nickserv/main</tt> module handle for use in adding the requisite
2031 callbacks and the <tt>ACCESS</tt> command.</p>
2032
2033 <p>One unusual feature is the use of a static buffer for reading and
2034 writing database records. Since the access list itself is stored in the
2035 corresponding nickname group's <tt>NickGroupInfo</tt> structure as an
2036 array, the entries must be extracted and made available to the database
2037 subsystem in an independent (normalized) format. This is done by using a
2038 <tt>{<i>nickgroup-ID</i>,<i>access-mask</i>}</tt> record format, and
2039 providing a single record buffer. When loading data from persistent
2040 storage, the table's <tt>newrec()</tt> function returns a pointer to this
2041 buffer, taking advantage of the fact that only one record is loaded at a
2042 time (see <a href="6.html#s2-1">section 6-2-1</a>); the <tt>insert()</tt>
2043 routine then looks up the nickname group stored in the buffer and appends
2044 the given access mask to that nickname group's access list, while the
2045 <tt>freerec()</tt> routine frees the access mask string. When saving data,
2046 the <tt>first()</tt> and <tt>next()</tt> routines call
2047 <tt>first_nickgroupinfo()</tt> and <tt>next_nickgroupinfo()</tt> in turn,
2048 looping through each access mask of each nickname group.</p>
2049
2050 <p>Ideally, the access lists would be stored in memory in the same fashion,
2051 as a distinct table using the nickname group ID as a key. However, since
2052 the current database implementation does not provide an efficient way to
2053 look up records matching arbitrary criteria (like a <tt>SELECT</tt>
2054 statement in SQL), and since problems would ensue when trying to save the
2055 data using the (deprecated, but still available) <tt>database/version4</tt>
2056 module, the in-memory data structures were left as is. See the comments in
2057 the <tt>autojoin.c</tt> source file for a more complete description.</p>
2058
2059 <p>Other than this, there is little of note in the module; the
2060 <tt>do_access()</tt> command handler simply adds or removes the requested
2061 mask to or from the access list, and the callback functions take care of
2062 setting an initial access mask on registration and determining whether the
2063 user should be treated as recognized by <tt>validate_user()</tt>.</p>
2064
2065 <p class="backlink"><a href="#top">Back to top</a></p>
2066
2067
2068 <h4 class="subsubsection-title" id="s3-3">7-3-3. Nickname auto-join lists</h4>
2069
2070 <p>Nickname auto-join lists are managed by the <tt>nickserv/autojoin</tt>
2071 module, defined in <tt>autojoin.c</tt>. Aside from the details of its
2072 operation, this module is nearly identical to the <tt>nickserv/access</tt>
2073 module, including the hack used for database loading and saving; see the
2074 discussion of that module above (<a href="#s3-2">section 7-3-2</a>) for
2075 details.</p>
2076
2077 <p class="backlink"><a href="#top">Back to top</a></p>
2078
2079
2080 <h4 class="subsubsection-title" id="s3-4">7-3-4. Linking and nickname groups</h4>
2081
2082 <p>The distinction between "nicknames" and "nickname groups" has been made
2083 several times above. Ordinarily, this is only of importance as far as
2084 which structure is accessed (<tt>NickInfo</tt> or <tt>NickGroupInfo</tt>);
2085 however, the <tt>nickserv/link</tt> module, defined in <tt>link.c</tt>,
2086 allows nicknames to be linked together by assigning the same nickname group
2087 to both nicknames. This results in all information in the
2088 <tt>NickGroupInfo</tt> structure being shared among all linked nicknames,
2089 with only the data in the <tt>NickInfo</tt> structure kept separately for
2090 each nickname.</p>
2091
2092 <p>The <tt>nickserv/link</tt> includes three commands: <tt>LINK</tt>,
2093 <tt>UNLINK</tt>, and <tt>LISTLINKS</tt>, as well as one additional
2094 <tt>SET</tt> option, <tt>SET MAINNICK</tt> (linked in through NickServ's
2095 "<tt>SET</tt>" callback). Of these, <tt>LISTLINKS</tt> and <tt>SET
2096 MAINNICK</tt> are straightforward: <tt>do_listlinks()</tt> simply echoes
2097 the contents of the <tt>nicks[]</tt> array for the calling client's
2098 nickname group (or the specified nickname's group for Services
2099 operators), and <tt>do_set_mainnick()</tt> modifies the nickname
2100 group's <tt>mainnick</tt> field based on the given nickname.</p>
2101
2102 <p>When the <tt>LINK</tt> command is given to link a new nickname to the
2103 caller's nickname group, <tt>do_link()</tt> first ensures that the new
2104 nickname is not already in use and that creating the link would not cause
2105 the caller's total number of nicknames to exceed the <tt>NSRegEmailMax</tt>
2106 limit, if set. (Note that <tt>LINK</tt> does <i>not</i> abort if the mail
2107 address is not authenticated, simply checking the absolute value of the
2108 return from <tt>count_nicks_with_email()</tt> against the limit; creating
2109 the link does not in itself grant any additional privileges to the user,
2110 and can at most be used to "hide" from other users while maintaining
2111 current privileges.) If these checks pass, a new <tt>NickInfo</tt>
2112 structure is created, passing <tt>NULL</tt> as the
2113 <tt><i>nickgroup_ret</i></tt> parameter to <tt>makenick()</tt> to indicate
2114 that a new nickname group is not required; updates the <tt>NickInfo</tt>
2115 structure with the calling user's data; stores the nickname group ID in the
2116 new nickname's <tt>nickgroup</tt> field; and appends the new nickname to
2117 the nickname group's <tt>nicks[]</tt> array.</p>
2118
2119 <p><tt>UNLINK</tt> acts similarly to the Services administrator command
2120 <tt>DROPNICK</tt> for a single nickname in a group. However, since
2121 <tt>UNLINK</tt> is not limited to Services administrators, care must be
2122 taken that an unprivileged client is not allowed to delete nicknames from
2123 other nickname groups; this check is made by ensuring that (1) the target
2124 nickname has a valid associated <tt>NickGroupInfo</tt> structure and (2)
2125 the nickname group IDs of the two nickname groups are equal, and
2126 disallowing the command otherwise if the <tt>FORCE</tt> option is not
2127 given. (The check is made on the <tt>FORCE</tt> option, disallowed for
2128 unprivileged clients, rather than on the client's privilege level in order
2129 to prevent accidental deletion of others' nicknames by Services
2130 administrators.) If the command is allowed, the routine then deletes the
2131 nickname by calling <tt>delnick()</tt>; if the nickname group's main
2132 nickname is the one being unlinked, <tt>delnick()</tt> automatically
2133 adjusts the <tt>mainnick</tt> field to the next nickname in the
2134 <tt>nicks[]</tt> array (or the previous nickname, if the deleted nickname
2135 was the last one in the array).</p>
2136
2137 <p class="backlink"><a href="#top">Back to top</a></p>
2138
2139
2140 <h4 class="subsubsection-title" id="s3-5">7-3-5. E-mail address authentication</h4>
2141
2142 <p>While it has long been possible to associate an E-mail address with a
2143 registered nickname, there was traditionally no way to ensure that the
2144 address given was in fact a valid one belonging to the nickname owner.
2145 Since Services 5.0, such functionality has been provided by the
2146 <tt>nickserv/mail-auth</tt> module, defined in <tt>mail-auth.c</tt>. As
2147 described in the user's manual, E-mail address authentication works by
2148 assigning a random "authentication code" to the nickname, then sending an
2149 E-mail message to the registered address containing that code; the owner is
2150 not allowed to identify to the nickname until the code has been entered,
2151 ensuring that the address is one which the owner has (or at least had, at
2152 the time the message was sent) access to.</p>
2153
2154 <p>Internally, this processing is managed with the <tt>authcode</tt>,
2155 <tt>authset</tt>, and <tt>authreason</tt> fields of the
2156 <tt>NickGroupInfo</tt> structure. When an event occurs requiring E-mail
2157 address authentication, the module generates a random 9-digit numeric code
2158 (100000000 through 999999999 inclusive&mdash;codes with leading zeroes are
2159 not used in order to avoid confusion), stores the code in the nickname
2160 group's <tt>authcode</tt> field, and calls the mail subsystem's
2161 <tt>sendmail()</tt> routine to send a message to the nickname group's
2162 registered E-mail address (see <a href="8.html#s3">section 8-3</a> for
2163 information about how mail is sent). Additionally, the current timestamp
2164 is stored in the <tt>authset</tt> field, and the reason for setting the
2165 code (one of the <tt>NICKAUTH_*</tt> constants) is stored in the
2166 <tt>authreason</tt> field. (In early versions of the module, the reason
2167 was stored in two bits of the authentication code; this method was later
2168 rejected, however, as being too kludgey and inflexible as well as leaking
2169 information.) The presence of a nonzero value in the <tt>authcode</tt>
2170 field indicates that the nickname group is awaiting authentication, and a
2171 nickname identification callback function ensures that clients are not
2172 allowed to identify for such nicknames (nor does <tt>validate_user()</tt>
2173 allow automatic identification if an authentication code is present), thus
2174 effectively preventing their use. By issuing an AUTH command with the
2175 correct code, a nickname owner can clear the nickname group's
2176 <tt>authcode</tt> field, allowing identification to the nickname(s) once
2177 more.</p>
2178
2179 <p>The module begins with several utility functions:</p>
2180
2181 <dl>
2182 <dt><tt>void <b>make_auth</b>(NickGroupInfo *<i>ngi</i>, int16 <i>reason</i>)</tt></dt>
2183 <dd>Generates a random authentication code, and sets the nickname
2184 group's <tt>authcode</tt>, <tt>authset</tt>, and <tt>authreason</tt>
2185 fields appropriately. The <tt><i>reason</i></tt> parameter is
2186 copied directly into the <tt>authreason</tt> field, without checks
2187 on its value.</dd>
2188
2189 <dt><tt>void <b>clear_auth</b>(NickGroupInfo *<i>ngi</i>)</tt></dt>
2190 <dd>Clears the given nickname group's authentication code (if any), as
2191 well as all related nickname group data fields (including the
2192 previous E-mail address).</dd>
2193
2194 <dt><tt>int <b>send_auth</b>(User *<i>u</i>, NickGroupInfo *<i>ngi</i>,
2195 const char *<i>nick</i>, int <i>what</i>)</tt></dt>
2196 <dd>Sends an E-mail to the given nickname group's owner containing the
2197 nickname's current authentication code. <tt><i>u</i></tt> is the
2198 <tt>User</tt> structure for the client whose command caused the
2199 message to be sent; <tt><i>nick</i></tt> is the specific nickname
2200 for which the command was issued; and <tt><i>what</i></tt> is
2201 one of the <tt>IS_*</tt> constants defined for the routine
2202 (internally a language string index for the mail body or -1 for the
2203 special case of <tt>SETAUTH</tt>). The routine itself is defined
2204 as <tt>send_auth_</tt>, taking a <tt><i>line</i></tt> parameter
2205 indicating where in the source the routine was called from; this is
2206 filled in automatically by the <tt>send_auth()</tt> macro. In
2207 order to inform the calling client of the success or failure of
2208 sending the message, <tt>send_auth()</tt> creates a
2209 <tt>sendauth_data</tt> structure for each message sent, used in the
2210 two routines listed below.</dd>
2211
2212 <dt><tt>void <b>send_auth_callback</b>(int <i>status</i>, void *<i>data</i>)</tt></dt>
2213 <dd>The callback function used for <tt>sendmail()</tt> when called from
2214 <tt>send_auth()</tt>. This routine uses the <tt>sendauth_data</tt>
2215 structure for the sent message (passed as the <tt><i>data</i></tt>
2216 parameter) to send a reply to the client that issued the original
2217 command, and also to clear the nickname group's
2218 <tt>last_sendauth</tt> field if the command used was
2219 <tt>SENDAUTH</tt> and the message could not be sent. The structure
2220 is then removed from the global list and freed.</dd>
2221
2222 <dt><tt>int <b>sendauth_userdel</b>(User *<i>user</i>,
2223 const char *<i>reason</i>, int <i>is_kill</i>)</tt></dt>
2224 <dd>Used as a callback function for the core's "<tt>user delete</tt>"
2225 callback. Iterates through the <tt>sendauth_data</tt> list,
2226 clearing the <tt>User</tt> pointer of any entries for the user
2227 being removed; this causes <tt>send_auth_callback()</tt> to skip
2228 sending a reply when the mail sending completes.</dd>
2229 </dl>
2230
2231 <p>These routines are followed by the command handlers for the commands
2232 supported by the module: <tt>AUTH</tt>, <tt>SENDAUTH</tt>, <tt>REAUTH</tt>,
2233 <tt>RESTOREMAIL</tt>, and the Services administrator commands
2234 <tt>SETAUTH</tt>, <tt>GETAUTH</tt>, and <tt>CLEARAUTH</tt>. Of these, the
2235 only fairly complex one is the <tt>AUTH</tt> handler, <tt>do_auth()</tt>,
2236 as it must watch for attempts to guess the authentication code. (Invalid
2237 <tt>AUTH</tt> commands are treated the same as bad passwords to
2238 <tt>IDENTIFY</tt> or other commands, by calling <tt>bad_password()</tt> and
2239 incrementing the nickname group's <tt>bad_auths</tt> field, which itself
2240 can generate a warning via <tt>WALLOPS</tt>.)</p>
2241
2242 <p>Finally, the module includes four callback functions. Two of these,
2243 <tt>do_registered()</tt> and <tt>do_set_email()</tt>, hook into the
2244 NickServ callbacks for the <tt>REGISTER</tt> and <tt>SET EMAIL</tt>
2245 commands, respectively, dropping the client's identified status and
2246 generating and sending an authentication code. (Changes to the E-mail
2247 address made by Services administrators are not subject to authentication,
2248 however.) These are followed by the <tt>IDENTIFY</tt> command callback
2249 function <tt>do_identify()</tt>, which disallows <tt>IDENTIFY</tt> for
2250 nicknames with pending authentication codes, and the expiration check
2251 callback function <tt>do_check_expire()</tt>, which drops a
2252 newly-registered nickname after <tt>NSNoAuthExpire</tt> seconds (if set) if
2253 not authenticated, and also clears any pending <tt>REAUTH</tt> after the
2254 same amount of time (the user can subsequently use a second <tt>REAUTH</tt>
2255 if necessary).</p>
2256
2257 <p>Since the ability to send E-mail is essential for this module to work,
2258 the <tt>init_module()</tt> function checks for the presence of the
2259 <tt>mail/main</tt> module, refusing to load if it is not available.</p>
2260
2261 <p class="backlink"><a href="#top">Back to top</a></p>
2262
2263 <!------------------------------------------------------------------------>
2264 <hr/>
2265
2266 <h3 class="subsection-title" id="s4">7-4. ChanServ</h3>
2267
2268 <p>ChanServ is the most complex of the standard Services pseudoclients,
2269 owing to the variety of operations that can be performed on channels.
2270 There is no easy way to split those operations up into separate modules
2271 (except by individual command, an avenue which has not been pursued), and
2272 as a result, the core ChanServ module is itself the largest module in
2273 Services.</p>
2274
2275 <p>As with NickServ, the core ChanServ module, <tt>chanserv/main</tt>, is
2276 split up over several source files. These are discussed in
2277 <a href="#s4-1">section 7-4-1</a> and its subsections, with the exception
2278 of the <tt>access.c</tt> source file, which is discussed in
2279 <a href="#s4-2">section 7-4-2</a> along with the access list manipulation
2280 submodules, <tt>chanserv/access-levels</tt> and
2281 <tt>chanserv/access-xop</tt>.</p>
2282
2283 <p class="backlink"><a href="#top">Back to top</a></p>
2284
2285
2286 <h4 class="subsubsection-title" id="s4-1">7-4-1. ChanServ core functionality</h4>
2287
2288 <p>The core ChanServ module, <tt>chanserv/main</tt>, is built from several
2289 source files, along much the same lines as the core NickServ module:
2290 <tt>main.c</tt>, containing the central module code and most command
2291 handlers; <tt>access.c</tt>, for handling channel access lists;
2292 <tt>check.c</tt>, for checking the status of a channel against registered
2293 data and making appropriate changes; <tt>set.c</tt>, implementing the
2294 <tt>SET</tt> command; and <tt>util.c</tt>, defining various ChanServ
2295 utility functions.</p>
2296
2297 <p class="backlink"><a href="#top">Back to top</a></p>
2298
2299
2300 <h5 class="subsubsubsection-title" id="s4-1-1">7-4-1-1. Channel data structures</h5>
2301
2302 <p>As with NickServ, ChanServ splits its declarations into two header
2303 files: <tt>chanserv.h</tt>, containing structures and routine declarations
2304 intended to be exported to other modules, and <tt>cs-local.h</tt>, for
2305 internal use by ChanServ only. (There is also a separate header file,
2306 <tt>access.h</tt>, specifically for channel access list definitions; this
2307 is discussed in <a href="#s4-2-1">section 7-4-2-1</a>.)</p>
2308
2309 <p>The channel data structure, <tt>ChannelInfo</tt>, is naturally exported.
2310 As ChanServ does not have the concept of "links" or "channel groups" that
2311 NickServ uses with nicknames, all data for a channel is stored in this
2312 single structure. <tt>ChannelInfo</tt> does, however, include three
2313 substructures, defined before it in <tt>chanserv.h</tt>:</p>
2314
2315 <dl>
2316 <dt><tt>ChanAccess</tt></dt>
2317 <dd>Contains the data for an entry on a channel's access list. Access
2318 list entries are stored by nickname group ID, rather than by
2319 nickname, both to optimize checking an access list for a particular
2320 client and to eliminate the possibility of two or more entries
2321 matching a single client. (This is why only registered nicknames
2322 are allowed on channel access lists, and why channel access list
2323 entries are always displayed using the nickname group's main
2324 nickname, regardless of the nickname actually added to the list.)
2325 Rather than resizing the array every time a change is made to the
2326 list, deleted entries are left in memory with a nickname group ID
2327 of zero, and subsequent adds reuse these entries before attempting
2328 to expand the array. The <tt>channel</tt> field is used to link
2329 the record with its associated channel when loading and saving
2330 data. There are also a number of access-level related constants
2331 declared below this structure, such as the maximum and minimum
2332 access levels and the equivalent access levels for the <tt>XOP</tt>
2333 commands.</dd>
2334
2335 <dt><tt>AutoKick</tt></dt>
2336 <dd>Contains the data for an entry on a channel's autokick list. As
2337 with access list entries, deleted entries are left in the list
2338 rather than resizing the array (a <tt>NULL</tt> value for the mask
2339 string indicates an unused entry), and the <tt>channel</tt> field
2340 is used when loading and saving data to link the record with its
2341 associated channel.</dd>
2342
2343 <dt><tt>ModeLock</tt></dt>
2344 <dd>Contains a channel's mode lock data, including the set of modes
2345 locked on and off along with parameters for modes that require
2346 them; with the exception of the presence of two mode sets rather
2347 than one (modes can be locked on, locked off, or neither), the
2348 structure's contents are the same as the fields used in channel
2349 data structures (<tt>Channel</tt> records) to record the channel's
2350 current mode. The mode sets are normally maintained as bitmasks,
2351 but when used in the <tt>convert-db</tt> tool, they are defined as
2352 strings instead to allow lossless conversion to XML without needing
2353 to know the specific set of modes supported by the program that
2354 created the database. Unlike the <tt>ChanAccess</tt> and
2355 <tt>AutoKick</tt> structures, there is only one <tt>ModeLock</tt>
2356 structure per channel, and the data in the structure is saved along
2357 with the channel record itself, so there is no need for a separate
2358 channel field.</dd>
2359 </dl>
2360
2361 <p><tt>chanserv.h</tt> also defines constants for each of the channel
2362 privilege levels (indices into the <tt>levels[]</tt> array of the
2363 <tt>ChannelInfo</tt> structure). As noted in the comment above the list
2364 of definitions, changing the values of any of the constants will cause
2365 malfunctions when using the <tt>database/version4</tt> module, since that
2366 module simply reads in the list of levels as a block. (This is why the
2367 index 18, formerly used for <tt>CA_AUTOOWNER</tt>, is unused&mdash;to avoid
2368 problems with databases in which that index is used.)</p>
2369
2370 <p>The <tt>ChannelInfo</tt> structure itself contains the following
2371 fields:</p>
2372
2373 <dl>
2374 <dt><tt>ChannelInfo *<b>next</b>, *<b>prev</b></tt></dt>
2375 <dd>Used to link records together in the internal hash table.</dd>
2376
2377 <dt><tt>int <b>usecount</b></tt></dt>
2378 <dd>The record's usage count (number of gets minus number of puts).
2379 <i>(Implementation note: As noted in <a href="#s1">section 7-1</a>,
2380 this field currently serves no actual purpose.)</i></dd>
2381
2382 <dt><tt>char <b>name</b>[CHANMAX]</tt></dt>
2383 <dd>The channel's name. Capitalization is as used when the channel was
2384 registered, and does not change due to later actions. The buffer
2385 size, <tt>CHANMAX</tt>, is defined in the global header file
2386 <tt>defs.h</tt>.</dd>
2387
2388 <dt><tt>uint32 <b>founder</b></tt>
2389 <br/><tt>uint32 <b>successor</b></tt></dt>
2390 <dd>The nickname group ID of the channel's founder and successor,
2391 respectively. If the channel does not have a successor set, the
2392 <tt>successor</tt> field will be zero.</dd>
2393
2394 <dt><tt>Password <b>founderpass</b></tt></dt>
2395 <dd>The founder password for the channel.</dd>
2396
2397 <dt><tt>char *<b>desc</b></tt></dt>
2398 <dd>The channel's description, as specified at registration time or
2399 with a later <tt>SET DESC</tt> command.</dd>
2400
2401 <dt><tt>char *<b>url</b></tt></dt>
2402 <dd>The URL associated with the channel, as set with the <tt>SET
2403 URL</tt> command. <tt>NULL</tt> if no URL has been set.</dd>
2404
2405 <dt><tt>char *<b>email</b></tt></dt>
2406 <dd>The E-mail address associated with the channel, as set with the
2407 <tt>SET EMAIL</tt> command. <tt>NULL</tt> if no E-mail address
2408 has been set.</dd>
2409
2410 <dt><tt>char *<b>entry_message</b></tt></dt>
2411 <dd>The channel's entry message (the message sent as a <tt>NOTICE</tt>
2412 to clients entering the channel), as set with the <tt>SET
2413 ENTRYMSG</tt> command. <tt>NULL</tt> if no entry message has been
2414 set.</dd>
2415
2416 <dt><tt>time_t <b>time_registered</b></tt></dt>
2417 <dd>The timestamp at which the channel was registered.</dd>
2418
2419 <dt><tt>time_t <b>last_used</b></tt></dt>
2420 <dd>The timestamp at which the channel was last used (see
2421 <a href="../3.html#2-3">section 3-2-3 of the user's manual</a> for
2422 details of how the last-used time is set).</dd>
2423
2424 <dt><tt>char *<b>last_topic</b></tt>
2425 <br/><tt>char <b>last_topic_setter</b>[NICKMAX]</tt>
2426 <br/><tt>time_t <b>last_topic_time</b></tt></dt>
2427 <dd>The topic most recently set on the channel, along with the nickname
2428 of the client that set the topic and the timestamp at which it was
2429 set. If no topic has been set on the channel, <tt>last_topic</tt>
2430 will be <tt>NULL</tt>, and the other two fields will be
2431 undefined.</dd>
2432
2433 <dt><tt>int32 <b>flags</b></tt></dt>
2434 <dd>A bitmask containing zero or more of the following channel flags:
2435 <ul>
2436 <li><b><tt>CF_KEEPTOPIC</tt>:</b> ChanServ should restore the
2437 channel's previous topic each time the channel is created
2438 on the IRC network (<tt>SET KEEPTOPIC</tt>).</li>
2439 <li><b><tt>CF_SECUREOPS</tt>:</b> Clients without a positive access
2440 level on the channel should be prevented from getting ops
2441 (<tt>SET SECUREOPS</tt>).</li>
2442 <li><b><tt>CF_PRIVATE</tt>:</b> The channel is hidden from the
2443 <tt>LIST</tt> command output, except when used by Services
2444 administrators (<tt>SET PRIVATE</tt>).</li>
2445 <li><b><tt>CF_TOPICLOCK</tt>:</b> ChanServ should prevent the topic
2446 from being changed except by the <tt>SET TOPIC</tt> command
2447 (<tt>SET TOPICLOCK</tt>).</li>
2448 <li><b><tt>CF_RESTRICTED</tt>:</b> ChanServ should automatically
2449 kick and ban any clients without a positive access level
2450 that attempt to join the channel (<tt>SET
2451 RESTRICTED</tt>).</li>
2452 <li><b><tt>CF_LEAVEOPS</tt>:</b> ChanServ should not remove
2453 server-generated ops for the first client to join a
2454 channel, even if that client would not normally be
2455 auto-opped (<tt>SET LEAVEOPS</tt>).</li>
2456 <li><b><tt>CF_SECURE</tt>:</b> When checking a client's channel
2457 access level, require the client to have identified to
2458 NickServ regardless of the setting of the nickname's
2459 <tt>SECURE</tt> option (<tt>SET SECURE</tt>).</li>
2460 <li><b><tt>CF_VERBOTEN</tt>:</b> The channel is forbidden
2461 (<tt>FORBID</tt>).</li>
2462 <li><b><tt>CF_NOEXPIRE</tt>:</b> The channel does not expire
2463 (<tt>SET NOEXPIRE</tt>).</li>
2464 <li><b><tt>CF_OPNOTICE</tt>:</b> ChanServ should send a notice to
2465 the channel whenever any of the <tt>OP</tt>, <tt>VOICE</tt>,
2466 or related commands are used (<tt>SET OPNOTICE</tt>).</li>
2467 <li><b><tt>CF_ENFORCE</tt>:</b> ChanServ should prevent clients
2468 from removing automatically-set channel user modes such as
2469 auto-ops (<tt>SET ENFORCE</tt>).</li>
2470 <li><b><tt>CF_HIDE_EMAIL</tt>:</b> The channel's E-mail address is
2471 hidden from the <tt>INFO</tt> command output, except when
2472 used by Services administrators (<tt>SET HIDE
2473 EMAIL</tt>).</li>
2474 <li><b><tt>CF_HIDE_TOPIC</tt>:</b> The channel's current or last
2475 topic is hidden from the <tt>INFO</tt> command output,
2476 except when used by Services administrators (<tt>SET HIDE
2477 TOPIC</tt>).</li>
2478 <li><b><tt>CF_HIDE_MLOCK</tt>:</b> The channel's mode lock is
2479 hidden from the <tt>INFO</tt> command output, except when
2480 used by Services administrators (<tt>SET HIDE
2481 MLOCK</tt>).</li>
2482 <li><b><tt>CF_SUSPENDED</tt>:</b> The channel is suspended
2483 (<tt>SUSPEND</tt>).</li>
2484 <li><b><tt>CF_MEMO_RESTRICTED</tt>:</b> Only users with the
2485 <tt>MEMO</tt> privilege are permitted to send memos to the
2486 channel (<tt>SET MEMO-RESTRICTED</tt>).</li>
2487 </ul>
2488 The flag values 0x00000100 and 0x00000400 are unused to avoid
2489 difficulties with databases from earlier versions of Services
2490 which used these values.</dd>
2491
2492 <dt><tt>char <b>suspend_who</b>[NICKMAX]</tt>
2493 <br/><tt>char *<b>suspend_reason</b></tt>
2494 <br/><tt>time_t <b>suspend_time</b></tt>
2495 <br/><tt>time_t <b>suspend_expires</b></tt></dt>
2496 <dd>Suspension data for the channel, if the <tt>CF_SUSPENDED</tt> flag
2497 is set. Used in the same fashion as the same-named fields in the
2498 <tt>NickGroupInfo</tt> structure (see <a href="#s3-1-1">section
2499 7-3-1-1</a>).</dd>
2500
2501 <dt><tt>int16 <b>levels</b>[CA_SIZE]</tt></dt>
2502 <dd>The channel access levels corresponding to each of the channel
2503 privileges (<tt>CA_INVITE</tt>, <tt>CA_AKICK</tt>, and so on).
2504 A value of <tt>ACCLEV_DEFAULT</tt> indicates that the corresponding
2505 privilege should use the default access level defined in
2506 <tt>access.c</tt>; a value of <tt>ACCLEV_INVALID</tt> indicates
2507 that the corresponding privilege is disabled entirely, except with
2508 respect to the channel founder.</dd>
2509
2510 <dt><tt>ChanAccess *<b>access</b></tt>
2511 <br/><tt>int16 <b>access_count</b></tt></dt>
2512 <dd>A variable-length array containing the channel's access list.</dd>
2513
2514 <dt><tt>AutoKick *<b>akick</b></tt>
2515 <br/><tt>int16 <b>akick_count</b></tt></dt>
2516 <dd>A variable-length array containing the channel's autokick list.</dd>
2517
2518 <dt><tt>ModeLock <b>mlock</b></tt></dt>
2519 <dd>The channel's mode lock data.</dd>
2520
2521 <dt><tt>Channel *<b>c</b></tt></dt>
2522 <dd><i>Not saved to persistent storage.</i> Points to the
2523 <tt>Channel</tt> structure for the channel if it is currently in
2524 use.</dd>
2525
2526 <dt><tt>int <b>bad_passwords</b></tt></dt>
2527 <dd><i>Not saved to persistent storage.</i> The number of times an
2528 incorrect password has been given for a channel command (such as
2529 <tt>IDENTIFY</tt>) since the last correct password. Used to warn
2530 about attempts to crack the password.</dd>
2531 </dl>
2532
2533 <p>The <tt>cs-local.h</tt> header file includes three definitions used
2534 internally by ChanServ:</p>
2535
2536 <dl>
2537 <dt><tt>MAX_MLOCK_PARAMS</tt> (constant)</dt>
2538 <dd>Sets the maximum number of command parameters that the <tt>SET
2539 MLOCK</tt> command will process. This constant is used to avoid
2540 the overhead of dynamically allocating an argument array for every
2541 invocation of the command; any parameters passed beyond this limit
2542 will be silently ignored. The default value, 256, is more
2543 parameters than are can be passed in an RFC-standard 512-byte line
2544 (even if every parameter is one character, subtracting out the
2545 "<tt>SET MLOCK</tt>" leaves space for only 251 parameters, not
2546 considering the trailing CR/LF and other IRC protocol overhead).</dd>
2547
2548 <dt><tt>ChanOpt</tt> (structure)</dt>
2549 <dd>Used to define channel option data, for use by the <tt>SET</tt> and
2550 <tt>INFO</tt> commands. The structure has the following fields:
2551 <ul>
2552 <li><b><tt>name</tt>:</b> The name of the option, as a string.</li>
2553 <li><b><tt>flag</tt>:</b> The corresponding <tt>ChannelInfo.flags</tt>
2554 flag value.</li>
2555 <li><b><tt>namestr</tt>:</b> The option's descriptive name (for use
2556 in <tt>INFO</tt> output), as a language string index. If
2557 -1, the option will not be included in <tt>INFO</tt>
2558 output.</li>
2559 <li><b><tt>onstr</tt>, <tt>offstr</tt></b>: Response messages for
2560 turning the option on and off via <tt>SET</tt>, as language
2561 string indices.</li>
2562 <li><b><tt>syntaxstr</tt></b>: The syntax message for setting the
2563 option, as a language string index.</li>
2564 </ul></dd>
2565
2566 <dt><tt>RET_*</tt> (constants)</dt>
2567 <dd>Return values from access list modification routines. See
2568 <a href="#s4-2-1">section 7-4-2-1</a> for details.</dd>
2569 </dl>
2570
2571 <p id="s4-1-1-rename">One other point of note in <tt>cs-local.h</tt> is the
2572 renaming of several functions in <tt>set.c</tt> and <tt>util.c</tt> using
2573 <tt>#define</tt> directives, such as renaming <tt>init_set()</tt> to
2574 <tt>init_set_cs()</tt>. This is to avoid conflicts with NickServ, which
2575 includes functions of the same name in its own <tt>set.c</tt> and
2576 <tt>util.c</tt>. While the functions involved are not used outside of
2577 ChanServ, they must be declared external for the multi-file link to
2578 succeed; as a result, if the functions are not renamed, linking the final
2579 program when using static modules will result in a symbol name clash when
2580 the symbols from both modules are processed. This problem does not occur
2581 when using dynamic modules, since the presence of conflicting symbols in
2582 dynamic modules is not itself an error, and no attempt is made to reference
2583 either set of symbols from any other module (the references within the
2584 respective modules are resolved at module link time).</p>
2585
2586 <p class="backlink"><a href="#top">Back to top</a></p>
2587
2588
2589 <h5 class="subsubsubsection-title" id="s4-1-2">7-4-1-2. Overall module structure</h5>
2590
2591 <p>The main source file for ChanServ, <tt>main.c</tt>, follows the same
2592 pattern as its NickServ counterpart; see <a href="#s3-1-2">section
2593 7-3-1-2</a> for a more extensive description.</p>
2594
2595 <p>One of the first things defined in <tt>main.c</tt> is the
2596 <tt>chanopts[]</tt> table, an array of <tt>ChanOpt</tt> structures (see
2597 above) describing on/off options available on channels from a user's
2598 perspective. This table is used primarily for the <tt>SET</tt> command
2599 (thus only flags which have a corresponding <tt>SET</tt> command are
2600 listed), and secondarily for outputting the channel's option set in
2601 response to the <tt>INFO</tt> command. Note that the three <tt>HIDE</tt>
2602 options are not listed here, as they are handled specially for the
2603 <tt>SET</tt> command and not listed in the <tt>INFO</tt> output.</p>
2604
2605 <p>In addition to the standard command list in the <tt>cmds[]</tt> array,
2606 two separate arrays are defined, for the <tt>HALFOP</tt>/<tt>DEHALFOP</tt>
2607 and <tt>PROTECT</tt>/<tt>DEPROTECT</tt> command pairs. These commands can
2608 only be used if the IRC server protocol supports the corresponding feature,
2609 so the module initialization routine checks the protocol's feature flags
2610 and conditionally registers these two pairs of commands.</p>
2611
2612 <p>ChanServ includes a significant number of callback functions for various
2613 IRC events: in addition to watching for newly-created channels and users
2614 joining channels, it must also monitor changes of status such as channel
2615 modes and channel topics to ensure that they remain consistent with the
2616 registered settings and to record changes, as well as take notice of
2617 nickname-related events that can affect channels. Of these, the
2618 <tt>do_nickgroup_delete()</tt> callback function, called when a nickname
2619 group is deleted, is easily the most complex. Since channel founders must
2620 be registered nicknames, the disappearance of a nickname group means that
2621 any channels with that group as founder will no longer have a valid founder
2622 group ID. If the channel has a successor set, the successor may be able to
2623 assume foundership of the channel&mdash;but the code must be careful that
2624 this does not cause the successor to exceed his registered channel limit,
2625 or users could circumvent the limit by registering multiple nicknames,
2626 setting one as founder and another as successor, and deliberately dropping
2627 the founder nickname. In addition, if the channel was suspended, it is
2628 changed to a forbidden channel to prevent users from getting around a
2629 suspension by dropping and re-registering their nickname. Because of these
2630 various potentialities, the callback function always logs any actions it
2631 takes in response to the deletion of a nickname group.</p>
2632
2633 <p>Of the command routines, the basic commands (<tt>HELP</tt>,
2634 <tt>REGISTER</tt>, <tt>IDENTIFY</tt>, <tt>DROP</tt>, <tt>DROPCHAN</tt>,
2635 <tt>INFO</tt>, <tt>LIST</tt>) are very similar to their NickServ
2636 counterparts, and are not discussed in detail here. The two
2637 ChanServ-specific commands whose handlers are fairly complex are
2638 <tt>AKICK</tt> and the <tt>OP</tt>/<tt>VOICE</tt> command set.</p>
2639
2640 <p>The <tt>AKICK</tt> command handler <tt>do_akick()</tt>, despite its
2641 length (including a separate helper routine used with <tt>LIST</tt> and
2642 <tt>VIEW</tt>), is not dissimilar to the OperServ autokill and S-line
2643 commands, or the NickServ <tt>ACCESS</tt> and <tt>AJOIN</tt> handlers. The
2644 only significant difference is the presence of the <tt>ENFORCE</tt>
2645 subcommand; this is implemented by calling <tt>check_kick()</tt>, the
2646 routine used to check whether newly-joined clients are allowed to join a
2647 channel (see <a href="#s4-1-3">section 7-4-1-3</a>) for each client on the
2648 channel, causing clients which match an entry on the autokill list to be
2649 kickbanned.</p>
2650
2651 <p>The <tt>OP</tt> and <tt>VOICE</tt> family of commands all perform a
2652 common function&mdash;adding or removing a channel user mode&mdash;and for
2653 this reason, all eight commands are handled by a single routine,
2654 <tt>do_opvoice()</tt>, with handlers for each command that call the common
2655 routine with the appropriate command name to indicate the mode of
2656 operation. The data used by the common routine is stored in
2657 <tt>opvoice_data[]</tt>, an array of structures with the following
2658 fields:</p>
2659
2660 <ul>
2661 <li><b><tt>cmd</tt>:</b> The command name.</li>
2662 <li><b><tt>add</tt>:</b> Nonzero if the command adds a mode, zero if it
2663 removes a mode.</li>
2664 <li><b><tt>mode</tt>:</b> The mode character added or removed.</li>
2665 <li><b><tt>target_acc</tt>:</b> A channel privilege index (<tt>CA_*</tt>
2666 constant); if the target client is in this privilege class, the
2667 command will be refused.</li>
2668 <li><b><tt>success_msg</tt>:</b> The language string index for the message
2669 to be sent when the command succeeds.</li>
2670 <li><b><tt>already_msg</tt>:</b> The language string index for the message
2671 to be sent when the client already has the mode added (or lacks the
2672 mode removed) by the command.</li>
2673 <li><b><tt>failure_msg</tt>:</b> The language string index for the message
2674 to be sent when the command is rejected.</li>
2675 </ul>
2676
2677 <p>When called, <tt>do_opvoice()</tt> first extracts the data for the
2678 command from the <tt>opvoice_data[]</tt> table, and sets an additional
2679 variable, <tt>target_nextacc</tt>, used for mode-removal commands to set an
2680 upper bound on the target client access level check; this is used to, for
2681 example, allow <tt>DEVOICE</tt> on an auto-op client (since the client can
2682 just give themselves voice status again if necessary). The routine then
2683 loops through all target nicknames given with the command; a
2684 <tt>do/while</tt> loop is used so that if no nicknames are given at all,
2685 the code will still be run once (in this case the client that gave the
2686 command is used as the target). For each target client, the standard
2687 permission and channel status checks are performed, and then the routine
2688 determines whether to allow the command:</p>
2689 <ol>
2690 <li>If the target client is the client giving the command, the command is
2691 allowed.</li>
2692 <li>If the command removes a mode (<tt>DEOP</tt>, <tt>DEVOICE</tt>, etc.)
2693 and the channel does not have the <tt>ENFORCE</tt> option set, the
2694 command is allowed.</li>
2695 <li>If a channel privilege check (<tt>target_acc</tt>) is not specified for
2696 the command, the command is allowed.</li>
2697 <li>If the the target client is not in the privilege class specified for
2698 the command's privilege check, the command is allowed.</li>
2699 <li>If an upper limit for the privilege check (<tt>target_nextacc</tt>) is
2700 set for the command and the target client is in that privilege
2701 class, the command is allowed.</li>
2702 <li>Otherwise, the command is refused.</li>
2703 </ol>
2704
2705 <p>Once the command has been allowed, the routine determines which mode
2706 flags need to be set or cleared for the target client. (For extensibility,
2707 the code allows for more than one flag to be set or cleared for a single
2708 command, though the data table only allows one mode character.) If there
2709 are no modes to be set or cleared, a notice to that effect is sent to the
2710 caller; otherwise, the necessary mode changes are performed, a notice of
2711 the mode change is sent to the channel if the <tt>OPNOTICE</tt> option is
2712 enabled, and a success notice is sent to the caller. In addition, if the
2713 command was an <tt>OP</tt> command, the channel's last-used time is updated
2714 as for auto-ops.</p>
2715
2716 <p class="backlink"><a href="#top">Back to top</a></p>
2717
2718
2719 <h5 class="subsubsubsection-title" id="s4-1-3">7-4-1-3. Channel status checking and modification</h5>
2720
2721 <p>ChanServ's routines for checking and adjusting channel status are
2722 located in the source file <tt>check.c</tt>. There are six routines
2723 exported from this file; two, <tt>init_check()</tt> and <tt>exit_check()</tt>,
2724 are initialization and cleanup routines called by the module initialization
2725 and cleanup code, respectively. The remaining routines are:</p>
2726
2727 <dl>
2728 <dt><tt>void <b>check_modes</b>(Channel *<i>c</i>)</tt></dt>
2729 <dd>Checks the given channel's modes, making any changes necessary.
2730 For registered channels, the "registered" mode (if any) is always
2731 added, and other modes are set or cleared according to the mode
2732 lock; for unregistered channels, the "registered" mode is always
2733 cleared. This routine also checks for the "bouncy modes"
2734 phenomenon in tandem with the channel <tt>MODE</tt> message
2735 handle (see <a href="2.html#s6-3">section 2-6-3</a>).</dd>
2736
2737 <dt><tt>void <b>check_chan_user_modes</b>(const char *<i>source</i>,
2738 struct c_userlist *<i>u</i>, Channel *<i>c</i>, int32 <i>oldmodes</i>)</tt></dt>
2739 <dd>Checks the channel user modes of the given client (<tt><i>u</i></tt>)
2740 on the given channel, making any changes necessary. The set of
2741 "necessary" changes depends not only on the client's current modes,
2742 but also on the source of the <tt>MODE</tt> message that caused the
2743 change (passing an empty string for the <tt><i>source</i></tt>
2744 parameter will cause such checks to be skipped).
2745 <tt><i>oldmodes</i></tt> is the client's previous set of modes, or
2746 -1 for a client joining a channel. The sequence of operations is
2747 fairly complicated:
2748 <ul>
2749 <li class="spaced">If the channel is not registered (or forbidden),
2750 no changes are made.</li>
2751 <li class="spaced">If <tt><i>source</i></tt> is Services' server
2752 name or the ChanServ or OperServ pseudoclient nickname,
2753 no changes are made (under the assumption that anything
2754 done by Services has been otherwise checked).</li>
2755 <li class="spaced">If <tt><i>source</i></tt> is the client whose
2756 modes are being checked, then no changes are made
2757 <i>unless</i> the user is either not opped or is about to
2758 be deopped, in which case the mode changes made by the
2759 client are reversed. However, this check is not performed
2760 for IRC operators (since some IRC servers allow operators
2761 to set arbitrary modes regardless of chanop status), and on
2762 servers supporting halfops, the mode change is not reversed
2763 if the user has halfops and is only changing the halfop or
2764 voice modes.</li>
2765 <li class="spaced">If the mode change is the opping by a server of
2766 the first client to join a channel and the channel does not
2767 have the <tt>LEAVEOPS</tt> option set, the client's channel
2768 access level is checked against the auto-op privilege
2769 level. If the client has auto-op privileges, then the
2770 channel's last-used time is updated as for ordinary auto-op
2771 processing (see below); otherwise, a "channel is
2772 registered" notice is sent to the client and the client is
2773 deopped (in that order, so that a human user will see the
2774 reason for the deop before the mode change itself).</li>
2775 <li class="spaced">The "<tt>check_chan_user_modes</tt>" callback is
2776 called, allowing protocol modules to handle modes not
2777 recognized by the standard processing.</li>
2778 <li class="spaced">The client's new modes, based on channel
2779 privilege level, are calculated by calling
2780 <tt>check_access_cumode()</tt> (see
2781 <a href="#s4-2-1">section 7-4-2-1</a>).</li>
2782 <li class="spaced">If the client just joined the channel, the mode
2783 change was done by a server, or the <tt>ENFORCE</tt> option
2784 is set on the channel, all missing automatic modes are
2785 added. (This has the effect of allowing automatic modes to
2786 be removed from clients if <tt>ENFORCE</tt> is not set.)
2787 In addition, if the mode change included a <tt>+o</tt>, the
2788 channel's last-used time is updated.</li>
2789 <li class="spaced">If the client is not an IRC operator, any
2790 necessary mode removals are performed.</li>
2791 </ul>
2792 <p>The mode changes in these last two steps are performed by a
2793 helper routine, <tt>local_set_cumodes()</tt>, which in turn calls
2794 <tt>set_cmode()</tt> for each mode in the given set.</p></dd>
2795
2796 <dt><tt>int <b>check_kick</b>(User *<i>user</i>, const char *<i>chan</i>,
2797 int <i>on_join</i>)</tt></dt>
2798 <dd>Checks whether a client is permitted to be on a channel; if so,
2799 returns zero, otherwise kickbans the client and returns nonzero.
2800 This routine is normally called when a client joins a channel,
2801 before the actual join processing, but setting the
2802 <tt><i>on_join</i></tt> parameter to zero allows this routine to be
2803 called for clients already in the channel as well, such as for the
2804 <tt>AKICK ENFORCE</tt> command. A client can be denied access to a
2805 channel for any number of reasons, checked in the following order:
2806 <ul>
2807 <li class="spaced">If the channel name is the single character
2808 "<tt>#"</tt>" and the <tt>CSForbidShortChannel</tt>
2809 configuration option is set, the client is kickbanned.</li>
2810 <li class="spaced">If the client is a Services administrator, the
2811 client is allowed.</li>
2812 <li class="spaced">If the "<tt>check_kick</tt>" callback returns 1,
2813 the client is kickbanned; if it returns 2, the client is
2814 allowed.</li>
2815 <li class="spaced">If the client is an IRC operator, the client is
2816 allowed.</li>
2817 <li class="spaced">If the channel already exists with an
2818 IRC-operators-only mode, the client is kickbanned.
2819 (Ordinarily, the IRC server takes care of such processing,
2820 but this code is included to handle desynchs and other
2821 network problems.)</li>
2822 <li class="spaced">If the channel is not registered, then the
2823 client is kickbanned if the <tt>CSRegisteredOnly</tt>
2824 configuration option is set, and allowed otherwise.</li>
2825 <li class="spaced">If the channel is forbidden or suspended, the
2826 client is kickbanned.</li>
2827 <li class="spaced">If the channel's mode lock has an
2828 IRC-operators-only mode set, the client is kickbanned.</li>
2829 <li class="spaced">If the channel's mode lock includes a
2830 registered-nicknames-only mode and the client's nickname is
2831 not registered, the client is kickbanned. (However, this
2832 check is skipped if the <tt>CSSkipModeRCeck</tt>
2833 configuration option is set.)</li>
2834 <li class="spaced">If the client's
2835 <tt><i>nick</i>!<i>user</i>@<i>host</i></tt> string
2836 matches an autokick mask, the client is kickbanned.</li>
2837 <li class="spaced">If the client matches the <tt>NOJOIN</tt>
2838 privilege on the channel, the client is kickbanned.
2839 The client is also kickbanned if it would match the
2840 <tt>NOJOIN</tt> privilege when identified to its nickname;
2841 however, this check is skipped if less time than specified
2842 in the <tt>CSRestrictDelay</tt> configuration option has
2843 passed since Services startup.</li>
2844 <li class="spaced">Otherwise, the client is allowed.</li>
2845 </ul>
2846 <p>If the client is to be kickbanned, the routine first checks
2847 whether kicking the client would cause the channel to become empty
2848 (and thus be deleted, nullifying the effecet of any ban); if so, a
2849 <tt>JOIN</tt> message is sent to the network to cause ChanServ to
2850 join the channel, and a timeout for <tt>CSInhabit</tt> seconds is
2851 added to cause ChanServ to leave the channel after that time.
2852 Following this, the routine ensures that the ban mask is properly
2853 formatted (containing a nickname as well as user and host), then
2854 clears any ban exceptions matching the user and adds the ban mask
2855 if it is not already present. Once the ban is present, the client
2856 is then kicked from the channel, and removed from the internal data
2857 structures if necessary.</p>
2858 <p><i>Implementation note: As mentioned in
2859 <a href="../d.html">Appendix D of the user manual</a>, when
2860 ChanServ temporarily enters a channel for a kickban, it is not
2861 added to the internal channel data; as a result, a subsequent
2862 <tt>UNBAN</tt> or <tt>INVITE</tt> on the channel will return a
2863 "channel does not exist" error. It would probably be better to
2864 add ChanServ to the channel's client list like any ordinary
2865 client.</i></p>
2866 </dd>
2867
2868 <dt><tt>int <b>check_topiclock</b>(Channel *<i>c</i>, time_t <i>topic_time</i>)</tt></dt>
2869 <dd>Called on a channel topic change (<tt><i>topic_time</i></tt> is the
2870 timestamp associated with the topic change) to restore the topic to
2871 its previous value if the channel's <tt>TOPICLOCK</tt> option is
2872 set. Returns nonzero if the topic is changed by the routine,
2873 otherwise zero.</dd>
2874 </dl>
2875
2876 <p class="backlink"><a href="#top">Back to top</a></p>
2877
2878
2879 <h5 class="subsubsubsection-title" id="s4-1-4">7-4-1-4. The <tt>SET</tt> and <tt>UNSET</tt> commands</h5>
2880
2881 <p>The handlers for the <tt>SET</tt> and <tt>UNSET</tt> commands are
2882 located in the <tt>set.c</tt> source file; as for NickServ, they function
2883 like miniature versions of the main <tt>chanserv()</tt> routine. One
2884 noteworthy difference is that the on/off options (other than the three
2885 <tt>HIDE</tt> options) are all handled by a single routine,
2886 <tt>do_set_boolean()</tt>; the main <tt>SET</tt> handler, <tt>do_set()</tt>,
2887 looks up the option name in the <tt>chanopts[]</tt> table defined in
2888 <tt>main.c</tt> (checking privileges for the <tt>NOEXPIRE</tt> option),
2889 then calls <tt>do_set_boolean()</tt>, which uses the data from the
2890 <tt>ChanOpt</tt> structure to set channel flags and send responses to the
2891 calling client.</p>
2892
2893 <p>Other noteworthy option handlers are:</p>
2894
2895 <dl>
2896 <dt><tt><b>do_set_founder()</b></tt>
2897 <br/><tt><b>do_set_successor()</b></tt></dt>
2898 <dd>Both <tt>SET FOUNDER</tt> and <tt>SET SUCCESSOR</tt> follow the
2899 same general pattern: the given nickname is looked up to retrieve
2900 its nickname group ID, the ID is checked to ensure that both
2901 founder and successor are not set to the same nickname group, and
2902 an informational message is logged to record the change. The major
2903 difference is that <tt>SET FOUNDER</tt> checks to ensure that the
2904 new founder has not reached the channel registration limit, while
2905 <tt>SET SUCCESSOR</tt> makes no such check. (Even if it did, the
2906 check would only make sense at the time the <tt>SET SUCCESSOR</tt>
2907 command was given, and would not reflect any future channel
2908 registrations or drops by the successor. An alternative
2909 possibility would be to have successor channels count against the
2910 channel limit as well, as mentioned in <a href="11.html#s1">section
2911 11-1</a>.)</dd>
2912
2913 <dt><tt><b>do_set_mlock()</b></tt></dt>
2914 <dd>The <tt>SET MLOCK</tt> handler is fairly complex, as it must parse
2915 the mode string and parameters to ensure that users cannot
2916 inadvertently (or maliciously) cause an invalid <tt>MODE</tt>
2917 message to be sent to the IRC network. The routine parses the mode
2918 string character by character; if a mode is found that conflicts
2919 with an earlier setting in the string, the later occurrence takes
2920 precedence. Additionally, in order to simplify cleanup in case a
2921 problem is found, the new mode lock is accumulated in a temporary
2922 <tt>ModeLock</tt> structure, which is copied into the channel's
2923 data when the routine successfully completes.
2924 <p>In order to support additional modes provided by particular IRC
2925 protocols, <tt>do_set_mlock()</tt> defines a callback, "<tt>SET
2926 MLOCK</tt>", which is called once for every mode in the mode
2927 string; it is also called once after all modes have been processed,
2928 to allow for a final validity check (for example, to check for
2929 modes that require other modes to be set, as the Unreal protocol
2930 module does).</p></dd>
2931 </dl>
2932
2933 <p class="backlink"><a href="#top">Back to top</a></p>
2934
2935
2936 <h5 class="subsubsubsection-title" id="s4-1-5">7-4-1-5. ChanServ utility routines</h5>
2937
2938 <p>ChanServ's utility functions are defined in <tt>util.c</tt>. As with
2939 NickServ, the preprocessor symbol <tt>STANDALONE_CHANSERV</tt> can be
2940 defined before including <tt>util.c</tt> in another file; this causes the
2941 routines <tt>new_channelinfo()</tt>, <tt>free_channelinfo()</tt>, and
2942 <tt>reset_levels</tt> to be defined as <tt>static</tt>, and eliminates all
2943 other code. <tt>new_channelinfo()</tt> and <tt>free_channelinfo()</tt> are
2944 used to allocate and free resources for a <tt>ChannelInfo</tt> structure,
2945 like their nickname counterparts; <tt>reset_levels()</tt> resets the
2946 privilege levels for a channel (the <tt>levels[]</tt> array) to default
2947 values.</p>
2948
2949 <p>Aside from these three functions (all exported from ChanServ),
2950 <tt>util.c</tt> defines the following routines, along with the
2951 initialization and cleanup routines <tt>init_util()</tt> and
2952 <tt>exit_util()</tt>:</p>
2953
2954 <dl>
2955 <dt><tt>int <b>check_channel_limit</b>(const NickGroupInfo *<i>ngi</i>, int *<i>max_ret</i>)</tt></dt>
2956 <dd>Compares the given nickname group's registered channel count with
2957 the limit applied to that nickname, returning -1 if the limit has
2958 yet to be reached, 0 if the limit has been reached, and 1 if the
2959 limit has been exceeded (much like string comparison functions).
2960 Also stores the registered channel limit in the variable pointed to
2961 by <tt><i>max_ret</i></tt> if <tt><i>max_ret</i></tt> is not
2962 <tt>NULL</tt>. This routine is exported.</dd>
2963
2964 <dt><tt>ChannelInfo *<b>makechan</b>(const char *<i>chan</i>)</tt></dt>
2965 <dd>Creates a new <tt>ChannelInfo</tt> structure for the given channel
2966 name, adds it to the database, and returns it.</dd>
2967
2968 <dt><tt>int <b>delchan</b>(ChannelInfo *<i>ci</i>)</tt></dt>
2969 <dd>Removes the given channel from the database, returning nonzero on
2970 success, zero on failure.</dd>
2971
2972 <dt><tt>void <b>count_chan</b>(ChannelInfo *<i>ci</i>)</tt></dt>
2973 <dd>Updates the <tt>NickGroupInfo</tt> record for the given channel's
2974 founder to indicate that that nickname group owns the channel,
2975 incrementing the owned-channel count.</dd>
2976
2977 <dt><tt>void <b>uncount_chan</b>(ChannelInfo *<i>ci</i>)</tt></dt>
2978 <dd>Removes the given channel from its founder's owned-channel list
2979 and decrements the owned-channel count.</dd>
2980
2981 <dt><tt>int <b>is_founder</b>(const User *<i>user</i>, const ChannelInfo *<i>ci</i>)</tt></dt>
2982 <dd>Returns whether the given user has founder access to the given
2983 channel, whether due to being the actual channel founder or to
2984 identifying for the channel with its founder password.</dd>
2985
2986 <dt><tt>int <b>is_identified</b>(const User *<i>user</i>, const ChannelInfo *<i>ci</i>)</tt></dt>
2987 <dd>Returns whether the given user has identified for the channel with
2988 its founder password. A subset of <tt>is_founder()</tt>.</dd>
2989
2990 <dt><tt>void <b>restore_topic</b>(Channel *<i>c</i>)</tt></dt>
2991 <dd>Restores the saved topic on a newly-created channel if the
2992 channel is registered and its <tt>KEEPTOPIC</tt> option is set.</dd>
2993
2994 <dt><tt>void <b>record_topic</b>(ChannelInfo *<i>ci</i>, const char *<i>topic</i>, const char *<i>setter</i>, time_t <i>topic_time</i>)</tt></dt>
2995 <dd>Records the given topic in the given channel's data structure.</dd>
2996
2997 <dt><tt>void <b>suspend_channel</b>(ChannelInfo *<i>ci</i>, const char *<i>reason</i>, const char *<i>who</i>, const time_t <i>expires</i>)</tt></dt>
2998 <dd>Suspends the given channel, copying the parameters
2999 <tt><i>reason</i></tt>, <tt><i>who</i></tt>, and
3000 <tt><i>expires</i></tt> into the suspension data fields. (If
3001 <tt><i>expires</i></tt> is zero, then the suspension will not
3002 expire.)</dd>
3003
3004 <dt><tt>void <b>unsuspend_channel</b>(ChannelInfo *<i>ci</i>, int <i>set_time</i>)</tt></dt>
3005 <dd>Cancels the suspension on the given channel. If
3006 <tt><i>set_time</i></tt> is nonzero, the last-used time of the
3007 channel will be updated according to <tt>CSSuspendGrace</tt> to
3008 prevent the channel from expiring for that length of time (if
3009 <tt>CSSuspendGrace</tt> or <tt>CSExpire</tt> are not set, or if the
3010 channel already has enough time before expiration, the last-used
3011 time will not be changed).</dd>
3012
3013 <dt><tt>void <b>chan_bad_password</b>(User *<i>u</i>, ChannelInfo *<i>ci</i>)</tt></dt>
3014 <dd>Records a bad password attempt for the given channel, sending out a
3015 <tt>WALLOPS</tt> if the number of consecutive bad password attempts
3016 for the channel reaches the limit specified by the
3017 <tt>BadPassWarning</tt> configuration option (if set).</dd>
3018
3019 <dt><tt>ChanOpt *<b>chanopt_from_name</b>(const char *<i>optname</i>)</tt></dt>
3020 <dd>Returns the <tt>ChanOpt</tt> corresponding to the given
3021 (case-insensitive) option name, or <tt>NULL</tt> if no matching
3022 option is found.</dd>
3023
3024 <dt><tt>char *<b>chanopts_to_string</b>(const ChannelInfo *<i>ci</i>, const NickGroupInfo *<i>ngi</i>)</tt></dt>
3025 <dd>Returns a string describing the set of options active on the given
3026 channel in human-readable form. <tt>ngi</tt> indicates the client
3027 to which the string will be sent and is used in <tt>getstring()</tt>
3028 calls. The returned string is stored in a static buffer, which
3029 will be overwritten by the next call to this routine.</dd>
3030 </dl>
3031
3032 <p class="backlink"><a href="#top">Back to top</a></p>
3033
3034
3035 <h4 class="subsubsection-title" id="s4-2">7-4-2. Channel access list handling</h4>
3036
3037 <p>As discussed in the user's manual, user privileges on channels are
3038 maintained via channel access lists. Channel access list handling in
3039 ChanServ is split into three files. One, <tt>access.c</tt>, contains
3040 common routines and privilege level definitions, and is included in the
3041 <tt>chanserv/main</tt> module; the other two, <tt>access-levels.c</tt> and
3042 <tt>access-xop.c</tt>, are independent modules which provide two different
3043 ways of manipulating access lists. A separate header file,
3044 <tt>access.h</tt>, contains definitions related to channel access lists.</p>
3045
3046 <p class="backlink"><a href="#top">Back to top</a></p>
3047
3048
3049 <h5 class="subsubsubsection-title" id="s4-2-1">7-4-2-1. Access list basics</h5>
3050
3051 <p>The <tt>access.c</tt> source file, included as part of the main ChanServ
3052 module, serves two main purposes; to define the set of privileges
3053 associated with channels, and to provide utility routines for performing
3054 common operations related to channel access lists. It also makes use of
3055 the <tt>access.h</tt> header file for certain structure and constant
3056 definitions.</p>
3057
3058 <p>The list of channel privileges is defined in the <tt>levelinfo[]</tt>
3059 array at the top of the file; each element in the array is a
3060 <tt>LevelInfo</tt> structure that describes one privilege. (The word
3061 "level" in the identifiers comes from the command, <tt>LEVELS</tt>, used
3062 to modify the settings on a per-channel basis; that command name was
3063 originally used for the meaning of "setting the <i>levels</i> at which
3064 privileges are given".)</p>
3065
3066 <p>The word "privilege" itself is something of a misnomer, as it includes
3067 two "negative privileges", <tt>CA_AUTODEOP</tt> and <tt>CA_NOJOIN</tt>.
3068 While these can be used in the same manner as ordinary privileges, their
3069 primary function is in conjunction with the <tt>SECUREOPS</tt> and
3070 <tt>RESTRICTED</tt> channel options; these cause the respective privilege
3071 levels to be treated as zero, preventing users not on the channel access
3072 list to be auto-deopped or blocked from entering the channel. However,
3073 these two privileges are not visible to users, so "privilege" is considered
3074 clear enough to use in the documentation</p>
3075
3076 <p>The <tt>LevelInfo</tt> structure, defined in <tt>access.h</tt>, contains
3077 the following fields:</p>
3078
3079 <dl>
3080 <dt><tt>int <b>what</b></tt></dt>
3081 <dd>The <tt>CA_*</tt> constant used for this privilege.</dd>
3082
3083 <dt><tt>int <b>defval</b></tt></dt>
3084 <dd>The default channel access level corresponding to this
3085 privilege.</dd>
3086
3087 <dt><tt>const char *<b>name</b></tt></dt>
3088 <dd>The user-visible name for this privilege, used in the
3089 <tt>LEVELS</tt> command. An empty string makes the privilege
3090 invisible to users.</dd>
3091
3092 <dt><tt>int <b>desc</b></tt></dt>
3093 <dd>The message string index giving the privilege's description.</dd>
3094
3095 <dt><tt>int <b>action</b></tt></dt>
3096 <dd>The "meaning" of the privilege: the action to be performed for
3097 clients with the appropriate access level. One of the following
3098 flags, any of which may be combined (OR'd) with
3099 <tt>CL_LESSEQUAL</tt> to make the privilege's associated level a
3100 maximum rather than a minimum:
3101 <ul>
3102 <li><b><tt>CL_SET_MODE</tt>:</b> Sets channel user modes on the
3103 corresponding client.</li>
3104 <li><b><tt>CL_CLEAR_MODE</tt>:</b> Clears channel user modes from
3105 the corresponding client.</li>
3106 <li><b><tt>CL_ALLOW_CMD</tt>:</b> Allows a command or set of
3107 commands to be used.</li>
3108 <li><b><tt>CL_OTHER</tt>:</b> Handled separately (or a no-op).</li>
3109 </ul></dd>
3110
3111 <dt><tt>union {...} <b>target</b></tt></dt>
3112 <dd>Data used in implementing the privilege. The union has two
3113 members:
3114 <ul>
3115 <li class="spaced"><tt>struct {...} <b>cumode</b></tt>: Used for
3116 <tt>CL_SET_MODE</tt> and <tt>CL_CLEAR_MODE</tt>. Includes
3117 three fields:
3118 <ul>
3119 <li><tt>const char *<b>modes</b></tt>: The string of
3120 mode(s) to set on the client.</li>
3121 <li><tt>int <b>cont</b></tt>: Used to "chain" privileges
3122 together, so that only the first applicable mode
3123 set is used (used for <tt>AUTOOP</tt>,
3124 <tt>AUTOHALFOP</tt>, and <tt>AUTOVOICE</tt>).</li>
3125 <li><tt>int32 <b>flags</b></tt>: The mode flags equivalent
3126 to <tt>modes</tt>. Set at module initialization
3127 time (this field can be left uninitialized).</li>
3128 </ul></li>
3129 <li class="spaced"><tt>struct {...} <b>cmd</b></tt>: Used for
3130 <tt>CL_ALLOW_CMD</tt>. Includes two string fields:
3131 <ul>
3132 <li><tt>const char *<b>main</b></tt>: The relevant command
3133 name.</li>
3134 <li><tt>const char *<b>sub</b></tt>: The relevant subcommand
3135 for the given command, or <tt>NULL</tt> if none.</li>
3136 </ul></li>
3137 </ul></dd>
3138 </dl>
3139
3140 <p>In addition to the <tt>levelinfo[]</tt> table itself, exported for use
3141 by other modules (particularly the <tt>http/dbaccess</tt> module, described
3142 in <a href="8.html#s2-7">section 8-2-7</a>), the file's initialization
3143 routine <tt>init_access()</tt> copies relevant parts of the table into two
3144 local arrays indexed by privilege (<tt>CA_*</tt> value):
3145 <tt>def_levels[]</tt>, containing each entry's default access level (the
3146 <tt>defval</tt> field), and <tt>lev_is_max[]</tt>, containing a boolean
3147 indication of whether the privilege's access level is a maximum (whether
3148 the <tt>action</tt> field has <tt>CL_LESSEQUAL</tt> set).</p>
3149
3150 <p>The main portion of <tt>access.c</tt> defines the following utility
3151 functions for use by the main ChanServ module and the two access list
3152 manipulation modules. Several of the routines are exported for use by
3153 external modules as well.</p>
3154
3155 <dl>
3156 <dt><tt>int <b>get_ci_level</b>(const ChannelInfo *<i>ci</i>, int <i>what</i>)</tt></dt>
3157 <dd><i>Exported routine.</i> Returns the given channel's level for the
3158 given privilege, translating <tt>ACCLEV_DEFAULT</tt> in the
3159 channel's <tt>levels[]</tt> into the appropriate default value.
3160 Returns <tt>ACCLEV_INVALID</tt> (and logs an error message) on
3161 invalid parameters.</dd>
3162
3163 <dt><tt>int <b>check_access</b>(const User *<i>user</i>, const ChannelInfo *<i>ci</i>, int <i>what</i>)</tt></dt>
3164 <dd><i>Exported routine.</i> Returns whether the given client has the
3165 given privilege (<tt><i>what</i></tt>) on the given channel. Due
3166 to an unfortunate coincidence of terms, this routine can seem
3167 confusing to call for the <tt>CA_NOJOIN</tt> "privilege": the
3168 return value will be 1 if the client does <i>not</i> "have access
3169 to" the channel, <i>i.e.</i> matches the <tt>CA_NOJOIN</tt>
3170 privilege.</dd>
3171
3172 <dt><tt>int check_access_if_idented(const User *user, const ChannelInfo *ci, int what)</tt></dt>
3173 <dd><i>Exported routine.</i> Like <tt>check_access()</tt>, but returns
3174 what the result would be if the client was identified for its
3175 nickname. (If the nickname is not registered, the return value
3176 will be the same as for <tt>check_access()</tt>.</dd>
3177
3178 <dt><tt>int check_access_cmd(const User *user, const ChannelInfo *ci, const char *command, const char *subcommand)</tt></dt>
3179 <dd><i>Exported routine.</i> Returns whether the client is allowed to
3180 use the given command on the given channel. If the check is being
3181 made for a specific subcommand, that subcommand is specified in
3182 <tt><i>subcommand</i></tt>; otherwise, <tt><i>subcommand</i></tt>
3183 is <tt>NULL</tt>.</dd>
3184
3185 <dt><tt>int <b>get_access</b>(const User *<i>user</i>, const ChannelInfo *<i>ci</i>)</tt></dt>
3186 <dd>Returns the given client's access level on the given channel,
3187 taking into account whether the client has identified for its
3188 nickname with respect to the nickname and channel <tt>SECURE</tt>
3189 options.</dd>
3190
3191 <dt><tt>static int get_access_if_idented(const User *user, const ChannelInfo *ci)</tt></dt>
3192 <dd>Like <tt>get_access()</tt>, but returns the access level associated
3193 with the client's nickname regardless of whether the client has
3194 identified or not.</dd>
3195
3196 <dt><tt>int check_access_cumode(const User *user, const ChannelInfo *ci, int32 newmodes, int32 changemask)</tt></dt>
3197 <dd>Checks the channel user modes of a client on a channel, returning a
3198 bitmask of modes that are to be changed (in other words, the
3199 bitwise exclusive-or of the current and resulting mode sets).
3200 <tt><i>newmodes</i></tt> is the client's current set of modes on
3201 the channel; <tt><i>changemask</i></tt> indicates which modes
3202 changed due to the action that caused this function to be called.</dd>
3203
3204 <dt><tt>int access_add(ChannelInfo *ci, const char *nick, int level, int uacc)</tt>
3205 <br/><tt>int access_del(ChannelInfo *ci, const char *nick, int uacc)</tt></dt>
3206 <dd>Adds (<tt>access_add()</tt>) or deletes (<tt>access_del()</tt>) an
3207 entry to or from the given channel's access list for the nickname
3208 group to which <tt><i>nick</i></tt> belongs. <tt><i>level</i></tt>
3209 is the access level for the new entry, and <tt><i>uacc</i></tt> is
3210 the access level of the client making the change. Both routines
3211 return one of the following result codes, defined in
3212 <tt>cs-local.h</tt>:
3213 <ul>
3214 <li><b><tt>RET_ADDED</tt></b> (<tt>access_add()</tt> only): The
3215 target nickname did not previously exist on the channel's
3216 access list, and was successfully added.</li>
3217 <li><b><tt>RET_CHANGED</tt></b> (<tt>access_add()</tt> only): The
3218 target nickname previously had a different access level on
3219 the channel, and the access level was successfully
3220 changed.</li>
3221 <li><b><tt>RET_UNCHANGED</tt></b> (<tt>access_add()</tt> only): The
3222 target nickname already had the desired access level on the
3223 channel.</li>
3224 <li><b><tt>RET_DELETED</tt></b> (<tt>access_del()</tt> only): The
3225 target nickname was successfully deleted from the channel's
3226 access list.</li>
3227 <li><b><tt>RET_LISTED</tt></b> (used by other modules): The target
3228 nickname was listed.</li>
3229 <li><b><tt>RET_PERMISSION</tt>:</b> The calling user does not have
3230 permission to make the requested change.</li>
3231 <li><b><tt>RET_NOSUCHNICK</tt>:</b> The given nickname is not
3232 registered.</li>
3233 <li><b><tt>RET_NICKFORBID</tt>:</b> The given nickname is
3234 forbidden.</li>
3235 <li><b><tt>RET_LISTFULL</tt></b> (<tt>access_add()</tt> only): The
3236 channel's access list is full and the given nickname is not
3237 already on the list.</li>
3238 <li><b><tt>RET_NOENTRY</tt></b> (<tt>access_del()</tt> only): The
3239 given nickname does not exist on the channel's access
3240 list.</li>
3241 <li><b><tt>RET_INTERR</tt></b>: An internal error occurred.</li>
3242 </ul>
3243 Note that successful return codes are positive, while failure
3244 return codes are negative (zero is not used as a return code).</dd>
3245 </dl>
3246
3247 <p><tt>access.c</tt> also includes initialization code in the
3248 <tt>init_access()</tt> routine, called from the <tt>chanserv/main</tt>
3249 module's <tt>init_module()</tt>. This routine initializes the
3250 <tt>def_levels[]</tt> and <tt>lev_is_max[]</tt> arrays, as well as the
3251 <tt>flags</tt> field of the <tt>target.cumode</tt> structure for privileges
3252 that set or clear modes; it also disables (by removing from the table) any
3253 privileges for features not supported by the IRC protocol in use.
3254 <i>Implementation note: This relies on the current design of Services, in
3255 which the protocol module will never be changed while the program is
3256 running. If this design is changed, the code will need to be updated to
3257 leave the appropriate entries in the table, perhaps by adding a "disabled"
3258 flag or field to each entry.</i></p>
3259
3260 <p>There is also a corresponding <tt>exit_access()</tt> routine; it does
3261 nothing, but is included for completeness.</p>
3262
3263 <p class="backlink"><a href="#top">Back to top</a></p>
3264
3265
3266 <h5 class="subsubsubsection-title" id="s4-2-2">7-4-2-2. Manipulation via <tt>ACCESS</tt> and <tt>LEVELS</tt></h5>
3267
3268 <p>The <tt>chanserv/access-levels</tt> module is one of two modules for
3269 manipulating channel access lists. It provides direct access to both the
3270 channel access list itself, via the <tt>ACCESS</tt> command, and channels'
3271 privilege level settings, via the <tt>LEVELS</tt> command.</p>
3272
3273 <p>Since the functions available in both commands change depending on
3274 runtime parameters, their help messages are handled by a "<tt>HELP</tt>"
3275 callback function, <tt>do_help()</tt>. In addition to description of the
3276 two commands, a third help option, <tt>LEVELS DESC</tt> provides
3277 descriptions of the available channel privileges; unlike most other help
3278 messages, the text is generated on the fly from the <tt>levelinfo[]</tt>
3279 array and corresponding description strings.</p>
3280
3281 <p>The <tt>ACCESS</tt> command handler, <tt>do_access()</tt>, calls one of
3282 several subroutines to perform each of the available actions, depending on
3283 the subcommand given. Two of these, <tt>do_access_add()</tt> and
3284 <tt>do_access_del()</tt>, simply call the <tt>access_add()</tt> and
3285 <tt>access_del()</tt> routines mentioned in <a href="#s4-2-1">section
3286 7-4-2-1</a>, sending appropriate result messages to the calling client
3287 depending on the return codes from those functions.
3288 <tt>do_access_list()</tt> and <tt>do_access_listlevel()</tt> select access
3289 entries for listing based on the given parameters, then call
3290 <tt>access_list()</tt>, defined below the <tt>ACCESS</tt> subcommand
3291 handlers, to actually send the list text to the calling client. (The
3292 <tt><i>sent_header</i></tt> parameter to <tt>access_list()</tt> is used to
3293 to record whether a list header message has been sent.) The final
3294 subcommand handler, <tt>do_access_count()</tt>, simply counts up the number
3295 of (active) access entries in the list and sends that in a response message
3296 to the calling client.</p>
3297
3298 <p>The <tt>LEVELS</tt> command also has several subcommands, though these
3299 are all handled within the command handler <tt>do_levels()</tt>. The
3300 command implementation itself is fairly straightforward, with <tt>SET</tt>
3301 and <tt>DISABLE</tt> searching the <tt>levelinfo[]</tt> array for the named
3302 privilege, and <tt>LIST</tt> iterating through that array to display the
3303 current level for each privilege.</p>
3304
3305 <p class="backlink"><a href="#top">Back to top</a></p>
3306
3307
3308 <h5 class="subsubsubsection-title" id="s4-2-3">7-4-2-3. Manipulation via <tt>XOP</tt></h5>
3309
3310 <p>The <tt>chanserv/access-xop</tt> module, defined in <tt>access-xop.c</tt>,
3311 provides the <tt>XOP</tt> command set for managing channel access lists.
3312 While these commands present the access list as several distinct lists
3313 (SOP, AOP, and so on), they are in fact only different views of the same
3314 channel access list, each containing nicknames with a particular predefined
3315 access level. This has the following side effects:</p>
3316
3317 <ul>
3318 <li class="spaced">A particular nickname cannot be present on two or more
3319 lists simultaneously (this would require having two entries on the
3320 access list for the same nickname). Attempting to add a nickname
3321 that is already on a different list is treated as an access level
3322 change.</li>
3323
3324 <li class="spaced">Changes to the access list made by the <tt>ACCESS</tt>
3325 command will also be reflected in the relevant XOP lists. If the
3326 <tt>ACCESS</tt> command is used to add a nickname at a level not
3327 associated with any <tt>XOP</tt> command, that nickname will be
3328 invisible from every <tt>XOP</tt> list, even if it would have
3329 privileges associated with one or more of the lists.
3330 <i>Implementation note: One could conceivably change the <tt>XOP
3331 LIST</tt> commands to list all entriess in intermediate or extreme
3332 ranges; for example, nicknames with an access level between
3333 <tt>ACCLEV_AOP</tt> and <tt>ACCLEV_SOP</tt> could be shown on the
3334 AOP list, and nicknames with an access level below
3335 <tt>ACCLEV_NOP</tt> could be shown on the NOP list.</i></li>
3336
3337 <li class="spaced">If the channel's privilege levels are changed (such as
3338 with the <tt>LEVELS</tt> command), the <tt>XOP</tt> commands may no
3339 longer perform as their help messages describe, because the XOP
3340 lists are associated with hardcoded access levels rather than
3341 specific privileges. <i>Implementation note: Attempting to base
3342 the lists on privilege levels could have unusual results if, for
3343 example, the auto-op privilege was lowered below auto-voice.</i></li>
3344 </ul>
3345
3346 <p>The commands themselves are handled by a single central routine,
3347 <tt>handle_xop()</tt>, which is called from each command's particular
3348 handler with the appropriate access level. <tt>handle_xop()</tt> works
3349 much like <tt>do_access()</tt> from <tt>access-levels.c</tt> (in fact, it
3350 is a modified copy of <tt>do_access()</tt>, and its subroutines are
3351 likewise derived from the handlers for the <tt>ACCESS</tt> subcommands).
3352 Response messages include the list name (SOP, AOP, etc.) as a parameter in
3353 the message, and this name is determined based on the command's access
3354 level using the <tt>XOP_LISTNAME</tt> macro at the top of the file.</p>
3355
3356 <p class="backlink"><a href="#top">Back to top</a></p>
3357
3358 <!------------------------------------------------------------------------>
3359 <hr/>
3360
3361 <h3 class="subsection-title" id="s5">7-5. MemoServ</h3>
3362
3363 <p>The MemoServ pseudoclient serves as an adjunct to NickServ, allowing
3364 short messages (memos) to be sent between users and storing those messages
3365 for the recipient. Like other pseudoclients, the majority of MemoServ's
3366 functionality is implemented in the <tt>memoserv/main</tt> module,
3367 described below in <a href="#s5-1">section 7-5-1</a>; additional modules
3368 allow users to maintain "ignore" lists (<tt>memoserv/ignore</tt>,
3369 <a href="#s5-2">section 7-5-2</a>) and have memos forwarded via E-mail
3370 (<tt>memoserv/forward</tt>, <a href="#s5-3">section 7-5-3</a>).</p>
3371
3372 <p class="backlink"><a href="#top">Back to top</a></p>
3373
3374
3375 <h4 class="subsubsection-title" id="s5-1">7-5-1. MemoServ core functionality</h4>
3376
3377 <p>Unlike OperServ, NickServ, and ChanServ, MemoServ only provides
3378 additional functionality to users (nicknames and, to an extent, channels)
3379 already registered with Services. For this reason, the main MemoServ
3380 code is comparatively simple, and the <tt>memoserv/main</tt> module is
3381 implemented by a single source file, <tt>main.c</tt>. There is also a
3382 header file, <tt>memoserv.h</tt>, containing structures and definitions
3383 used by MemoServ.</p>
3384
3385 <p class="backlink"><a href="#top">Back to top</a></p>
3386
3387
3388 <h5 class="subsubsubsection-title" id="s5-1-1">7-5-1-1. Memo data structures</h5>
3389
3390 <p>The structure used to store memos are defined in the header file
3391 <tt>memoserv.h</tt>. Each memo is stored in a structure called
3392 (appropriately enough) <tt>Memo</tt>, and the set of memos belonging to a
3393 particular nickname group is stored in a <tt>MemoInfo</tt> structure. The
3394 <tt>Memo</tt> structure contains the following fields:</p>
3395
3396 <dl>
3397 <dt><tt>uint32 <b>number</b></tt></dt>
3398 <dd>The index number associated with this memo, for use with MemoServ
3399 commands such as <tt>READ</tt> and <tt>DEL</tt>. Note that while
3400 the array of memos in a <tt>MemoInfo</tt> structure is kept free of
3401 holes caused by memo deletions, memo index numbers do not change
3402 except as a result of the <tt>RENUMBER</tt> command, so there is
3403 not a one-to-one mapping between the two.</dd>
3404
3405 <dt><tt>int16 <b>flags</b></tt></dt>
3406 <dd>Flags associated with the memo. Zero or more of the following
3407 constants, OR'd together:
3408 <ul>
3409 <li><b><tt>MF_UNREAD</tt>:</b> The memo has not yet been read.</li>
3410 <li><b><tt>MF_EXPIREOK</tt>:</b> The memo is allowed to expire.
3411 <i>Implementation note: The sense of this flag is opposite
3412 that of MemoServ's design, which expires any memos except
3413 those explicitly locked with the <tt>SAVE</tt> command.
3414 This was done to keep compatibility with memos sent using
3415 old versions of Services, in which memos did not expire;
3416 rather than explicitly adding a "locked" flag to every memo
3417 when loading databases from such a version, the flag takes
3418 advantage of the fact that the corresponding bit in such
3419 memos is zero. This way, for a memo to expire, the flag
3420 must be explicitly enabled by the new version when the memo
3421 is sent.</i></li>
3422 </ul></dd>
3423
3424 <dt><tt>time_t <b>time</b></tt></dt>
3425 <dd>The timestamp when the memo was sent.</dd>
3426
3427 <dt><tt>time_t <b>firstread</b></tt></dt>
3428 <dd>The time at which the memo was first read by its recipient. This
3429 is stored to ensure that an unread memo does not expire immediately
3430 after it is first read (the <tt>MSExpireDelay</tt> configuration
3431 option controls how long MemoServ will wait after this timestamp
3432 before expiring the memo).</dd>
3433
3434 <dt><tt>char <b>sender</b>[NICKMAX]</tt></dt>
3435 <dd>The nickname of the client that sent the memo.</dd>
3436
3437 <dt><tt>char *<b>channel</b></tt></dt>
3438 <dd>For memos sent to channels, the name of the channel to which the
3439 memo was sent. <tt>NULL</tt> for other memos.</dd>
3440
3441 <dt><tt>char *<b>text</b></tt></dt>
3442 <dd>The text of the memo.</dd>
3443 </dl>
3444
3445 <p>The <tt>MemoInfo</tt> structure contains:</p>
3446
3447 <dl>
3448 <dt><tt>Memo *<b>memos</b></tt>
3449 <br/><tt>int16 <b>memos_count</b></tt></dt>
3450 <dd>A variable-length array containing the memos associated with this
3451 structure.</dd>
3452
3453 <dt><tt>int16 <b>memomax</b></tt></dt>
3454 <dd>The maximum number of memos this nickname group is allowed to have
3455 stored. Either a nonnegative literal value (zero is allowed, and
3456 means that the nickname group cannot receive any memos at all), or
3457 one of the following constants:
3458 <ul>
3459 <li><b><tt>MEMOMAX_UNLIMITED</tt>:</b> There is no limit on the
3460 number of nicknames that can be stored.</li>
3461 <li><b><tt>MEMOMAX_DEFAULT</tt>:</b> The default limit, set by the
3462 <tt>MSMaxMemos</tt> configuration option, is used. (If
3463 <tt>MSMaxMemos</tt> is changed, the new limit will be
3464 automatically applied.)</li>
3465 </ul>
3466 The constant <tt>MEMOMAX_MAX</tt> is also provided to give the
3467 largest possible maximum value (a side-effect of storing the value
3468 in 16 bits).</dd>
3469 </dl>
3470
3471 <p>Each <tt>MemoInfo</tt> structure is stored as part of the corresponding
3472 nickname group's <tt>NickGroupInfo</tt> structure (see
3473 <a href="#s3-1-1">section 7-3-1-1</a>). In previous versions, channels had
3474 associated memo lists as well, but this feature was removed for version 5.1
3475 in favor of the current system of distributing channel memos to privileged
3476 users.</p>
3477
3478 <p>There are two more constants in <tt>memoserv.h</tt>:
3479 <tt>MS_RECEIVE_PRI_CHECK</tt> and <tt>MS_RECEIVE_PRI_DELIVER</tt>. These
3480 are callback priorities that can be used with <tt>add_callback_pri()</tt>
3481 to allow a "<tt>receive memo</tt>" callback function to ensure it is called
3482 before functions which try to deliver the memo. Both the
3483 <tt>memoserv/ignore</tt> and <tt>memoserv/forward</tt> modules take
3484 advantage of these constants.</p>
3485
3486 <p class="backlink"><a href="#top">Back to top</a></p>
3487
3488
3489 <h5 class="subsubsubsection-title" id="s5-1-2">7-5-1-2. The <tt>memoserv/main</tt> module</h5>
3490
3491 <p>The <tt>memoserv/main</tt> module is defined in the file <tt>main.c</tt>,
3492 and aside from the lack of any auxiliary source files, its structure is
3493 more or less the same as that of the other pseudoclients' core modules.</p>
3494
3495 <p>Since, as mentioned above, the <tt>MemoInfo</tt> structures containing
3496 memo data are stored as part of the corresponding <tt>NickGroupInfo</tt>
3497 structures, special handling is required when moving the data to or from
3498 persistent storage. MemoServ uses iterator functions for the
3499 <tt>MemoInfo</tt> table that in turn iterate through <tt>NickGroupInfo</tt>
3500 structures, and sets up a dummy record containing each record's associated
3501 nickname group ID, much like the <tt>nickserv/access</tt> module (see
3502 <a href="#s3-2">section 7-3-2</a>). For individial <tt>Memo</tt> records,
3503 an additional iterator is used to loop through each memo in every
3504 <tt>MemoInfo</tt> structure.</p>
3505
3506 <p>Most MemoServ actions are implemented by separate routines in the
3507 "MemoServ private routines" section of the file, rather than directly in
3508 the command handlers. These functions are:</p>
3509 <ul>
3510 <li><b><tt>send_memo()</tt></b> and <b><tt>send_chan_memo()</tt></b>,
3511 which send memos to users and channels respectively;</li>
3512 <li><b><tt>list_memo()</tt></b>, which sends the calling client a one-line
3513 description of a memo, and <b><tt>list_memo_callback()</tt></b>, a
3514 callback function to do the same thing;</li>
3515 <li><b><tt>read_memo()</tt></b> and <b><tt>read_memo_callback</tt></b>,
3516 which display the text of a memo;</li>
3517 <li><b><tt>save_memo()</tt></b> and <b><tt>save_memo_callback</tt></b>,
3518 which mark memos as non-expiring; and</li>
3519 <li><b><tt>del_memo()</tt></b> and <b><tt>del_memo_callback()</tt></b>,
3520 which delete memos.</li>
3521 </ul>
3522
3523 <p>Other utility routines include:</p>
3524
3525 <dl>
3526 <dt><tt>void <b>check_memos</b>(User *<i>u</i>)</tt></dt>
3527 <dd>Checks whether the given client's nickname group has any unread
3528 memos, sending an appropriate message to the client if so (and if
3529 the <tt>NF_MEMO_SIGNON</tt> flag is set for the nickname group).
3530 Called by the "<tt>user create</tt>" callback function
3531 <tt>do_user_create()</tt> if the client is recognized.</dd>
3532
3533 <dt><tt>void <b>expire_memos</b>(MemoInfo *<i>mi</i>)</tt></dt>
3534 <dd>Deletes all memos in the given <tt>MemoInfo</tt> structure that
3535 are eligible for expiration.</dd>
3536
3537 <dt><tt>MemoInfo *<b>get_memoinfo</b>(const char *<i>name</i>, NickGroupInfo **<i>owner_ret</i>, int *<i>error_ret</i></tt></dt>
3538 <dd>Returns the <tt>MemoInfo</tt> structure corresponding to the given
3539 nickname, or <tt>NULL</tt> on error. On success,
3540 <tt>*<i>owner_ret</i></tt> is set to point to the
3541 <tt>NickGroupInfo</tt> structure for the corresponding nickname
3542 group; on error, <tt>*<i>error_ret</i></tt> is set to one of the
3543 following error codes:
3544 <ul>
3545 <li><b>GMI_INTERR</b>: An internal error occurred.</li>
3546 <li><b>GMI_FORBIDDEN</b>: The given nickname is forbidden.</li>
3547 <li><b>GMI_SUSPENDED</b>: The given nickname is suspended.</li>
3548 <li><b>GMI_NOTFOUND</b>: The given nickname is not registered.</li>
3549 </ul>
3550 <i>Implementation note: This function's primary purpose of handling
3551 both nicknames and channel names transparently was obsoleted with
3552 the redesign of channel memo handling; however, the function still
3553 serves the purpose of checking for unregistered, forbidden, or
3554 suspended nicknames, eliminating the necessity to include such
3555 checks directly in every command handler.</i></dd>
3556 </dl>
3557
3558 <p>The command handlers are for the most part simple, only needing to parse
3559 parameters and call the appropriate utility routine. The two commands
3560 which are implemented directly, <tt>SET</tt> and <tt>INFO</tt>, are mostly
3561 branching trees for the various nickname options and statuses.</p>
3562
3563 <p class="backlink"><a href="#top">Back to top</a></p>
3564
3565
3566 <h4 class="subsubsection-title" id="s5-2">7-5-2. Memo ignore lists</h4>
3567
3568 <p>The <tt>memoserv/ignore</tt> module was added to allow users a way to
3569 block memos from unwanted senders such as spammers. The module is
3570 implemented by the source file <tt>ignore.c</tt>.</p>
3571
3572 <p>For the most part, <tt>ignore.c</tt> works in the same way as the
3573 <tt>nickserv/access</tt> and <tt>nickserv/autojoin</tt> modules. The
3574 one routine unique to <tt>memoserv/ignore</tt> is the
3575 <tt>check_if_ignored()</tt> routine, added as a callback function to the
3576 core MemoServ module's "<tt>receive memo</tt>" callback at priority
3577 <tt>MS_RECEIVE_PRI_CHECK</tt>. The routine runs through the nickname
3578 group's ignore list twoce: the first time, it treats each entry as a
3579 <tt><i>Nick</i>!<i>user</i>@<i>host</i></tt> mask which is compared against
3580 that of the memo sender, while the second time, it treats each entry as a
3581 nickname, and the memo is blocked if that nickname's nickname group ID
3582 matches that of the sender (thus proventing malicious clients from evading
3583 the block by simply changing to another linked nick). If thd memo is
3584 blocked, the routine returns the language string index
3585 <tt>MEMO_C_GETS_NO_MEMOS</tt> (the same as is used if the target has a
3586 memo limit of zero), to prevent leaking information about the ignore list
3587 contents.</p>
3588
3589 <p class="backlink"><a href="#top">Back to top</a></p>
3590
3591
3592 <h4 class="subsubsection-title" id="s5-3">7-5-3. Memo forwarding</h4>
3593
3594 <p>The <tt>memoserv/forward</tt> module, defined in the source file
3595 <tt>forward.c</tt>, provides an interface between memos in Services and an
3596 external mail system. As such, one of its prerequisite modules (other than
3597 <tt>memoserv/main</tt>, of course) is <tt>nickserv/mail-auth</tt>, to
3598 reduce the possibility of Services being abused to send mail to arbitrary
3599 addresses.</p>
3600
3601 <p>The module includes two methods of forwarding memos: manual and
3602 automatic. The former, manual forwarding, is done through the
3603 <tt>FORWARD</tt> command, implemented by the <tt>do_forward()</tt> routine
3604 and its subroutines <tt>fwd_memo()</tt> and <tt>fwd_memo_callback()</tt>.
3605 As with other commands that allow users to send mail via Services, the
3606 command handler includes a check that the command is not used more
3607 frequently than the configuration option <tt>MSForwardDelay</tt> specifies.
3608 If this and the other checks pass, the command handler takes one of two
3609 actions, depending on its parameter. If "<tt>ALL</tt>" was given, then
3610 <tt>fwd_memo()</tt> is called for each memo in the calling client's
3611 <tt>MemoInfo</tt> structure; otherwise, the parameter is passed to
3612 <tt>process_numlist()</tt> to call the <tt>fwd_memo_callback()</tt>
3613 callback function (which in turn calls <tt>fwd_memo()</tt>) for each memo
3614 specified in the index list.</p>
3615
3616 <p><tt>fwd_memo()</tt> itself does not perform the actual sending of the
3617 mail message; rather, it accumulates message body text in its parameters
3618 <tt>char **<i>p_body</i></tt> and <tt>int *<i>p_bodylen</i></tt> (both of
3619 which are modified as a result of the routine). This allows the caller to
3620 combine multiple memos into a single message without knowing ahead of time
3621 how many or which memos are to be sent.</p>
3622
3623 <p>The second method of forwarding, automatic forwarding on receipt, is
3624 implemented by the <tt>do_receive_memo()</tt> function, attached to the
3625 MemoServ "<tt>receive memo</tt>" callback, along with the
3626 <tt>do_set_forward()</tt> option handler (attached to the "<tt>SET</tt>"
3627 callback) to set forwarding options for a nickname group. Of the
3628 forwarding options, <tt>ON</tt> (flag <tt>NF_MEMO_FWD</tt>) and
3629 <tt>OFF</tt> (no flags set) are fairly obvious. For <tt>COPY</tt> (flags
3630 <tt>NF_MEMO_FWD</tt> and <tt>NF_MEMO_FWDCOPY</tt>), however, it is worth
3631 noting that (as also mentioned in the user's manual and help messages)
3632 memos will be rejected when the recipient has a full list of memos. This
3633 is partly a result of the callback implementation, in the sense that the
3634 check for a full memo list is made before the callback is ever called; but
3635 it also ensures that every memo received by the user is either processed
3636 completely (both forwarded and saved) or not at all. This can be important
3637 if, for example, a user uses <tt>SET FORWARD COPY</tt> to save copies of
3638 memos to an archival E-mail address, but only uses Services to actually
3639 read the memos. If a memo that would overflow the list was nonetheless
3640 forwarded and treated as "sent", the sender would be left wondering why the
3641 recipient was not responding to the purportedly delivered memo.</p>
3642
3643 <p class="backlink"><a href="#top">Back to top</a></p>
3644
3645 <!------------------------------------------------------------------------>
3646 <hr/>
3647
3648 <h3 class="subsection-title" id="s6">7-6. StatServ</h3>
3649
3650 <p>The StatServ pseudoclient is intended to record and provide network
3651 statistics; however, mostly due to lack of developer interest, it has
3652 floundered. The module is defined in the <tt>modules/statserv</tt>
3653 directory by a single source file, <tt>main.c</tt>, and an accompanying
3654 header file, <tt>statserv.h</tt>.</p>
3655
3656 <p class="backlink"><a href="#top">Back to top</a></p>
3657
3658
3659 <h4 class="subsubsection-title" id="s6-1">7-6-1. StatServ data structures</h4>
3660
3661 <p>The current implementation of StatServ only records data for servers.
3662 This data is stored in a <tt>ServerStats</tt> structure, defined in
3663 <tt>statserv.h</tt> and containing the following fields:</p>
3664
3665 <dl>
3666 <dt><tt>ServerStats *<b>next</b>, *<b>prev</b></tt></dt>
3667 <dd>Used to maintain the linked list of <tt>ServerStats</tt>
3668 structures.</dd>
3669
3670 <dt><tt>char *<b>name</b></tt></dt>
3671 <dd>The name of the server to which this structure applies.</dd>
3672
3673 <dt><tt>time_t <b>t_join</b></tt></dt>
3674 <dd>The timestamp at which the server most recently joined the network.
3675 Zero if the server is not currently connected.</dd>
3676
3677 <dt><tt>time_t <b>t_quit</b></tt></dt>
3678 <dd>The timestamp at which the server last disconnected. Zero if
3679 Services has never seen the server disconnect.</dd>
3680
3681 <dt><tt>char *<b>quit_message</b></tt></dt>
3682 <dd>The quit message used the last time the server disconnected.
3683 <tt>NULL</tt> if Services has never seen the server disconnect.</dd>
3684
3685 <dt><tt>int <b>usercnt</b>, <b>opercnt</b></tt></dt>
3686 <dd>The current number of clients and IRC operators on the server.</dd>
3687 </dl>
3688
3689 <p>As the data has no direct references to other data stored persistently,
3690 saving the <tt>ServerStats</tt> records is straightforward.</p>
3691
3692 <p>There are also commented-out definitions for <tt>MinMax</tt> and
3693 <tt>MinMaxHistory</tt> structures, and <tt>MinMaxHistory</tt> fields in
3694 <tt>ServerStats</tt>; these were originally intended for keeping a history
3695 of client and operator counts on each server, but this functionality was
3696 never implemented.</p>
3697
3698 <p class="backlink"><a href="#top">Back to top</a></p>
3699
3700
3701 <h4 class="subsubsection-title" id="s6-2">7-6-2. The StatServ module</h4>
3702
3703 <p>The module itself, defined in <tt>main.c</tt>, is likewise quite simple.
3704 It follows the general layout of other pseudoclient core modules, though it
3705 only has two commands (other than <tt>HELP</tt>) and a few callback
3706 routines.</p>
3707
3708 <p>The two commands, <tt>SERVERS</tt> and <tt>USERS</tt>, are handled by
3709 <tt>do_servers()</tt> and <tt>do_users()</tt> respectively. The latter
3710 needs no additional explanation, as it only sends the calling client the
3711 user and operator counts it maintains internally (via the client-related
3712 callbacks mentioned below). <tt>do_servers()</tt> is only slightly more
3713 complex, handling four distinct subcommands. Three of these
3714 (<tt>STATS</tt>, <tt>LIST</tt>, and <tt>VIEW</tt>) extract information from
3715 the <tt>ServerStats</tt> structures and send them to the calling client;
3716 the last, <tt>DELETE</tt>, allows a structure to be deleted, and is
3717 protected by an <tt>is_services_admin()</tt> check in the <tt>if</tt>
3718 chain.</p>
3719
3720 <p>In order to keep track of statistics, StatServ naturally relies on
3721 callbacks. To watch for connecting and disconnecting servers, StatServ
3722 adds callback functions to the core's "<tt>server create</tt>" and
3723 "<tt>server delete</tt>" callbacks; these functions update the relevant
3724 <tt>ServerStats</tt> structures as servers join and leave the network, with
3725 <tt>stats_do_server()</tt> (the "<tt>server create</tt>" handler) creating
3726 a new <tt>ServerStats</tt> structure if it sees a server connect that is
3727 not recorded in the <tt>ServerStats</tt> structure table.</p>
3728
3729 <p>StatServ also uses the "<tt>user create</tt>", "<tt>user delete</tt>",
3730 and "<tt>user MODE</tt>" callbacks to keep track of the number of clients
3731 and IRC operators on the network, stored in the file-scope variables
3732 <tt>usercnt</tt> and <tt>opcnt</tt> respectively. Note that this overlaps
3733 slightly with the maximum client count maintained by OperServ; a good
3734 argument could be made for moving this functionality to StatServ as well,
3735 but it has been left in OperServ for historical reasons (the maximum client
3736 count monitoring functionality has been part of OperServ since the earliest
3737 versions of Services, long before StatServ existed).</p>
3738
3739 <p class="backlink"><a href="#top">Back to top</a></p>
3740
3741 <!------------------------------------------------------------------------>
3742 <hr/>
3743
3744 <h3 class="subsection-title" id="s7">7-7. Miscellaneous pseudoclients</h3>
3745
3746 <p>Aside from the standard pseudoclients listed above, there are two
3747 additional pseudoclients, HelpServ and DevNull, provided in case they can
3748 be of use. These pseudoclients are disabled in the default Services
3749 configuration. These modules are so simple as to not warrant their own
3750 subdirectories, and are stored in the <tt>modules/misc</tt> directory.</p>
3751
3752 <p class="backlink"><a href="#top">Back to top</a></p>
3753
3754
3755 <h4 class="subsubsection-title" id="s7-1">7-7-1. HelpServ</h4>
3756
3757 <p>The HelpServ pseudoclient, defined in <tt>modules/misc/helpserv.c</tt>,
3758 uses the parameters given in each <tt>PRIVMSG</tt> it receives to form a
3759 pathname for a text file, which (if it exists) is then sent to the calling
3760 client as <tt>NOTICE</tt>s. The pathname is formed by concatenating the
3761 path given by the <tt>HelpDir</tt> module configuration setting (the
3762 example configuration file uses <tt>helpfiles</tt>, relative to the
3763 Services data directory) with each of its space-separated parameters,
3764 inserting a path separator ("<tt>/</tt>") between each element. To allow
3765 the parameter to be case-insensitive even when using case-sensitive
3766 filesystems, all uppercase characters in the parameters are lowercased.</p>
3767
3768 <p>Since this involves access to a file specified by an arbitrary
3769 user-specified string, the routine must take care not to allow access to
3770 inappropriate files. This is done by replacing all slashes and periods in
3771 the string with underscores, to prevent a malicious user from specifying
3772 a parameter like "<tt>../../../../../etc/passwd</tt>". (If there are
3773 explicit symbolic links to parent directories, of course, HelpServ will
3774 happily follow them.) <i>Implementation note: As a general rule, when
3775 sanitizing user input like this it is better to make a set of explicitly
3776 allowed characters and delete or convert anything outside that set.
3777 However, pathnames on Unix systems are simple and well defined:
3778 disregarding the effects of symbolic links, only a slash can allow access
3779 to file entries outside of the current directory, and "<tt>.</tt>" and
3780 "<tt>..</tt>" are the only entries that are automatically created within
3781 each directory, so the set of allowed characters is essentially "everything
3782 except <tt>/</tt> and <tt>.</tt>".</i></p>
3783
3784 <p>In the earliest versions of Services, HelpServ was a standard
3785 pseudoclient, and other pseudoclients made use of its functionality to
3786 display their own help messages, which were stored as text files under the
3787 <tt>data/helpfiles</tt> directory. However, the help messages were later
3788 moved to string data stored directly in the executable file, and then to
3789 the current model of language files, diluting the usefulness of HelpServ
3790 itself. The module has nonetheless been left in Services in case it is
3791 useful for things such as providing network information.</p>
3792
3793 <p class="backlink"><a href="#top">Back to top</a></p>
3794
3795
3796 <h4 class="subsubsection-title" id="s7-2">7-7-2. DevNull</h4>
3797
3798 <p>The DevNull pseudoclient, defined in <tt>modules/misc/devnull.c</tt>, is
3799 an extremely simple pseudoclient which, like its Unix namesake
3800 <tt>/dev/null</tt>, simply discards any <tt>PRIVMSG</tt>s sent to it. It
3801 is not particularly useful in the ordinary course of events, but the author
3802 has made use of it as a default <tt>/query</tt> target to prevent messages
3803 from going to unintended users.</p>
3804
3805 <p class="backlink"><a href="#top">Back to top</a></p>
3806
3807 <!------------------------------------------------------------------------>
3808 <hr/>
3809
3810 <p class="backlink"><a href="6.html">Previous section: Database handling</a> |
3811 <a href="index.html">Table of Contents</a> |
3812 <a href="8.html">Next section: Other modules</a></p>
3813
3814 </body>
3815 </html>