Author: Isomer <isomer@coders.net>
[ircu2.10.12-pk.git] / ircd / s_user.c
index 39bb074375004b2f98bf7f1a1c421b24968ea570..1c93ad4188d816305b1f2b8766a4a7c926694266 100644 (file)
@@ -245,8 +245,7 @@ int hunt_server(int MustBeOper, struct Client *cptr, struct Client *sptr, char *
     }
     else if (!(acptr = find_match_server(parv[server])))
     {
-      sendto_one(sptr, err_str(ERR_NOSUCHSERVER),
-          me.name, parv[0], parv[server]);
+      send_reply(sptr, ERR_NOSUCHSERVER, parv[server]);
       return (HUNTED_NOSUCH);
     }
   }
@@ -258,7 +257,7 @@ int hunt_server(int MustBeOper, struct Client *cptr, struct Client *sptr, char *
 
   if (MustBeOper && !IsPrivileged(sptr))
   {
-    sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, sptr->name);
+    send_reply(sptr, ERR_NOPRIVILEGES);
     return HUNTED_NOSUCH;
   }
 
@@ -266,12 +265,58 @@ int hunt_server(int MustBeOper, struct Client *cptr, struct Client *sptr, char *
   parv[server] = y;
 
   assert(!IsServer(sptr));
-  sendto_one(acptr, command, NumNick(sptr), parv[1], parv[2], parv[3], parv[4],
+  /* XXX sendto_one used with explicit command; must be very careful */
+  sendto_one(acptr, command, NumNick(sptr), parv[1], parv[2], parv[3], parv[4], /* XXX hunt_server */
       parv[5], parv[6], parv[7], parv[8]);
 
   return (HUNTED_PASS);
 }
 
+int hunt_server_cmd(struct Client *from, const char *cmd, const char *tok,
+                   struct Client *one, int MustBeOper, const char *pattern,
+                   int server, int parc, char *parv[])
+{
+  struct Client *acptr;
+  char *to;
+
+  /* Assume it's me, if no server or an unregistered client */
+  if (parc <= server || EmptyString((to = parv[server])) || IsUnknown(from))
+    return (HUNTED_ISME);
+
+  /* Make sure it's a server */
+  if (MyUser(from)) {
+    /* Make sure it's a server */
+    if (!strchr(to, '*')) {
+      if (0 == (acptr = FindClient(to)))
+        return HUNTED_NOSUCH;
+
+      if (acptr->user)
+        acptr = acptr->user->server;
+    } else if (!(acptr = find_match_server(to))) {
+      send_reply(from, ERR_NOSUCHSERVER, to);
+      return (HUNTED_NOSUCH);
+    }
+  } else if (!(acptr = FindNServer(to)))
+    return (HUNTED_NOSUCH);        /* Server broke off in the meantime */
+
+  if (IsMe(acptr))
+    return (HUNTED_ISME);
+
+  if (MustBeOper && !IsPrivileged(from)) {
+    send_reply(from, ERR_NOPRIVILEGES);
+    return HUNTED_NOSUCH;
+  }
+
+  assert(!IsServer(from));
+
+  parv[server] = (char *) acptr; /* HACK! HACK! HACK! ARGH! */
+
+  sendcmdto_one(from, cmd, tok, acptr, pattern, parv[1], parv[2], parv[3],
+               parv[4], parv[5], parv[6], parv[7], parv[8]);
+
+  return (HUNTED_PASS);
+}
+
 /*
  * 'do_nick_name' ensures that the given parameter (nick) is really a proper
  * string for a nickname (note, the 'nick' may be modified in the process...)
@@ -362,7 +407,7 @@ static char *clean_user_id(char *dest, char *source, int tilde)
  *    nick from local user or kill him/her...
  */
 int register_user(struct Client *cptr, struct Client *sptr,
-                  const char *nick, char *username)
+                  const char *nick, char *username, struct Gline *agline)
 {
   struct ConfItem* aconf;
   char*            parv[3];
@@ -397,37 +442,38 @@ int register_user(struct Client *cptr, struct Client *sptr,
       case ACR_OK:
         break;
       case ACR_NO_AUTHORIZATION:
-        sendto_op_mask(SNO_UNAUTH, "Unauthorized connection from %s.",
-                       get_client_name(sptr, HIDE_IP));
+        sendto_opmask_butone(0, SNO_UNAUTH, "Unauthorized connection from %s.",
+                            get_client_name(sptr, HIDE_IP));
         ++ServerStats->is_ref;
         return exit_client(cptr, sptr, &me,
-            "No Authorization - use another server");
+                          "No Authorization - use another server");
       case ACR_TOO_MANY_IN_CLASS:
         if (CurrentTime - last_too_many1 >= (time_t) 60)
         {
           last_too_many1 = CurrentTime;
-          sendto_op_mask(SNO_TOOMANY, "Too many connections in class for %s.",
-                         get_client_name(sptr, HIDE_IP));
+          sendto_opmask_butone(0, SNO_TOOMANY, "Too many connections in "
+                              "class for %s.",
+                              get_client_name(sptr, HIDE_IP));
         }
         ++ServerStats->is_ref;
-        IPcheck_connect_fail(sptr->ip);
         return exit_client(cptr, sptr, &me,
-            "Sorry, your connection class is full - try again later or try another server");
+                          "Sorry, your connection class is full - try "
+                          "again later or try another server");
       case ACR_TOO_MANY_FROM_IP:
         if (CurrentTime - last_too_many2 >= (time_t) 60)
         {
           last_too_many2 = CurrentTime;
-          sendto_op_mask(SNO_TOOMANY, "Too many connections from same IP for %s.",
-                         get_client_name(sptr, HIDE_IP));
+          sendto_opmask_butone(0, SNO_TOOMANY, "Too many connections from "
+                              "same IP for %s.",
+                              get_client_name(sptr, HIDE_IP));
         }
         ++ServerStats->is_ref;
         return exit_client(cptr, sptr, &me,
-            "Too many connections from your host");
+                          "Too many connections from your host");
       case ACR_ALREADY_AUTHORIZED:
         /* Can this ever happen? */
       case ACR_BAD_SOCKET:
         ++ServerStats->is_ref;
