Beispiel #1
0
void checkServer(struct Client *sptr, struct Client *acptr)
{
   char outbuf[BUFSIZE];

   /* Header */
   send_reply(sptr, RPL_DATASTR, " ");
   send_reply(sptr, RPL_CHKHEAD, "server", acptr->cli_name);
   send_reply(sptr, RPL_DATASTR, " ");

   ircd_snprintf(0, outbuf, sizeof(outbuf),  "   Connected at:: %s (%Tu)", myctime(acptr->cli_serv->timestamp), acptr->cli_serv->timestamp);
   send_reply(sptr, RPL_DATASTR, outbuf);

   ircd_snprintf(0, outbuf, sizeof(outbuf), "    Server name:: %s", acptr->cli_name);
   send_reply(sptr, RPL_DATASTR,  outbuf);

   if (cli_sslclifp(acptr) && (strlen(cli_sslclifp(acptr)) > 0)) {
     ircd_snprintf(0, outbuf, sizeof(outbuf), "SSL Fingerprint:: %s", cli_sslclifp(acptr));
     send_reply(sptr, RPL_DATASTR, outbuf);
   }

   ircd_snprintf(0, outbuf, sizeof(outbuf), "        Numeric:: %s --> %d", NumServ(acptr), base64toint(acptr->cli_yxx));
   send_reply(sptr, RPL_DATASTR, outbuf);

   ircd_snprintf(0, outbuf, sizeof(outbuf), "          Users:: %d / %d", (acptr == &me) ? UserStats.local_clients : cli_serv(acptr)->clients, 
                 base64toint(cli_serv(acptr)->nn_capacity));
   send_reply(sptr, RPL_DATASTR, outbuf);

   if (IsBurst(acptr))
     send_reply(sptr, RPL_DATASTR, "         Status:: Bursting");
   else if (IsBurstAck(acptr))
     send_reply(sptr, RPL_DATASTR, "         Status:: Awaiting EOB Ack");
   else if (IsService(acptr))
     send_reply(sptr, RPL_DATASTR, "         Status:: Network Service");
   else if (IsHub(acptr))
     send_reply(sptr, RPL_DATASTR, "         Status:: Network Hub");

   ircd_snprintf(0, outbuf, sizeof(outbuf), "          Class:: %s", get_client_class(acptr));
   send_reply(sptr, RPL_DATASTR, outbuf);

   if (feature_bool(FEAT_CHECK_EXTENDED)) {
     int dlinkc = 0;
     struct DLink* slink = NULL;
    
     send_reply(sptr, RPL_DATASTR, " ");
     send_reply(sptr, RPL_DATASTR, "Downlinks::");
     for (slink = cli_serv(acptr)->down; slink; slink = slink->next) {
       ircd_snprintf(0, outbuf, sizeof(outbuf), "[%d] - %s%s", ++dlinkc, 
             IsBurst(slink->value.cptr) ? "*" : IsBurstAck(slink->value.cptr) ? "!" : IsService(slink->value.cptr) ? "=" : IsHub(slink->value.cptr) ? "+" : " ", 
             cli_name(slink->value.cptr));
       send_reply(sptr, RPL_DATASTR, outbuf);
     }

     if (!dlinkc)
       send_reply(sptr, RPL_DATASTR, "<none>");
   }

   /* Send 'END OF CHECK' message */
   send_reply(sptr, RPL_ENDOFCHECK, " ");
}
Beispiel #2
0
/** Send a server map to a client.
 * @param[in] cptr Client to who to send the map.
 * @param[in] server Top-level server to display.
 * @param[in] mask Mask to filter which servers are shown.
 * @param[in] prompt_length Number of characters used in prompt.
 */
