ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/client.c
(Generate patch)

Comparing:
ircd-hybrid-7.2/src/client.c (file contents), Revision 706 by michael, Sun Jul 2 11:25:55 2006 UTC vs.
ircd-hybrid-8/src/client.c (file contents), Revision 1176 by michael, Sun Aug 14 11:24:24 2011 UTC

# Line 23 | Line 23
23   */
24  
25   #include "stdinc.h"
26 < #include "tools.h"
26 > #include "list.h"
27   #include "client.h"
28   #include "channel_mode.h"
29   #include "common.h"
# Line 31 | Line 31
31   #include "fdlist.h"
32   #include "hash.h"
33   #include "irc_string.h"
34 #include "sprintf_irc.h"
34   #include "ircd.h"
36 #include "list.h"
35   #include "s_gline.h"
36   #include "numeric.h"
37   #include "packet.h"
# Line 53 | Line 51
51   #include "listener.h"
52   #include "irc_res.h"
53   #include "userhost.h"
54 + #include "watch.h"
55  
56   dlink_list listing_client_list = { NULL, NULL, 0 };
57   /* Pointer to beginning of Client list */
# Line 76 | Line 75 | static dlink_node *eac_next;  /* next ab
75  
76   static void check_pings_list(dlink_list *);
77   static void check_unknowns_list(void);
78 < static void ban_them(struct Client *client_p, struct ConfItem *conf);
78 > static void ban_them(struct Client *, struct ConfItem *);
79  
80  
81   /* init_client()
# Line 124 | Line 123 | make_client(struct Client *from)
123      client_p->localClient = BlockHeapAlloc(lclient_heap);
124      client_p->localClient->registration = REG_INIT;
125      /* as good a place as any... */
126 <    dlinkAdd(client_p, make_dlink_node(), &unknown_list);
126 >    dlinkAdd(client_p, &client_p->localClient->lclient_node, &unknown_list);
127    }
128    else
129      client_p->from = from; /* 'from' of local client is self! */
# Line 253 | Line 252 | check_pings_list(dlink_list *list)
252        continue;
253      }
254  
256    if (GlobalSetOptions.idletime && IsClient(client_p))
257    {
258      if (!IsExemptKline(client_p) && !IsOper(client_p) &&
259          !IsIdlelined(client_p) &&
260          ((CurrentTime - client_p->localClient->last) > GlobalSetOptions.idletime))
261      {
262        struct ConfItem *conf;
263        struct AccessItem *aconf;
264
265        conf = make_conf_item(KLINE_TYPE);
266        aconf = (struct AccessItem *)map_to_conf(conf);
267
268        DupString(aconf->host, client_p->host);
269        DupString(aconf->reason, "idle exceeder");
270        DupString(aconf->user, client_p->username);
271        aconf->hold = CurrentTime + 60;
272        add_temp_line(conf);
273
274        sendto_realops_flags(UMODE_ALL, L_ALL,
275                             "Idle time limit exceeded for %s - temp k-lining",
276                             get_client_name(client_p, HIDE_IP));
277        exit_client(client_p, &me, aconf->reason);
278        continue;
279      }
280    }
281
255      if (!IsRegistered(client_p))
256        ping = CONNECTTIMEOUT, pingwarn = 0;
257      else
# Line 318 | Line 291 | check_pings_list(dlink_list *list)
291                   get_client_name(client_p, HIDE_IP));
292            }
293  
294 <          ircsprintf(scratch, "Ping timeout: %d seconds",
295 <                     (int)(CurrentTime - client_p->lasttime));
294 >          snprintf(scratch, sizeof(scratch), "Ping timeout: %d seconds",
295 >                   (int)(CurrentTime - client_p->lasttime));
296            exit_client(client_p, &me, scratch);
297          }
298          else if (!IsPingWarning(client_p) && pingwarn > 0 &&
# Line 554 | Line 527 | ban_them(struct Client *client_p, struct
527   static void
528   update_client_exit_stats(struct Client *client_p)
529   {
530 <  if (IsServer(client_p))
558 <  {
559 <    sendto_realops_flags(UMODE_EXTERNAL, L_ALL,
560 <                         "Server %s split from %s",
561 <                         client_p->name, client_p->servptr->name);
562 <  }
563 <  else if (IsClient(client_p))
530 >  if (IsClient(client_p))
531    {
532 +    assert(Count.total > 0);
533      --Count.total;
534      if (IsOper(client_p))
535        --Count.oper;
536      if (IsInvisible(client_p))
537        --Count.invisi;
538    }
539 +  else if (IsServer(client_p))
540 +    sendto_realops_flags(UMODE_EXTERNAL, L_ALL, "Server %s split from %s",
541 +                         client_p->name, client_p->servptr->name);
542  
543    if (splitchecking && !splitmode)
544      check_splitmode(NULL);
# Line 595 | Line 566 | find_person(const struct Client *client_
566      }
567    }
568    else
569 <    c2ptr = find_client(name);
569 >    c2ptr = hash_find_client(name);
570  
571    return ((c2ptr != NULL && IsClient(c2ptr)) ? c2ptr : NULL);
572   }
# Line 615 | Line 586 | find_chasing(struct Client *client_p, st
586      *chasing = 0;
587  
588    if (who)
589 <    return(who);
589 >    return who;
590  
591    if (IsDigit(*user))
592 <    return(NULL);
592 >    return NULL;
593  
594    if ((who = get_history(user,
595                          (time_t)ConfigFileEntry.kill_chase_time_limit))
# Line 626 | Line 597 | find_chasing(struct Client *client_p, st
597    {
598      sendto_one(source_p, form_str(ERR_NOSUCHNICK),
599                 me.name, source_p->name, user);
600 <    return(NULL);
600 >    return NULL;
601    }
602  
603    if (chasing)
604      *chasing = 1;
605  
606 <  return(who);
606 >  return who;
607   }
608  
609   /*
# Line 654 | Line 625 | find_chasing(struct Client *client_p, st
625   *        to modify what it points!!!
626   */
627   const char *
628 < get_client_name(struct Client *client, int showip)
628 > get_client_name(const struct Client *client, int showip)
629   {
630    static char nbuf[HOSTLEN * 2 + USERLEN + 5];
631  
632    assert(client != NULL);
633  
634    if (irccmp(client->name, client->host) == 0)
635 <    return(client->name);
635 >    return client->name;
636  
637    if (ConfigServerHide.hide_server_ips)
638      if (IsServer(client) || IsConnecting(client) || IsHandshake(client))
# Line 677 | Line 648 | get_client_name(struct Client *client, i
648      case SHOW_IP:
649        if (MyConnect(client))
650        {
651 <        ircsprintf(nbuf, "%s[%s@%s]", client->name, client->username,
652 <                   client->sockhost);
651 >        snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]",
652 >                 client->name,
653 >                 client->username, client->sockhost);
654          break;
655        }
656      case MASK_IP:
657 <      ircsprintf(nbuf, "%s[%s@255.255.255.255]", client->name,
658 <                 client->username);
657 >      snprintf(nbuf, sizeof(nbuf), "%s[%s@255.255.255.255]",
658 >               client->name, client->username);
659        break;
660      default:
661 <      ircsprintf(nbuf, "%s[%s@%s]", client->name, client->username,
662 <                 client->host);
661 >      snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]",
662 >               client->name,
663 >               client->username, client->host);
664    }
665  
666 <  return(nbuf);
666 >  return nbuf;
667   }
668  
669   void
670   free_exited_clients(void)
671   {
672 <  dlink_node *ptr, *next;
700 <  struct Client *target_p;
672 >  dlink_node *ptr = NULL, *next = NULL;
673    
674    DLINK_FOREACH_SAFE(ptr, next, dead_list.head)
675    {
676 <    target_p = ptr->data;
705 <
706 <    if (ptr->data == NULL)
707 <    {
708 <      sendto_realops_flags(UMODE_ALL, L_ALL,
709 <                           "Warning: null client on dead_list!");
710 <      dlinkDelete(ptr, &dead_list);
711 <      free_dlink_node(ptr);
712 <      continue;
713 <    }
714 <
715 <    free_client(target_p);
676 >    free_client(ptr->data);
677      dlinkDelete(ptr, &dead_list);
678      free_dlink_node(ptr);
679    }
# Line 731 | Line 692 | exit_one_client(struct Client *source_p,
692  
693    assert(!IsMe(source_p));
694  
695 <  if (IsServer(source_p))
735 <  {
736 <    dlinkDelete(&source_p->lnode, &source_p->servptr->serv->servers);
737 <
738 <    if ((lp = dlinkFindDelete(&global_serv_list, source_p)) != NULL)
739 <      free_dlink_node(lp);
740 <
741 <    if (!MyConnect(source_p))
742 <    {
743 <      source_p->from->serv->dep_servers--;
744 <      assert(source_p->from->serv->dep_servers > 0);
745 <    }
746 <  }
747 <  else if (IsClient(source_p))
695 >  if (IsClient(source_p))
696    {
697      if (source_p->servptr->serv != NULL)
698 <      dlinkDelete(&source_p->lnode, &source_p->servptr->serv->users);
698 >      dlinkDelete(&source_p->lnode, &source_p->servptr->serv->client_list);
699  
700 <    /* If a person is on a channel, send a QUIT notice
701 <    ** to every client (person) on the same channel (so
702 <    ** that the client can show the "**signoff" message).
703 <    ** (Note: The notice is to the local clients *only*)
704 <    */
700 >    /*
701 >     * If a person is on a channel, send a QUIT notice
702 >     * to every client (person) on the same channel (so
703 >     * that the client can show the "**signoff" message).
704 >     * (Note: The notice is to the local clients *only*)
705 >     */
706      sendto_common_channels_local(source_p, 0, ":%s!%s@%s QUIT :%s",
707                                   source_p->name, source_p->username,
708                                   source_p->host, quitmsg);
709      DLINK_FOREACH_SAFE(lp, next_lp, source_p->channel.head)
710        remove_user_from_channel(lp->data);
711  
763    /* Clean up allow lists */
764    del_all_accepts(source_p);
712      add_history(source_p, 0);
713      off_history(source_p);
714  
715 <    if (!MyConnect(source_p))
716 <    {
717 <      source_p->from->serv->dep_users--;
771 <      assert(source_p->from->serv->dep_users >= 0);
772 <    }
773 <    else
715 >    watch_check_hash(source_p, RPL_LOGOFF);
716 >
717 >    if (MyConnect(source_p))
718      {
719        /* Clean up invitefield */
720        DLINK_FOREACH_SAFE(lp, next_lp, source_p->localClient->invited.head)
721          del_invite(lp->data, source_p);
722 +
723 +      del_all_accepts(source_p);
724      }
725    }
726 +  else if (IsServer(source_p))
727 +  {
728 +    dlinkDelete(&source_p->lnode, &source_p->servptr->serv->server_list);
729 +
730 +    if ((lp = dlinkFindDelete(&global_serv_list, source_p)) != NULL)
731 +      free_dlink_node(lp);
732 +  }
733  
734    /* Remove source_p from the client lists */
735    if (HasID(source_p))
# Line 816 | Line 769 | exit_one_client(struct Client *source_p,
769   static void
770   recurse_send_quits(struct Client *original_source_p, struct Client *source_p,
771                     struct Client *from, struct Client *to, const char *comment,
772 <                   const char *splitstr, const char *myname)
772 >                   const char *splitstr)
773   {
774    dlink_node *ptr, *next;
775    struct Client *target_p;
776 <  int hidden = match(myname, source_p->name);
776 >  int hidden = match(me.name, source_p->name); /* XXX */
777  
778    assert(to != source_p);  /* should be already removed from serv_list */
779  
# Line 831 | Line 784 | recurse_send_quits(struct Client *origin
784     * hidden behind fakename. If so, send out the QUITs -adx
785     */
786    if (hidden || !IsCapable(to, CAP_QS))
787 <    DLINK_FOREACH_SAFE(ptr, next, source_p->serv->users.head)
787 >    DLINK_FOREACH_SAFE(ptr, next, source_p->serv->client_list.head)
788      {
789        target_p = ptr->data;
790        sendto_one(to, ":%s QUIT :%s", target_p->name, splitstr);
791      }
792  
793 <  DLINK_FOREACH_SAFE(ptr, next, source_p->serv->servers.head)
793 >  DLINK_FOREACH_SAFE(ptr, next, source_p->serv->server_list.head)
794      recurse_send_quits(original_source_p, ptr->data, from, to,
795 <                       comment, splitstr, myname);
795 >                       comment, splitstr);
796  
797    if (!hidden && ((source_p == original_source_p && to != from) ||
798                    !IsCapable(to, CAP_QS)))
# Line 861 | Line 814 | recurse_remove_clients(struct Client *so
814   {
815    dlink_node *ptr, *next;
816  
817 <  DLINK_FOREACH_SAFE(ptr, next, source_p->serv->users.head)
817 >  DLINK_FOREACH_SAFE(ptr, next, source_p->serv->client_list.head)
818      exit_one_client(ptr->data, quitmsg);
819  
820 <  DLINK_FOREACH_SAFE(ptr, next, source_p->serv->servers.head)
820 >  DLINK_FOREACH_SAFE(ptr, next, source_p->serv->server_list.head)
821    {
822      recurse_remove_clients(ptr->data, quitmsg);
823      exit_one_client(ptr->data, quitmsg);
824    }
872
873  assert(source_p->serv->dep_servers == 1);
874  assert(source_p->serv->dep_users == 0);
825   }
826  
827   /*
# Line 883 | Line 833 | static void
833   remove_dependents(struct Client *source_p, struct Client *from,
834                    const char *comment, const char *splitstr)
835   {
836 <  struct Client *to;
887 <  struct ConfItem *conf;
888 <  static char myname[HOSTLEN+1];
889 <  dlink_node *ptr;
836 >  dlink_node *ptr = NULL;
837  
838    DLINK_FOREACH(ptr, serv_list.head)
839 <  {
840 <    to = ptr->data;
894 <
895 <    if ((conf = to->serv->sconf) != NULL)
896 <      strlcpy(myname, my_name_for_link(conf), sizeof(myname));
897 <    else
898 <      strlcpy(myname, me.name, sizeof(myname));
899 <    recurse_send_quits(source_p, source_p, from, to,
900 <                       comment, splitstr, myname);
901 <  }
839 >    recurse_send_quits(source_p, source_p, from, ptr->data,
840 >                       comment, splitstr);
841  
842    recurse_remove_clients(source_p, splitstr);
843   }
# Line 924 | Line 863 | remove_dependents(struct Client *source_
863   void
864   exit_client(struct Client *source_p, struct Client *from, const char *comment)
865   {
866 <  dlink_node *m;
866 >  dlink_node *m = NULL;
867  
868    if (MyConnect(source_p))
869    {
# Line 939 | Line 878 | exit_client(struct Client *source_p, str
878      if (IsIpHash(source_p))
879        remove_one_ip(&source_p->localClient->ip);
880  
881 <    delete_auth(source_p);
881 >    if (source_p->localClient->auth)
882 >    {
883 >      delete_auth(source_p->localClient->auth);
884 >      source_p->localClient->auth = NULL;
885 >    }
886  
887      /* This source_p could have status of one of STAT_UNKNOWN, STAT_CONNECTING
888       * STAT_HANDSHAKE or STAT_UNKNOWN
# Line 949 | Line 892 | exit_client(struct Client *source_p, str
892       */
893      if (!IsRegistered(source_p))
894      {
895 <      if ((m = dlinkFindDelete(&unknown_list, source_p)) != NULL)
896 <        free_dlink_node(m);
895 >      assert(dlinkFind(&unknown_list, source_p));
896 >
897 >      dlinkDelete(&source_p->localClient->lclient_node, &unknown_list);
898      }
899      else if (IsClient(source_p))
900      {
901 +      assert(Count.local > 0);
902        Count.local--;
903  
904        if (IsOper(source_p))
# Line 962 | Line 907 | exit_client(struct Client *source_p, str
907            free_dlink_node(m);
908        }
909  
910 +      assert(dlinkFind(&local_client_list, source_p));
911        dlinkDelete(&source_p->localClient->lclient_node, &local_client_list);
912 +
913        if (source_p->localClient->list_task != NULL)
914          free_list_task(source_p->localClient->list_task, source_p);
915  
916 +      watch_del_watch_list(source_p);
917        sendto_realops_flags(UMODE_CCONN, L_ALL, "Client exiting: %s (%s@%s) [%s] [%s]",
918                             source_p->name, source_p->username, source_p->host, comment,
919                             ConfigFileEntry.hide_spoof_ips && IsIPSpoof(source_p) ?
920                             "255.255.255.255" : source_p->sockhost);
921 +      sendto_realops_flags(UMODE_CCONN_FULL, L_ALL, "CLIEXIT: %s %s %s %s 0 %s",
922 +                           source_p->name,
923 +                           source_p->username,
924 +                           source_p->host,
925 +
926 +                           ConfigFileEntry.hide_spoof_ips && IsIPSpoof(source_p) ?
927 +                           "255.255.255.255" : source_p->sockhost,
928 +                           comment);
929      }
930  
931      /* As soon as a client is known to be a server of some sort
# Line 986 | Line 942 | exit_client(struct Client *source_p, str
942        }
943  
944        if (IsServer(source_p))
989      {
945          Count.myserver--;
991        if (ServerInfo.hub)
992          remove_lazylink_flags(source_p->localClient->serverMask);
993        else
994          uplink = NULL;
995      }
946      }
947  
948      log_user_exit(source_p);
# Line 1032 | Line 982 | exit_client(struct Client *source_p, str
982      assert(source_p->serv != NULL && source_p->servptr != NULL);
983  
984      if (ConfigServerHide.hide_servers)
985 <      /* set netsplit message to "*.net *.split" to still show
985 >      /*
986 >       * Set netsplit message to "*.net *.split" to still show
987         * that its a split, but hide the servers splitting
988         */
989        strcpy(splitstr, "*.net *.split");
# Line 1057 | Line 1008 | exit_client(struct Client *source_p, str
1008    }
1009    else if (IsClient(source_p) && !IsKilled(source_p))
1010    {
1011 <    sendto_server(from->from, source_p, NULL, CAP_TS6, NOCAPS, NOFLAGS,
1011 >    sendto_server(from->from, NULL, CAP_TS6, NOCAPS,
1012                    ":%s QUIT :%s", ID(source_p), comment);
1013 <    sendto_server(from->from, source_p, NULL, NOCAPS, CAP_TS6, NOFLAGS,
1013 >    sendto_server(from->from, NULL, NOCAPS, CAP_TS6,
1014                    ":%s QUIT :%s", source_p->name, comment);
1015    }
1016  
# Line 1155 | Line 1106 | dead_link_on_read(struct Client *client_
1106      strlcpy(errmsg, "Remote host closed the connection",
1107              sizeof(errmsg));
1108    else
1109 <    ircsprintf(errmsg, "Read error: %s",
1110 <               strerror(current_error));
1109 >    snprintf(errmsg, sizeof(errmsg), "Read error: %s",
1110 >             strerror(current_error));
1111  
1112    exit_client(client_p, &me, errmsg);
1113   }
# Line 1196 | Line 1147 | exit_aborted_clients(void)
1147  
1148   /*
1149   * accept processing, this adds a form of "caller ID" to ircd
1150 < *
1150 > *
1151   * If a client puts themselves into "caller ID only" mode,
1152 < * only clients that match a client pointer they have put on
1152 > * only clients that match a client pointer they have put on
1153   * the accept list will be allowed to message them.
1154   *
1155 < * [ source.on_allow_list ] -> [ target1 ] -> [ target2 ]
1205 < *
1206 < * [target.allow_list] -> [ source1 ] -> [source2 ]
1207 < *
1208 < * i.e. a target will have a link list of source pointers it will allow
1209 < * each source client then has a back pointer pointing back
1210 < * to the client that has it on its accept list.
1211 < * This allows for exit_one_client to remove these now bogus entries
1212 < * from any client having an accept on them.
1155 > * Diane Bruce, "Dianora" db@db.net
1156   */
1157  
1158 < /* accept_message()
1159 < *
1217 < * inputs       - pointer to source client
1218 < *              - pointer to target client
1219 < * output       - 1 if accept this message 0 if not
1220 < * side effects - See if source is on target's allow list
1221 < */
1222 < int
1223 < accept_message(struct Client *source, struct Client *target)
1158 > void
1159 > del_accept(struct split_nuh_item *accept_p, struct Client *client_p)
1160   {
1161 <  dlink_node *ptr;
1226 <
1227 <  DLINK_FOREACH(ptr, target->allow_list.head)
1228 <  {
1229 <    struct Client *target_p = ptr->data;
1230 <
1231 <    if (source == target_p)
1232 <      return (1);
1233 <  }
1234 <
1235 <  if (IsSoftCallerId(target))
1236 <  {
1237 <    DLINK_FOREACH(ptr, target->channel.head)
1238 <      if (IsMember(source, ((struct Membership *)ptr->data)->chptr))
1239 <        return (1);
1240 <  }
1161 >  dlinkDelete(&accept_p->node, &client_p->localClient->acceptlist);
1162  
1163 <  return (0);
1163 >  MyFree(accept_p->nickptr);
1164 >  MyFree(accept_p->userptr);
1165 >  MyFree(accept_p->hostptr);
1166 >  MyFree(accept_p);
1167   }
1168  
1169 < /* del_from_accept()
1170 < *
1171 < * inputs       - pointer to source client
1248 < *              - pointer to target client
1249 < * output       - NONE
1250 < * side effects - Delete's source pointer to targets allow list
1251 < *
1252 < * Walk through the target's accept list, remove if source is found,
1253 < * Then walk through the source's on_accept_list remove target if found.
1254 < */
1255 < void
1256 < del_from_accept(struct Client *source, struct Client *target)
1169 > struct split_nuh_item *
1170 > find_accept(const char *nick, const char *user,
1171 >            const char *host, struct Client *client_p, int do_match)
1172   {
1173 <  dlink_node *ptr;
1174 <  dlink_node *ptr2;
1175 <  dlink_node *next_ptr;
1261 <  dlink_node *next_ptr2;
1262 <  struct Client *target_p;
1173 >  dlink_node *ptr = NULL;
1174 >  /* XXX We wouldn't need that if match() would return 0 on match */
1175 >  int (*cmpfunc)(const char *, const char *) = do_match ? match : irccmp;
1176  
1177 <  DLINK_FOREACH_SAFE(ptr, next_ptr, target->allow_list.head)
1177 >  DLINK_FOREACH(ptr, client_p->localClient->acceptlist.head)
1178    {
1179 <    target_p = ptr->data;
1179 >    struct split_nuh_item *accept_p = ptr->data;
1180  
1181 <    if (source == target_p)
1182 <    {
1183 <      dlinkDelete(ptr, &target->allow_list);
1184 <      free_dlink_node(ptr);
1272 <
1273 <      DLINK_FOREACH_SAFE(ptr2, next_ptr2, source->on_allow_list.head)
1274 <      {
1275 <        target_p = ptr2->data;
1276 <
1277 <        if (target == target_p)
1278 <        {
1279 <          dlinkDelete(ptr2, &source->on_allow_list);
1280 <          free_dlink_node(ptr2);
1281 <        }
1282 <      }
1283 <    }
1181 >    if (cmpfunc(accept_p->nickptr, nick) == do_match &&
1182 >        cmpfunc(accept_p->userptr, user) == do_match &&
1183 >        cmpfunc(accept_p->hostptr, host) == do_match)
1184 >      return accept_p;
1185    }
1186 +
1187 +  return NULL;
1188   }
1189  
1190 < /* del_all_accepts()
1190 > /* accept_message()
1191   *
1192 < * inputs       - pointer to exiting client
1193 < * output       - NONE
1194 < * side effects - Walk through given clients allow_list and on_allow_list
1195 < *                remove all references to this client
1192 > * inputs       - pointer to source client
1193 > *              - pointer to target client
1194 > * output       - 1 if accept this message 0 if not
1195 > * side effects - See if source is on target's allow list
1196   */
1197 < void
1198 < del_all_accepts(struct Client *client_p)
1197 > int
1198 > accept_message(struct Client *source,
1199 >               struct Client *target)
1200   {
1201 <  dlink_node *ptr, *next_ptr;
1201 >  dlink_node *ptr = NULL;
1202  
1203 <  DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->allow_list.head)
1204 <    del_from_accept(ptr->data, client_p);
1205 <
1302 <  DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->on_allow_list.head)
1303 <    del_from_accept(client_p, ptr->data);
1304 < }
1203 >  if (source == target || find_accept(source->name, source->username,
1204 >                                      source->host, target, 1))
1205 >    return 1;
1206  
1207 < /* del_all_their_accepts()
1208 < *
1209 < * inputs       - pointer to exiting client
1210 < * output       - NONE
1310 < * side effects - Walk through given clients on_allow_list
1311 < *                remove all references to this client,
1312 < *                allow this client to keep their own allow_list
1313 < */
1314 < void
1315 < del_all_their_accepts(struct Client *client_p)
1316 < {
1317 <  dlink_node *ptr, *next_ptr;
1207 >  if (IsSoftCallerId(target))
1208 >    DLINK_FOREACH(ptr, target->channel.head)
1209 >      if (IsMember(source, ((struct Membership *)ptr->data)->chptr))
1210 >        return 1;
1211  
1212 <  DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->on_allow_list.head)
1320 <    del_from_accept(client_p, ptr->data);
1212 >  return 0;
1213   }
1214  
1215 < /* set_initial_nick()
1324 < *
1325 < * inputs
1326 < * output
1327 < * side effects -
1215 > /* del_all_accepts()
1216   *
1217 < * This function is only called to set up an initially registering
1218 < * client.
1217 > * inputs       - pointer to exiting client
1218 > * output       - NONE
1219 > * side effects - Walk through given clients acceptlist and remove all entries
1220   */
1221   void
1222 < set_initial_nick(struct Client *client_p, struct Client *source_p,
1334 <                 const char *nick)
1222 > del_all_accepts(struct Client *client_p)
1223   {
1224 < char buf[USERLEN + 1];
1337 <
1338 <  /* Client setting NICK the first time */
1339 <  
1340 <  /* This had to be copied here to avoid problems.. */
1341 <  source_p->tsinfo = CurrentTime;
1342 <  source_p->localClient->registration &= ~REG_NEED_NICK;
1343 <
1344 <  if (source_p->name[0])
1345 <    hash_del_client(source_p);
1346 <
1347 <  strlcpy(source_p->name, nick, sizeof(source_p->name));
1348 <  hash_add_client(source_p);
1349 <
1350 <  /* fd_desc is long enough */
1351 <  fd_note(&client_p->localClient->fd, "Nick: %s", nick);
1352 <  
1353 <  /* They have the nick they want now.. */
1354 <  client_p->llname[0] = '\0';
1355 <
1356 <  if (!source_p->localClient->registration)
1357 <  {
1358 <    strlcpy(buf, source_p->username, sizeof(buf));
1224 >  dlink_node *ptr = NULL, *next_ptr = NULL;
1225  
1226 <    /*
1227 <     * USER already received, now we have NICK.
1362 <     * *NOTE* For servers "NICK" *must* precede the
1363 <     * user message (giving USER before NICK is possible
1364 <     * only for local client connection!). register_user
1365 <     * may reject the client and call exit_client for it
1366 <     * --must test this and exit m_nick too!!!
1367 <     */
1368 <    register_local_user(client_p, source_p, nick, buf);
1369 <  }
1226 >  DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->localClient->acceptlist.head)
1227 >    del_accept(ptr->data, client_p);
1228   }
1229  
1230   /* change_local_nick()
# Line 1380 | Line 1238 | set_initial_nick(struct Client *client_p
1238   void
1239   change_local_nick(struct Client *client_p, struct Client *source_p, const char *nick)
1240   {
1241 +  int samenick = 0;
1242 +
1243 +  assert(source_p->name[0] && !EmptyString(nick));
1244 +
1245    /*
1246 <  ** Client just changing his/her nick. If he/she is
1247 <  ** on a channel, send note of change to all clients
1248 <  ** on that channel. Propagate notice to other servers.
1249 <  */
1246 >   * Client just changing his/her nick. If he/she is
1247 >   * on a channel, send note of change to all clients
1248 >   * on that channel. Propagate notice to other servers.
1249 >   */
1250    if ((source_p->localClient->last_nick_change +
1251         ConfigFileEntry.max_nick_time) < CurrentTime)
1252      source_p->localClient->number_of_nick_changes = 0;
# Line 1397 | Line 1259 | change_local_nick(struct Client *client_
1259       !ConfigFileEntry.anti_nick_flood ||
1260       (IsOper(source_p) && ConfigFileEntry.no_oper_flood))
1261    {
1262 <    if (irccmp(source_p->name, nick))
1262 >    samenick = !irccmp(source_p->name, nick);
1263 >
1264 >    if (!samenick)
1265      {
1402      /*
1403       * Make sure everyone that has this client on its accept list
1404       * loses that reference.
1405       */
1406      del_all_their_accepts(source_p);
1266        source_p->tsinfo = CurrentTime;
1267 +      clear_ban_cache_client(source_p);
1268 +      watch_check_hash(source_p, RPL_LOGOFF);
1269 +
1270 +      if (HasUMode(source_p, UMODE_REGISTERED))
1271 +      {
1272 +        unsigned int oldmodes = source_p->umodes;
1273 +        char modebuf[IRCD_BUFSIZE] = { '\0' };
1274 +
1275 +        DelUMode(source_p, UMODE_REGISTERED);
1276 +        send_umode(source_p, source_p, oldmodes, 0xffffffff, modebuf);
1277 +      }
1278      }
1279  
1280      /* XXX - the format of this notice should eventually be changed
# Line 1417 | Line 1287 | change_local_nick(struct Client *client_
1287                                   source_p->host, nick);
1288      add_history(source_p, 1);
1289  
1290 <    /*
1421 <     * Only hubs care about lazy link nicks not being sent on yet
1422 <     * lazylink leafs/leafs always send their nicks up to hub,
1423 <     * hence must always propagate nick changes.
1424 <     * hubs might not propagate a nick change, if the leaf
1425 <     * does not know about that client yet.
1426 <     */
1427 <    sendto_server(client_p, source_p, NULL, CAP_TS6, NOCAPS, NOFLAGS,
1290 >    sendto_server(client_p, NULL, CAP_TS6, NOCAPS,
1291                    ":%s NICK %s :%lu",
1292                    ID(source_p), nick, (unsigned long)source_p->tsinfo);
1293 <    sendto_server(client_p, source_p, NULL, NOCAPS, CAP_TS6, NOFLAGS,
1293 >    sendto_server(client_p, NULL, NOCAPS, CAP_TS6,
1294                    ":%s NICK %s :%lu",
1295                    source_p->name, nick, (unsigned long)source_p->tsinfo);
1296 +
1297 +    hash_del_client(source_p);
1298 +    strcpy(source_p->name, nick);
1299 +    hash_add_client(source_p);
1300 +
1301 +    if (!samenick)
1302 +      watch_check_hash(source_p, RPL_LOGON);
1303 +
1304 +    /* fd_desc is long enough */
1305 +    fd_note(&client_p->localClient->fd, "Nick: %s", nick);
1306    }
1307    else
1435  {
1308      sendto_one(source_p, form_str(ERR_NICKTOOFAST),
1309                 me.name, source_p->name, source_p->name,
1310                 nick, ConfigFileEntry.max_nick_time);
1439    return;
1440  }
1441
1442  /* Finally, add to hash */
1443  if (source_p->name[0])
1444    hash_del_client(source_p);
1445
1446  strcpy(source_p->name, nick);
1447  hash_add_client(source_p);
1448
1449  /* fd_desc is long enough */
1450  fd_note(&client_p->localClient->fd, "Nick: %s", nick);
1311   }

Diff Legend

Removed lines
+ Added lines
< Changed lines (old)
> Changed lines (new)