-        IPcheck_connect_fail(sptr->ip);
         return exit_client(cptr, sptr, &me, "Unknown error -- Try again");
     }
     ircd_strncpy(user->host, sptr->sockhost, HOSTLEN);
@@ -443,14 +489,10 @@ int register_user(struct Client *cptr, struct Client *sptr,
 
     if (!EmptyString(aconf->passwd)
         && !(IsDigit(*aconf->passwd) && !aconf->passwd[1])
-#ifdef USEONE
-        && strcmp("ONE", aconf->passwd)
-#endif
         && strcmp(sptr->passwd, aconf->passwd))
     {
       ServerStats->is_ref++;
-      IPcheck_connect_fail(sptr->ip);
-      sendto_one(sptr, err_str(ERR_PASSWDMISMATCH), me.name, parv[0]);
+      send_reply(sptr, ERR_PASSWDMISMATCH);
       return exit_client(cptr, sptr, &me, "Bad Password");
     }
     memset(sptr->passwd, 0, sizeof(sptr->passwd));
@@ -459,7 +501,6 @@ int register_user(struct Client *cptr, struct Client *sptr,
      */
     if (find_kill(sptr)) {
       ServerStats->is_ref++;
-      IPcheck_connect_fail(sptr->ip);
       return exit_client(cptr, sptr, &me, "K-lined");
     }
     /*
@@ -530,14 +571,14 @@ int register_user(struct Client *cptr, struct Client *sptr,
         strcmp(sptr->username, username) != 0))
     {
       ServerStats->is_ref++;
-      sendto_one(cptr, ":%s %d %s :Your username is invalid.",
-                 me.name, ERR_INVALIDUSERNAME, cptr->name);
-      sendto_one(cptr,
-                 ":%s %d %s :Connect with your real username, in lowercase.",
-                 me.name, ERR_INVALIDUSERNAME, cptr->name);
-      sendto_one(cptr, ":%s %d %s :If your mail address were foo@bar.com, "
-                 "your username would be foo.",
-                 me.name, ERR_INVALIDUSERNAME, cptr->name);
+
+      send_reply(cptr, SND_EXPLICIT | ERR_INVALIDUSERNAME,
+                ":Your username is invalid.");
+      send_reply(cptr, SND_EXPLICIT | ERR_INVALIDUSERNAME,
+                ":Connect with your real username, in lowercase.");
+      send_reply(cptr, SND_EXPLICIT | ERR_INVALIDUSERNAME,
+                ":If your mail address were foo@bar.com, your username "
+                "would be foo.");
       return exit_client(cptr, sptr, &me, "USER: Bad username");
     }
     Count_unknownbecomesclient(sptr, UserStats);
@@ -548,6 +589,14 @@ int register_user(struct Client *cptr, struct Client *sptr,
   }
   SetUser(sptr);
 
+  /* a gline wasn't passed in, so find a matching global one that isn't
+   * a Uworld-set one, and propagate it if there is such an animal.
+   */
+  if (!agline &&
+      (agline = gline_lookup(sptr, GLINE_GLOBAL | GLINE_LASTMOD)) &&
+      !IsBurstOrBurstAck(cptr))
+    gline_resend(cptr, agline);
+  
   if (IsInvisible(sptr))
     ++UserStats.inv_clients;
   if (IsOper(sptr))
@@ -557,16 +606,15 @@ int register_user(struct Client *cptr, struct Client *sptr,
     sptr->handler = CLIENT_HANDLER;
     release_dns_reply(sptr);
 
-    sendto_one(sptr, rpl_str(RPL_WELCOME), me.name, nick, nick);
+    send_reply(sptr, RPL_WELCOME, nick);
     /*
      * This is a duplicate of the NOTICE but see below...
      */
-    sendto_one(sptr, rpl_str(RPL_YOURHOST), me.name, nick,
-               me.name, version);
-    sendto_one(sptr, rpl_str(RPL_CREATED), me.name, nick, creation);
-    sendto_one(sptr, rpl_str(RPL_MYINFO), me.name, parv[0], me.name, version);
+    send_reply(sptr, RPL_YOURHOST, me.name, version);
+    send_reply(sptr, RPL_CREATED, creation);
+    send_reply(sptr, RPL_MYINFO, me.name, version);
     sprintf_irc(featurebuf,FEATURES,FEATURESVALUES);
-    sendto_one(sptr, rpl_str(RPL_ISUPPORT), me.name, nick, featurebuf);
+    send_reply(sptr, RPL_ISUPPORT, featurebuf);
     m_lusers(sptr, sptr, 1, parv);
     update_load();
 #ifdef NODEFAULTMOTD
@@ -577,21 +625,7 @@ int register_user(struct Client *cptr, struct Client *sptr,
     nextping = CurrentTime;
     if (sptr->snomask & SNO_NOISY)
       set_snomask(sptr, sptr->snomask & SNO_NOISY, SNO_ADD);
-#ifdef ALLOW_SNO_CONNEXIT
-#ifdef SNO_CONNEXIT_IP
-    sprintf_irc(sendbuf,
-                ":%s NOTICE * :*** Notice -- Client connecting: %s (%s@%s) [%s] {%d}",
-                me.name, nick, user->username, user->host, cptr->sock_ip,
-                get_client_class(sptr));
-    sendbufto_op_mask(SNO_CONNEXIT);
-#else /* SNO_CONNEXIT_IP */
-    sprintf_irc(sendbuf,
-                ":%s NOTICE * :*** Notice -- Client connecting: %s (%s@%s)",
-                me.name, nick, user->username, user->host);
-    sendbufto_op_mask(SNO_CONNEXIT);
-#endif /* SNO_CONNEXIT_IP */
-#endif /* ALLOW_SNO_CONNEXIT */
-    IPcheck_connect_succeeded(sptr);
+    ip_registry_connect_succeeded(sptr);
   }
   else
     /* if (IsServer(cptr)) */
@@ -601,9 +635,9 @@ int register_user(struct Client *cptr, struct Client *sptr,
     acptr = user->server;
     if (acptr->from != sptr->from)
     {
-      sendto_one(cptr, "%s " TOK_KILL " %s%s :%s (%s != %s[%s])",
-                 NumServ(&me), NumNick(sptr), me.name, user->server->name,
-                 acptr->from->name, acptr->from->sockhost);
+      sendcmdto_one(&me, CMD_KILL, cptr, "%C :%s (%s != %s[%s])",
+                   sptr, me.name, user->server->name, acptr->from->name,
+                   acptr->from->sockhost);
       sptr->flags |= FLAGS_KILLED;
       return exit_client(cptr, sptr, &me, "NICK server wrong direction");
     }
@@ -620,29 +654,33 @@ int register_user(struct Client *cptr, struct Client *sptr,
       if (IsBurst(acptr) || Protocol(acptr) < 10)
         break;
     }
-    if (!IPcheck_remote_connect(sptr, (acptr != &me)))
-      /*
-       * We ran out of bits to count this
-       */
-      return exit_client(cptr, sptr, &me, "More than 255 connections from this address");
   }
-
   tmpstr = umode_str(sptr);
-  sendto_serv_butone(cptr, *tmpstr ?
-                     "%s " TOK_NICK " %s %d %d %s %s +%s %s %s%s :%s" :
-                     "%s " TOK_NICK " %s %d %d %s %s %s%s %s%s :%s",
-                     NumServ(user->server), nick, sptr->hopcount + 1, sptr->lastnick,
-                     user->username, user->host, tmpstr, 
-                     inttobase64(ip_base64, ntohl(sptr->ip.s_addr), 6),
-                     NumNick(sptr), sptr->info);
-
+  if (agline)
+    sendcmdto_serv_butone(user->server, CMD_NICK, cptr,
+                         "%s %d %Tu %s %s %s%s%s%%%Tu:%s@%s %s %s%s :%s",
+                         nick, sptr->hopcount + 1, sptr->lastnick,
+                         user->username, user->host,
+                         *tmpstr ? "+" : "", tmpstr, *tmpstr ? " " : "",
+                         GlineLastMod(agline), GlineUser(agline),
+                         GlineHost(agline),
+                         inttobase64(ip_base64, ntohl(sptr->ip.s_addr), 6),
+                         NumNick(sptr), sptr->info);
+  else
+    sendcmdto_serv_butone(user->server, CMD_NICK, cptr,
+                         "%s %d %Tu %s %s %s%s%s%s %s%s :%s",
+                         nick, sptr->hopcount + 1, sptr->lastnick,
+                         user->username, user->host,
+                         *tmpstr ? "+" : "", tmpstr, *tmpstr ? " " : "",
+                         inttobase64(ip_base64, ntohl(sptr->ip.s_addr), 6),
+                         NumNick(sptr), sptr->info);
+  
   /* Send umode to client */
   if (MyUser(sptr))
   {
     send_umode(cptr, sptr, 0, ALL_UMODES);
     if (sptr->snomask != SNO_DEFAULT && (sptr->flags & FLAGS_SERVNOTICE))
-      sendto_one(sptr, rpl_str(RPL_SNOMASK), me.name, sptr->name,
-                 sptr->snomask, sptr->snomask);
+      send_reply(sptr, RPL_SNOMASK, sptr->snomask, sptr->snomask);
   }
 
   return 0;
@@ -690,7 +728,8 @@ int set_nick_name(struct Client* cptr, struct Client* sptr,
   if (IsServer(sptr)) {
     int   i;
     const char* p;
-    struct Gline *gline;
+    char *t;
+    struct Gline *agline = 0;
 
     /*
      * A server introducing a new client, change source
@@ -729,9 +768,26 @@ int set_nick_name(struct Client* cptr, struct Client* sptr,
     ircd_strncpy(new_client->username, parv[4], USERLEN);
     ircd_strncpy(new_client->user->host, parv[5], HOSTLEN);
     ircd_strncpy(new_client->info, parv[parc - 1], REALLEN);
-    if ((gline = gline_lookup(new_client)) && GlineIsActive(gline))
-      gline_resend(cptr, gline);
-    return register_user(cptr, new_client, new_client->name, parv[4]);
+
+    /* Deal with GLINE parameters... */
+    if (*parv[parc - 4] == '%' && (t = strchr(parv[parc - 4] + 1, ':'))) {
+      time_t lastmod;
+
+      *(t++) = '\0';
+      lastmod = atoi(parv[parc - 4] + 1);
+
+      if (lastmod &&
+         (agline = gline_find(t, GLINE_EXACT | GLINE_GLOBAL | GLINE_LASTMOD))
+         && GlineLastMod(agline) > lastmod && !IsBurstOrBurstAck(cptr))
+       gline_resend(cptr, agline);
+    }
+    if (!ip_registry_remote_connect(new_client)) {
+       sendcmdto_one(&me, CMD_KILL, new_client, "%C :%s (Too many connections from your host -- Ghost)",
+                     new_client,me.name);
+       return exit_client(cptr,new_client,&me,"Too many connections from your host -- throttled");
+    }
+    sendto_ops("Registering new remote client");
+    return register_user(cptr, new_client, new_client->name, parv[4], agline);
   }
   else if (sptr->name[0]) {
     /*
@@ -744,9 +800,7 @@ int set_nick_name(struct Client* cptr, struct Client* sptr,
     if (MyUser(sptr)) {
       const char* channel_name;
       if ((channel_name = find_no_nickchange_channel(sptr))) {
-        sendto_one(cptr, err_str(ERR_BANNICKCHANGE), me.name, parv[0],
-                   channel_name);
-        return 0;
+       return send_reply(cptr, ERR_BANNICKCHANGE, channel_name);
       }
       /*
        * Refuse nick change if the last nick change was less
@@ -758,10 +812,10 @@ int set_nick_name(struct Client* cptr, struct Client* sptr,
        */
       if (CurrentTime < cptr->nextnick) {
         cptr->nextnick += 2;
-        sendto_one(cptr, err_str(ERR_NICKTOOFAST),
-            me.name, parv[0], parv[1], cptr->nextnick - CurrentTime);
+       send_reply(cptr, ERR_NICKTOOFAST, parv[1],
+                  cptr->nextnick - CurrentTime);
         /* Send error message */
-        sendto_prefix_one(cptr, cptr, ":%s NICK %s", parv[0], parv[0]);
+       sendcmdto_one(cptr, CMD_NICK, cptr, "%s", cptr->name);
         /* bounce NICK to user */
         return 0;                /* ignore nick change! */
       }
@@ -785,13 +839,13 @@ int set_nick_name(struct Client* cptr, struct Client* sptr,
      * on that channel. Propagate notice to other servers.
      */
     if (IsUser(sptr)) {
-      sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick);
+      sendcmdto_common_channels(sptr, CMD_NICK, ":%s", nick);
       add_history(sptr, 1);
-      sendto_serv_butone(cptr,
-          "%s%s " TOK_NICK " %s " TIME_T_FMT, NumNick(sptr), nick, sptr->lastnick);
+      sendcmdto_serv_butone(sptr, CMD_NICK, cptr, "%s %Tu", nick,
+                           sptr->lastnick);
     }
     else
-      sendto_one(sptr, ":%s NICK :%s", parv[0], nick);
+      sendcmdto_one(sptr, CMD_NICK, sptr, ":%s", nick);
 
     if (sptr->name[0])
       hRemClient(sptr);
@@ -817,7 +871,7 @@ int set_nick_name(struct Client* cptr, struct Client* sptr,
       do {
         sptr->cookie = (ircrandom() & 0x7fffffff);
       } while (!sptr->cookie);
-      sendto_one(cptr, "PING :%u", sptr->cookie);
+      sendrawto_one(cptr, MSG_PING " :%u", sptr->cookie);
     }
     else if (*sptr->user->host && sptr->cookie == COOKIE_VERIFIED) {
       /*
@@ -826,7 +880,7 @@ int set_nick_name(struct Client* cptr, struct Client* sptr,
        * for it - must test this and exit m_nick too !
        */
       sptr->lastnick = TStime();        /* Always local client */
-      if (register_user(cptr, sptr, nick, sptr->user->username) == CPTR_KILLED)
+      if (register_user(cptr, sptr, nick, sptr->user->username, 0) == CPTR_KILLED)
         return CPTR_KILLED;
     }
   }
@@ -910,14 +964,15 @@ int check_target_limit(struct Client *sptr, void *target, const char *name,
          * No server flooding
          */
         sptr->nexttarget += 2;
-        sendto_one(sptr, err_str(ERR_TARGETTOOFAST),
-                   me.name, sptr->name, name, sptr->nexttarget - CurrentTime);
+       send_reply(sptr, ERR_TARGETTOOFAST, name,
+                  sptr->nexttarget - CurrentTime);
       }
       return 1;
     }
     else {
 #ifdef GODMODE
-      sendto_one(sptr, ":%s NOTICE %s :New target: %s; ft " TIME_T_FMT,
+      /* XXX Let's get rid of GODMODE */
+      sendto_one(sptr, ":%s NOTICE %s :New target: %s; ft " TIME_T_FMT, /* XXX Possibly DEAD */
           me.name, sptr->name, name, (CurrentTime - sptr->nexttarget) / TARGET_DELAY);
 #endif
       sptr->nexttarget += TARGET_DELAY;
@@ -960,12 +1015,10 @@ int whisper(struct Client* source, const char* nick, const char* channel,
   assert(MyUser(source));
 
   if (!(dest = FindUser(nick))) {
-    sendto_one(source, err_str(ERR_NOSUCHNICK), me.name, source->name, nick);
-    return 0;
+    return send_reply(source, ERR_NOSUCHNICK, nick);
   }
   if (!(chptr = FindChannel(channel))) {
-    sendto_one(source, err_str(ERR_NOSUCHCHANNEL), me.name, source->name, channel);
-    return 0;
+    return send_reply(source, ERR_NOSUCHCHANNEL, channel);
   }
   /*
    * compare both users channel lists, instead of the channels user list
@@ -977,12 +1030,10 @@ int whisper(struct Client* source, const char* nick, const char* channel,
       break;
   }
   if (0 == membership) {
-    sendto_one(source, err_str(ERR_NOTONCHANNEL), me.name, source->name, chptr->chname);
-    return 0;
+    return send_reply(source, ERR_NOTONCHANNEL, chptr->chname);
   }
   if (!IsVoicedOrOpped(membership)) {
-    sendto_one(source, err_str(ERR_VOICENEEDED), me.name, source->name, chptr->chname);
-    return 0;
+    return send_reply(source, ERR_VOICENEEDED, chptr->chname);
   }
   /*
    * lookup channel in destination
@@ -993,24 +1044,17 @@ int whisper(struct Client* source, const char* nick, const char* channel,
       break;
   }
   if (0 == membership || IsZombie(membership)) {
-    sendto_one(source, err_str(ERR_USERNOTINCHANNEL), me.name, 
-               source->name, dest->name, chptr->chname);
-    return 0;
+    return send_reply(source, ERR_USERNOTINCHANNEL, dest->name, chptr->chname);
   }
   if (is_silenced(source, dest))
     return 0;
           
   if (dest->user->away)
-    sendto_one(source, rpl_str(RPL_AWAY), me.name, source->name,
-               dest->name, dest->user->away);
-  if (MyUser(dest))
-    sendto_prefix_one(dest, source, ":%s %s %s :%s",
-                      source->name, is_notice ? MSG_NOTICE : MSG_PRIVATE, 
-                      dest->name, text);
+    send_reply(source, RPL_AWAY, dest->name, dest->user->away);
+  if (is_notice)
+    sendcmdto_one(source, CMD_NOTICE, dest, "%C :%s", dest, text);
   else
-    sendto_one(dest, "%s%s %s %s%s :%s",
-               NumNick(source), is_notice ? TOK_NOTICE : TOK_PRIVATE, 
-               NumNick(dest), text);
+    sendcmdto_one(source, CMD_PRIVATE, dest, "%C :%s", dest, text);
   return 0;
 }
 
@@ -1028,7 +1072,7 @@ void send_umode_out(struct Client *cptr, struct Client *sptr, int old)
   for (i = HighestFd; i >= 0; i--) {
     if ((acptr = LocalClientArray[i]) && IsServer(acptr) &&
         (acptr != cptr) && (acptr != sptr) && *umodeBuf)
-      sendto_one(acptr, "%s%s " TOK_MODE " %s :%s", NumNick(sptr), sptr->name, umodeBuf);
+      sendcmdto_one(sptr, CMD_MODE, acptr, "%s :%s", sptr->name, umodeBuf);
   }
   if (cptr && MyUser(cptr))
     send_umode(cptr, sptr, old, ALL_UMODES);
@@ -1097,17 +1141,18 @@ int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv
   if (!(acptr = FindUser(parv[1])))
   {
     if (MyConnect(sptr))
-      sendto_one(sptr, err_str(ERR_NOSUCHCHANNEL), me.name, parv[0], parv[1]);
+      send_reply(sptr, ERR_NOSUCHCHANNEL, parv[1]);
     return 0;
   }
 
   if (IsServer(sptr) || sptr != acptr)
   {
     if (IsServer(cptr))
-      sendto_ops_butone(NULL, &me, ":%s WALLOPS :MODE for User %s From %s!%s",
-          me.name, parv[1], cptr->name, sptr->name);
+      sendcmdto_flag_butone(&me, CMD_WALLOPS, 0, FLAGS_WALLOP,
+                           ":MODE for User %s from %s!%s", parv[1],
+                           cptr->name, sptr->name);
     else
-      sendto_one(sptr, err_str(ERR_USERSDONTMATCH), me.name, parv[0]);
+      send_reply(sptr, ERR_USERSDONTMATCH);
     return 0;
   }
 
@@ -1120,12 +1165,11 @@ int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv
         *m++ = userModeList[i].c;
     }
     *m = '\0';
-    sendto_one(sptr, rpl_str(RPL_UMODEIS), me.name, parv[0], buf);
+    send_reply(sptr, RPL_UMODEIS, buf);
     if ((sptr->flags & FLAGS_SERVNOTICE) && MyConnect(sptr)
         && sptr->snomask !=
         (unsigned int)(IsOper(sptr) ? SNO_OPERDEFAULT : SNO_DEFAULT))
-      sendto_one(sptr, rpl_str(RPL_SNOMASK), me.name, parv[0], sptr->snomask,
-          sptr->snomask);
+      send_reply(sptr, RPL_SNOMASK, sptr->snomask, sptr->snomask);
     return 0;
   }
 
@@ -1269,8 +1313,7 @@ int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv
     if (tmpmask != sptr->snomask)
       set_snomask(sptr, tmpmask, SNO_SET);
     if (sptr->snomask && snomask_given)
-      sendto_one(sptr, rpl_str(RPL_SNOMASK), me.name, sptr->name,
-                 sptr->snomask, sptr->snomask);
+      send_reply(sptr, RPL_SNOMASK, sptr->snomask, sptr->snomask);
   }
 
   return 0;
@@ -1344,7 +1387,7 @@ void send_umode(struct Client *cptr, struct Client *sptr, int old, int sendmask)
   }
   *m = '\0';
   if (*umodeBuf && cptr)
-    sendto_one(cptr, ":%s MODE %s :%s", sptr->name, sptr->name, umodeBuf);
+    sendcmdto_one(sptr, CMD_MODE, cptr, "%s :%s", sptr->name, umodeBuf);
 }
 
 /*
@@ -1436,7 +1479,7 @@ void set_snomask(struct Client *cptr, unsigned int newmask, int what)
   else if (what == SNO_DEL)
     newmask = oldmask & ~newmask;
   else if (what != SNO_SET)        /* absolute set, no math needed */
-    sendto_ops("setsnomask called with %d ?!", what);
+    sendto_opmask_butone(0, SNO_OLDSNO, "setsnomask called with %d ?!", what);
 
   newmask &= (IsAnOper(cptr) ? SNO_ALL : SNO_USER);
 
@@ -1487,12 +1530,8 @@ int is_silenced(struct Client *sptr, struct Client *acptr)
     {
       if (!MyConnect(sptr))
       {
-        if (Protocol(sptr->from) < 10)
-          sendto_one(sptr->from, ":%s SILENCE %s %s", acptr->name,
-              sptr->name, lp->value.cp);
-        else
-          sendto_one(sptr->from, ":%s SILENCE %s%s %s", acptr->name,
-              NumNick(sptr), lp->value.cp);
+       sendcmdto_one(acptr, CMD_SILENCE, sptr->from, "%C %s", sptr,
+                     lp->value.cp);
       }
       return 1;
     }
@@ -1550,7 +1589,7 @@ int add_silence(struct Client* sptr, const char* mask)
       len += strlen(lp->value.cp);
       if ((len > MAXSILELENGTH) || (++cnt >= MAXSILES))
       {
-        sendto_one(sptr, err_str(ERR_SILELISTFULL), me.name, sptr->name, mask);
+       send_reply(sptr, ERR_SILELISTFULL, mask);
         return -1;
       }
       else if (!mmatch(lp->value.cp, mask))