ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/parse.c
Revision: 1247
Committed: Sat Oct 1 07:54:24 2011 UTC (12 years, 6 months ago) by michael
Content type: text/x-csrc
File size: 24956 byte(s)
Log Message:
- Rewrite and cleanup half-broken logging subsystem.
  Logfile rotating is not working yet

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 "client.h"
27 #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 #include "s_log.h"
35 #include "send.h"
36 #include "s_conf.h"
37 #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 static char *para[MAXPARA + 1];
106 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 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 static void add_msg_element(struct MessageTree *, struct Message *, const char *);
113 static void del_msg_element(struct MessageTree *, const char *);
114
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 struct Message *msg_ptr = NULL;
126 char *ch = NULL;
127 char *s = NULL;
128 char *numeric = NULL;
129 unsigned int parc = 0;
130 unsigned int paramcount;
131
132 if (IsDefunct(client_p))
133 return;
134
135 assert(client_p->localClient->fd.flags.open);
136 assert((bufend - pbuffer) < 512);
137
138 for (ch = pbuffer; *ch == ' '; ++ch) /* skip spaces */
139 /* null statement */ ;
140
141 if (*ch == ':')
142 {
143 /*
144 * Copy the prefix to 'sender' assuming it terminates
145 * with SPACE (or NULL, which is an error, though).
146 */
147 sender = ++ch;
148
149 if ((s = strchr(ch, ' ')) != NULL)
150 {
151 *s = '\0';
152 ch = ++s;
153 }
154
155 if (*sender && IsServer(client_p))
156 {
157 if ((from = find_person(client_p, sender)) == NULL)
158 from = hash_find_server(sender);
159
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 ++ServerStats.is_unpf;
169 remove_unknown(client_p, sender, pbuffer);
170 return;
171 }
172
173 if (from->from != client_p)
174 {
175 ++ServerStats.is_wrdi;
176 cancel_clients(client_p, from, pbuffer);
177 return;
178 }
179 }
180
181 while (*ch == ' ')
182 ++ch;
183 }
184
185 if (*ch == '\0')
186 {
187 ++ServerStats.is_empt;
188 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 ++ServerStats.is_num;
205 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 unsigned int ii = 0;
211
212 if ((s = strchr(ch, ' ')) != NULL)
213 *s++ = '\0';
214
215 if ((msg_ptr = find_command(ch)) == NULL)
216 {
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 if (*pbuffer != '\0')
228 {
229 if (IsClient(from))
230 sendto_one(from, form_str(ERR_UNKNOWNCOMMAND),
231 me.name, from->name, ch);
232 }
233
234 ++ServerStats.is_unco;
235 return;
236 }
237
238 assert(msg_ptr->cmd != NULL);
239
240 paramcount = msg_ptr->args_max;
241 ii = bufend - ((s) ? s : ch);
242 msg_ptr->bytes += ii;
243 }
244
245 /*
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 {
258 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 }
285
286 para[++parc] = NULL;
287
288 if (msg_ptr != NULL)
289 handle_command(msg_ptr, client_p, from, parc, para);
290 else
291 handle_numeric(numeric, client_p, from, parc, para);
292 }
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 if (i < mptr->args_min)
331 {
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 client_p->name, mptr->cmd, i, mptr->args_min);
343 ilog(LOG_TYPE_IRCD, "Insufficient parameters (%d) for command '%s' from %s.",
344 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 if ((ntree_p = mtree_p->pointers[*cmd & (MAXPTRLEN - 1)]) == NULL)
406 {
407 ntree_p = MyMalloc(sizeof(struct MessageTree));
408 mtree_p->pointers[*cmd & (MAXPTRLEN - 1)] = ntree_p;
409
410 mtree_p->links++; /* Have new pointer, so up ref count */
411 }
412
413 add_msg_element(ntree_p, msg_p, cmd + 1);
414 }
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 /*
446 * In case this is called for a nonexistent command
447 * 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 if ((ntree_p = mtree_p->pointers[*cmd & (MAXPTRLEN - 1)]) != NULL)
458 {
459 del_msg_element(ntree_p, cmd + 1);
460
461 if (ntree_p->links == 0)
462 {
463 mtree_p->pointers[*cmd & (MAXPTRLEN - 1)] = NULL;
464 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 struct MessageTree *mtree = root;
482 assert(cmd && *cmd);
483
484 while (IsAlpha(*cmd) && (mtree = mtree->pointers[*cmd & (MAXPTRLEN - 1)]))
485 if (*++cmd == '\0')
486 return mtree->msg;
487
488 return NULL;
489 }
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 assert(msg && msg->cmd);
503
504 /* command already added? */
505 if (msg_tree_parse(msg->cmd, &msg_tree))
506 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 assert(msg && msg->cmd);
522
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 return msg_tree_parse(cmd, &msg_tree);
536 }
537
538 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 /* 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 const struct MessageTree *mtree = &msg_tree;
564 unsigned int i;
565
566 for (i = 0; i < MAXPTRLEN; ++i)
567 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 return -1;
612 /* 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 return 0;
634 }
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 handle_numeric(char numeric[], struct Client *client_p, struct Client *source_p,
686 int parc, char *parv[])
687 {
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 ircsprintf(t," :%s", parv[parc-1]);
713
714 if (((target_p = find_person(client_p, parv[1])) != NULL) ||
715 ((target_p = hash_find_server(parv[1])) != NULL))
716 {
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 MyClient(target_p) && !HasUMode(target_p, UMODE_OPER))
766 sendto_one(target_p, ":%s %s %s%s", me.name, numeric, target_p->name, buffer);
767 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 return;
771 }
772 else if ((chptr = hash_find_channel(parv[1])) != NULL)
773 sendto_channel_local(ALL_MEMBERS, 0, chptr,
774 ":%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 me.name, source_p->name);
790 }
791
792 void
793 m_unregistered(struct Client *client_p, struct Client *source_p,
794 int parc, char *parv[])
795 {
796 sendto_one(source_p, form_str(ERR_NOTREGISTERED), me.name,
797 source_p->name[0] ? source_p->name : "*");
798 }
799
800 void
801 m_registered(struct Client *client_p, struct Client *source_p,
802 int parc, char *parv[])
803 {
804 sendto_one(source_p, form_str(ERR_ALREADYREGISTRED),
805 me.name, source_p->name);
806 }
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 void
816 rfc1459_command_send_error(struct Client *client_p, struct Client *source_p,
817 int parc, char *parv[])
818 {
819 const char *in_para;
820
821 in_para = (parc > 1 && *parv[1] != '\0') ? parv[1] : "<>";
822
823 ilog(LOG_TYPE_IRCD, "Received ERROR message from %s: %s",
824 source_p->name, in_para);
825
826 if (client_p == source_p)
827 {
828 sendto_realops_flags(UMODE_ALL, L_ADMIN, "ERROR :from %s -- %s",
829 get_client_name(client_p, HIDE_IP), in_para);
830 sendto_realops_flags(UMODE_ALL, L_OPER, "ERROR :from %s -- %s",
831 get_client_name(client_p, MASK_IP), in_para);
832 }
833 else
834 {
835 sendto_realops_flags(UMODE_ALL, L_OPER, "ERROR :from %s via %s -- %s",
836 source_p->name, get_client_name(client_p, MASK_IP), in_para);
837 sendto_realops_flags(UMODE_ALL, L_ADMIN, "ERROR :from %s via %s -- %s",
838 source_p->name, get_client_name(client_p, HIDE_IP), in_para);
839 }
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