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

Comparing ircd-hybrid/trunk/src/s_serv.c (file contents):
Revision 3280 by michael, Mon Apr 7 18:21:22 2014 UTC vs.
Revision 3303 by michael, Sun Apr 13 11:19:36 2014 UTC

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