/*! \brief REHASH 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] = option [CONF, DNS, MOTD] * or for remote REHASH: * - parv[0] = command * - parv[1] = target server mask * - parv[2] = option [CONF, DNS, MOTD] */ static int mo_rehash(struct Client *source_p, int parc, char *parv[]) { const char *option = NULL; const char *server = NULL; if (EmptyString(parv[parc - 1])) { sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "REHASH"); return 0; } if (parc < 3) { if (!HasOFlag(source_p, OPER_FLAG_REHASH)) { sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "rehash"); return 0; } option = parv[1]; } else { if (!HasOFlag(source_p, OPER_FLAG_REHASH_REMOTE)) { sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "rehash:remote"); return 0; } server = parv[1]; option = parv[2]; } for (const struct RehashStruct *tab = rehash_cmd_table; tab->handler; ++tab) { if (irccmp(tab->option, option)) continue; if (!EmptyString(server)) sendto_match_servs(source_p, server, 0, "REHASH %s %s", server, option); if (EmptyString(server) || match(server, me.name)) tab->handler(source_p); return 0; } sendto_one_notice(source_p, &me, ":%s is not a valid option. " "Choose from CONF, DNS, MOTD", option); return 0; }
/*! \brief RESTART 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] = server name */ static int mo_restart(struct Client *source_p, int parc, char *parv[]) { char buf[IRCD_BUFSIZE] = ""; const char *const name = parv[1]; if (!HasOFlag(source_p, OPER_FLAG_RESTART)) { sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "restart"); return 0; } if (EmptyString(name)) { sendto_one_notice(source_p, &me, ":Need server name /restart %s", me.name); return 0; } if (irccmp(name, me.name)) { sendto_one_notice(source_p, &me, ":Mismatch on /restart %s", me.name); return 0; } snprintf(buf, sizeof(buf), "received RESTART command from %s", get_client_name(source_p, HIDE_IP)); server_die(buf, 1); return 0; }
/*! \brief UNRESV 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/nick * - parv[2] = "ON" * - parv[3] = target server */ static int mo_unresv(struct Client *source_p, int parc, char *parv[]) { char *resv = NULL; char *reason = NULL; char *target_server = NULL; if (!HasOFlag(source_p, OPER_FLAG_UNRESV)) { sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "unresv"); return 0; } if (!parse_aline("UNRESV", source_p, parc, parv, 0, &resv, NULL, NULL, &target_server, &reason)) return 0; if (target_server) { sendto_match_servs(source_p, target_server, CAPAB_CLUSTER, "UNRESV %s %s", target_server, resv); /* Allow ON to apply local unresv as well if it matches */ if (match(target_server, me.name)) return 0; } else cluster_a_line(source_p, "UNRESV", CAPAB_KLN, SHARED_UNRESV, resv); resv_remove(source_p, resv); return 0; }
/*! \brief DIE 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] = server name */ static int mo_die(struct Client *source_p, int parc, char *parv[]) { char buf[IRCD_BUFSIZE] = ""; if (!HasOFlag(source_p, OPER_FLAG_DIE)) { sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "die"); return 0; } if (parc < 2 || EmptyString(parv[1])) { sendto_one_notice(source_p, &me, ":Need server name /die %s", me.name); return 0; } if (irccmp(parv[1], me.name)) { sendto_one_notice(source_p, &me, ":Mismatch on /die %s", me.name); return 0; } snprintf(buf, sizeof(buf), "received DIE command from %s", get_client_name(source_p, HIDE_IP)); server_die(buf, 0); return 0; }
/* * mo_wallops (write to *all* opers currently online) * parv[0] = sender prefix * parv[1] = message text */ static void mo_wallops(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { const char *message = parv[1]; if (!HasOFlag(source_p, OPER_FLAG_WALLOPS)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "wallops"); return; } if (EmptyString(message)) { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "WALLOPS"); return; } sendto_wallops_flags(UMODE_OPERWALL, source_p, "OPERWALL - %s", message); sendto_server(NULL, CAP_TS6, NOCAPS, ":%s WALLOPS :%s", ID(source_p), message); sendto_server(NULL, NOCAPS, CAP_TS6, ":%s WALLOPS :%s", source_p->name, message); }
/* ** m_undline ** added May 28th 2000 by Toby Verrall <*****@*****.**> ** based totally on m_unkline ** added to hybrid-7 7/11/2000 --is ** ** parv[0] = sender nick ** parv[1] = dline to remove */ static void mo_undline(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char *addr = NULL, *user = NULL; char *target_server = NULL; if (!HasOFlag(source_p, OPER_FLAG_UNDLINE)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "undline"); return; } if (parc < 2 || EmptyString(parv[1])) { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "UNDLINE"); return; } if (parse_aline("UNDLINE", source_p, parc, parv, 0, &user, &addr, NULL, &target_server, NULL) < 0) return; if (target_server != NULL) { sendto_match_servs(source_p, target_server, CAP_UNDLN, "UNDLINE %s %s", target_server, addr); /* Allow ON to apply local unkline as well if it matches */ if (match(target_server, me.name)) return; } else cluster_a_line(source_p, "UNDLINE", CAP_UNDLN, SHARED_UNDLINE, "%s", addr); if (remove_dline_match(addr)) { sendto_one(source_p, ":%s NOTICE %s :D-Line for [%s] is removed", me.name, source_p->name, addr); sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE, "%s has removed the D-Line for: [%s]", get_oper_name(source_p), addr); ilog(LOG_TYPE_DLINE, "%s removed D-Line for [%s]", get_oper_name(source_p), addr); } else sendto_one(source_p, ":%s NOTICE %s :No D-Line for [%s] found", me.name, source_p->name, addr); }
/*! \brief REHASH 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] = additional option */ static int mo_rehash(struct Client *source_p, int parc, char *parv[]) { int found = 0; const char *const option = parv[1]; if (!HasOFlag(source_p, OPER_FLAG_REHASH)) { sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "rehash"); return 0; } if (!EmptyString(option)) { if (!irccmp(option, "DNS")) { sendto_one_numeric(source_p, &me, RPL_REHASHING, "DNS"); sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE, "%s is rehashing DNS", get_oper_name(source_p)); restart_resolver(); found = 1; } else if (!irccmp(option, "MOTD")) { sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE, "%s is forcing re-reading of MOTD files", get_oper_name(source_p)); motd_recache(); found = 1; } if (found) ilog(LOG_TYPE_IRCD, "REHASH %s From %s", option, get_oper_name(source_p)); else sendto_one_notice(source_p, &me, ":%s is not a valid option. " "Choose from DNS, MOTD", option); } else { sendto_one_numeric(source_p, &me, RPL_REHASHING, ConfigGeneral.configfile); sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE, "%s is rehashing configuration file(s)", get_oper_name(source_p)); ilog(LOG_TYPE_IRCD, "REHASH From %s", get_oper_name(source_p)); conf_rehash(0); } return 0; }
/*! \brief UNKLINE 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] = user\@host mask * - parv[2] = "ON" * - parv[3] = target server */ static int mo_unkline(struct Client *source_p, int parc, char *parv[]) { char *target_server = NULL; char *user, *host; if (!HasOFlag(source_p, OPER_FLAG_UNKLINE)) { sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "unkline"); return 0; } if (EmptyString(parv[1])) { sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "UNKLINE"); return 0; } if (parse_aline("UNKLINE", source_p, parc, parv, 0, &user, &host, NULL, &target_server, NULL) < 0) return 0; if (target_server) { sendto_match_servs(source_p, target_server, CAP_UNKLN, "UNKLINE %s %s %s", target_server, user, host); /* Allow ON to apply local unkline as well if it matches */ if (match(target_server, me.name)) return 0; } else cluster_a_line(source_p, "UNKLINE", CAP_UNKLN, SHARED_UNKLINE, "%s %s", user, host); if (remove_kline_match(host, user)) { sendto_one_notice(source_p, &me, ":K-Line for [%s@%s] is removed", user, host); sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE, "%s has removed the K-Line for: [%s@%s]", get_oper_name(source_p), user, host); ilog(LOG_TYPE_KLINE, "%s removed K-Line for [%s@%s]", get_oper_name(source_p), user, host); } else sendto_one_notice(source_p, &me, ":No K-Line for [%s@%s] found", user, host); return 0; }
/*! \brief Blindly opers up given source_p, using conf info. * All checks on passwords have already been done. * \param source_p Pointer to given client to oper * \param conf operator {} configuration record */ static void oper_up(struct Client *source_p, const struct MaskItem *conf) { const unsigned int old = source_p->umodes; ++Count.oper; SetOper(source_p); if (conf->modes) AddUMode(source_p, conf->modes); else if (ConfigGeneral.oper_umodes) AddUMode(source_p, ConfigGeneral.oper_umodes); if (!(old & UMODE_INVISIBLE) && HasUMode(source_p, UMODE_INVISIBLE)) ++Count.invisi; else if ((old & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE)) --Count.invisi; assert(dlinkFind(&oper_list, source_p) == NULL); dlinkAdd(source_p, make_dlink_node(), &oper_list); AddOFlag(source_p, conf->port); if (HasOFlag(source_p, OPER_FLAG_ADMIN)) AddUMode(source_p, UMODE_ADMIN); if (!EmptyString(conf->whois)) { svstag_attach(&source_p->svstags, RPL_WHOISOPERATOR, "+", conf->whois); sendto_server(NULL, 0, 0, ":%s SVSTAG %s %ju %u + :%s", me.id, source_p->id, source_p->tsinfo, RPL_WHOISOPERATOR, conf->whois); } ilog(LOG_TYPE_OPER, "OPER %s by %s!%s@%s", conf->name, source_p->name, source_p->username, source_p->host); sendto_realops_flags(UMODE_SERVNOTICE, L_ALL, SEND_NOTICE, "%s is now an operator", get_oper_name(source_p)); sendto_server(NULL, 0, 0, ":%s GLOBOPS :%s is now an operator", me.id, get_oper_name(source_p)); send_umode_out(source_p, old); sendto_one_numeric(source_p, &me, RPL_YOUREOPER); }
/*! \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; }
/*! \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 *const 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, 0, 0, ":%s WALLOPS :%s", source_p->id, message); 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; }
/* set_user_mode() * * added 15/10/91 By Darren Reed. * parv[0] - command * parv[1] - username to change mode for * parv[2] - modes to change */ static void set_user_mode(struct Client *source_p, const int parc, char *parv[]) { const struct user_modes *tab = NULL; const unsigned int setmodes = source_p->umodes; const struct Client *target_p = NULL; int what = MODE_ADD, badmode = 0; if ((target_p = find_person(source_p, parv[1])) == NULL) { if (MyConnect(source_p)) sendto_one_numeric(source_p, &me, ERR_NOSUCHCHANNEL, parv[1]); return; } if (source_p != target_p) { sendto_one_numeric(source_p, &me, ERR_USERSDONTMATCH); return; } if (parc < 3) { char buf[IRCD_BUFSIZE] = ""; char *m = buf; *m++ = '+'; for (tab = umode_tab; tab->c; ++tab) if (HasUMode(source_p, tab->flag)) *m++ = tab->c; *m = '\0'; sendto_one_numeric(source_p, &me, RPL_UMODEIS, buf); return; } /* Parse user mode change string */ for (const char *m = parv[2]; *m; ++m) { switch (*m) { case '+': what = MODE_ADD; break; case '-': what = MODE_DEL; break; case 'o': if (what == MODE_ADD) { if (!MyConnect(source_p) && !HasUMode(source_p, UMODE_OPER)) { ++Count.oper; SetOper(source_p); } } else { if (!HasUMode(source_p, UMODE_OPER)) break; ClearOper(source_p); --Count.oper; if (MyConnect(source_p)) { dlink_node *node = NULL; detach_conf(source_p, CONF_OPER); ClrOFlag(source_p); DelUMode(source_p, ConfigGeneral.oper_only_umodes); if ((node = dlinkFindDelete(&oper_list, source_p))) free_dlink_node(node); } } break; case 'S': /* Only servers may set +S in a burst */ case 'W': /* Only servers may set +W in a burst */ case 'r': /* Only services may set +r */ case 'x': /* Only services may set +x */ break; default: if ((tab = umode_map[(unsigned char)*m])) { if (MyConnect(source_p) && !HasUMode(source_p, UMODE_OPER) && (ConfigGeneral.oper_only_umodes & tab->flag)) badmode = 1; else { if (what == MODE_ADD) AddUMode(source_p, tab->flag); else DelUMode(source_p, tab->flag); } } else if (MyConnect(source_p)) badmode = 1; break; } } if (badmode) sendto_one_numeric(source_p, &me, ERR_UMODEUNKNOWNFLAG); if (MyConnect(source_p) && HasUMode(source_p, UMODE_ADMIN) && !HasOFlag(source_p, OPER_FLAG_ADMIN)) { sendto_one_notice(source_p, &me, ":*** You have no admin flag;"); DelUMode(source_p, UMODE_ADMIN); } if (!(setmodes & UMODE_INVISIBLE) && HasUMode(source_p, UMODE_INVISIBLE)) ++Count.invisi; if ((setmodes & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE)) --Count.invisi; /* * Compare new modes with old modes and send string which will cause * servers to update correctly. */ send_umode_out(source_p, setmodes); }
/*! \brief UNXLINE 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] = gecos * - parv[2] = "ON" * - parv[3] = target server */ static int mo_unxline(struct Client *source_p, int parc, char *parv[]) { struct aline_ctx aline = { .add = false, .simple_mask = true }; if (!HasOFlag(source_p, OPER_FLAG_UNXLINE)) { sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "unxline"); return 0; } if (parse_aline("UNXLINE", source_p, parc, parv, &aline) == false) return 0; if (aline.server) { sendto_match_servs(source_p, aline.server, CAPAB_CLUSTER, "UNXLINE %s %s", aline.server, aline.mask); /* Allow ON to apply local unxline as well if it matches */ if (match(aline.server, me.name)) return 0; } else cluster_distribute(source_p, "UNXLINE", CAPAB_CLUSTER, CLUSTER_UNXLINE, "%s", aline.host); xline_remove(source_p, &aline); return 0; } /*! \brief UNXLINE 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] = target server mask * - parv[2] = gecos */ static int ms_unxline(struct Client *source_p, int parc, char *parv[]) { struct aline_ctx aline = { .add = false, .simple_mask = true, .mask = parv[2], .server = parv[1] }; if (parc != 3 || EmptyString(parv[parc - 1])) return 0; sendto_match_servs(source_p, aline.server, CAPAB_CLUSTER, "UNXLINE %s %s", aline.server, aline.mask); if (match(aline.server, me.name)) return 0; if (HasFlag(source_p, FLAGS_SERVICE) || shared_find(SHARED_UNXLINE, source_p->servptr->name, source_p->username, source_p->host)) xline_remove(source_p, &aline); return 0; } static struct Message unxline_msgtab = { .cmd = "UNXLINE", .args_min = 2, .args_max = MAXPARA, .handlers[UNREGISTERED_HANDLER] = m_unregistered, .handlers[CLIENT_HANDLER] = m_not_oper, .handlers[SERVER_HANDLER] = ms_unxline, .handlers[ENCAP_HANDLER] = m_ignore, .handlers[OPER_HANDLER] = mo_unxline }; static void module_init(void) { mod_add_cmd(&unxline_msgtab); } static void module_exit(void) { mod_del_cmd(&unxline_msgtab); } struct module module_entry = { .version = "$Revision$", .modinit = module_init, .modexit = module_exit, };
/* mo_dline() * * inputs - pointer to server * - pointer to client * - parameter count * - parameter list * output - * side effects - D line is added * */ static void mo_dline(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char def_reason[] = CONF_NOREASON; char *dlhost = NULL, *reason = NULL; char *target_server = NULL; const char *creason; const struct Client *target_p = NULL; struct irc_ssaddr daddr; struct MaskItem *conf=NULL; time_t tkline_time=0; int bits = 0, aftype = 0, t = 0; const char *current_date = NULL; time_t cur_time; char hostip[HOSTIPLEN + 1]; char buffer[IRCD_BUFSIZE]; if (!HasOFlag(source_p, OPER_FLAG_DLINE)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "dline"); return; } if (parse_aline("DLINE", source_p, parc, parv, AWILD, &dlhost, NULL, &tkline_time, &target_server, &reason) < 0) return; if (target_server != NULL) { if (HasID(source_p)) { sendto_server(NULL, CAP_DLN|CAP_TS6, NOCAPS, ":%s DLINE %s %lu %s :%s", source_p->id, target_server, (unsigned long)tkline_time, dlhost, reason); sendto_server(NULL, CAP_DLN, CAP_TS6, ":%s DLINE %s %lu %s :%s", source_p->name, target_server, (unsigned long)tkline_time, dlhost, reason); } else sendto_server(NULL, CAP_DLN, NOCAPS, ":%s DLINE %s %lu %s :%s", source_p->name, target_server, (unsigned long)tkline_time, dlhost, reason); /* Allow ON to apply local kline as well if it matches */ if (match(target_server, me.name)) return; } else cluster_a_line(source_p, "DLINE", CAP_DLN, SHARED_DLINE, "%d %s :%s", tkline_time, dlhost, reason); if ((t = parse_netmask(dlhost, NULL, &bits)) == HM_HOST) { if ((target_p = find_chasing(client_p, source_p, dlhost, NULL)) == NULL) return; if (!MyConnect(target_p)) { sendto_one(source_p, ":%s NOTICE %s :Can't DLINE nick on another server", me.name, source_p->name); return; } if (IsExemptKline(target_p)) { sendto_one(source_p, ":%s NOTICE %s :%s is E-lined", me.name, source_p->name, target_p->name); return; } getnameinfo((struct sockaddr *)&target_p->localClient->ip, target_p->localClient->ip.ss_len, hostip, sizeof(hostip), NULL, 0, NI_NUMERICHOST); dlhost = hostip; t = parse_netmask(dlhost, NULL, &bits); assert(t == HM_IPV4 || t == HM_IPV6); } if (bits < 8) { sendto_one(source_p, ":%s NOTICE %s :For safety, bitmasks less than 8 require conf access.", me.name, source_p->name); return; } #ifdef IPV6 if (t == HM_IPV6) aftype = AF_INET6; else #endif aftype = AF_INET; parse_netmask(dlhost, &daddr, NULL); if ((conf = find_dline_conf(&daddr, aftype)) != NULL) { creason = conf->reason ? conf->reason : def_reason; if (IsConfExemptKline(conf)) sendto_one(source_p, ":%s NOTICE %s :[%s] is (E)d-lined by [%s] - %s", me.name, source_p->name, dlhost, conf->host, creason); else sendto_one(source_p, ":%s NOTICE %s :[%s] already D-lined by [%s] - %s", me.name, source_p->name, dlhost, conf->host, creason); return; } cur_time = CurrentTime; current_date = smalldate(cur_time); if (!valid_comment(source_p, reason, 1)) return; conf = conf_make(CONF_DLINE); conf->host = xstrdup(dlhost); if (tkline_time != 0) snprintf(buffer, sizeof(buffer), "Temporary D-line %d min. - %s (%s)", (int)(tkline_time/60), reason, current_date); else snprintf(buffer, sizeof(buffer), "%s (%s)", reason, current_date); conf->reason = xstrdup(buffer); apply_dline(source_p, conf, tkline_time); rehashed_klines = 1; }
/* * mo_set - SET command handler * set options while running */ static int mo_set(struct Client *source_p, int parc, char *parv[]) { int n; int newval; const char *strarg = NULL; const char *intarg = NULL; if (!HasOFlag(source_p, OPER_FLAG_SET)) { sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "set"); return 0; } if (parc > 1) { /* * Go through all the commands in set_cmd_table, until one is * matched. */ for (const struct SetStruct *tab = set_cmd_table; tab->handler; ++tab) { if (irccmp(tab->name, parv[1])) continue; /* * Command found; now execute the code */ n = 2; if (tab->wants_char) strarg = parv[n++]; if (tab->wants_int) intarg = parv[n++]; if ((n - 1) > parc) sendto_one_notice(source_p, &me, ":SET %s expects (\"%s%s\") args", tab->name, (tab->wants_char ? "string, " : ""), (tab->wants_int ? "int" : "")); if (parc <= 2) { strarg = NULL; intarg = NULL; } if (tab->wants_int && parc > 2) { if (intarg) { if (!irccmp(intarg, "yes") || !irccmp(intarg, "on")) newval = 1; else if (!irccmp(intarg, "no") || !irccmp(intarg, "off")) newval = 0; else newval = atoi(intarg); } else newval = -1; if (newval < 0) { sendto_one_notice(source_p, &me, ":Value less than 0 illegal for %s", tab->name); return 0; } } else newval = -1; tab->handler(source_p, strarg, newval); return 0; } /* * Code here will be executed when a /QUOTE SET command is not * found within set_cmd_table. */ sendto_one_notice(source_p, &me, ":Variable not found."); return 0; } list_quote_commands(source_p); return 0; }
/*! \brief CONNECT 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] = target server * - parv[2] = port number * - parv[3] = nickname/servername */ static int mo_connect(struct Client *source_p, int parc, char *parv[]) { int port = 0, tmpport = 0; struct MaskItem *conf = NULL; const struct Client *target_p = NULL; if (EmptyString(parv[1])) { sendto_one_numeric(source_p, &me, ERR_NEEDMOREPARAMS, "CONNECT"); return 0; } if (parc > 3) { if (!HasOFlag(source_p, OPER_FLAG_CONNECT_REMOTE)) { sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "connect:remote"); return 0; } if (hunt_server(source_p, ":%s CONNECT %s %s :%s", 3, parc, parv) != HUNTED_ISME) return 0; } else if (!HasOFlag(source_p, OPER_FLAG_CONNECT)) { sendto_one_numeric(source_p, &me, ERR_NOPRIVS, "connect"); return 0; } /* * Try to find the name, then host, if both fail notify ops and bail */ if (!(conf = find_matching_name_conf(CONF_SERVER, parv[1], NULL, NULL, 0)) && !(conf = find_matching_name_conf(CONF_SERVER, NULL, NULL, parv[1], 0))) { sendto_one_notice(source_p, &me, ":Connect: Host %s not listed in configuration file", parv[1]); return 0; } if ((target_p = hash_find_server(conf->name))) { sendto_one_notice(source_p, &me, ":Connect: Server %s already exists from %s.", target_p->name, target_p->from->name); return 0; } /* * Get port number from user, if given. If not specified, * use the default from configuration structure. If missing * from there, then use the precompiled default. */ tmpport = port = conf->port; if (parc > 2 && !EmptyString(parv[2])) { if ((port = atoi(parv[2])) <= 0) { sendto_one_notice(source_p, &me, ":Connect: Illegal port number"); return 0; } } else if (port <= 0 && (port = PORTNUM) <= 0) { sendto_one_notice(source_p, &me, ":Connect: missing port number"); return 0; } if (find_servconn_in_progress(conf->name)) { sendto_one_notice(source_p, &me, ":Connect: a connection to %s " "is already in progress.", conf->name); return 0; } /* * Notify all operators about remote connect requests */ ilog(LOG_TYPE_IRCD, "CONNECT From %s : %s %s", source_p->name, parv[1], parv[2] ? parv[2] : ""); conf->port = port; /* * At this point we should be calling connect_server with a valid * connect{} block and a valid port in the connect{} block */ if (serv_connect(conf, source_p)) { if (!ConfigServerHide.hide_server_ips && HasUMode(source_p, UMODE_ADMIN)) sendto_one_notice(source_p, &me, ":*** Connecting to %s[%s].%d", conf->host, conf->name, conf->port); else sendto_one_notice(source_p, &me, ":*** Connecting to %s.%d", conf->name, conf->port); } else sendto_one_notice(source_p, &me, ":*** Couldn't connect to %s.%d", conf->name, conf->port); /* * Client is either connecting with all the data it needs or has been * destroyed */ conf->port = tmpport; return 0; }
/* mo_dline() * * inputs - pointer to server * - pointer to client * - parameter count * - parameter list * output - * side effects - D line is added * */ static void mo_dline(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { char def_reason[] = CONF_NOREASON; char *dlhost = NULL, *oper_reason = NULL, *reason = NULL; char *target_server = NULL; const char *creason; const struct Client *target_p = NULL; struct sockaddr_storage daddr; struct AccessItem *aconf = NULL; time_t tkline_time = 0; int bits, t; char hostip[HOSTIPLEN + 1]; if (!HasOFlag(source_p, OPER_FLAG_DLINE)) { sendto_one(source_p, form_str(ERR_NOPRIVS), me.name, source_p->name, "dline"); return; } if (parse_aline("DLINE", source_p, parc, parv, AWILD, &dlhost, NULL, &tkline_time, &target_server, &reason) < 0) return; if (target_server != NULL) { if (HasID(source_p)) { sendto_server(NULL, CAP_DLN | CAP_TS6, NOCAPS, ":%s DLINE %s %lu %s :%s", source_p->id, target_server, (unsigned long)tkline_time, dlhost, reason); sendto_server(NULL, CAP_DLN, CAP_TS6, ":%s DLINE %s %lu %s :%s", source_p->name, target_server, (unsigned long)tkline_time, dlhost, reason); } else sendto_server(NULL, CAP_DLN, NOCAPS, ":%s DLINE %s %lu %s :%s", source_p->name, target_server, (unsigned long)tkline_time, dlhost, reason); /* Allow ON to apply local kline as well if it matches */ if (!match(target_server, me.name)) return; } else cluster_a_line(source_p, "DLINE", CAP_DLN, SHARED_DLINE, "%d %s :%s", tkline_time, dlhost, reason); if ((t = parse_netmask(dlhost, NULL, &bits)) == HM_HOST) { if ((target_p = find_chasing(client_p, source_p, dlhost, NULL)) == NULL) return; if (!MyConnect(target_p)) { sendto_one(source_p, ":%s NOTICE %s :Can't DLINE nick on another server", me.name, source_p->name); return; } if (IsExemptKline(target_p)) { sendto_one(source_p, ":%s NOTICE %s :%s is E-lined", me.name, source_p->name, target_p->name); return; } ip_to_string(&target_p->ip, hostip, sizeof(hostip)); dlhost = hostip; t = parse_netmask(dlhost, NULL, &bits); assert(t == HM_IPV4 || t == HM_IPV6); } if (bits < 8) { sendto_one(source_p, ":%s NOTICE %s :For safety, bitmasks less than 8 require conf access.", me.name, source_p->name); return; } if (t == HM_IPV6) t = AF_INET6; else t = AF_INET; parse_netmask(dlhost, &daddr, NULL); if ((aconf = find_dline_conf(&daddr, t)) != NULL) { creason = aconf->reason ? aconf->reason : def_reason; if (IsConfExemptKline(aconf)) sendto_one(source_p, ":%s NOTICE %s :[%s] is (E)d-lined by [%s] - %s", me.name, source_p->name, dlhost, aconf->host, creason); else sendto_one(source_p, ":%s NOTICE %s :[%s] already D-lined by [%s] - %s", me.name, source_p->name, dlhost, aconf->host, creason); return; } /* Look for an oper reason */ if ((oper_reason = strchr(reason, '|')) != NULL) * oper_reason++ = '\0'; if (!valid_comment(source_p, reason, 1)) return; apply_conf_ban(source_p, DLINE_TYPE, NULL, dlhost, reason, oper_reason, tkline_time); }
/*! \brief NICK 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 */ static int m_nick(struct Client *source_p, int parc, char *parv[]) { char nick[NICKLEN + 1] = ""; struct Client *target_p = NULL; struct MaskItem *conf = NULL; assert(MyClient(source_p)); if (parc < 2 || EmptyString(parv[1])) { sendto_one_numeric(source_p, &me, ERR_NONICKNAMEGIVEN); return 0; } /* Mark end of grace period, to prevent nickflooding */ if (!IsFloodDone(source_p)) flood_endgrace(source_p); /* Terminate nick to NICKLEN */ strlcpy(nick, parv[1], IRCD_MIN(sizeof(nick), ConfigServerInfo.max_nick_length + 1)); /* Check the nickname is ok */ if (!valid_nickname(nick, 1)) { sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, nick, "Erroneous Nickname"); return 0; } if (!HasFlag(source_p, FLAGS_EXEMPTRESV) && !(HasUMode(source_p, UMODE_OPER) && HasOFlag(source_p, OPER_FLAG_NICK_RESV)) && (conf = find_matching_name_conf(CONF_NRESV, nick, NULL, NULL, 0))) { ++conf->count; sendto_one_numeric(source_p, &me, ERR_ERRONEUSNICKNAME, nick, conf->reason); sendto_realops_flags(UMODE_REJ, L_ALL, SEND_NOTICE, "Forbidding reserved nick %s from user %s", nick, get_client_name(source_p, HIDE_IP)); return 0; } if ((target_p = hash_find_client(nick)) == NULL) change_local_nick(source_p, nick); else if (target_p == source_p) { /* * If (target_p == source_p) the client is changing nicks between * equivalent nicknames ie: [nick] -> {nick} */ /* Check the nick isn't exactly the same */ if (strcmp(target_p->name, nick)) change_local_nick(source_p, nick); } else if (IsUnknown(target_p)) { /* * If the client that has the nick isn't registered yet (nick but no * user) then drop the unregged client */ exit_client(target_p, "Overridden by other sign on"); change_local_nick(source_p, nick); } else sendto_one_numeric(source_p, &me, ERR_NICKNAMEINUSE, target_p->name); return 0; }