]> jfr.im git - solanum.git/blobdiff - ircd/s_user.c
Support more human friendly k/d/x-line duration format
[solanum.git] / ircd / s_user.c
index 4ac4741e68cd7a629b3d292f78b733d30c09ea97..d758b537c2d9f628522f2031704f40bd420df302 100644 (file)
@@ -81,7 +81,7 @@ int user_modes[256] = {
        0,                      /* O */
        0,                      /* P */
        UMODE_NOFORWARD,        /* Q */
-       UMODE_REGONLYMSG,       /* R */
+       0,                      /* R */
        UMODE_SERVICE,          /* S */
        0,                      /* T */
        0,                      /* U */
@@ -89,7 +89,7 @@ int user_modes[256] = {
        0,                      /* W */
        0,                      /* X */
        0,                      /* Y */
-       UMODE_SSLCLIENT,        /* Z */
+       UMODE_SECURE,           /* Z */
        /* 0x5B */ 0, 0, 0, 0, 0, 0, /* 0x60 */
        UMODE_ADMIN,            /* a */
        0,                      /* b */
@@ -97,7 +97,7 @@ int user_modes[256] = {
        0,                      /* d */
        0,                      /* e */
        0,                      /* f */
-       UMODE_CALLERID,         /* g */
+       0,                      /* g */
        0,                      /* h */
        UMODE_INVISIBLE,        /* i */
        0,                      /* j */
@@ -213,25 +213,25 @@ authd_check(struct Client *client_p, struct Client *source_p)
 
        switch(source_p->preClient->auth.cause)
        {
-       case 'B':       /* Blacklists */
+       case 'B':       /* DNSBL */
                {
-                       struct BlacklistStats *stats;
-                       char *blacklist = source_p->preClient->auth.data;
+                       struct DNSBLEntryStats *stats;
+                       char *dnsbl_name = source_p->preClient->auth.data;
 
-                       if(bl_stats != NULL)
-                               if((stats = rb_dictionary_retrieve(bl_stats, blacklist)) != NULL)
+                       if(dnsbl_stats != NULL)
+                               if((stats = rb_dictionary_retrieve(dnsbl_stats, dnsbl_name)) != NULL)
                                        stats->hits++;
 
                        if(IsExemptKline(source_p) || IsConfExemptDNSBL(aconf))
                        {
                                sendto_one_notice(source_p, ":*** Your IP address %s is listed in %s, but you are exempt",
-                                               source_p->sockhost, blacklist);
+                                               source_p->sockhost, dnsbl_name);
                                break;
                        }
 
                        sendto_realops_snomask(SNO_REJ, L_NETWIDE,
                                "Listed on DNSBL %s: %s (%s@%s) [%s] [%s]",
-                               blacklist, source_p->name, source_p->username, source_p->host,
+                               dnsbl_name, source_p->name, source_p->username, source_p->host,
                                IsIPSpoof(source_p) ? "255.255.255.255" : source_p->sockhost,
                                source_p->info);
 
@@ -239,9 +239,9 @@ authd_check(struct Client *client_p, struct Client *source_p)
                                me.name, source_p->name, reason);
 
                        sendto_one_notice(source_p, ":*** Your IP address %s is listed in %s",
-                               source_p->sockhost, blacklist);
-                       add_reject(source_p, NULL, NULL);
-                       exit_client(client_p, source_p, &me, "Banned (DNS blacklist)");
+                               source_p->sockhost, dnsbl_name);
+                       add_reject(source_p, NULL, NULL, NULL, "Banned (listed in a DNSBL)");
+                       exit_client(client_p, source_p, &me, "Banned (listed in a DNSBL)");
                        reject = true;
                }
                break;
@@ -254,7 +254,7 @@ authd_check(struct Client *client_p, struct Client *source_p)
                        {
                                /* This shouldn't happen, better tell the ops... */
                                ierror("authd sent us a malformed OPM string %s", proxy);
-                               sendto_realops_snomask(SNO_GENERAL, L_ALL,
+                               sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                        "authd sent us a malformed OPM string %s", proxy);
                                break;
                        }
@@ -283,7 +283,7 @@ authd_check(struct Client *client_p, struct Client *source_p)
                        sendto_one_notice(source_p,
                                ":*** Your IP address %s has been detected as an open proxy (type %s, port %s)",
                                source_p->sockhost, proxy, port);
-                       add_reject(source_p, NULL, NULL);
+                       add_reject(source_p, NULL, NULL, NULL, "Banned (Open proxy)");
                        exit_client(client_p, source_p, &me, "Banned (Open proxy)");
                        reject = true;
                }
