/** Find a ConfItem that has the same name and user+host fields as * specified. Requires an exact match for \a name. * @param name Name to match * @param cptr Client to match against * @param statmask Filter for ConfItem::status * @return First found matching ConfItem. */ struct ConfItem* find_conf_exact(const char* name, struct Client *cptr, int statmask) { struct ConfItem *tmp; for (tmp = GlobalConfList; tmp; tmp = tmp->next) { if (!(tmp->status & statmask) || !tmp->name || !tmp->host || 0 != ircd_strcmp(tmp->name, name)) continue; if (tmp->username && (EmptyString(cli_username(cptr)) || match(tmp->username, cli_username(cptr)))) continue; if (tmp->addrbits < 0) { if (match(tmp->host, cli_sockhost(cptr))) continue; } else if (!ipmask_check(&cli_ip(cptr), &tmp->address.addr, tmp->addrbits)) continue; if ((tmp->status & CONF_OPERATOR) && (MaxLinks(tmp->conn_class) > 0) && (tmp->clients >= MaxLinks(tmp->conn_class))) continue; return tmp; } return 0; }
/** Handle a RESTART message from a server connection. * * \a parv has the following elements: * \li \a parv[1] is the target server, or "*" for all. * \li \a parv[2] is either "cancel" or a time interval in seconds * \li \a parv[\a parc - 1] is the reason * * All fields must be present. Additionally, the time interval should * not be 0 for messages sent to "*", as that may not function * reliably due to buffering in the server. * * See @ref m_functions for discussion of the arguments. * @param[in] cptr Client that sent us the message. * @param[in] sptr Original source of message. * @param[in] parc Number of arguments. * @param[in] parv Argument vector. */ int ms_restart(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { const char *target, *when, *reason; if (parc < 4) return need_more_params(sptr, "RESTART"); target = parv[1]; when = parv[2]; reason = parv[parc - 1]; /* is it a message we should pay attention to? */ if (target[0] != '*' || target[1] != '\0') { if (hunt_server_cmd(sptr, CMD_RESTART, cptr, 0, "%C %s :%s", 1, parc, parv) != HUNTED_ISME) return 0; } else /* must forward the message */ sendcmdto_serv(sptr, CMD_RESTART, cptr, "* %s :%s", when, reason); /* OK, the message has been forwarded, but before we can act... */ if (!feature_bool(FEAT_NETWORK_RESTART)) return 0; /* is it a cancellation? */ if (!ircd_strcmp(when, "cancel")) exit_cancel(sptr); /* cancel a pending exit */ else /* schedule an exit */ exit_schedule(1, atoi(when), sptr, reason); return 0; }
static int pc_join(char *name) { patrolchannel *pc = NULL; channel *cp; for (pc = patrolchannels; pc; pc = pc->next) if (ircd_strcmp(pc->channel->content, name) == 0) return 0; cp = findchannel(name); if (!cp) return -1; pc = malloc(sizeof(patrolchannel)); pc->channel = getsstring(name, 512); pc->nick = NULL; pc->next = patrolchannels; patrolchannels = pc; pc_check(); return 0; }
/** Find a Z-line for a particular mask, guided by certain flags. * Certain bits in \a flags are interpreted specially: * <dl> * <dt>ZLINE_ANY</dt><dd>Search user Z-lines.</dd> * <dt>ZLINE_GLOBAL</dt><dd>Only match global Z-lines.</dd> * <dt>ZLINE_LOCAL</dt><dd>Only match local Z-lines.</dd> * <dt>ZLINE_LASTMOD</dt><dd>Only match Z-lines with a last modification time.</dd> * <dt>ZLINE_EXACT</dt><dd>Require an exact match of Z-line mask.</dd> * <dt>anything else</dt><dd>Search user Z-lines.</dd> * </dl> * @param[in] ipmask Mask to search for. * @param[in] flags Bitwise combination of ZLINE_* flags. * @return First matching Z-line, or NULL if none are found. */ struct Zline * zline_find(char *ipmask, unsigned int flags) { struct Zline *zline = 0; struct Zline *szline; char *mask, *t_uh; DupString(t_uh, ipmask); mask = t_uh; zliter(GlobalZlineList, zline, szline) { if ((flags & (ZlineIsLocal(zline) ? ZLINE_GLOBAL : ZLINE_LOCAL)) || (flags & ZLINE_LASTMOD && !zline->zl_lastmod)) continue; else if (flags & ZLINE_EXACT) { if (((zline->zl_mask && mask && ircd_strcmp(zline->zl_mask, mask) == 0) || (!zline->zl_mask && !mask))) break; } else { if (((zline->zl_mask && mask && match(zline->zl_mask, mask) == 0) || (!zline->zl_mask && !mask))) break; } } MyFree(t_uh); return zline; }
/* * ms_fakehost - fakehost server message handler * * parv[0] = sender prefix * parv[1] = target user numeric * parv[2] = target user's new fake host */ int ms_fakehost(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { struct Client *target; if (parc < 3) return need_more_params(sptr, "FAKEHOST"); /* Locate our target user; ignore the message if we can't */ if(!(target = findNUser(parv[1]))) return 0; /* Ignore the assignment if it changes nothing */ if (HasFakeHost(target) && ircd_strcmp(cli_user(target)->fakehost, parv[2]) == 0) { return 0; } /* Assign and propagate the fakehost */ SetFakeHost(target); ircd_strncpy(cli_user(target)->fakehost, parv[2], HOSTLEN); hide_hostmask(target); sendcmdto_serv_butone(sptr, CMD_FAKEHOST, cptr, "%C %s", target, cli_user(target)->fakehost); return 0; }
hchannel *hchannel_get_by_name(const char *cname) { hchannel *tmp = hchannels; for (;tmp;tmp=tmp->next) if (!ircd_strcmp(cname, tmp->real_channel->index->name->content)) return tmp; return NULL; }
hchanban *hchanban_get(hchannel* hchan, const char* banmask) { hchanban *ptr = hchanbans; for (;ptr;ptr = ptr->next) if (ptr->hchan == hchan && !ircd_strcmp(ptr->banmask->content, banmask)) return ptr; return NULL; }
host *findhost(const char *hostname) { host *hp; for (hp=hosttable[hosthash(hostname)];hp;hp=(host *)hp->next) { if (!ircd_strcmp(hostname,hp->name->content)) return hp; } return NULL; }
qab_user* qabot_getuser(const char* authname) { qab_user* u; for (u = qabot_users; u; u = u->next) if (!ircd_strcmp(u->authname, authname)) return u; return 0; }
static fakeuser *findfakeuserbynick(char *nick) { fakeuser *fake; for (fake = fakeuserlist; fake; fake = fake->next) if (!ircd_strcmp(nick, fake->nick)) return fake; return NULL; }
/* * unique_name_vector - create a unique vector of names from * a token separated list * list - [in] a token delimited null terminated character array * token - [in] the token to replace * vector - [out] vector of strings to be returned * size - [in] maximum number of elements to place in vector * Returns count of elements placed into the vector, if the list * is an empty string { '\0' } 0 is returned. * list, and vector must be non-null and size must be > 0 * Empty strings <token><token> are not placed in the vector or counted. * This function ignores all subsequent tokens when count == size * * NOTE: this function destroys it's input, do not use list after it * is passed to this function */ int unique_name_vector(char* list, char token, char** vector, int size) { int i; int count = 0; char* start = list; char* end; assert(0 != list); assert(0 != vector); assert(0 < size); /* * ignore spurious tokens */ while (token == *start) ++start; for (end = strchr(start, token); end; end = strchr(start, token)) { *end++ = '\0'; /* * ignore spurious tokens */ while (token == *end) ++end; for (i = 0; i < count; ++i) { if (0 == ircd_strcmp(vector[i], start)) break; } if (i == count) { vector[count++] = start; if (count == size) return count; } start = end; } if (*start) { for (i = 0; i < count; ++i) if (0 == ircd_strcmp(vector[i], start)) return count; vector[count++] = start; } return count; }
vsauthdata* versionscan_getauthbyauth(char* auth) { vsauthdata* v; for (v=vsauths; v; v=v->next) { if (!ircd_strcmp(v->account, auth)) { return v; } } return 0; }
unsigned char versionscan_getlevelbyauth(char* auth) { vsauthdata* v; for (v=vsauths; v; v=v->next) { if (!ircd_strcmp(v->account, auth)) { return v->flags; } } return 0; }
/** Find any existing quarantine for the named channel. * @param chname Channel name to search for. * @return Reason for channel's quarantine, or NULL if none exists. */ const char* find_quarantine(const char *chname) { struct qline *qline; for (qline = GlobalQuarantineList; qline; qline = qline->next) if (!ircd_strcmp(qline->chname, chname)) return qline->reason; return NULL; }
vspattern* versionscan_getpattern(char* pattern) { vspattern* v; for (v=vspatterns; v; v=v->next) { if (!ircd_strcmp(v->pattern, pattern)) { return v; } } return 0; }
/* * m_whowas - generic message handler * * parv[0] = sender prefix * parv[1] = nickname queried * parv[2] = maximum returned items (optional, default is unlimited) * parv[3] = remote server target (Opers only, max returned items 20) */ int m_whowas(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { struct Whowas *temp; int cur = 0; int max = -1, found = 0; char *p, *nick, *s; if (parc < 2) { send_reply(sptr, ERR_NONICKNAMEGIVEN); return 0; } if (parc > 2) max = atoi(parv[2]); if (parc > 3) if (hunt_server_cmd(sptr, CMD_WHOWAS, cptr, 1, "%s %s :%C", 3, parc, parv)) return 0; parv[1] = canonize(parv[1]); if (!MyConnect(sptr) && (max > 20)) max = 20; /* Set max replies at 20 */ for (s = parv[1]; (nick = ircd_strtok(&p, s, ",")); s = 0) { /* Search through bucket, finding all nicknames that match */ found = 0; for (temp = whowashash[hash_whowas_name(nick)]; temp; temp = temp->hnext) { if (0 == ircd_strcmp(nick, temp->name)) { send_reply(sptr, RPL_WHOWASUSER, temp->name, temp->username, temp->hostname, temp->realname); if (IsAnOper(sptr) && temp->realhost) send_reply(sptr, RPL_WHOISACTUALLY, temp->name, temp->username, temp->realhost, "<untracked>"); send_reply(sptr, RPL_WHOISSERVER, temp->name, (feature_bool(FEAT_HIS_WHOIS_SERVERNAME) && !IsOper(sptr)) ? feature_str(FEAT_HIS_SERVERNAME) : temp->servername, myctime(temp->logoff)); if (temp->away) send_reply(sptr, RPL_AWAY, temp->name, temp->away); cur++; found++; } if (max >= 0 && cur >= max) break; } if (!found) send_reply(sptr, ERR_WASNOSUCHNICK, nick); /* To keep parv[1] intact for ENDOFWHOWAS */ if (p) p[-1] = ','; } send_reply(sptr, RPL_ENDOFWHOWAS, parv[1]); return 0; }
/* * hSeekClient * New semantics: finds a client whose name is 'name' and whose * status is one of those marked in TMask, if can't find one * returns NULL. If it finds one moves it to the top of the list * and returns it. */ struct Client* hSeekClient(const char *name, int TMask) { HASHREGS hashv = strhash(name); struct Client *cptr = clientTable[hashv]; if (cptr) { if (0 == (cli_status(cptr) & TMask) || 0 != ircd_strcmp(name, cli_name(cptr))) { struct Client* prev; while (prev = cptr, cptr = cli_hnext(cptr)) { if ((cli_status(cptr) & TMask) && (0 == ircd_strcmp(name, cli_name(cptr)))) { cli_hnext(prev) = cli_hnext(cptr); cli_hnext(cptr) = clientTable[hashv]; clientTable[hashv] = cptr; break; } } } } return cptr; }
int find_mark(struct Client* sptr, const char* mark) { struct SLink *lp; for (lp = cli_marks(sptr); lp; lp = lp->next) { if (!ircd_strcmp(lp->value.cp, mark)) return 1; } return 0; }
/** Find a connection class by name. * @param[in] name Name of connection class to search for. * @param[in] extras If non-zero, include unreferenced classes. * @return Pointer to connection class structure (or NULL if none match). */ struct ConnectionClass* do_find_class(const char *name, int extras) { struct ConnectionClass *cltmp; for (cltmp = connClassList; cltmp; cltmp = cltmp->next) { if (!cltmp->valid && !extras) continue; if (!ircd_strcmp(ConClass(cltmp), name)) return cltmp; } return NULL; }
/* * isNickJuped() * Tells if a nick is juped (nonzero returned) or not (zero) */ int isNickJuped(const char *nick) { int pos; if (nick && *nick) { for (pos = strhash(nick); (pos &= JUPEHASHMASK), jupeTable[pos][0]; pos++) { if (0 == ircd_strcmp(nick, jupeTable[pos])) return 1; } } return 0; /* A bogus pointer is NOT a juped nick, right ? :) */ }
/* * hSeekChannel * New semantics: finds a channel whose name is 'name', * if can't find one returns NULL, if can find it moves * it to the top of the list and returns it. */ struct Channel* hSeekChannel(const char *name) { HASHREGS hashv = strhash(name); struct Channel *chptr = channelTable[hashv]; if (chptr) { if (0 != ircd_strcmp(name, chptr->chname)) { struct Channel* prev; while (prev = chptr, chptr = chptr->hnext) { if (0 == ircd_strcmp(name, chptr->chname)) { prev->hnext = chptr->hnext; chptr->hnext = channelTable[hashv]; channelTable[hashv] = chptr; break; } } } } return chptr; }
int versionscan_modecmd(void* sender, int cargc, char** cargv) { nick* np=(nick*)sender; int oldmode=versionscan_mode; if (cargc < 1) { sendnoticetouser(versionscan_nick, np, "Currently running in %s mode.", (versionscan_mode == VS_SCAN)?"SCAN":(versionscan_mode == VS_STAT)?"STATISTICS":"IDLE"); return CMD_OK; } if (!ircd_strcmp(cargv[0], "idle")) { versionscan_mode=VS_IDLE; sendnoticetouser(versionscan_nick, np, "Now operating in IDLE mode."); } else if (!ircd_strcmp(cargv[0], "scan")) { versionscan_mode=VS_SCAN; sendnoticetouser(versionscan_nick, np, "Now operating in SCAN mode."); } else if (!ircd_strcmp(cargv[0], "stat")) { versionscan_mode=VS_STAT; sendnoticetouser(versionscan_nick, np, "Now operating in STATISTICS mode."); } else { sendnoticetouser(versionscan_nick, np, "Invalid mode of operation."); return CMD_ERROR; } if (oldmode == VS_STAT) { vsstatistic* v, *nv; for (v=vsstats; v;) { nv=v->next; free(v->reply); free(v); v=nv; } vsstats=0; } return CMD_OK; }
int csa_doaddchan(void *source, int cargc, char **cargv) { nick *sender=(nick *)source; reguser *rup = getreguserfromnick(sender), *founder; chanindex *cip; short type; regchan *rcp; if(cargc<3) { controlreply(sender, "ADDCHAN FALSE args"); return CMD_ERROR; } if (*cargv[0] != '#' || strlen(cargv[0]) > CHANNELLEN) { controlreply(sender, "ADDCHAN FALSE invalidchannel"); return CMD_ERROR; } if (!(cip=findorcreatechanindex(cargv[0]))) { controlreply(sender, "ADDCHAN FALSE invalidchannel"); return CMD_ERROR; } founder = findreguserbyID(atoi(cargv[1])); if(founder == NULL) { controlreply(sender, "ADDCHAN FALSE useridnotexist"); return CMD_ERROR; } if(UIsInactive(founder)) { controlreply(sender, "ADDCHAN FALSE accountinactive"); return CMD_ERROR; } for(type=CHANTYPES-1;type;type--) if(!ircd_strcmp(chantypes[type]->content, cargv[2])) break; if(!type) { controlreply(sender, "ADDCHAN FALSE invalidchantype"); return CMD_ERROR; } rcp = cs_addchan(cip, sender, rup, founder, QCFLAG_JOINED | QCFLAG_AUTOOP | QCFLAG_BITCH | QCFLAG_FORCETOPIC | QCFLAG_PROTECT | QCFLAG_TOPICSAVE, CHANMODE_NOCTCP | CHANMODE_DELJOINS | CHANMODE_MODNOAUTH | CHANMODE_NONOTICE | CHANMODE_NOEXTMSG | CHANMODE_SINGLETARG | CHANMODE_TOPICLIMIT | CHANMODE_NOQUITMSG, 0, type); if(!rcp) { controlreply(sender, "ADDCHAN FALSE alreadyregistered"); return CMD_ERROR; } cs_log(sender, "ADDCHAN %s #%s %s %s", cip->name->content, founder->username, printflags(rcp->flags, rcflags), chantypes[type]->content); controlreply(sender, "ADDCHAN TRUE %u", rcp->ID); return CMD_OK; }
int verify_sslclifp(struct Client* cptr, struct ConfItem* aconf) { if (!(aconf->sslfp)) return 1; if (!cli_sslclifp(cptr)) return 0; if (ircd_strcmp(aconf->sslfp, cli_sslclifp(cptr)) != 0) return 0; return 1; }
/* * ms_ping - server message handler */ int ms_ping(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { struct Client* acptr; char* origin; char* destination; assert(0 != cptr); assert(0 != sptr); assert(IsServer(cptr)); if (parc < 2 || EmptyString(parv[1])) { /* * don't bother sending the error back */ return 0; } origin = parv[1]; destination = parv[2]; /* Will get NULL or pointer (parc >= 2!!) */ if (parc > 3) { /* AsLL ping, send reply back */ int diff = atoi(militime_float(parv[3])); sendcmdto_one(&me, CMD_PONG, sptr, "%C %s %s %i %s", &me, origin, parv[3], diff, militime_float(NULL)); return 0; } if (!EmptyString(destination) && 0 != ircd_strcmp(destination, cli_name(&me))) { if ((acptr = FindServer(destination))) { /* * Servers can just forward the origin */ sendcmdto_one(sptr, CMD_PING, acptr, "%s :%s", origin, destination); } else { /* * this can happen if server split before the ping got here */ send_reply(sptr, ERR_NOSUCHSERVER, destination); } } else { /* * send pong back * NOTE: sptr is never local so if pong handles numerics everywhere we * could send a numeric here. */ sendcmdto_one(&me, CMD_PONG, sptr, "%C :%s", &me, origin); } return 0; }
/** Find a jupe by name. * @param[in] server %Jupe name to search for. * @return Matching jupe (or NULL if none match). */ struct Jupe * jupe_find(char *server) { struct Jupe* jupe; struct Jupe* sjupe; for (jupe = GlobalJupeList; jupe; jupe = sjupe) { /* go through jupes */ sjupe = jupe->ju_next; if (jupe->ju_expire <= CurrentTime) /* expire any that need expiring */ jupe_free(jupe); else if (0 == ircd_strcmp(server, jupe->ju_server)) /* found it yet? */ return jupe; } return 0; }
/** Look up a struct LogType given the type string. * @param[in] from &Client requesting type, or NULL. * @param[in] type Name of log type to find. * @return Pointer to the found LogType, or NULL if none was found. */ static struct LogTypes * feature_log_desc(struct Client* from, const char *type) { int i; assert(0 != type); for (i = 0; logTypes[i].type; i++) /* find appropriate descriptor */ if (!ircd_strcmp(type, logTypes[i].type)) return &logTypes[i]; Debug((DEBUG_ERROR, "Unknown log feature type \"%s\"", type)); if (from) /* send an error; if from is NULL, called from conf parser */ send_reply(from, ERR_BADLOGTYPE, type); else log_write(LS_CONFIG, L_ERROR, 0, "Unknown log feature type \"%s\"", type); return 0; /* not found */ }
/* * ms_pong - server message handler * * parv[0] = sender prefix * parv[1] = origin * parv[2] = destination */ int ms_pong(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { char* origin; char* destination; assert(0 != cptr); assert(0 != sptr); assert(IsServer(cptr)); if (parc < 2 || EmptyString(parv[1])) { return protocol_violation(sptr,"No Origin on PONG"); } origin = parv[1]; destination = parv[2]; ClearPingSent(cptr); ClearPingSent(sptr); cli_lasttime(cptr) = CurrentTime; if (parc > 5) { /* AsLL pong */ cli_serv(cptr)->asll_rtt = atoi(militime_float(parv[3])); cli_serv(cptr)->asll_to = atoi(parv[4]); cli_serv(cptr)->asll_from = atoi(militime_float(parv[5])); cli_serv(cptr)->asll_last = CurrentTime; return 0; } if (EmptyString(destination)) return 0; if (*destination == '!') { /* AsLL ping reply from a non-AsLL server */ cli_serv(cptr)->asll_rtt = atoi(militime_float(destination + 1)); } else if (0 != ircd_strcmp(destination, cli_name(&me))) { struct Client* acptr; if ((acptr = FindClient(destination))) sendcmdto_one(sptr, CMD_PONG, acptr, "%s %s", origin, destination); } return 0; }
static int crule_parsefunction(CRuleNodePtr* funcrootp, int* next_tokp, const char** ruleptr) { int errcode = CR_NOERR; char funcname[CR_MAXARGLEN]; int namelen; int funcnum; *funcrootp = NULL; crule_getword(funcname, &namelen, CR_MAXARGLEN - 1, ruleptr); if ((errcode = crule_gettoken(next_tokp, ruleptr)) != CR_NOERR) return (errcode); if (*next_tokp == CR_OPENPAREN) { for (funcnum = 0;; funcnum++) { if (0 == ircd_strcmp(crule_funclist[funcnum].name, funcname)) break; if (crule_funclist[funcnum].name[0] == '\0') return (CR_UNKNWFUNC); } if ((errcode = crule_gettoken(next_tokp, ruleptr)) != CR_NOERR) return (errcode); *funcrootp = (CRuleNodePtr) MyMalloc(sizeof(struct CRuleNode)); #ifdef CR_DEBUG fprintf(stderr, "allocating function element at %ld\n", *funcrootp); #endif (*funcrootp)->funcptr = NULL; /* for freeing aborted trees */ if ((errcode = crule_parsearglist(*funcrootp, next_tokp, ruleptr)) != CR_NOERR) return (errcode); if (*next_tokp != CR_CLOSEPAREN) return (CR_EXPCTCLOSE); if ((crule_funclist[funcnum].reqnumargs != (*funcrootp)->numargs) && (crule_funclist[funcnum].reqnumargs != -1)) return (CR_ARGMISMAT); if ((errcode = crule_gettoken(next_tokp, ruleptr)) != CR_NOERR) return (errcode); (*funcrootp)->funcptr = crule_funclist[funcnum].funcptr; return (CR_NOERR); } else return (CR_EXPCTOPEN); }
void versionscan_delpattern(char* pattern) { vspattern* v, *pv; pv=0; for (v=vspatterns; v; v=v->next) { if (!ircd_strcmp(v->pattern, pattern)) { if (pv) { pv->next=v->next; free(v); } else { vspatterns=v->next; free(v); } return; } pv=v; } }