static void dump_map(struct Client *cptr, struct Client *server, char *mask, int prompt_length)
{
  const char *chr;
  static char prompt[64];
  struct DLink *lp;
  char *p = prompt + prompt_length;
  int cnt = 0;
  
  *p = '\0';
  if (prompt_length > 60)
    send_reply(cptr, RPL_MAPMORE, prompt, cli_name(server));
  else
  {
    char lag[512];
    if (cli_serv(server)->lag>10000)
      lag[0]=0;
    else if (cli_serv(server)->lag<0)
      strcpy(lag,"(0s)");
    else
      sprintf(lag,"(%is)",cli_serv(server)->lag);
    if (IsBurst(server))
      chr = "*";
    else if (IsBurstAck(server))
      chr = "!";
    else
      chr = "";
    send_reply(cptr, RPL_MAP, prompt, chr, cli_name(server),
               lag, (server == &me) ? UserStats.local_clients :
                                      cli_serv(server)->clients);
  }
  if (prompt_length > 0)
  {
    p[-1] = ' ';
    if (p[-2] == '`')
      p[-2] = ' ';
  }
  if (prompt_length > 60)
    return;
  strcpy(p, "|-");
  for (lp = cli_serv(server)->down; lp; lp = lp->next)
    if (match(mask, cli_name(lp->value.cptr)))
      ClrFlag(lp->value.cptr, FLAG_MAP);
    else
    {
      SetFlag(lp->value.cptr, FLAG_MAP);
      cnt++;
    }
  for (lp = cli_serv(server)->down; lp; lp = lp->next)
  {
    if (!HasFlag(lp->value.cptr, FLAG_MAP))
      continue;
    if (--cnt == 0)
      *p = '`';
    dump_map(cptr, lp->value.cptr, mask, prompt_length + 2);
  }
  if (prompt_length > 0)
    p[-1] = '-';
}
Beispiel #3
0
static void
stats_servers_verbose(struct Client* sptr, struct StatDesc* sd, int stat,
		      char* param)
{
  struct Client *acptr;

  /* lowercase 'v' is for human-readable,
   * uppercase 'V' is for machine-readable */
  if (stat == 'v')
    send_reply(sptr, SND_EXPLICIT | RPL_STATSVERBOSE,
	       "%-20s %-20s Flags Hops Numeric   Lag  RTT   Up Down "
	       "Clients/Max Proto %-10s :Info", "Servername", "Uplink",
	       "LinkTS");

  for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr)) {
    if (!IsServer(acptr) && !IsMe(acptr))
      continue;
    if (param && match(param, cli_name(acptr))) /* narrow search */
      continue;
    send_reply(sptr, SND_EXPLICIT | RPL_STATSVERBOSE, stat == 'v' ?
	       "%-20s %-20s %c%c%c%c  %4i %s %-4i %5i %4i %4i %4i %5i %5i "
	       "P%-2i   %Tu :%s" :
	       "%s %s %c%c%c%c %i %s %i %i %i %i %i %i %i P%i %Tu :%s",
	       cli_name(acptr),
	       cli_name(cli_serv(acptr)->up),
	       IsBurst(acptr) ? 'B' : '-',
	       IsBurstAck(acptr) ? 'A' : '-',
	       IsHub(acptr) ? 'H' : '-',
	       IsService(acptr) ? 'S' : '-',
	       cli_hopcount(acptr),
	       NumServ(acptr),
	       base64toint(cli_yxx(acptr)),
	       cli_serv(acptr)->lag,
	       cli_serv(acptr)->asll_rtt,
	       cli_serv(acptr)->asll_to,
	       cli_serv(acptr)->asll_from,
	       cli_serv(acptr)->clients,
	       cli_serv(acptr)->nn_mask,
	       cli_serv(acptr)->prot,
	       cli_serv(acptr)->timestamp,
	       cli_info(acptr));
  }
}
Beispiel #4
0
/** Handle a connection that has sent a valid PASS and SERVER.
 * @param cptr New peer server.
 * @param aconf Connect block for \a cptr.
 * @return Zero.
 */
