ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/parse.c
(Generate patch)

Comparing:
ircd-hybrid/src/parse.c (file contents), Revision 33 by knight, Sun Oct 2 20:50:00 2005 UTC vs.
ircd-hybrid/trunk/src/parse.c (file contents), Revision 1726 by michael, Thu Jan 3 00:07:58 2013 UTC

# Line 23 | Line 23
23   */
24  
25   #include "stdinc.h"
26 – #include "parse.h"
26   #include "client.h"
27 + #include "parse.h"
28   #include "channel.h"
29 – #include "handlers.h"
30 – #include "common.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"
37 < #include "s_stats.h"
34 > #include "log.h"
35   #include "send.h"
36 < #include "ircd_handler.h"
40 < #include "msg.h"
41 < #include "s_conf.h"
36 > #include "conf.h"
37   #include "memory.h"
38   #include "s_user.h"
39   #include "s_serv.h"
# Line 107 | Line 102 | static struct MessageTree msg_tree;
102   * NOTE: parse() should not be called recursively by other functions!
103   */
104   static char *sender;
105 < static char *para[MAXPARA + 1];
111 < static char buffer[1024];
105 > static char *para[MAXPARA + 2]; /* <prefix> + <params> + NULL */
106  
107   static int cancel_clients(struct Client *, struct Client *, char *);
108   static void remove_unknown(struct Client *, char *, char *);
109 < static void do_numeric(char[], struct Client *, struct Client *, int, char **);
110 < static void handle_command(struct Message *, struct Client *, struct Client *, unsigned int, char **);
117 < static void recurse_report_messages(struct Client *source_p, struct MessageTree *mtree);
118 < static void add_msg_element(struct MessageTree *mtree_p, struct Message *msg_p, const char *cmd);
119 < static void del_msg_element(struct MessageTree *mtree_p, const char *cmd);
120 <
121 < /* turn a string into a parc/parv pair */
122 < static inline int
123 < string_to_array(char *string, char *parv[MAXPARA])
124 < {
125 <  char *p;
126 <  char *buf = string;
127 <  int x = 1;
128 <
129 <  parv[x] = NULL;
130 <
131 <  while (*buf == ' ') /* skip leading spaces */
132 <    buf++;
133 <
134 <  if (*buf == '\0') /* ignore all-space args */
135 <    return(x);
136 <
137 <  do
138 <  {
139 <    if (*buf == ':') /* Last parameter */
140 <    {
141 <      buf++;
142 <      parv[x++] = buf;
143 <      parv[x]   = NULL;
144 <      return(x);
145 <    }
146 <    else
147 <    {
148 <      parv[x++] = buf;
149 <      parv[x]   = NULL;
109 > static void handle_numeric(char[], struct Client *, struct Client *, int, char *[]);
110 > static void handle_command(struct Message *, struct Client *, struct Client *, unsigned int, char *[]);
111  
151 –      if ((p = strchr(buf, ' ')) != NULL)
152 –      {
153 –        *p++ = '\0';
154 –        buf  = p;
155 –      }
156 –      else
157 –        return(x);
158 –    }      
159 –
160 –    while (*buf == ' ')
161 –      buf++;
162 –
163 –    if (*buf == '\0')
164 –      return(x);
165 –  } while (x < MAXPARA - 1);
166 –
167 –  if (*p == ':')
168 –    p++;
169 –
170 –  parv[x++] = p;
171 –  parv[x]   = NULL;
172 –  return(x);
173 – }
112  
113   /*
114   * parse a buffer.
# Line 181 | Line 119 | void
119   parse(struct Client *client_p, char *pbuffer, char *bufend)
120   {
121    struct Client *from = client_p;
122 <  char *ch;
123 <  char *s;
124 <  char *numeric = 0;
125 <  unsigned int i = 0;
126 <  int paramcount;
127 <  int mpara = 0;
190 <  struct Message *mptr = NULL;
122 >  struct Message *msg_ptr = NULL;
123 >  char *ch = NULL;
124 >  char *s = NULL;
125 >  char *numeric = NULL;
126 >  unsigned int parc = 0;
127 >  unsigned int paramcount;
128  
129    if (IsDefunct(client_p))
130      return;
# Line 195 | Line 132 | parse(struct Client *client_p, char *pbu
132    assert(client_p->localClient->fd.flags.open);
133    assert((bufend - pbuffer) < 512);
134  
135 <  for (ch = pbuffer; *ch == ' '; ch++) /* skip spaces */
135 >  for (ch = pbuffer; *ch == ' '; ++ch) /* skip spaces */
136      /* null statement */ ;
137  
201 –  para[0] = from->name;
202 –
138    if (*ch == ':')
139    {
140 <    ch++;
141 <
207 <    /* Copy the prefix to 'sender' assuming it terminates
140 >    /*
141 >     * Copy the prefix to 'sender' assuming it terminates
142       * with SPACE (or NULL, which is an error, though).
143       */
144 <    sender = ch;
144 >    sender = ++ch;
145  
146      if ((s = strchr(ch, ' ')) != NULL)
147      {
148        *s = '\0';
149 <      s++;
216 <      ch = s;
149 >      ch = ++s;
150      }
151  
152      if (*sender && IsServer(client_p))
153      {
221 –      /*
222 –       * XXX it could be useful to know which of these occurs most frequently.
223 –       * the ID check should always come first, though, since it is so easy.
224 –       */
154        if ((from = find_person(client_p, sender)) == NULL)
155 <      {
227 <        from = find_server(sender);
155 >        from = hash_find_server(sender);
156  
229 –        if (from == NULL && IsCapable(client_p, CAP_TS6) &&
230 –          client_p->name[0] == '*' && IsDigit(*sender) && strlen(sender) == 3)
231 –        {
232 –          /* Dirty hack to allow messages from masked SIDs (i.e. the ones
233 –           * hidden by fakename="..."). It shouldn't break anything, since
234 –           * unknown SIDs don't happen during normal ircd work --adx
235 –           */
236 –          from = client_p;
237 –        }
238 –      }
239 –      
157        /* Hmm! If the client corresponding to the
158         * prefix is not found--what is the correct
159         * action??? Now, I will ignore the message
# Line 245 | Line 162 | parse(struct Client *client_p, char *pbu
162         */
163        if (from == NULL)
164        {
165 <        ServerStats->is_unpf++;
165 >        ++ServerStats.is_unpf;
166          remove_unknown(client_p, sender, pbuffer);
167          return;
168        }
169  
253 –      para[0] = from->name;
254 –
170        if (from->from != client_p)
171        {
172 <        ServerStats->is_wrdi++;
172 >        ++ServerStats.is_wrdi;
173          cancel_clients(client_p, from, pbuffer);
174          return;
175        }
176      }
177  
178      while (*ch == ' ')
179 <      ch++;
179 >      ++ch;
180    }
181  
182    if (*ch == '\0')
183    {
184 <    ServerStats->is_empt++;
184 >    ++ServerStats.is_empt;
185      return;
186    }
187  
# Line 281 | Line 196 | parse(struct Client *client_p, char *pbu
196    if (*(ch + 3) == ' ' && /* ok, lets see if its a possible numeric.. */
197        IsDigit(*ch) && IsDigit(*(ch + 1)) && IsDigit(*(ch + 2)))
198    {
284 –    mptr = NULL;
199      numeric = ch;
200 <    paramcount = MAXPARA;
201 <    ServerStats->is_num++;
200 >    paramcount = 2; /* destination, and the rest of it */
201 >    ++ServerStats.is_num;
202      s = ch + 3;  /* I know this is ' ' from above if            */
203      *s++ = '\0'; /* blow away the ' ', and point s to next part */
204    }
205    else
206    {
207 <    int ii = 0;
207 >    unsigned int ii = 0;
208  
209      if ((s = strchr(ch, ' ')) != NULL)
210        *s++ = '\0';
211  
212 <    if ((mptr = find_command(ch)) == NULL)
212 >    if ((msg_ptr = find_command(ch)) == NULL)
213      {
214        /* Note: Give error message *only* to recognized
215         * persons. It's a nightmare situation to have
# Line 307 | Line 221 | parse(struct Client *client_p, char *pbu
221         * Hm, when is the buffer empty -- if a command
222         * code has been found ?? -Armin
223         */
224 <      if (pbuffer[0] != '\0')
224 >      if (*pbuffer != '\0')
225        {
226          if (IsClient(from))
227            sendto_one(from, form_str(ERR_UNKNOWNCOMMAND),
228                       me.name, from->name, ch);
229        }
230  
231 <      ServerStats->is_unco++;
231 >      ++ServerStats.is_unco;
232        return;
233      }
234  
235 <    assert(mptr->cmd != NULL);
322 <
323 <    paramcount = mptr->parameters;
324 <    mpara      = mptr->maxpara;
235 >    assert(msg_ptr->cmd != NULL);
236  
237 +    paramcount = msg_ptr->args_max;
238      ii = bufend - ((s) ? s : ch);
239 <    mptr->bytes += ii;
239 >    msg_ptr->bytes += ii;
240    }
241  
242 <  if (s != NULL)
243 <    i = string_to_array(s, para);
244 <  else
242 >  /*
243 >   * Must the following loop really be so devious? On surface it
244 >   * splits the message to parameters from blank spaces. But, if
245 >   * paramcount has been reached, the rest of the message goes into
246 >   * this last parameter (about same effect as ":" has...) --msa
247 >   */
248 >
249 >  /* Note initially true: s==NULL || *(s-1) == '\0' !! */
250 >
251 >  para[parc] = from->name;
252 >
253 >  if (s)
254    {
255 <    i = 0;
256 <    para[1] = NULL;
255 >    if (paramcount > MAXPARA)
256 >      paramcount = MAXPARA;
257 >
258 >    while (1)
259 >    {
260 >       while (*s == ' ')
261 >         *s++ = '\0';
262 >
263 >       if (*s == '\0')
264 >         break;
265 >
266 >       if (*s == ':')
267 >       {
268 >         /* The rest is a single parameter */
269 >         para[++parc] = s + (!numeric); /* keep the colon if it's a numeric */
270 >         break;
271 >       }
272 >
273 >       para[++parc] = s;
274 >
275 >       if (parc >= paramcount)
276 >         break;
277 >
278 >       while (*s && *s != ' ')
279 >         ++s;
280 >    }
281    }
282  
283 <  if (mptr == NULL)
284 <    do_numeric(numeric, client_p, from, i, para);
283 >  para[++parc] = NULL;
284 >
285 >  if (msg_ptr != NULL)
286 >    handle_command(msg_ptr, client_p, from, parc, para);
287    else
288 <    handle_command(mptr, client_p, from, i, para);
288 >    handle_numeric(numeric, client_p, from, parc, para);
289   }
290  
291   /* handle_command()
# Line 353 | Line 300 | parse(struct Client *client_p, char *pbu
300   */
301   static void
302   handle_command(struct Message *mptr, struct Client *client_p,
303 <               struct Client *from, unsigned int i, char *hpara[MAXPARA])
303 >               struct Client *from, unsigned int i, char *hpara[])
304   {
305    MessageHandler handler = 0;
306  
# Line 362 | Line 309 | handle_command(struct Message *mptr, str
309  
310    mptr->count++;
311  
365 –  /* New patch to avoid server flooding from unregistered connects
366 –   * - Pie-Man 07/27/2000 */
367 –  if (!IsRegistered(client_p))
368 –  {
369 –    /* if its from a possible server connection
370 –     * ignore it.. more than likely its a header thats sneaked through
371 –     */
372 –    if ((IsHandshake(client_p) || IsConnecting(client_p) ||
373 –        IsServer(client_p)) && !(mptr->flags & MFLG_UNREG))
374 –      return;
375 –  }
376 –
312    handler = mptr->handlers[client_p->handler];
313  
314    /* check right amount of params is passed... --is */
315 <  if (i < mptr->parameters)
315 >  if (i < mptr->args_min)
316    {
317      if (!IsServer(client_p))
318      {
319 <      sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS),
320 <                   me.name, EmptyString(hpara[0]) ? "*" : hpara[0], mptr->cmd);
319 >      sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS), me.name,
320 >                 EmptyString(hpara[0]) ? "*" : hpara[0], mptr->cmd);
321      }
322      else
323      {
324 <      sendto_realops_flags(UMODE_ALL, L_ALL,
324 >      sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
325                             "Dropping server %s due to (invalid) command '%s' "
326                             "with only %d arguments (expecting %d).",
327 <                           client_p->name, mptr->cmd, i, mptr->parameters);
328 <      ilog(L_CRIT, "Insufficient parameters (%d) for command '%s' from %s.",
327 >                           client_p->name, mptr->cmd, i, mptr->args_min);
328 >      ilog(LOG_TYPE_IRCD, "Insufficient parameters (%d) for command '%s' from %s.",
329             i, mptr->cmd, client_p->name);
330        exit_client(client_p, client_p,
331                    "Not enough arguments to server command.");
# Line 400 | Line 335 | handle_command(struct Message *mptr, str
335      (*handler)(client_p, from, i, hpara);
336   }
337  
403 – /* clear_tree_parse()
404 – *
405 – * inputs       - NONE
406 – * output       - NONE
407 – * side effects - MUST MUST be called at startup ONCE before
408 – *                any other keyword routine is used.
409 – */
410 – void
411 – clear_tree_parse(void)
412 – {
413 –  memset(&msg_tree, 0, sizeof(msg_tree));
414 – }
415 –
338   /* add_msg_element()
339   *
340   * inputs       - pointer to MessageTree
# Line 434 | Line 356 | clear_tree_parse(void)
356   * in the parent.
357   */
358   static void
359 < add_msg_element(struct MessageTree *mtree_p,
360 <                struct Message *msg_p, const char *cmd)
359 > add_msg_element(struct MessageTree *mtree_p, struct Message *msg_p,
360 >                const char *cmd)
361   {
362    struct MessageTree *ntree_p;
363  
364    if (*cmd == '\0')
365    {
366      mtree_p->msg = msg_p;
367 <    mtree_p->links++;           /* Have msg pointer, so up ref count */
367 >    mtree_p->links++;  /* Have msg pointer, so up ref count */
368    }
369    else
370    {
# Line 452 | Line 374 | add_msg_element(struct MessageTree *mtre
374       * Thus 'A' -> 0x1 'B' -> 0x2 'c' -> 0x3 etc.
375       */
376  
377 <    if ((ntree_p = mtree_p->pointers[*cmd & (MAXPTRLEN-1)]) == NULL)
377 >    if ((ntree_p = mtree_p->pointers[*cmd & (MAXPTRLEN - 1)]) == NULL)
378      {
379 <      ntree_p = (struct MessageTree *)MyMalloc(sizeof(struct MessageTree));
380 <      mtree_p->pointers[*cmd & (MAXPTRLEN-1)] = ntree_p;
379 >      ntree_p = MyMalloc(sizeof(struct MessageTree));
380 >      mtree_p->pointers[*cmd & (MAXPTRLEN - 1)] = ntree_p;
381  
382 <      mtree_p->links++;         /* Have new pointer, so up ref count */
382 >      mtree_p->links++;  /* Have new pointer, so up ref count */
383      }
384 <    add_msg_element(ntree_p, msg_p, cmd+1);
384 >
385 >    add_msg_element(ntree_p, msg_p, cmd + 1);
386    }
387   }
388  
# Line 491 | Line 414 | del_msg_element(struct MessageTree *mtre
414   {
415    struct MessageTree *ntree_p;
416  
417 <  /* In case this is called for a nonexistent command
417 >  /*
418 >   * In case this is called for a nonexistent command
419     * check that there is a msg pointer here, else links-- goes -ve
420     * -db
421     */
498 –
422    if ((*cmd == '\0') && (mtree_p->msg != NULL))
423    {
424      mtree_p->msg = NULL;
# Line 503 | Line 426 | del_msg_element(struct MessageTree *mtre
426    }
427    else
428    {
429 <    if ((ntree_p = mtree_p->pointers[*cmd & (MAXPTRLEN-1)]) != NULL)
429 >    if ((ntree_p = mtree_p->pointers[*cmd & (MAXPTRLEN - 1)]) != NULL)
430      {
431 <      del_msg_element(ntree_p, cmd+1);
431 >      del_msg_element(ntree_p, cmd + 1);
432 >
433        if (ntree_p->links == 0)
434        {
435 <        mtree_p->pointers[*cmd & (MAXPTRLEN-1)] = NULL;
436 <        mtree_p->links--;
437 <        MyFree(ntree_p);
435 >        mtree_p->pointers[*cmd & (MAXPTRLEN - 1)] = NULL;
436 >        mtree_p->links--;
437 >        MyFree(ntree_p);
438        }
439      }
440    }
# Line 524 | Line 448 | del_msg_element(struct MessageTree *mtre
448   * side effects - none
449   */
450   static struct Message *
451 < msg_tree_parse(const char *cmd, struct MessageTree *root)
451 > msg_tree_parse(const char *cmd)
452   {
453 <  struct MessageTree *mtree;
453 >  struct MessageTree *mtree = &msg_tree;
454    assert(cmd && *cmd);
531 –  for (mtree = root->pointers[(*cmd) & (MAXPTRLEN-1)]; mtree != NULL;
532 –       mtree = mtree->pointers[(*++cmd) & (MAXPTRLEN-1)])
533 –  {
534 –    if (!IsAlpha(*cmd))
535 –      return(NULL);
536 –    if (*(cmd + 1) == '\0')
537 –      return(mtree->msg); /* NULL if parsed invalid/unknown command */
455  
456 <  }
456 >  while (IsAlpha(*cmd) && (mtree = mtree->pointers[*cmd & (MAXPTRLEN - 1)]))
457 >    if (*++cmd == '\0')
458 >      return mtree->msg;
459  
460 <  return(NULL);
460 >  return NULL;
461   }
462  
463   /* mod_add_cmd()
# Line 552 | Line 471 | msg_tree_parse(const char *cmd, struct M
471   void
472   mod_add_cmd(struct Message *msg)
473   {
474 <  struct Message *found_msg;
556 <
557 <  if (msg == NULL)
558 <    return;
559 <
560 <  /* someone loaded a module with a bad messagetab */
561 <  assert(msg->cmd != NULL);
474 >  assert(msg && msg->cmd);
475  
476    /* command already added? */
477 <  if ((found_msg = msg_tree_parse(msg->cmd, &msg_tree)) != NULL)
477 >  if (msg_tree_parse(msg->cmd))
478      return;
479  
480    add_msg_element(&msg_tree, msg, msg->cmd);
# Line 577 | Line 490 | mod_add_cmd(struct Message *msg)
490   void
491   mod_del_cmd(struct Message *msg)
492   {
493 <  assert(msg != NULL);
581 <
582 <  if (msg == NULL)
583 <    return;
493 >  assert(msg && msg->cmd);
494  
495    del_msg_element(&msg_tree, msg->cmd);
496   }
# Line 594 | Line 504 | mod_del_cmd(struct Message *msg)
504   struct Message *
505   find_command(const char *cmd)
506   {
507 <  return(msg_tree_parse(cmd, &msg_tree));
507 >  return msg_tree_parse(cmd);
508 > }
509 >
510 > static void
511 > recurse_report_messages(struct Client *source_p, const struct MessageTree *mtree)
512 > {
513 >  unsigned int i;
514 >
515 >  if (mtree->msg != NULL)
516 >    sendto_one(source_p, form_str(RPL_STATSCOMMANDS),
517 >               me.name, source_p->name, mtree->msg->cmd,
518 >               mtree->msg->count, mtree->msg->bytes,
519 >               mtree->msg->rcount);
520 >
521 >  for (i = 0; i < MAXPTRLEN; ++i)
522 >    if (mtree->pointers[i] != NULL)
523 >      recurse_report_messages(source_p, mtree->pointers[i]);
524   }
525  
526   /* report_messages()
# Line 606 | Line 532 | find_command(const char *cmd)
532   void
533   report_messages(struct Client *source_p)
534   {
535 <  struct MessageTree *mtree = &msg_tree;
536 <  int i;
535 >  const struct MessageTree *mtree = &msg_tree;
536 >  unsigned int i;
537  
538 <  for (i = 0; i < MAXPTRLEN; i++)
613 <  {
538 >  for (i = 0; i < MAXPTRLEN; ++i)
539      if (mtree->pointers[i] != NULL)
540        recurse_report_messages(source_p, mtree->pointers[i]);
616 –  }
617 – }
618 –
619 – static void
620 – recurse_report_messages(struct Client *source_p, struct MessageTree *mtree)
621 – {
622 –  int i;
623 –
624 –  if (mtree->msg != NULL)
625 –  {
626 –    sendto_one(source_p, form_str(RPL_STATSCOMMANDS),
627 –               me.name, source_p->name, mtree->msg->cmd,
628 –               mtree->msg->count, mtree->msg->bytes,
629 –               mtree->msg->rcount);
630 –  }
631 –
632 –  for (i = 0; i < MAXPTRLEN; i++)
633 –  {
634 –    if (mtree->pointers[i] != NULL)
635 –      recurse_report_messages(source_p, mtree->pointers[i]);
636 –  }
541   }
542  
543   /* cancel_clients()
# Line 667 | Line 571 | cancel_clients(struct Client *client_p,
571     */
572    if (IsServer(source_p) || IsMe(source_p))
573    {
574 <    sendto_realops_flags(UMODE_DEBUG, L_ADMIN, "Message for %s[%s] from %s",
574 >    sendto_realops_flags(UMODE_DEBUG, L_ADMIN, SEND_NOTICE,
575 >                         "Message for %s[%s] from %s",
576                           source_p->name, source_p->from->name,
577                           get_client_name(client_p, SHOW_IP));
578 <    sendto_realops_flags(UMODE_DEBUG, L_OPER,  "Message for %s[%s] from %s",
578 >    sendto_realops_flags(UMODE_DEBUG, L_OPER, SEND_NOTICE,
579 >                         "Message for %s[%s] from %s",
580                           source_p->name, source_p->from->name,
581                           get_client_name(client_p, MASK_IP));
582 <    sendto_realops_flags(UMODE_DEBUG, L_ALL,
582 >    sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
583                           "Not dropping server %s (%s) for Fake Direction",
584                           client_p->name, source_p->name);
585 <    return(-1);
585 >    return -1;
586      /* return exit_client(client_p, client_p, &me, "Fake Direction");*/
587    }
588  
# Line 689 | Line 595 | cancel_clients(struct Client *client_p,
595     *
596     * all servers must be TS these days --is
597     */
598 <  sendto_realops_flags(UMODE_DEBUG, L_ADMIN,
598 >  sendto_realops_flags(UMODE_DEBUG, L_ADMIN, SEND_NOTICE,
599                         "Message for %s[%s@%s!%s] from %s (TS, ignored)",
600                         source_p->name, source_p->username, source_p->host,
601                         source_p->from->name, get_client_name(client_p, SHOW_IP));
602 <  sendto_realops_flags(UMODE_DEBUG, L_OPER,
602 >  sendto_realops_flags(UMODE_DEBUG, L_OPER, SEND_NOTICE,
603                         "Message for %s[%s@%s!%s] from %s (TS, ignored)",
604                         source_p->name, source_p->username, source_p->host,
605                         source_p->from->name, get_client_name(client_p, MASK_IP));
606  
607 <  return(0);
607 >  return 0;
608   }
609  
610   /* remove_unknown()
# Line 721 | Line 627 | remove_unknown(struct Client *client_p,
627    if ((IsDigit(*lsender) && strlen(lsender) <= IRC_MAXSID) ||
628        strchr(lsender, '.') != NULL)
629    {
630 <    sendto_realops_flags(UMODE_DEBUG, L_ADMIN,
630 >    sendto_realops_flags(UMODE_DEBUG, L_ADMIN, SEND_NOTICE,
631                           "Unknown prefix (%s) from %s, Squitting %s",
632                           lbuffer, get_client_name(client_p, SHOW_IP), lsender);
633 <    sendto_realops_flags(UMODE_DEBUG, L_OPER,
633 >    sendto_realops_flags(UMODE_DEBUG, L_OPER, SEND_NOTICE,
634                           "Unknown prefix (%s) from %s, Squitting %s",
635                           lbuffer, client_p->name, lsender);
636      sendto_one(client_p, ":%s SQUIT %s :(Unknown prefix (%s) from %s)",
# Line 748 | Line 654 | remove_unknown(struct Client *client_p,
654   *      wrong with the message, just *DROP* it! Don't even think of
655   *      sending back a neat error message -- big danger of creating
656   *      a ping pong error message...
657 + *
658 + * Rewritten by Nemesi, Jan 1999, to support numeric nicks in parv[1]
659 + *
660 + * Called when we get a numeric message from a remote _server_ and we are
661 + * supposed to forward it somewhere. Note that we always ignore numerics sent
662 + * to 'me' and simply drop the message if we can't handle with this properly:
663 + * the savvy approach is NEVER generate an error in response to an... error :)
664   */
665   static void
666 < do_numeric(char numeric[], struct Client *client_p, struct Client *source_p,
667 <           int parc, char *parv[])
666 > handle_numeric(char numeric[], struct Client *client_p, struct Client *source_p,
667 >               int parc, char *parv[])
668   {
669 <  struct Client *target_p;
670 <  struct Channel *chptr;
758 <  char *t;    /* current position within the buffer */
759 <  int i, tl;  /* current length of presently being built string in t */
669 >  struct Client *target_p = NULL;
670 >  struct Channel *chptr = NULL;
671  
672 +  /* Avoid trash, we need it to come from a server and have a target  */
673    if (parc < 2 || !IsServer(source_p))
674      return;
675  
676 <  /* Remap low number numerics. */
677 <  if (numeric[0] == '0')
678 <    numeric[0] = '1';
679 <
680 <  /* Prepare the parameter portion of the message into 'buffer'.
681 <   * (Because the buffer is twice as large as the message buffer
770 <   * for the socket, no overflow can occur here... ...on current
771 <   * assumptions--bets are off, if these are changed --msa)
676 >  /*
677 >   * Who should receive this message ? Will we do something with it ?
678 >   *  Note that we use findUser functions, so the target can't be neither
679 >   *  a server, nor a channel (?) nor a list of targets (?) .. u2.10
680 >   *  should never generate numeric replies to non-users anyway
681 >   *  Ahem... it can be a channel actually, csc bots use it :\ --Nem
682     */
683 <  t = buffer;
684 <  for (i = 2; i < (parc - 1); i++)
685 <  {
686 <    tl = ircsprintf(t, " %s", parv[i]);
777 <    t += tl;
778 <  }
779 <
780 <  ircsprintf(t," :%s", parv[parc-1]);
781 <
782 <  if (((target_p = find_person(client_p, parv[1])) != NULL) ||
783 <      ((target_p = find_server(parv[1])) != NULL))
784 <  {
785 <    if (IsMe(target_p))
786 <    {
787 <      int num;
788 <
789 <      /*
790 <       * We shouldn't get numerics sent to us,
791 <       * any numerics we do get indicate a bug somewhere..
792 <       */
793 <      /* ugh.  this is here because of nick collisions.  when two servers
794 <       * relink, they burst each other their nicks, then perform collides.
795 <       * if there is a nick collision, BOTH servers will kill their own
796 <       * nicks, and BOTH will kill the other servers nick, which wont exist,
797 <       * because it will have been already killed by the local server.
798 <       *
799 <       * unfortunately, as we cant guarantee other servers will do the
800 <       * "right thing" on a nick collision, we have to keep both kills.  
801 <       * ergo we need to ignore ERR_NOSUCHNICK. --fl_
802 <       */
803 <      /* quick comment. This _was_ tried. i.e. assume the other servers
804 <       * will do the "right thing" and kill a nick that is colliding.
805 <       * unfortunately, it did not work. --Dianora
806 <       */
683 >  if (IsChanPrefix(*parv[1]))
684 >    chptr = hash_find_channel(parv[1]);
685 >  else
686 >    target_p = find_person(client_p, parv[1]);
687  
688 <      /* Yes, a good compiler would have optimised this, but
689 <       * this is probably easier to read. -db
810 <       */
811 <      num = atoi(numeric);
688 >  if (((!target_p) || (target_p->from == client_p)) && !chptr)
689 >    return;
690  
691 <      if ((num != ERR_NOSUCHNICK))
692 <        sendto_realops_flags(UMODE_ALL, L_ADMIN,
693 <                             "*** %s(via %s) sent a %s numeric to me: %s",
694 <                             source_p->name, client_p->name, numeric, buffer);
695 <      return;
696 <    }
697 <    else if (target_p->from == client_p)
698 <    {
699 <      /* This message changed direction (nick collision?)
700 <       * ignore it.
701 <       */
824 <      return;
825 <    }
691 >  /*
692 >   * Remap low number numerics, not that I understand WHY.. --Nemesi
693 >   */
694 >  /*
695 >   * numerics below 100 talk about the current 'connection', you're not
696 >   * connected to a remote server so it doesn't make sense to send them
697 >   * remotely - but the information they contain may be useful, so we
698 >   * remap them up.  Weird, but true.  -- Isomer
699 >   */
700 >  if (numeric[0] == '0')
701 >    numeric[0] = '1';
702  
703 <    /* csircd will send out unknown umode flag for +a (admin), drop it here. */
704 <    if ((atoi(numeric) == ERR_UMODEUNKNOWNFLAG) && MyClient(target_p))
829 <      return;
830 <    
703 >  if (target_p)
704 >  {
705      /* Fake it for server hiding, if its our client */
706 <    if (ConfigServerHide.hide_servers &&
707 <        MyClient(target_p) && !IsOper(target_p))
708 <      sendto_one(target_p, ":%s %s %s%s", me.name, numeric, target_p->name, buffer);
709 <    else if (!MyClient(target_p) && IsCapable(target_p->from, CAP_TS6) && HasID(source_p))
710 <      sendto_one(target_p, ":%s %s %s%s", source_p->id, numeric, target_p->id, buffer);
711 <    else /* either it is our client, or a client linked throuh a non-ts6 server. must use names! */
838 <      sendto_one(target_p, ":%s %s %s%s", source_p->name, numeric, target_p->name, buffer);
839 <    return;
706 >    if (ConfigServerHide.hide_servers && MyClient(target_p) &&
707 >        !HasUMode(target_p, UMODE_OPER))
708 >      sendto_one(target_p, ":%s %s %s %s", me.name, numeric, target_p->name, parv[2]);
709 >    else
710 >      sendto_one(target_p, ":%s %s %s %s", ID_or_name(source_p, target_p->from),
711 >                 numeric, ID_or_name(target_p, target_p->from), parv[2]);
712    }
713 <  else if ((chptr = hash_find_channel(parv[1])) != NULL)
714 <    sendto_channel_local(ALL_MEMBERS, NO, chptr,
715 <                         ":%s %s %s %s",
844 <                         source_p->name,
845 <                         numeric, chptr->chname, buffer);
713 >  else
714 >    sendto_channel_local(ALL_MEMBERS, 0, chptr, ":%s %s %s %s",
715 >                         source_p->name, numeric, chptr->chname, parv[2]);
716   }
717  
718   /* m_not_oper()
# Line 855 | Line 725 | m_not_oper(struct Client *client_p, stru
725             int parc, char *parv[])
726   {
727    sendto_one(source_p, form_str(ERR_NOPRIVILEGES),
728 <             me.name, parv[0]);
728 >             me.name, source_p->name);
729   }
730  
731   void
732   m_unregistered(struct Client *client_p, struct Client *source_p,
733                 int parc, char *parv[])
734   {
735 <  /* bit of a hack.
736 <   * I don't =really= want to waste a bit in a flag
867 <   * number_of_nick_changes is only really valid after the client
868 <   * is fully registered..
869 <   */
870 <  if (client_p->localClient->number_of_nick_changes == 0)
871 <  {
872 <    sendto_one(client_p, ":%s %d * %s :Register first.",
873 <               me.name, ERR_NOTREGISTERED, parv[0]);
874 <    client_p->localClient->number_of_nick_changes++;
875 <  }
735 >  sendto_one(source_p, form_str(ERR_NOTREGISTERED), me.name,
736 >             source_p->name[0] ? source_p->name : "*");
737   }
738  
739   void
740   m_registered(struct Client *client_p, struct Client *source_p,
741               int parc, char *parv[])
742   {
743 <  sendto_one(client_p, form_str(ERR_ALREADYREGISTRED),  
744 <             me.name, parv[0]);
743 >  sendto_one(source_p, form_str(ERR_ALREADYREGISTRED),  
744 >             me.name, source_p->name);
745   }
746  
747   void
# Line 890 | Line 751 | m_ignore(struct Client *client_p, struct
751    return;
752   }
753  
754 + void
755 + rfc1459_command_send_error(struct Client *client_p, struct Client *source_p,
756 +                           int parc, char *parv[])
757 + {
758 +  const char *in_para;
759 +
760 +  in_para = (parc > 1 && *parv[1] != '\0') ? parv[1] : "<>";
761 +
762 +  ilog(LOG_TYPE_IRCD, "Received ERROR message from %s: %s",
763 +       source_p->name, in_para);
764 +
765 +  if (client_p == source_p)
766 +  {
767 +    sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
768 +                         "ERROR :from %s -- %s",
769 +                         get_client_name(client_p, HIDE_IP), in_para);
770 +    sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
771 +                         "ERROR :from %s -- %s",
772 +                         get_client_name(client_p, MASK_IP), in_para);
773 +  }
774 +  else
775 +  {
776 +    sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
777 +                         "ERROR :from %s via %s -- %s",
778 +                         source_p->name, get_client_name(client_p, HIDE_IP), in_para);
779 +    sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
780 +                         "ERROR :from %s via %s -- %s",
781 +                         source_p->name, get_client_name(client_p, MASK_IP), in_para);
782 +  }
783 +
784 +  if (MyClient(source_p))
785 +    exit_client(source_p, source_p, "ERROR");
786 + }

Diff Legend

– Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)