@@ -307,7 +307,7 @@ authd_check(struct Client *client_p, struct Client *source_p)
 
                sendto_one_notice(source_p, ":*** Rejected by authentication system: %s",
                        reason);
-               add_reject(source_p, NULL, NULL);
+               add_reject(source_p, NULL, NULL, NULL, "Banned (authentication system)");
                exit_client(client_p, source_p, &me, "Banned (authentication system)");
                reject = true;
                break;
@@ -351,7 +351,7 @@ register_local_user(struct Client *client_p, struct Client *source_p)
        char tmpstr2[BUFSIZE];
        char ipaddr[HOSTIPLEN];
        char myusername[USERLEN+1];
-       int status;
+       int status, umodes;
 
        s_assert(NULL != source_p);
        s_assert(MyConnect(source_p));
@@ -386,7 +386,9 @@ register_local_user(struct Client *client_p, struct Client *source_p)
        if(source_p->preClient->auth.cid)
                return -1;
 
-       client_p->localClient->last = rb_current_time();
+       /* Set firsttime here so that post_registration_delay works from registration,
+        * rather than initial connection.  */
+       source_p->localClient->firsttime = client_p->localClient->last = rb_current_time();
 
        /* XXX - fixme. we shouldnt have to build a users buffer twice.. */
        if(!IsGotId(source_p) && (strchr(source_p->username, '[') != NULL))
@@ -426,7 +428,12 @@ register_local_user(struct Client *client_p, struct Client *source_p)
 
        if(!valid_hostname(source_p->host))
        {
-               sendto_one_notice(source_p, ":*** Notice -- You have an illegal character in your hostname");
+               const char *illegal_hostname_client_message = ConfigFileEntry.illegal_hostname_client_message;
+
+               if (illegal_hostname_client_message == NULL)
+                       illegal_hostname_client_message = "You have an illegal character in your hostname.";
+
+               sendto_one_notice(source_p, ":*** Notice -- %s", illegal_hostname_client_message);
 
                rb_strlcpy(source_p->host, source_p->sockhost, sizeof(source_p->host));
        }
@@ -435,23 +442,40 @@ register_local_user(struct Client *client_p, struct Client *source_p)
 
        if(aconf == NULL)
        {
-               exit_client(client_p, source_p, &me, "*** Not Authorised");
+               const char *not_authorised_client_message = ConfigFileEntry.not_authorised_client_message;
+
+               if (not_authorised_client_message == NULL)
+                       not_authorised_client_message = "You are not authorised to access this server.";
+
+               exit_client(client_p, source_p, &me, not_authorised_client_message);
                return (CLIENT_EXITED);
        }
 
-       if(IsConfSSLNeeded(aconf) && !IsSSL(source_p))
+       if(IsConfSSLNeeded(aconf) && !IsSecure(source_p))
        {
+               const char *ssltls_only_client_message = ConfigFileEntry.ssltls_only_client_message;
+
+               if (ssltls_only_client_message == NULL)
+                       ssltls_only_client_message = "You need to use SSL/TLS to use this server.";
+
                ServerStats.is_ref++;
-               sendto_one_notice(source_p, ":*** Notice -- You need to use SSL/TLS to use this server");
-               exit_client(client_p, source_p, &me, "Use SSL/TLS");
+               sendto_one_notice(source_p, ":*** Notice -- %s", ssltls_only_client_message);
+
+               exit_client(client_p, source_p, &me, ssltls_only_client_message);
                return (CLIENT_EXITED);
        }
 
        if(IsSCTP(source_p) && !IsConfAllowSCTP(aconf))
        {
+               const char *sctp_forbidden_client_message = ConfigFileEntry.sctp_forbidden_client_message;
+
+               if (sctp_forbidden_client_message == NULL)
+                       sctp_forbidden_client_message = "You are not allowed to use SCTP on this server.";
+
                ServerStats.is_ref++;
-               sendto_one_notice(source_p, ":*** Notice -- You are not allowed to use SCTP on this server");
-               exit_client(client_p, source_p, &me, "SCTP not allowed");
+               sendto_one_notice(source_p, ":*** Notice -- %s", sctp_forbidden_client_message);
+
+               exit_client(client_p, source_p, &me, sctp_forbidden_client_message);
                return (CLIENT_EXITED);
        }
 
