void handle_encap(struct Client *client_p, struct Client *source_p, const char *command, int parc, char *parv[]) { struct Message *mptr; MessageHandler handler = 0; parv[0] = source_p->name; mptr = hash_parse(command); if(mptr == NULL || mptr->cmd == NULL) return; handler = mptr->handlers[ENCAP_HANDLER]; (*handler)(client_p, source_p, parc, parv); }
void handle_encap(struct Client *client_p, struct Client *source_p, const char *command, int parc, const char *parv[]) { struct Message *mptr; struct MessageEntry ehandler; MessageHandler handler = 0; parv[0] = source_p->name; mptr = hash_parse(command); if(mptr == NULL || mptr->cmd == NULL) return; ehandler = mptr->handlers[ENCAP_HANDLER]; handler = ehandler.handler; if(parc < ehandler.min_para || (ehandler.min_para && EmptyString(parv[ehandler.min_para - 1]))) return; (*handler) (client_p, source_p, parc, parv); }
/* * parse a buffer. * * NOTE: parse() should not be called recusively by any other functions! */ void parse(struct Client *client_p, char *pbuffer, char *bufend) { struct Client *from = client_p; char *ch; char *s; char *end; int i; int paramcount, mpara = 0; char *numeric = 0; struct Message *mptr; Debug((DEBUG_DEBUG, "Parsing %s:", pbuffer)); s_assert(!IsDead(client_p)); s_assert(client_p->localClient->fd >= 0); if(IsDead(client_p) || client_p->localClient->fd < 0) return; s_assert(bufend-pbuffer < 512); for (ch = pbuffer; *ch == ' '; ch++) /* skip spaces */ /* null statement */ ; para[0] = from->name; if(*ch == ':') { ch++; /* * Copy the prefix to 'sender' assuming it terminates * with SPACE (or NULL, which is an error, though). */ sender = ch; if((s = strchr(ch, ' '))) { *s = '\0'; s++; ch = s; } i = 0; if(*sender && IsServer(client_p)) { from = find_client(sender); if(from == NULL) { from = find_server(sender); } /* Hmm! If the client corresponding to the * prefix is not found--what is the correct * action??? Now, I will ignore the message * (old IRC just let it through as if the * prefix just wasn't there...) --msa */ if(from == NULL) { Debug((DEBUG_ERROR, "Unknown prefix (%s)(%s) from (%s)", sender, pbuffer, client_p->name)); ServerStats->is_unpf++; remove_unknown(client_p, sender, pbuffer); return; } para[0] = from->name; if(from->from != client_p) { ServerStats->is_wrdi++; Debug((DEBUG_ERROR, "Message (%s) coming from (%s)", pbuffer, client_p->name)); cancel_clients(client_p, from, pbuffer); return; } } while (*ch == ' ') ch++; } if(*ch == '\0') { ServerStats->is_empt++; Debug((DEBUG_NOTICE, "Empty message from host %s:%s", client_p->name, from->name)); return; } /* * Extract the command code from the packet. Point s to the end * of the command code and calculate the length using pointer * arithmetic. Note: only need length for numerics and *all* * numerics must have parameters and thus a space after the command * code. -avalon */ /* EOB is 3 chars long but is not a numeric */ if(*(ch + 3) == ' ' && /* ok, lets see if its a possible numeric.. */ IsDigit(*ch) && IsDigit(*(ch + 1)) && IsDigit(*(ch + 2))) { mptr = (struct Message *) NULL; numeric = ch; paramcount = MAXPARA; ServerStats->is_num++; s = ch + 3; /* I know this is ' ' from above if */ *s++ = '\0'; /* blow away the ' ', and point s to next part */ } else { int ii = 0; if((s = strchr(ch, ' '))) *s++ = '\0'; mptr = hash_parse(ch); if(!mptr || !mptr->cmd) { /* * Note: Give error message *only* to recognized * persons. It's a nightmare situation to have * two programs sending "Unknown command"'s or * equivalent to each other at full blast.... * If it has got to person state, it at least * seems to be well behaving. Perhaps this message * should never be generated, though... --msa * Hm, when is the buffer empty -- if a command * code has been found ?? -Armin */ if(pbuffer[0] != '\0') { if(IsPerson(from)) sendto_one(from, ":%s %d %s %s :Unknown command", me.name, ERR_UNKNOWNCOMMAND, from->name, ch); Debug((DEBUG_ERROR, "Unknown (%s) from %s", ch, get_client_name(client_p, HIDE_IP))); } ServerStats->is_unco++; return; } paramcount = mptr->parameters; mpara = mptr->maxpara; ii = bufend - ((s) ? s : ch); mptr->bytes += ii; } end = bufend - 1; /* XXX this should be done before parse() is called */ if(*end == '\n') *end-- = '\0'; if(*end == '\r') *end = '\0'; i = 0; if(s != NULL) i = string_to_array(s, para); if(mptr == (struct Message *) NULL) { do_numeric(numeric, client_p, from, i, para); return; } if(handle_command(mptr, client_p, from, i, para) < -1) { char *p; for (p = pbuffer; p <= end; p += 8) { /* HACK HACK */ /* Its expected this nasty code can be removed * or rewritten later if still needed. */ if((unsigned long) (p + 8) > (unsigned long) end) { for (; p <= end; p++) { ilog(L_CRIT, "%02x |%c", p[0], p[0]); } } else ilog(L_CRIT, "%02x %02x %02x %02x %02x %02x %02x %02x |%c%c%c%c%c%c%c%c", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); } } }
/* parse() * * given a raw buffer, parses it and generates parv, parc and sender */ void parse(struct Client *client_p, char *pbuffer, char *bufend) { struct Client *from = client_p; char *ch; char *s; char *end; int i = 1; char *numeric = 0; struct Message *mptr; s_assert(MyConnect(client_p)); s_assert(client_p->localClient->fd >= 0); if(IsAnyDead(client_p)) return; for (ch = pbuffer; *ch == ' '; ch++) /* skip spaces */ /* null statement */ ; para[0] = from->name; if(*ch == ':') { ch++; /* point sender to the sender param */ sender = ch; if((s = strchr(ch, ' '))) { *s = '\0'; s++; ch = s; } if(*sender && IsServer(client_p)) { from = find_any_client(sender); /* didnt find any matching client, issue a kill */ if(from == NULL) { ServerStats->is_unpf++; remove_unknown(client_p, sender, pbuffer); return; } para[0] = from->name; /* fake direction, hmm. */ if(from->from != client_p) { ServerStats->is_wrdi++; cancel_clients(client_p, from, pbuffer); return; } } while (*ch == ' ') ch++; } if(*ch == '\0') { ServerStats->is_empt++; return; } /* at this point there must be some sort of command parameter */ /* * Extract the command code from the packet. Point s to the end * of the command code and calculate the length using pointer * arithmetic. Note: only need length for numerics and *all* * numerics must have parameters and thus a space after the command * code. -avalon */ /* EOB is 3 chars long but is not a numeric */ if(*(ch + 3) == ' ' && /* ok, lets see if its a possible numeric.. */ IsDigit(*ch) && IsDigit(*(ch + 1)) && IsDigit(*(ch + 2))) { mptr = NULL; numeric = ch; ServerStats->is_num++; s = ch + 3; /* I know this is ' ' from above if */ *s++ = '\0'; /* blow away the ' ', and point s to next part */ } else { int ii = 0; if((s = strchr(ch, ' '))) *s++ = '\0'; mptr = hash_parse(ch); /* no command or its encap only, error */ if(!mptr || !mptr->cmd) { /* * Note: Give error message *only* to recognized * persons. It's a nightmare situation to have * two programs sending "Unknown command"'s or * equivalent to each other at full blast.... * If it has got to person state, it at least * seems to be well behaving. Perhaps this message * should never be generated, though... --msa * Hm, when is the buffer empty -- if a command * code has been found ?? -Armin */ if(pbuffer[0] != '\0') { if(IsPerson(from)) sendto_one(from, form_str(ERR_UNKNOWNCOMMAND), me.name, from->name, ch); } ServerStats->is_unco++; return; } ii = bufend - ((s) ? s : ch); mptr->bytes += ii; } end = bufend - 1; /* XXX this should be done before parse() is called */ if(*end == '\n') *end-- = '\0'; if(*end == '\r') *end = '\0'; if(s != NULL) i = string_to_array(s, para); if(mptr == NULL) { do_numeric(numeric, client_p, from, i, para); return; } if(handle_command(mptr, client_p, from, i, /* XXX discards const!!! */ (const char **)para) < -1) { char *p; for (p = pbuffer; p <= end; p += 8) { /* HACK HACK */ /* Its expected this nasty code can be removed * or rewritten later if still needed. */ if((unsigned long) (p + 8) > (unsigned long) end) { for (; p <= end; p++) { ilog(L_MAIN, "%02x |%c", p[0], p[0]); } } else ilog(L_MAIN, "%02x %02x %02x %02x %02x %02x %02x %02x |%c%c%c%c%c%c%c%c", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); } } }