int server_estab(struct Client *cptr, struct ConfItem *aconf)
{
  struct Client* acptr = 0;
  const char*    inpath;
  int            i;

  assert(0 != cptr);
  assert(0 != cli_local(cptr));

  inpath = cli_name(cptr);

  if (IsUnknown(cptr)) {
    if (aconf->passwd[0])
      sendrawto_one(cptr, MSG_PASS " :%s", aconf->passwd);
    /*
     *  Pass my info to the new server
     */
    sendrawto_one(cptr, MSG_SERVER " %s 1 %Tu %Tu J%s %s%s +%s6 :%s",
		  cli_name(&me), cli_serv(&me)->timestamp,
		  cli_serv(cptr)->timestamp, MAJOR_PROTOCOL, NumServCap(&me),
		  feature_bool(FEAT_HUB) ? "h" : "",
		  *(cli_info(&me)) ? cli_info(&me) : "IRCers United");
  }

  det_confs_butmask(cptr, CONF_SERVER);

  if (!IsHandshake(cptr))
    hAddClient(cptr);
  SetServer(cptr);
  cli_handler(cptr) = SERVER_HANDLER;
  Count_unknownbecomesserver(UserStats);
  SetBurst(cptr);

/*    nextping = CurrentTime; */

  /*
   * NOTE: check for acptr->user == cptr->serv->user is necessary to insure
   * that we got the same one... bleah
   */
  if (cli_serv(cptr)->user && *(cli_serv(cptr))->by &&
      (acptr = findNUser(cli_serv(cptr)->by))) {
    if (cli_user(acptr) == cli_serv(cptr)->user) {
      sendcmdto_one(&me, CMD_NOTICE, acptr, "%C :Link with %s established.",
                    acptr, inpath);
    }
    else {
      /*
       * if not the same client, set by to empty string
       */
      acptr = 0;
      *(cli_serv(cptr))->by = '\0';
    }
  }

  sendto_opmask(acptr, SNO_OLDSNO, "Link with %s established.", inpath);
  cli_serv(cptr)->up = &me;
  cli_serv(cptr)->updown = add_dlink(&(cli_serv(&me))->down, cptr);
  sendto_opmask(0, SNO_NETWORK, "Net junction: %s %s", cli_name(&me),
                cli_name(cptr));
  SetJunction(cptr);
  /*
   * Old sendto_serv_but_one() call removed because we now
   * need to send different names to different servers
   * (domain name matching) Send new server to other servers.
   */
  for (i = 0; i <= HighestFd; i++)
  {
    if (!(acptr = LocalClientArray[i]) || !IsServer(acptr) ||
        acptr == cptr || IsMe(acptr))
      continue;
    if (!match(cli_name(&me), cli_name(cptr)))
      continue;
    sendcmdto_one(&me, CMD_SERVER, acptr,
		  "%s 2 0 %Tu J%02u %s%s +%s%s%s :%s", cli_name(cptr),
		  cli_serv(cptr)->timestamp, Protocol(cptr), NumServCap(cptr),
		  IsHub(cptr) ? "h" : "", IsService(cptr) ? "s" : "",
		  IsIPv6(cptr) ? "6" : "", cli_info(cptr));
  }

  /* Send these as early as possible so that glined users/juped servers can
   * be removed from the network while the remote server is still chewing
   * our burst.
   */
  gline_burst(cptr);
  jupe_burst(cptr);

  /*
   * Pass on my client information to the new server
   *
   * First, pass only servers (idea is that if the link gets
   * canceled because the server was already there,
   * there are no NICK's to be canceled...). Of course,
   * if cancellation occurs, all this info is sent anyway,
   * and I guess the link dies when a read is attempted...? --msa
   *
   * Note: Link cancellation to occur at this point means
   * that at least two servers from my fragment are building
   * up connection this other fragment at the same time, it's
   * a race condition, not the normal way of operation...
   */

  for (acptr = &me; acptr; acptr = cli_prev(acptr)) {
    /* acptr->from == acptr for acptr == cptr */
    if (cli_from(acptr) == cptr)
      continue;
    if (IsServer(acptr)) {
      const char* protocol_str;

      if (Protocol(acptr) > 9)
        protocol_str = IsBurst(acptr) ? "J" : "P";
      else
        protocol_str = IsBurst(acptr) ? "J0" : "P0";

      if (0 == match(cli_name(&me), cli_name(acptr)))
        continue;
      sendcmdto_one(cli_serv(acptr)->up, CMD_SERVER, cptr,
		    "%s %d 0 %Tu %s%u %s%s +%s%s%s :%s", cli_name(acptr),
		    cli_hopcount(acptr) + 1, cli_serv(acptr)->timestamp,
		    protocol_str, Protocol(acptr), NumServCap(acptr),
		    IsHub(acptr) ? "h" : "", IsService(acptr) ? "s" : "",
		    IsIPv6(acptr) ? "6" : "", cli_info(acptr));
    }
  }

  for (acptr = &me; acptr; acptr = cli_prev(acptr))
  {
    /* acptr->from == acptr for acptr == cptr */
    if (cli_from(acptr) == cptr)
      continue;
    if (IsUser(acptr))
    {
      char xxx_buf[25];
      char *s = umode_str(acptr);
      sendcmdto_one(cli_user(acptr)->server, CMD_NICK, cptr,
		    "%s %d %Tu %s %s %s%s%s%s %s%s :%s",
		    cli_name(acptr), cli_hopcount(acptr) + 1, cli_lastnick(acptr),
		    cli_user(acptr)->username, cli_user(acptr)->realhost,
		    *s ? "+" : "", s, *s ? " " : "",
		    iptobase64(xxx_buf, &cli_ip(acptr), sizeof(xxx_buf), IsIPv6(cptr)),
		    NumNick(acptr), cli_info(acptr));
    }
  }
  /*
   * Last, send the BURST.
   * (Or for 2.9 servers: pass all channels plus statuses)
   */
  {
    struct Channel *chptr;
    for (chptr = GlobalChannelList; chptr; chptr = chptr->next)
      send_channel_modes(cptr, chptr);
  }
  sendcmdto_one(&me, CMD_END_OF_BURST, cptr, "");
  return 0;
}
/*
 * ms_burst - server message handler
 *
 * --  by Run [email protected]  december 1995 till march 1997
 *
 * parv[0] = sender prefix
 * parv[1] = channel name
 * parv[2] = channel timestamp
 * The meaning of the following parv[]'s depend on their first character:
 * If parv[n] starts with a '+':
 * Net burst, additive modes
 *   parv[n] = <mode>
 *   parv[n+1] = <param> (optional)
 *   parv[n+2] = <param> (optional)
 * If parv[n] starts with a '%', then n will be parc-1:
 *   parv[n] = %<ban> <ban> <ban> ...
 * If parv[n] starts with another character:
 *   parv[n] = <nick>[:<mode>],<nick>[:<mode>],...
 *   where <mode> is the channel mode (ov) of nick and all following nicks.
 *
 * Example:
 * "S BURST #channel 87654321 +ntkl key 123 AAA,AAB:o,BAA,BAB:ov :%ban1 ban2"
 *
 * Anti net.ride code.
 *
 * When the channel already exist, and its TS is larger then
 * the TS in the BURST message, then we cancel all existing modes.
 * If its is smaller then the received BURST message is ignored.
 * If it's equal, then the received modes are just added.
 */