@@ -462,9 +486,16 @@ register_local_user(struct Client *client_p, struct Client *source_p)
 
                if(IsNeedIdentd(aconf))
                {
+
+                       const char *identd_only_client_message = ConfigFileEntry.identd_only_client_message;
+
+                       if (identd_only_client_message == NULL)
+                               identd_only_client_message = "You need to install identd to use this server.";
+
                        ServerStats.is_ref++;
-                       sendto_one_notice(source_p, ":*** Notice -- You need to install identd to use this server");
-                       exit_client(client_p, source_p, &me, "Install identd");
+                       sendto_one_notice(source_p, ":*** Notice -- %s", identd_only_client_message);
+
+                       exit_client(client_p, source_p, &me, identd_only_client_message);
                        return (CLIENT_EXITED);
                }
 
@@ -489,9 +520,16 @@ register_local_user(struct Client *client_p, struct Client *source_p)
 
        if(IsNeedSasl(aconf) && !*source_p->user->suser)
        {
+
+               const char *sasl_only_client_message = ConfigFileEntry.sasl_only_client_message;
+
+               if (sasl_only_client_message == NULL)
+                       sasl_only_client_message = "You need to identify via SASL to use this server.";
+
                ServerStats.is_ref++;
-               sendto_one_notice(source_p, ":*** Notice -- You need to identify via SASL to use this server");
-               exit_client(client_p, source_p, &me, "SASL access only");
+               sendto_one_notice(source_p, ":*** Notice -- %s", sasl_only_client_message);
+
+               exit_client(client_p, source_p, &me, sasl_only_client_message);
                return (CLIENT_EXITED);
        }
 
@@ -540,11 +578,16 @@ register_local_user(struct Client *client_p, struct Client *source_p)
        if(rb_dlink_list_length(&lclient_list) >=
            (unsigned long)GlobalSetOptions.maxclients && !IsConfExemptLimits(aconf))
        {
-               sendto_realops_snomask(SNO_FULL, L_ALL,
+               sendto_realops_snomask(SNO_FULL, L_NETWIDE,
                                     "Too many clients, rejecting %s[%s].", source_p->name, source_p->host);
 
+               const char *server_full_client_message = ConfigFileEntry.server_full_client_message;
+
+               if (server_full_client_message == NULL)
+                       server_full_client_message = "Sorry, server is full - try later";
+
                ServerStats.is_ref++;
-               exit_client(client_p, source_p, &me, "Sorry, server is full - try later");
+               exit_client(client_p, source_p, &me, server_full_client_message);
                return (CLIENT_EXITED);
        }
 
@@ -553,7 +596,11 @@ register_local_user(struct Client *client_p, struct Client *source_p)
           (xconf = find_xline(source_p->info, 1)) != NULL)
        {
                ServerStats.is_ref++;
-               add_reject(source_p, xconf->host, NULL);
+               sendto_realops_snomask(SNO_BANNED, L_NETWIDE,
+                       "Rejecting X-Lined user %s [%s] (%s)", get_client_name(source_p, HIDE_IP),
+                       show_ip(NULL, source_p) ? source_p->sockhost : "255.255.255.255", xconf->host);
+
+               add_reject(source_p, xconf->host, NULL, NULL, NULL);
                exit_client(client_p, source_p, &me, "Bad user info");
                return CLIENT_EXITED;
        }
