/* ** mo_info ** parv[0] = sender prefix ** parv[1] = servername */ static int mo_info(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { if(hunt_server(client_p, source_p, ":%s INFO :%s", 1, parc, parv) == HUNTED_ISME) { info_spy(source_p); SetCork(source_p); send_info_text(source_p); if(IsOper(source_p)) { send_conf_options(source_p); sendto_one_numeric(source_p, RPL_INFO, ":%s", rb_lib_version()); } send_birthdate_online_time(source_p); ClearCork(source_p); sendto_one_numeric(source_p, RPL_ENDOFINFO, form_str(RPL_ENDOFINFO)); } return 0; }
/* ** m_info ** parv[0] = sender prefix ** parv[1] = servername */ static int m_info(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { static time_t last_used = 0L; static int count; if (!check_limit(source_p, &last_used, &count, "INFO")) { sendto_one_numeric(source_p, RPL_ENDOFINFO, form_str(RPL_ENDOFINFO)); return 0; } if(hunt_server(client_p, source_p, ":%s INFO :%s", 1, parc, parv) != HUNTED_ISME) return 0; info_spy(source_p); SetCork(source_p); send_info_text(source_p); send_birthdate_online_time(source_p); ClearCork(source_p); sendto_one_numeric(source_p, RPL_ENDOFINFO, form_str(RPL_ENDOFINFO)); return 0; }
/* * inputs - flag privmsg or notice * - pointer to command "PRIVMSG" or "NOTICE" * - pointer to source_p * - pointer to channel */ static void m_message(int p_or_n, const char *command, struct Client *source_p, int parc, char *parv[]) { if (parc < 2 || EmptyString(parv[1])) { if (p_or_n != NOTICE) sendto_one_numeric(source_p, &me, ERR_NORECIPIENT, command); return; } if (parc < 3 || EmptyString(parv[2])) { if (p_or_n != NOTICE) sendto_one_numeric(source_p, &me, ERR_NOTEXTTOSEND); return; } /* Finish the flood grace period... */ if (MyClient(source_p) && !IsFloodDone(source_p)) flood_endgrace(source_p); if (build_target_list(p_or_n, command, source_p, parv[1], parv[2]) < 0) return; for (unsigned int i = 0; i < ntargets; ++i) { switch (targets[i].type) { case ENTITY_CLIENT: msg_client(p_or_n, command, source_p, targets[i].ptr, parv[2]); break; case ENTITY_CHANNEL: msg_channel(p_or_n, command, source_p, targets[i].ptr, targets[i].flags, parv[2]); break; } } }
static int ms_tmode(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Channel *chptr = NULL; struct membership *msptr; /* Now, try to find the channel in question */ if(!IsChanPrefix(parv[2][0]) || !check_channel_name(parv[2])) { sendto_one_numeric(source_p, ERR_BADCHANNAME, form_str(ERR_BADCHANNAME), parv[2]); return 0; } chptr = find_channel(parv[2]); if(chptr == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), parv[2]); return 0; } /* TS is higher, drop it. */ if(atol(parv[1]) > chptr->channelts) return 0; if(IsServer(source_p)) { set_channel_mode(client_p, source_p, chptr, NULL, parc - 3, parv + 3); } else { msptr = find_channel_membership(chptr, source_p); set_channel_mode(client_p, source_p, chptr, msptr, parc - 3, parv + 3); } return 0; }
/*! \brief VERSION command handler * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = command * - parv[1] = nickname/servername */ static int m_version(struct Client *source_p, int parc, char *parv[]) { static time_t last_used = 0; if ((last_used + ConfigGeneral.pace_wait_simple) > CurrentTime) { sendto_one_numeric(source_p, &me, RPL_LOAD2HI, "VERSION"); return 0; } last_used = CurrentTime; if (!ConfigServerHide.disable_remote_commands) if (hunt_server(source_p, ":%s VERSION :%s", 1, parc, parv) != HUNTED_ISME) return 0; sendto_one_numeric(source_p, &me, RPL_VERSION, ircd_version, serno, me.name, serveropts); isupport_show(source_p); return 0; }
/* * mo_version - VERSION command handler * parv[1] = remote server */ static int mo_version(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { if(hunt_server(client_p, source_p, ":%s VERSION :%s", 1, parc, parv) == HUNTED_ISME) { sendto_one_numeric(source_p, RPL_VERSION, form_str(RPL_VERSION), ircd_version, serno, me.name, confopts(source_p), TS_CURRENT, ServerInfo.sid); show_isupport(source_p); } return 0; }
/*! \brief LOCOPS command handler * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = command * - parv[1] = message text */ static int mo_locops(struct Client *source_p, int parc, char *parv[]) { const char *const message = parv[1]; if (!HasOFlag(source_p, OPER_FLAG_LOCOPS)) { sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "locops"); return 0; } if (EmptyString(message)) { sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "LOCOPS"); return 0; } sendto_realops_flags(UMODE_LOCOPS, L_ALL, SEND_LOCOPS, "from %s: %s", source_p->name, message); cluster_distribute(source_p, "LOCOPS", 0, CLUSTER_LOCOPS, message); return 0; }
/* * m_time * parv[1] = servername */ static int m_time(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { /* this is not rate limited, so end the grace period */ if(MyClient(source_p) && !IsFloodDone(source_p)) flood_endgrace(source_p); if(hunt_server(client_p, source_p, ":%s TIME :%s", 1, parc, parv) == HUNTED_ISME) sendto_one_numeric(source_p, RPL_TIME, form_str(RPL_TIME), me.name, date()); return 0; }
/*! \brief WALLOPS command handler * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = command * - parv[1] = message text */ static int mo_wallops(struct Client *source_p, int parc, char *parv[]) { const char *message = parv[1]; if (!HasOFlag(source_p, OPER_FLAG_WALLOPS)) { sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "wallops"); return 0; } if (EmptyString(message)) { sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "WALLOPS"); return 0; } sendto_wallops_flags(UMODE_WALLOP, source_p, "%s", message); sendto_server(source_p, NOCAPS, NOCAPS, ":%s WALLOPS :%s", source_p->id, message); return 0; }
static void forcepart_channels(struct Client *client_p, struct Client *source_p, struct Client *target_p, const char *channels, const char *reason) { struct Channel *chptr = NULL; struct membership *msptr = NULL; char *name; char *p = NULL; char *chanlist; chanlist = LOCAL_COPY(channels); for(name = rb_strtok_r(chanlist, ",", &p); name; name = rb_strtok_r(NULL, ",", &p)) { if((chptr = find_channel(name)) == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), name); continue; } if((msptr = find_channel_membership(chptr, target_p)) == NULL) { sendto_one_numeric(source_p, ERR_USERNOTINCHANNEL, form_str(ERR_USERNOTINCHANNEL), target_p->name, name); continue; } sendto_server(target_p, chptr, NOCAPS, NOCAPS, ":%s PART %s :%s", use_id(target_p), chptr->chname, reason); sendto_channel_local(ALL_MEMBERS, chptr, ":%s!%s@%s PART %s :%s", target_p->name, target_p->username, target_p->host, chptr->chname, reason); remove_user_from_channel(msptr); } return; }
static void recurse_report_messages(struct Client *source_p, const struct MessageTree *mtree) { if (mtree->msg) sendto_one_numeric(source_p, &me, RPL_STATSCOMMANDS, mtree->msg->cmd, mtree->msg->count, mtree->msg->bytes, mtree->msg->rcount); for (unsigned int i = 0; i < MAXPTRLEN; ++i) if (mtree->pointers[i]) recurse_report_messages(source_p, mtree->pointers[i]); }
static int mr_starttls(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { #ifdef HAVE_LIBCRYPTO ssl_ctl_t *ctl; rb_fde_t *F[2]; if (!MyConnect(client_p)) return 0; if (rb_socketpair(AF_UNIX, SOCK_STREAM, 0, &F[0], &F[1], "STARTTLS ssld session") == -1) { ilog_error("error creating SSL/TLS socketpair for ssld slave"); sendto_one_numeric(client_p, ERR_STARTTLS, form_str(ERR_STARTTLS), "Unable to create SSL/TLS socketpair for ssld offload slave"); return 1; } s_assert(client_p->localClient != NULL); /* clear out any remaining plaintext lines */ rb_linebuf_donebuf(&client_p->localClient->buf_recvq); sendto_one_numeric(client_p, RPL_STARTTLS, form_str(RPL_STARTTLS)); send_queued(client_p); ctl = start_ssld_accept(client_p->localClient->F, F[1], rb_get_fd(F[0])); if (ctl != NULL) { client_p->localClient->F = F[0]; client_p->localClient->ssl_ctl = ctl; SetSSL(client_p); } else return 1; #endif return 0; }
static int me_dehelper(struct Client *client_p, struct Client *source_p, int parc, const char **parv) { struct Client *target_p = find_person(parv[1]); if(!target_p) { sendto_one_numeric(source_p, ERR_NOSUCHNICK, form_str(ERR_NOSUCHNICK), me.name, parv[1]); return 0; } if(!MyClient(target_p)) return 0; do_dehelper(source_p, target_p); return 0; }
/*! \brief GLOBOPS command handler * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = command * - parv[1] = message text */ static int mo_globops(struct Client *source_p, int parc, char *parv[]) { const char *const message = parv[1]; if (!HasOFlag(source_p, OPER_FLAG_GLOBOPS)) { sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "globops"); return 0; } if (EmptyString(message)) { sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "GLOBOPS"); return 0; } sendto_server(source_p, 0, 0, ":%s GLOBOPS :%s", source_p->id, message); sendto_realops_flags(UMODE_ALL, L_ALL, SEND_GLOBAL, "from %s: %s", source_p->name, message); return 0; }
/* ** m_motd ** parv[0] = sender prefix ** parv[1] = servername */ static int m_motd(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { static time_t last_used = 0; if((last_used + ConfigFileEntry.pace_wait) > rb_current_time()) { /* safe enough to give this on a local connect only */ sendto_one_numeric(source_p, s_RPL(RPL_LOAD2HI), "MOTD"); sendto_one_numeric(source_p, s_RPL(RPL_ENDOFMOTD)); return 0; } else last_used = rb_current_time(); if(hunt_server(client_p, source_p, ":%s MOTD :%s", 1, parc, parv) != HUNTED_ISME) return 0; motd_spy(source_p); send_user_motd(source_p); return 0; }
/*! \brief TIME command handler * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = command * - parv[1] = nickname/servername */ static int m_time(struct Client *source_p, int parc, char *parv[]) { /* This is not rate limited, so end the grace period */ if (!IsFloodDone(source_p)) flood_endgrace(source_p); /* This is safe enough to use during non hidden server mode */ if (!ConfigServerHide.disable_remote_commands) if (hunt_server(source_p, ":%s TIME :%s", 1, parc, parv) != HUNTED_ISME) return 0; sendto_one_numeric(source_p, &me, RPL_TIME, me.name, date(0)); return 0; }
/* * void show_events(struct Client *source_p) * * Input: Client requesting the event * Output: List of events * Side Effects: None */ void show_events(struct Client *source_p) { int i; if(last_event_ran) sendto_one_numeric(source_p, RPL_STATSDEBUG, "E :Last event to run: %s", last_event_ran); sendto_one_numeric(source_p, RPL_STATSDEBUG, "E :Operation Next Execution"); for (i = 0; i < MAX_EVENTS; i++) { if(event_table[i].active) { sendto_one_numeric(source_p, RPL_STATSDEBUG, "E :%-28s %-4d seconds", event_table[i].name, (int)(event_table[i].when - CurrentTime)); } } }
/*! \brief WHOWAS command handler * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = command * - parv[1] = nickname * - parv[2] = count * - parv[3] = nickname/servername */ static int ms_whowas(struct Client *source_p, int parc, char *parv[]) { if (parc < 2 || EmptyString(parv[1])) { sendto_one_numeric(source_p, &me, ERR_NONICKNAMEGIVEN); return 0; } if (hunt_server(source_p, ":%s WHOWAS %s %s :%s", 3, parc, parv) != HUNTED_ISME) return 0; do_whowas(source_p, parc, parv); return 0; }
static void sendhelpfile(struct Client *source_p, const char *path, const char *topic) { FILE *file = NULL; char *p = NULL; char line[HELPLEN] = ""; if ((file = fopen(path, "r")) == NULL) { sendto_one_numeric(source_p, &me, ERR_HELPNOTFOUND, topic); return; } if (fgets(line, sizeof(line), file) == NULL) { sendto_one_numeric(source_p, &me, ERR_HELPNOTFOUND, topic); fclose(file); return; } if ((p = strpbrk(line, "\r\n"))) *p = '\0'; sendto_one_numeric(source_p, &me, RPL_HELPSTART, topic, line); while (fgets(line, sizeof(line), file)) { if ((p = strpbrk(line, "\r\n"))) *p = '\0'; sendto_one_numeric(source_p, &me, RPL_HELPTXT, topic, line); } fclose(file); sendto_one_numeric(source_p, &me, RPL_ENDOFHELP, topic); }
/* * show_ports - send port listing to a client * inputs - pointer to client to show ports to * output - none * side effects - show ports */ void show_ports(struct Client *source_p) { struct Listener *listener = 0; for (listener = ListenerPollList; listener; listener = listener->next) { sendto_one_numeric(source_p, RPL_STATSPLINE, form_str(RPL_STATSPLINE), 'P', get_listener_port(listener), IsOperAdmin(source_p) ? listener->name : me.name, listener->ref_count, (listener->active) ? "active" : "disabled", listener->ssl ? " ssl" : ""); } }
/* * fd_dump() - dump the list of active filedescriptors */ void fd_dump(struct Client *source_p) { int i; for (i = 0; i <= highest_fd; i++) { if(!fd_table[i].flags.open) continue; sendto_one_numeric(source_p, RPL_STATSDEBUG, "F :fd %-3d desc '%s'", i, fd_table[i].desc); } }
static void distribute_hostchange(struct Client *client) { if (irccmp(client->host, client->orighost)) sendto_one_numeric(client, RPL_HOSTHIDDEN, "%s :is now your hidden host", client->host); else sendto_one_numeric(client, RPL_HOSTHIDDEN, "%s :hostname reset", client->host); sendto_server(NULL, NULL, CAP_EUID | CAP_TS6, NOCAPS, ":%s CHGHOST %s :%s", use_id(&me), use_id(client), client->host); sendto_server(NULL, NULL, CAP_TS6, CAP_EUID, ":%s ENCAP * CHGHOST %s :%s", use_id(&me), use_id(client), client->host); sendto_server(NULL, NULL, NOCAPS, CAP_TS6, ":%s ENCAP * CHGHOST %s :%s", me.name, client->name, client->host); if (irccmp(client->host, client->orighost)) SetDynSpoof(client); else ClearDynSpoof(client); }
static void chm_nonotice_process(hook_data_privmsg_channel *data) { /* don't waste CPU if message is already blocked */ if (data->approved || data->msgtype != MESSAGE_TYPE_NOTICE) return; /* block all notices except CTCPs; use chm_noctcp to block CTCPs. */ if (data->chptr->mode.mode & mode_nonotice && *data->text != '\001') { sendto_one_numeric(data->source_p, ERR_CANNOTSENDTOCHAN, form_str(ERR_CANNOTSENDTOCHAN), data->chptr->chname); data->approved = ERR_CANNOTSENDTOCHAN; return; } }
/*! \brief HELP command handler * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = command * - parv[1] = help topic */ static int m_help(struct Client *source_p, int parc, char *parv[]) { static uintmax_t last_used = 0; if ((last_used + ConfigGeneral.pace_wait_simple) > CurrentTime) { sendto_one_numeric(source_p, &me, RPL_LOAD2HI, "HELP"); return 0; } last_used = CurrentTime; do_help(source_p, parv[1]); return 0; }
/*! \brief PART command handler * * \param source_p Pointer to allocated Client struct from which the message * originally comes from. This can be a local or remote client. * \param parc Integer holding the number of supplied arguments. * \param parv Argument vector where parv[0] .. parv[parc-1] are non-NULL * pointers. * \note Valid arguments for this command are: * - parv[0] = command * - parv[1] = channel name * - parv[2] = part message */ static int m_part(struct Client *source_p, int parc, char *parv[]) { if (EmptyString(parv[1])) { sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "PART"); return 0; } /* Finish the flood grace period... */ if (MyClient(source_p) && !IsFloodDone(source_p)) flood_endgrace(source_p); channel_do_part(source_p, parv[1], parv[2]); return 0; }
static int m_cap(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct clicap_cmd *cmd; if(!(cmd = bsearch(parv[1], clicap_cmdlist, sizeof(clicap_cmdlist) / sizeof(struct clicap_cmd), sizeof(struct clicap_cmd), (bqcmp) clicap_cmd_search))) { sendto_one_numeric(source_p, s_RPL(ERR_INVALIDCAPCMD), parv[1]); return 0; } (cmd->func) (source_p, parv[2]); return 0; }
static int ms_pong(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Client *target_p; const char *destination; destination = parv[2]; source_p->flags &= ~FLAGS_PINGSENT; /* Now attempt to route the PONG, comstud pointed out routable PING * is used for SPING. routable PING should also probably be left in * -Dianora * That being the case, we will route, but only for registered clients (a * case can be made to allow them only from servers). -Shadowfax */ if(!EmptyString(destination) && !match(destination, me.name) && irccmp(destination, me.id)) { if((target_p = find_client(destination)) || (target_p = find_server(NULL, destination))) sendto_one(target_p, ":%s PONG %s %s", get_id(source_p, target_p), parv[1], get_id(target_p, target_p)); else { if(!IsDigit(*destination)) sendto_one_numeric(source_p, ERR_NOSUCHSERVER, form_str(ERR_NOSUCHSERVER), destination); return 0; } } /* destination is us, emulate EOB */ if(IsServer(source_p) && !HasSentEob(source_p)) { if(MyConnect(source_p)) sendto_realops_snomask(SNO_GENERAL, L_ALL, "End of burst (emulated) from %s (%d seconds)", source_p->name, (signed int) (CurrentTime - source_p->localClient->firsttime)); SetEob(source_p); eob_count++; call_hook(h_server_eob, source_p); } return 0; }
static void do_whowas(struct Client *source_p, const int parc, char *parv[]) { int cur = 0; int max = -1; const dlink_node *node = NULL; if (parc > 2 && !EmptyString(parv[2])) max = atoi(parv[2]); if (!MyConnect(source_p) && (max <= 0 || max > WHOWAS_MAX_REPLIES)) max = WHOWAS_MAX_REPLIES; DLINK_FOREACH(node, whowas_get_hash(strhash(parv[1]))->head) { const struct Whowas *whowas = node->data; if (!irccmp(parv[1], whowas->name)) { sendto_one_numeric(source_p, &me, RPL_WHOWASUSER, whowas->name, whowas->username, whowas->hostname, whowas->realname); if (HasUMode(source_p, UMODE_OPER)) sendto_one_numeric(source_p, &me, RPL_WHOISACTUALLY, whowas->name, whowas->username, whowas->hostname, whowas->sockhost); if (strcmp(whowas->account, "*")) sendto_one_numeric(source_p, &me, RPL_WHOISACCOUNT, whowas->name, whowas->account, "was"); if ((whowas->shide || ConfigServerHide.hide_servers) && !HasUMode(source_p, UMODE_OPER)) sendto_one_numeric(source_p, &me, RPL_WHOISSERVER, whowas->name, ConfigServerInfo.network_name, date_ctime(whowas->logoff)); else sendto_one_numeric(source_p, &me, RPL_WHOISSERVER, whowas->name, whowas->servername, date_ctime(whowas->logoff)); ++cur; } if (max > 0 && cur >= max) break; } if (!cur) sendto_one_numeric(source_p, &me, ERR_WASNOSUCHNICK, parv[1]); sendto_one_numeric(source_p, &me, RPL_ENDOFWHOWAS, parv[1]); }
static int ms_mode(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { struct Channel *chptr; chptr = find_channel(parv[1]); if(chptr == NULL) { sendto_one_numeric(source_p, ERR_NOSUCHCHANNEL, form_str(ERR_NOSUCHCHANNEL), parv[1]); return 0; } set_channel_mode(client_p, source_p, chptr, NULL, parc - 2, parv + 2); return 0; }
/* 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 void parse_handle_command(struct Message *message, struct Client *source_p, unsigned int i, char *para[]) { if (IsServer(source_p->from)) ++message->rcount; ++message->count; if (MyClient(source_p) && (message->flags & MFLG_ENDGRACE)) flood_endgrace(source_p); /* Check right amount of parameters is passed... --is */ if (i < message->args_min) sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, message->cmd); else message->handlers[source_p->from->handler](source_p, i, para); }