ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/releases/8.1.0beta2/src/parse.c
Revision: 1155
Committed: Tue Aug 9 20:27:45 2011 UTC (14 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid/src/parse.c
File size: 25875 byte(s)
Log Message:
- recreate "trunk"

File Contents

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

Properties

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