static void ms_ping(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { struct Client *target_p; const char *origin, *destination; if(parc < 2 || *parv[1] == '\0') { sendto_one(source_p, form_str(ERR_NOORIGIN), me.name, parv[0]); return; } origin = source_p->name; destination = parv[2]; /* Will get NULL or pointer (parc >= 2!!) */ if(!EmptyString(destination) && irccmp(destination, me.name) != 0 && irccmp(destination, me.id) != 0) { if((target_p = find_server(destination))) sendto_one(target_p, ":%s PING %s :%s", parv[0], origin, destination); else { sendto_one(source_p, form_str(ERR_NOSUCHSERVER), ID_or_name(&me, client_p), parv[0], destination); return; } } else sendto_one(source_p, ":%s PONG %s :%s", ID_or_name(&me, client_p), (destination) ? destination : me.name, origin); }
/* apply_tdline() * * inputs - * output - NONE * side effects - tkline as given is placed */ static void apply_dline(struct Client *source_p, struct MaskItem *conf, time_t tkline_time) { if (tkline_time) { conf->until = CurrentTime + tkline_time; sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE, "%s added temporary %d min. D-Line for [%s] [%s]", get_oper_name(source_p), tkline_time/60, conf->host, conf->reason); sendto_one(source_p, ":%s NOTICE %s :Added temporary %d min. D-Line [%s]", MyConnect(source_p) ? me.name : ID_or_name(&me, source_p->from), source_p->name, tkline_time/60, conf->host); ilog(LOG_TYPE_DLINE, "%s added temporary %d min. D-Line for [%s] [%s]", get_oper_name(source_p), tkline_time/60, conf->host, conf->reason); } else { sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE, "%s added D-Line for [%s] [%s]", get_oper_name(source_p), conf->host, conf->reason); sendto_one(source_p, ":%s NOTICE %s :Added D-Line [%s]", MyConnect(source_p) ? me.name : ID_or_name(&me, source_p->from), source_p->name, conf->host); ilog(LOG_TYPE_DLINE, "%s added D-Line for [%s] [%s]", get_oper_name(source_p), conf->host, conf->reason); } SetConfDatabase(conf); conf->setat = CurrentTime; add_conf_by_address(CONF_DLINE, conf); rehashed_klines = 1; }
/* * ms_tmode() * * inputs - parv[0] = UID * parv[1] = TS * parv[2] = channel name * parv[3] = modestring */ static void ms_tmode(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { struct Channel *chptr = NULL; struct Membership *member = NULL; if ((chptr = hash_find_channel(parv[2])) == NULL) { sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL), ID_or_name(&me, client_p), ID_or_name(source_p, client_p), parv[2]); return; } if (atol(parv[1]) > chptr->channelts) return; if (IsServer(source_p)) set_channel_mode(client_p, source_p, chptr, NULL, parc - 3, parv + 3, chptr->chname); else { member = find_channel_link(source_p, chptr); /* XXX are we sure we just want to bail here? */ if (has_member_flags(member, CHFL_DEOPPED)) return; set_channel_mode(client_p, source_p, chptr, member, parc - 3, parv + 3, chptr->chname); } }
/*! \brief PONG 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] = origin * - parv[2] = destination */ static int ms_pong(struct Client *source_p, int parc, char *parv[]) { struct Client *target_p = NULL; const char *destination = NULL; if (parc < 2 || EmptyString(parv[1])) { sendto_one_numeric(source_p, &me, ERR_NOORIGIN); return 0; } destination = parv[2]; /* 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 = hash_find_client(destination)) || (target_p = hash_find_id(destination))) sendto_one(target_p, ":%s PONG %s %s", ID_or_name(source_p, target_p), parv[1], ID_or_name(target_p, target_p)); else if (!IsDigit(*destination)) sendto_one_numeric(source_p, &me, ERR_NOSUCHSERVER, destination); } return 0; }
/* * ms_version - VERSION command handler * parv[0] = sender prefix * parv[1] = remote server */ static void ms_version(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { if (hunt_server(client_p, source_p, ":%s VERSION :%s", 1, parc, parv) == HUNTED_ISME) { sendto_one(source_p, form_str(RPL_VERSION), ID_or_name(&me, client_p), ID_or_name(source_p, client_p), ircd_version, serno, me.name, confopts(source_p), serveropts); show_isupport(source_p); } }
/* ** ms_info() ** parv[0] = sender prefix ** parv[1] = servername */ static void ms_info(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { if (!IsClient(source_p)) return; if (hunt_server(client_p, source_p, ":%s INFO :%s", 1, parc, parv) == HUNTED_ISME) { info_spy(source_p); send_info_text(source_p); if (IsOper(source_p)) send_conf_options(source_p); send_birthdate_online_time(source_p); sendto_one(source_p, form_str(RPL_ENDOFINFO), ID_or_name(&me, client_p), ID_or_name(source_p, client_p)); } }
/* msg_channel() * * inputs - flag privmsg or notice * - pointer to command "PRIVMSG" or "NOTICE" * - pointer to client_p * - pointer to source_p * - pointer to channel * output - NONE * side effects - message given channel */ static void msg_channel(int p_or_n, const char *command, struct Client *client_p, struct Client *source_p, struct Channel *chptr, char *text) { int result; if(MyClient(source_p)) { /* idle time shouldnt be reset by notices --fl */ if(p_or_n != NOTICE) source_p->localClient->last = CurrentTime; } #ifndef STATIC_MODULES execute_callback(channel_message, source_p, chptr, text); #endif /* chanops and voiced can flood their own channel with impunity */ if((result = can_send(chptr, source_p, NULL, text, p_or_n)) > 0) { if(result == CAN_SEND_OPV || !flood_attack_channel(p_or_n, source_p, chptr, chptr->chname)) { sendto_channel_butone(client_p, source_p, chptr, command, ":%s", text); } } else { if(p_or_n != NOTICE) { if(result == CAN_SEND_NOREGNICK) sendto_one(source_p, form_str(ERR_NEEDREGGEDNICK), ID_or_name(&me, client_p), ID_or_name(source_p, client_p), chptr->chname, "speak in"); else if(result == CAN_SEND_NOCTRLS) sendto_one(source_p, form_str(ERR_NOCTRLSONCHAN), ID_or_name(&me, client_p), ID_or_name(source_p, client_p), chptr->chname, text); else if(result == CAN_SEND_NOCTCP) sendto_one(source_p, form_str(ERR_NOCTCP), ID_or_name(&me, client_p), ID_or_name(source_p, client_p), chptr->chname, "channel", text); else sendto_one(source_p, form_str(ERR_CANNOTSENDTOCHAN), ID_or_name(&me, client_p), ID_or_name(source_p, client_p), chptr->chname); } } }
/* do_admin() * * inputs - pointer to client to report to * output - none * side effects - admin info is sent to client given */ static void do_admin(struct Client *source_p) { const char *nick; if (IsPerson(source_p)) admin_spy(source_p); nick = ID_or_name(source_p, source_p->from); sendto_one(source_p, form_str(RPL_ADMINME), ID_or_name(&me, source_p->from), nick, me.name); if (AdminInfo.name != NULL) sendto_one(source_p, form_str(RPL_ADMINLOC1), ID_or_name(&me, source_p->from), nick, AdminInfo.name); if (AdminInfo.description != NULL) sendto_one(source_p, form_str(RPL_ADMINLOC2), ID_or_name(&me, source_p->from), nick, AdminInfo.description); if (AdminInfo.email != NULL) sendto_one(source_p, form_str(RPL_ADMINEMAIL), ID_or_name(&me, source_p->from), nick, AdminInfo.email); }
/*! \brief Sends administrative information about this server. * * \param source_p Pointer to client to report to */ static void do_admin(struct Client *source_p) { const char *me_name = ID_or_name(&me, source_p->from); const char *nick = ID_or_name(source_p, source_p->from); sendto_realops_flags(UMODE_SPY, L_ALL, SEND_NOTICE, "ADMIN requested by %s (%s@%s) [%s]", source_p->name, source_p->username, source_p->host, source_p->servptr->name); sendto_one(source_p, form_str(RPL_ADMINME), me_name, nick, me.name); if (AdminInfo.name != NULL) sendto_one(source_p, form_str(RPL_ADMINLOC1), me_name, nick, AdminInfo.name); if (AdminInfo.description != NULL) sendto_one(source_p, form_str(RPL_ADMINLOC2), me_name, nick, AdminInfo.description); if (AdminInfo.email != NULL) sendto_one(source_p, form_str(RPL_ADMINEMAIL), me_name, nick, AdminInfo.email); }
/* * m_mode - MODE command handler * parv[0] - sender * parv[1] - channel */ static void m_mode(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { struct Channel *chptr = NULL; struct Membership *member; static char modebuf[MODEBUFLEN]; static char parabuf[MODEBUFLEN]; if (parv[1][0] == '\0') { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "MODE"); return; } /* Now, try to find the channel in question */ if (!IsChanPrefix(parv[1][0])) { /* if here, it has to be a non-channel name */ set_user_mode(client_p, source_p, parc, parv); return; } if (!check_channel_name(parv[1])) { sendto_one(source_p, form_str(ERR_BADCHANNAME), me.name, source_p->name, parv[1]); return; } chptr = hash_find_channel(parv[1]); if (chptr == NULL) { /* if chptr isn't found locally, it =could= exist * on the uplink. So ask. */ /* LazyLinks */ /* only send a mode upstream if a local client sent this request * -davidt */ if (MyClient(source_p) && !ServerInfo.hub && uplink && IsCapable(uplink, CAP_LL)) { sendto_one(uplink, ":%s MODE %s %s", ID_or_name(source_p, uplink), parv[1], (parv[2] ? parv[2] : "")); return; } else { sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL), me.name, parv[0], parv[1]); return; } } /* Now known the channel exists */ if (parc < 3) { channel_modes(chptr, source_p, modebuf, parabuf); sendto_one(source_p, form_str(RPL_CHANNELMODEIS), me.name, parv[0], parv[1], modebuf, parabuf); sendto_one(source_p, form_str(RPL_CREATIONTIME), me.name, parv[0], parv[1], chptr->channelts); } /* bounce all modes from people we deop on sjoin * servers have always gotten away with murder, * including telnet servers *g* - Dianora * * XXX Is it worth the bother to make an ms_mode() ? - Dianora */ else if (IsServer(source_p)) { set_channel_mode(client_p, source_p, chptr, NULL, parc - 2, parv + 2, chptr->chname); } else { member = find_channel_link(source_p, chptr); if (!has_member_flags(member, CHFL_DEOPPED)) { /* Finish the flood grace period... */ if (MyClient(source_p) && !IsFloodDone(source_p)) { if (!((parc == 3) && (parv[2][0] == 'b') && (parv[2][1] == '\0'))) flood_endgrace(source_p); } set_channel_mode(client_p, source_p, chptr, member, parc - 2, parv + 2, chptr->chname); } } }
/* * m_mode - MODE command handler * parv[0] - sender * parv[1] - channel */ static void m_mode(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { struct Channel *chptr = NULL; struct Membership *member; static char modebuf[MODEBUFLEN]; static char parabuf[MODEBUFLEN]; if (EmptyString(parv[1])) { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "MODE"); return; } /* Now, try to find the channel in question */ if (!IsChanPrefix(*parv[1])) { /* if here, it has to be a non-channel name */ set_user_mode(client_p, source_p, parc, parv); return; } if ((chptr = hash_find_channel(parv[1])) == NULL) { sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL), ID_or_name(&me, source_p->from), ID_or_name(source_p, source_p->from), parv[1]); return; } /* Now known the channel exists */ if (parc < 3) { channel_modes(chptr, source_p, modebuf, parabuf); sendto_one(source_p, form_str(RPL_CHANNELMODEIS), me.name, source_p->name, chptr->chname, modebuf, parabuf); sendto_one(source_p, form_str(RPL_CREATIONTIME), me.name, source_p->name, chptr->chname, chptr->channelts); } /* bounce all modes from people we deop on sjoin * servers have always gotten away with murder, * including telnet servers *g* - Dianora * * XXX Is it worth the bother to make an ms_mode() ? - Dianora */ else if (IsServer(source_p)) { set_channel_mode(client_p, source_p, chptr, NULL, parc - 2, parv + 2, chptr->chname); } else { member = find_channel_link(source_p, chptr); if (!has_member_flags(member, CHFL_DEOPPED)) { /* Finish the flood grace period... */ if (MyClient(source_p) && !IsFloodDone(source_p)) { if (!((parc == 3) && (parv[2][0] == 'b') && (parv[2][1] == '\0'))) flood_endgrace(source_p); } set_channel_mode(client_p, source_p, chptr, member, parc - 2, parv + 2, chptr->chname); } } }
/* ** m_invite ** parv[0] - sender prefix ** parv[1] - user to invite ** parv[2] - channel name ** parv[3] - invite timestamp */ static void m_invite(struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { struct Client *target_p = NULL; struct Channel *chptr = NULL; struct Membership *ms = NULL; if (IsServer(source_p)) return; if (EmptyString(parv[2])) { sendto_one(source_p, form_str(ERR_NEEDMOREPARAMS), me.name, source_p->name, "INVITE"); return; } if (MyClient(source_p) && !IsFloodDone(source_p)) flood_endgrace(source_p); if ((target_p = find_person(client_p, parv[1])) == NULL) { sendto_one(source_p, form_str(ERR_NOSUCHNICK), me.name, source_p->name, parv[1]); return; } /* Do not send local channel invites to users if they are not on the * same server as the person sending the INVITE message. */ /* Possibly should be an error sent to source_p */ /* done .. there should be no problem because MyConnect(source_p) should * always be true if parse() and such is working correctly --is */ if (!MyConnect(target_p) && (*parv[2] == '&')) { if (ConfigServerHide.hide_servers == 0) sendto_one(source_p, form_str(ERR_USERNOTONSERV), me.name, source_p->name, target_p->name); return; } if ((chptr = hash_find_channel(parv[2])) == NULL) { sendto_one(source_p, form_str(ERR_NOSUCHCHANNEL), me.name, source_p->name, parv[2]); return; } if (MyConnect(source_p) && (ms = find_channel_link(source_p, chptr)) == NULL) { sendto_one(source_p, form_str(ERR_NOTONCHANNEL), me.name, source_p->name, chptr->chname); return; } if (MyConnect(source_p) && !has_member_flags(ms, CHFL_CHANOP|CHFL_HALFOP)) { sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), me.name, source_p->name, chptr->chname); return; } if ((chptr->mode.mode & MODE_OPERONLY)) { if (MyConnect(source_p) && !IsOper(source_p)) { sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), me.name, source_p->name, chptr->chname); return; } } if (IsMember(target_p, chptr)) { sendto_one(source_p, form_str(ERR_USERONCHANNEL), me.name, source_p->name, target_p->name, chptr->chname); return; } if (MyConnect(source_p)) { sendto_one(source_p, form_str(RPL_INVITING), me.name, source_p->name, target_p->name, chptr->chname); if (target_p->away) sendto_one(source_p, form_str(RPL_AWAY), me.name, source_p->name, target_p->name, target_p->away); } else if (parc > 3 && IsDigit(*parv[3])) if (atoi(parv[3]) > chptr->channelts) return; if (MyConnect(target_p)) { sendto_one(target_p, ":%s!%s@%s INVITE %s :%s", source_p->name, source_p->username, source_p->host, target_p->name, chptr->chname); if (chptr->mode.mode & MODE_INVITEONLY) { sendto_channel_local(CHFL_CHANOP|CHFL_HALFOP, 0, chptr, ":%s NOTICE %s :%s is inviting %s to %s.", me.name, chptr->chname, source_p->name, target_p->name, chptr->chname); sendto_channel_remote(source_p, client_p, CHFL_CHANOP|CHFL_HALFOP, NOCAPS, NOCAPS, chptr, ":%s NOTICE %s :%s is inviting %s to %s.", source_p->name, chptr->chname, source_p->name, target_p->name, chptr->chname); /* Add the invite if channel is +i */ add_invite(chptr, target_p); } } else if (target_p->from != client_p) sendto_one(target_p, ":%s INVITE %s %s %lu", ID_or_name(source_p, target_p->from), ID_or_name(target_p, target_p->from), chptr->chname, (unsigned long)chptr->channelts); }
static void do_ison(struct Client *client_p, struct Client *up, struct Client *source_p, int parc, char *parv[]) { struct Client *target_p = NULL; char *nick; char *p; char *current_insert_point, *current_insert_point2; char buf[IRCD_BUFSIZE]; char buf2[IRCD_BUFSIZE]; int len; int i; int done = 0; int relay_to_hub = 0; current_insert_point2 = buf2; *buf2 = '\0'; len = ircsprintf(buf, form_str(RPL_ISON), me.name, parv[0]); current_insert_point = buf + len; /* rfc1459 is ambigious about how to handle ISON * this should handle both interpretations. */ for (i = 1; i < parc; i++) { for (nick = strtoken(&p, parv[i], " "); nick; nick = strtoken(&p, NULL, " ")) { if ((target_p = find_person(client_p, nick))) { len = strlen(target_p->name); if ((current_insert_point + (len + 5)) < (buf + sizeof(buf))) { memcpy(current_insert_point, target_p->name, len); current_insert_point += len; *current_insert_point++ = ' '; } else { done = 1; break; } } if (up) { /* Build up a single list, for use if we relay.. */ len = strlen(nick); if ((current_insert_point2 + len + 5) < (buf2 + sizeof(buf2))) { memcpy(current_insert_point2, nick, len); current_insert_point2 += len; *current_insert_point2++ = ' '; } if (target_p == NULL) { /* * XXX Ick. we need to ask our hub if nick is online. * it's probably safest to relay the whole command, * unless we can answer it fully ourselves. * -davidt */ relay_to_hub = 1; /* Also cache info about nick */ sendto_one(up, ":%s NBURST %s", ID_or_name(&me, up), nick); } } } if (done) break; } /* current_insert_point--; * Do NOT take out the trailing space, it breaks ircII * --Rodder */ *current_insert_point = '\0'; *current_insert_point2 = '\0'; if (relay_to_hub) sendto_one(up, ":%s ISON :%s", ID_or_name(source_p, up), buf2); else sendto_one(source_p, "%s", buf); }
/* * * parc number of arguments ('sender' counted as one!) * parv[0] pointer to 'sender' (may point to empty string) (not used) * parv[1]..parv[parc-1] * pointers to additional parameters, this is a NULL * terminated list (parv[parc] == NULL). * * *WARNING* * Numerics are mostly error reports. If there is something * wrong with the message, just *DROP* it! Don't even think of * sending back a neat error message -- big danger of creating * a ping pong error message... */ static void do_numeric(char numeric[], struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { struct Client *target_p; struct Channel *chptr; char *t; /* current position within the buffer */ int i, tl; /* current length of presently being built string in t */ if (parc < 2 || !IsServer(source_p)) return; /* Remap low number numerics. */ if (numeric[0] == '0') numeric[0] = '1'; /* Prepare the parameter portion of the message into 'buffer'. * (Because the buffer is twice as large as the message buffer * for the socket, no overflow can occur here... ...on current * assumptions--bets are off, if these are changed --msa) */ t = buffer; for (i = 2; i < (parc - 1); i++) { tl = ircsprintf(t, " %s", parv[i]); t += tl; } ircsprintf(t," :%s", parv[parc-1]); if (((target_p = find_person(client_p, parv[1])) != NULL) || ((target_p = find_server(parv[1])) != NULL)) { if (IsMe(target_p)) { int num; /* * We shouldn't get numerics sent to us, * any numerics we do get indicate a bug somewhere.. */ /* ugh. this is here because of nick collisions. when two servers * relink, they burst each other their nicks, then perform collides. * if there is a nick collision, BOTH servers will kill their own * nicks, and BOTH will kill the other servers nick, which wont exist, * because it will have been already killed by the local server. * * unfortunately, as we cant guarantee other servers will do the * "right thing" on a nick collision, we have to keep both kills. * ergo we need to ignore ERR_NOSUCHNICK. --fl_ */ /* quick comment. This _was_ tried. i.e. assume the other servers * will do the "right thing" and kill a nick that is colliding. * unfortunately, it did not work. --Dianora */ /* Yes, a good compiler would have optimised this, but * this is probably easier to read. -db */ num = atoi(numeric); if ((num != ERR_NOSUCHNICK)) sendto_gnotice_flags(UMODE_ALL, L_ALL, me.name, &me, NULL, "*** %s(via %s) sent a %s numeric to me: %s", source_p->name, client_p->name, numeric, buffer); return; } else if (target_p->from == client_p) { /* This message changed direction (nick collision?) * ignore it. */ return; } /* csircd will send out unknown umode flag for +a (admin), drop it here. */ if ((atoi(numeric) == ERR_UMODEUNKNOWNFLAG) && MyClient(target_p)) return; /* Fake it for server hiding, if its our client */ if (ConfigServerHide.hide_servers && MyClient(target_p) && !IsOper(target_p)) sendto_one(target_p, ":%s %s %s%s", me.name, numeric, target_p->name, buffer); else sendto_one(target_p, ":%s %s %s%s", ID_or_name(source_p, target_p->from), numeric, ID_or_name(target_p, target_p->from), buffer); return; } else if ((chptr = hash_find_channel(parv[1])) != NULL) sendto_channel_local(ALL_MEMBERS, NO, chptr, ":%s %s %s %s", source_p->name, numeric, chptr->chname, buffer); }
/* write_conf_line() * * inputs - pointer to struct AccessItem * - string current_date (small date) * - time_t cur_time * output - NONE * side effects - This function takes care of * finding right conf file, writing * the right lines to this file, * notifying the oper that their kline/dline etc. is in place * notifying the opers on the server about the k/d etc. line * * - Dianora */ void write_conf_line(struct Client *source_p, struct ConfItem *conf, const char *current_date, time_t cur_time, time_t duration) { FBFILE *out; const char *filename, *from, *to; struct AccessItem *aconf; struct MatchItem *xconf; struct ResvChannel *cresv_p=NULL; struct MatchItem *nresv_p=NULL; ConfType type; type = conf->type; filename = get_conf_name(type); if (!MyConnect(source_p) && IsCapable(source_p->from, CAP_TS6) && HasID(source_p)) { from = me.id; to = source_p->id; } else { from = me.name; to = source_p->name; } if ((out = fbopen(filename, "a")) == NULL) { sendto_realops_flags(UMODE_ALL, L_ALL, "*** Problem opening %s ", filename); return; } switch(type) { case KLINE_TYPE: aconf = (struct AccessItem *)map_to_conf(conf); if(duration == 0) { sendto_realops_flags(UMODE_ALL, L_ALL, "%s added K-Line for [%s@%s] [%s]", get_oper_name(source_p), aconf->user, aconf->host, aconf->reason); sendto_one(source_p, ":%s NOTICE %s :Added K-Line [%s@%s]", from, to, aconf->user, aconf->host); ilog(L_TRACE, "%s added K-Line for [%s@%s] [%s]", source_p->name, aconf->user, aconf->host, aconf->reason); log_oper_action(LOG_KLINE_TYPE, source_p, "[%s@%s] [%s]\n", aconf->user, aconf->host, aconf->reason); write_csv_line(out, "%s%s%s%s%s%s%d", aconf->user, aconf->host, aconf->reason, aconf->oper_reason, current_date, get_oper_name(source_p), cur_time); } else { sendto_realops_flags(UMODE_ALL, L_ALL, "%s added temporary %d min. K-Line for [%s@%s] [%s]", get_oper_name(source_p), duration/60, aconf->user, aconf->host, aconf->reason); sendto_one(source_p, ":%s NOTICE %s :Added temporary %d min. K-Line [%s@%s]", from, to, duration/60, aconf->user, aconf->host); ilog(L_TRACE, "%s added temporary %ld min. K-Line for [%s@%s] [%s]", source_p->name, duration/60, aconf->user, aconf->host, aconf->reason); log_oper_action(LOG_TEMP_KLINE_TYPE, source_p, "[%s@%s] [%s]\n", aconf->user, aconf->host, aconf->reason); write_csv_line(out, "%s%s%s%s%s%s%d%d", aconf->user, aconf->host, aconf->reason, aconf->oper_reason, current_date, get_oper_name(source_p), cur_time, aconf->hold); } break; case RKLINE_TYPE: aconf = map_to_conf(conf); if(duration == 0) { sendto_realops_flags(UMODE_ALL, L_ALL, "%s added RK-Line for [%s@%s] [%s]", get_oper_name(source_p), aconf->user, aconf->host, aconf->reason); sendto_one(source_p, ":%s NOTICE %s :Added RK-Line [%s@%s]", from, to, aconf->user, aconf->host); ilog(L_TRACE, "%s added K-Line for [%s@%s] [%s]", source_p->name, aconf->user, aconf->host, aconf->reason); log_oper_action(LOG_RKLINE_TYPE, source_p, "[%s@%s] [%s]\n", aconf->user, aconf->host, aconf->reason); write_csv_line(out, "%s%s%s%s%s%s%d", aconf->user, aconf->host, aconf->reason, aconf->oper_reason, current_date, get_oper_name(source_p), cur_time); } else { sendto_realops_flags(UMODE_ALL, L_ALL, "%s added temporary %d min. RK-Line for [%s@%s] [%s]", get_oper_name(source_p), duration/60, aconf->user, aconf->host, aconf->reason); sendto_one(source_p, ":%s NOTICE %s :Added temporary %d min. RK-Line [%s@%s]", from, to, duration/60, aconf->user, aconf->host); ilog(L_TRACE, "%s added temporary %ld min. RK-Line for [%s@%s] [%s]", source_p->name, duration/60, aconf->user, aconf->host, aconf->reason); log_oper_action(LOG_TEMP_RKLINE_TYPE, source_p, "[%s@%s] [%s]\n", aconf->user, aconf->host, aconf->reason); write_csv_line(out, "%s%s%s%s%s%s%d%d", aconf->user, aconf->host, aconf->reason, aconf->oper_reason, current_date, get_oper_name(source_p), cur_time, aconf->hold); } break; case DLINE_TYPE: aconf = (struct AccessItem *)map_to_conf(conf); if(duration == 0) { sendto_realops_flags(UMODE_ALL, L_ALL, "%s added D-Line for [%s] [%s]", get_oper_name(source_p), aconf->host, aconf->reason); sendto_one(source_p, ":%s NOTICE %s :Added D-Line [%s] to %s", from, to, aconf->host, filename); ilog(L_TRACE, "%s added D-Line for [%s] [%s]", get_oper_name(source_p), aconf->host, aconf->reason); log_oper_action(LOG_DLINE_TYPE, source_p, "[%s] [%s]\n", aconf->host, aconf->reason); write_csv_line(out, "%s%s%s%s%s%d", aconf->host, aconf->reason, aconf->oper_reason, current_date, get_oper_name(source_p), cur_time); } else { sendto_realops_flags(UMODE_ALL, L_ALL, "%s added temporary %d min. D-Line for [%s] [%s]", get_oper_name(source_p), duration/60, aconf->host, aconf->reason); sendto_one(source_p, ":%s NOTICE %s :Added temporary %d min. D-Line [%s]", from, to, duration/60, aconf->host); ilog(L_TRACE, "%s added temporary %d min. D-Line for [%s] [%s]", source_p->name, (int)duration/60, aconf->host, aconf->reason); log_oper_action(LOG_TEMP_DLINE_TYPE, source_p, "[%s@%s] [%s]\n", aconf->user, aconf->host, aconf->reason); write_csv_line(out, "%s%s%s%s%s%d%d", aconf->host, aconf->reason, aconf->oper_reason, current_date, get_oper_name(source_p), cur_time, aconf->hold); } break; case XLINE_TYPE: xconf = (struct MatchItem *)map_to_conf(conf); if(duration == 0) { sendto_realops_flags(UMODE_ALL, L_ALL, "%s added X-Line for [%s] [%s]", get_oper_name(source_p), conf->name, xconf->reason); sendto_one(source_p, ":%s NOTICE %s :Added X-Line [%s] [%d] [%s] to %s", from, to, conf->name, xconf->action, xconf->reason, filename); ilog(L_TRACE, "%s added X-Line for [%s] [%s]", get_oper_name(source_p), conf->name, xconf->reason); write_csv_line(out, "%s%s%s%s%s%d", conf->name, xconf->reason, xconf->oper_reason, current_date, get_oper_name(source_p), cur_time); } else { sendto_realops_flags(UMODE_ALL, L_ALL, "%s added temporary %d min. X-Line for [%s] [%s]", get_oper_name(source_p), (int)duration/60, conf->name, xconf->reason); sendto_one(source_p, ":%s NOTICE %s :Added temporary %d min. X-Line [%s]", MyConnect(source_p) ? me.name : ID_or_name(&me, source_p->from), source_p->name, (int)duration/60, conf->name); ilog(L_TRACE, "%s added temporary %d min. X-Line for [%s] [%s]", source_p->name, (int)duration/60, conf->name, xconf->reason); write_csv_line(out, "%s%s%s%s%s%d%d", conf->name, xconf->reason, xconf->oper_reason, current_date, get_oper_name(source_p), cur_time, xconf->hold); } break; case RXLINE_TYPE: xconf = (struct MatchItem *)map_to_conf(conf); if(duration == 0) { sendto_realops_flags(UMODE_ALL, L_ALL, "%s added RX-Line for [%s] [%s]", get_oper_name(source_p), conf->name, xconf->reason); sendto_one(source_p, ":%s NOTICE %s :Added RX-Line [%s] [%s] to %s", from, to, conf->name, xconf->reason, filename); ilog(L_TRACE, "%s added X-Line for [%s] [%s]", get_oper_name(source_p), conf->name, xconf->reason); write_csv_line(out, "%s%s%s%s%s%d", conf->name, xconf->reason, xconf->oper_reason, current_date, get_oper_name(source_p), cur_time); } else { sendto_realops_flags(UMODE_ALL, L_ALL, "%s added temporary %d min. RX-Line for [%s] [%s]", get_oper_name(source_p), (int)duration/60, conf->name, xconf->reason); sendto_one(source_p, ":%s NOTICE %s :Added temporary %d min. RX-Line [%s]", from, to, (int)duration/60, conf->name); ilog(L_TRACE, "%s added temporary %d min. RX-Line for [%s] [%s]", source_p->name, (int)duration/60, conf->name, xconf->reason); write_csv_line(out, "%s%s%s%s%s%d%d", conf->name, xconf->reason, xconf->oper_reason, current_date, get_oper_name(source_p), cur_time, xconf->hold); } break; case CRESV_TYPE: cresv_p = (struct ResvChannel *)map_to_conf(conf); if(duration == 0) write_csv_line(out, "%s%s", cresv_p->name, cresv_p->reason); else write_csv_line(out, "%s%s%d", cresv_p->name, cresv_p->reason, cresv_p->hold); break; case NRESV_TYPE: nresv_p = (struct MatchItem *)map_to_conf(conf); if(duration == 0) write_csv_line(out, "%s%s", conf->name, nresv_p->reason); else write_csv_line(out, "%s%s%d", conf->name, nresv_p->reason, nresv_p->hold); break; default: fbclose(out); return; } fbclose(out); }
/* * inputs - flag privmsg or notice * - pointer to command "PRIVMSG" or "NOTICE" * - pointer to client_p * - pointer to source_p * - pointer to channel */ static void m_message(int p_or_n, const char *command, struct Client *client_p, struct Client *source_p, int parc, char *parv[]) { int i; if(parc < 2 || EmptyString(parv[1])) { if(p_or_n != NOTICE) sendto_one(source_p, form_str(ERR_NORECIPIENT), ID_or_name(&me, client_p), ID_or_name(source_p, client_p), command); return; } if(parc < 3 || EmptyString(parv[2])) { if(p_or_n != NOTICE) sendto_one(source_p, form_str(ERR_NOTEXTTOSEND), ID_or_name(&me, client_p), ID_or_name(source_p, client_p)); return; } /* Finish the flood grace period... */ if(MyClient(source_p) && !IsFloodDone(source_p)) #if 0 &&irccmp(source_p->name, parv[1]) != 0) /* some dumb clients msg/notice themself to determine lag to the server BEFORE sending JOIN commands, and then flood off because they left gracemode. -wiz */ /* * Not our problem if they do this. -Michael */ #endif flood_endgrace(source_p); if(build_target_list(p_or_n, command, client_p, source_p, parv[1], parv[2]) < 0) { /* Sigh. We need to relay this command to the hub */ if(!ServerInfo.hub && (uplink != NULL)) sendto_one(uplink, ":%s %s %s :%s", source_p->name, command, parv[1], parv[2]); return; } for(i = 0; i < ntargets; i++) { switch (targets[i].type) { case ENTITY_CHANNEL: msg_channel(p_or_n, command, client_p, source_p, (struct Channel *) targets[i].ptr, parv[2]); break; case ENTITY_CHANOPS_ON_CHANNEL: msg_channel_flags(p_or_n, command, client_p, source_p, (struct Channel *) targets[i].ptr, targets[i].flags, parv[2]); break; case ENTITY_CLIENT: msg_client(p_or_n, command, source_p, (struct Client *) targets[i].ptr, parv[2]); break; } } }
/* build_target_list() * * inputs - pointer to given client_p (server) * - pointer to given source (oper/client etc.) * - pointer to list of nicks/channels * - pointer to table to place results * - pointer to text (only used if source_p is an oper) * output - number of valid entities * side effects - target_table is modified to contain a list of * pointers to channels or clients * if source client is an oper * all the classic old bizzare oper privmsg tricks * are parsed and sent as is, if prefixed with $ * to disambiguate. * */ static int build_target_list(int p_or_n, const char *command, struct Client *client_p, struct Client *source_p, char *nicks_channels, char *text) { int type; char *p = NULL, *nick, *target_list, ncbuf[IRCD_BUFSIZE]; struct Channel *chptr = NULL; struct Client *target_p = NULL; /* Sigh, we can't mutilate parv[1] incase we need it to send to a hub */ if(!ServerInfo.hub && (uplink != NULL) && IsCapable(uplink, CAP_LL)) { strlcpy(ncbuf, nicks_channels, sizeof(ncbuf)); target_list = ncbuf; } else target_list = nicks_channels; /* skip strcpy for non-lazyleafs */ ntargets = 0; for(nick = strtoken(&p, target_list, ","); nick; nick = strtoken(&p, NULL, ",")) { char *with_prefix; /* * channels are privmsg'd a lot more than other clients, moved up * here plain old channel msg? */ if(IsChanPrefix(*nick)) { /* ignore send of local channel to a server (should not happen) */ if(*nick == '&' && IsServer(client_p)) continue; if((chptr = hash_find_channel(nick)) != NULL) { if(!duplicate_ptr(chptr)) { if(ntargets >= ConfigFileEntry.max_targets) { sendto_one(source_p, form_str(ERR_TOOMANYTARGETS), ID_or_name(&me, client_p), ID_or_name(source_p, client_p), nick, ConfigFileEntry.max_targets); return (1); } targets[ntargets].ptr = (void *) chptr; targets[ntargets++].type = ENTITY_CHANNEL; } } else { if(!ServerInfo.hub && (uplink != NULL) && IsCapable(uplink, CAP_LL)) return -1; else if(p_or_n != NOTICE) sendto_one(source_p, form_str(ERR_NOSUCHNICK), ID_or_name(&me, client_p), ID_or_name(source_p, client_p), nick); } continue; } /* look for a privmsg to another client */ if((target_p = find_person(client_p, nick)) != NULL) { if(!duplicate_ptr(target_p)) { if(ntargets >= ConfigFileEntry.max_targets) { sendto_one(source_p, form_str(ERR_TOOMANYTARGETS), ID_or_name(&me, client_p), ID_or_name(source_p, client_p), nick, ConfigFileEntry.max_targets); return (1); } targets[ntargets].ptr = (void *) target_p; targets[ntargets].type = ENTITY_CLIENT; targets[ntargets++].flags = 0; } continue; } /* @#channel or +#channel message ? */ type = 0; with_prefix = nick; /* allow ~&%+@ if someone wants to do that */ for(;;) { #ifdef CHANAQ if(*nick == '~') type |= CHFL_OWNER; else if(*nick == '&') type |= CHFL_OWNER | CHFL_PROTECTED; else #endif if(*nick == '@') type |= CHFL_OWNER | CHFL_PROTECTED | CHFL_CHANOP; #ifdef HALFOPS else if(*nick == '%') type |= CHFL_OWNER | CHFL_PROTECTED | CHFL_CHANOP | CHFL_HALFOP; #endif else if(*nick == '+') type |= CHFL_OWNER | CHFL_PROTECTED | CHFL_CHANOP | CHFL_HALFOP | CHFL_VOICE; else break; nick++; } if(type != 0) { /* suggested by Mortiis */ if(*nick == '\0') /* if its a '\0' dump it, there is no recipient */ { sendto_one(source_p, form_str(ERR_NORECIPIENT), ID_or_name(&me, client_p), ID_or_name(source_p, client_p), command); continue; } /* At this point, nick+1 should be a channel name i.e. #foo or &foo * if the channel is found, fine, if not report an error */ if((chptr = hash_find_channel(nick)) != NULL) { if(!has_member_flags(find_channel_link(source_p, chptr), CHFL_OWNER | CHFL_PROTECTED | CHFL_CHANOP | CHFL_HALFOP | CHFL_VOICE)) { sendto_one(source_p, form_str(ERR_CHANOPRIVSNEEDED), ID_or_name(&me, client_p), ID_or_name(source_p, client_p), with_prefix); return (-1); } if(!duplicate_ptr(chptr)) { if(ntargets >= ConfigFileEntry.max_targets) { sendto_one(source_p, form_str(ERR_TOOMANYTARGETS), ID_or_name(&me, client_p), ID_or_name(source_p, client_p), nick, ConfigFileEntry.max_targets); return (1); } targets[ntargets].ptr = (void *) chptr; targets[ntargets].type = ENTITY_CHANOPS_ON_CHANNEL; targets[ntargets++].flags = type; } } else { if(!ServerInfo.hub && (uplink != NULL) && IsCapable(uplink, CAP_LL)) return -1; else if(p_or_n != NOTICE) sendto_one(source_p, form_str(ERR_NOSUCHNICK), ID_or_name(&me, client_p), ID_or_name(source_p, client_p), nick); } continue; } if((*nick == '$') || strchr(nick, '@') != NULL) { handle_special(p_or_n, command, client_p, source_p, nick, text); } else { if(!ServerInfo.hub && (uplink != NULL) && IsCapable(uplink, CAP_LL)) return -1; else if(p_or_n != NOTICE) { if(!IsDigit(*nick) || MyClient(source_p)) sendto_one(source_p, form_str(ERR_NOSUCHNICK), ID_or_name(&me, client_p), ID_or_name(source_p, client_p), nick); } } /* continue; */ } return (1); }