ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/user.c
Revision: 1644
Committed: Tue Nov 6 22:20:16 2012 UTC (11 years, 5 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid/trunk/src/s_user.c
File size: 40547 byte(s)
Log Message:
- More config subsystem cleanups

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * s_user.c: User related functions.
4     *
5     * Copyright (C) 2002 by the past and present ircd coders, and others.
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20     * USA
21     *
22 knight 31 * $Id$
23 adx 30 */
24    
25     #include "stdinc.h"
26 michael 1011 #include "list.h"
27 adx 30 #include "s_user.h"
28     #include "s_misc.h"
29     #include "channel.h"
30     #include "channel_mode.h"
31     #include "client.h"
32     #include "fdlist.h"
33     #include "hash.h"
34     #include "irc_string.h"
35     #include "sprintf_irc.h"
36     #include "s_bsd.h"
37     #include "ircd.h"
38     #include "listener.h"
39     #include "motd.h"
40     #include "numeric.h"
41 michael 1309 #include "conf.h"
42     #include "log.h"
43 adx 30 #include "s_serv.h"
44     #include "send.h"
45     #include "supported.h"
46     #include "whowas.h"
47     #include "memory.h"
48     #include "packet.h"
49 michael 982 #include "rng_mt.h"
50 adx 30 #include "userhost.h"
51     #include "hook.h"
52     #include "s_misc.h"
53 michael 1243 #include "parse.h"
54 michael 876 #include "watch.h"
55 adx 30
56 michael 1143
57 adx 30 struct Callback *entering_umode_cb = NULL;
58     struct Callback *umode_cb = NULL;
59    
60     static char umode_buffer[IRCD_BUFSIZE];
61    
62     static void user_welcome(struct Client *);
63 michael 1632 static void report_and_set_user_flags(struct Client *, const struct MaskItem *);
64 adx 30 static int check_xline(struct Client *);
65 michael 1080 static void introduce_client(struct Client *);
66     static const char *uid_get(void);
67 adx 30
68     /* Used for building up the isupport string,
69     * used with init_isupport, add_isupport, delete_isupport
70     */
71    
72     struct Isupport
73     {
74     dlink_node node;
75     char *name;
76     char *options;
77     int number;
78     };
79    
80     static dlink_list support_list = { NULL, NULL, 0 };
81     MessageFile *isupportFile;
82    
83     /* memory is cheap. map 0-255 to equivalent mode */
84     unsigned int user_modes[256] =
85     {
86     /* 0x00 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x0F */
87     /* 0x10 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x1F */
88     /* 0x20 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x2F */
89     /* 0x30 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x3F */
90     0, /* @ */
91     0, /* A */
92     0, /* B */
93 db 849 UMODE_CCONN_FULL, /* C */
94 adx 30 UMODE_DEAF, /* D */
95     0, /* E */
96     0, /* F */
97     UMODE_SOFTCALLERID, /* G */
98 michael 1294 UMODE_HIDDEN, /* H */
99 adx 30 0, /* I */
100     0, /* J */
101     0, /* K */
102     0, /* L */
103     0, /* M */
104     0, /* N */
105     0, /* O */
106     0, /* P */
107     0, /* Q */
108 michael 1175 UMODE_REGONLY, /* R */
109     0, /* S */
110 adx 30 0, /* T */
111     0, /* U */
112     0, /* V */
113     0, /* W */
114     0, /* X */
115     0, /* Y */
116     0, /* Z 0x5A */
117     0, 0, 0, 0, 0, /* 0x5F */
118     0, /* 0x60 */
119     UMODE_ADMIN, /* a */
120     UMODE_BOTS, /* b */
121     UMODE_CCONN, /* c */
122     UMODE_DEBUG, /* d */
123     0, /* e */
124     UMODE_FULL, /* f */
125     UMODE_CALLERID, /* g */
126     0, /* h */
127     UMODE_INVISIBLE, /* i */
128 michael 1158 UMODE_REJ, /* j */
129 adx 30 UMODE_SKILL, /* k */
130     UMODE_LOCOPS, /* l */
131     0, /* m */
132     UMODE_NCHANGE, /* n */
133     UMODE_OPER, /* o */
134     0, /* p */
135     0, /* q */
136 michael 1158 UMODE_REGISTERED, /* r */
137 adx 30 UMODE_SERVNOTICE, /* s */
138     0, /* t */
139     UMODE_UNAUTH, /* u */
140     0, /* v */
141     UMODE_WALLOP, /* w */
142     UMODE_EXTERNAL, /* x */
143     UMODE_SPY, /* y */
144     UMODE_OPERWALL, /* z 0x7A */
145     0,0,0,0,0, /* 0x7B - 0x7F */
146    
147     /* 0x80 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x8F */
148     /* 0x90 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x9F */
149     /* 0xA0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xAF */
150     /* 0xB0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xBF */
151     /* 0xC0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xCF */
152     /* 0xD0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xDF */
153     /* 0xE0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0xEF */
154     /* 0xF0 */ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 0xFF */
155     };
156    
157     void
158     assemble_umode_buffer(void)
159     {
160     unsigned int idx = 0;
161     char *umode_buffer_ptr = umode_buffer;
162    
163 michael 1013 for (; idx < (sizeof(user_modes) / sizeof(user_modes[0])); ++idx)
164 adx 30 if (user_modes[idx])
165     *umode_buffer_ptr++ = idx;
166    
167     *umode_buffer_ptr = '\0';
168     }
169    
170     /* show_lusers()
171     *
172     * inputs - pointer to client
173     * output - NONE
174     * side effects - display to client user counts etc.
175     */
176     void
177     show_lusers(struct Client *source_p)
178     {
179     const char *from, *to;
180    
181     if (!MyConnect(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p))
182     {
183     from = me.id;
184     to = source_p->id;
185     }
186     else
187     {
188     from = me.name;
189     to = source_p->name;
190     }
191    
192 michael 1219 if (!ConfigServerHide.hide_servers || HasUMode(source_p, UMODE_OPER))
193 adx 30 sendto_one(source_p, form_str(RPL_LUSERCLIENT),
194     from, to, (Count.total-Count.invisi),
195     Count.invisi, dlink_list_length(&global_serv_list));
196     else
197     sendto_one(source_p, form_str(RPL_LUSERCLIENT), from, to,
198 michael 56 (Count.total-Count.invisi), Count.invisi, 1);
199 adx 30
200     if (Count.oper > 0)
201     sendto_one(source_p, form_str(RPL_LUSEROP),
202 michael 56 from, to, Count.oper);
203 adx 30
204     if (dlink_list_length(&unknown_list) > 0)
205     sendto_one(source_p, form_str(RPL_LUSERUNKNOWN),
206 michael 56 from, to, dlink_list_length(&unknown_list));
207 adx 30
208     if (dlink_list_length(&global_channel_list) > 0)
209     sendto_one(source_p, form_str(RPL_LUSERCHANNELS),
210 michael 56 from, to, dlink_list_length(&global_channel_list));
211 adx 30
212 michael 1219 if (!ConfigServerHide.hide_servers || HasUMode(source_p, UMODE_OPER))
213 adx 30 {
214     sendto_one(source_p, form_str(RPL_LUSERME),
215 michael 56 from, to, Count.local, Count.myserver);
216 adx 30 sendto_one(source_p, form_str(RPL_LOCALUSERS),
217 michael 56 from, to, Count.local, Count.max_loc,
218     Count.local, Count.max_loc);
219 adx 30 }
220     else
221     {
222     sendto_one(source_p, form_str(RPL_LUSERME),
223 michael 56 from, to, Count.total, 0);
224 adx 30 sendto_one(source_p, form_str(RPL_LOCALUSERS),
225 michael 56 from, to, Count.total, Count.max_tot,
226 adx 30 Count.total, Count.max_tot);
227     }
228    
229     sendto_one(source_p, form_str(RPL_GLOBALUSERS),
230     from, to, Count.total, Count.max_tot,
231     Count.total, Count.max_tot);
232    
233 michael 1219 if (!ConfigServerHide.hide_servers || HasUMode(source_p, UMODE_OPER))
234 adx 30 sendto_one(source_p, form_str(RPL_STATSCONN), from, to,
235 michael 1143 Count.max_loc_con, Count.max_loc_cli, Count.totalrestartcount);
236 adx 30
237 michael 1143 if (Count.local > Count.max_loc_cli)
238     Count.max_loc_cli = Count.local;
239 adx 30
240 michael 1143 if ((Count.local + Count.myserver) > Count.max_loc_con)
241     Count.max_loc_con = Count.local + Count.myserver;
242 adx 30 }
243    
244     /* show_isupport()
245     *
246     * inputs - pointer to client
247     * output - NONE
248     * side effects - display to client what we support (for them)
249     */
250     void
251     show_isupport(struct Client *source_p)
252     {
253     send_message_file(source_p, isupportFile);
254     }
255    
256     /*
257     ** register_local_user
258     ** This function is called when both NICK and USER messages
259     ** have been accepted for the client, in whatever order. Only
260     ** after this, is the USER message propagated.
261     **
262     ** NICK's must be propagated at once when received, although
263     ** it would be better to delay them too until full info is
264     ** available. Doing it is not so simple though, would have
265     ** to implement the following:
266     **
267     ** (actually it has been implemented already for a while) -orabidoo
268     **
269     ** 1) user telnets in and gives only "NICK foobar" and waits
270     ** 2) another user far away logs in normally with the nick
271     ** "foobar" (quite legal, as this server didn't propagate
272     ** it).
273     ** 3) now this server gets nick "foobar" from outside, but
274     ** has alread the same defined locally. Current server
275     ** would just issue "KILL foobar" to clean out dups. But,
276     ** this is not fair. It should actually request another
277     ** nick from local user or kill him/her...
278     */
279     void
280 michael 1080 register_local_user(struct Client *source_p)
281 adx 30 {
282 michael 1115 const char *id = NULL;
283 michael 1632 const struct MaskItem *conf = NULL;
284 adx 30
285     assert(source_p != NULL);
286 michael 1080 assert(source_p == source_p->from);
287 adx 30 assert(MyConnect(source_p));
288 michael 503 assert(!source_p->localClient->registration);
289 adx 30
290 michael 1080 ClearCap(source_p, CAP_TS6);
291 michael 589
292 adx 30 if (ConfigFileEntry.ping_cookie)
293     {
294 michael 1080 if (!IsPingSent(source_p) && source_p->localClient->random_ping == 0)
295 adx 30 {
296 michael 983 do
297     source_p->localClient->random_ping = genrand_int32();
298     while (!source_p->localClient->random_ping);
299    
300 michael 982 sendto_one(source_p, "PING :%u",
301 adx 30 source_p->localClient->random_ping);
302     SetPingSent(source_p);
303     return;
304     }
305    
306     if (!HasPingCookie(source_p))
307     return;
308     }
309    
310 michael 1176 source_p->localClient->last_privmsg = CurrentTime;
311 adx 30 /* Straight up the maximum rate of flooding... */
312     source_p->localClient->allow_read = MAX_FLOOD_BURST;
313    
314 michael 1644 if (!check_client(source_p))
315 adx 30 return;
316    
317     if (valid_hostname(source_p->host) == 0)
318     {
319     sendto_one(source_p, ":%s NOTICE %s :*** Notice -- You have an illegal "
320     "character in your hostname", me.name, source_p->name);
321     strlcpy(source_p->host, source_p->sockhost,
322     sizeof(source_p->host));
323     }
324    
325 michael 1632 conf = source_p->localClient->confs.head->data;
326 adx 30
327     if (!IsGotId(source_p))
328     {
329 michael 1080 char username[USERLEN + 1];
330     const char *p = username;
331 adx 30 unsigned int i = 0;
332    
333 michael 1632 if (IsNeedIdentd(conf))
334 adx 30 {
335 michael 896 ++ServerStats.is_ref;
336 adx 30 sendto_one(source_p, ":%s NOTICE %s :*** Notice -- You need to install "
337     "identd to use this server", me.name, source_p->name);
338     exit_client(source_p, &me, "Install identd");
339     return;
340     }
341    
342 michael 1080 strlcpy(username, source_p->username, sizeof(username));
343 adx 30
344 michael 1632 if (!IsNoTilde(conf))
345 adx 30 source_p->username[i++] = '~';
346    
347 michael 1080 for (; *p && i < USERLEN; ++p)
348 adx 30 if (*p != '[')
349     source_p->username[i++] = *p;
350    
351     source_p->username[i] = '\0';
352     }
353    
354     /* password check */
355 michael 1632 if (!EmptyString(conf->passwd))
356 adx 30 {
357     const char *pass = source_p->localClient->passwd;
358    
359 michael 1632 if (!match_conf_password(pass, conf))
360 adx 30 {
361 michael 896 ++ServerStats.is_ref;
362 adx 30 sendto_one(source_p, form_str(ERR_PASSWDMISMATCH),
363     me.name, source_p->name);
364     exit_client(source_p, &me, "Bad Password");
365     return;
366     }
367     }
368    
369     /* don't free source_p->localClient->passwd here - it can be required
370     * by masked /stats I if there are auth{} blocks with need_password = no;
371     * --adx
372     */
373    
374     /* report if user has &^>= etc. and set flags as needed in source_p */
375 michael 1632 report_and_set_user_flags(source_p, conf);
376 adx 30
377 michael 1080 if (IsDead(source_p))
378 michael 980 return;
379    
380 adx 30 /* Limit clients -
381     * We want to be able to have servers and F-line clients
382     * connect, so save room for "buffer" connections.
383     * Smaller servers may want to decrease this, and it should
384     * probably be just a percentage of the MAXCLIENTS...
385     * -Taner
386     */
387     /* Except "F:" clients */
388     if ((Count.local >= ServerInfo.max_clients + MAX_BUFFER) ||
389     (Count.local >= ServerInfo.max_clients && !IsExemptLimits(source_p)))
390     {
391 michael 1618 sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
392 adx 30 "Too many clients, rejecting %s[%s].",
393 michael 1080 source_p->name, source_p->host);
394 michael 896 ++ServerStats.is_ref;
395 adx 30 exit_client(source_p, &me, "Sorry, server is full - try later");
396     return;
397     }
398    
399     /* valid user name check */
400     if (valid_username(source_p->username) == 0)
401     {
402     char tmpstr2[IRCD_BUFSIZE];
403    
404 michael 1618 sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
405     "Invalid username: %s (%s@%s)",
406 michael 1080 source_p->name, source_p->username, source_p->host);
407 michael 896 ++ServerStats.is_ref;
408 michael 1124 snprintf(tmpstr2, sizeof(tmpstr2), "Invalid username [%s]",
409     source_p->username);
410 adx 30 exit_client(source_p, &me, tmpstr2);
411     return;
412     }
413    
414 michael 592 if (check_xline(source_p))
415 adx 30 return;
416    
417 michael 1115 while (hash_find_id((id = uid_get())) != NULL)
418     ;
419 michael 573
420 michael 1115 strlcpy(source_p->id, id, sizeof(source_p->id));
421     hash_add_id(source_p);
422 adx 30
423 michael 1618 sendto_realops_flags(UMODE_CCONN, L_ALL, SEND_NOTICE,
424 michael 1137 "Client connecting: %s (%s@%s) [%s] {%s} [%s] <%s>",
425 michael 1080 source_p->name, source_p->username, source_p->host,
426 adx 30 ConfigFileEntry.hide_spoof_ips && IsIPSpoof(source_p) ?
427 michael 891 "255.255.255.255" : source_p->sockhost,
428 michael 1632 get_client_class(&source_p->localClient->confs),
429 michael 1137 source_p->info, source_p->id);
430 adx 30
431 michael 1618 sendto_realops_flags(UMODE_CCONN_FULL, L_ALL, SEND_NOTICE,
432 db 849 "CLICONN %s %s %s %s %s %s %s 0 %s",
433 michael 1080 source_p->name, source_p->username, source_p->host,
434 db 849 ConfigFileEntry.hide_spoof_ips && IsIPSpoof(source_p) ?
435 michael 891 "255.255.255.255" : source_p->sockhost,
436 michael 1632 get_client_class(&source_p->localClient->confs),
437 db 849 ConfigFileEntry.hide_spoof_ips && IsIPSpoof(source_p) ?
438 michael 1113 "<hidden>" : source_p->localClient->client_host,
439 db 849 ConfigFileEntry.hide_spoof_ips && IsIPSpoof(source_p) ?
440 michael 1113 "<hidden>" : source_p->localClient->client_server,
441 db 849 source_p->info);
442    
443    
444 adx 30 if (ConfigFileEntry.invisible_on_connect)
445 michael 159 {
446 michael 1219 AddUMode(source_p, UMODE_INVISIBLE);
447 michael 980 ++Count.invisi;
448 michael 159 }
449 adx 30
450     if ((++Count.local) > Count.max_loc)
451     {
452     Count.max_loc = Count.local;
453    
454     if (!(Count.max_loc % 10))
455 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
456     "New Max Local Clients: %d",
457 adx 30 Count.max_loc);
458     }
459    
460     /* Increment our total user count here */
461     if (++Count.total > Count.max_tot)
462     Count.max_tot = Count.total;
463 michael 948 ++Count.totalrestartcount;
464 adx 30
465 michael 1080 assert(source_p->servptr == &me);
466     SetClient(source_p);
467     dlinkAdd(source_p, &source_p->lnode, &source_p->servptr->serv->client_list);
468    
469 adx 30 source_p->localClient->allow_read = MAX_FLOOD_BURST;
470    
471 michael 1125 assert(dlinkFind(&unknown_list, source_p));
472 michael 1013
473 michael 1126 dlink_move_node(&source_p->localClient->lclient_node,
474     &unknown_list, &local_client_list);
475 adx 30
476     user_welcome(source_p);
477     add_user_host(source_p->username, source_p->host, 0);
478     SetUserHost(source_p);
479    
480 michael 1080 introduce_client(source_p);
481 adx 30 }
482    
483     /* register_remote_user()
484     *
485 michael 1080 * inputs - source_p remote or directly connected client
486 adx 30 * - username to register as
487     * - host name to register as
488     * - server name
489     * - realname (gecos)
490     * output - NONE
491     * side effects - This function is called when a remote client
492     * is introduced by a server.
493     */
494     void
495 michael 1080 register_remote_user(struct Client *source_p,
496 michael 56 const char *username, const char *host, const char *server,
497     const char *realname)
498 adx 30 {
499 michael 56 struct Client *target_p = NULL;
500 adx 30
501     assert(source_p != NULL);
502     assert(source_p->username != username);
503    
504     strlcpy(source_p->host, host, sizeof(source_p->host));
505     strlcpy(source_p->username, username, sizeof(source_p->username));
506    
507     /*
508     * coming from another server, take the servers word for it
509     */
510 michael 1169 source_p->servptr = hash_find_server(server);
511 adx 30
512 michael 1618 /*
513     * Super GhostDetect:
514 adx 30 * If we can't find the server the user is supposed to be on,
515     * then simply blow the user away. -Taner
516     */
517     if (source_p->servptr == NULL)
518     {
519 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
520 adx 30 "No server %s for user %s[%s@%s] from %s",
521     server, source_p->name, source_p->username,
522     source_p->host, source_p->from->name);
523 michael 1080 kill_client(source_p->from, source_p, "%s (Server doesn't exist)", me.name);
524 adx 30
525 michael 1219 AddFlag(source_p, FLAGS_KILLED);
526 adx 30 exit_client(source_p, &me, "Ghosted Client");
527     return;
528     }
529    
530     if ((target_p = source_p->servptr) && target_p->from != source_p->from)
531     {
532 michael 1618 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
533 adx 30 "Bad User [%s] :%s USER %s@%s %s, != %s[%s]",
534 michael 1080 source_p->from->name, source_p->name, source_p->username,
535 adx 30 source_p->host, source_p->servptr->name,
536     target_p->name, target_p->from->name);
537 michael 1080 kill_client(source_p->from, source_p,
538 adx 30 "%s (NICK from wrong direction (%s != %s))",
539     me.name, source_p->servptr->name, target_p->from->name);
540 michael 1219 AddFlag(source_p, FLAGS_KILLED);
541 adx 30 exit_client(source_p, &me, "USER server wrong direction");
542     return;
543     }
544    
545 michael 1167 /*
546     * If the nick has been introduced by a services server,
547     * make it a service as well.
548     */
549 michael 1219 if (HasFlag(source_p->servptr, FLAGS_SERVICE))
550     AddFlag(source_p, FLAGS_SERVICE);
551 michael 1167
552 michael 510 /* Increment our total user count here */
553     if (++Count.total > Count.max_tot)
554     Count.max_tot = Count.total;
555    
556 adx 30 SetClient(source_p);
557 michael 889 dlinkAdd(source_p, &source_p->lnode, &source_p->servptr->serv->client_list);
558 adx 30 add_user_host(source_p->username, source_p->host, 1);
559     SetUserHost(source_p);
560    
561 michael 1080 introduce_client(source_p);
562 adx 30 }
563    
564     /* introduce_client()
565     *
566 michael 1080 * inputs - source_p
567 adx 30 * output - NONE
568     * side effects - This common function introduces a client to the rest
569     * of the net, either from a local client connect or
570     * from a remote connect.
571     */
572     static void
573 michael 1080 introduce_client(struct Client *source_p)
574 adx 30 {
575 michael 56 dlink_node *server_node = NULL;
576 adx 30 static char ubuf[12];
577    
578     if (MyClient(source_p))
579     send_umode(source_p, source_p, 0, SEND_UMODES, ubuf);
580     else
581     send_umode(NULL, source_p, 0, SEND_UMODES, ubuf);
582    
583 michael 876 watch_check_hash(source_p, RPL_LOGON);
584    
585 adx 30 if (*ubuf == '\0')
586     {
587     ubuf[0] = '+';
588     ubuf[1] = '\0';
589     }
590    
591 michael 885 DLINK_FOREACH(server_node, serv_list.head)
592     {
593     struct Client *server = server_node->data;
594 adx 30
595 michael 1080 if (server == source_p->from)
596 michael 885 continue;
597    
598 michael 1196 if (IsCapable(server, CAP_SVS))
599     {
600     if (IsCapable(server, CAP_TS6) && HasID(source_p))
601 michael 1559 sendto_one(server, ":%s UID %s %d %lu %s %s %s %s %s %s :%s",
602 michael 1196 source_p->servptr->id,
603     source_p->name, source_p->hopcount+1,
604     (unsigned long)source_p->tsinfo,
605     ubuf, source_p->username, source_p->host,
606     (MyClient(source_p) && IsIPSpoof(source_p)) ?
607     "0" : source_p->sockhost, source_p->id,
608 michael 1559 source_p->svid,
609 michael 1196 source_p->info);
610     else
611 michael 1559 sendto_one(server, "NICK %s %d %lu %s %s %s %s %s :%s",
612 michael 1196 source_p->name, source_p->hopcount+1,
613     (unsigned long)source_p->tsinfo,
614     ubuf, source_p->username, source_p->host,
615 michael 1559 source_p->servptr->name, source_p->svid,
616 michael 1196 source_p->info);
617    
618     }
619 adx 30 else
620 michael 1196 {
621     if (IsCapable(server, CAP_TS6) && HasID(source_p))
622     sendto_one(server, ":%s UID %s %d %lu %s %s %s %s %s :%s",
623     source_p->servptr->id,
624     source_p->name, source_p->hopcount+1,
625     (unsigned long)source_p->tsinfo,
626     ubuf, source_p->username, source_p->host,
627     (MyClient(source_p) && IsIPSpoof(source_p)) ?
628     "0" : source_p->sockhost, source_p->id, source_p->info);
629     else
630     sendto_one(server, "NICK %s %d %lu %s %s %s %s :%s",
631     source_p->name, source_p->hopcount+1,
632     (unsigned long)source_p->tsinfo,
633     ubuf, source_p->username, source_p->host,
634     source_p->servptr->name, source_p->info);
635     }
636 adx 30 }
637     }
638    
639     /* valid_hostname()
640     *
641     * Inputs - pointer to hostname
642     * Output - 1 if valid, 0 if not
643     * Side effects - check hostname for validity
644     *
645     * NOTE: this doesn't allow a hostname to begin with a dot and
646     * will not allow more dots than chars.
647     */
648     int
649     valid_hostname(const char *hostname)
650     {
651     const char *p = hostname;
652    
653     assert(p != NULL);
654    
655 michael 1080 if (*p == '.' || *p == ':')
656 michael 56 return 0;
657 adx 30
658 michael 1080 for (; *p; ++p)
659 adx 30 if (!IsHostChar(*p))
660 michael 56 return 0;
661 adx 30
662 michael 56 return 1;
663 adx 30 }
664    
665     /* valid_username()
666     *
667     * Inputs - pointer to user
668     * Output - 1 if valid, 0 if not
669     * Side effects - check username for validity
670     *
671     * Absolutely always reject any '*' '!' '?' '@' in an user name
672     * reject any odd control characters names.
673     * Allow '.' in username to allow for "first.last"
674     * style of username
675     */
676     int
677     valid_username(const char *username)
678     {
679     int dots = 0;
680     const char *p = username;
681    
682     assert(p != NULL);
683    
684 michael 1080 if (*p == '~')
685 adx 30 ++p;
686    
687     /* reject usernames that don't start with an alphanum
688     * i.e. reject jokers who have '-@somehost' or '.@somehost'
689     * or "-hi-@somehost", "h-----@somehost" would still be accepted.
690     */
691     if (!IsAlNum(*p))
692 michael 56 return 0;
693 adx 30
694     while (*++p)
695     {
696     if ((*p == '.') && ConfigFileEntry.dots_in_ident)
697     {
698 michael 1080 if (++dots > ConfigFileEntry.dots_in_ident)
699 michael 56 return 0;
700 michael 1080 if (!IsUserChar(*(p + 1)))
701 michael 56 return 0;
702 adx 30 }
703     else if (!IsUserChar(*p))
704 michael 56 return 0;
705 adx 30 }
706    
707 michael 56 return 1;
708 adx 30 }
709    
710 michael 1165 /* clean_nick_name()
711     *
712     * input - nickname
713     * - whether it's a local nick (1) or remote (0)
714     * output - none
715     * side effects - walks through the nickname, returning 0 if erroneous
716     */
717     int
718     valid_nickname(const char *nickname, const int local)
719     {
720     const char *p = nickname;
721     assert(nickname && *nickname);
722    
723     /* nicks can't start with a digit or - or be 0 length */
724     /* This closer duplicates behaviour of hybrid-6 */
725     if (*p == '-' || (IsDigit(*p) && local) || *p == '\0')
726     return 0;
727    
728     for (; *p; ++p)
729     if (!IsNickChar(*p))
730     return 0;
731    
732 michael 1431 return p - nickname <= NICKLEN;
733 michael 1165 }
734    
735 adx 30 /* report_and_set_user_flags()
736     *
737     * inputs - pointer to source_p
738 michael 1632 * - pointer to conf for this user
739 adx 30 * output - NONE
740     * side effects - Report to user any special flags
741     * they are getting, and set them.
742     */
743     static void
744 michael 1632 report_and_set_user_flags(struct Client *source_p, const struct MaskItem *conf)
745 adx 30 {
746     /* If this user is being spoofed, tell them so */
747 michael 1632 if (IsConfDoSpoofIp(conf))
748 adx 30 {
749     sendto_one(source_p,
750     ":%s NOTICE %s :*** Spoofing your IP. congrats.",
751     me.name, source_p->name);
752     }
753    
754     /* If this user is in the exception class, Set it "E lined" */
755 michael 1632 if (IsConfExemptKline(conf))
756 adx 30 {
757     SetExemptKline(source_p);
758     sendto_one(source_p,
759     ":%s NOTICE %s :*** You are exempt from K/D/G lines. congrats.",
760     me.name, source_p->name);
761     }
762    
763     /* The else here is to make sure that G line exempt users
764     * do not get noticed twice.
765     */
766 michael 1632 else if (IsConfExemptGline(conf))
767 adx 30 {
768     SetExemptGline(source_p);
769     sendto_one(source_p, ":%s NOTICE %s :*** You are exempt from G lines.",
770     me.name, source_p->name);
771     }
772    
773 michael 1632 if (IsConfExemptResv(conf))
774 adx 30 {
775     SetExemptResv(source_p);
776     sendto_one(source_p, ":%s NOTICE %s :*** You are exempt from resvs.",
777     me.name, source_p->name);
778     }
779    
780     /* If this user is exempt from user limits set it "F lined" */
781 michael 1632 if (IsConfExemptLimits(conf))
782 adx 30 {
783     SetExemptLimits(source_p);
784     sendto_one(source_p,
785     ":%s NOTICE %s :*** You are exempt from user limits. congrats.",
786     me.name,source_p->name);
787     }
788    
789 michael 1632 if (IsConfCanFlood(conf))
790 adx 30 {
791     SetCanFlood(source_p);
792     sendto_one(source_p, ":%s NOTICE %s :*** You are exempt from flood "
793     "protection, aren't you fearsome.",
794     me.name, source_p->name);
795     }
796     }
797    
798     /* change_simple_umode()
799     *
800     * this callback can be hooked to allow special handling of
801     * certain usermodes
802     */
803     static void *
804     change_simple_umode(va_list args)
805     {
806 michael 627 struct Client *client_p;
807 adx 30 struct Client *source_p;
808     int what;
809     unsigned int flag;
810    
811 michael 627 client_p = va_arg(args, struct Client *);
812 adx 30 source_p = va_arg(args, struct Client *);
813     what = va_arg(args, int);
814     flag = va_arg(args, unsigned int);
815    
816     if (what == MODE_ADD)
817 michael 1219 AddUMode(source_p, flag);
818 adx 30 else
819 michael 1219 DelUMode(source_p, flag);
820 adx 30
821     return NULL;
822     }
823    
824     /* set_user_mode()
825     *
826     * added 15/10/91 By Darren Reed.
827     * parv[0] - sender
828     * parv[1] - username to change mode for
829     * parv[2] - modes to change
830     */
831     void
832     set_user_mode(struct Client *client_p, struct Client *source_p,
833     int parc, char *parv[])
834     {
835     unsigned int flag, setflags;
836     char **p, *m, buf[IRCD_BUFSIZE];
837     struct Client *target_p;
838     int what = MODE_ADD, badflag = 0, i;
839 michael 56
840     assert(!(parc < 2));
841    
842 adx 30 if ((target_p = find_person(client_p, parv[1])) == NULL)
843     {
844     if (MyConnect(source_p))
845     sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
846     me.name, source_p->name, parv[1]);
847     return;
848     }
849    
850     if (IsServer(source_p))
851     {
852 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
853     "*** Mode for User %s from %s",
854 adx 30 parv[1], source_p->name);
855     return;
856     }
857    
858 michael 1115 if (source_p != target_p)
859 adx 30 {
860     sendto_one(source_p, form_str(ERR_USERSDONTMATCH),
861     me.name, source_p->name);
862     return;
863     }
864    
865     if (parc < 3)
866     {
867     m = buf;
868     *m++ = '+';
869    
870     for (i = 0; i < 128; i++)
871 michael 1219 if (HasUMode(source_p, user_modes[i]))
872 adx 30 *m++ = (char)i;
873     *m = '\0';
874    
875     sendto_one(source_p, form_str(RPL_UMODEIS),
876     me.name, source_p->name, buf);
877     return;
878     }
879    
880     execute_callback(entering_umode_cb, client_p, source_p);
881    
882     /* find flags already set for user */
883     setflags = source_p->umodes;
884    
885     /* parse mode change string(s) */
886     for (p = &parv[2]; p && *p; p++)
887     {
888     for (m = *p; *m; m++)
889     {
890     switch (*m)
891     {
892     case '+':
893     what = MODE_ADD;
894     break;
895     case '-':
896     what = MODE_DEL;
897     break;
898     case 'o':
899     if (what == MODE_ADD)
900     {
901 michael 1219 if (IsServer(client_p) && !HasUMode(source_p, UMODE_OPER))
902 adx 30 {
903     ++Count.oper;
904     SetOper(source_p);
905     }
906     }
907     else
908     {
909     /* Only decrement the oper counts if an oper to begin with
910     * found by Pat Szuta, Perly , perly@xnet.com
911     */
912 michael 1219 if (!HasUMode(source_p, UMODE_OPER))
913 adx 30 break;
914    
915     ClearOper(source_p);
916     Count.oper--;
917    
918     if (MyConnect(source_p))
919     {
920     dlink_node *dm;
921    
922 michael 1632 detach_conf(source_p, CONF_OPER);
923 michael 1219 ClrOFlag(source_p);
924     DelUMode(source_p, ConfigFileEntry.oper_only_umodes);
925 adx 30
926     if ((dm = dlinkFindDelete(&oper_list, source_p)) != NULL)
927     free_dlink_node(dm);
928     }
929     }
930    
931     break;
932    
933     /* we may not get these,
934     * but they shouldnt be in default
935     */
936 michael 1158 case 'r':
937 adx 30 case ' ' :
938     case '\n':
939     case '\r':
940     case '\t':
941     break;
942    
943     default:
944     if ((flag = user_modes[(unsigned char)*m]))
945     {
946 michael 1219 if (MyConnect(source_p) && !HasUMode(source_p, UMODE_OPER) &&
947 adx 30 (ConfigFileEntry.oper_only_umodes & flag))
948     {
949     badflag = 1;
950     }
951     else
952 michael 56 execute_callback(umode_cb, client_p, source_p, what, flag);
953 adx 30 }
954     else
955     {
956     if (MyConnect(source_p))
957     badflag = 1;
958     }
959    
960     break;
961     }
962     }
963     }
964    
965     if (badflag)
966     sendto_one(source_p, form_str(ERR_UMODEUNKNOWNFLAG),
967     me.name, source_p->name);
968    
969 michael 1219 if (HasUMode(source_p, UMODE_NCHANGE) && !HasOFlag(source_p, OPER_FLAG_N))
970 adx 30 {
971 michael 1219 sendto_one(source_p, ":%s NOTICE %s :*** You have no nchange flag;",
972 adx 30 me.name, source_p->name);
973 michael 1219 DelUMode(source_p, UMODE_NCHANGE);
974 adx 30 }
975    
976 michael 1219 if (MyConnect(source_p) && HasUMode(source_p, UMODE_ADMIN) &&
977 michael 1294 !HasOFlag(source_p, OPER_FLAG_ADMIN))
978 adx 30 {
979     sendto_one(source_p, ":%s NOTICE %s :*** You have no admin flag;",
980     me.name, source_p->name);
981 michael 1219 DelUMode(source_p, UMODE_ADMIN);
982 adx 30 }
983    
984 michael 1219 if (!(setflags & UMODE_INVISIBLE) && HasUMode(source_p, UMODE_INVISIBLE))
985 adx 30 ++Count.invisi;
986 michael 1219 if ((setflags & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE))
987 adx 30 --Count.invisi;
988    
989 michael 56 /*
990     * compare new flags with old flags and send string which
991 adx 30 * will cause servers to update correctly.
992     */
993     send_umode_out(client_p, source_p, setflags);
994     }
995    
996     /* send_umode()
997     * send the MODE string for user (user) to connection client_p
998     * -avalon
999 db 849 *
1000     * inputs - client_p
1001     * - source_p
1002     * - int old
1003     * - sendmask mask of modes to send
1004     * - suplied umode_buf
1005     * output - NONE
1006 adx 30 */
1007     void
1008     send_umode(struct Client *client_p, struct Client *source_p,
1009     unsigned int old, unsigned int sendmask, char *umode_buf)
1010     {
1011 michael 1013 char *m = umode_buf;
1012 adx 30 int what = 0;
1013     unsigned int i;
1014     unsigned int flag;
1015    
1016 michael 56 /*
1017     * build a string in umode_buf to represent the change in the user's
1018 adx 30 * mode between the new (source_p->umodes) and 'old'.
1019     */
1020     for (i = 0; i < 128; i++)
1021     {
1022     flag = user_modes[i];
1023     if (!flag)
1024     continue;
1025    
1026     if (MyClient(source_p) && !(flag & sendmask))
1027     continue;
1028    
1029 michael 1219 if ((flag & old) && !HasUMode(source_p, flag))
1030 adx 30 {
1031     if (what == MODE_DEL)
1032     *m++ = (char)i;
1033     else
1034     {
1035     what = MODE_DEL;
1036     *m++ = '-';
1037     *m++ = (char)i;
1038     }
1039     }
1040 michael 1219 else if (!(flag & old) && HasUMode(source_p, flag))
1041 adx 30 {
1042     if (what == MODE_ADD)
1043     *m++ = (char)i;
1044     else
1045     {
1046     what = MODE_ADD;
1047     *m++ = '+';
1048     *m++ = (char)i;
1049     }
1050     }
1051     }
1052    
1053     *m = '\0';
1054    
1055     if (*umode_buf && client_p)
1056 michael 528 sendto_one(client_p, ":%s!%s@%s MODE %s :%s",
1057     source_p->name, source_p->username,
1058     source_p->host, source_p->name, umode_buf);
1059 adx 30 }
1060    
1061     /* send_umode_out()
1062     *
1063     * inputs -
1064     * output - NONE
1065     * side effects - Only send ubuf out to servers that know about this client
1066     */
1067     void
1068     send_umode_out(struct Client *client_p, struct Client *source_p,
1069     unsigned int old)
1070     {
1071 michael 573 char buf[IRCD_BUFSIZE] = { '\0' };
1072 adx 30 dlink_node *ptr = NULL;
1073    
1074 michael 1294 send_umode(NULL, source_p, old, SEND_UMODES, buf);
1075 adx 30
1076 michael 573 if (buf[0])
1077 adx 30 {
1078     DLINK_FOREACH(ptr, serv_list.head)
1079     {
1080     struct Client *target_p = ptr->data;
1081    
1082     if ((target_p != client_p) && (target_p != source_p))
1083 michael 885 sendto_one(target_p, ":%s MODE %s :%s",
1084     ID_or_name(source_p, target_p),
1085     ID_or_name(source_p, target_p), buf);
1086 adx 30 }
1087     }
1088    
1089     if (client_p && MyClient(client_p))
1090     send_umode(client_p, source_p, old, 0xffffffff, buf);
1091     }
1092    
1093     /* user_welcome()
1094     *
1095     * inputs - client pointer to client to welcome
1096     * output - NONE
1097     * side effects -
1098     */
1099     static void
1100     user_welcome(struct Client *source_p)
1101     {
1102     #if defined(__TIME__) && defined(__DATE__)
1103     static const char built_date[] = __DATE__ " at " __TIME__;
1104     #else
1105     static const char built_date[] = "unknown";
1106     #endif
1107    
1108     #ifdef HAVE_LIBCRYPTO
1109     if (source_p->localClient->fd.ssl != NULL)
1110     sendto_one(source_p, ":%s NOTICE %s :*** Connected securely via %s",
1111     me.name, source_p->name,
1112     ssl_get_cipher(source_p->localClient->fd.ssl));
1113     #endif
1114    
1115     sendto_one(source_p, form_str(RPL_WELCOME), me.name, source_p->name,
1116     ServerInfo.network_name, source_p->name);
1117     sendto_one(source_p, form_str(RPL_YOURHOST), me.name, source_p->name,
1118 michael 56 get_listener_name(source_p->localClient->listener), ircd_version);
1119 adx 30 sendto_one(source_p, form_str(RPL_CREATED),
1120 michael 56 me.name, source_p->name, built_date);
1121 adx 30 sendto_one(source_p, form_str(RPL_MYINFO),
1122     me.name, source_p->name, me.name, ircd_version, umode_buffer);
1123     show_isupport(source_p);
1124    
1125     if (source_p->id[0] != '\0')
1126     sendto_one(source_p, form_str(RPL_YOURID), me.name,
1127     source_p->name, source_p->id);
1128    
1129     show_lusers(source_p);
1130    
1131     if (ConfigFileEntry.short_motd)
1132     {
1133 michael 1115 sendto_one(source_p, ":%s NOTICE %s :*** Notice -- motd was last changed at %s",
1134     me.name, source_p->name, ConfigFileEntry.motd.lastChangedDate);
1135 adx 30 sendto_one(source_p,
1136 michael 1115 ":%s NOTICE %s :*** Notice -- Please read the motd if you haven't "
1137     "read it", me.name, source_p->name);
1138 adx 30 sendto_one(source_p, form_str(RPL_MOTDSTART),
1139     me.name, source_p->name, me.name);
1140     sendto_one(source_p, form_str(RPL_MOTD),
1141     me.name, source_p->name,
1142     "*** This is the short motd ***");
1143     sendto_one(source_p, form_str(RPL_ENDOFMOTD),
1144     me.name, source_p->name);
1145     }
1146     else
1147     send_message_file(source_p, &ConfigFileEntry.motd);
1148     }
1149    
1150     /* check_xline()
1151     *
1152     * inputs - pointer to client to test
1153     * outupt - 1 if exiting 0 if ok
1154     * side effects -
1155     */
1156     static int
1157     check_xline(struct Client *source_p)
1158     {
1159 michael 1632 struct MaskItem *conf = NULL;
1160 michael 592 const char *reason = NULL;
1161 adx 30
1162 michael 1632 if ((conf = find_matching_name_conf(CONF_XLINE, source_p->info, NULL, NULL, 0)) ||
1163     (conf = find_matching_name_conf(CONF_RXLINE, source_p->info, NULL, NULL, 0)))
1164 adx 30 {
1165 michael 1632 ++conf->count;
1166 adx 30
1167 michael 1632 if (conf->reason != NULL)
1168     reason = conf->reason;
1169 adx 30 else
1170     reason = "No Reason";
1171    
1172 michael 1618 sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
1173 michael 56 "X-line Rejecting [%s] [%s], user %s [%s]",
1174     source_p->info, reason,
1175     get_client_name(source_p, HIDE_IP),
1176     source_p->sockhost);
1177 adx 30
1178 michael 896 ++ServerStats.is_ref;
1179 michael 1549 exit_client(source_p, &me, "Bad user info");
1180 adx 30 return 1;
1181     }
1182    
1183     return 0;
1184     }
1185    
1186     /* oper_up()
1187     *
1188     * inputs - pointer to given client to oper
1189     * output - NONE
1190 michael 1632 * side effects - Blindly opers up given source_p, using conf info
1191 adx 30 * all checks on passwords have already been done.
1192     * This could also be used by rsa oper routines.
1193     */
1194     void
1195     oper_up(struct Client *source_p)
1196     {
1197 michael 1469 const unsigned int old = source_p->umodes;
1198 michael 1644 const struct MaskItem *conf = source_p->localClient->confs.head->data;
1199 adx 30
1200 michael 56 assert(source_p->localClient->confs.head);
1201    
1202     ++Count.oper;
1203 adx 30 SetOper(source_p);
1204    
1205 michael 1632 if (conf->modes)
1206     AddUMode(source_p, conf->modes);
1207 michael 56 else if (ConfigFileEntry.oper_umodes)
1208 michael 1219 AddUMode(source_p, ConfigFileEntry.oper_umodes);
1209 adx 30
1210 michael 1219 if (!(old & UMODE_INVISIBLE) && HasUMode(source_p, UMODE_INVISIBLE))
1211 michael 882 ++Count.invisi;
1212 michael 1219 if ((old & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE))
1213 michael 882 --Count.invisi;
1214    
1215 adx 30 assert(dlinkFind(&oper_list, source_p) == NULL);
1216     dlinkAdd(source_p, make_dlink_node(), &oper_list);
1217    
1218 michael 1632 AddOFlag(source_p, conf->port);
1219 adx 30
1220 michael 1294 if (HasOFlag(source_p, OPER_FLAG_ADMIN))
1221 michael 1158 AddUMode(source_p, UMODE_ADMIN);
1222 michael 1219 if (!HasOFlag(source_p, OPER_FLAG_N))
1223 michael 1158 DelUMode(source_p, UMODE_NCHANGE);
1224 adx 30
1225 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE, "%s is now an operator",
1226 michael 1458 get_oper_name(source_p));
1227 adx 30 send_umode_out(source_p, source_p, old);
1228     sendto_one(source_p, form_str(RPL_YOUREOPER), me.name, source_p->name);
1229     }
1230    
1231 michael 573 static char new_uid[TOTALSIDUID + 1]; /* allow for \0 */
1232 adx 30
1233 michael 573 int
1234     valid_sid(const char *sid)
1235     {
1236     if (strlen(sid) == IRC_MAXSID)
1237     if (IsDigit(*sid))
1238 michael 582 if (IsAlNum(*(sid + 1)) && IsAlNum(*(sid + 2)))
1239 michael 573 return 1;
1240    
1241     return 0;
1242     }
1243    
1244 adx 30 /*
1245     * init_uid()
1246     *
1247     * inputs - NONE
1248     * output - NONE
1249     * side effects - new_uid is filled in with server id portion (sid)
1250     * (first 3 bytes) or defaulted to 'A'.
1251     * Rest is filled in with 'A'
1252     */
1253     void
1254     init_uid(void)
1255     {
1256     int i;
1257    
1258     memset(new_uid, 0, sizeof(new_uid));
1259    
1260 michael 1115 if (!EmptyString(ServerInfo.sid))
1261 michael 573 strlcpy(new_uid, ServerInfo.sid, sizeof(new_uid));
1262    
1263 michael 1115 for (i = 0; i < IRC_MAXSID; ++i)
1264 adx 30 if (new_uid[i] == '\0')
1265     new_uid[i] = 'A';
1266    
1267 michael 573 /* NOTE: if IRC_MAXUID != 6, this will have to be rewritten */
1268 adx 30 /* Yes nenolod, I have known it was off by one ever since I wrote it
1269     * But *JUST* for you, though, it really doesn't look as *pretty*
1270     * -Dianora
1271     */
1272 michael 573 memcpy(new_uid + IRC_MAXSID, "AAAAA@", IRC_MAXUID);
1273 adx 30
1274     entering_umode_cb = register_callback("entering_umode", NULL);
1275     umode_cb = register_callback("changing_umode", change_simple_umode);
1276     }
1277    
1278     /*
1279     * add_one_to_uid
1280     *
1281     * inputs - index number into new_uid
1282     * output - NONE
1283     * side effects - new_uid is incremented by one
1284     * note this is a recursive function
1285     */
1286     static void
1287     add_one_to_uid(int i)
1288     {
1289 michael 56 if (i != IRC_MAXSID) /* Not reached server SID portion yet? */
1290 adx 30 {
1291     if (new_uid[i] == 'Z')
1292     new_uid[i] = '0';
1293     else if (new_uid[i] == '9')
1294     {
1295     new_uid[i] = 'A';
1296     add_one_to_uid(i-1);
1297     }
1298 michael 573 else
1299     ++new_uid[i];
1300 adx 30 }
1301     else
1302     {
1303 michael 573 /* NOTE: if IRC_MAXUID != 6, this will have to be rewritten */
1304 adx 30 if (new_uid[i] == 'Z')
1305 michael 573 memcpy(new_uid + IRC_MAXSID, "AAAAAA", IRC_MAXUID);
1306 adx 30 else
1307 michael 573 ++new_uid[i];
1308 adx 30 }
1309     }
1310    
1311     /*
1312 michael 573 * uid_get
1313     *
1314     * inputs - struct Client *
1315     * output - new UID is returned to caller
1316     * side effects - new_uid is incremented by one.
1317     */
1318 michael 1080 static const char *
1319     uid_get(void)
1320 michael 573 {
1321     add_one_to_uid(TOTALSIDUID - 1); /* index from 0 */
1322     return new_uid;
1323     }
1324    
1325     /*
1326 adx 30 * init_isupport()
1327     *
1328     * input - NONE
1329     * output - NONE
1330     * side effects - Must be called before isupport is enabled
1331     */
1332     void
1333     init_isupport(void)
1334     {
1335     isupportFile = init_MessageLine();
1336    
1337     add_isupport("CALLERID", NULL, -1);
1338     add_isupport("CASEMAPPING", CASEMAP, -1);
1339 adx 716 add_isupport("DEAF", "D", -1);
1340 adx 30 add_isupport("KICKLEN", NULL, KICKLEN);
1341     add_isupport("MODES", NULL, MAXMODEPARAMS);
1342 michael 1431 add_isupport("NICKLEN", NULL, NICKLEN);
1343 adx 30 #ifdef HALFOPS
1344     add_isupport("PREFIX", "(ohv)@%+", -1);
1345     add_isupport("STATUSMSG", "@%+", -1);
1346     #else
1347     add_isupport("PREFIX", "(ov)@+", -1);
1348     add_isupport("STATUSMSG", "@+", -1);
1349     #endif
1350     add_isupport("TOPICLEN", NULL, TOPICLEN);
1351     }
1352    
1353     /*
1354     * add_isupport()
1355     *
1356     * input - name of supported function
1357     * - options if any
1358     * - number if any
1359     * output - NONE
1360     * side effects - Each supported item must call this when activated
1361     */
1362     void
1363     add_isupport(const char *name, const char *options, int n)
1364     {
1365     dlink_node *ptr;
1366     struct Isupport *support;
1367    
1368     DLINK_FOREACH(ptr, support_list.head)
1369     {
1370     support = ptr->data;
1371     if (irccmp(support->name, name) == 0)
1372     {
1373     MyFree(support->name);
1374     MyFree(support->options);
1375     break;
1376     }
1377     }
1378    
1379     if (ptr == NULL)
1380     {
1381     support = MyMalloc(sizeof(*support));
1382     dlinkAddTail(support, &support->node, &support_list);
1383     }
1384    
1385     DupString(support->name, name);
1386     if (options != NULL)
1387     DupString(support->options, options);
1388     support->number = n;
1389    
1390     rebuild_isupport_message_line();
1391     }
1392    
1393     /*
1394     * delete_isupport()
1395     *
1396     * input - name of supported function
1397     * output - NONE
1398     * side effects - Each supported item must call this when deactivated
1399     */
1400     void
1401     delete_isupport(const char *name)
1402     {
1403     dlink_node *ptr;
1404     struct Isupport *support;
1405    
1406     DLINK_FOREACH(ptr, support_list.head)
1407     {
1408     support = ptr->data;
1409     if (irccmp(support->name, name) == 0)
1410     {
1411     dlinkDelete(ptr, &support_list);
1412     MyFree(support->name);
1413     MyFree(support->options);
1414     MyFree(support);
1415     break;
1416     }
1417     }
1418    
1419     rebuild_isupport_message_line();
1420     }
1421    
1422     /*
1423     * rebuild_isupport_message_line
1424     *
1425     * input - NONE
1426     * output - NONE
1427     * side effects - Destroy the isupport MessageFile lines, and rebuild.
1428     */
1429     void
1430     rebuild_isupport_message_line(void)
1431     {
1432     char isupportbuffer[IRCD_BUFSIZE];
1433     char *p = isupportbuffer;
1434     dlink_node *ptr = NULL;
1435     int n = 0;
1436     int tokens = 0;
1437     size_t len = 0;
1438     size_t reserve = strlen(me.name) + HOSTLEN + strlen(form_str(RPL_ISUPPORT));
1439    
1440     destroy_MessageLine(isupportFile);
1441    
1442     DLINK_FOREACH(ptr, support_list.head)
1443     {
1444     struct Isupport *support = ptr->data;
1445    
1446     p += (n = ircsprintf(p, "%s", support->name));
1447     len += n;
1448    
1449     if (support->options != NULL)
1450     {
1451     p += (n = ircsprintf(p, "=%s", support->options));
1452     len += n;
1453     }
1454    
1455     if (support->number > 0)
1456     {
1457     p += (n = ircsprintf(p, "=%d", support->number));
1458     len += n;
1459     }
1460    
1461     *p++ = ' ';
1462     len++;
1463     *p = '\0';
1464    
1465     if (++tokens == (MAXPARA-2) || len >= (sizeof(isupportbuffer)-reserve))
1466     { /* arbritrary for now */
1467     if (*--p == ' ')
1468 michael 56 *p = '\0';
1469 adx 30
1470     addto_MessageLine(isupportFile, isupportbuffer);
1471     p = isupportbuffer;
1472     len = 0;
1473     n = tokens = 0;
1474     }
1475     }
1476    
1477     if (len != 0)
1478     {
1479     if (*--p == ' ')
1480     *p = '\0';
1481     addto_MessageLine(isupportFile, isupportbuffer);
1482     }
1483     }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision