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/trunk/src/parse.c (file contents):
Revision 4298 by michael, Sun Jul 20 13:51:16 2014 UTC vs.
Revision 9400 by michael, Fri May 15 20:43:28 2020 UTC

# Line 1 | Line 1
1   /*
2   *  ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3   *
4 < *  Copyright (c) 1997-2014 ircd-hybrid development team
4 > *  Copyright (c) 1997-2020 ircd-hybrid development team
5   *
6   *  This program is free software; you can redistribute it and/or modify
7   *  it under the terms of the GNU General Public License as published by
# Line 15 | Line 15
15   *
16   *  You should have received a copy of the GNU General Public License
17   *  along with this program; if not, write to the Free Software
18 < *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
18 > *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
19   *  USA
20   */
21  
# Line 29 | Line 29
29   #include "parse.h"
30   #include "channel.h"
31   #include "hash.h"
32 + #include "id.h"
33   #include "irc_string.h"
34   #include "ircd.h"
35   #include "numeric.h"
# Line 38 | Line 39
39   #include "memory.h"
40   #include "user.h"
41   #include "server.h"
42 + #include "packet.h"
43  
44  
45   /*
# Line 82 | Line 84
84   * For a small parser like this, this is a good compromise and does
85   * make it somewhat faster. - Dianora
86   */
87 < #define MAXPTRLEN 32
87 > enum { MAXPTRLEN = 32 };
88  
89  
90   static struct MessageTree
# Line 102 | Line 104 | static struct MessageTree
104   * side effects -
105   */
106   static void
107 < parse_remove_unknown(struct Client *client_p, char *lsender, char *lbuffer)
107 > parse_remove_unknown(struct Client *client, const char *lsender, char *lbuffer)
108   {
109    /*
110     * Do kill if it came from a server because it means there is a ghost
# Line 118 | Line 120 | parse_remove_unknown(struct Client *clie
120    {
121      sendto_realops_flags(UMODE_DEBUG, L_ADMIN, SEND_NOTICE,
122                           "Unknown prefix (%s) from %s, Squitting %s",
123 <                         lbuffer, get_client_name(client_p, SHOW_IP), lsender);
123 >                         lbuffer, client_get_name(client, SHOW_IP), lsender);
124      sendto_realops_flags(UMODE_DEBUG, L_OPER, SEND_NOTICE,
125                           "Unknown prefix (%s) from %s, Squitting %s",
126 <                         lbuffer, client_p->name, lsender);
127 <    sendto_one(client_p, ":%s SQUIT %s :(Unknown prefix (%s) from %s)",
128 <               me.id, lsender, lbuffer, client_p->name);
126 >                         lbuffer, client_get_name(client, MASK_IP), lsender);
127 >    sendto_one(client, ":%s SQUIT %s :(Unknown prefix (%s) from %s)",
128 >               me.id, lsender, lbuffer, client->name);
129    }
130    else
131 <    sendto_one(client_p, ":%s KILL %s :%s (Unknown Client)",
131 >    sendto_one(client, ":%s KILL %s :%s (Unknown Client)",
132                 me.id, lsender, me.name);
133   }
134  
133 – /* cancel_clients()
134 – *
135 – * inputs       -
136 – * output       -
137 – * side effects -
138 – */
139 – static void
140 – parse_cancel_clients(struct Client *client_p, struct Client *source_p, char *cmd)
141 – {
142 –  if (IsServer(source_p) || IsMe(source_p))
143 –  {
144 –    sendto_realops_flags(UMODE_DEBUG, L_ADMIN, SEND_NOTICE,
145 –                         "Message for %s[%s] from %s",
146 –                         source_p->name, source_p->from->name,
147 –                         get_client_name(client_p, SHOW_IP));
148 –    sendto_realops_flags(UMODE_DEBUG, L_OPER, SEND_NOTICE,
149 –                         "Message for %s[%s] from %s",
150 –                         source_p->name, source_p->from->name,
151 –                         get_client_name(client_p, MASK_IP));
152 –    sendto_realops_flags(UMODE_DEBUG, L_ALL, SEND_NOTICE,
153 –                         "Not dropping server %s (%s) for Fake Direction",
154 –                         client_p->name, source_p->name);
155 –    return;
156 –  }
157 –
158 –  sendto_realops_flags(UMODE_DEBUG, L_ADMIN, SEND_NOTICE,
159 –                       "Message for %s[%s@%s!%s] from %s (TS, ignored)",
160 –                       source_p->name, source_p->username, source_p->host,
161 –                       source_p->from->name, get_client_name(client_p, SHOW_IP));
162 –  sendto_realops_flags(UMODE_DEBUG, L_OPER, SEND_NOTICE,
163 –                       "Message for %s[%s@%s!%s] from %s (TS, ignored)",
164 –                       source_p->name, source_p->username, source_p->host,
165 –                       source_p->from->name, get_client_name(client_p, MASK_IP));
166 – }
167 –
135   /*
136   *
137   *      parc    number of arguments ('sender' counted as one!)
# Line 187 | Line 154 | parse_cancel_clients(struct Client *clie
154   * the savvy approach is NEVER generate an error in response to an... error :)
155   */
156   static void
157 < parse_handle_numeric(unsigned int numeric, struct Client *source_p, int parc, char *parv[])
157 > parse_handle_numeric(unsigned int numeric, struct Client *source, int parc, char *parv[])
158   {
192 –  struct Client *target_p = NULL;
193 –  struct Channel *chptr = NULL;
194 –
159    /*
160     * Avoid trash, we need it to come from a server and have a target
161     */
162 <  if (parc < 2 || !IsServer(source_p))
199 <    return;
200 <
201 <  /*
202 <   * Who should receive this message ? Will we do something with it ?
203 <   * Note that we use findUser functions, so the target can't be neither
204 <   * a server, nor a channel (?) nor a list of targets (?) .. u2.10
205 <   * should never generate numeric replies to non-users anyway
206 <   * Ahem... it can be a channel actually, csc bots use it :\ --Nem
207 <   */
208 <  if (IsChanPrefix(*parv[1]))
209 <    chptr = hash_find_channel(parv[1]);
210 <  else
211 <    target_p = find_person(source_p, parv[1]);
212 <
213 <  if (((!target_p) || (target_p->from == source_p->from)) && !chptr)
162 >  if (parc < 2 || !IsServer(source))
163      return;
164  
165    /*
# Line 225 | Line 174 | parse_handle_numeric(unsigned int numeri
174    if (numeric < 100)
175      numeric += 100;
176  
177 <  if (target_p)
177 >  /*
178 >   * Who should receive this message ? Will we do something with it ?
179 >   * Note that we use findUser functions, so the target can't be neither
180 >   * a server, nor a channel (?) nor a list of targets (?) .. u2.10
181 >   * should never generate numeric replies to non-users anyway
182 >   * Ahem... it can be a channel actually, csc bots use it :\ --Nem
183 >   */
184 >  if (IsChanPrefix(*parv[1]))
185    {
186 +    struct Channel *channel = hash_find_channel(parv[1]);
187 +    if (channel == NULL)
188 +      return;
189 +
190 +    sendto_channel_butone(source, source, channel, 0, "%u %s %s",
191 +                          numeric, channel->name, parv[2]);
192 +  }
193 +  else
194 +  {
195 +    struct Client *target = find_person(source, parv[1]);
196 +    if (target == NULL || target->from == source->from)
197 +      return;
198 +
199      /* Fake it for server hiding, if it's our client */
200 <    if ((ConfigServerHide.hide_servers || IsHidden(source_p)) && MyConnect(target_p) &&
201 <        !HasUMode(target_p, UMODE_OPER))
202 <      sendto_one_numeric(target_p, &me, numeric|SND_EXPLICIT, "%s", parv[2]);
200 >    if ((ConfigServerHide.hide_servers || IsHidden(source)) && MyConnect(target) &&
201 >        !HasUMode(target, UMODE_OPER))
202 >      sendto_one_numeric(target, &me, numeric | SND_EXPLICIT, "%s", parv[2]);
203      else
204 <      sendto_one_numeric(target_p, source_p, numeric|SND_EXPLICIT, "%s", parv[2]);
204 >      sendto_one_numeric(target, source, numeric | SND_EXPLICIT, "%s", parv[2]);
205    }
237 –  else
238 –    sendto_channel_butone(source_p, source_p, chptr, 0, "%u %s %s",
239 –                          numeric, chptr->chname, parv[2]);
206   }
207  
208   /* handle_command()
# Line 250 | Line 216 | parse_handle_numeric(unsigned int numeri
216   * side effects -
217   */
218   static void
219 < parse_handle_command(struct Message *mptr, struct Client *source_p,
219 > parse_handle_command(struct Message *message, struct Client *source,
220                       unsigned int i, char *para[])
221   {
222 <  if (IsServer(source_p->from))
223 <    ++mptr->rcount;
222 >  const struct MessageHandler *const handler = &message->handlers[source->from->handler];
223 >
224 >  if (IsServer(source->from))
225 >    ++message->rcount;
226 >  ++message->count;
227  
228 <  ++mptr->count;
228 >  if (handler->end_grace_period == true && MyClient(source))
229 >    flood_endgrace(source);
230  
231    /* Check right amount of parameters is passed... --is */
232 <  if (i < mptr->args_min)
233 <    sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, mptr->cmd);
232 >  if (handler->args_min &&
233 >      ((i < handler->args_min) ||
234 >       (handler->empty_last_arg != true && EmptyString(para[handler->args_min - 1]))))
235 >    sendto_one_numeric(source, &me, ERR_NEEDMOREPARAMS, message->cmd);
236    else
237 <    mptr->handlers[source_p->from->handler](source_p, i, para);
237 >    handler->handler(source, i, para);
238   }
239  
240   /*
# Line 271 | Line 243 | parse_handle_command(struct Message *mpt
243   * NOTE: parse() should not be called recusively by any other functions!
244   */
245   void
246 < parse(struct Client *client_p, char *pbuffer, char *bufend)
246 > parse(struct Client *client, char *pbuffer, char *bufend)
247   {
248 <  struct Client *from = client_p;
249 <  struct Message *msg_ptr = NULL;
248 >  struct Client *from = client;
249 >  struct Message *message = NULL;
250    char *para[MAXPARA + 2];  /* <command> + <parameters> + NULL */
251    char *ch = NULL;
252    char *s = NULL;
# Line 282 | Line 254 | parse(struct Client *client_p, char *pbu
254    unsigned int parc = 0;
255    unsigned int paramcount;
256  
257 <  if (IsDefunct(client_p))
257 >  if (IsDead(client))
258      return;
259  
260 <  assert(client_p->localClient->fd.flags.open);
260 >  assert(client->connection);
261 >  assert(client->connection->fd);
262 >  assert(client->connection->fd->flags.open);
263 >
264 >
265    assert((bufend - pbuffer) < IRCD_BUFSIZE);
266  
267    for (ch = pbuffer; *ch == ' '; ++ch)  /* Skip spaces */
# Line 297 | Line 273 | parse(struct Client *client_p, char *pbu
273       * Copy the prefix to 'sender' assuming it terminates
274       * with SPACE (or NULL, which is an error, though).
275       */
276 <    char *sender = ++ch;
276 >    const char *const sender = ++ch;
277  
278      if ((s = strchr(ch, ' ')))
279      {
# Line 305 | Line 281 | parse(struct Client *client_p, char *pbu
281        ch = ++s;
282      }
283  
284 <    if (*sender && IsServer(client_p))
284 >    if (*sender && IsServer(client))
285      {
286 <      if ((from = find_person(client_p, sender)) == NULL)
287 <        from = hash_find_server(sender);
286 >      if ((from = hash_find_id(sender)) == NULL)
287 >        from = hash_find_client(sender);
288  
289        /*
290         * Hmm! If the client corresponding to the prefix is not found--what is
# Line 318 | Line 294 | parse(struct Client *client_p, char *pbu
294        if (from == NULL)
295        {
296          ++ServerStats.is_unpf;
297 <        parse_remove_unknown(client_p, sender, pbuffer);
297 >        parse_remove_unknown(client, sender, pbuffer);
298          return;
299        }
300  
301 <      if (from->from != client_p)
301 >      if (from->from != client)
302        {
303          ++ServerStats.is_wrdi;
304 <        parse_cancel_clients(client_p, from, pbuffer);
304 >        sendto_realops_flags(UMODE_DEBUG, L_ADMIN, SEND_NOTICE,
305 >                             "Fake direction: dropped message from %s[%s] via %s",
306 >                             from->name, from->from->name,
307 >                             client_get_name(client, SHOW_IP));
308 >        sendto_realops_flags(UMODE_DEBUG, L_OPER, SEND_NOTICE,
309 >                             "Fake direction: dropped message from %s[%s] via %s",
310 >                             from->name, from->from->name,
311 >                             client_get_name(client, MASK_IP));
312          return;
313        }
314      }
# Line 360 | Line 343 | parse(struct Client *client_p, char *pbu
343    }
344    else
345    {
363 –    unsigned int ii = 0;
364 –
346      if ((s = strchr(ch, ' ')))
347        *s++ = '\0';
348  
349 <    if ((msg_ptr = find_command(ch)) == NULL)
349 >    if ((message = find_command(ch)) == NULL)
350      {
351        /*
352         * Note: Give error message *only* to recognized
# Line 386 | Line 367 | parse(struct Client *client_p, char *pbu
367        return;
368      }
369  
370 <    assert(msg_ptr->cmd);
370 >    assert(message->cmd);
371 >
372 >    paramcount = message->handlers[from->from->handler].args_max;
373  
374 <    paramcount = msg_ptr->args_max;
375 <    ii = bufend - ((s) ? s : ch);
393 <    msg_ptr->bytes += ii;
374 >    size_t length = bufend - ((s) ? s : ch);
375 >    message->bytes += length;
376    }
377  
378 +  memset(para, 0, sizeof(para));
379 +
380    /*
381     * Must the following loop really be so devious? On surface it
382     * splits the message to parameters from blank spaces. But, if
# Line 404 | Line 388 | parse(struct Client *client_p, char *pbu
388  
389    para[parc] = ch;
390  
391 +  if (message && message->extra)
392 +  {
393 +    /*
394 +     * XXX: This will have to go away after the command handler rewrite
395 +     */
396 +    para[++parc] = message->extra;
397 +  }
398 +
399    if (s)
400    {
401 <    if (paramcount > MAXPARA)
401 >    if (paramcount == 0 || paramcount > MAXPARA)
402        paramcount = MAXPARA;
403  
404 <    while (1)
404 >    while (true)
405      {
406         while (*s == ' ')
407           *s++ = '\0';
# Line 419 | Line 411 | parse(struct Client *client_p, char *pbu
411  
412         if (*s == ':')
413         {
414 <         /* The rest is a single parameter */
415 <         para[++parc] = s + (!numeric);  /* Keep the colon if it's a numeric */
414 >         /* The rest is single parameter--can include blanks also. */
415 >         para[++parc] = s + (numeric == 0);  /* Keep the colon if it's a numeric */
416           break;
417         }
418  
# Line 436 | Line 428 | parse(struct Client *client_p, char *pbu
428  
429    para[++parc] = NULL;
430  
431 <  if (msg_ptr)
432 <    parse_handle_command(msg_ptr, from, parc, para);
431 >  if (message)
432 >    parse_handle_command(message, from, parc, para);
433    else
434      parse_handle_numeric(numeric, from, parc, para);
435   }
# Line 466 | Line 458 | static void
458   add_msg_element(struct MessageTree *mtree_p, struct Message *msg_p,
459                  const char *cmd)
460   {
469 –  struct MessageTree *ntree_p = NULL;
470 –
461    if (*cmd == '\0')
462    {
463      mtree_p->msg = msg_p;
# Line 481 | Line 471 | add_msg_element(struct MessageTree *mtre
471       * between 0 and MAXPTRLEN.
472       * Thus 'A' -> 0x1 'B' -> 0x2 'c' -> 0x3 etc.
473       */
474 <    if ((ntree_p = mtree_p->pointers[*cmd & (MAXPTRLEN - 1)]) == NULL)
474 >    struct MessageTree *ntree_p = mtree_p->pointers[*cmd & (MAXPTRLEN - 1)];
475 >    if (ntree_p == NULL)
476      {
477 <      ntree_p = MyCalloc(sizeof(struct MessageTree));
477 >      ntree_p = xcalloc(sizeof(*ntree_p));
478        mtree_p->pointers[*cmd & (MAXPTRLEN - 1)] = ntree_p;
479  
480        mtree_p->links++;  /* Have new pointer, so up ref count */
# Line 519 | Line 510 | add_msg_element(struct MessageTree *mtre
510   static void
511   del_msg_element(struct MessageTree *mtree_p, const char *cmd)
512   {
522 –  struct MessageTree *ntree_p = NULL;
523 –
513    /*
514     * In case this is called for a nonexistent command
515     * check that there is a msg pointer here, else links-- goes -ve
# Line 533 | Line 522 | del_msg_element(struct MessageTree *mtre
522    }
523    else
524    {
525 <    if ((ntree_p = mtree_p->pointers[*cmd & (MAXPTRLEN - 1)]))
525 >    struct MessageTree *ntree_p = mtree_p->pointers[*cmd & (MAXPTRLEN - 1)];
526 >    if (ntree_p)
527      {
528        del_msg_element(ntree_p, cmd + 1);
529  
# Line 541 | Line 531 | del_msg_element(struct MessageTree *mtre
531        {
532          mtree_p->pointers[*cmd & (MAXPTRLEN - 1)] = NULL;
533          mtree_p->links--;
534 <        MyFree(ntree_p);
534 >        xfree(ntree_p);
535        }
536      }
537    }
# Line 559 | Line 549 | msg_tree_parse(const char *cmd)
549   {
550    struct MessageTree *mtree = &msg_tree;
551  
552 <  assert(cmd && *cmd);
552 >  assert(!EmptyString(cmd));
553  
554    while (IsAlpha(*cmd) && (mtree = mtree->pointers[*cmd & (MAXPTRLEN - 1)]))
555      if (*++cmd == '\0')
# Line 577 | Line 567 | msg_tree_parse(const char *cmd)
567   void
568   mod_add_cmd(struct Message *msg)
569   {
570 <  assert(msg && msg->cmd);
570 >  assert(msg);
571 >  assert(msg->cmd);
572  
573    /* Command already added? */
574 <  if (msg_tree_parse(msg->cmd))
575 <    return;
585 <
586 <  add_msg_element(&msg_tree, msg, msg->cmd);
574 >  if (msg_tree_parse(msg->cmd) == NULL)
575 >    add_msg_element(&msg_tree, msg, msg->cmd);
576   }
577  
578   /* mod_del_cmd()
# Line 595 | Line 584 | mod_add_cmd(struct Message *msg)
584   void
585   mod_del_cmd(struct Message *msg)
586   {
587 <  assert(msg && msg->cmd);
588 <
600 <  if (!msg_tree_parse(msg->cmd))
601 <    return;
587 >  assert(msg);
588 >  assert(msg->cmd);
589  
590 <  del_msg_element(&msg_tree, msg->cmd);
590 >  if (msg_tree_parse(msg->cmd))
591 >    del_msg_element(&msg_tree, msg->cmd);
592   }
593  
594   /* find_command()
# Line 616 | Line 604 | find_command(const char *cmd)
604   }
605  
606   static void
607 < recurse_report_messages(struct Client *source_p, const struct MessageTree *mtree)
607 > recurse_report_messages(struct Client *source, const struct MessageTree *mtree)
608   {
609    if (mtree->msg)
610 <    sendto_one_numeric(source_p, &me, RPL_STATSCOMMANDS,
610 >    sendto_one_numeric(source, &me, RPL_STATSCOMMANDS,
611                         mtree->msg->cmd,
612 <                       mtree->msg->count, mtree->msg->bytes,
613 <                       mtree->msg->rcount);
612 >                       mtree->msg->count,
613 >                       mtree->msg->bytes,
614 >                       mtree->msg->rcount,
615 >                       mtree->msg->ecount);
616  
617    for (unsigned int i = 0; i < MAXPTRLEN; ++i)
618      if (mtree->pointers[i])
619 <      recurse_report_messages(source_p, mtree->pointers[i]);
619 >      recurse_report_messages(source, mtree->pointers[i]);
620   }
621  
622   /* report_messages()
# Line 636 | Line 626 | recurse_report_messages(struct Client *s
626   * side effects - client is shown list of commands
627   */
628   void
629 < report_messages(struct Client *source_p)
629 > report_messages(struct Client *source)
630   {
631 <  const struct MessageTree *mtree = &msg_tree;
631 >  const struct MessageTree *const mtree = &msg_tree;
632  
633    for (unsigned int i = 0; i < MAXPTRLEN; ++i)
634      if (mtree->pointers[i])
635 <      recurse_report_messages(source_p, mtree->pointers[i]);
635 >      recurse_report_messages(source, mtree->pointers[i]);
636   }
637  
638   /* m_not_oper()
# Line 650 | Line 640 | report_messages(struct Client *source_p)
640   * output       -
641   * side effects - just returns a nastyogram to given user
642   */
643 < int
644 < m_not_oper(struct Client *source_p, int parc, char *parv[])
643 > void
644 > m_not_oper(struct Client *source, int parc, char *parv[])
645   {
646 <  sendto_one_numeric(source_p, &me, ERR_NOPRIVILEGES);
657 <  return 0;
646 >  sendto_one_numeric(source, &me, ERR_NOPRIVILEGES);
647   }
648  
649 < int
650 < m_unregistered(struct Client *source_p, int parc, char *parv[])
649 > void
650 > m_unregistered(struct Client *source, int parc, char *parv[])
651   {
652 <  sendto_one_numeric(source_p, &me, ERR_NOTREGISTERED);
664 <  return 0;
652 >  sendto_one_numeric(source, &me, ERR_NOTREGISTERED);
653   }
654  
655 < int
656 < m_registered(struct Client *source_p, int parc, char *parv[])
655 > void
656 > m_registered(struct Client *source, int parc, char *parv[])
657   {
658 <  sendto_one_numeric(source_p, &me, ERR_ALREADYREGISTRED);
671 <  return 0;
658 >  sendto_one_numeric(source, &me, ERR_ALREADYREGISTRED);
659   }
660  
661 < int
662 < m_ignore(struct Client *source_p, int parc, char *parv[])
661 > void
662 > m_ignore(struct Client *source, int parc, char *parv[])
663   {
664 <  return 0;
664 >  return;
665   }

Comparing ircd-hybrid/trunk/src/parse.c (property svn:keywords):
Revision 4298 by michael, Sun Jul 20 13:51:16 2014 UTC vs.
Revision 9400 by michael, Fri May 15 20:43:28 2020 UTC

# Line 1 | Line 1
1 < Id Revision
1 > Id

Diff Legend

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