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

Contents of /ircd-hybrid/trunk/src/parse.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1681 - (show annotations)
Tue Dec 18 18:43:55 2012 UTC (7 years, 7 months ago) by michael
File MIME type: text/x-chdr
File size: 25590 byte(s)
- parse.c:handle_numeric(): added temporary workaround for servers sending
  numeric 451 (ERR_NOTREGISTERED) in response to the "NOTICE AUTH ..." messages
  uppon registration

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

Properties

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

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