/* ** m_ping ** parv[0] = sender prefix ** parv[1] = origin ** parv[2] = destination */ DLLFUNC int m_ping(aClient *cptr, aClient *sptr, int parc, char *parv[]) { aClient *acptr; char *origin, *destination; if (parc < 2 || *parv[1] == '\0') { sendto_one(sptr, err_str(ERR_NOORIGIN), me.name, parv[0]); return 0; } origin = parv[1]; destination = parv[2]; /* Will get NULL or pointer (parc >= 2!!) */ if (!MyClient(sptr)) { /* I've no idea who invented this or what it is supposed to do.. */ acptr = find_client(origin, NULL); if (!acptr) acptr = find_server_quick(origin); if (acptr && acptr != sptr) origin = cptr->name; } if (!BadPtr(destination) && mycmp(destination, me.name) != 0) { if (MyClient(sptr)) origin = sptr->name; /* Make sure origin is not spoofed */ if ((acptr = find_server_quick(destination)) && (acptr != &me)) sendto_one(acptr, ":%s PING %s :%s", parv[0], origin, destination); else { sendto_one(sptr, err_str(ERR_NOSUCHSERVER), me.name, parv[0], destination); return 0; } } else sendto_one(sptr, ":%s %s %s :%s", me.name, IsToken(cptr) ? TOK_PONG : MSG_PONG, (destination) ? destination : me.name, origin); return 0; }
/* ** m_pong ** parv[0] = sender prefix ** parv[1] = origin ** parv[2] = destination */ DLLFUNC int m_pong(aClient *cptr, aClient *sptr, int parc, char *parv[]) { aClient *acptr; char *origin, *destination; #ifdef NOSPOOF if (!IsRegistered(cptr)) return m_nospoof(cptr, sptr, parc, parv); #endif if (parc < 2 || *parv[1] == '\0') { sendto_one(sptr, err_str(ERR_NOORIGIN), me.name, parv[0]); return 0; } origin = parv[1]; destination = parv[2]; cptr->flags &= ~FLAGS_PINGSENT; sptr->flags &= ~FLAGS_PINGSENT; /* Remote pongs for clients? uhh... */ if (MyClient(sptr) || !IsRegistered(sptr)) destination = NULL; if (!BadPtr(destination) && mycmp(destination, me.name) != 0) { if ((acptr = find_client(destination, NULL)) || (acptr = find_server_quick(destination))) { if (!IsServer(cptr) && !IsServer(acptr)) { sendto_one(sptr, err_str(ERR_NOSUCHSERVER), me.name, parv[0], destination); return 0; } else sendto_one(acptr, ":%s PONG %s %s", parv[0], origin, destination); } else { sendto_one(sptr, err_str(ERR_NOSUCHSERVER), me.name, parv[0], destination); return 0; } } #ifdef DEBUGMODE else Debug((DEBUG_NOTICE, "PONG: %s %s", origin, destination ? destination : "*")); #endif return 0; }
/* ** m_whois ** parv[0] = sender prefix ** parv[1] = nickname masklist */ DLLFUNC int m_whois(aClient *cptr, aClient *sptr, int parc, char *parv[]) { Membership *lp; anUser *user; aClient *acptr, *a2cptr; aChannel *chptr; char *nick, *tmp, *name; char *p = NULL; int found, len, mlen, cnt = 0; char querybuf[BUFSIZE]; if (IsServer(sptr)) return 0; if (parc < 2) { sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN), me.name, parv[0]); return 0; } if (parc > 2) { if (hunt_server(cptr, sptr, ":%s WHOIS %s :%s", 1, parc, parv) != HUNTED_ISME) return 0; parv[1] = parv[2]; } strcpy(querybuf, parv[1]); for (tmp = canonize(parv[1]); (nick = strtok_r(tmp, ",", &p)); tmp = NULL) { unsigned char invis, showchannel, member, wilds, hideoper; /* <- these are all boolean-alike */ if (++cnt > MAXTARGETS) break; found = 0; /* We do not support "WHOIS *" */ wilds = (index(nick, '?') || index(nick, '*')); if (wilds) continue; if ((acptr = find_client(nick, NULL))) { if (IsServer(acptr)) continue; /* * I'm always last :-) and acptr->next == NULL!! */ if (IsMe(acptr)) break; /* * 'Rules' established for sending a WHOIS reply: * - only send replies about common or public channels * the target user(s) are on; */ if (!IsPerson(acptr)) continue; user = acptr->user; name = (!*acptr->name) ? "?" : acptr->name; invis = acptr != sptr && IsInvisible(acptr); member = (user->channel) ? 1 : 0; a2cptr = find_server_quick(user->server); hideoper = 0; if (IsHideOper(acptr) && (acptr != sptr) && !IsAnOper(sptr)) hideoper = 1; if (IsWhois(acptr) && (sptr != acptr)) { sendnotice(acptr, "*** %s (%s@%s) did a /whois on you.", sptr->name, sptr->user->username, sptr->user->realhost); } sendto_one(sptr, rpl_str(RPL_WHOISUSER), me.name, parv[0], name, user->username, IsHidden(acptr) ? user->virthost : user->realhost, acptr->info); if (IsOper(sptr) || acptr == sptr) { char sno[512]; strcpy(sno, get_sno_str(acptr)); /* send the target user's modes */ sendto_one(sptr, rpl_str(RPL_WHOISMODES), me.name, parv[0], name, get_mode_str(acptr), sno[1] == 0 ? "" : sno); } if ((acptr == sptr) || IsAnOper(sptr)) { sendto_one(sptr, rpl_str(RPL_WHOISHOST), me.name, parv[0], acptr->name, (MyConnect(acptr) && strcmp(acptr->username, "unknown")) ? acptr->username : "******", user->realhost, user->ip_str ? user->ip_str : ""); } if (IsARegNick(acptr)) sendto_one(sptr, rpl_str(RPL_WHOISREGNICK), me.name, parv[0], name); found = 1; mlen = strlen(me.name) + strlen(parv[0]) + 10 + strlen(name); for (len = 0, *buf = '\0', lp = user->channel; lp; lp = lp->next) { chptr = lp->chptr; showchannel = 0; if (ShowChannel(sptr, chptr)) showchannel = 1; if (OPCanSeeSecret(sptr)) showchannel = 1; if ((acptr->umodes & UMODE_HIDEWHOIS) && !IsMember(sptr, chptr) && !IsAnOper(sptr)) showchannel = 0; if (IsServices(acptr) && !IsNetAdmin(sptr) && !IsSAdmin(sptr)) showchannel = 0; if (acptr == sptr) showchannel = 1; /* Hey, if you are editting here... don't forget to change the webtv w_whois ;p. */ if (showchannel) { long access; if (len + strlen(chptr->chname) > (size_t)BUFSIZE - 4 - mlen) { sendto_one(sptr, ":%s %d %s %s :%s", me.name, RPL_WHOISCHANNELS, parv[0], name, buf); *buf = '\0'; len = 0; } #ifdef SHOW_SECRET if (IsAnOper(sptr) #else if (IsNetAdmin(sptr) #endif && SecretChannel(chptr) && !IsMember(sptr, chptr)) *(buf + len++) = '?'; if (acptr->umodes & UMODE_HIDEWHOIS && !IsMember(sptr, chptr) && IsAnOper(sptr)) *(buf + len++) = '!'; access = get_access(acptr, chptr); if (!SupportNAMESX(sptr)) { #ifdef PREFIX_AQ if (access & CHFL_CHANOWNER) *(buf + len++) = '~'; else if (access & CHFL_CHANPROT) *(buf + len++) = '&'; else #endif if (access & CHFL_CHANOP) *(buf + len++) = '@'; else if (access & CHFL_HALFOP) *(buf + len++) = '%'; else if (access & CHFL_VOICE) *(buf + len++) = '+'; } else { #ifdef PREFIX_AQ if (access & CHFL_CHANOWNER) *(buf + len++) = '~'; if (access & CHFL_CHANPROT) *(buf + len++) = '&'; #endif if (access & CHFL_CHANOP) *(buf + len++) = '@'; if (access & CHFL_HALFOP) *(buf + len++) = '%'; if (access & CHFL_VOICE) *(buf + len++) = '+'; } if (len) *(buf + len) = '\0'; (void)strcpy(buf + len, chptr->chname); len += strlen(chptr->chname); (void)strcat(buf + len, " "); len++; } } if (buf[0] != '\0') sendto_one(sptr, rpl_str(RPL_WHOISCHANNELS), me.name, parv[0], name, buf); if (!(IsULine(acptr) && !IsOper(sptr) && HIDE_ULINES)) sendto_one(sptr, rpl_str(RPL_WHOISSERVER), me.name, parv[0], name, user->server, a2cptr ? a2cptr->info : "*Not On This Net*"); if (user->away) sendto_one(sptr, rpl_str(RPL_AWAY), me.name, parv[0], name, user->away); /* makesure they aren't +H (we'll also check before we display a helpop or IRCD Coder msg) -- codemastr */ if ((IsAnOper(acptr) || IsServices(acptr)) && !hideoper) { buf[0] = '\0'; if (IsNetAdmin(acptr)) strlcat(buf, "a Network Administrator", sizeof buf); else if (IsSAdmin(acptr)) strlcat(buf, "a Services Administrator", sizeof buf); else if (IsAdmin(acptr) && !IsCoAdmin(acptr)) strlcat(buf, "a Server Administrator", sizeof buf); else if (IsCoAdmin(acptr)) strlcat(buf, "a Co Administrator", sizeof buf); else if (IsServices(acptr)) strlcat(buf, "a Network Service", sizeof buf); else if (IsOper(acptr)) strlcat(buf, "an IRC Operator", sizeof buf); else strlcat(buf, "a Local IRC Operator", sizeof buf); if (buf[0]) { if (IsOper(sptr) && MyClient(acptr)) sendto_one(sptr, ":%s 313 %s %s :is %s (%s)", me.name, parv[0], name, buf, acptr->user->operlogin); else sendto_one(sptr, rpl_str(RPL_WHOISOPERATOR), me.name, parv[0], name, buf); } } if (IsHelpOp(acptr) && !hideoper && !user->away) sendto_one(sptr, rpl_str(RPL_WHOISHELPOP), me.name, parv[0], name); if (acptr->umodes & UMODE_BOT) sendto_one(sptr, rpl_str(RPL_WHOISBOT), me.name, parv[0], name, ircnetwork); if (acptr->umodes & UMODE_SECURE) sendto_one(sptr, rpl_str(RPL_WHOISSECURE), me.name, parv[0], name, "is using a Secure Connection"); if (!BadPtr(user->swhois) && !hideoper) sendto_one(sptr, ":%s %d %s %s :%s", me.name, RPL_WHOISSPECIAL, parv[0], name, acptr->user->swhois); /* * display services account name if it's actually a services account name and * not a legacy timestamp. --nenolod */ if (!isdigit(*user->svid)) sendto_one(sptr, rpl_str(RPL_WHOISLOGGEDIN), me.name, parv[0], name, user->svid); /* * Umode +I hides an oper's idle time from regular users. * -Nath. */ if (MyConnect(acptr) && (IsAnOper(sptr) || !(acptr->umodes & UMODE_HIDLE))) { sendto_one(sptr, rpl_str(RPL_WHOISIDLE), me.name, parv[0], name, TStime() - acptr->last, acptr->firsttime); } } if (!found) sendto_one(sptr, err_str(ERR_NOSUCHNICK), me.name, parv[0], nick); } sendto_one(sptr, rpl_str(RPL_ENDOFWHOIS), me.name, parv[0], querybuf); return 0; }
/* ** DoNumeric (replacement for the old do_numeric) ** ** 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... */ int do_numeric(int numeric, aClient *cptr, aClient *sptr, int parc, char *parv[]) { aClient *acptr; aChannel *chptr; char *nick, *p; int i; /* Is this an outgoing connect, and we get a numeric 451 (not registered) back for the * magic command __PANGPANG__ and we did not send a SERVER message yet? * Then this means we are dealing with an Unreal server <3.2.9 and we should send the * SERVER command right now. */ if (!IsServer(sptr) && !IsPerson(sptr) && (numeric == 451) && (parc > 2) && strstr(parv[1], "__PANGPANG__") && IsHandshake(cptr) && sptr->serv && !IsServerSent(sptr)) { send_server_message(sptr); return 0; } if (parc < 1 || !IsServer(sptr)) return 0; /* Remap low number numerics. */ if (numeric < 100) numeric += 100; /* ** 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) ** Note: if buffer is non-empty, it will begin with SPACE. */ buffer[0] = '\0'; if (parc > 2) { /* * For strlcat nazis, please read above */ for (i = 2; i < (parc - 1); i++) { (void)strcat(buffer, " "); (void)strcat(buffer, parv[i]); } (void)strcat(buffer, " :"); (void)strcat(buffer, parv[parc - 1]); } else sendto_realops("do_numeric( %i, %s, %s, %i, { %s, %s } )!", numeric, cptr->name, sptr->name, parc, parv[0], parv[1] ? parv[1] : "<null>"); for (; (nick = strtoken(&p, parv[1], ",")); parv[1] = NULL) { if ((acptr = find_client(nick, (aClient *)NULL))) { /* ** Drop to bit bucket if for me... ** ...one might consider sendto_ops ** here... --msa ** And so it was done. -avalon ** And regretted. Dont do it that way. Make sure ** it goes only to non-servers. -avalon ** Check added to make sure servers don't try to loop ** with numerics which can happen with nick collisions. ** - Avalon */ if (!IsMe(acptr) && IsPerson(acptr)) { /* Added for .U3.2. drop remote 'You are not on ** that channel', we should be synced anyway, ** and this is an annoying message with TSpre7 ** still on the net; would result in numeric 442 for ** every KICK... Can be removed when TSpre7 is gone. ** --Run if (numeric==ERR_NOTONCHANNEL) return 0; */ sendto_prefix_one(acptr, sptr, ":%s %d %s%s", parv[0], numeric, nick, buffer); } else if (IsServer(acptr) && acptr->from != cptr) sendto_prefix_one(acptr, sptr, ":%s %d %s%s", parv[0], numeric, nick, buffer); } else if ((acptr = find_server_quick(nick))) { if (!IsMe(acptr) && acptr->from != cptr) sendto_prefix_one(acptr, sptr, ":%s %d %s%s", parv[0], numeric, nick, buffer); } else if ((chptr = find_channel(nick, (aChannel *)NULL))) sendto_channel_butone(cptr, sptr, chptr, ":%s %d %s%s", parv[0], numeric, chptr->chname, buffer); } return 0; }
/*********************************************************************** * m_connect() - Added by Jto 11 Feb 1989 ***********************************************************************//* ** m_connect ** parv[0] = sender prefix ** parv[1] = servername ** parv[2] = port number ** parv[3] = remote server */ DLLFUNC CMD_FUNC(m_connect) { int port, tmpport, retval; ConfigItem_link *aconf; ConfigItem_deny_link *deny; aClient *acptr; if (!IsPrivileged(sptr)) { sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); return -1; } if (MyClient(sptr) && !OPCanGRoute(sptr) && parc > 3) { /* Only allow LocOps to make */ /* local CONNECTS --SRB */ sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } if (MyClient(sptr) && !OPCanLRoute(sptr) && parc <= 3) { sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, parv[0]); return 0; } if (hunt_server_token(cptr, sptr, MSG_CONNECT, TOK_CONNECT, "%s %s :%s", 3, parc, parv) != HUNTED_ISME) return 0; if (parc < 2 || *parv[1] == '\0') { sendto_one(sptr, err_str(ERR_NEEDMOREPARAMS), me.name, parv[0], "CONNECT"); return -1; } if ((acptr = find_server_quick(parv[1]))) { sendto_one(sptr, ":%s %s %s :*** Connect: Server %s %s %s.", me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", parv[0], parv[1], "already exists from", acptr->from->name); return 0; } for (aconf = conf_link; aconf; aconf = (ConfigItem_link *) aconf->next) if (!match(parv[1], aconf->servername)) break; /* Checked first servernames, then try hostnames. */ if (!aconf) { sendto_one(sptr, ":%s %s %s :*** Connect: Server %s is not configured for linking", me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", parv[0], parv[1]); return 0; } /* ** Get port number from user, if given. If not specified, ** use the default form configuration structure. If missing ** from there, then use the precompiled default. */ tmpport = port = aconf->port; if (parc > 2 && !BadPtr(parv[2])) { if ((port = atoi(parv[2])) <= 0) { sendto_one(sptr, ":%s %s %s :*** Connect: Illegal port number", me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", parv[0]); return 0; } } else if (port <= 0 && (port = PORTNUM) <= 0) { sendto_one(sptr, ":%s %s %s :*** Connect: missing port number", me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", parv[0]); return 0; } /* Evaluate deny link */ for (deny = conf_deny_link; deny; deny = (ConfigItem_deny_link *) deny->next) { if (deny->flag.type == CRULE_ALL && !match(deny->mask, aconf->servername) && crule_eval(deny->rule)) { sendto_one(sptr, ":%s %s %s :*** Connect: Disallowed by connection rule", me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", parv[0]); return 0; } } if (strchr(aconf->hostname, '*') != NULL || strchr(aconf->hostname, '?') != NULL) { sendto_one(sptr, ":%s %s %s :*** Connect: You cannot connect to a server with wildcards (* and ?) in the hostname", me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", parv[0]); return 0; } /* ** Notify all operators about remote connect requests */ if (!IsAnOper(cptr)) { sendto_serv_butone(&me, ":%s GLOBOPS :Remote CONNECT %s %s from %s", me.name, parv[1], parv[2] ? parv[2] : "", get_client_name(sptr, FALSE)); } /* Interesting */ aconf->port = port; switch (retval = connect_server(aconf, sptr, NULL)) { case 0: sendto_one(sptr, ":%s %s %s :*** Connecting to %s[%s].", me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", parv[0], aconf->servername, aconf->hostname); break; case -1: sendto_one(sptr, ":%s %s %s :*** Couldn't connect to %s.", me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", parv[0], aconf->servername); break; case -2: sendto_one(sptr, ":%s %s %s :*** Resolving hostname '%s'...", me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", parv[0], aconf->hostname); break; default: sendto_one(sptr, ":%s %s %s :*** Connection to %s failed: %s", me.name, IsWebTV(sptr) ? "PRIVMSG" : "NOTICE", parv[0], aconf->servername, STRERROR(retval)); } aconf->port = tmpport; return 0; }