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

Comparing ircd-hybrid/trunk/src/s_serv.c (file contents):
Revision 3246 by michael, Sun Mar 30 17:37:13 2014 UTC vs.
Revision 3303 by michael, Sun Apr 13 11:19:36 2014 UTC

# Line 30 | Line 30
30   #include "rsa.h"
31   #endif
32   #include "list.h"
33 #include "channel.h"
34 #include "channel_mode.h"
33   #include "client.h"
34   #include "event.h"
37 #include "fdlist.h"
35   #include "hash.h"
36   #include "irc_string.h"
37   #include "ircd.h"
# Line 42 | Line 39
39   #include "s_bsd.h"
40   #include "numeric.h"
41   #include "packet.h"
45 #include "irc_res.h"
42   #include "conf.h"
43   #include "s_serv.h"
44   #include "log.h"
# Line 57 | Line 53
53  
54   dlink_list flatten_links;
55   static dlink_list cap_list = { NULL, NULL, 0 };
60 static void server_burst(struct Client *);
61 static void burst_all(struct Client *);
62 static void send_tb(struct Client *client_p, struct Channel *chptr);
63
56   static CNCB serv_connect_callback;
57  
66 static void burst_members(struct Client *, struct Channel *);
58  
59   /*
60   * write_links_file
# Line 552 | Line 543 | send_capabilities(struct Client *client_
543    sendto_one(client_p, "CAPAB :%s", msgbuf);
544   }
545  
555 /* sendnick_TS()
556 *
557 * inputs       - client (server) to send nick towards
558 *          - client to send nick for
559 * output       - NONE
560 * side effects - NICK message is sent towards given client_p
561 */
562 void
563 sendnick_TS(struct Client *client_p, struct Client *target_p)
564 {
565  char ubuf[IRCD_BUFSIZE] = "";
566
567  if (!IsClient(target_p))
568    return;
569
570  send_umode(NULL, target_p, 0, SEND_UMODES, ubuf);
571
572  if (ubuf[0] == '\0')
573  {
574    ubuf[0] = '+';
575    ubuf[1] = '\0';
576  }
577
578  if (IsCapable(client_p, CAP_SVS))
579    sendto_one(client_p, ":%s UID %s %d %lu %s %s %s %s %s %s :%s",
580               target_p->servptr->id,
581               target_p->name, target_p->hopcount + 1,
582               (unsigned long) target_p->tsinfo,
583               ubuf, target_p->username, target_p->host,
584               (MyClient(target_p) && IsIPSpoof(target_p)) ?
585               "0" : target_p->sockhost, target_p->id,
586               target_p->svid, target_p->info);
587  else
588    sendto_one(client_p, ":%s UID %s %d %lu %s %s %s %s %s :%s",
589               target_p->servptr->id,
590               target_p->name, target_p->hopcount + 1,
591               (unsigned long) target_p->tsinfo,
592               ubuf, target_p->username, target_p->host,
593               (MyClient(target_p) && IsIPSpoof(target_p)) ?
594               "0" : target_p->sockhost, target_p->id, target_p->info);
595
596  if (!EmptyString(target_p->certfp))
597    sendto_one(client_p, ":%s CERTFP %s", target_p->id, target_p->certfp);
598
599  if (target_p->away[0])
600    sendto_one(client_p, ":%s AWAY :%s", target_p->id, target_p->away);
601
602 }
603
546   /*
547   * show_capabilities - show current server capabilities
548   *
# Line 646 | Line 588 | make_server(struct Client *client_p)
588    return client_p->serv;
589   }
590  
649 /* server_estab()
650 *
651 * inputs       - pointer to a struct Client
652 * output       -
653 * side effects -
654 */
655 void
656 server_estab(struct Client *client_p)
657 {
658  struct MaskItem *conf = NULL;
659  char *host;
660  const char *inpath;
661  static char inpath_ip[HOSTLEN * 2 + USERLEN + 6];
662  dlink_node *ptr;
663 #ifdef HAVE_LIBCRYPTO
664  const COMP_METHOD *compression = NULL, *expansion = NULL;
665 #endif
666
667  assert(client_p);
668
669  strlcpy(inpath_ip, get_client_name(client_p, SHOW_IP), sizeof(inpath_ip));
670
671  inpath = get_client_name(client_p, MASK_IP); /* "refresh" inpath with host */
672  host   = client_p->name;
673
674  if ((conf = find_conf_name(&client_p->localClient->confs, host, CONF_SERVER))
675      == NULL)
676  {
677    /* This shouldn't happen, better tell the ops... -A1kmm */
678    sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
679                         "Warning: Lost connect{} block "
680                         "for server %s(this shouldn't happen)!", host);
681    exit_client(client_p, "Lost connect{} block!");
682    return;
683  }
684
685  MyFree(client_p->localClient->passwd);
686  client_p->localClient->passwd = NULL;
687
688  /* Its got identd, since its a server */
689  SetGotId(client_p);
690
691  /* If there is something in the serv_list, it might be this
692   * connecting server..
693   */
694  if (!ServerInfo.hub && serv_list.head)
695  {
696    if (client_p != serv_list.head->data || serv_list.head->next)
697    {
698      ++ServerStats.is_ref;
699      sendto_one(client_p, "ERROR :I'm a leaf not a hub");
700      exit_client(client_p, "I'm a leaf");
701      return;
702    }
703  }
704
705  if (IsUnknown(client_p))
706  {
707    sendto_one(client_p, "PASS %s TS %d %s", conf->spasswd, TS_CURRENT, me.id);
708
709    send_capabilities(client_p, 0);
710
711    sendto_one(client_p, "SERVER %s 1 :%s%s",
712               me.name, ConfigServerHide.hidden ? "(H) " : "", me.info);
713  }
714
715  sendto_one(client_p, "SVINFO %d %d 0 :%lu", TS_CURRENT, TS_MIN,
716             (unsigned long)CurrentTime);
717
718  /* XXX Does this ever happen? I don't think so -db */
719  detach_conf(client_p, CONF_OPER);
720
721  /* *WARNING*
722  **    In the following code in place of plain server's
723  **    name we send what is returned by get_client_name
724  **    which may add the "sockhost" after the name. It's
725  **    *very* *important* that there is a SPACE between
726  **    the name and sockhost (if present). The receiving
727  **    server will start the information field from this
728  **    first blank and thus puts the sockhost into info.
729  **    ...a bit tricky, but you have been warned, besides
730  **    code is more neat this way...  --msa
731  */
732  client_p->servptr = &me;
733
734  if (IsClosing(client_p))
735    return;
736
737  SetServer(client_p);
738
739  /* Some day, all these lists will be consolidated *sigh* */
740  dlinkAdd(client_p, &client_p->lnode, &me.serv->server_list);
741
742  assert(dlinkFind(&unknown_list, client_p));
743
744  dlink_move_node(&client_p->localClient->lclient_node,
745                  &unknown_list, &serv_list);
746
747  Count.myserver++;
748
749  dlinkAdd(client_p, make_dlink_node(), &global_serv_list);
750  hash_add_client(client_p);
751  hash_add_id(client_p);
752
753  /* doesnt duplicate client_p->serv if allocated this struct already */
754  make_server(client_p);
755
756  /* fixing eob timings.. -gnp */
757  client_p->localClient->firsttime = CurrentTime;
758
759  if (find_matching_name_conf(CONF_SERVICE, client_p->name, NULL, NULL, 0))
760    AddFlag(client_p, FLAGS_SERVICE);
761
762  /* Show the real host/IP to admins */
763 #ifdef HAVE_LIBCRYPTO
764  if (client_p->localClient->fd.ssl)
765  {
766    compression = SSL_get_current_compression(client_p->localClient->fd.ssl);
767    expansion   = SSL_get_current_expansion(client_p->localClient->fd.ssl);
768
769    sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
770                         "Link with %s established: [SSL: %s, Compression/Expansion method: %s/%s] (Capabilities: %s)",
771                         inpath_ip, ssl_get_cipher(client_p->localClient->fd.ssl),
772                         compression ? SSL_COMP_get_name(compression) : "NONE",
773                         expansion ? SSL_COMP_get_name(expansion) : "NONE",
774                         show_capabilities(client_p));
775    /* Now show the masked hostname/IP to opers */
776    sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
777                         "Link with %s established: [SSL: %s, Compression/Expansion method: %s/%s] (Capabilities: %s)",
778                         inpath, ssl_get_cipher(client_p->localClient->fd.ssl),
779                         compression ? SSL_COMP_get_name(compression) : "NONE",
780                         expansion ? SSL_COMP_get_name(expansion) : "NONE",
781                         show_capabilities(client_p));
782    ilog(LOG_TYPE_IRCD, "Link with %s established: [SSL: %s, Compression/Expansion method: %s/%s] (Capabilities: %s)",
783         inpath_ip, ssl_get_cipher(client_p->localClient->fd.ssl),
784         compression ? SSL_COMP_get_name(compression) : "NONE",
785         expansion ? SSL_COMP_get_name(expansion) : "NONE",
786         show_capabilities(client_p));
787  }
788  else
789 #endif
790  {
791    sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
792                         "Link with %s established: (Capabilities: %s)",
793                         inpath_ip, show_capabilities(client_p));
794    /* Now show the masked hostname/IP to opers */
795    sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
796                         "Link with %s established: (Capabilities: %s)",
797                         inpath, show_capabilities(client_p));
798    ilog(LOG_TYPE_IRCD, "Link with %s established: (Capabilities: %s)",
799         inpath_ip, show_capabilities(client_p));
800  }
801
802  fd_note(&client_p->localClient->fd, "Server: %s", client_p->name);
803
804  sendto_server(client_p, NOCAPS, NOCAPS, ":%s SID %s 2 %s :%s%s",
805                me.id, client_p->name, client_p->id,
806                IsHidden(client_p) ? "(H) " : "", client_p->info);
807
808  /*
809   * Pass on my client information to the new server
810   *
811   * First, pass only servers (idea is that if the link gets
812   * cancelled beacause the server was already there,
813   * there are no NICK's to be cancelled...). Of course,
814   * if cancellation occurs, all this info is sent anyway,
815   * and I guess the link dies when a read is attempted...? --msa
816   *
817   * Note: Link cancellation to occur at this point means
818   * that at least two servers from my fragment are building
819   * up connection this other fragment at the same time, it's
820   * a race condition, not the normal way of operation...
821   *
822   * ALSO NOTE: using the get_client_name for server names--
823   *    see previous *WARNING*!!! (Also, original inpath
824   *    is destroyed...)
825   */
826
827  DLINK_FOREACH_PREV(ptr, global_serv_list.tail)
828  {
829    struct Client *target_p = ptr->data;
830
831    /* target_p->from == target_p for target_p == client_p */
832    if (IsMe(target_p) || target_p->from == client_p)
833      continue;
834
835    sendto_one(client_p, ":%s SID %s %d %s :%s%s",
836               target_p->servptr->id, target_p->name, target_p->hopcount+1,
837               target_p->id, IsHidden(target_p) ? "(H) " : "",
838               target_p->info);
839
840    if (HasFlag(target_p, FLAGS_EOB))
841      sendto_one(client_p, ":%s EOB", target_p->id, client_p);
842  }
843
844  server_burst(client_p);
845 }
846
847 /* server_burst()
848 *
849 * inputs       - struct Client pointer server
850 *              -
851 * output       - none
852 * side effects - send a server burst
853 * bugs         - still too long
854 */
855 static void
856 server_burst(struct Client *client_p)
857 {
858  /* Send it in the shortened format with the TS, if
859  ** it's a TS server; walk the list of channels, sending
860  ** all the nicks that haven't been sent yet for each
861  ** channel, then send the channel itself -- it's less
862  ** obvious than sending all nicks first, but on the
863  ** receiving side memory will be allocated more nicely
864  ** saving a few seconds in the handling of a split
865  ** -orabidoo
866  */
867
868  burst_all(client_p);
869
870  /* EOB stuff is now in burst_all */
871  /* Always send a PING after connect burst is done */
872  sendto_one(client_p, "PING :%s", me.id);
873 }
874
875 /* burst_all()
876 *
877 * inputs       - pointer to server to send burst to
878 * output       - NONE
879 * side effects - complete burst of channels/nicks is sent to client_p
880 */
881 static void
882 burst_all(struct Client *client_p)
883 {
884  dlink_node *ptr = NULL;
885
886  DLINK_FOREACH(ptr, global_channel_list.head)
887  {
888    struct Channel *chptr = ptr->data;
889
890    if (dlink_list_length(&chptr->members))
891    {
892      burst_members(client_p, chptr);
893      send_channel_modes(client_p, chptr);
894
895      if (IsCapable(client_p, CAP_TBURST))
896        send_tb(client_p, chptr);
897    }
898  }
899
900  /* also send out those that are not on any channel
901   */
902  DLINK_FOREACH(ptr, global_client_list.head)
903  {
904    struct Client *target_p = ptr->data;
905
906    if (!HasFlag(target_p, FLAGS_BURSTED) && target_p->from != client_p)
907      sendnick_TS(client_p, target_p);
908
909    DelFlag(target_p, FLAGS_BURSTED);
910  }
911
912  if (IsCapable(client_p, CAP_EOB))
913    sendto_one(client_p, ":%s EOB", me.id);
914 }
915
916 /*
917 * send_tb
918 *
919 * inputs       - pointer to Client
920 *              - pointer to channel
921 * output       - NONE
922 * side effects - Called on a server burst when
923 *                server is CAP_TBURST capable
924 */
925 static void
926 send_tb(struct Client *client_p, struct Channel *chptr)
927 {
928  /*
929   * We may also send an empty topic here, but only if topic_time isn't 0,
930   * i.e. if we had a topic that got unset.  This is required for syncing
931   * topics properly.
932   *
933   * Imagine the following scenario: Our downlink introduces a channel
934   * to us with a TS that is equal to ours, but the channel topic on
935   * their side got unset while the servers were in splitmode, which means
936   * their 'topic' is newer.  They simply wanted to unset it, so we have to
937   * deal with it in a more sophisticated fashion instead of just resetting
938   * it to their old topic they had before.  Read m_tburst.c:ms_tburst
939   * for further information   -Michael
940   */
941  if (chptr->topic_time)
942    sendto_one(client_p, ":%s TBURST %lu %s %lu %s :%s", me.id,
943               (unsigned long)chptr->channelts, chptr->chname,
944               (unsigned long)chptr->topic_time,
945               chptr->topic_info,
946               chptr->topic);
947 }
948
949 /* burst_members()
950 *
951 * inputs       - pointer to server to send members to
952 *              - dlink_list pointer to membership list to send
953 * output       - NONE
954 * side effects -
955 */
956 static void
957 burst_members(struct Client *client_p, struct Channel *chptr)
958 {
959  struct Client *target_p;
960  struct Membership *ms;
961  dlink_node *ptr;
962
963  DLINK_FOREACH(ptr, chptr->members.head)
964  {
965    ms       = ptr->data;
966    target_p = ms->client_p;
967
968    if (!HasFlag(target_p, FLAGS_BURSTED))
969    {
970      AddFlag(target_p, FLAGS_BURSTED);
971
972      if (target_p->from != client_p)
973        sendnick_TS(client_p, target_p);
974    }
975  }
976 }
977
591   /* New server connection code
592   * Based upon the stuff floating about in s_bsd.c
593   *   -- adrian

Diff Legend

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