/[svn]/ircd-hybrid-8/src/parse.c
ViewVC logotype

Annotation of /ircd-hybrid-8/src/parse.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1322 - (hide annotations)
Fri Mar 30 11:37:32 2012 UTC (8 years, 5 months ago) by michael
File MIME type: text/x-chdr
File size: 24986 byte(s)
- parse.c: fixed archaic bug which would easily allow para[] being accessed
  out of bounds. Just to remember: para[] must be able hold: <prefix>+<15params>+<NULL>

1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * parse.c: The message parser.
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 1243 #include "client.h"
27 adx 30 #include "parse.h"
28     #include "channel.h"
29     #include "hash.h"
30     #include "irc_string.h"
31     #include "sprintf_irc.h"
32     #include "ircd.h"
33     #include "numeric.h"
34 michael 1309 #include "log.h"
35 adx 30 #include "send.h"
36 michael 1309 #include "conf.h"
37 adx 30 #include "memory.h"
38     #include "s_user.h"
39     #include "s_serv.h"
40    
41     /*
42     * (based on orabidoo's parser code)
43     *
44     * This has always just been a trie. Look at volume III of Knuth ACP
45     *
46     *
47     * ok, you start out with an array of pointers, each one corresponds
48     * to a letter at the current position in the command being examined.
49     *
50     * so roughly you have this for matching 'trie' or 'tie'
51     *
52     * 't' points -> [MessageTree *] 'r' -> [MessageTree *] -> 'i'
53     * -> [MessageTree *] -> [MessageTree *] -> 'e' and matches
54     *
55     * 'i' -> [MessageTree *] -> 'e' and matches
56     *
57     * BUGS (Limitations!)
58     *
59     * I designed this trie to parse ircd commands. Hence it currently
60     * casefolds. This is trivial to fix by increasing MAXPTRLEN.
61     * This trie also "folds" '{' etc. down. This means, the input to this
62     * trie must be alpha tokens only. This again, is a limitation that
63     * can be overcome by increasing MAXPTRLEN to include upper/lower case
64     * at the expense of more memory. At the extreme end, you could make
65     * MAXPTRLEN 128.
66     *
67     * This is also not a patricia trie. On short ircd tokens, this is
68     * not likely going to matter.
69     *
70     * Diane Bruce (Dianora), June 6 2003
71     */
72    
73     #define MAXPTRLEN 32
74     /* Must be a power of 2, and
75     * larger than 26 [a-z]|[A-Z]
76     * its used to allocate the set
77     * of pointers at each node of the tree
78     * There are MAXPTRLEN pointers at each node.
79     * Obviously, there have to be more pointers
80     * Than ASCII letters. 32 is a nice number
81     * since there is then no need to shift
82     * 'A'/'a' to base 0 index, at the expense
83     * of a few never used pointers. For a small
84     * parser like this, this is a good compromise
85     * and does make it somewhat faster.
86     *
87     * - Dianora
88     */
89    
90     struct MessageTree
91     {
92     int links; /* Count of all pointers (including msg) at this node
93     * used as reference count for deletion of _this_ node.
94     */
95     struct Message *msg;
96     struct MessageTree *pointers[MAXPTRLEN];
97     };
98    
99     static struct MessageTree msg_tree;
100    
101     /*
102     * NOTE: parse() should not be called recursively by other functions!
103     */
104     static char *sender;
105 michael 1322 static char *para[MAXPARA + 2]; /* <prefix> + <params> + NULL */
106 adx 30 static char buffer[1024];
107    
108     static int cancel_clients(struct Client *, struct Client *, char *);
109     static void remove_unknown(struct Client *, char *, char *);
110 michael 1178 static void handle_numeric(char[], struct Client *, struct Client *, int, char *[]);
111     static void handle_command(struct Message *, struct Client *, struct Client *, unsigned int, char *[]);
112 michael 1013 static void add_msg_element(struct MessageTree *, struct Message *, const char *);
113     static void del_msg_element(struct MessageTree *, const char *);
114 adx 30
115    
116     /*
117     * parse a buffer.
118     *
119     * NOTE: parse() should not be called recusively by any other functions!
120     */
121     void
122     parse(struct Client *client_p, char *pbuffer, char *bufend)
123     {
124     struct Client *from = client_p;
125 michael 1178 struct Message *msg_ptr = NULL;
126 michael 1246 char *ch = NULL;
127     char *s = NULL;
128     char *numeric = NULL;
129 michael 1178 unsigned int parc = 0;
130     unsigned int paramcount;
131 adx 30
132     if (IsDefunct(client_p))
133     return;
134    
135     assert(client_p->localClient->fd.flags.open);
136     assert((bufend - pbuffer) < 512);
137    
138 michael 1246 for (ch = pbuffer; *ch == ' '; ++ch) /* skip spaces */
139 adx 30 /* null statement */ ;
140    
141     if (*ch == ':')
142     {
143 michael 1178 /*
144     * Copy the prefix to 'sender' assuming it terminates
145 adx 30 * with SPACE (or NULL, which is an error, though).
146     */
147 michael 1178 sender = ++ch;
148 adx 30
149     if ((s = strchr(ch, ' ')) != NULL)
150     {
151     *s = '\0';
152 michael 1178 ch = ++s;
153 adx 30 }
154    
155     if (*sender && IsServer(client_p))
156     {
157     if ((from = find_person(client_p, sender)) == NULL)
158 michael 1169 from = hash_find_server(sender);
159 adx 30
160     /* Hmm! If the client corresponding to the
161     * prefix is not found--what is the correct
162     * action??? Now, I will ignore the message
163     * (old IRC just let it through as if the
164     * prefix just wasn't there...) --msa
165     */
166     if (from == NULL)
167     {
168 michael 896 ++ServerStats.is_unpf;
169 adx 30 remove_unknown(client_p, sender, pbuffer);
170     return;
171     }
172    
173     if (from->from != client_p)
174     {
175 michael 896 ++ServerStats.is_wrdi;
176 adx 30 cancel_clients(client_p, from, pbuffer);
177     return;
178     }
179     }
180    
181     while (*ch == ' ')
182 michael 1178 ++ch;
183 adx 30 }
184    
185     if (*ch == '\0')
186     {
187 michael 896 ++ServerStats.is_empt;
188 adx 30 return;
189     }
190    
191     /* Extract the command code from the packet. Point s to the end
192     * of the command code and calculate the length using pointer
193     * arithmetic. Note: only need length for numerics and *all*
194     * numerics must have parameters and thus a space after the command
195     * code. -avalon
196     */
197    
198     /* EOB is 3 chars long but is not a numeric */
199     if (*(ch + 3) == ' ' && /* ok, lets see if its a possible numeric.. */
200     IsDigit(*ch) && IsDigit(*(ch + 1)) && IsDigit(*(ch + 2)))
201     {
202     numeric = ch;
203     paramcount = MAXPARA;
204 michael 896 ++ServerStats.is_num;
205 adx 30 s = ch + 3; /* I know this is ' ' from above if */
206     *s++ = '\0'; /* blow away the ' ', and point s to next part */
207     }
208     else
209     {
210 michael 948 unsigned int ii = 0;
211 adx 30
212     if ((s = strchr(ch, ' ')) != NULL)
213     *s++ = '\0';
214    
215 michael 1178 if ((msg_ptr = find_command(ch)) == NULL)
216 adx 30 {
217     /* Note: Give error message *only* to recognized
218     * persons. It's a nightmare situation to have
219     * two programs sending "Unknown command"'s or
220     * equivalent to each other at full blast....
221     * If it has got to person state, it at least
222     * seems to be well behaving. Perhaps this message
223     * should never be generated, though... --msa
224     * Hm, when is the buffer empty -- if a command
225     * code has been found ?? -Armin
226     */
227 michael 1246 if (*pbuffer != '\0')
228 adx 30 {
229     if (IsClient(from))
230     sendto_one(from, form_str(ERR_UNKNOWNCOMMAND),
231     me.name, from->name, ch);
232     }
233    
234 michael 896 ++ServerStats.is_unco;
235 adx 30 return;
236     }
237    
238 michael 1178 assert(msg_ptr->cmd != NULL);
239 adx 30
240 michael 1178 paramcount = msg_ptr->args_max;
241 adx 30 ii = bufend - ((s) ? s : ch);
242 michael 1178 msg_ptr->bytes += ii;
243 adx 30 }
244    
245 michael 1178 /*
246     * Must the following loop really be so devious? On surface it
247     * splits the message to parameters from blank spaces. But, if
248     * paramcount has been reached, the rest of the message goes into
249     * this last parameter (about same effect as ":" has...) --msa
250     */
251    
252     /* Note initially true: s==NULL || *(s-1) == '\0' !! */
253    
254     para[parc] = from->name;
255    
256     if (s)
257 adx 30 {
258 michael 1178 if (paramcount > MAXPARA)
259     paramcount = MAXPARA;
260    
261     while (1)
262     {
263     while (*s == ' ')
264     *s++ = '\0';
265    
266     if (*s == '\0')
267     break;
268    
269     if (*s == ':')
270     {
271     /* The rest is a single parameter */
272     para[++parc] = s + 1;
273     break;
274     }
275    
276     para[++parc] = s;
277    
278     if (parc >= paramcount)
279     break;
280    
281     while (*s && *s != ' ')
282     ++s;
283     }
284 adx 30 }
285    
286 michael 1178 para[++parc] = NULL;
287    
288     if (msg_ptr != NULL)
289     handle_command(msg_ptr, client_p, from, parc, para);
290 adx 30 else
291 michael 1178 handle_numeric(numeric, client_p, from, parc, para);
292 adx 30 }
293    
294     /* handle_command()
295     *
296     * inputs - pointer to message block
297     * - pointer to client
298     * - pointer to client message is from
299     * - count of number of args
300     * - pointer to argv[] array
301     * output - -1 if error from server
302     * side effects -
303     */
304     static void
305     handle_command(struct Message *mptr, struct Client *client_p,
306     struct Client *from, unsigned int i, char *hpara[MAXPARA])
307     {
308     MessageHandler handler = 0;
309    
310     if (IsServer(client_p))
311     mptr->rcount++;
312    
313     mptr->count++;
314    
315     /* New patch to avoid server flooding from unregistered connects
316     * - Pie-Man 07/27/2000 */
317     if (!IsRegistered(client_p))
318     {
319     /* if its from a possible server connection
320     * ignore it.. more than likely its a header thats sneaked through
321     */
322     if ((IsHandshake(client_p) || IsConnecting(client_p) ||
323     IsServer(client_p)) && !(mptr->flags & MFLG_UNREG))
324     return;
325     }
326    
327     handler = mptr->handlers[client_p->handler];
328    
329     /* check right amount of params is passed... --is */
330 michael 1178 if (i < mptr->args_min)
331 adx 30 {
332     if (!IsServer(client_p))
333     {
334     sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS),
335     me.name, EmptyString(hpara[0]) ? "*" : hpara[0], mptr->cmd);
336     }
337     else
338     {
339     sendto_realops_flags(UMODE_ALL, L_ALL,
340     "Dropping server %s due to (invalid) command '%s' "
341     "with only %d arguments (expecting %d).",
342 michael 1178 client_p->name, mptr->cmd, i, mptr->args_min);
343 michael 1247 ilog(LOG_TYPE_IRCD, "Insufficient parameters (%d) for command '%s' from %s.",
344 adx 30 i, mptr->cmd, client_p->name);
345     exit_client(client_p, client_p,
346     "Not enough arguments to server command.");
347     }
348     }
349     else
350     (*handler)(client_p, from, i, hpara);
351     }
352    
353     /* clear_tree_parse()
354     *
355     * inputs - NONE
356     * output - NONE
357     * side effects - MUST MUST be called at startup ONCE before
358     * any other keyword routine is used.
359     */
360     void
361     clear_tree_parse(void)
362     {
363     memset(&msg_tree, 0, sizeof(msg_tree));
364     }
365    
366     /* add_msg_element()
367     *
368     * inputs - pointer to MessageTree
369     * - pointer to Message to add for given command
370     * - pointer to current portion of command being added
371     * output - NONE
372     * side effects - recursively build the Message Tree ;-)
373     */
374     /*
375     * How this works.
376     *
377     * The code first checks to see if its reached the end of the command
378     * If so, that struct MessageTree has a msg pointer updated and the links
379     * count incremented, since a msg pointer is a reference.
380     * Then the code descends recursively, building the trie.
381     * If a pointer index inside the struct MessageTree is NULL a new
382     * child struct MessageTree has to be allocated.
383     * The links (reference count) is incremented as they are created
384     * in the parent.
385     */
386     static void
387     add_msg_element(struct MessageTree *mtree_p,
388     struct Message *msg_p, const char *cmd)
389     {
390     struct MessageTree *ntree_p;
391    
392     if (*cmd == '\0')
393     {
394     mtree_p->msg = msg_p;
395     mtree_p->links++; /* Have msg pointer, so up ref count */
396     }
397     else
398     {
399     /* *cmd & (MAXPTRLEN-1)
400     * convert the char pointed to at *cmd from ASCII to an integer
401     * between 0 and MAXPTRLEN.
402     * Thus 'A' -> 0x1 'B' -> 0x2 'c' -> 0x3 etc.
403     */
404    
405 michael 1013 if ((ntree_p = mtree_p->pointers[*cmd & (MAXPTRLEN - 1)]) == NULL)
406 adx 30 {
407 michael 1013 ntree_p = MyMalloc(sizeof(struct MessageTree));
408     mtree_p->pointers[*cmd & (MAXPTRLEN - 1)] = ntree_p;
409 adx 30
410     mtree_p->links++; /* Have new pointer, so up ref count */
411     }
412 michael 896
413 michael 1013 add_msg_element(ntree_p, msg_p, cmd + 1);
414 adx 30 }
415     }
416    
417     /* del_msg_element()
418     *
419     * inputs - Pointer to MessageTree to delete from
420     * - pointer to command name to delete
421     * output - NONE
422     * side effects - recursively deletes a token from the Message Tree ;-)
423     */
424     /*
425     * How this works.
426     *
427     * Well, first off, the code recursively descends into the trie
428     * until it finds the terminating letter of the command being removed.
429     * Once it has done that, it marks the msg pointer as NULL then
430     * reduces the reference count on that allocated struct MessageTree
431     * since a command counts as a reference.
432     *
433     * Then it pops up the recurse stack. As it comes back up the recurse
434     * The code checks to see if the child now has no pointers or msg
435     * i.e. the links count has gone to zero. If its no longer used, the
436     * child struct MessageTree can be deleted. The parent reference
437     * to this child is then removed and the parents link count goes down.
438     * Thus, we continue to go back up removing all unused MessageTree(s)
439     */
440     static void
441     del_msg_element(struct MessageTree *mtree_p, const char *cmd)
442     {
443     struct MessageTree *ntree_p;
444    
445 michael 1246 /*
446     * In case this is called for a nonexistent command
447 adx 30 * check that there is a msg pointer here, else links-- goes -ve
448     * -db
449     */
450     if ((*cmd == '\0') && (mtree_p->msg != NULL))
451     {
452     mtree_p->msg = NULL;
453     mtree_p->links--;
454     }
455     else
456     {
457 michael 1013 if ((ntree_p = mtree_p->pointers[*cmd & (MAXPTRLEN - 1)]) != NULL)
458 adx 30 {
459 michael 1013 del_msg_element(ntree_p, cmd + 1);
460 michael 896
461 adx 30 if (ntree_p->links == 0)
462     {
463 michael 1013 mtree_p->pointers[*cmd & (MAXPTRLEN - 1)] = NULL;
464 adx 30 mtree_p->links--;
465     MyFree(ntree_p);
466     }
467     }
468     }
469     }
470    
471     /* msg_tree_parse()
472     *
473     * inputs - Pointer to command to find
474     * - Pointer to MessageTree root
475     * output - Find given command returning Message * if found NULL if not
476     * side effects - none
477     */
478     static struct Message *
479     msg_tree_parse(const char *cmd, struct MessageTree *root)
480     {
481 michael 522 struct MessageTree *mtree = root;
482 adx 30 assert(cmd && *cmd);
483    
484 michael 522 while (IsAlpha(*cmd) && (mtree = mtree->pointers[*cmd & (MAXPTRLEN - 1)]))
485     if (*++cmd == '\0')
486     return mtree->msg;
487 adx 30
488 michael 522 return NULL;
489 adx 30 }
490    
491     /* mod_add_cmd()
492     *
493     * inputs - pointer to struct Message
494     * output - none
495     * side effects - load this one command name
496     * msg->count msg->bytes is modified in place, in
497     * modules address space. Might not want to do that...
498     */
499     void
500     mod_add_cmd(struct Message *msg)
501     {
502 michael 1246 assert(msg && msg->cmd);
503 adx 30
504     /* command already added? */
505 michael 1246 if (msg_tree_parse(msg->cmd, &msg_tree))
506 adx 30 return;
507    
508     add_msg_element(&msg_tree, msg, msg->cmd);
509     msg->count = msg->rcount = msg->bytes = 0;
510     }
511    
512     /* mod_del_cmd()
513     *
514     * inputs - pointer to struct Message
515     * output - none
516     * side effects - unload this one command name
517     */
518     void
519     mod_del_cmd(struct Message *msg)
520     {
521 michael 1246 assert(msg && msg->cmd);
522 adx 30
523     del_msg_element(&msg_tree, msg->cmd);
524     }
525    
526     /* find_command()
527     *
528     * inputs - command name
529     * output - pointer to struct Message
530     * side effects - none
531     */
532     struct Message *
533     find_command(const char *cmd)
534     {
535 michael 896 return msg_tree_parse(cmd, &msg_tree);
536 adx 30 }
537    
538 michael 1246 static void
539     recurse_report_messages(struct Client *source_p, const struct MessageTree *mtree)
540     {
541     unsigned int i;
542    
543     if (mtree->msg != NULL)
544     sendto_one(source_p, form_str(RPL_STATSCOMMANDS),
545     me.name, source_p->name, mtree->msg->cmd,
546     mtree->msg->count, mtree->msg->bytes,
547     mtree->msg->rcount);
548    
549     for (i = 0; i < MAXPTRLEN; ++i)
550     if (mtree->pointers[i] != NULL)
551     recurse_report_messages(source_p, mtree->pointers[i]);
552     }
553    
554 adx 30 /* report_messages()
555     *
556     * inputs - pointer to client to report to
557     * output - NONE
558     * side effects - client is shown list of commands
559     */
560     void
561     report_messages(struct Client *source_p)
562     {
563 michael 1013 const struct MessageTree *mtree = &msg_tree;
564     unsigned int i;
565 adx 30
566 michael 1246 for (i = 0; i < MAXPTRLEN; ++i)
567 adx 30 if (mtree->pointers[i] != NULL)
568     recurse_report_messages(source_p, mtree->pointers[i]);
569     }
570    
571     /* cancel_clients()
572     *
573     * inputs -
574     * output -
575     * side effects -
576     */
577     static int
578     cancel_clients(struct Client *client_p, struct Client *source_p, char *cmd)
579     {
580     /* kill all possible points that are causing confusion here,
581     * I'm not sure I've got this all right...
582     * - avalon
583     *
584     * knowing avalon, probably not.
585     */
586    
587     /* with TS, fake prefixes are a common thing, during the
588     * connect burst when there's a nick collision, and they
589     * must be ignored rather than killed because one of the
590     * two is surviving.. so we don't bother sending them to
591     * all ops everytime, as this could send 'private' stuff
592     * from lagged clients. we do send the ones that cause
593     * servers to be dropped though, as well as the ones from
594     * non-TS servers -orabidoo
595     */
596     /* Incorrect prefix for a server from some connection. If it is a
597     * client trying to be annoying, just QUIT them, if it is a server
598     * then the same deal.
599     */
600     if (IsServer(source_p) || IsMe(source_p))
601     {
602     sendto_realops_flags(UMODE_DEBUG, L_ADMIN, "Message for %s[%s] from %s",
603     source_p->name, source_p->from->name,
604     get_client_name(client_p, SHOW_IP));
605     sendto_realops_flags(UMODE_DEBUG, L_OPER, "Message for %s[%s] from %s",
606     source_p->name, source_p->from->name,
607     get_client_name(client_p, MASK_IP));
608     sendto_realops_flags(UMODE_DEBUG, L_ALL,
609     "Not dropping server %s (%s) for Fake Direction",
610     client_p->name, source_p->name);
611 michael 896 return -1;
612 adx 30 /* return exit_client(client_p, client_p, &me, "Fake Direction");*/
613     }
614    
615     /* Ok, someone is trying to impose as a client and things are
616     * confused. If we got the wrong prefix from a server, send out a
617     * kill, else just exit the lame client.
618     */
619     /* If the fake prefix is coming from a TS server, discard it
620     * silently -orabidoo
621     *
622     * all servers must be TS these days --is
623     */
624     sendto_realops_flags(UMODE_DEBUG, L_ADMIN,
625     "Message for %s[%s@%s!%s] from %s (TS, ignored)",
626     source_p->name, source_p->username, source_p->host,
627     source_p->from->name, get_client_name(client_p, SHOW_IP));
628     sendto_realops_flags(UMODE_DEBUG, L_OPER,
629     "Message for %s[%s@%s!%s] from %s (TS, ignored)",
630     source_p->name, source_p->username, source_p->host,
631     source_p->from->name, get_client_name(client_p, MASK_IP));
632    
633 michael 896 return 0;
634 adx 30 }
635    
636     /* remove_unknown()
637     *
638     * inputs -
639     * output -
640     * side effects -
641     */
642     static void
643     remove_unknown(struct Client *client_p, char *lsender, char *lbuffer)
644     {
645     /* Do kill if it came from a server because it means there is a ghost
646     * user on the other server which needs to be removed. -avalon
647     * Tell opers about this. -Taner
648     */
649     /* '[0-9]something' is an ID (KILL/SQUIT depending on its length)
650     * 'nodots' is a nickname (KILL)
651     * 'no.dot.at.start' is a server (SQUIT)
652     */
653     if ((IsDigit(*lsender) && strlen(lsender) <= IRC_MAXSID) ||
654     strchr(lsender, '.') != NULL)
655     {
656     sendto_realops_flags(UMODE_DEBUG, L_ADMIN,
657     "Unknown prefix (%s) from %s, Squitting %s",
658     lbuffer, get_client_name(client_p, SHOW_IP), lsender);
659     sendto_realops_flags(UMODE_DEBUG, L_OPER,
660     "Unknown prefix (%s) from %s, Squitting %s",
661     lbuffer, client_p->name, lsender);
662     sendto_one(client_p, ":%s SQUIT %s :(Unknown prefix (%s) from %s)",
663     me.name, lsender, lbuffer, client_p->name);
664     }
665     else
666     sendto_one(client_p, ":%s KILL %s :%s (Unknown Client)",
667     me.name, lsender, me.name);
668     }
669    
670     /*
671     *
672     * parc number of arguments ('sender' counted as one!)
673     * parv[0] pointer to 'sender' (may point to empty string) (not used)
674     * parv[1]..parv[parc-1]
675     * pointers to additional parameters, this is a NULL
676     * terminated list (parv[parc] == NULL).
677     *
678     * *WARNING*
679     * Numerics are mostly error reports. If there is something
680     * wrong with the message, just *DROP* it! Don't even think of
681     * sending back a neat error message -- big danger of creating
682     * a ping pong error message...
683     */
684     static void
685 michael 1178 handle_numeric(char numeric[], struct Client *client_p, struct Client *source_p,
686     int parc, char *parv[])
687 adx 30 {
688     struct Client *target_p;
689     struct Channel *chptr;
690     char *t; /* current position within the buffer */
691     int i, tl; /* current length of presently being built string in t */
692    
693     if (parc < 2 || !IsServer(source_p))
694     return;
695    
696     /* Remap low number numerics. */
697     if (numeric[0] == '0')
698     numeric[0] = '1';
699    
700     /* Prepare the parameter portion of the message into 'buffer'.
701     * (Because the buffer is twice as large as the message buffer
702     * for the socket, no overflow can occur here... ...on current
703     * assumptions--bets are off, if these are changed --msa)
704     */
705     t = buffer;
706     for (i = 2; i < (parc - 1); i++)
707     {
708     tl = ircsprintf(t, " %s", parv[i]);
709     t += tl;
710     }
711    
712 michael 1298 ircsprintf(t, " :%s", parv[parc-1]);
713 adx 30
714     if (((target_p = find_person(client_p, parv[1])) != NULL) ||
715 michael 1169 ((target_p = hash_find_server(parv[1])) != NULL))
716 adx 30 {
717     if (IsMe(target_p))
718     {
719     int num;
720    
721     /*
722     * We shouldn't get numerics sent to us,
723     * any numerics we do get indicate a bug somewhere..
724     */
725     /* ugh. this is here because of nick collisions. when two servers
726     * relink, they burst each other their nicks, then perform collides.
727     * if there is a nick collision, BOTH servers will kill their own
728     * nicks, and BOTH will kill the other servers nick, which wont exist,
729     * because it will have been already killed by the local server.
730     *
731     * unfortunately, as we cant guarantee other servers will do the
732     * "right thing" on a nick collision, we have to keep both kills.
733     * ergo we need to ignore ERR_NOSUCHNICK. --fl_
734     */
735     /* quick comment. This _was_ tried. i.e. assume the other servers
736     * will do the "right thing" and kill a nick that is colliding.
737     * unfortunately, it did not work. --Dianora
738     */
739    
740     /* Yes, a good compiler would have optimised this, but
741     * this is probably easier to read. -db
742     */
743     num = atoi(numeric);
744    
745     if ((num != ERR_NOSUCHNICK))
746     sendto_realops_flags(UMODE_ALL, L_ADMIN,
747     "*** %s(via %s) sent a %s numeric to me: %s",
748     source_p->name, client_p->name, numeric, buffer);
749     return;
750     }
751     else if (target_p->from == client_p)
752     {
753     /* This message changed direction (nick collision?)
754     * ignore it.
755     */
756     return;
757     }
758    
759     /* csircd will send out unknown umode flag for +a (admin), drop it here. */
760     if ((atoi(numeric) == ERR_UMODEUNKNOWNFLAG) && MyClient(target_p))
761     return;
762    
763     /* Fake it for server hiding, if its our client */
764     if (ConfigServerHide.hide_servers &&
765 michael 1219 MyClient(target_p) && !HasUMode(target_p, UMODE_OPER))
766 adx 30 sendto_one(target_p, ":%s %s %s%s", me.name, numeric, target_p->name, buffer);
767 adx 753 else
768     sendto_one(target_p, ":%s %s %s%s", ID_or_name(source_p, target_p->from),
769     numeric, ID_or_name(target_p, target_p->from), buffer);
770 adx 30 return;
771     }
772     else if ((chptr = hash_find_channel(parv[1])) != NULL)
773 michael 1243 sendto_channel_local(ALL_MEMBERS, 0, chptr,
774 adx 30 ":%s %s %s %s",
775     source_p->name,
776     numeric, chptr->chname, buffer);
777     }
778    
779     /* m_not_oper()
780     * inputs -
781     * output -
782     * side effects - just returns a nastyogram to given user
783     */
784     void
785     m_not_oper(struct Client *client_p, struct Client *source_p,
786     int parc, char *parv[])
787     {
788     sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
789 michael 948 me.name, source_p->name);
790 adx 30 }
791    
792     void
793     m_unregistered(struct Client *client_p, struct Client *source_p,
794     int parc, char *parv[])
795     {
796 michael 1235 sendto_one(source_p, form_str(ERR_NOTREGISTERED), me.name,
797     source_p->name[0] ? source_p->name : "*");
798 adx 30 }
799    
800     void
801     m_registered(struct Client *client_p, struct Client *source_p,
802     int parc, char *parv[])
803     {
804 michael 1235 sendto_one(source_p, form_str(ERR_ALREADYREGISTRED),
805 michael 1080 me.name, source_p->name);
806 adx 30 }
807    
808     void
809     m_ignore(struct Client *client_p, struct Client *source_p,
810     int parc, char *parv[])
811     {
812     return;
813     }
814    
815 michael 946 void
816     rfc1459_command_send_error(struct Client *client_p, struct Client *source_p,
817     int parc, char *parv[])
818     {
819 michael 948 const char *in_para;
820 michael 946
821 michael 948 in_para = (parc > 1 && *parv[1] != '\0') ? parv[1] : "<>";
822 michael 946
823 michael 1247 ilog(LOG_TYPE_IRCD, "Received ERROR message from %s: %s",
824 michael 948 source_p->name, in_para);
825 michael 946
826     if (client_p == source_p)
827     {
828     sendto_realops_flags(UMODE_ALL, L_ADMIN, "ERROR :from %s -- %s",
829 michael 948 get_client_name(client_p, HIDE_IP), in_para);
830 michael 946 sendto_realops_flags(UMODE_ALL, L_OPER, "ERROR :from %s -- %s",
831 michael 948 get_client_name(client_p, MASK_IP), in_para);
832 michael 946 }
833     else
834     {
835     sendto_realops_flags(UMODE_ALL, L_OPER, "ERROR :from %s via %s -- %s",
836 michael 948 source_p->name, get_client_name(client_p, MASK_IP), in_para);
837 michael 946 sendto_realops_flags(UMODE_ALL, L_ADMIN, "ERROR :from %s via %s -- %s",
838 michael 948 source_p->name, get_client_name(client_p, HIDE_IP), in_para);
839 michael 946 }
840    
841     if (MyClient(source_p))
842     exit_client(source_p, source_p, "ERROR");
843     }

Properties

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

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28