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 885 by michael, Wed Oct 31 18:09:24 2007 UTC vs.
ircd-hybrid-8/src/client.c (file contents), Revision 1340 by michael, Fri Apr 6 10:43:23 2012 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"
29   #include "event.h"
30   #include "fdlist.h"
31   #include "hash.h"
32   #include "irc_string.h"
34 #include "sprintf_irc.h"
33   #include "ircd.h"
36 #include "list.h"
34   #include "s_gline.h"
35   #include "numeric.h"
36   #include "packet.h"
37   #include "s_auth.h"
38   #include "s_bsd.h"
39 < #include "s_conf.h"
40 < #include "s_log.h"
39 > #include "conf.h"
40 > #include "log.h"
41   #include "s_misc.h"
42   #include "s_serv.h"
43   #include "send.h"
# Line 77 | Line 74 | static dlink_node *eac_next;  /* next ab
74  
75   static void check_pings_list(dlink_list *);
76   static void check_unknowns_list(void);
77 < static void ban_them(struct Client *client_p, struct ConfItem *conf);
77 > static void ban_them(struct Client *, struct ConfItem *);
78  
79  
80   /* init_client()
# Line 119 | Line 116 | make_client(struct Client *from)
116  
117    if (from == NULL)
118    {
119 <    client_p->from  = client_p; /* 'from' of local client is self! */
120 <    client_p->since = client_p->lasttime = client_p->firsttime = CurrentTime;
121 <
122 <    client_p->localClient = BlockHeapAlloc(lclient_heap);
119 >    client_p->from                      = client_p; /* 'from' of local client is self! */
120 >    client_p->localClient               = BlockHeapAlloc(lclient_heap);
121 >    client_p->localClient->since        = CurrentTime;
122 >    client_p->localClient->lasttime     = CurrentTime;
123 >    client_p->localClient->firsttime    = CurrentTime;
124      client_p->localClient->registration = REG_INIT;
125 +
126      /* as good a place as any... */
127 <    dlinkAdd(client_p, make_dlink_node(), &unknown_list);
127 >    dlinkAdd(client_p, &client_p->localClient->lclient_node, &unknown_list);
128    }
129    else
130      client_p->from = from; /* 'from' of local client is self! */
# Line 254 | Line 253 | check_pings_list(dlink_list *list)
253        continue;
254      }
255  
257    if (GlobalSetOptions.idletime && IsClient(client_p))
258    {
259      if (!IsExemptKline(client_p) && !IsOper(client_p) &&
260          !IsIdlelined(client_p) &&
261          ((CurrentTime - client_p->localClient->last) > GlobalSetOptions.idletime))
262      {
263        struct ConfItem *conf;
264        struct AccessItem *aconf;
265
266        conf = make_conf_item(KLINE_TYPE);
267        aconf = (struct AccessItem *)map_to_conf(conf);
268
269        DupString(aconf->host, client_p->host);
270        DupString(aconf->reason, "idle exceeder");
271        DupString(aconf->user, client_p->username);
272        aconf->hold = CurrentTime + 60;
273        add_temp_line(conf);
274
275        sendto_realops_flags(UMODE_ALL, L_ALL,
276                             "Idle time limit exceeded for %s - temp k-lining",
277                             get_client_name(client_p, HIDE_IP));
278        exit_client(client_p, &me, aconf->reason);
279        continue;
280      }
281    }
282
256      if (!IsRegistered(client_p))
257        ping = CONNECTTIMEOUT, pingwarn = 0;
258      else
259        ping = get_client_ping(client_p, &pingwarn);
260  
261 <    if (ping < CurrentTime - client_p->lasttime)
261 >    if (ping < CurrentTime - client_p->localClient->lasttime)
262      {
263        if (!IsPingSent(client_p))
264        {
# Line 296 | Line 269 | check_pings_list(dlink_list *list)
269           */
270          SetPingSent(client_p);
271          ClearPingWarning(client_p);
272 <        client_p->lasttime = CurrentTime - ping;
272 >        client_p->localClient->lasttime = CurrentTime - ping;
273          sendto_one(client_p, "PING :%s", ID_or_name(&me, client_p));
274        }
275        else
276        {
277 <        if (CurrentTime - client_p->lasttime >= 2 * ping)
277 >        if (CurrentTime - client_p->localClient->lasttime >= 2 * ping)
278          {
279            /*
280             * If the client/server hasn't talked to us in 2*ping seconds
# Line 315 | Line 288 | check_pings_list(dlink_list *list)
288              sendto_realops_flags(UMODE_ALL, L_OPER,
289                                   "No response from %s, closing link",
290                                   get_client_name(client_p, MASK_IP));
291 <            ilog(L_NOTICE, "No response from %s, closing link",
291 >            ilog(LOG_TYPE_IRCD, "No response from %s, closing link",
292                   get_client_name(client_p, HIDE_IP));
293            }
294  
295 <          ircsprintf(scratch, "Ping timeout: %d seconds",
296 <                     (int)(CurrentTime - client_p->lasttime));
295 >          snprintf(scratch, sizeof(scratch), "Ping timeout: %d seconds",
296 >                   (int)(CurrentTime - client_p->localClient->lasttime));
297            exit_client(client_p, &me, scratch);
298          }
299          else if (!IsPingWarning(client_p) && pingwarn > 0 &&
300                   (IsServer(client_p) || IsHandshake(client_p)) &&
301 <                 CurrentTime - client_p->lasttime >= ping + pingwarn)
301 >                 CurrentTime - client_p->localClient->lasttime >= ping + pingwarn)
302          {
303            /*
304             * If the server hasn't replied in pingwarn seconds after sending
# Line 338 | Line 311 | check_pings_list(dlink_list *list)
311            sendto_realops_flags(UMODE_ALL, L_OPER,
312                                 "Warning, no response from %s in %d seconds",
313                                 get_client_name(client_p, MASK_IP), pingwarn);
314 <          ilog(L_NOTICE, "No response from %s in %d seconds",
314 >          ilog(LOG_TYPE_IRCD, "No response from %s in %d seconds",
315                 get_client_name(client_p, HIDE_IP), pingwarn);
316          }
317        }
# Line 372 | Line 345 | check_unknowns_list(void)
345       * Check UNKNOWN connections - if they have been in this state
346       * for > 30s, close them.
347       */
348 <    if (IsAuthFinished(client_p) && (CurrentTime - client_p->firsttime) > 30)
348 >    if (IsAuthFinished(client_p) && (CurrentTime - client_p->localClient->firsttime) > 30)
349        exit_client(client_p, &me, "Registration timed out");
350    }
351   }
# Line 555 | Line 528 | ban_them(struct Client *client_p, struct
528   static void
529   update_client_exit_stats(struct Client *client_p)
530   {
531 <  if (IsServer(client_p))
559 <  {
560 <    sendto_realops_flags(UMODE_EXTERNAL, L_ALL,
561 <                         "Server %s split from %s",
562 <                         client_p->name, client_p->servptr->name);
563 <  }
564 <  else if (IsClient(client_p))
531 >  if (IsClient(client_p))
532    {
533 +    assert(Count.total > 0);
534      --Count.total;
535 <    if (IsOper(client_p))
535 >    if (HasUMode(client_p, UMODE_OPER))
536        --Count.oper;
537 <    if (IsInvisible(client_p))
537 >    if (HasUMode(client_p, UMODE_INVISIBLE))
538        --Count.invisi;
539    }
540 +  else if (IsServer(client_p))
541 +    sendto_realops_flags(UMODE_EXTERNAL, L_ALL, "Server %s split from %s",
542 +                         client_p->name, client_p->servptr->name);
543  
544    if (splitchecking && !splitmode)
545      check_splitmode(NULL);
# Line 591 | Line 562 | find_person(const struct Client *client_
562      if ((c2ptr = hash_find_id(name)) != NULL)
563      {
564        /* invisible users shall not be found by UID guessing */
565 <      if (IsInvisible(c2ptr) && !IsServer(client_p))
565 >      if (HasUMode(c2ptr, UMODE_INVISIBLE) && !IsServer(client_p))
566          c2ptr = NULL;
567      }
568    }
569    else
570 <    c2ptr = find_client(name);
570 >    c2ptr = hash_find_client(name);
571  
572    return ((c2ptr != NULL && IsClient(c2ptr)) ? c2ptr : NULL);
573   }
# Line 616 | Line 587 | find_chasing(struct Client *client_p, st
587      *chasing = 0;
588  
589    if (who)
590 <    return(who);
590 >    return who;
591  
592    if (IsDigit(*user))
593 <    return(NULL);
593 >    return NULL;
594  
595    if ((who = get_history(user,
596                          (time_t)ConfigFileEntry.kill_chase_time_limit))
# Line 627 | Line 598 | find_chasing(struct Client *client_p, st
598    {
599      sendto_one(source_p, form_str(ERR_NOSUCHNICK),
600                 me.name, source_p->name, user);
601 <    return(NULL);
601 >    return NULL;
602    }
603  
604    if (chasing)
605      *chasing = 1;
606  
607 <  return(who);
607 >  return who;
608   }
609  
610   /*
# Line 655 | Line 626 | find_chasing(struct Client *client_p, st
626   *        to modify what it points!!!
627   */
628   const char *
629 < get_client_name(struct Client *client, int showip)
629 > get_client_name(const struct Client *client, enum addr_mask_type type)
630   {
631    static char nbuf[HOSTLEN * 2 + USERLEN + 5];
632  
633    assert(client != NULL);
634  
635 <  if (irccmp(client->name, client->host) == 0)
636 <    return(client->name);
635 >  if (!MyConnect(client))
636 >    return client->name;
637  
638 <  if (ConfigServerHide.hide_server_ips)
639 <    if (IsServer(client) || IsConnecting(client) || IsHandshake(client))
640 <      showip = MASK_IP;
638 >  if (IsServer(client) || IsConnecting(client) || IsHandshake(client))
639 >  {
640 >    if (!irccmp(client->name, client->host))
641 >      return client->name;
642 >    else if (ConfigServerHide.hide_server_ips)
643 >      type = MASK_IP;
644 >  }
645  
646    if (ConfigFileEntry.hide_spoof_ips)
647 <    if (showip == SHOW_IP && IsIPSpoof(client))
648 <      showip = MASK_IP;
647 >    if (type == SHOW_IP && IsIPSpoof(client))
648 >      type = MASK_IP;
649  
650    /* And finally, let's get the host information, ip or name */
651 <  switch (showip)
651 >  switch (type)
652    {
653      case SHOW_IP:
654 <      if (MyConnect(client))
655 <      {
656 <        ircsprintf(nbuf, "%s[%s@%s]", client->name, client->username,
657 <                   client->sockhost);
683 <        break;
684 <      }
654 >      snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]",
655 >               client->name,
656 >               client->username, client->sockhost);
657 >      break;
658      case MASK_IP:
659 <      ircsprintf(nbuf, "%s[%s@255.255.255.255]", client->name,
660 <                 client->username);
659 >      if (client->localClient->aftype == AF_INET)
660 >        snprintf(nbuf, sizeof(nbuf), "%s[%s@255.255.255.255]",
661 >                 client->name, client->username);
662 >      else
663 >        snprintf(nbuf, sizeof(nbuf), "%s[%s@ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff]",
664 >                 client->name, client->username);
665        break;
666      default:
667 <      ircsprintf(nbuf, "%s[%s@%s]", client->name, client->username,
668 <                 client->host);
667 >      snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]",
668 >               client->name,
669 >               client->username, client->host);
670    }
671  
672 <  return(nbuf);
672 >  return nbuf;
673   }
674  
675   void
676   free_exited_clients(void)
677   {
678 <  dlink_node *ptr, *next;
701 <  struct Client *target_p;
678 >  dlink_node *ptr = NULL, *next = NULL;
679    
680    DLINK_FOREACH_SAFE(ptr, next, dead_list.head)
681    {
682 <    target_p = ptr->data;
706 <
707 <    if (ptr->data == NULL)
708 <    {
709 <      sendto_realops_flags(UMODE_ALL, L_ALL,
710 <                           "Warning: null client on dead_list!");
711 <      dlinkDelete(ptr, &dead_list);
712 <      free_dlink_node(ptr);
713 <      continue;
714 <    }
715 <
716 <    free_client(target_p);
682 >    free_client(ptr->data);
683      dlinkDelete(ptr, &dead_list);
684      free_dlink_node(ptr);
685    }
# Line 732 | Line 698 | exit_one_client(struct Client *source_p,
698  
699    assert(!IsMe(source_p));
700  
701 <  if (IsServer(source_p))
736 <  {
737 <    dlinkDelete(&source_p->lnode, &source_p->servptr->serv->servers);
738 <
739 <    if ((lp = dlinkFindDelete(&global_serv_list, source_p)) != NULL)
740 <      free_dlink_node(lp);
741 <
742 <    if (!MyConnect(source_p))
743 <    {
744 <      source_p->from->serv->dep_servers--;
745 <      assert(source_p->from->serv->dep_servers > 0);
746 <    }
747 <  }
748 <  else if (IsClient(source_p))
701 >  if (IsClient(source_p))
702    {
703      if (source_p->servptr->serv != NULL)
704 <      dlinkDelete(&source_p->lnode, &source_p->servptr->serv->users);
704 >      dlinkDelete(&source_p->lnode, &source_p->servptr->serv->client_list);
705  
706 <    /* If a person is on a channel, send a QUIT notice
707 <    ** to every client (person) on the same channel (so
708 <    ** that the client can show the "**signoff" message).
709 <    ** (Note: The notice is to the local clients *only*)
710 <    */
706 >    /*
707 >     * If a person is on a channel, send a QUIT notice
708 >     * to every client (person) on the same channel (so
709 >     * that the client can show the "**signoff" message).
710 >     * (Note: The notice is to the local clients *only*)
711 >     */
712      sendto_common_channels_local(source_p, 0, ":%s!%s@%s QUIT :%s",
713                                   source_p->name, source_p->username,
714                                   source_p->host, quitmsg);
715      DLINK_FOREACH_SAFE(lp, next_lp, source_p->channel.head)
716        remove_user_from_channel(lp->data);
717  
764    /* Clean up allow lists */
765    del_all_accepts(source_p);
718      add_history(source_p, 0);
719      off_history(source_p);
720  
721      watch_check_hash(source_p, RPL_LOGOFF);
722  
723 <    if (!MyConnect(source_p))
772 <    {
773 <      source_p->from->serv->dep_users--;
774 <      assert(source_p->from->serv->dep_users >= 0);
775 <    }
776 <    else
723 >    if (MyConnect(source_p))
724      {
725        /* Clean up invitefield */
726        DLINK_FOREACH_SAFE(lp, next_lp, source_p->localClient->invited.head)
727          del_invite(lp->data, source_p);
728 +
729 +      del_all_accepts(source_p);
730      }
731    }
732 +  else if (IsServer(source_p))
733 +  {
734 +    dlinkDelete(&source_p->lnode, &source_p->servptr->serv->server_list);
735 +
736 +    if ((lp = dlinkFindDelete(&global_serv_list, source_p)) != NULL)
737 +      free_dlink_node(lp);
738 +  }
739  
740    /* Remove source_p from the client lists */
741    if (HasID(source_p))
# Line 819 | Line 775 | exit_one_client(struct Client *source_p,
775   static void
776   recurse_send_quits(struct Client *original_source_p, struct Client *source_p,
777                     struct Client *from, struct Client *to, const char *comment,
778 <                   const char *splitstr, const char *myname)
778 >                   const char *splitstr)
779   {
780    dlink_node *ptr, *next;
781    struct Client *target_p;
782 <  int hidden = match(myname, source_p->name);
782 >  int hidden = match(me.name, source_p->name); /* XXX */
783  
784    assert(to != source_p);  /* should be already removed from serv_list */
785  
# Line 834 | Line 790 | recurse_send_quits(struct Client *origin
790     * hidden behind fakename. If so, send out the QUITs -adx
791     */
792    if (hidden || !IsCapable(to, CAP_QS))
793 <    DLINK_FOREACH_SAFE(ptr, next, source_p->serv->users.head)
793 >    DLINK_FOREACH_SAFE(ptr, next, source_p->serv->client_list.head)
794      {
795        target_p = ptr->data;
796        sendto_one(to, ":%s QUIT :%s", target_p->name, splitstr);
797      }
798  
799 <  DLINK_FOREACH_SAFE(ptr, next, source_p->serv->servers.head)
799 >  DLINK_FOREACH_SAFE(ptr, next, source_p->serv->server_list.head)
800      recurse_send_quits(original_source_p, ptr->data, from, to,
801 <                       comment, splitstr, myname);
801 >                       comment, splitstr);
802  
803    if (!hidden && ((source_p == original_source_p && to != from) ||
804                    !IsCapable(to, CAP_QS)))
# Line 864 | Line 820 | recurse_remove_clients(struct Client *so
820   {
821    dlink_node *ptr, *next;
822  
823 <  DLINK_FOREACH_SAFE(ptr, next, source_p->serv->users.head)
823 >  DLINK_FOREACH_SAFE(ptr, next, source_p->serv->client_list.head)
824      exit_one_client(ptr->data, quitmsg);
825  
826 <  DLINK_FOREACH_SAFE(ptr, next, source_p->serv->servers.head)
826 >  DLINK_FOREACH_SAFE(ptr, next, source_p->serv->server_list.head)
827    {
828      recurse_remove_clients(ptr->data, quitmsg);
829      exit_one_client(ptr->data, quitmsg);
830    }
875
876  assert(source_p->serv->dep_servers == 1);
877  assert(source_p->serv->dep_users == 0);
831   }
832  
833   /*
# Line 886 | Line 839 | static void
839   remove_dependents(struct Client *source_p, struct Client *from,
840                    const char *comment, const char *splitstr)
841   {
842 <  struct Client *to;
890 <  struct ConfItem *conf;
891 <  static char myname[HOSTLEN+1];
892 <  dlink_node *ptr;
842 >  dlink_node *ptr = NULL;
843  
844    DLINK_FOREACH(ptr, serv_list.head)
845 <  {
846 <    to = ptr->data;
897 <
898 <    if ((conf = to->serv->sconf) != NULL)
899 <      strlcpy(myname, my_name_for_link(conf), sizeof(myname));
900 <    else
901 <      strlcpy(myname, me.name, sizeof(myname));
902 <    recurse_send_quits(source_p, source_p, from, to,
903 <                       comment, splitstr, myname);
904 <  }
845 >    recurse_send_quits(source_p, source_p, from, ptr->data,
846 >                       comment, splitstr);
847  
848    recurse_remove_clients(source_p, splitstr);
849   }
# Line 911 | Line 853 | remove_dependents(struct Client *source_
853   * this on any struct Client, regardless of its state.
854   *
855   * Note, you shouldn't exit remote _users_ without first doing
856 < * SetKilled and propagating a kill or similar message. However,
857 < * it is perfectly correct to call exit_client to force a _server_
856 > * AddFlag(x, FLAGS_KILLED) and propagating a kill or similar message.
857 > * However, it is perfectly correct to call exit_client to force a _server_
858   * quit (either local or remote one).
859   *
860   * inputs:       - a client pointer that is going to be exited
# Line 927 | Line 869 | remove_dependents(struct Client *source_
869   void
870   exit_client(struct Client *source_p, struct Client *from, const char *comment)
871   {
872 <  dlink_node *m;
872 >  dlink_node *m = NULL;
873  
874    if (MyConnect(source_p))
875    {
# Line 942 | Line 884 | exit_client(struct Client *source_p, str
884      if (IsIpHash(source_p))
885        remove_one_ip(&source_p->localClient->ip);
886  
887 <    delete_auth(source_p);
887 >    if (source_p->localClient->auth)
888 >    {
889 >      delete_auth(source_p->localClient->auth);
890 >      source_p->localClient->auth = NULL;
891 >    }
892  
893      /* This source_p could have status of one of STAT_UNKNOWN, STAT_CONNECTING
894       * STAT_HANDSHAKE or STAT_UNKNOWN
# Line 952 | Line 898 | exit_client(struct Client *source_p, str
898       */
899      if (!IsRegistered(source_p))
900      {
901 <      if ((m = dlinkFindDelete(&unknown_list, source_p)) != NULL)
902 <        free_dlink_node(m);
901 >      assert(dlinkFind(&unknown_list, source_p));
902 >
903 >      dlinkDelete(&source_p->localClient->lclient_node, &unknown_list);
904      }
905      else if (IsClient(source_p))
906      {
907 +      time_t on_for = CurrentTime - source_p->localClient->firsttime;
908 +      assert(Count.local > 0);
909        Count.local--;
910  
911 <      if (IsOper(source_p))
911 >      if (HasUMode(source_p, UMODE_OPER))
912        {
913          if ((m = dlinkFindDelete(&oper_list, source_p)) != NULL)
914            free_dlink_node(m);
915        }
916  
917 +      assert(dlinkFind(&local_client_list, source_p));
918        dlinkDelete(&source_p->localClient->lclient_node, &local_client_list);
919 +
920        if (source_p->localClient->list_task != NULL)
921          free_list_task(source_p->localClient->list_task, source_p);
922  
# Line 978 | Line 929 | exit_client(struct Client *source_p, str
929                             source_p->name,
930                             source_p->username,
931                             source_p->host,
981
932                             ConfigFileEntry.hide_spoof_ips && IsIPSpoof(source_p) ?
933                             "255.255.255.255" : source_p->sockhost,
934                             comment);
935 +      ilog(LOG_TYPE_USER, "%s (%3u:%02u:%02u): %s!%s@%s %llu/%llu",
936 +           myctime(source_p->localClient->firsttime), (unsigned int)(on_for / 3600),
937 +           (unsigned int)((on_for % 3600)/60), (unsigned int)(on_for % 60),
938 +           source_p->name, source_p->username, source_p->host,
939 +           source_p->localClient->send.bytes>>10,
940 +           source_p->localClient->recv.bytes>>10);
941      }
942  
943      /* As soon as a client is known to be a server of some sort
944       * it has to be put on the serv_list, or SJOIN's to this new server
945       * from the connect burst will not be seen.
946 +     * XXX - TBV.  This is not true. The only place where we put a server on
947 +     * serv_list is in server_estab right now after registration process.
948 +     * And only after this, a burst is sent to the remote server, i.e. we never
949 +     * send a burst to STAT_CONNECTING, or STAT_HANDSHAKE. This will need
950 +     * more investigation later on, but for now, it's not a problem after all.
951       */
952      if (IsServer(source_p) || IsConnecting(source_p) ||
953          IsHandshake(source_p))
954      {
955 <      if ((m = dlinkFindDelete(&serv_list, source_p)) != NULL)
955 >      if (dlinkFind(&serv_list, source_p))
956        {
957 <        free_dlink_node(m);
957 >        dlinkDelete(&source_p->localClient->lclient_node, &serv_list);
958          unset_chcap_usage_counts(source_p);
959        }
960  
# Line 1001 | Line 962 | exit_client(struct Client *source_p, str
962          Count.myserver--;
963      }
964  
1004    log_user_exit(source_p);
1005
965      if (!IsDead(source_p))
966      {
967        if (IsServer(source_p))
# Line 1038 | Line 997 | exit_client(struct Client *source_p, str
997      assert(source_p->serv != NULL && source_p->servptr != NULL);
998  
999      if (ConfigServerHide.hide_servers)
1000 <      /* set netsplit message to "*.net *.split" to still show
1000 >      /*
1001 >       * Set netsplit message to "*.net *.split" to still show
1002         * that its a split, but hide the servers splitting
1003         */
1004        strcpy(splitstr, "*.net *.split");
# Line 1052 | Line 1012 | exit_client(struct Client *source_p, str
1012      {
1013        sendto_realops_flags(UMODE_ALL, L_ALL,
1014                             "%s was connected for %d seconds.  %llu/%llu sendK/recvK.",
1015 <                           source_p->name, (int)(CurrentTime - source_p->firsttime),
1015 >                           source_p->name, (int)(CurrentTime - source_p->localClient->firsttime),
1016                             source_p->localClient->send.bytes >> 10,
1017                             source_p->localClient->recv.bytes >> 10);
1018 <      ilog(L_NOTICE, "%s was connected for %d seconds.  %llu/%llu sendK/recvK.",
1019 <           source_p->name, (int)(CurrentTime - source_p->firsttime),
1018 >      ilog(LOG_TYPE_IRCD, "%s was connected for %d seconds.  %llu/%llu sendK/recvK.",
1019 >           source_p->name, (int)(CurrentTime - source_p->localClient->firsttime),
1020             source_p->localClient->send.bytes >> 10,
1021             source_p->localClient->recv.bytes >> 10);
1022      }
1023    }
1024 <  else if (IsClient(source_p) && !IsKilled(source_p))
1024 >  else if (IsClient(source_p) && !HasFlag(source_p, FLAGS_KILLED))
1025    {
1026      sendto_server(from->from, NULL, CAP_TS6, NOCAPS,
1027                    ":%s QUIT :%s", ID(source_p), comment);
# Line 1124 | Line 1084 | dead_link_on_read(struct Client *client_
1084  
1085    if (IsServer(client_p) || IsHandshake(client_p))
1086    {
1087 <    int connected = CurrentTime - client_p->firsttime;
1087 >    int connected = CurrentTime - client_p->localClient->firsttime;
1088        
1089      if (error == 0)
1090      {
# Line 1138 | Line 1098 | dead_link_on_read(struct Client *client_
1098                             "Server %s closed the connection",
1099                             get_client_name(client_p, MASK_IP));
1100  
1101 <      ilog(L_NOTICE, "Server %s closed the connection",
1101 >      ilog(LOG_TYPE_IRCD, "Server %s closed the connection",
1102             get_client_name(client_p, SHOW_IP));
1103      }
1104      else
# Line 1161 | Line 1121 | dead_link_on_read(struct Client *client_
1121      strlcpy(errmsg, "Remote host closed the connection",
1122              sizeof(errmsg));
1123    else
1124 <    ircsprintf(errmsg, "Read error: %s",
1125 <               strerror(current_error));
1124 >    snprintf(errmsg, sizeof(errmsg), "Read error: %s",
1125 >             strerror(current_error));
1126  
1127    exit_client(client_p, &me, errmsg);
1128   }
# Line 1202 | Line 1162 | exit_aborted_clients(void)
1162  
1163   /*
1164   * accept processing, this adds a form of "caller ID" to ircd
1165 < *
1165 > *
1166   * If a client puts themselves into "caller ID only" mode,
1167 < * only clients that match a client pointer they have put on
1167 > * only clients that match a client pointer they have put on
1168   * the accept list will be allowed to message them.
1169   *
1170 < * [ source.on_allow_list ] -> [ target1 ] -> [ target2 ]
1211 < *
1212 < * [target.allow_list] -> [ source1 ] -> [source2 ]
1213 < *
1214 < * i.e. a target will have a link list of source pointers it will allow
1215 < * each source client then has a back pointer pointing back
1216 < * to the client that has it on its accept list.
1217 < * This allows for exit_one_client to remove these now bogus entries
1218 < * from any client having an accept on them.
1170 > * Diane Bruce, "Dianora" db@db.net
1171   */
1172  
1173 < /* accept_message()
1174 < *
1223 < * inputs       - pointer to source client
1224 < *              - pointer to target client
1225 < * output       - 1 if accept this message 0 if not
1226 < * side effects - See if source is on target's allow list
1227 < */
1228 < int
1229 < accept_message(struct Client *source, struct Client *target)
1173 > void
1174 > del_accept(struct split_nuh_item *accept_p, struct Client *client_p)
1175   {
1176 <  dlink_node *ptr;
1232 <
1233 <  DLINK_FOREACH(ptr, target->allow_list.head)
1234 <  {
1235 <    struct Client *target_p = ptr->data;
1236 <
1237 <    if (source == target_p)
1238 <      return (1);
1239 <  }
1240 <
1241 <  if (IsSoftCallerId(target))
1242 <  {
1243 <    DLINK_FOREACH(ptr, target->channel.head)
1244 <      if (IsMember(source, ((struct Membership *)ptr->data)->chptr))
1245 <        return (1);
1246 <  }
1176 >  dlinkDelete(&accept_p->node, &client_p->localClient->acceptlist);
1177  
1178 <  return (0);
1178 >  MyFree(accept_p->nickptr);
1179 >  MyFree(accept_p->userptr);
1180 >  MyFree(accept_p->hostptr);
1181 >  MyFree(accept_p);
1182   }
1183  
1184 < /* del_from_accept()
1185 < *
1186 < * inputs       - pointer to source client
1254 < *              - pointer to target client
1255 < * output       - NONE
1256 < * side effects - Delete's source pointer to targets allow list
1257 < *
1258 < * Walk through the target's accept list, remove if source is found,
1259 < * Then walk through the source's on_accept_list remove target if found.
1260 < */
1261 < void
1262 < del_from_accept(struct Client *source, struct Client *target)
1184 > struct split_nuh_item *
1185 > find_accept(const char *nick, const char *user,
1186 >            const char *host, struct Client *client_p, int do_match)
1187   {
1188 <  dlink_node *ptr;
1189 <  dlink_node *ptr2;
1190 <  dlink_node *next_ptr;
1267 <  dlink_node *next_ptr2;
1268 <  struct Client *target_p;
1188 >  dlink_node *ptr = NULL;
1189 >  /* XXX We wouldn't need that if match() would return 0 on match */
1190 >  int (*cmpfunc)(const char *, const char *) = do_match ? match : irccmp;
1191  
1192 <  DLINK_FOREACH_SAFE(ptr, next_ptr, target->allow_list.head)
1192 >  DLINK_FOREACH(ptr, client_p->localClient->acceptlist.head)
1193    {
1194 <    target_p = ptr->data;
1273 <
1274 <    if (source == target_p)
1275 <    {
1276 <      dlinkDelete(ptr, &target->allow_list);
1277 <      free_dlink_node(ptr);
1278 <
1279 <      DLINK_FOREACH_SAFE(ptr2, next_ptr2, source->on_allow_list.head)
1280 <      {
1281 <        target_p = ptr2->data;
1194 >    struct split_nuh_item *accept_p = ptr->data;
1195  
1196 <        if (target == target_p)
1197 <        {
1198 <          dlinkDelete(ptr2, &source->on_allow_list);
1199 <          free_dlink_node(ptr2);
1287 <        }
1288 <      }
1289 <    }
1196 >    if (cmpfunc(accept_p->nickptr, nick) == do_match &&
1197 >        cmpfunc(accept_p->userptr, user) == do_match &&
1198 >        cmpfunc(accept_p->hostptr, host) == do_match)
1199 >      return accept_p;
1200    }
1291 }
1292
1293 /* del_all_accepts()
1294 *
1295 * inputs       - pointer to exiting client
1296 * output       - NONE
1297 * side effects - Walk through given clients allow_list and on_allow_list
1298 *                remove all references to this client
1299 */
1300 void
1301 del_all_accepts(struct Client *client_p)
1302 {
1303  dlink_node *ptr, *next_ptr;
1304
1305  DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->allow_list.head)
1306    del_from_accept(ptr->data, client_p);
1201  
1202 <  DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->on_allow_list.head)
1309 <    del_from_accept(client_p, ptr->data);
1202 >  return NULL;
1203   }
1204  
1205 < /* del_all_their_accepts()
1313 < *
1314 < * inputs       - pointer to exiting client
1315 < * output       - NONE
1316 < * side effects - Walk through given clients on_allow_list
1317 < *                remove all references to this client,
1318 < *                allow this client to keep their own allow_list
1319 < */
1320 < void
1321 < del_all_their_accepts(struct Client *client_p)
1322 < {
1323 <  dlink_node *ptr, *next_ptr;
1324 <
1325 <  DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->on_allow_list.head)
1326 <    del_from_accept(client_p, ptr->data);
1327 < }
1328 <
1329 < /* set_initial_nick()
1330 < *
1331 < * inputs
1332 < * output
1333 < * side effects -
1205 > /* accept_message()
1206   *
1207 < * This function is only called to set up an initially registering
1208 < * client.
1207 > * inputs       - pointer to source client
1208 > *              - pointer to target client
1209 > * output       - 1 if accept this message 0 if not
1210 > * side effects - See if source is on target's allow list
1211   */
1212 < void
1213 < set_initial_nick(struct Client *client_p, struct Client *source_p,
1214 <                 const char *nick)
1212 > int
1213 > accept_message(struct Client *source,
1214 >               struct Client *target)
1215   {
1216 < char buf[USERLEN + 1];
1343 <
1344 <  /* Client setting NICK the first time */
1345 <  
1346 <  /* This had to be copied here to avoid problems.. */
1347 <  source_p->tsinfo = CurrentTime;
1348 <  source_p->localClient->registration &= ~REG_NEED_NICK;
1349 <
1350 <  if (source_p->name[0])
1351 <    hash_del_client(source_p);
1216 >  dlink_node *ptr = NULL;
1217  
1218 <  strlcpy(source_p->name, nick, sizeof(source_p->name));
1219 <  hash_add_client(source_p);
1218 >  if (source == target || find_accept(source->name, source->username,
1219 >                                      source->host, target, 1))
1220 >    return 1;
1221  
1222 <  /* fd_desc is long enough */
1223 <  fd_note(&client_p->localClient->fd, "Nick: %s", nick);
1224 <  
1225 <  if (!source_p->localClient->registration)
1360 <  {
1361 <    strlcpy(buf, source_p->username, sizeof(buf));
1222 >  if (HasUMode(target, UMODE_SOFTCALLERID))
1223 >    DLINK_FOREACH(ptr, target->channel.head)
1224 >      if (IsMember(source, ((struct Membership *)ptr->data)->chptr))
1225 >        return 1;
1226  
1227 <    /*
1364 <     * USER already received, now we have NICK.
1365 <     * *NOTE* For servers "NICK" *must* precede the
1366 <     * user message (giving USER before NICK is possible
1367 <     * only for local client connection!). register_user
1368 <     * may reject the client and call exit_client for it
1369 <     * --must test this and exit m_nick too!!!
1370 <     */
1371 <    register_local_user(client_p, source_p, nick, buf);
1372 <  }
1227 >  return 0;
1228   }
1229  
1230 < /* change_local_nick()
1230 > /* del_all_accepts()
1231   *
1232 < * inputs       - pointer to server
1233 < *              - pointer to client
1234 < *              - nick
1380 < * output       -
1381 < * side effects - changes nick of a LOCAL user
1232 > * inputs       - pointer to exiting client
1233 > * output       - NONE
1234 > * side effects - Walk through given clients acceptlist and remove all entries
1235   */
1236   void
1237 < change_local_nick(struct Client *client_p, struct Client *source_p, const char *nick)
1237 > del_all_accepts(struct Client *client_p)
1238   {
1239 <  int samenick = 0;
1387 <
1388 <  assert(source_p->name[0] && !EmptyString(nick));
1389 <
1390 <  /*
1391 <   * Client just changing his/her nick. If he/she is
1392 <   * on a channel, send note of change to all clients
1393 <   * on that channel. Propagate notice to other servers.
1394 <   */
1395 <  if ((source_p->localClient->last_nick_change +
1396 <       ConfigFileEntry.max_nick_time) < CurrentTime)
1397 <    source_p->localClient->number_of_nick_changes = 0;
1398 <  source_p->localClient->last_nick_change = CurrentTime;
1399 <  source_p->localClient->number_of_nick_changes++;
1400 <
1401 <  if ((ConfigFileEntry.anti_nick_flood &&
1402 <      (source_p->localClient->number_of_nick_changes
1403 <       <= ConfigFileEntry.max_nick_changes)) ||
1404 <     !ConfigFileEntry.anti_nick_flood ||
1405 <     (IsOper(source_p) && ConfigFileEntry.no_oper_flood))
1406 <  {
1407 <    samenick = !irccmp(source_p->name, nick);
1408 <
1409 <    if (!samenick)
1410 <    {
1411 <      /*
1412 <       * Make sure everyone that has this client on its accept list
1413 <       * loses that reference.
1414 <       */
1415 <      del_all_their_accepts(source_p);
1416 <      source_p->tsinfo = CurrentTime;
1417 <      clear_ban_cache_client(source_p);
1418 <      watch_check_hash(source_p, RPL_LOGOFF);
1419 <    }
1420 <
1421 <    /* XXX - the format of this notice should eventually be changed
1422 <     * to either %s[%s@%s], or even better would be get_client_name() -bill
1423 <     */
1424 <    sendto_realops_flags(UMODE_NCHANGE, L_ALL, "Nick change: From %s to %s [%s@%s]",
1425 <                         source_p->name, nick, source_p->username, source_p->host);
1426 <    sendto_common_channels_local(source_p, 1, ":%s!%s@%s NICK :%s",
1427 <                                 source_p->name, source_p->username,
1428 <                                 source_p->host, nick);
1429 <    add_history(source_p, 1);
1430 <
1431 <    sendto_server(client_p, NULL, CAP_TS6, NOCAPS,
1432 <                  ":%s NICK %s :%lu",
1433 <                  ID(source_p), nick, (unsigned long)source_p->tsinfo);
1434 <    sendto_server(client_p, NULL, NOCAPS, CAP_TS6,
1435 <                  ":%s NICK %s :%lu",
1436 <                  source_p->name, nick, (unsigned long)source_p->tsinfo);
1239 >  dlink_node *ptr = NULL, *next_ptr = NULL;
1240  
1241 <    hash_del_client(source_p);
1242 <    strcpy(source_p->name, nick);
1440 <    hash_add_client(source_p);
1441 <
1442 <    if (!samenick)
1443 <      watch_check_hash(source_p, RPL_LOGON);
1444 <
1445 <    /* fd_desc is long enough */
1446 <    fd_note(&client_p->localClient->fd, "Nick: %s", nick);
1447 <  }
1448 <  else
1449 <    sendto_one(source_p, form_str(ERR_NICKTOOFAST),
1450 <               me.name, source_p->name, source_p->name,
1451 <               nick, ConfigFileEntry.max_nick_time);
1241 >  DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->localClient->acceptlist.head)
1242 >    del_accept(ptr->data, client_p);
1243   }

Diff Legend

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