@@ -566,13 +613,22 @@ register_local_user(struct Client *client_p, struct Client *source_p)
 
        if(!valid_username(source_p->username))
        {
-               sendto_realops_snomask(SNO_REJ, L_ALL,
+               sendto_realops_snomask(SNO_REJ, L_NETWIDE,
                                     "Invalid username: %s (%s@%s)",
                                     source_p->name, source_p->username, source_p->host);
+
+               const char *illegal_name_long_client_message = ConfigFileEntry.illegal_name_long_client_message;
+               const char *illegal_name_short_client_message = ConfigFileEntry.illegal_name_short_client_message;
+
+               if (illegal_name_long_client_message == NULL)
+                       illegal_name_long_client_message = "Your username is invalid. Please make sure that your username contains "
+                                                                                          "only alphanumeric characters.";
+               if (illegal_name_short_client_message == NULL)
+                       illegal_name_short_client_message = "Invalid username";
+
                ServerStats.is_ref++;
-               sendto_one_notice(source_p, ":*** Your username is invalid. Please make sure that your username contains "
-                                           "only alphanumeric characters.");
-               sprintf(tmpstr2, "Invalid username [%s]", source_p->username);
+               sendto_one_notice(source_p, ":*** %s", illegal_name_long_client_message);
+               sprintf(tmpstr2, "%s [%s]", illegal_name_short_client_message, source_p->username);
                exit_client(client_p, source_p, &me, tmpstr2);
                return (CLIENT_EXITED);
        }
@@ -592,7 +648,11 @@ register_local_user(struct Client *client_p, struct Client *source_p)
                        SetDynSpoof(source_p);
        }
 
-       source_p->umodes |= ConfigFileEntry.default_umodes & ~ConfigFileEntry.oper_only_umodes & ~orphaned_umodes;
+       umodes = ConfigFileEntry.default_umodes & ~aconf->umodes_mask;
+       umodes |= aconf->umodes;
+       umodes &= ~ConfigFileEntry.oper_only_umodes;
+       umodes &= ~orphaned_umodes;
+       source_p->umodes |= umodes;
 
        call_hook(h_new_local_user, source_p);
 
@@ -607,18 +667,21 @@ register_local_user(struct Client *client_p, struct Client *source_p)
        rb_inet_ntop_sock((struct sockaddr *)&source_p->localClient->ip, ipaddr, sizeof(ipaddr));
 
        sendto_realops_snomask(SNO_CCONN, L_ALL,
-                            "Client connecting: %s (%s@%s) [%s] {%s} [%s]",
+                            "Client connecting: %s (%s@%s) [%s] {%s} <%s> [%s]",
                             source_p->name, source_p->username, source_p->orighost,
                             show_ip(NULL, source_p) ? ipaddr : "255.255.255.255",
-                            get_client_class(source_p), source_p->info);
+                            get_client_class(source_p),
+                            *source_p->user->suser ? source_p->user->suser : "*",
+                            source_p->info);
 
        sendto_realops_snomask(SNO_CCONNEXT, L_ALL,
-                       "CLICONN %s %s %s %s %s %s 0 %s",
+                       "CLICONN %s %s %s %s %s %s 0 %s %s",
                        source_p->name, source_p->username, source_p->orighost,
                        show_ip(NULL, source_p) ? ipaddr : "255.255.255.255",
                        get_client_class(source_p),
                        /* mirc can sometimes send ips here */
                        show_ip(NULL, source_p) ? source_p->localClient->fullcaps : "<hidden> <hidden>",
+                       *source_p->user->suser ? source_p->user->suser : "*",
                        source_p->info);
 
        add_to_hostname_hash(source_p->orighost, source_p);
@@ -632,8 +695,8 @@ register_local_user(struct Client *client_p, struct Client *source_p)
                add_to_id_hash(source_p->id, source_p);
        }
 
-       if (IsSSL(source_p) && !IsInsecure(source_p))
-               source_p->umodes |= UMODE_SSLCLIENT;
+       if (IsSecure(source_p))
+               source_p->umodes |= UMODE_SECURE;
 
        if (source_p->umodes & UMODE_INVISIBLE)
                Count.invisi++;
@@ -657,7 +720,7 @@ register_local_user(struct Client *client_p, struct Client *source_p)
        {
                Count.max_loc = rb_dlink_list_length(&lclient_list);
                if(!(Count.max_loc % 10))
-                       sendto_realops_snomask(SNO_GENERAL, L_ALL,
+                       sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                             "New Max Local Clients: %d", Count.max_loc);
        }
 
@@ -925,7 +988,7 @@ report_and_set_user_flags(struct Client *source_p, struct ConfItem *aconf)
        if(IsConfExemptDNSBL(aconf))
                /* kline exempt implies this, don't send both */
                if(!IsConfExemptKline(aconf))
