ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/parse.c
Revision: 1234
Committed: Fri Sep 23 08:15:04 2011 UTC (13 years, 11 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/parse.c
File size: 25819 byte(s)
Log Message:
- replace all instances of parv[0] with source_p->name

File Contents

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

Properties

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