X-Git-Url: http://git.pk910.de/?a=blobdiff_plain;f=ircd%2Fm_server.c;h=1e38d39746079a768573c3e51e432d62175c62a0;hb=2a6a833ef097f5c53726ddd6b59b5643bfa18143;hp=f433c3d053c0a7e0bb797ab44a6bb0251f65fc24;hpb=41e9f41d2cca307c6d6b8b5a68f49d22bafda948;p=ircu2.10.12-pk.git diff --git a/ircd/m_server.c b/ircd/m_server.c index f433c3d..1e38d39 100644 --- a/ircd/m_server.c +++ b/ircd/m_server.c @@ -49,7 +49,7 @@ #include "send.h" #include "userload.h" -#include +/* #include -- Now using assert in ircd_log.h */ #include #include @@ -100,27 +100,56 @@ parse_protocol(const char *proto) * or be disallowed by leaf and hub configuration directives. * @param[in] cptr Neighbor who sent the message. * @param[in] sptr Client that originated the message. - * @param[in] LHcptr Who to SQUIT on error (if NULL, SQUIT new server). - * @param[in] lhconf Leaf or hub configuration block to use. * @param[out] ghost If non-NULL, receives ghost timestamp for new server. * @param[in] host Name of new server. * @param[in] numnick Numnick mask of new server. * @param[in] timestamp Claimed link timestamp of new server. - * @param[in] active_lh_line Pseudo-enum value for rejection reason. - * 0 means no leaf or hub restrictions. 1 means \a lhconf is a leaf - * rule. 2 means \a lhconf is a hub rule. 3 means #me does not have - * the HUB feature but already has a server link. + * @param[in] hop Number of hops to the new server. + * @param[in] junction Non-zero if the new server is still bursting. * @return CPTR_KILLED if \a cptr was SQUIT. 0 if some other server * was SQUIT. 1 if the new server is allowed. */ static int -check_loop_and_lh(struct Client* cptr, struct Client *sptr, struct Client *LHcptr, struct ConfItem *lhconf, time_t *ghost, const char *host, const char *numnick, time_t timestamp, int active_lh_line) +check_loop_and_lh(struct Client* cptr, struct Client *sptr, time_t *ghost, const char *host, const char *numnick, time_t timestamp, int hop, int junction) { struct Client* acptr; + struct Client* LHcptr = NULL; + struct ConfItem* lhconf; + int active_lh_line = 0, ii; if (ghost) *ghost = 0; + /* + * Calculate type of connect limit and applicable config item. + */ + lhconf = find_conf_byname(cli_confs(cptr), cli_name(cptr), CONF_SERVER); + assert(lhconf != NULL); + if (ghost) + { + if (!feature_bool(FEAT_HUB)) + for (ii = 0; ii <= HighestFd; ii++) + if (LocalClientArray[ii] && IsServer(LocalClientArray[ii])) { + active_lh_line = 3; + break; + } + } + else if (hop > lhconf->maximum) + { + active_lh_line = 1; + } + else if (lhconf->hub_limit && match(lhconf->hub_limit, host)) + { + struct Client *ac3ptr; + active_lh_line = 2; + if (junction) + for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = cli_serv(ac3ptr)->up) + if (IsJunction(ac3ptr)) { + LHcptr = ac3ptr; + break; + } + } + /* * We want to find IsConnecting() and IsHandshake() too, * use FindClient(). @@ -175,7 +204,7 @@ check_loop_and_lh(struct Client* cptr, struct Client *sptr, struct Client *LHcpt } /* * Avoid other nick collisions... - * This is a doubtfull test though, what else would it be + * This is a doubtful test though, what else would it be * when it has a server.name ? */ else if (!IsServer(acptr) && !IsHandshake(acptr)) @@ -370,37 +399,33 @@ check_loop_and_lh(struct Client* cptr, struct Client *sptr, struct Client *LHcpt if (active_lh_line) { - if (LHcptr == 0) { - return exit_new_server(cptr, sptr, host, timestamp, - (active_lh_line == 2) ? "Non-Hub link %s <- %s(%s), check H:" : - "Leaf-only link %s <- %s(%s), check L:", - cli_name(cptr), host, - lhconf ? (lhconf->name ? lhconf->name : "*") : "!"); + int killed = 0; + if (LHcptr) + killed = a_kills_b_too(LHcptr, sptr); + else + LHcptr = sptr; + if (active_lh_line == 1) + { + if (exit_client_msg(cptr, LHcptr, &me, + "Maximum hops exceeded for %s at %s", + cli_name(cptr), host) == CPTR_KILLED) + return CPTR_KILLED; + } + else if (active_lh_line == 2) + { + if (exit_client_msg(cptr, LHcptr, &me, + "%s is not allowed to hub for %s", + cli_name(cptr), host) == CPTR_KILLED) + return CPTR_KILLED; } else { - int killed = a_kills_b_too(LHcptr, sptr); - if (active_lh_line < 3) - { - if (exit_client_msg(cptr, LHcptr, &me, - (active_lh_line == 2) ? "Non-Hub link %s <- %s(%s), check H:" : - "Leaf-only link %s <- %s(%s), check L:", - cli_name(cptr), host, - lhconf ? (lhconf->name ? lhconf->name : "*") : "!") == CPTR_KILLED) - return CPTR_KILLED; - } - else - { - ServerStats->is_ref++; - if (exit_client(cptr, LHcptr, &me, "I'm a leaf, define HUB") == CPTR_KILLED) - return CPTR_KILLED; - } - /* - * Did we kill the incoming server off already ? - */ - if (killed) - return 0; + ServerStats->is_ref++; + if (exit_client(cptr, LHcptr, &me, "I'm a leaf, define HUB") == CPTR_KILLED) + return CPTR_KILLED; } + /* We just squit somebody, and it wasn't cptr. */ + return 0; } return 1; @@ -451,6 +476,20 @@ check_start_timestamp(struct Client *cptr, time_t timestamp, time_t start_timest } } +/** Interpret a server's flags. + * + * @param[in] cptr New server structure. + * @param[in] flags String listing server's P10 flags. + */ +void set_server_flags(struct Client *cptr, const char *flags) +{ + while (*flags) switch (*flags++) { + case 'h': SetHub(cptr); break; + case 's': SetService(cptr); break; + case '6': SetIPv6(cptr); break; + } +} + /** Handle a SERVER message from an unregistered connection. * * \a parv has the following elements: @@ -471,15 +510,11 @@ check_start_timestamp(struct Client *cptr, time_t timestamp, time_t start_timest */ int mr_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { - char* ch; - int i; char* host; - const char* encr; struct ConfItem* aconf; struct Jupe* ajupe; int hop; int ret; - int active_lh_line = 0; unsigned short prot; time_t start_timestamp; time_t timestamp; @@ -519,6 +554,9 @@ int mr_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) /* * Detect protocol */ + hop = atoi(parv[2]); + start_timestamp = atoi(parv[3]); + timestamp = atoi(parv[4]); prot = parse_protocol(parv[5]); if (!prot) return exit_client_msg(cptr, sptr, &me, "Bogus protocol (%s)", parv[5]); @@ -526,9 +564,6 @@ int mr_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) return exit_new_server(cptr, sptr, host, timestamp, "Incompatible protocol: %s", parv[5]); - hop = atoi(parv[2]); - start_timestamp = atoi(parv[3]); - timestamp = atoi(parv[4]); Debug((DEBUG_INFO, "Got SERVER %s with timestamp [%s] age %Tu (%Tu)", host, parv[4], start_timestamp, cli_serv(&me)->timestamp)); @@ -552,7 +587,7 @@ int mr_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) log_write(LS_NETWORK, L_NOTICE, LOG_NOSNOTICE, "Received unauthorized " "connection from %C [%s]", cptr, ircd_ntoa(&cli_ip(cptr))); - return exit_client(cptr, cptr, &me, "No C:line"); + return exit_client(cptr, cptr, &me, "No Connect block"); } host = cli_name(cptr); @@ -566,9 +601,8 @@ int mr_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) return exit_client_msg(cptr, cptr, &me, "Access denied. No conf line for server %s", cli_name(cptr)); } - encr = cli_passwd(cptr); - if (*aconf->passwd && !!strcmp(aconf->passwd, encr)) { + if (*aconf->passwd && !!strcmp(aconf->passwd, cli_passwd(cptr))) { ++ServerStats->is_ref; sendto_opmask_butone(0, SNO_OLDSNO, "Access denied (passwd mismatch) %s", cli_name(cptr)); @@ -578,15 +612,7 @@ int mr_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) memset(cli_passwd(cptr), 0, sizeof(cli_passwd(cptr))); - if (!feature_bool(FEAT_HUB)) { - for (i = 0; i <= HighestFd; i++) - if (LocalClientArray[i] && IsServer(LocalClientArray[i])) { - active_lh_line = 3; - break; - } - } - - ret = check_loop_and_lh(cptr, sptr, NULL, NULL, &ghost, host, (parc > 7 ? parv[6] : NULL), timestamp, active_lh_line); + ret = check_loop_and_lh(cptr, sptr, &ghost, host, (parc > 7 ? parv[6] : NULL), timestamp, hop, 1); if (ret != 1) return ret; @@ -594,21 +620,18 @@ int mr_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) cli_serv(cptr)->timestamp = timestamp; cli_serv(cptr)->prot = prot; cli_serv(cptr)->ghost = ghost; + memset(cli_privs(cptr), 255, sizeof(struct Privs)); + ClrPriv(cptr, PRIV_SET); SetServerYXX(cptr, cptr, parv[6]); - if (*parv[7] == '+') { - for (ch = parv[7] + 1; *ch; ch++) - switch (*ch) { - case 'h': - SetHub(cptr); - break; - case 's': - SetService(cptr); - break; - } - } + /* Attach any necessary UWorld config items. */ + attach_confs_byhost(cptr, host, CONF_UWORLD); - check_start_timestamp(cptr, timestamp, start_timestamp, TStime()); + if (*parv[7] == '+') + set_server_flags(cptr, parv[7] + 1); + + recv_time = TStime(); + check_start_timestamp(cptr, timestamp, start_timestamp, recv_time); ret = server_estab(cptr, aconf); if (feature_bool(FEAT_RELIABLE_CLOCK) && @@ -644,16 +667,12 @@ int mr_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) */ int ms_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) { - char* ch; int i; char* host; struct Client* acptr; struct Client* bcptr; - struct Client* LHcptr; - struct ConfItem* lhconf; int hop; int ret; - int active_lh_line = 0; unsigned short prot; time_t start_timestamp; time_t timestamp; @@ -674,6 +693,9 @@ int ms_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) /* * Detect protocol */ + hop = atoi(parv[2]); + start_timestamp = atoi(parv[3]); + timestamp = atoi(parv[4]); prot = parse_protocol(parv[5]); if (!prot) return exit_client_msg(cptr, sptr, &me, "Bogus protocol (%s)", parv[5]); @@ -681,9 +703,6 @@ int ms_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) return exit_new_server(cptr, sptr, host, timestamp, "Incompatible protocol: %s", parv[5]); - hop = atoi(parv[2]); - start_timestamp = atoi(parv[3]); - timestamp = atoi(parv[4]); Debug((DEBUG_INFO, "Got SERVER %s with timestamp [%s] age %Tu (%Tu)", host, parv[4], start_timestamp, cli_serv(&me)->timestamp)); @@ -691,50 +710,11 @@ int ms_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) return exit_client_msg(cptr, sptr, &me, "Bogus timestamps (%s %s)", parv[3], parv[4]); - /* - * A local server introduces a new server behind this link. - * Check if this is allowed according L:, H: and Q: lines. - */ if (parv[parc - 1][0] == '\0') return exit_client_msg(cptr, cptr, &me, "No server info specified for %s", host); - /* - * See if the newly found server is behind a guaranteed - * leaf (L-line). If so, close the link. - */ - if ((lhconf = find_conf_byhost(cli_confs(cptr), cli_name(cptr), CONF_LEAF)) && - (!lhconf->address.port || (hop > lhconf->address.port))) - { - /* - * L: lines normally come in pairs, here we try to - * make sure that the oldest link is squitted, not - * both. - */ - active_lh_line = 1; - if (timestamp <= cli_serv(cptr)->timestamp) - LHcptr = 0; /* Kill incoming server */ - else - LHcptr = cptr; /* Squit ourselfs */ - } - else if (!(lhconf = find_conf_byname(cli_confs(cptr), cli_name(cptr), CONF_HUB)) || - (lhconf->address.port && (hop > lhconf->address.port)) || - (!BadPtr(lhconf->host) && match(lhconf->host, host))) - { - struct Client *ac3ptr; - active_lh_line = 2; - /* Look for net junction causing this: */ - LHcptr = 0; /* incoming server */ - if (*parv[5] != 'J') { - for (ac3ptr = sptr; ac3ptr != &me; ac3ptr = cli_serv(ac3ptr)->up) { - if (IsJunction(ac3ptr)) { - LHcptr = ac3ptr; - break; - } - } - } - } - ret = check_loop_and_lh(cptr, sptr, LHcptr, lhconf, NULL, host, (parc > 7 ? parv[6] : NULL), timestamp, active_lh_line); + ret = check_loop_and_lh(cptr, sptr, NULL, host, (parc > 7 ? parv[6] : NULL), timestamp, hop, parv[5][0] == 'J'); if (ret != 1) return ret; @@ -758,17 +738,11 @@ int ms_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) for numeric nicks ! */ SetServerYXX(cptr, acptr, parv[6]); - if (*parv[7] == '+') { - for (ch = parv[7] + 1; *ch; ch++) - switch (*ch) { - case 'h': - SetHub(acptr); - break; - case 's': - SetService(acptr); - break; - } - } + /* Attach any necessary UWorld config items. */ + attach_confs_byhost(cptr, host, CONF_UWORLD); + + if (*parv[7] == '+') + set_server_flags(acptr, parv[7] + 1); Count_newremoteserver(UserStats); if (Protocol(acptr) < 10) @@ -778,9 +752,13 @@ int ms_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) if (*parv[5] == 'J') { SetBurst(acptr); - sendto_opmask_butone(0, SNO_NETWORK, "Net junction: %s %s", - cli_name(sptr), cli_name(acptr)); SetJunction(acptr); + for (bcptr = cli_serv(acptr)->up; !IsMe(bcptr); bcptr = cli_serv(bcptr)->up) + if (IsBurstOrBurstAck(bcptr)) + break; + if (IsMe(bcptr)) + sendto_opmask_butone(0, SNO_NETWORK, "Net junction: %s %s", + cli_name(sptr), cli_name(acptr)); } /* * Old sendto_serv_but_one() call removed because we now need to send @@ -793,10 +771,11 @@ int ms_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) continue; if (0 == match(cli_name(&me), cli_name(acptr))) continue; - sendcmdto_one(sptr, CMD_SERVER, bcptr, "%s %d 0 %s %s %s%s +%s%s :%s", + sendcmdto_one(sptr, CMD_SERVER, bcptr, "%s %d 0 %s %s %s%s +%s%s%s :%s", cli_name(acptr), hop + 1, parv[4], parv[5], NumServCap(acptr), IsHub(acptr) ? "h" : "", - IsService(acptr) ? "s" : "", cli_info(acptr)); + IsService(acptr) ? "s" : "", IsIPv6(acptr) ? "6" : "", + cli_info(acptr)); } return 0; }