-                       sendto_one_notice(source_p, ":*** You are exempt from DNS blacklists");
+                       sendto_one_notice(source_p, ":*** You are exempt from DNSBL listings");
 
        /* If this user is exempt from user limits set it F lined" */
        if(IsConfExemptLimits(aconf))
@@ -970,6 +1033,22 @@ report_and_set_user_flags(struct Client *source_p, struct ConfItem *aconf)
        }
 }
 
+void
+report_priv_change(struct Client *client, struct PrivilegeSet *old, struct PrivilegeSet *new)
+{
+       struct privset_diff diff = privilegeset_diff(old, new);
+
+       hook_data_priv_change hdata = {
+               .client = client,
+               .new = new,
+               .old = old,
+               .unchanged = diff.unchanged,
+               .added = diff.added,
+               .removed = diff.removed,
+       };
+       call_hook(h_priv_change, &hdata);
+}
+
 static void
 show_other_user_mode(struct Client *source_p, struct Client *target_p)
 {
@@ -1038,14 +1117,14 @@ user_mode(struct Client *client_p, struct Client *source_p, int parc, const char
 
        if(IsServer(source_p))
        {
-               sendto_realops_snomask(SNO_GENERAL, L_ADMIN,
+               sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                     "*** Mode for User %s from %s", parv[1], source_p->name);
                return 0;
        }
 
        if(source_p != target_p)
        {
-               if (MyOper(source_p) && parc < 3)
+               if (HasPrivilege(source_p, "auspex:umodes") && parc < 3)
                        show_other_user_mode(source_p, target_p);
                else
                        sendto_one(source_p, form_str(ERR_USERSDONTMATCH), me.name, source_p->name);
@@ -1114,11 +1193,6 @@ user_mode(struct Client *client_p, struct Client *source_p, int parc, const char
                                if(MyConnect(source_p))
                                {
                                        source_p->umodes &= ~ConfigFileEntry.oper_only_umodes;
-                                       if (!(source_p->umodes & UMODE_SERVNOTICE) && source_p->snomask != 0)
-                                       {
-                                               source_p->snomask = 0;
-                                               showsnomask = true;
-                                       }
                                        source_p->flags &= ~OPER_FLAGS;
 
                                        rb_dlinkFindDestroy(source_p, &local_oper_list);
@@ -1132,6 +1206,8 @@ user_mode(struct Client *client_p, struct Client *source_p, int parc, const char
 
                                if(source_p->user->privset != NULL)
                                {
+                                       report_priv_change(source_p, source_p->user->privset, NULL);
+
                                        privilegeset_unref(source_p->user->privset);
                                        source_p->user->privset = NULL;
                                }
@@ -1156,8 +1232,8 @@ user_mode(struct Client *client_p, struct Client *source_p, int parc, const char
                case 's':
                        if (MyConnect(source_p))
                        {
-                               if(!IsOper(source_p)
-                                               && (ConfigFileEntry.oper_only_umodes & UMODE_SERVNOTICE))
+                               if((ConfigFileEntry.oper_only_umodes & UMODE_SERVNOTICE) &&
+                                               (!IsOper(source_p) || !HasPrivilege(source_p, "usermode:servnotice")))
                                {
                                        if (what == MODE_ADD || source_p->umodes & UMODE_SERVNOTICE)
                                                badflag = true;
@@ -1216,6 +1292,18 @@ user_mode(struct Client *client_p, struct Client *source_p, int parc, const char
        if(badflag)
                sendto_one(source_p, form_str(ERR_UMODEUNKNOWNFLAG), me.name, source_p->name);
 
+       if(MyClient(source_p))
+       {
+               if ((ConfigFileEntry.oper_only_umodes & UMODE_SERVNOTICE) &&
+                               !HasPrivilege(source_p, "usermode:servnotice"))
+                       source_p->umodes &= ~UMODE_SERVNOTICE;
+               if (!(source_p->umodes & UMODE_SERVNOTICE) && source_p->snomask != 0)
+               {
+                       source_p->snomask = 0;
+                       showsnomask = true;
+               }
+       }
+
        if(MyClient(source_p) && (source_p->snomask & SNO_NCHANGE) && !IsOperN(source_p))
        {
                sendto_one_notice(source_p, ":*** You need oper and nick_changes flag for +s +n");
@@ -1235,6 +1323,9 @@ user_mode(struct Client *client_p, struct Client *source_p, int parc, const char
                source_p->umodes &= ~UMODE_ADMIN;
        }
 
+       if(MyClient(source_p))
+               source_p->handler = IsOperGeneral(source_p) ? OPER_HANDLER : CLIENT_HANDLER;
+
        /* let modules providing usermodes know that we've changed our usermode --nenolod */
        hdata.client = source_p;
        hdata.oldumodes = setflags;
@@ -1423,6 +1514,8 @@ oper_up(struct Client *source_p, struct oper_conf *oper_p)
        source_p->user->opername = rb_strdup(oper_p->name);
        source_p->user->privset = privilegeset_ref(oper_p->privset);
 
+       report_priv_change(source_p, NULL, source_p->user->privset);
+
        rb_dlinkAddAlloc(source_p, &local_oper_list);
        rb_dlinkAddAlloc(source_p, &oper_list);
 
@@ -1432,11 +1525,19 @@ oper_up(struct Client *source_p, struct oper_conf *oper_p)
                source_p->snomask &= ~SNO_NCHANGE;
        if(!IsOperOperwall(source_p))
                source_p->umodes &= ~UMODE_OPERWALL;
+       if((ConfigFileEntry.oper_only_umodes & UMODE_SERVNOTICE) &&
+                       !HasPrivilege(source_p, "usermode:servnotice"))
+       {
+               source_p->umodes &= ~UMODE_SERVNOTICE;
+               source_p->snomask = 0;
+       }
        hdata.client = source_p;
        hdata.oldumodes = old;
        hdata.oldsnomask = oldsnomask;
        call_hook(h_umode_changed, &hdata);
 
+       source_p->handler = IsOperGeneral(source_p) ? OPER_HANDLER : CLIENT_HANDLER;
+
        sendto_realops_snomask(SNO_GENERAL, L_ALL,
                             "%s (%s!%s@%s) is now an operator", oper_p->name, source_p->name,
                             source_p->username, source_p->host);
@@ -1451,7 +1552,10 @@ oper_up(struct Client *source_p, struct oper_conf *oper_p)
                   construct_snobuf(source_p->snomask));
        sendto_one(source_p, form_str(RPL_YOUREOPER), me.name, source_p->name);
        sendto_one_notice(source_p, ":*** Oper privilege set is %s", oper_p->privset->name);
-       sendto_one_notice(source_p, ":*** Oper privs are %s", oper_p->privset->privs);
+       send_multiline_init(source_p, " ", ":%s NOTICE %s :*** Oper privs are ", me.name, source_p->name);
+       for (const char *const *s = privilegeset_privs(oper_p->privset); *s != NULL; s++)
+               send_multiline_item(source_p, "%s", *s);
+       send_multiline_fini(source_p, NULL);
        send_oper_motd(source_p);
 }
 
@@ -1493,12 +1597,12 @@ construct_umodebuf(void)
                        if (user_modes[i] == 0)
                        {
                                orphaned_umodes |= prev_user_modes[i];
-                               sendto_realops_snomask(SNO_DEBUG, L_ALL, "Umode +%c is now orphaned", i);
+                               sendto_realops_snomask(SNO_DEBUG, L_NETWIDE, "Umode +%c is now orphaned", i);
                        }
                        else
                        {
                                orphaned_umodes &= ~prev_user_modes[i];
-                               sendto_realops_snomask(SNO_DEBUG, L_ALL, "Orphaned umode +%c is picked up by module", i);
+                               sendto_realops_snomask(SNO_DEBUG, L_NETWIDE, "Orphaned umode +%c is picked up by module", i);
                        }
                        user_modes[i] = prev_user_modes[i];
                }
@@ -1624,3 +1728,20 @@ change_nick_user_host(struct Client *target_p,   const char *nick, const char *use
                del_all_accepts(target_p);
        }
 }
+
+bool
+has_common_channel(struct Client *source_p, struct Client *target_p)
+{
+        rb_dlink_node *ps, *pt;
+        struct membership *ms, *mt;
+        struct Channel *chptr;
+
+        ITER_COMM_CHANNELS(ps, pt, source_p->user->channel.head, target_p->user->channel.head, ms, mt, chptr)
+        {
+                if (ms != NULL && mt != NULL)
+                        return true;
+        }
+
+        return false;
+}
+