static void io_loop (void) { while (ServerRunning) { /* * Maybe we want a flags word? * ie. if (REHASHED_KLINES(global_flags)) * SET_REHASHED_KLINES(global_flags) * CLEAR_REHASHED_KLINES(global_flags) * * - Dianora */ if (rehashed_klines) { check_conf_klines (); rehashed_klines = 0; } else if (rehashed_xlines) { check_xlines (); rehashed_xlines = 0; } /* Run pending events, then get the number of seconds to the next * event */ while (eventNextTime () <= CurrentTime) eventRun (); comm_select (500); exit_aborted_clients (); free_exited_clients (); send_queued_all (); /* Check to see whether we have to rehash the configuration .. */ if (dorehash) { rehash (1); dorehash = 0; } if (doremotd) { read_message_file (&ConfigFileEntry.motd); sendto_realops_flags (UMODE_ALL, L_ALL, "Got signal SIGUSR1, reloading ircd motd file"); doremotd = 0; } } }
/* ms_ban() * * parv[1] - type * parv[2] - username mask or * * parv[3] - hostname mask * parv[4] - creation TS * parv[5] - duration (relative to creation) * parv[6] - lifetime (relative to creation) * parv[7] - oper or * * parv[8] - reason (possibly with |operreason) */ static int ms_ban(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { rb_dlink_node *ptr; struct ConfItem *aconf; unsigned int ntype; const char *oper, *stype; time_t now, created, hold, lifetime; char *p; int act; int valid; now = rb_current_time(); if (strlen(parv[1]) != 1) { sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Unknown BAN type %s from %s", parv[1], source_p->name); return 0; } switch (parv[1][0]) { case 'K': ntype = CONF_KILL; stype = "K-Line"; break; case 'X': ntype = CONF_XLINE; stype = "X-Line"; break; case 'R': ntype = IsChannelName(parv[3]) ? CONF_RESV_CHANNEL : CONF_RESV_NICK; stype = "RESV"; break; default: sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Unknown BAN type %s from %s", parv[1], source_p->name); return 0; } created = atol(parv[4]); hold = created + atoi(parv[5]); lifetime = created + atoi(parv[6]); if (!strcmp(parv[7], "*")) oper = IsServer(source_p) ? source_p->name : get_oper_name(source_p); else oper = parv[7]; ptr = find_prop_ban(ntype, parv[2], parv[3]); if (ptr != NULL) { /* We already know about this ban mask. */ aconf = ptr->data; if (aconf->created > created || (aconf->created == created && aconf->lifetime >= lifetime)) { if (IsPerson(source_p)) sendto_one_notice(source_p, ":Your %s [%s%s%s] has been superseded", stype, aconf->user ? aconf->user : "", aconf->user ? "@" : "", aconf->host); return 0; } /* act indicates if something happened (from the oper's * point of view). This is the case if the ban was * previously active (not deleted) or if the new ban * is not a removal and not already expired. */ act = !(aconf->status & CONF_ILLEGAL) || (hold != created && hold > now); if (lifetime > aconf->lifetime) aconf->lifetime = lifetime; /* already expired, hmm */ if (aconf->lifetime <= now) return 0; /* Deactivate, it will be reactivated later if appropriate. */ deactivate_conf(aconf, ptr, now); rb_free(aconf->user); aconf->user = NULL; rb_free(aconf->host); aconf->host = NULL; operhash_delete(aconf->info.oper); aconf->info.oper = NULL; rb_free(aconf->passwd); aconf->passwd = NULL; rb_free(aconf->spasswd); aconf->spasswd = NULL; } else { /* New ban mask. */ aconf = make_conf(); aconf->status = CONF_ILLEGAL | ntype; aconf->lifetime = lifetime; rb_dlinkAddAlloc(aconf, &prop_bans); act = hold != created && hold > now; } aconf->flags &= ~CONF_FLAGS_MYOPER; aconf->flags |= CONF_FLAGS_TEMPORARY; aconf->user = ntype == CONF_KILL ? rb_strdup(parv[2]) : NULL; aconf->host = rb_strdup(parv[3]); aconf->info.oper = operhash_add(oper); aconf->created = created; aconf->hold = hold; if (ntype != CONF_KILL || (p = strchr(parv[parc - 1], '|')) == NULL) aconf->passwd = rb_strdup(parv[parc - 1]); else { aconf->passwd = rb_strndup(parv[parc - 1], p - parv[parc - 1] + 1); aconf->spasswd = rb_strdup(p + 1); } /* The ban is fully filled in and in the prop_bans list * but still deactivated. Now determine if it should be activated * and send the server notices. */ /* We only reject *@* and the like here. * Otherwise malformed bans are fairly harmless and can be removed. */ switch (ntype) { case CONF_KILL: valid = valid_wild_card(aconf->user, aconf->host); break; case CONF_RESV_CHANNEL: valid = 1; break; default: valid = valid_wild_card_simple(aconf->host); break; } if (act && hold != created && !valid) { sendto_realops_snomask(SNO_GENERAL, L_ALL, "Ignoring global %d min. %s from %s%s%s for [%s%s%s]: too few non-wildcard characters", (int)((hold - now) / 60), stype, IsServer(source_p) ? source_p->name : get_oper_name(source_p), strcmp(parv[7], "*") ? " on behalf of " : "", strcmp(parv[7], "*") ? parv[7] : "", aconf->user ? aconf->user : "", aconf->user ? "@" : "", aconf->host); if(IsPerson(source_p)) sendto_one_notice(source_p, ":Your %s [%s%s%s] has too few non-wildcard characters", stype, aconf->user ? aconf->user : "", aconf->user ? "@" : "", aconf->host); /* Propagate it, but do not apply it locally. */ } else if (act && hold != created) { /* Keep the notices in sync with modules/m_kline.c etc. */ sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s added global %d min. %s%s%s for [%s%s%s] [%s]", IsServer(source_p) ? source_p->name : get_oper_name(source_p), (int)((hold - now) / 60), stype, strcmp(parv[7], "*") ? " from " : "", strcmp(parv[7], "*") ? parv[7] : "", aconf->user ? aconf->user : "", aconf->user ? "@" : "", aconf->host, parv[parc - 1]); ilog(L_KLINE, "%s %s %d %s%s%s %s", parv[1], IsServer(source_p) ? source_p->name : get_oper_name(source_p), (int)((hold - now) / 60), aconf->user ? aconf->user : "", aconf->user ? " " : "", aconf->host, parv[parc - 1]); aconf->status &= ~CONF_ILLEGAL; } else if (act) { sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s has removed the global %s for: [%s%s%s]%s%s", IsServer(source_p) ? source_p->name : get_oper_name(source_p), stype, aconf->user ? aconf->user : "", aconf->user ? "@" : "", aconf->host, strcmp(parv[7], "*") ? " on behalf of " : "", strcmp(parv[7], "*") ? parv[7] : ""); ilog(L_KLINE, "U%s %s %s%s %s", parv[1], IsServer(source_p) ? source_p->name : get_oper_name(source_p), aconf->user ? aconf->user : "", aconf->user ? " " : "", aconf->host); } /* If CONF_ILLEGAL is still set at this point, remove entries from the * reject cache (for klines and xlines). * If CONF_ILLEGAL is not set, add the ban to the type-specific data * structure and take action on matched clients/channels. */ switch (ntype) { case CONF_KILL: if (aconf->status & CONF_ILLEGAL) remove_reject_mask(aconf->user, aconf->host); else { add_conf_by_address(aconf->host, CONF_KILL, aconf->user, NULL, aconf); if(ConfigFileEntry.kline_delay || (IsServer(source_p) && !HasSentEob(source_p))) { if(kline_queued == 0) { rb_event_addonce("check_klines", check_klines_event, NULL, ConfigFileEntry.kline_delay ? ConfigFileEntry.kline_delay : 1); kline_queued = 1; } } else check_klines(); } break; case CONF_XLINE: if (aconf->status & CONF_ILLEGAL) remove_reject_mask(aconf->host, NULL); else { rb_dlinkAddAlloc(aconf, &xline_conf_list); check_xlines(); } break; case CONF_RESV_CHANNEL: if (!(aconf->status & CONF_ILLEGAL)) { add_to_resv_hash(aconf->host, aconf); resv_chan_forcepart(aconf->host, aconf->passwd, hold - now); } break; case CONF_RESV_NICK: if (!(aconf->status & CONF_ILLEGAL)) rb_dlinkAddAlloc(aconf, &resv_conf_list); break; } sendto_server(client_p, NULL, CAP_BAN|CAP_TS6, NOCAPS, ":%s BAN %s %s %s %s %s %s %s :%s", source_p->id, parv[1], parv[2], parv[3], parv[4], parv[5], parv[6], parv[7], parv[parc - 1]); return 0; }