ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/user.c
Revision: 1618
Committed: Tue Oct 30 21:04:38 2012 UTC (12 years, 10 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid/trunk/src/s_user.c
File size: 40704 byte(s)
Log Message:
- Made m_globops() and ms_globops() use sendto_realops_flags()
- Added message-type parameter to sendto_realops_flags() which can be one of
  SEND_NOTICE, SEND_GLOBAL, SEND_LOCOPS
- Forward-port -r1617

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     static void report_and_set_user_flags(struct Client *, const struct AccessItem *);
64     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 adx 30 const struct AccessItem *aconf = NULL;
284 michael 56 dlink_node *ptr = NULL;
285 adx 30
286     assert(source_p != NULL);
287 michael 1080 assert(source_p == source_p->from);
288 adx 30 assert(MyConnect(source_p));
289 michael 503 assert(!source_p->localClient->registration);
290 adx 30
291 michael 1080 ClearCap(source_p, CAP_TS6);
292 michael 589
293 adx 30 if (ConfigFileEntry.ping_cookie)
294     {
295 michael 1080 if (!IsPingSent(source_p) && source_p->localClient->random_ping == 0)
296 adx 30 {
297 michael 983 do
298     source_p->localClient->random_ping = genrand_int32();
299     while (!source_p->localClient->random_ping);
300    
301 michael 982 sendto_one(source_p, "PING :%u",
302 adx 30 source_p->localClient->random_ping);
303     SetPingSent(source_p);
304     return;
305     }
306    
307     if (!HasPingCookie(source_p))
308     return;
309     }
310    
311 michael 1176 source_p->localClient->last_privmsg = CurrentTime;
312 adx 30 /* Straight up the maximum rate of flooding... */
313     source_p->localClient->allow_read = MAX_FLOOD_BURST;
314    
315 michael 1080 if (!execute_callback(client_check_cb, source_p, source_p->username))
316 adx 30 return;
317    
318     if (valid_hostname(source_p->host) == 0)
319     {
320     sendto_one(source_p, ":%s NOTICE %s :*** Notice -- You have an illegal "
321     "character in your hostname", me.name, source_p->name);
322     strlcpy(source_p->host, source_p->sockhost,
323     sizeof(source_p->host));
324     }
325    
326     ptr = source_p->localClient->confs.head;
327     aconf = map_to_conf(ptr->data);
328    
329     if (!IsGotId(source_p))
330     {
331 michael 1080 char username[USERLEN + 1];
332     const char *p = username;
333 adx 30 unsigned int i = 0;
334    
335     if (IsNeedIdentd(aconf))
336     {
337 michael 896 ++ServerStats.is_ref;
338 adx 30 sendto_one(source_p, ":%s NOTICE %s :*** Notice -- You need to install "
339     "identd to use this server", me.name, source_p->name);
340     exit_client(source_p, &me, "Install identd");
341     return;
342     }
343    
344 michael 1080 strlcpy(username, source_p->username, sizeof(username));
345 adx 30
346     if (!IsNoTilde(aconf))
347     source_p->username[i++] = '~';
348    
349 michael 1080 for (; *p && i < USERLEN; ++p)
350 adx 30 if (*p != '[')
351     source_p->username[i++] = *p;
352    
353     source_p->username[i] = '\0';
354     }
355    
356     /* password check */
357     if (!EmptyString(aconf->passwd))
358     {
359     const char *pass = source_p->localClient->passwd;
360    
361     if (!match_conf_password(pass, aconf))
362     {
363 michael 896 ++ServerStats.is_ref;
364 adx 30 sendto_one(source_p, form_str(ERR_PASSWDMISMATCH),
365     me.name, source_p->name);
366     exit_client(source_p, &me, "Bad Password");
367     return;
368     }
369     }
370    
371     /* don't free source_p->localClient->passwd here - it can be required
372     * by masked /stats I if there are auth{} blocks with need_password = no;
373     * --adx
374     */
375    
376     /* report if user has &^>= etc. and set flags as needed in source_p */
377     report_and_set_user_flags(source_p, aconf);
378    
379 michael 1080 if (IsDead(source_p))
380 michael 980 return;
381    
382 adx 30 /* Limit clients -
383     * We want to be able to have servers and F-line clients
384     * connect, so save room for "buffer" connections.
385     * Smaller servers may want to decrease this, and it should
386     * probably be just a percentage of the MAXCLIENTS...
387     * -Taner
388     */
389     /* Except "F:" clients */
390     if ((Count.local >= ServerInfo.max_clients + MAX_BUFFER) ||
391     (Count.local >= ServerInfo.max_clients && !IsExemptLimits(source_p)))
392     {
393 michael 1618 sendto_realops_flags(UMODE_FULL, L_ALL, SEND_NOTICE,
394 adx 30 "Too many clients, rejecting %s[%s].",
395 michael 1080 source_p->name, source_p->host);
396 michael 896 ++ServerStats.is_ref;
397 adx 30 exit_client(source_p, &me, "Sorry, server is full - try later");
398     return;
399     }
400    
401     /* valid user name check */
402     if (valid_username(source_p->username) == 0)
403     {
404     char tmpstr2[IRCD_BUFSIZE];
405    
406 michael 1618 sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
407     "Invalid username: %s (%s@%s)",
408 michael 1080 source_p->name, source_p->username, source_p->host);
409 michael 896 ++ServerStats.is_ref;
410 michael 1124 snprintf(tmpstr2, sizeof(tmpstr2), "Invalid username [%s]",
411     source_p->username);
412 adx 30 exit_client(source_p, &me, tmpstr2);
413     return;
414     }
415    
416 michael 592 if (check_xline(source_p))
417 adx 30 return;
418    
419 michael 1115 while (hash_find_id((id = uid_get())) != NULL)
420     ;
421 michael 573
422 michael 1115 strlcpy(source_p->id, id, sizeof(source_p->id));
423     hash_add_id(source_p);
424 adx 30
425 michael 1618 sendto_realops_flags(UMODE_CCONN, L_ALL, SEND_NOTICE,
426 michael 1137 "Client connecting: %s (%s@%s) [%s] {%s} [%s] <%s>",
427 michael 1080 source_p->name, source_p->username, source_p->host,
428 adx 30 ConfigFileEntry.hide_spoof_ips && IsIPSpoof(source_p) ?
429 michael 891 "255.255.255.255" : source_p->sockhost,
430     get_client_class(source_p),
431 michael 1137 source_p->info, source_p->id);
432 adx 30
433 michael 1618 sendto_realops_flags(UMODE_CCONN_FULL, L_ALL, SEND_NOTICE,
434 db 849 "CLICONN %s %s %s %s %s %s %s 0 %s",
435 michael 1080 source_p->name, source_p->username, source_p->host,
436 db 849 ConfigFileEntry.hide_spoof_ips && IsIPSpoof(source_p) ?
437 michael 891 "255.255.255.255" : source_p->sockhost,
438 db 849 get_client_class(source_p),
439     ConfigFileEntry.hide_spoof_ips && IsIPSpoof(source_p) ?
440 michael 1113 "<hidden>" : source_p->localClient->client_host,
441 db 849 ConfigFileEntry.hide_spoof_ips && IsIPSpoof(source_p) ?
442 michael 1113 "<hidden>" : source_p->localClient->client_server,
443 db 849 source_p->info);
444    
445    
446 adx 30 if (ConfigFileEntry.invisible_on_connect)
447 michael 159 {
448 michael 1219 AddUMode(source_p, UMODE_INVISIBLE);
449 michael 980 ++Count.invisi;
450 michael 159 }
451 adx 30
452     if ((++Count.local) > Count.max_loc)
453     {
454     Count.max_loc = Count.local;
455    
456     if (!(Count.max_loc % 10))
457 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
458     "New Max Local Clients: %d",
459 adx 30 Count.max_loc);
460     }
461    
462     /* Increment our total user count here */
463     if (++Count.total > Count.max_tot)
464     Count.max_tot = Count.total;
465 michael 948 ++Count.totalrestartcount;
466 adx 30
467 michael 1080 assert(source_p->servptr == &me);
468     SetClient(source_p);
469     dlinkAdd(source_p, &source_p->lnode, &source_p->servptr->serv->client_list);
470    
471 adx 30 source_p->localClient->allow_read = MAX_FLOOD_BURST;
472    
473 michael 1125 assert(dlinkFind(&unknown_list, source_p));
474 michael 1013
475 michael 1126 dlink_move_node(&source_p->localClient->lclient_node,
476     &unknown_list, &local_client_list);
477 adx 30
478     user_welcome(source_p);
479     add_user_host(source_p->username, source_p->host, 0);
480     SetUserHost(source_p);
481    
482 michael 1080 introduce_client(source_p);
483 adx 30 }
484    
485     /* register_remote_user()
486     *
487 michael 1080 * inputs - source_p remote or directly connected client
488 adx 30 * - username to register as
489     * - host name to register as
490     * - server name
491     * - realname (gecos)
492     * output - NONE
493     * side effects - This function is called when a remote client
494     * is introduced by a server.
495     */
496     void
497 michael 1080 register_remote_user(struct Client *source_p,
498 michael 56 const char *username, const char *host, const char *server,
499     const char *realname)
500 adx 30 {
501 michael 56 struct Client *target_p = NULL;
502 adx 30
503     assert(source_p != NULL);
504     assert(source_p->username != username);
505    
506     strlcpy(source_p->host, host, sizeof(source_p->host));
507     strlcpy(source_p->username, username, sizeof(source_p->username));
508    
509     /*
510     * coming from another server, take the servers word for it
511     */
512 michael 1169 source_p->servptr = hash_find_server(server);
513 adx 30
514 michael 1618 /*
515     * Super GhostDetect:
516 adx 30 * If we can't find the server the user is supposed to be on,
517     * then simply blow the user away. -Taner
518     */
519     if (source_p->servptr == NULL)
520     {
521 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
522 adx 30 "No server %s for user %s[%s@%s] from %s",
523     server, source_p->name, source_p->username,
524     source_p->host, source_p->from->name);
525 michael 1080 kill_client(source_p->from, source_p, "%s (Server doesn't exist)", me.name);
526 adx 30
527 michael 1219 AddFlag(source_p, FLAGS_KILLED);
528 adx 30 exit_client(source_p, &me, "Ghosted Client");
529     return;
530     }
531    
532     if ((target_p = source_p->servptr) && target_p->from != source_p->from)
533     {
534 michael 1618 sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
535 adx 30 "Bad User [%s] :%s USER %s@%s %s, != %s[%s]",
536 michael 1080 source_p->from->name, source_p->name, source_p->username,
537 adx 30 source_p->host, source_p->servptr->name,
538     target_p->name, target_p->from->name);
539 michael 1080 kill_client(source_p->from, source_p,
540 adx 30 "%s (NICK from wrong direction (%s != %s))",
541     me.name, source_p->servptr->name, target_p->from->name);
542 michael 1219 AddFlag(source_p, FLAGS_KILLED);
543 adx 30 exit_client(source_p, &me, "USER server wrong direction");
544     return;
545     }
546    
547 michael 1167 /*
548     * If the nick has been introduced by a services server,
549     * make it a service as well.
550     */
551 michael 1219 if (HasFlag(source_p->servptr, FLAGS_SERVICE))
552     AddFlag(source_p, FLAGS_SERVICE);
553 michael 1167
554 michael 510 /* Increment our total user count here */
555     if (++Count.total > Count.max_tot)
556     Count.max_tot = Count.total;
557    
558 adx 30 SetClient(source_p);
559 michael 889 dlinkAdd(source_p, &source_p->lnode, &source_p->servptr->serv->client_list);
560 adx 30 add_user_host(source_p->username, source_p->host, 1);
561     SetUserHost(source_p);
562    
563 michael 1080 introduce_client(source_p);
564 adx 30 }
565    
566     /* introduce_client()
567     *
568 michael 1080 * inputs - source_p
569 adx 30 * output - NONE
570     * side effects - This common function introduces a client to the rest
571     * of the net, either from a local client connect or
572     * from a remote connect.
573     */
574     static void
575 michael 1080 introduce_client(struct Client *source_p)
576 adx 30 {
577 michael 56 dlink_node *server_node = NULL;
578 adx 30 static char ubuf[12];
579    
580     if (MyClient(source_p))
581     send_umode(source_p, source_p, 0, SEND_UMODES, ubuf);
582     else
583     send_umode(NULL, source_p, 0, SEND_UMODES, ubuf);
584    
585 michael 876 watch_check_hash(source_p, RPL_LOGON);
586    
587 adx 30 if (*ubuf == '\0')
588     {
589     ubuf[0] = '+';
590     ubuf[1] = '\0';
591     }
592    
593 michael 885 DLINK_FOREACH(server_node, serv_list.head)
594     {
595     struct Client *server = server_node->data;
596 adx 30
597 michael 1080 if (server == source_p->from)
598 michael 885 continue;
599    
600 michael 1196 if (IsCapable(server, CAP_SVS))
601     {
602     if (IsCapable(server, CAP_TS6) && HasID(source_p))
603 michael 1559 sendto_one(server, ":%s UID %s %d %lu %s %s %s %s %s %s :%s",
604 michael 1196 source_p->servptr->id,
605     source_p->name, source_p->hopcount+1,
606     (unsigned long)source_p->tsinfo,
607     ubuf, source_p->username, source_p->host,
608     (MyClient(source_p) && IsIPSpoof(source_p)) ?
609     "0" : source_p->sockhost, source_p->id,
610 michael 1559 source_p->svid,
611 michael 1196 source_p->info);
612     else
613 michael 1559 sendto_one(server, "NICK %s %d %lu %s %s %s %s %s :%s",
614 michael 1196 source_p->name, source_p->hopcount+1,
615     (unsigned long)source_p->tsinfo,
616     ubuf, source_p->username, source_p->host,
617 michael 1559 source_p->servptr->name, source_p->svid,
618 michael 1196 source_p->info);
619    
620     }
621 adx 30 else
622 michael 1196 {
623     if (IsCapable(server, CAP_TS6) && HasID(source_p))
624     sendto_one(server, ":%s UID %s %d %lu %s %s %s %s %s :%s",
625     source_p->servptr->id,
626     source_p->name, source_p->hopcount+1,
627     (unsigned long)source_p->tsinfo,
628     ubuf, source_p->username, source_p->host,
629     (MyClient(source_p) && IsIPSpoof(source_p)) ?
630     "0" : source_p->sockhost, source_p->id, source_p->info);
631     else
632     sendto_one(server, "NICK %s %d %lu %s %s %s %s :%s",
633     source_p->name, source_p->hopcount+1,
634     (unsigned long)source_p->tsinfo,
635     ubuf, source_p->username, source_p->host,
636     source_p->servptr->name, source_p->info);
637     }
638 adx 30 }
639     }
640    
641     /* valid_hostname()
642     *
643     * Inputs - pointer to hostname
644     * Output - 1 if valid, 0 if not
645     * Side effects - check hostname for validity
646     *
647     * NOTE: this doesn't allow a hostname to begin with a dot and
648     * will not allow more dots than chars.
649     */
650     int
651     valid_hostname(const char *hostname)
652     {
653     const char *p = hostname;
654    
655     assert(p != NULL);
656    
657 michael 1080 if (*p == '.' || *p == ':')
658 michael 56 return 0;
659 adx 30
660 michael 1080 for (; *p; ++p)
661 adx 30 if (!IsHostChar(*p))
662 michael 56 return 0;
663 adx 30
664 michael 56 return 1;
665 adx 30 }
666    
667     /* valid_username()
668     *
669     * Inputs - pointer to user
670     * Output - 1 if valid, 0 if not
671     * Side effects - check username for validity
672     *
673     * Absolutely always reject any '*' '!' '?' '@' in an user name
674     * reject any odd control characters names.
675     * Allow '.' in username to allow for "first.last"
676     * style of username
677     */
678     int
679     valid_username(const char *username)
680     {
681     int dots = 0;
682     const char *p = username;
683    
684     assert(p != NULL);
685    
686 michael 1080 if (*p == '~')
687 adx 30 ++p;
688    
689     /* reject usernames that don't start with an alphanum
690     * i.e. reject jokers who have '-@somehost' or '.@somehost'
691     * or "-hi-@somehost", "h-----@somehost" would still be accepted.
692     */
693     if (!IsAlNum(*p))
694 michael 56 return 0;
695 adx 30
696     while (*++p)
697     {
698     if ((*p == '.') && ConfigFileEntry.dots_in_ident)
699     {
700 michael 1080 if (++dots > ConfigFileEntry.dots_in_ident)
701 michael 56 return 0;
702 michael 1080 if (!IsUserChar(*(p + 1)))
703 michael 56 return 0;
704 adx 30 }
705     else if (!IsUserChar(*p))
706 michael 56 return 0;
707 adx 30 }
708    
709 michael 56 return 1;
710 adx 30 }
711    
712 michael 1165 /* clean_nick_name()
713     *
714     * input - nickname
715     * - whether it's a local nick (1) or remote (0)
716     * output - none
717     * side effects - walks through the nickname, returning 0 if erroneous
718     */
719     int
720     valid_nickname(const char *nickname, const int local)
721     {
722     const char *p = nickname;
723     assert(nickname && *nickname);
724    
725     /* nicks can't start with a digit or - or be 0 length */
726     /* This closer duplicates behaviour of hybrid-6 */
727     if (*p == '-' || (IsDigit(*p) && local) || *p == '\0')
728     return 0;
729    
730     for (; *p; ++p)
731     if (!IsNickChar(*p))
732     return 0;
733    
734 michael 1431 return p - nickname <= NICKLEN;
735 michael 1165 }
736    
737 adx 30 /* report_and_set_user_flags()
738     *
739     * inputs - pointer to source_p
740     * - pointer to aconf for this user
741     * output - NONE
742     * side effects - Report to user any special flags
743     * they are getting, and set them.
744     */
745     static void
746     report_and_set_user_flags(struct Client *source_p, const struct AccessItem *aconf)
747     {
748     /* If this user is being spoofed, tell them so */
749     if (IsConfDoSpoofIp(aconf))
750     {
751     sendto_one(source_p,
752     ":%s NOTICE %s :*** Spoofing your IP. congrats.",
753     me.name, source_p->name);
754     }
755    
756     /* If this user is in the exception class, Set it "E lined" */
757     if (IsConfExemptKline(aconf))
758     {
759     SetExemptKline(source_p);
760     sendto_one(source_p,
761     ":%s NOTICE %s :*** You are exempt from K/D/G lines. congrats.",
762     me.name, source_p->name);
763     }
764    
765     /* The else here is to make sure that G line exempt users
766     * do not get noticed twice.
767     */
768     else if (IsConfExemptGline(aconf))
769     {
770     SetExemptGline(source_p);
771     sendto_one(source_p, ":%s NOTICE %s :*** You are exempt from G lines.",
772     me.name, source_p->name);
773     }
774    
775     if (IsConfExemptResv(aconf))
776     {
777     SetExemptResv(source_p);
778     sendto_one(source_p, ":%s NOTICE %s :*** You are exempt from resvs.",
779     me.name, source_p->name);
780     }
781    
782     /* If this user is exempt from user limits set it "F lined" */
783     if (IsConfExemptLimits(aconf))
784     {
785     SetExemptLimits(source_p);
786     sendto_one(source_p,
787     ":%s NOTICE %s :*** You are exempt from user limits. congrats.",
788     me.name,source_p->name);
789     }
790    
791     if (IsConfCanFlood(aconf))
792     {
793     SetCanFlood(source_p);
794     sendto_one(source_p, ":%s NOTICE %s :*** You are exempt from flood "
795     "protection, aren't you fearsome.",
796     me.name, source_p->name);
797     }
798     }
799    
800     /* change_simple_umode()
801     *
802     * this callback can be hooked to allow special handling of
803     * certain usermodes
804     */
805     static void *
806     change_simple_umode(va_list args)
807     {
808 michael 627 struct Client *client_p;
809 adx 30 struct Client *source_p;
810     int what;
811     unsigned int flag;
812    
813 michael 627 client_p = va_arg(args, struct Client *);
814 adx 30 source_p = va_arg(args, struct Client *);
815     what = va_arg(args, int);
816     flag = va_arg(args, unsigned int);
817    
818     if (what == MODE_ADD)
819 michael 1219 AddUMode(source_p, flag);
820 adx 30 else
821 michael 1219 DelUMode(source_p, flag);
822 adx 30
823     return NULL;
824     }
825    
826     /* set_user_mode()
827     *
828     * added 15/10/91 By Darren Reed.
829     * parv[0] - sender
830     * parv[1] - username to change mode for
831     * parv[2] - modes to change
832     */
833     void
834     set_user_mode(struct Client *client_p, struct Client *source_p,
835     int parc, char *parv[])
836     {
837     unsigned int flag, setflags;
838     char **p, *m, buf[IRCD_BUFSIZE];
839     struct Client *target_p;
840     int what = MODE_ADD, badflag = 0, i;
841 michael 56
842     assert(!(parc < 2));
843    
844 adx 30 if ((target_p = find_person(client_p, parv[1])) == NULL)
845     {
846     if (MyConnect(source_p))
847     sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL),
848     me.name, source_p->name, parv[1]);
849     return;
850     }
851    
852     if (IsServer(source_p))
853     {
854 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
855     "*** Mode for User %s from %s",
856 adx 30 parv[1], source_p->name);
857     return;
858     }
859    
860 michael 1115 if (source_p != target_p)
861 adx 30 {
862     sendto_one(source_p, form_str(ERR_USERSDONTMATCH),
863     me.name, source_p->name);
864     return;
865     }
866    
867     if (parc < 3)
868     {
869     m = buf;
870     *m++ = '+';
871    
872     for (i = 0; i < 128; i++)
873 michael 1219 if (HasUMode(source_p, user_modes[i]))
874 adx 30 *m++ = (char)i;
875     *m = '\0';
876    
877     sendto_one(source_p, form_str(RPL_UMODEIS),
878     me.name, source_p->name, buf);
879     return;
880     }
881    
882     execute_callback(entering_umode_cb, client_p, source_p);
883    
884     /* find flags already set for user */
885     setflags = source_p->umodes;
886    
887     /* parse mode change string(s) */
888     for (p = &parv[2]; p && *p; p++)
889     {
890     for (m = *p; *m; m++)
891     {
892     switch (*m)
893     {
894     case '+':
895     what = MODE_ADD;
896     break;
897     case '-':
898     what = MODE_DEL;
899     break;
900     case 'o':
901     if (what == MODE_ADD)
902     {
903 michael 1219 if (IsServer(client_p) && !HasUMode(source_p, UMODE_OPER))
904 adx 30 {
905     ++Count.oper;
906     SetOper(source_p);
907     }
908     }
909     else
910     {
911     /* Only decrement the oper counts if an oper to begin with
912     * found by Pat Szuta, Perly , perly@xnet.com
913     */
914 michael 1219 if (!HasUMode(source_p, UMODE_OPER))
915 adx 30 break;
916    
917     ClearOper(source_p);
918     Count.oper--;
919    
920     if (MyConnect(source_p))
921     {
922     dlink_node *dm;
923    
924     detach_conf(source_p, OPER_TYPE);
925 michael 1219 ClrOFlag(source_p);
926     DelUMode(source_p, ConfigFileEntry.oper_only_umodes);
927 adx 30
928     if ((dm = dlinkFindDelete(&oper_list, source_p)) != NULL)
929     free_dlink_node(dm);
930     }
931     }
932    
933     break;
934    
935     /* we may not get these,
936     * but they shouldnt be in default
937     */
938 michael 1158 case 'r':
939 adx 30 case ' ' :
940     case '\n':
941     case '\r':
942     case '\t':
943     break;
944    
945     default:
946     if ((flag = user_modes[(unsigned char)*m]))
947     {
948 michael 1219 if (MyConnect(source_p) && !HasUMode(source_p, UMODE_OPER) &&
949 adx 30 (ConfigFileEntry.oper_only_umodes & flag))
950     {
951     badflag = 1;
952     }
953     else
954 michael 56 execute_callback(umode_cb, client_p, source_p, what, flag);
955 adx 30 }
956     else
957     {
958     if (MyConnect(source_p))
959     badflag = 1;
960     }
961    
962     break;
963     }
964     }
965     }
966    
967     if (badflag)
968     sendto_one(source_p, form_str(ERR_UMODEUNKNOWNFLAG),
969     me.name, source_p->name);
970    
971 michael 1219 if (HasUMode(source_p, UMODE_NCHANGE) && !HasOFlag(source_p, OPER_FLAG_N))
972 adx 30 {
973 michael 1219 sendto_one(source_p, ":%s NOTICE %s :*** You have no nchange flag;",
974 adx 30 me.name, source_p->name);
975 michael 1219 DelUMode(source_p, UMODE_NCHANGE);
976 adx 30 }
977    
978 michael 1219 if (MyConnect(source_p) && HasUMode(source_p, UMODE_ADMIN) &&
979 michael 1294 !HasOFlag(source_p, OPER_FLAG_ADMIN))
980 adx 30 {
981     sendto_one(source_p, ":%s NOTICE %s :*** You have no admin flag;",
982     me.name, source_p->name);
983 michael 1219 DelUMode(source_p, UMODE_ADMIN);
984 adx 30 }
985    
986 michael 1219 if (!(setflags & UMODE_INVISIBLE) && HasUMode(source_p, UMODE_INVISIBLE))
987 adx 30 ++Count.invisi;
988 michael 1219 if ((setflags & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE))
989 adx 30 --Count.invisi;
990    
991 michael 56 /*
992     * compare new flags with old flags and send string which
993 adx 30 * will cause servers to update correctly.
994     */
995     send_umode_out(client_p, source_p, setflags);
996     }
997    
998     /* send_umode()
999     * send the MODE string for user (user) to connection client_p
1000     * -avalon
1001 db 849 *
1002     * inputs - client_p
1003     * - source_p
1004     * - int old
1005     * - sendmask mask of modes to send
1006     * - suplied umode_buf
1007     * output - NONE
1008 adx 30 */
1009     void
1010     send_umode(struct Client *client_p, struct Client *source_p,
1011     unsigned int old, unsigned int sendmask, char *umode_buf)
1012     {
1013 michael 1013 char *m = umode_buf;
1014 adx 30 int what = 0;
1015     unsigned int i;
1016     unsigned int flag;
1017    
1018 michael 56 /*
1019     * build a string in umode_buf to represent the change in the user's
1020 adx 30 * mode between the new (source_p->umodes) and 'old'.
1021     */
1022     for (i = 0; i < 128; i++)
1023     {
1024     flag = user_modes[i];
1025     if (!flag)
1026     continue;
1027    
1028     if (MyClient(source_p) && !(flag & sendmask))
1029     continue;
1030    
1031 michael 1219 if ((flag & old) && !HasUMode(source_p, flag))
1032 adx 30 {
1033     if (what == MODE_DEL)
1034     *m++ = (char)i;
1035     else
1036     {
1037     what = MODE_DEL;
1038     *m++ = '-';
1039     *m++ = (char)i;
1040     }
1041     }
1042 michael 1219 else if (!(flag & old) && HasUMode(source_p, flag))
1043 adx 30 {
1044     if (what == MODE_ADD)
1045     *m++ = (char)i;
1046     else
1047     {
1048     what = MODE_ADD;
1049     *m++ = '+';
1050     *m++ = (char)i;
1051     }
1052     }
1053     }
1054    
1055     *m = '\0';
1056    
1057     if (*umode_buf && client_p)
1058 michael 528 sendto_one(client_p, ":%s!%s@%s MODE %s :%s",
1059     source_p->name, source_p->username,
1060     source_p->host, source_p->name, umode_buf);
1061 adx 30 }
1062    
1063     /* send_umode_out()
1064     *
1065     * inputs -
1066     * output - NONE
1067     * side effects - Only send ubuf out to servers that know about this client
1068     */
1069     void
1070     send_umode_out(struct Client *client_p, struct Client *source_p,
1071     unsigned int old)
1072     {
1073 michael 573 char buf[IRCD_BUFSIZE] = { '\0' };
1074 adx 30 dlink_node *ptr = NULL;
1075    
1076 michael 1294 send_umode(NULL, source_p, old, SEND_UMODES, buf);
1077 adx 30
1078 michael 573 if (buf[0])
1079 adx 30 {
1080     DLINK_FOREACH(ptr, serv_list.head)
1081     {
1082     struct Client *target_p = ptr->data;
1083    
1084     if ((target_p != client_p) && (target_p != source_p))
1085 michael 885 sendto_one(target_p, ":%s MODE %s :%s",
1086     ID_or_name(source_p, target_p),
1087     ID_or_name(source_p, target_p), buf);
1088 adx 30 }
1089     }
1090    
1091     if (client_p && MyClient(client_p))
1092     send_umode(client_p, source_p, old, 0xffffffff, buf);
1093     }
1094    
1095     /* user_welcome()
1096     *
1097     * inputs - client pointer to client to welcome
1098     * output - NONE
1099     * side effects -
1100     */
1101     static void
1102     user_welcome(struct Client *source_p)
1103     {
1104     #if defined(__TIME__) && defined(__DATE__)
1105     static const char built_date[] = __DATE__ " at " __TIME__;
1106     #else
1107     static const char built_date[] = "unknown";
1108     #endif
1109    
1110     #ifdef HAVE_LIBCRYPTO
1111     if (source_p->localClient->fd.ssl != NULL)
1112     sendto_one(source_p, ":%s NOTICE %s :*** Connected securely via %s",
1113     me.name, source_p->name,
1114     ssl_get_cipher(source_p->localClient->fd.ssl));
1115     #endif
1116    
1117     sendto_one(source_p, form_str(RPL_WELCOME), me.name, source_p->name,
1118     ServerInfo.network_name, source_p->name);
1119     sendto_one(source_p, form_str(RPL_YOURHOST), me.name, source_p->name,
1120 michael 56 get_listener_name(source_p->localClient->listener), ircd_version);
1121 adx 30 sendto_one(source_p, form_str(RPL_CREATED),
1122 michael 56 me.name, source_p->name, built_date);
1123 adx 30 sendto_one(source_p, form_str(RPL_MYINFO),
1124     me.name, source_p->name, me.name, ircd_version, umode_buffer);
1125     show_isupport(source_p);
1126    
1127     if (source_p->id[0] != '\0')
1128     sendto_one(source_p, form_str(RPL_YOURID), me.name,
1129     source_p->name, source_p->id);
1130    
1131     show_lusers(source_p);
1132    
1133     if (ConfigFileEntry.short_motd)
1134     {
1135 michael 1115 sendto_one(source_p, ":%s NOTICE %s :*** Notice -- motd was last changed at %s",
1136     me.name, source_p->name, ConfigFileEntry.motd.lastChangedDate);
1137 adx 30 sendto_one(source_p,
1138 michael 1115 ":%s NOTICE %s :*** Notice -- Please read the motd if you haven't "
1139     "read it", me.name, source_p->name);
1140 adx 30 sendto_one(source_p, form_str(RPL_MOTDSTART),
1141     me.name, source_p->name, me.name);
1142     sendto_one(source_p, form_str(RPL_MOTD),
1143     me.name, source_p->name,
1144     "*** This is the short motd ***");
1145     sendto_one(source_p, form_str(RPL_ENDOFMOTD),
1146     me.name, source_p->name);
1147     }
1148     else
1149     send_message_file(source_p, &ConfigFileEntry.motd);
1150     }
1151    
1152     /* check_xline()
1153     *
1154     * inputs - pointer to client to test
1155     * outupt - 1 if exiting 0 if ok
1156     * side effects -
1157     */
1158     static int
1159     check_xline(struct Client *source_p)
1160     {
1161 michael 592 struct ConfItem *conf = NULL;
1162     const char *reason = NULL;
1163 adx 30
1164 michael 592 if ((conf = find_matching_name_conf(XLINE_TYPE, source_p->info, NULL, NULL, 0)) ||
1165     (conf = find_matching_name_conf(RXLINE_TYPE, source_p->info, NULL, NULL, 0)))
1166 adx 30 {
1167 michael 592 struct MatchItem *reg = map_to_conf(conf);
1168 adx 30
1169 michael 592 ++reg->count;
1170    
1171     if (reg->reason != NULL)
1172     reason = reg->reason;
1173 adx 30 else
1174     reason = "No Reason";
1175    
1176 michael 1618 sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE,
1177 michael 56 "X-line Rejecting [%s] [%s], user %s [%s]",
1178     source_p->info, reason,
1179     get_client_name(source_p, HIDE_IP),
1180     source_p->sockhost);
1181 adx 30
1182 michael 896 ++ServerStats.is_ref;
1183 michael 1549 exit_client(source_p, &me, "Bad user info");
1184 adx 30 return 1;
1185     }
1186    
1187     return 0;
1188     }
1189    
1190     /* oper_up()
1191     *
1192     * inputs - pointer to given client to oper
1193     * output - NONE
1194     * side effects - Blindly opers up given source_p, using aconf info
1195     * all checks on passwords have already been done.
1196     * This could also be used by rsa oper routines.
1197     */
1198     void
1199     oper_up(struct Client *source_p)
1200     {
1201 michael 1469 const unsigned int old = source_p->umodes;
1202 michael 56 const struct AccessItem *oconf = NULL;
1203 adx 30
1204 michael 56 assert(source_p->localClient->confs.head);
1205     oconf = map_to_conf((source_p->localClient->confs.head)->data);
1206    
1207     ++Count.oper;
1208 adx 30 SetOper(source_p);
1209    
1210 michael 56 if (oconf->modes)
1211 michael 1219 AddUMode(source_p, oconf->modes);
1212 michael 56 else if (ConfigFileEntry.oper_umodes)
1213 michael 1219 AddUMode(source_p, ConfigFileEntry.oper_umodes);
1214 adx 30
1215 michael 1219 if (!(old & UMODE_INVISIBLE) && HasUMode(source_p, UMODE_INVISIBLE))
1216 michael 882 ++Count.invisi;
1217 michael 1219 if ((old & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE))
1218 michael 882 --Count.invisi;
1219    
1220 adx 30 assert(dlinkFind(&oper_list, source_p) == NULL);
1221     dlinkAdd(source_p, make_dlink_node(), &oper_list);
1222    
1223 michael 1219 AddOFlag(source_p, oconf->port);
1224 adx 30
1225 michael 1294 if (HasOFlag(source_p, OPER_FLAG_ADMIN))
1226 michael 1158 AddUMode(source_p, UMODE_ADMIN);
1227 michael 1219 if (!HasOFlag(source_p, OPER_FLAG_N))
1228 michael 1158 DelUMode(source_p, UMODE_NCHANGE);
1229 adx 30
1230 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE, "%s is now an operator",
1231 michael 1458 get_oper_name(source_p));
1232 adx 30 send_umode_out(source_p, source_p, old);
1233     sendto_one(source_p, form_str(RPL_YOUREOPER), me.name, source_p->name);
1234     }
1235    
1236 michael 573 static char new_uid[TOTALSIDUID + 1]; /* allow for \0 */
1237 adx 30
1238 michael 573 int
1239     valid_sid(const char *sid)
1240     {
1241     if (strlen(sid) == IRC_MAXSID)
1242     if (IsDigit(*sid))
1243 michael 582 if (IsAlNum(*(sid + 1)) && IsAlNum(*(sid + 2)))
1244 michael 573 return 1;
1245    
1246     return 0;
1247     }
1248    
1249 adx 30 /*
1250     * init_uid()
1251     *
1252     * inputs - NONE
1253     * output - NONE
1254     * side effects - new_uid is filled in with server id portion (sid)
1255     * (first 3 bytes) or defaulted to 'A'.
1256     * Rest is filled in with 'A'
1257     */
1258     void
1259     init_uid(void)
1260     {
1261     int i;
1262    
1263     memset(new_uid, 0, sizeof(new_uid));
1264    
1265 michael 1115 if (!EmptyString(ServerInfo.sid))
1266 michael 573 strlcpy(new_uid, ServerInfo.sid, sizeof(new_uid));
1267    
1268 michael 1115 for (i = 0; i < IRC_MAXSID; ++i)
1269 adx 30 if (new_uid[i] == '\0')
1270     new_uid[i] = 'A';
1271    
1272 michael 573 /* NOTE: if IRC_MAXUID != 6, this will have to be rewritten */
1273 adx 30 /* Yes nenolod, I have known it was off by one ever since I wrote it
1274     * But *JUST* for you, though, it really doesn't look as *pretty*
1275     * -Dianora
1276     */
1277 michael 573 memcpy(new_uid + IRC_MAXSID, "AAAAA@", IRC_MAXUID);
1278 adx 30
1279     entering_umode_cb = register_callback("entering_umode", NULL);
1280     umode_cb = register_callback("changing_umode", change_simple_umode);
1281     }
1282    
1283     /*
1284     * add_one_to_uid
1285     *
1286     * inputs - index number into new_uid
1287     * output - NONE
1288     * side effects - new_uid is incremented by one
1289     * note this is a recursive function
1290     */
1291     static void
1292     add_one_to_uid(int i)
1293     {
1294 michael 56 if (i != IRC_MAXSID) /* Not reached server SID portion yet? */
1295 adx 30 {
1296     if (new_uid[i] == 'Z')
1297     new_uid[i] = '0';
1298     else if (new_uid[i] == '9')
1299     {
1300     new_uid[i] = 'A';
1301     add_one_to_uid(i-1);
1302     }
1303 michael 573 else
1304     ++new_uid[i];
1305 adx 30 }
1306     else
1307     {
1308 michael 573 /* NOTE: if IRC_MAXUID != 6, this will have to be rewritten */
1309 adx 30 if (new_uid[i] == 'Z')
1310 michael 573 memcpy(new_uid + IRC_MAXSID, "AAAAAA", IRC_MAXUID);
1311 adx 30 else
1312 michael 573 ++new_uid[i];
1313 adx 30 }
1314     }
1315    
1316     /*
1317 michael 573 * uid_get
1318     *
1319     * inputs - struct Client *
1320     * output - new UID is returned to caller
1321     * side effects - new_uid is incremented by one.
1322     */
1323 michael 1080 static const char *
1324     uid_get(void)
1325 michael 573 {
1326     add_one_to_uid(TOTALSIDUID - 1); /* index from 0 */
1327     return new_uid;
1328     }
1329    
1330     /*
1331 adx 30 * init_isupport()
1332     *
1333     * input - NONE
1334     * output - NONE
1335     * side effects - Must be called before isupport is enabled
1336     */
1337     void
1338     init_isupport(void)
1339     {
1340     isupportFile = init_MessageLine();
1341    
1342     add_isupport("CALLERID", NULL, -1);
1343     add_isupport("CASEMAPPING", CASEMAP, -1);
1344 adx 716 add_isupport("DEAF", "D", -1);
1345 adx 30 add_isupport("KICKLEN", NULL, KICKLEN);
1346     add_isupport("MODES", NULL, MAXMODEPARAMS);
1347 michael 1431 add_isupport("NICKLEN", NULL, NICKLEN);
1348 adx 30 #ifdef HALFOPS
1349     add_isupport("PREFIX", "(ohv)@%+", -1);
1350     add_isupport("STATUSMSG", "@%+", -1);
1351     #else
1352     add_isupport("PREFIX", "(ov)@+", -1);
1353     add_isupport("STATUSMSG", "@+", -1);
1354     #endif
1355     add_isupport("TOPICLEN", NULL, TOPICLEN);
1356     }
1357    
1358     /*
1359     * add_isupport()
1360     *
1361     * input - name of supported function
1362     * - options if any
1363     * - number if any
1364     * output - NONE
1365     * side effects - Each supported item must call this when activated
1366     */
1367     void
1368     add_isupport(const char *name, const char *options, int n)
1369     {
1370     dlink_node *ptr;
1371     struct Isupport *support;
1372    
1373     DLINK_FOREACH(ptr, support_list.head)
1374     {
1375     support = ptr->data;
1376     if (irccmp(support->name, name) == 0)
1377     {
1378     MyFree(support->name);
1379     MyFree(support->options);
1380     break;
1381     }
1382     }
1383    
1384     if (ptr == NULL)
1385     {
1386     support = MyMalloc(sizeof(*support));
1387     dlinkAddTail(support, &support->node, &support_list);
1388     }
1389    
1390     DupString(support->name, name);
1391     if (options != NULL)
1392     DupString(support->options, options);
1393     support->number = n;
1394    
1395     rebuild_isupport_message_line();
1396     }
1397    
1398     /*
1399     * delete_isupport()
1400     *
1401     * input - name of supported function
1402     * output - NONE
1403     * side effects - Each supported item must call this when deactivated
1404     */
1405     void
1406     delete_isupport(const char *name)
1407     {
1408     dlink_node *ptr;
1409     struct Isupport *support;
1410    
1411     DLINK_FOREACH(ptr, support_list.head)
1412     {
1413     support = ptr->data;
1414     if (irccmp(support->name, name) == 0)
1415     {
1416     dlinkDelete(ptr, &support_list);
1417     MyFree(support->name);
1418     MyFree(support->options);
1419     MyFree(support);
1420     break;
1421     }
1422     }
1423    
1424     rebuild_isupport_message_line();
1425     }
1426    
1427     /*
1428     * rebuild_isupport_message_line
1429     *
1430     * input - NONE
1431     * output - NONE
1432     * side effects - Destroy the isupport MessageFile lines, and rebuild.
1433     */
1434     void
1435     rebuild_isupport_message_line(void)
1436     {
1437     char isupportbuffer[IRCD_BUFSIZE];
1438     char *p = isupportbuffer;
1439     dlink_node *ptr = NULL;
1440     int n = 0;
1441     int tokens = 0;
1442     size_t len = 0;
1443     size_t reserve = strlen(me.name) + HOSTLEN + strlen(form_str(RPL_ISUPPORT));
1444    
1445     destroy_MessageLine(isupportFile);
1446    
1447     DLINK_FOREACH(ptr, support_list.head)
1448     {
1449     struct Isupport *support = ptr->data;
1450    
1451     p += (n = ircsprintf(p, "%s", support->name));
1452     len += n;
1453    
1454     if (support->options != NULL)
1455     {
1456     p += (n = ircsprintf(p, "=%s", support->options));
1457     len += n;
1458     }
1459    
1460     if (support->number > 0)
1461     {
1462     p += (n = ircsprintf(p, "=%d", support->number));
1463     len += n;
1464     }
1465    
1466     *p++ = ' ';
1467     len++;
1468     *p = '\0';
1469    
1470     if (++tokens == (MAXPARA-2) || len >= (sizeof(isupportbuffer)-reserve))
1471     { /* arbritrary for now */
1472     if (*--p == ' ')
1473 michael 56 *p = '\0';
1474 adx 30
1475     addto_MessageLine(isupportFile, isupportbuffer);
1476     p = isupportbuffer;
1477     len = 0;
1478     n = tokens = 0;
1479     }
1480     }
1481    
1482     if (len != 0)
1483     {
1484     if (*--p == ' ')
1485     *p = '\0';
1486     addto_MessageLine(isupportFile, isupportbuffer);
1487     }
1488     }

Properties

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