int ms_burst(struct Client *cptr, struct Client *sptr, int parc, char *parv[])
{
  struct ModeBuf modebuf, *mbuf = 0;
  struct Channel *chptr;
  time_t timestamp;
  struct Membership *member, *nmember;
  struct SLink *lp, **lp_p;
  unsigned int parse_flags = (MODE_PARSE_FORCE | MODE_PARSE_BURST);
  int param, nickpos = 0, banpos = 0;
  char modestr[BUFSIZE], nickstr[BUFSIZE], banstr[BUFSIZE];

  if (parc < 3)
    return protocol_violation(sptr,"Too few parameters for BURST");

  if (!IsBurst(sptr)) /* don't allow BURST outside of burst */
    return exit_client_msg(cptr, cptr, &me, "HACK: BURST message outside "
			   "net.burst from %s", cli_name(sptr));

  if (!(chptr = get_channel(sptr, parv[1], CGT_CREATE)))
    return 0; /* can't create the channel? */

  timestamp = atoi(parv[2]);

  if (!chptr->creationtime || chptr->creationtime > timestamp) {
    /*
     * Kick local members if channel is +i or +k and our TS was larger
     * than the burst TS (anti net.ride). The modes hack is here because
     * we have to do this before mode_parse, as chptr may go away.
     */
    for (param = 3; param < parc; param++) {
      if (parv[param][0] != '+')
        continue;
      if (strchr(parv[param], 'i') || strchr(parv[param], 'k')) {
        /* Clear any outstanding rogue invites */
        mode_invite_clear(chptr);
        for (member = chptr->members; member; member = nmember) {
          nmember=member->next_member;
          if (!MyUser(member->user) || IsZombie(member))
            continue;
          sendcmdto_serv_butone(&me, CMD_KICK, NULL, "%H %C :Net Rider", chptr, member->user);
          sendcmdto_channel_butserv_butone(&me, CMD_KICK, chptr, NULL, "%H %C :Net Rider", chptr, member->user);
          make_zombie(member, member->user, &me, &me, chptr);
        }
      }
      break;
    }

    /* If the channel had only locals, it went away by now. */
    if (!(chptr = get_channel(sptr, parv[1], CGT_CREATE)))
      return 0; /* can't create the channel? */
  }

  /* turn off burst joined flag */
  for (member = chptr->members; member; member = member->next_member)
    member->status &= ~CHFL_BURST_JOINED;

  if (!chptr->creationtime) /* mark channel as created during BURST */
    chptr->mode.mode |= MODE_BURSTADDED;

  /* new channel or an older one */
  if (!chptr->creationtime || chptr->creationtime > timestamp) {
    chptr->creationtime = timestamp;

    modebuf_init(mbuf = &modebuf, &me, cptr, chptr,
		 MODEBUF_DEST_CHANNEL | MODEBUF_DEST_NOKEY);
    modebuf_mode(mbuf, MODE_DEL | chptr->mode.mode); /* wipeout modes */
    chptr->mode.mode &= ~(MODE_ADD | MODE_DEL | MODE_PRIVATE | MODE_SECRET |
			  MODE_MODERATED | MODE_TOPICLIMIT | MODE_INVITEONLY |
			  MODE_NOPRIVMSGS);

    parse_flags |= (MODE_PARSE_SET | MODE_PARSE_WIPEOUT); /* wipeout keys */

    /* mark bans for wipeout */
    for (lp = chptr->banlist; lp; lp = lp->next)
      lp->flags |= CHFL_BURST_BAN_WIPEOUT;
  
    /* clear topic set by netrider (if set) */
    if (*chptr->topic) {
      *chptr->topic = '\0';
      *chptr->topic_nick = '\0';
      chptr->topic_time = 0;
      sendcmdto_channel_butserv_butone(&me, CMD_TOPIC, chptr, NULL, 
                                       "%H :%s", chptr, chptr->topic);
    }
  } else if (chptr->creationtime == timestamp) {
    modebuf_init(mbuf = &modebuf, &me, cptr, chptr,
		 MODEBUF_DEST_CHANNEL | MODEBUF_DEST_NOKEY);

    parse_flags |= MODE_PARSE_SET; /* set new modes */
  }

  param = 3; /* parse parameters */
  while (param < parc) {
    switch (*parv[param]) {
    case '+': /* parameter introduces a mode string */
      param += mode_parse(mbuf, cptr, sptr, chptr, parc - param,
			  parv + param, parse_flags);
      break;

    case '%': /* parameter contains bans */
      if (parse_flags & MODE_PARSE_SET) {
	char *banlist = parv[param] + 1, *p = 0, *ban, *ptr;
	struct SLink *newban;

	for (ban = ircd_strtok(&p, banlist, " "); ban;
	     ban = ircd_strtok(&p, 0, " ")) {
	  ban = collapse(pretty_mask(ban));

	    /*
	     * Yeah, we should probably do this elsewhere, and make it better
	     * and more general; this will hold until we get there, though.
	     * I dislike the current add_banid API... -Kev
	     *
	     * I wish there were a better algo. for this than the n^2 one
	     * shown below *sigh*
	     */
	  for (lp = chptr->banlist; lp; lp = lp->next) {
	    if (!ircd_strcmp(lp->value.ban.banstr, ban)) {
	      ban = 0; /* don't add ban */
	      lp->flags &= ~CHFL_BURST_BAN_WIPEOUT; /* not wiping out */
	      break; /* new ban already existed; don't even repropagate */
	    } else if (!(lp->flags & CHFL_BURST_BAN_WIPEOUT) &&
		       !mmatch(lp->value.ban.banstr, ban)) {
	      ban = 0; /* don't add ban unless wiping out bans */
	      break; /* new ban is encompassed by an existing one; drop */
	    } else if (!mmatch(ban, lp->value.ban.banstr))
	      lp->flags |= CHFL_BAN_OVERLAPPED; /* remove overlapping ban */

	    if (!lp->next)
	      break;
	  }

	  if (ban) { /* add the new ban to the end of the list */
	    /* Build ban buffer */
	    if (!banpos) {
	      banstr[banpos++] = ' ';
	      banstr[banpos++] = ':';
	      banstr[banpos++] = '%';
	    } else
	      banstr[banpos++] = ' ';
	    for (ptr = ban; *ptr; ptr++) /* add ban to buffer */
	      banstr[banpos++] = *ptr;

	    newban = make_link(); /* create new ban */

	    DupString(newban->value.ban.banstr, ban);

	    DupString(newban->value.ban.who, 
		      cli_name(feature_bool(FEAT_HIS_BANWHO) ? &me : sptr));

	    newban->value.ban.when = TStime();

	    newban->flags = CHFL_BAN | CHFL_BURST_BAN; /* set flags */
	    if ((ptr = strrchr(ban, '@')) && check_if_ipmask(ptr + 1))
	      newban->flags |= CHFL_BAN_IPMASK;

	    newban->next = 0;
	    if (lp)
	      lp->next = newban; /* link it in */
	    else
	      chptr->banlist = newban;
	  }
	}
      } 
      param++; /* look at next param */
      break;

    default: /* parameter contains clients */
      {
	struct Client *acptr;
	char *nicklist = parv[param], *p = 0, *nick, *ptr;
	int default_mode = CHFL_DEOPPED | CHFL_BURST_JOINED;
	int last_mode = CHFL_DEOPPED | CHFL_BURST_JOINED;

	for (nick = ircd_strtok(&p, nicklist, ","); nick;
	     nick = ircd_strtok(&p, 0, ",")) {

	  if ((ptr = strchr(nick, ':'))) { /* new flags; deal */
	    *ptr++ = '\0';

	    if (parse_flags & MODE_PARSE_SET) {
	      for (default_mode = CHFL_DEOPPED | CHFL_BURST_JOINED; *ptr;
		   ptr++) {
		if (*ptr == 'o') /* has oper status */
		  default_mode = (default_mode & ~CHFL_DEOPPED) | CHFL_CHANOP;
		else if (*ptr == 'v') /* has voice status */
		  default_mode |= CHFL_VOICE;
		else /* I don't recognize that flag */
		  break; /* so stop processing */
	      }
	    }
	  }

	  if (!(acptr = findNUser(nick)) || cli_from(acptr) != cptr)
	    continue; /* ignore this client */

	  /* Build nick buffer */
	  nickstr[nickpos] = nickpos ? ',' : ' '; /* first char */
	  nickpos++;

	  for (ptr = nick; *ptr; ptr++) /* store nick */
	    nickstr[nickpos++] = *ptr;

	  if (default_mode != last_mode) { /* if mode changed... */
	    last_mode = default_mode;

	    nickstr[nickpos++] = ':'; /* add a specifier */
	    if (default_mode & CHFL_CHANOP)
	      nickstr[nickpos++] = 'o';
	    if (default_mode & CHFL_VOICE)
	      nickstr[nickpos++] = 'v';
	  }

	  add_user_to_channel(chptr, acptr, default_mode);
	  sendcmdto_channel_butserv_butone(acptr, CMD_JOIN, chptr, NULL, "%H", chptr);
	}
      }
      param++;
      break;
    } /* switch (*parv[param]) { */
  } /* while (param < parc) { */

  nickstr[nickpos] = '\0';
  banstr[banpos] = '\0';

  if (parse_flags & MODE_PARSE_SET) {
    modebuf_extract(mbuf, modestr + 1); /* for sending BURST onward */
    modestr[0] = modestr[1] ? ' ' : '\0';
  } else
    modestr[0] = '\0';

  sendcmdto_serv_butone(sptr, CMD_BURST, cptr, "%H %Tu%s%s%s", chptr,
			chptr->creationtime, modestr, nickstr, banstr);

  if (parse_flags & MODE_PARSE_WIPEOUT || banpos)
    mode_ban_invalidate(chptr);

  if (parse_flags & MODE_PARSE_SET) { /* any modes changed? */
    /* first deal with channel members */
    for (member = chptr->members; member; member = member->next_member) {
      if (member->status & CHFL_BURST_JOINED) { /* joined during burst */
	if (member->status & CHFL_CHANOP)
	  modebuf_mode_client(mbuf, MODE_ADD | CHFL_CHANOP, member->user);
	if (member->status & CHFL_VOICE)
	  modebuf_mode_client(mbuf, MODE_ADD | CHFL_VOICE, member->user);
      } else if (parse_flags & MODE_PARSE_WIPEOUT) { /* wipeout old ops */
	if (member->status & CHFL_CHANOP)
	  modebuf_mode_client(mbuf, MODE_DEL | CHFL_CHANOP, member->user);
	if (member->status & CHFL_VOICE)
	  modebuf_mode_client(mbuf, MODE_DEL | CHFL_VOICE, member->user);
	member->status = ((member->status & ~(CHFL_CHANOP | CHFL_VOICE)) |
			  CHFL_DEOPPED);
      }
    }

    /* Now deal with channel bans */
    lp_p = &chptr->banlist;
    while (*lp_p) {
      lp = *lp_p;

      /* remove ban from channel */
      if (lp->flags & (CHFL_BAN_OVERLAPPED | CHFL_BURST_BAN_WIPEOUT)) {
	modebuf_mode_string(mbuf, MODE_DEL | MODE_BAN,
			    lp->value.ban.banstr, 1); /* let it free banstr */

	*lp_p = lp->next; /* clip out of list */
	MyFree(lp->value.ban.who); /* free who */
	free_link(lp); /* free ban */
	continue;
      } else if (lp->flags & CHFL_BURST_BAN) /* add ban to channel */
	modebuf_mode_string(mbuf, MODE_ADD | MODE_BAN,
			    lp->value.ban.banstr, 0); /* don't free banstr */

      lp->flags &= (CHFL_BAN | CHFL_BAN_IPMASK); /* reset the flag */
      lp_p = &(*lp_p)->next;
    }
  }

  return mbuf ? modebuf_flush(mbuf) : 0;
}
Beispiel #6
0
static int
do_server_estab(aClient *cptr)
{
    aClient *acptr;
    aConnect *aconn;
    aChannel *chptr;
    int i;
    /* "refresh" inpath with host  */
    char *inpath = get_client_name(cptr, HIDEME);

    SetServer(cptr);

    Count.unknown--;
    Count.server++;
    Count.myserver++;

    if(IsZipCapable(cptr) && DoZipThis(cptr))
    {
        sendto_one(cptr, "SVINFO ZIP");
        SetZipOut(cptr);
        cptr->serv->zip_out = zip_create_output_session();
    }

#ifdef MAXBUFFERS
    /* let's try to bump up server sock_opts... -Taner */
    reset_sock_opts(cptr->fd, 1);
#endif

    /* adds to server list */
    add_to_list(&server_list, cptr);

    set_effective_class(cptr);

    /* Check one more time for good measure... is it there? */
    if ((acptr = find_name(cptr->name, NULL)))
    {
        char        nbuf[HOSTLEN * 2 + USERLEN + 5];
        aClient *bcptr;

        /*
         * While negotiating stuff, another copy of this server appeared.
         *
         * Rather than KILL the link which introduced it, KILL the
         * youngest of the two links. -avalon
         */

        bcptr = (cptr->firsttime > acptr->from->firsttime) ? cptr :
            acptr->from;
        sendto_one(bcptr, "ERROR :Server %s already exists", cptr->name);
        if (bcptr == cptr)
        {
            sendto_gnotice("from %s: Link %s cancelled, server %s already "
                           "exists (final phase)", me.name,
                           get_client_name(bcptr, HIDEME), cptr->name);
            sendto_serv_butone(bcptr, ":%s GNOTICE :Link %s cancelled, "
                                "server %s already exists (final phase)",
                                me.name, get_client_name(bcptr, HIDEME),
                                cptr->name);
            return exit_client(bcptr, bcptr, &me,
                               "Server Exists (final phase)");
        }
        /* inform all those who care (set +n) -epi */

        strcpy(nbuf, get_client_name(bcptr, HIDEME));
        sendto_gnotice("from %s: Link %s cancelled, server %s reintroduced "
                       "by %s (final phase)", me.name, nbuf, cptr->name,
                       get_client_name(cptr, HIDEME));
        sendto_serv_butone(bcptr, ":%s GNOTICE :Link %s cancelled, server %s "
                           "reintroduced by %s (final phase)", me.name, nbuf,
                           cptr->name, get_client_name(cptr, HIDEME));
        exit_client(bcptr, bcptr, &me, "Server Exists (final phase)");
    }

    /* error, error, error! if a server is U:'d, and it connects to us,
     * we need to figure that out! So, do it here. - lucas
     */

    if (find_aUserver(cptr->name))
    {
        Count.myulined++;
        cptr->flags |= FLAGS_ULINE;

        /* If the server has special u:line flags, let's set them.. */
        cptr->serv->uflags = cptr->serv->aconn->uflags;
    }

    fakelinkserver_update(cptr->name, cptr->info);

    sendto_gnotice("from %s: Link with %s established, states:%s%s%s%s",
                   me.name, inpath, ZipOut(cptr) ? " Output-compressed" : "",
                   RC4EncLink(cptr) ? " encrypted" : "",
                   IsULine(cptr) ? " ULined" : "",
                   DoesTS(cptr) ? " TS" : " Non-TS");

    /*
     * Notify everyone of the fact that this has just linked: the entire
     * network should get two of these, one explaining the link between
     * me->serv and the other between serv->me
     */

    sendto_serv_butone(NULL, ":%s GNOTICE :Link with %s established: %s",
                       me.name, inpath,
                       DoesTS(cptr) ? "TS link" : "Non-TS link!");

    add_to_client_hash_table(cptr->name, cptr);

    /* add it to scache */

    find_or_add(cptr->name);

    /*
     * Old sendto_serv_but_one() call removed because we now need to
     * send different names to different servers (domain name
     * matching) Send new server to other servers.
     */
    for (i = 0; i <= highest_fd; i++)
    {
        if (!(acptr = local[i]) || !IsServer(acptr) || acptr == cptr ||
            IsMe(acptr))
            continue;
        if ((aconn = acptr->serv->aconn) &&
            !match(my_name_for_link(me.name, aconn), cptr->name))
            continue;
        sendto_one(acptr, ":%s SERVER %s 2 :%s", me.name, cptr->name,
                   cptr->info);
    }

    /*
     * Pass on my client information to the new server
     *
     * First, pass only servers (idea is that if the link gets
     * cancelled beacause the server was already there, there are no
     * NICK's to be cancelled...). Of course, if cancellation occurs,
     * all this info is sent anyway, and I guess the link dies when a
     * read is attempted...? --msa
     *
     * Note: Link cancellation to occur at this point means that at
     * least two servers from my fragment are building up connection
     * this other fragment at the same time, it's a race condition,
     * not the normal way of operation...
     *
     * ALSO NOTE: using the get_client_name for server names-- see
     * previous *WARNING*!!! (Also, original inpath is
     * destroyed...)
     */

    aconn = cptr->serv->aconn;
    for (acptr = &me; acptr; acptr = acptr->prev)
    {
        if (acptr->from == cptr)
            continue;
        if (IsServer(acptr))
        {
            if (match(my_name_for_link(me.name, aconn), acptr->name) == 0)
                continue;
            sendto_one(cptr, ":%s SERVER %s %d :%s",
                       acptr->serv->up, acptr->name,
                       acptr->hopcount + 1, acptr->info);
        }
    }

    /* send out our SQLINES and SGLINES too */
    send_simbans(cptr, SBAN_CHAN|SBAN_NETWORK);
    send_simbans(cptr, SBAN_NICK|SBAN_NETWORK);
    send_simbans(cptr, SBAN_GCOS|SBAN_NETWORK);

    /* Send out fake server list and other 'fake' stuff */
    fakeserver_sendserver(cptr);

    /* Send UHM (user host-masking) type */
    if(confopts & FLAGS_HUB)
        sendto_one(cptr, "SVSUHM %d", uhm_type);

    /* send clone list */
    clones_send(cptr);

    /* Bursts are about to start.. send a BURST */
    if (IsBurst(cptr))
        sendto_one(cptr, "BURST");

    /*
     * * Send it in the shortened format with the TS, if it's a TS
     * server; walk the list of channels, sending all the nicks that
     * haven't been sent yet for each channel, then send the channel
     * itself -- it's less obvious than sending all nicks first, but
     * on the receiving side memory will be allocated more nicely
     * saving a few seconds in the handling of a split -orabidoo
     */
    {
        chanMember       *cm;
        static char nickissent = 1;

        nickissent = 3 - nickissent;
        /*
         * flag used for each nick to check if we've sent it yet - must
         * be different each time and !=0, so we alternate between 1 and
         * 2 -orabidoo
         */
        for (chptr = channel; chptr; chptr = chptr->nextch)
        {
            for (cm = chptr->members; cm; cm = cm->next)
            {
                acptr = cm->cptr;
                if (acptr->nicksent != nickissent)
                {
                    acptr->nicksent = nickissent;
                    if (acptr->from != cptr)
                        sendnick_TS(cptr, acptr);
                }
            }
            send_channel_modes(cptr, chptr);
        }
        /* also send out those that are not on any channel */
        for (acptr = &me; acptr; acptr = acptr->prev)
            if (acptr->nicksent != nickissent)
            {
                acptr->nicksent = nickissent;
                if (acptr->from != cptr)
                    sendnick_TS(cptr, acptr);
            }
    }

    if(confopts & FLAGS_HUB)
        fakelusers_sendlock(cptr);

    if(ZipOut(cptr))
    {
        unsigned long inb, outb;
        double rat;

        zip_out_get_stats(cptr->serv->zip_out, &inb, &outb, &rat);

        if(inb)
        {
            sendto_gnotice("from %s: Connect burst to %s: %lu bytes normal, "
                           "%lu compressed (%3.2f%%)", me.name,
                           get_client_name(cptr, HIDEME), inb, outb, rat);
            sendto_serv_butone(cptr, ":%s GNOTICE :Connect burst to %s: %lu "
                               "bytes normal, %lu compressed (%3.2f%%)",
                               me.name, get_client_name(cptr, HIDEME), inb,
                               outb, rat);
        }
    }

    /* stuff a PING at the end of this burst so we can figure out when
       the other side has finished processing it. */
    cptr->flags |= FLAGS_BURST|FLAGS_PINGSENT;
    if (IsBurst(cptr)) cptr->flags |= FLAGS_SOBSENT;
    sendto_one(cptr, "PING :%s", me.name);

    return 0;
}
Beispiel #7
0
static void dump_map(struct Client *cptr, struct Client *server, char *mask, int prompt_length)
{
    static char prompt[64];
    struct DLink *lp;
    char *p = &prompt[prompt_length];
    int cnt = 0;

    *p = '\0';
    if (prompt_length > 60)
        send_reply(cptr, RPL_MAPMORE, prompt, cli_name(server));
    else {
        char lag[512];
        int showserv = 1;
        unsigned int totalusers = UserStats.clients;
        unsigned int percentage;
        unsigned int serv_clients;

        if (totalusers == 0)
            totalusers = 1; /* ¿? NO deberia ocurrir nunca... */

        percentage = (10000 * (IsMe(server) ? UserStats.local_clients : cli_serv(server)->clients)) / totalusers;
        if (IsMe(server))
            strcpy(lag,"(0s)");
        else if (cli_serv(server)->lag>10000)
            lag[0]=0;
        else if (cli_serv(server)->lag<0)
            strcpy(lag,"(0s)");
        else
            sprintf(lag,"(%is)",cli_serv(server)->lag);
        if (IsHiddenserv(server) && !feature_bool(FEAT_SHOWSERVON_MAP))
            if (!IsAnOper(cptr) && !es_representante(cptr))
                showserv = 0;

        serv_clients = (server == &me) ? UserStats.local_clients : cli_serv(server)->clients;

        send_reply(cptr, RPL_MAP, prompt, (
                       (IsBurst(server)) ? "*" : (IsBurstAck(server) ? "!" : "")),
                   showserv ? cli_name(server) : feature_str(FEAT_HIS_SERVERNAME),
                   lag, NumServ(server), base64toint(NumServ(server)), serv_clients,
                   (serv_clients == 1) ? "" : "s",
                   (percentage / 100), (percentage % 100));
    }
    if (prompt_length > 0)
    {
        p[-1] = ' ';
        if (p[-2] == '`')
            p[-2] = ' ';
    }
    if (prompt_length > 60)
        return;
    strcpy(p, "|-");
    for (lp = cli_serv(server)->down; lp; lp = lp->next)
        if (match(mask, cli_name(lp->value.cptr)))
            cli_flags(lp->value.cptr) &= ~FLAGS_MAP;
        else
        {
            cli_flags(lp->value.cptr) |= FLAGS_MAP;
            cnt++;
        }
    for (lp = cli_serv(server)->down; lp; lp = lp->next)
    {
        if ((cli_flags(lp->value.cptr) & FLAGS_MAP) == 0)
            continue;
        if (--cnt == 0)
            *p = '`';
        dump_map(cptr, lp->value.cptr, mask, prompt_length + 2);
    }
    if (prompt_length > 0)
        p[-1] = '-';
}