/* * handle_command * * inputs - pointer to message block * - pointer to client * - pointer to client message is from * - count of number of args * - pointer to argv[] array * output - -1 if error from server * side effects - */ static int handle_command(struct Message *mptr, struct Client *client_p, struct Client *from, int i, const char **hpara) { struct MessageEntry ehandler; MessageHandler handler = 0; static time_t last_warning; if(IsAnyDead(client_p)) return -1; if(IsServer(client_p)) mptr->rcount++; mptr->count++; ehandler = mptr->handlers[from->handler]; handler = ehandler.handler; /* check right amount of params is passed... --is */ if(i < ehandler.min_para || (ehandler.min_para && EmptyString(hpara[ehandler.min_para - 1]))) { if(!IsServer(client_p)) { sendto_one_numeric(client_p, s_RPL(ERR_NEEDMOREPARAMS), mptr->cmd); if(MyClient(client_p)) return (1); else return (-1); } sendto_realops_flags(UMODE_ALL, L_ALL, "Dropping server %s due to (invalid) command '%s'" " with only %d arguments (expecting %d).", client_p->name, mptr->cmd, i, ehandler.min_para); ilog(L_SERVER, "Insufficient parameters (%d) for command '%s' from %s.", i, mptr->cmd, client_p->name); exit_client(client_p, client_p, client_p, "Not enough arguments to server command."); return (-1); } if(handler == NULL) /* module hasn't set a handler, just use m_ignore */ handler = m_ignore; (*handler) (client_p, from, i, hpara); if(!IsAnyDead(client_p) && IsCork(client_p) && !IsCapable(client_p, CAP_ZIP)) { if(last_warning + 300 <= rb_current_time()) { sendto_realops_flags(UMODE_DEBUG, L_ALL, "Bug: client %s was left corked after command %s", client_p->name, mptr->cmd); last_warning = rb_current_time(); } client_p->localClient->cork_count = 0; send_pop_queue(client_p); } return (1); }
/* * handle_command * * inputs - pointer to message block * - pointer to message buffer * - pointer to client * - pointer to client message is from * output - -1 if error from server * side effects - */ static int handle_command(struct Message *mptr, struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *from) { struct MessageEntry ehandler; MessageHandler handler = 0; char squitreason[80]; if(IsAnyDead(client_p)) return -1; if(IsServer(client_p)) mptr->rcount++; mptr->count++; ehandler = mptr->handlers[from->handler]; handler = ehandler.handler; /* check right amount of params is passed... --is */ if(msgbuf_p->n_para < ehandler.min_para || (ehandler.min_para && EmptyString(msgbuf_p->para[ehandler.min_para - 1]))) { if(!IsServer(client_p)) { sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS), me.name, EmptyString(client_p->name) ? "*" : client_p->name, mptr->cmd); if(MyClient(client_p)) return (1); else return (-1); } sendto_realops_snomask(SNO_GENERAL, L_ALL, "Dropping server %s due to (invalid) command '%s'" " with only %zu arguments (expecting %zu).", client_p->name, mptr->cmd, msgbuf_p->n_para, ehandler.min_para); ilog(L_SERVER, "Insufficient parameters (%zu < %zu) for command '%s' from %s.", msgbuf_p->n_para, ehandler.min_para, mptr->cmd, client_p->name); snprintf(squitreason, sizeof squitreason, "Insufficient parameters (%zu < %zu) for command '%s'", msgbuf_p->n_para, ehandler.min_para, mptr->cmd); exit_client(client_p, client_p, client_p, squitreason); return (-1); } (*handler) (msgbuf_p, client_p, from, msgbuf_p->n_para, msgbuf_p->para); return (1); }
/* parse() * * given a raw buffer, parses it and generates parv and parc */ void parse(struct Client *client_p, char *pbuffer, char *bufend) { struct Client *from = client_p; char *end; int res; int numeric = 0; struct Message *mptr; struct MsgBuf msgbuf; s_assert(MyConnect(client_p)); s_assert(client_p->localClient->F != NULL); if(IsAnyDead(client_p)) return; end = bufend - 1; /* XXX this should be done before parse() is called */ if(*end == '\n') *end-- = '\0'; if(*end == '\r') *end = '\0'; res = msgbuf_parse(&msgbuf, pbuffer); if (res) { ServerStats.is_empt++; return; } if (msgbuf.origin != NULL && IsServer(client_p)) { from = find_client(msgbuf.origin); /* didnt find any matching client, issue a kill */ if(from == NULL) { ServerStats.is_unpf++; remove_unknown(client_p, msgbuf.origin, pbuffer); return; } /* fake direction, hmm. */ if(from->from != client_p) { ServerStats.is_wrdi++; cancel_clients(client_p, from); return; } } if(IsDigit(*msgbuf.cmd) && IsDigit(*(msgbuf.cmd + 1)) && IsDigit(*(msgbuf.cmd + 2))) { mptr = NULL; numeric = atoi(msgbuf.cmd); ServerStats.is_num++; } else { mptr = rb_dictionary_retrieve(cmd_dict, msgbuf.cmd); /* no command or its encap only, error */ if(!mptr || !mptr->cmd) { if(IsPerson(from)) { sendto_one(from, form_str(ERR_UNKNOWNCOMMAND), me.name, from->name, msgbuf.cmd); } ServerStats.is_unco++; return; } mptr->bytes += msgbuf.parselen; } if(mptr == NULL) { do_numeric(numeric, client_p, from, msgbuf.n_para, msgbuf.para); return; } if(handle_command(mptr, &msgbuf, client_p, from) < -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((p + 8) > 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]); } } }
/* * handle_command * * inputs - pointer to message block * - pointer to client * - pointer to client message is from * - count of number of args * - pointer to argv[] array * output - -1 if error from server * side effects - */ static int handle_command(struct Message *mptr, struct Client *client_p, struct Client *from, int i, const char** hpara) { struct MessageEntry ehandler; MessageHandler handler = 0; if(IsAnyDead(client_p)) return -1; if(IsServer(client_p)) mptr->rcount++; mptr->count++; /* New patch to avoid server flooding from unregistered connects - Pie-Man 07/27/2000 */ if(!IsRegistered(client_p)) { /* if its from a possible server connection * ignore it.. more than likely its a header thats sneaked through */ if(IsAnyServer(client_p) && !(mptr->flags & MFLG_UNREG)) return (1); } ehandler = mptr->handlers[from->handler]; handler = ehandler.handler; /* check right amount of params is passed... --is */ if(i < ehandler.min_para || (ehandler.min_para && EmptyString(hpara[ehandler.min_para - 1]))) { if(!IsServer(client_p)) { sendto_one(client_p, form_str(ERR_NEEDMOREPARAMS), me.name, EmptyString(client_p->name) ? "*" : client_p->name, mptr->cmd); if(MyClient(client_p)) return (1); else return (-1); } sendto_realops_flags(UMODE_ALL, L_ALL, "Dropping server %s due to (invalid) command '%s'" " with only %d arguments (expecting %d).", client_p->name, mptr->cmd, i, ehandler.min_para); ilog(L_SERVER, "Insufficient parameters (%d) for command '%s' from %s.", i, mptr->cmd, client_p->name); exit_client(client_p, client_p, client_p, "Not enough arguments to server command."); return (-1); } (*handler) (client_p, from, i, hpara); return (1); }
/* 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]); } } }