Exemple #1
0
 bool url_client::prepare(const std::string &url, const common::header_map &hdr) {
     the_request_.clear();
     common::parsed_url_type purl;
     if(!parse_url(url, purl, false, false))
         return false;
     // TODO: HTTPS
     std::string host=purl.host;
     if (common::iequal()(purl.schema, "http")) {
         if(purl.port==0) {
             purl.port=80;
         } else {
             host+=':';
             host+=boost::lexical_cast<std::string>(purl.port);
         }
         if(!make_client(false, purl.host, purl.port))
             return false;
     } else if (common::iequal()(purl.schema, "https")) {
         if(purl.port==0) {
             purl.port=443;
         } else {
             host+=':';
             host+=boost::lexical_cast<std::string>(purl.port);
         }
         if(!make_client(true, purl.host, purl.port))
             return false;
     } else {
         // ERROR: Unknown protocol
         return false;
     }
     the_request_.url.reserve(url.length());
     the_request_.url=purl.path;
     if(!purl.query.empty()) {
         the_request_.url+='?';
         the_request_.url+=purl.query;
     }
     if(!purl.fragment.empty()) {
         the_request_.url+='?';
         the_request_.url+=purl.fragment;
     }
     the_request_.version=http_version::HTTP_1_1;
     the_request_.keep_alive=true;
     the_request_.headers.insert({"Host", std::move(host)});
     the_request_.headers.insert(hdr.begin(), hdr.end());
     return true;
 }
Exemple #2
0
void dssim_t::configure(Net* _net, const dssim_t::Config& _config) {
   net = _net;
   config = _config;
   rand_gen.seed(config.rand_seed);
   rand_percent = std::make_unique<std::uniform_int_distribution<int>>(0, 100);

   // Initially, servers do know about each other.  This corresponds to
   // a service starting by booting some machines who then contact
   // each other for a view change
   MASSERT(config.nservers > 0, "impossible");
   std::unordered_set<node_id_t> serv_ids;
   for(int i = 0; i < config.nservers; ++i) {
      serv_ids.insert(net->get_new_nid());
   }
   for(auto& nid : serv_ids) {
      make_server(nid);
   }

   // Gosh, isn't there a simpler way?
   std::vector<std::string> prefix;
   if(config.nclients <= 26) {
      prefix.resize(26);
      int i = 0;
      for(char c = 'a'; c <= 'z'; ++c) {
         prefix[i++] = std::string(1, c);
      }
   } else if(config.nclients <= 26*26) {
      prefix.resize(26*26);
      int i = 0;
      for(char b = 'a'; b <= 'z'; ++b) {
         for(char c = 'a'; c <= 'z'; ++c) {
            prefix[i++] = std::string(1, b) + c;
         }
      }
   } else if(config.nclients <= 26*26*26) {
      prefix.resize(26*26*26);
      int i = 0;
      for(char a = 'a'; a <= 'z'; ++a) {
         for(char b = 'a'; b <= 'z'; ++b) {
            for(char c = 'a'; c <= 'z'; ++c) {
               prefix[i++] = std::string(1, a) + b + c;
            }
         }
      }
   } else {
      std::fprintf(stderr, "Too many clients %d (max is %d)\n", 
                   config.nclients, 26*26*26);
      exit(79);
   }
   for(int i = 0; i < config.nclients; ++i) {
      node_id_t nid = net->get_new_nid();
      make_client(nid, prefix[i]);
   }
}
Exemple #3
0
int			main(int ac, char **av)
{
	int		port;
	int		sock;

	if (ac != 3)
		return (client_error(-1));
	port = ft_atoi(av[2]);
	sock = create_client(av[1], port);
	if (sock == -1)
		return (-1);
	make_client(sock);
	return (0);
}
Exemple #4
0
/*
 * add_connection - creates a client which has just connected to us on
 * the given fd. The sockhost field is initialized with the ip# of the host.
 * The client is sent to the auth module for verification, and not put in
 * any client list yet.
 */
static void
add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, struct sockaddr *lai)
{
	struct Client *new_client;
	s_assert(NULL != listener);

	/*
	 * get the client socket name from the socket
	 * the client has already been checked out in accept_connection
	 */
	new_client = make_client(NULL);

	if (listener->ssl)
	{
		rb_fde_t *xF[2];
		if(rb_socketpair(AF_UNIX, SOCK_STREAM, 0, &xF[0], &xF[1], "Incoming ssld Connection") == -1)
		{
			free_client(new_client);
			return;
		}
		new_client->localClient->ssl_ctl = start_ssld_accept(F, xF[1], new_client->localClient->connid);        /* this will close F for us */
		if(new_client->localClient->ssl_ctl == NULL)
		{
			free_client(new_client);
			return;
		}
		F = xF[0];
		SetSSL(new_client);
	}

	memcpy(&new_client->localClient->ip, sai, sizeof(struct rb_sockaddr_storage));
	memcpy(&new_client->preClient->lip, lai, sizeof(struct rb_sockaddr_storage));

	/*
	 * copy address to 'sockhost' as a string, copy it to host too
	 * so we have something valid to put into error messages...
	 */
	rb_inet_ntop_sock((struct sockaddr *)&new_client->localClient->ip, new_client->sockhost,
		sizeof(new_client->sockhost));


	rb_strlcpy(new_client->host, new_client->sockhost, sizeof(new_client->host));

	new_client->localClient->F = F;
	new_client->localClient->listener = listener;

	++listener->ref_count;

	start_auth(new_client);
}
Exemple #5
0
void 
connect_server()
{
  struct Client *client = make_client(NULL);
  struct Server *server = make_server(client);
  struct Module *protomod;
  char modes[MODEBUFLEN+1] = "";
  int i, j = 0;

  protomod = find_module(Connect.protocol, NO);
  if(protomod == NULL)
  {
    ilog(L_CRIT, "Unable to connect to uplink, protocol module %s not found.",
        Connect.protocol);
    services_die("Connect error", NO);
  }

  ServerModeList = (struct ModeList *)modsym(protomod->handle, "ModeList");
  for(i = 0; ServerModeList[i].letter != '\0'; i++)
  {
    modes[j++] = ServerModeList[i].letter;
    if(j > MODEBUFLEN)
      break;
  }
  modes[j] = '\0';

  ilog(L_DEBUG, "Loaded server mode list %p %s %d", ServerModeList, modes, j);

  strlcpy(server->pass, Connect.password, sizeof(server->pass));
  strlcpy(client->name, Connect.name, sizeof(client->name));
  strlcpy(client->host, Connect.host, sizeof(client->host));

  SetConnecting(client);
  client->from = client;
    
  dlinkAdd(client, &client->node, &global_client_list);

  if(comm_open(&server->fd, AF_INET, SOCK_STREAM, 0, NULL) < 0)
  {
    ilog(L_CRIT, "connect_server: Could not open socket");
    exit(1);
  }

  comm_connect_tcp(&server->fd, Connect.host, Connect.port,
      NULL, 0, serv_connect_callback, client, AF_INET, CONNECTTIMEOUT);

  eventAdd("Server connection check", try_reconnect, NULL, 60);
}
Exemple #6
0
    SyncClient(std::unique_ptr<util::Logger> logger,
               ReconnectMode reconnect_mode = ReconnectMode::normal,
               bool verify_ssl = true)
    : client(make_client(*logger, reconnect_mode, verify_ssl)) // Throws
    , m_logger(std::move(logger))
    , m_thread([this] {
        if (g_binding_callback_thread_observer)
            g_binding_callback_thread_observer->did_create_thread();

        auto will_destroy_thread = util::make_scope_exit([&]() noexcept {
            if (g_binding_callback_thread_observer)
                g_binding_callback_thread_observer->will_destroy_thread();
        });

        client.run(); // Throws
    }) // Throws
    {
    }
/*
 * add_connection - creates a client which has just connected to us on 
 * the given fd. The sockhost field is initialized with the ip# of the host.
 * The client is sent to the auth module for verification, and not put in
 * any client list yet.
 */
static void
add_connection(struct Listener *listener, int fd, struct sockaddr *sai)
{
	struct Client *new_client;
	s_assert(NULL != listener);

	/* 
	 * get the client socket name from the socket
	 * the client has already been checked out in accept_connection
	 */
	new_client = make_client(NULL);

	memcpy(&new_client->localClient->ip, sai, sizeof(struct irc_sockaddr_storage));

	/* 
	 * copy address to 'sockhost' as a string, copy it to host too
	 * so we have something valid to put into error messages...
	 */
	inetntop_sock((struct sockaddr *) &new_client->localClient->ip, new_client->sockhost,
		      sizeof(new_client->sockhost));


	strlcpy(new_client->host, new_client->sockhost, sizeof(new_client->host));

#ifdef IPV6
	if(new_client->localClient->ip.ss_family == AF_INET6
	   && ConfigFileEntry.dot_in_ip6_addr == 1)
	{
		strlcat(new_client->host, ".", sizeof(new_client->host));
	}
#endif

	new_client->localClient->fd = fd;

	new_client->localClient->listener = listener;
	++listener->ref_count;

	if(check_reject(new_client))
		return;
	start_auth(new_client);
}
Exemple #8
0
/*
 * client_from_server()
 */
static void
uid_from_server(struct Client *client_p, struct Client *source_p, int parc,
                char *parv[], time_t newts, const char *svsid, char *nick, char *ugecos)
{
  const char *m = NULL;
  const char *servername = source_p->name;

  source_p = make_client(client_p);
  dlinkAdd(source_p, &source_p->node, &global_client_list);

  source_p->hopcount = atoi(parv[2]);
  source_p->tsinfo = newts;
  strlcpy(source_p->svid, svsid, sizeof(source_p->svid));

  /* copy the nick in place */
  strlcpy(source_p->name, nick, sizeof(source_p->name));
  strlcpy(source_p->id, parv[8], sizeof(source_p->id));
  strlcpy(source_p->sockhost, parv[7], sizeof(source_p->sockhost));
  strlcpy(source_p->info, ugecos, sizeof(source_p->info));

  hash_add_client(source_p);
  hash_add_id(source_p);

  /* parse usermodes */
  for (m = &parv[4][1]; *m; ++m)
  {
    unsigned int flag = user_modes[(unsigned char)*m];

    if ((flag & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE))
      ++Count.invisi;
    if ((flag & UMODE_OPER) && !HasUMode(source_p, UMODE_OPER))
      ++Count.oper;

    source_p->umodes |= flag & SEND_UMODES;
  }

  register_remote_user(source_p, parv[5], parv[6],
                       servername, ugecos);
}
Exemple #9
0
struct Client *make_local_person_full(const char *nick, const char *username, const char *hostname, const char *ip, const char *realname)
{
	struct Client *client;

	client = make_client(NULL);
	rb_dlinkMoveNode(&client->localClient->tnode, &unknown_list, &lclient_list);
	client->servptr = &me;
	rb_dlinkAdd(client, &client->lnode, &client->servptr->serv->users);
	make_user(client);
	SetClient(client);

	rb_inet_pton_sock(ip, (struct sockaddr *)&client->localClient->ip);
	rb_strlcpy(client->name, nick, sizeof(client->name));
	rb_strlcpy(client->username, username, sizeof(client->username));
	rb_strlcpy(client->host, hostname, sizeof(client->host));
	rb_inet_ntop_sock((struct sockaddr *)&client->localClient->ip, client->sockhost, sizeof(client->sockhost));
	rb_strlcpy(client->info, realname, sizeof(client->info));

	add_to_client_hash(client->name, client);

	return client;
}
Exemple #10
0
/*!
 *
 * \param source_p Pointer to allocated Client struct from which the message
 *                 originally comes from.  This can be a local or remote client.
 * \param parc     Integer holding the number of supplied arguments.
 * \param parv     Argument vector where parv[0] .. parv[parc-1] are non-NULL
 *                 pointers.
 * \note Valid arguments for this command are:
 *
 * server introducing new nick/UID (without services support)
 *      - parv[0] = command
 *      - parv[1] = nickname
 *      - parv[2] = hop count
 *      - parv[3] = TS
 *      - parv[4] = umode
 *      - parv[5] = username
 *      - parv[6] = hostname
 *      - parv[7] = ip
 *      - parv[8] = uid
 *      - parv[9] = ircname (gecos)
 *
 * server introducing new nick/UID (with services support)
 *      - parv[ 0] = command
 *      - parv[ 1] = nickname
 *      - parv[ 2] = hop count
 *      - parv[ 3] = TS
 *      - parv[ 4] = umode
 *      - parv[ 5] = username
 *      - parv[ 6] = hostname
 *      - parv[ 7] = ip
 *      - parv[ 8] = uid
 *      - parv[ 9] = services account
 *      - parv[10] = ircname (gecos)
 */
static void
uid_from_server(struct Client *source_p, int parc, char *parv[])
{
  struct Client *client_p = NULL;

  client_p = make_client(source_p->from);
  client_p->servptr = source_p;
  client_p->hopcount = atoi(parv[2]);
  client_p->tsinfo = atol(parv[3]);

  strlcpy(client_p->account, (parc == 11 ? parv[9] : "*"), sizeof(client_p->account));
  strlcpy(client_p->name, parv[1], sizeof(client_p->name));
  strlcpy(client_p->id, parv[8], sizeof(client_p->id));
  strlcpy(client_p->sockhost, parv[7], sizeof(client_p->sockhost));
  strlcpy(client_p->info, parv[parc - 1], sizeof(client_p->info));
  strlcpy(client_p->host, parv[6], sizeof(client_p->host));
  strlcpy(client_p->username, parv[5], sizeof(client_p->username));

  hash_add_client(client_p);
  hash_add_id(client_p);

  /* Parse user modes */
  for (const char *m = &parv[4][1]; *m; ++m)
  {
    const struct user_modes *tab = umode_map[(unsigned char)*m];

    if (!tab)
      continue;
    if ((tab->flag & UMODE_INVISIBLE) && !HasUMode(client_p, UMODE_INVISIBLE))
      ++Count.invisi;
    if ((tab->flag & UMODE_OPER) && !HasUMode(client_p, UMODE_OPER))
      ++Count.oper;

    AddUMode(client_p, tab->flag);
  }

  register_remote_user(client_p);
}
Exemple #11
0
int
ACE_TMAIN (int argc, ACE_TCHAR *argv[])
{
  Options::set_options (argc, argv);

  SM_Client *sm_client = make_client ();

  if (sm_client->send () < 0)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "%p\n",
                       Options::program_name),
                      -1);

  if (sm_client->receive (Options::max_server_timeout) < 0)
    ACE_ERROR_RETURN ((LM_ERROR,
                       "%p\n",
                       Options::program_name),
                      -1);

  sm_client->process ();

  return 0;
}
Exemple #12
0
struct Client *make_remote_server_full(struct Client *uplink, const char *name, const char *id)
{
	struct Client *client;

	client = make_client(NULL);
	client->servptr = uplink;

	attach_server_conf(client, find_server_conf(name));

	rb_strlcpy(client->name, name, sizeof(client->name));
	rb_strlcpy(client->id, id, sizeof(client->id));

	rb_dlinkAdd(client, &client->lnode, &uplink->serv->servers);
	rb_dlinkMoveNode(&client->localClient->tnode, &unknown_list, &serv_list);
	rb_dlinkAddTailAlloc(client, &global_serv_list);

	make_server(client);
	SetServer(client);

	add_to_client_hash(client->name, client);

	return client;
}
Exemple #13
0
/*
 * add_connection - creates a client which has just connected to us on 
 * the given fd. The sockhost field is initialized with the ip# of the host.
 * The client is sent to the auth module for verification, and not put in
 * any client list yet.
 */
static void
add_connection(struct Listener *listener, rb_fde_t *F, struct sockaddr *sai, struct sockaddr *lai, void *ssl_ctl)
{
	struct Client *new_client;
	s_assert(NULL != listener);

	/* 
	 * get the client socket name from the socket
	 * the client has already been checked out in accept_connection
	 */
	new_client = make_client(NULL);

	memcpy(&new_client->localClient->ip, sai, sizeof(struct rb_sockaddr_storage));
	memcpy(&new_client->preClient->lip, lai, sizeof(struct rb_sockaddr_storage));

	/* 
	 * copy address to 'sockhost' as a string, copy it to host too
	 * so we have something valid to put into error messages...
	 */
	rb_inet_ntop_sock((struct sockaddr *)&new_client->localClient->ip, new_client->sockhost, 
		sizeof(new_client->sockhost));


	rb_strlcpy(new_client->host, new_client->sockhost, sizeof(new_client->host));

	new_client->localClient->F = F;
	add_to_cli_fd_hash(new_client);
	new_client->localClient->listener = listener;
	new_client->localClient->ssl_ctl = ssl_ctl;
	if(ssl_ctl != NULL || rb_fd_ssl(F))
		SetSSL(new_client);

	++listener->ref_count;

	start_auth(new_client);
}
Exemple #14
0
struct Client *make_remote_person_full(struct Client *server, const char *nick, const char *username, const char *hostname, const char *ip, const char *realname)
{
	struct Client *client;
	struct sockaddr addr;

	client = make_client(server);
	make_user(client);
	SetRemoteClient(client);

	client->servptr = server;
	rb_dlinkAdd(server, &server->lnode, &server->servptr->serv->users);

	rb_inet_pton_sock(ip, &addr);
	rb_strlcpy(client->name, nick, sizeof(client->name));
	rb_strlcpy(client->username, username, sizeof(client->username));
	rb_strlcpy(client->host, hostname, sizeof(client->host));
	rb_inet_ntop_sock(&addr, client->sockhost, sizeof(client->sockhost));
	rb_strlcpy(client->info, realname, sizeof(client->info));

	add_to_client_hash(nick, client);
	add_to_hostname_hash(client->host, client);

	return client;
}
Exemple #15
0
// XXX Check IDs to make sure they are legal
void dssim_t::do_events() {
   while(config.sched.eventp(ticks)) {
      Sched::event ev = config.sched.pop();
      node_id_t nid = config.sched.nidid2nid[ev.nidid];
      LOG(l::DBG_EV, "Event tick:" << ticks
          << " nidid:" << ev.nidid
          << " nid:" << nid
          << " aid:" << aid2str[ev.aid]
          << "\n");
      switch(ev.aid){
         case Sched::A_DIE:
            net->die(nid);
            nodes.erase(nid);
            break;
         case Sched::A_SJOIN: {
            node_id_t nid = net->get_new_nid();
            make_server(nid);
         }
            break;
         case Sched::A_CJOIN: {
            node_id_t nid = net->get_new_nid();
            make_client(nid, "dynamic");
         }
            break;
         case Sched::A_PAUSE:
            paused.insert(nid);
            break;
         case Sched::A_UNPAUSE:
            if(paused.count(nid) > 0) {
               paused.erase(nid);
               nodes[nid]->set_unpaused_tick(now());
            }
            break;
      }
   }
}
Exemple #16
0
/*
 *  m_server
 *       parv[0] = sender prefix
 *       parv[1] = servername
 *       parv[2] = serverinfo/hopcount
 *       parv[3] = serverinfo
 */
int m_server(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
    int     i;
    char        info[REALLEN + 1], *host;
    aClient    *acptr, *bcptr;
    aConnect   *aconn;
    int         hop;
    char        nbuf[HOSTLEN * 2 + USERLEN + 5]; /* same size as in s_misc.c */

    info[0] = '\0';

    if (parc < 2 || *parv[1] == '\0')
    {
        sendto_one(cptr, "ERROR :No servername");
        return 0;
    }

    hop = 0;
    host = parv[1];
    if (parc > 3 && atoi(parv[2]))
    {
        hop = atoi(parv[2]);
        strncpyzt(info, parv[3], REALLEN + 1);
    }
    else if (parc > 2)
    {
        strncpyzt(info, parv[2], REALLEN + 1);
        if ((parc > 3) && ((i = strlen(info)) < (REALLEN - 2)))
        {
            strcat(info, " ");
            strncat(info, parv[3], REALLEN - i - 2);
            info[REALLEN] = '\0';
        }
    }
    /*
     * July 5, 1997
     * Rewritten to throw away server cruft from users,
     * combined the hostname validity test with cleanup of host name,
     * so a cleaned up hostname can be returned as an error if
     * necessary. - Dianora
     */

    /* yes, the if(strlen) below is really needed!! */
    if (strlen(host) > HOSTLEN)
        host[HOSTLEN] = '\0';

    if (IsPerson(cptr))
    {
        /* A local link that has been identified as a USER tries
         * something fishy... ;-)
         */
        sendto_one(cptr, err_str(ERR_UNKNOWNCOMMAND),
                   me.name, parv[0], "SERVER");

        return 0;
    }
    else
        /* hostile servername check */
    {
        /*
         * Lets check for bogus names and clean them up we don't bother
         * cleaning up ones from users, becasuse we will never see them
         * any more - Dianora
         */

        int bogus_server = 0;
        int found_dot = 0;
        char clean_host[(2 * HOSTLEN) + 1];
        char *s;
        char *d;
        int n;

        s = host;
        d = clean_host;
        n = (2 * HOSTLEN) - 2;

        while (*s && n > 0)
        {
            if ((unsigned char) *s < (unsigned char) ' ')
                /* Is it a control character? */
            {
                bogus_server = 1;
                *d++ = '^';
                *d++ = (char) ((unsigned char) *s + 0x40);
                /* turn it into a printable */
                n -= 2;
            }
            else if ((unsigned char) *s > (unsigned char) '~')
            {
                bogus_server = 1;
                *d++ = '.';
                n--;
            }
            else
            {
                if (*s == '.')
                    found_dot = 1;
                *d++ = *s;
                n--;
            }
            s++;
        }
        *d = '\0';

        if ((!found_dot) || bogus_server)
        {
            sendto_one(sptr, "ERROR :Bogus server name (%s)",
                       clean_host);
            return exit_client(cptr, cptr, cptr, "Bogus server name");
        }
    }

    /* new connection */
    if (IsUnknown(cptr) || IsHandshake(cptr))
    {
        strncpyzt(cptr->name, host, sizeof(cptr->name));
        strncpyzt(cptr->info, info[0] ? info : me.name, REALLEN + 1);
        cptr->hopcount = hop;

        switch (check_server_init(cptr))
        {
            case 0:
                return m_server_estab(cptr);
            case 1:
                sendto_ops("Access check for %s in progress",
                           get_client_name(cptr, HIDEME));
                return 1;
            default:
                ircstp->is_ref++;
                sendto_ops_lev(ADMIN_LEV, "Link %s dropped, no Connect block",
                           get_client_name(cptr, TRUE));
                return exit_client(cptr, cptr, cptr, "No Connect block");
        }
    }
    
    /* already linked server */
    if (!IsServer(cptr))
        return 0;

    if ((acptr = find_name(host, NULL)))
    {
        /*
         * * This link is trying feed me a server that I already have
         * access through another path -- multiple paths not accepted
         * currently, kill this link immediately!!
         *
         * 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", host);
        if (bcptr == cptr)
        {
            /* Don't complain for servers that are juped */
            /* (don't complain if the server that already exists is U: lined,
                unless I actually have a .conf U: line for it */
            if(!IsULine(acptr) || find_aUserver(acptr->name))
            {
                sendto_gnotice("from %s: Link %s cancelled, server %s already "
                               "exists", me.name, get_client_name(bcptr, HIDEME),
                               host);
                sendto_serv_butone(bcptr, ":%s GNOTICE :Link %s cancelled, "
                                   "server %s already exists", me.name,
                                   get_client_name(bcptr, HIDEME), host);
            }
            return exit_client(bcptr, bcptr, &me, "Server Exists");
        }
        /* 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", me.name, nbuf, host,
                       get_client_name(cptr, HIDEME));
        sendto_serv_butone(bcptr, ":%s GNOTICE :Link %s cancelled, server %s "
                           "reintroduced by %s", me.name, nbuf, host,
                           get_client_name(cptr, HIDEME));
        exit_client(bcptr, bcptr, &me, "Server Exists");
    }
    /*
     * The following if statement would be nice to remove since user
     * nicks never have '.' in them and servers must always have '.' in
     * them. There should never be a server/nick name collision, but it
     * is possible a capricious server admin could deliberately do
     * something strange.
     *
     * -Dianora
     */

    if ((acptr = find_client(host, NULL)) && acptr != cptr)
    {
        /*
         * * Server trying to use the same name as a person. Would
         * cause a fair bit of confusion. Enough to make it hellish for
         * a while and servers to send stuff to the wrong place.
         */
        sendto_one(cptr, "ERROR :Nickname %s already exists!", host);
        strcpy(nbuf, get_client_name(cptr, HIDEME));
        sendto_gnotice("from %s: Link %s cancelled, servername/nick collision",
                       me.name, nbuf);
        sendto_serv_butone(cptr, ":%s GNOTICE :Link %s cancelled, "
                           "servername/nick collision", me.name, nbuf);
        return exit_client(cptr, cptr, cptr, "Nick as Server");
    }

    if (IsServer(cptr))
    {
        /*
         * * Server is informing about a new server behind this link.
         * Create REMOTE server structure, add it to list and propagate
         * word to my other server links...
         */
        if (parc == 1 || info[0] == '\0')
        {
            sendto_one(cptr, "ERROR :No server info specified for %s", host);
            return 0;
        }
        /*
         * * See if the newly found server is behind a guaranteed leaf
         * (L-line). If so, close the link.
         *
         * Depreciated.  Kinda redundant with Hlines. -epi
         */
        if (!(cptr->serv->aconn->flags & CONN_HUB))
        {
            aconn = cptr->serv->aconn;
            sendto_gnotice("from %s: Non-Hub link %s introduced %s",
                           me.name, get_client_name(cptr, HIDEME), host);
            sendto_serv_butone(cptr,":%s GNOTICE :Non-Hub link %s introduced "
                               "%s", me.name, get_client_name(cptr, HIDEME),
                               host);
            sendto_one(cptr, "ERROR :You're not a hub (introducing %s)",
                       host);
            return exit_client(cptr, cptr, cptr, "Too many servers");
        }

        acptr = make_client(cptr, sptr);
        make_server(acptr);
        acptr->hopcount = hop;
        strncpyzt(acptr->name, host, sizeof(acptr->name));
        strncpyzt(acptr->info, info, REALLEN + 1);
        acptr->serv->up = find_or_add(parv[0]);

        fakelinkserver_update(acptr->name, acptr->info);
        SetServer(acptr);

        /*
         * if this server is behind a U-lined server, make it U-lined as
         * well. - lucas
         */

        if (IsULine(sptr) || find_aUserver(acptr->name))
        {
            acptr->flags |= FLAGS_ULINE;
            sendto_realops_lev(DEBUG_LEV, "%s introducing super server %s",
                               cptr->name, acptr->name);
        }

        Count.server++;

        add_client_to_list(acptr);
        add_to_client_hash_table(acptr->name, acptr);
        /*
         * Old sendto_serv_but_one() call removed because we now need
         * to send different names to different servers (domain name matching)
         */
        for (i = 0; i <= highest_fd; i++)
        {
            if (!(bcptr = local[i]) || !IsServer(bcptr) || bcptr == cptr ||
                IsMe(bcptr))
                continue;
            if (!(aconn = bcptr->serv->aconn))
            {
                sendto_gnotice("from %s: Lost Connect block for %s on %s."
                               " Closing", me.name,
                               get_client_name(cptr, HIDEME), host);
                sendto_serv_butone(cptr, ":%s GNOTICE :Lost Connect block for"
                                   " %s on %s. Closing", me.name,
                                   get_client_name(cptr, HIDEME), host);
                return exit_client(cptr, cptr, cptr, "Lost Connect block");
            }
            if (match(my_name_for_link(me.name, aconn), acptr->name) == 0)
                continue;
            sendto_one(bcptr, ":%s SERVER %s %d :%s",
                       parv[0], acptr->name, hop + 1, acptr->info);
        }
        return 0;
    }

    return 0;
}
Exemple #17
0
/** Read a 'packet' of data from a connection and process it.  Read in
 * 8k chunks to give a better performance rating (for server
 * connections).  Do some tricky stuff for client connections to make
 * sure they don't do any flooding >:-) -avalon
 * @param cptr Client from which to read data.
 * @param socket_ready If non-zero, more data can be read from the client's socket.
 * @return Positive number on success, zero on connection-fatal failure, negative
 *   if user is killed.
 */
static int read_packet(struct Client *cptr, int socket_ready)
{
  unsigned int dolen = 0;
  unsigned int length = 0;

  if (socket_ready &&
      !(IsUser(cptr) &&
	DBufLength(&(cli_recvQ(cptr))) > feature_uint(FEAT_CLIENT_FLOOD))) {
#if defined(USE_SSL)
    switch (client_recv(cptr, readbuf, sizeof(readbuf), &length)) {
#else
    switch (os_recv_nonb(cli_fd(cptr), readbuf, sizeof(readbuf), &length)) {
#endif
    case IO_SUCCESS:
      if (length)
      {
        cli_lasttime(cptr) = CurrentTime;
        ClearPingSent(cptr);
        ClrFlag(cptr, FLAG_NONL);
        if (cli_lasttime(cptr) > cli_since(cptr))
          cli_since(cptr) = cli_lasttime(cptr);
      }
      break;
    case IO_BLOCKED:
      break;
    case IO_FAILURE:
      cli_error(cptr) = errno;
      /* SetFlag(cptr, FLAG_DEADSOCKET); */
      return 0;
    }
  }

  /*
   * For server connections, we process as many as we can without
   * worrying about the time of day or anything :)
   */
  if (length > 0 && IsServer(cptr))
    return server_dopacket(cptr, readbuf, length);
  else if (length > 0 && (IsHandshake(cptr) || IsConnecting(cptr)))
    return connect_dopacket(cptr, readbuf, length);
  else
  {
    /*
     * Before we even think of parsing what we just read, stick
     * it on the end of the receive queue and do it when its
     * turn comes around.
     */
    if (length > 0 && dbuf_put(cptr, &(cli_recvQ(cptr)), readbuf, length) == 0)
      return exit_client(cptr, cptr, &me, "dbuf_put fail");

    if ((DBufLength(&(cli_recvQ(cptr))) > feature_uint(FEAT_CLIENT_FLOOD))
         && !IsChannelService(cptr))
      return exit_client(cptr, cptr, &me, "Excess Flood");

    while (DBufLength(&(cli_recvQ(cptr))) && !NoNewLine(cptr) &&
           (IsTrusted(cptr) || IsChannelService(cptr) || cli_since(cptr) - CurrentTime < 10))
    {
      dolen = dbuf_getmsg(&(cli_recvQ(cptr)), cli_buffer(cptr), BUFSIZE);
      /*
       * Devious looking...whats it do ? well..if a client
       * sends a *long* message without any CR or LF, then
       * dbuf_getmsg fails and we pull it out using this
       * loop which just gets the next 512 bytes and then
       * deletes the rest of the buffer contents.
       * -avalon
       */
      if (dolen == 0)
      {
        if (DBufLength(&(cli_recvQ(cptr))) < 510)
          SetFlag(cptr, FLAG_NONL);
        else
        {
          /* More than 512 bytes in the line - drop the input and yell
           * at the client.
           */
          DBufClear(&(cli_recvQ(cptr)));
          send_reply(cptr, ERR_INPUTTOOLONG);
        }
      }
      else if (client_dopacket(cptr, dolen) == CPTR_KILLED)
        return CPTR_KILLED;
      /*
       * If it has become registered as a Server
       * then skip the per-message parsing below.
       */
      if (IsHandshake(cptr) || IsServer(cptr))
      {
        while (-1)
        {
          dolen = dbuf_get(&(cli_recvQ(cptr)), readbuf, sizeof(readbuf));
          if (dolen <= 0)
            return 1;
          else if (dolen == 0)
          {
            if (DBufLength(&(cli_recvQ(cptr))) < 510)
              SetFlag(cptr, FLAG_NONL);
            else {
              DBufClear(&(cli_recvQ(cptr)));
              /* send_reply(cptr, ERR_INPUTTOOLONG); */
            }
          }
          else if ((IsServer(cptr) &&
                    server_dopacket(cptr, readbuf, dolen) == CPTR_KILLED) ||
                   (!IsServer(cptr) &&
                    connect_dopacket(cptr, readbuf, dolen) == CPTR_KILLED))
            return CPTR_KILLED;
        }
      }
    }

    /* If there's still data to process, wait 2 seconds first */
    if (DBufLength(&(cli_recvQ(cptr))) && !NoNewLine(cptr) &&
	!t_onqueue(&(cli_proc(cptr))))
    {
      Debug((DEBUG_LIST, "Adding client process timer for %C", cptr));
      cli_freeflag(cptr) |= FREEFLAG_TIMER;
      timer_add(&(cli_proc(cptr)), client_timer_callback, cli_connect(cptr),
		TT_RELATIVE, 2);
    }
  }
  return 1;
}

/** Start a connection to another server.
 * @param aconf Connect block data for target server.
 * @param by Client who requested the connection (if any).
 * @return Non-zero on success; zero on failure.
 */
int connect_server(struct ConfItem* aconf, struct Client* by)
{
  struct Client*   cptr = 0;
  assert(0 != aconf);

  if (aconf->dns_pending) {
    sendto_opmask(0, SNO_OLDSNO, "Server %s connect DNS pending",
                  aconf->name);
    return 0;
  }
  Debug((DEBUG_NOTICE, "Connect to %s[@%s]", aconf->name,
         ircd_ntoa(&aconf->address.addr)));

  if ((cptr = FindClient(aconf->name))) {
    if (IsServer(cptr) || IsMe(cptr)) {
      sendto_opmask(0, SNO_OLDSNO, "Server %s already present from %s",
                    aconf->name, cli_name(cli_from(cptr)));
      if (by && IsUser(by) && !MyUser(by)) {
        sendcmdto_one(&me, CMD_NOTICE, by, "%C :Server %s already present "
                      "from %s", by, aconf->name, cli_name(cli_from(cptr)));
      }
      return 0;
    }
    else if (IsHandshake(cptr) || IsConnecting(cptr)) {
      if (by && IsUser(by)) {
        sendcmdto_one(&me, CMD_NOTICE, by, "%C :Connection to %s already in "
                      "progress", by, cli_name(cptr));
      }
      return 0;
    }
  }
  /*
   * If we don't know the IP# for this host and it is a hostname and
   * not a ip# string, then try and find the appropriate host record.
   */
  if (!irc_in_addr_valid(&aconf->address.addr)
      && !ircd_aton(&aconf->address.addr, aconf->host)) {
    char buf[HOSTLEN + 1];

    host_from_uh(buf, aconf->host, HOSTLEN);
    gethost_byname(buf, connect_dns_callback, aconf);
    aconf->dns_pending = 1;
    return 0;
  }
  cptr = make_client(NULL, STAT_UNKNOWN_SERVER);

  /*
   * Copy these in so we have something for error detection.
   */
  ircd_strncpy(cli_name(cptr), aconf->name, HOSTLEN);
  ircd_strncpy(cli_sockhost(cptr), aconf->host, HOSTLEN);

  /*
   * Attach config entries to client here rather than in
   * completed_connection. This to avoid null pointer references
   */
  attach_confs_byhost(cptr, aconf->host, CONF_SERVER);

  if (!find_conf_byhost(cli_confs(cptr), aconf->host, CONF_SERVER)) {
    sendto_opmask(0, SNO_OLDSNO, "Host %s is not enabled for "
                  "connecting: no Connect block", aconf->name);
    if (by && IsUser(by) && !MyUser(by)) {
      sendcmdto_one(&me, CMD_NOTICE, by, "%C :Connect to host %s failed: no "
                    "Connect block", by, aconf->name);
    }
    det_confs_butmask(cptr, 0);
    free_client(cptr);
    return 0;
  }
  /*
   * attempt to connect to the server in the conf line
   */
  if (!connect_inet(aconf, cptr)) {
    if (by && IsUser(by) && !MyUser(by)) {
      sendcmdto_one(&me, CMD_NOTICE, by, "%C :Couldn't connect to %s", by,
                    cli_name(cptr));
    }
    det_confs_butmask(cptr, 0);
    free_client(cptr);
    return 0;
  }
  /*
   * NOTE: if we're here we have a valid C:Line and the client should
   * have started the connection and stored the remote address/port and
   * ip address name in itself
   *
   * The socket has been connected or connect is in progress.
   */
  make_server(cptr);
  if (by && IsUser(by)) {
    ircd_snprintf(0, cli_serv(cptr)->by, sizeof(cli_serv(cptr)->by), "%s%s",
		  NumNick(by));
    assert(0 == cli_serv(cptr)->user);
    cli_serv(cptr)->user = cli_user(by);
    cli_user(by)->refcnt++;
  }
  else {
    *(cli_serv(cptr))->by = '\0';
    /* strcpy(cptr->serv->by, "Auto"); */
  }
  cli_serv(cptr)->up = &me;
  SetConnecting(cptr);

  if (cli_fd(cptr) > HighestFd)
    HighestFd = cli_fd(cptr);

  LocalClientArray[cli_fd(cptr)] = cptr;

  Count_newunknown(UserStats);
  /* Actually we lie, the connect hasn't succeeded yet, but we have a valid
   * cptr, so we register it now.
   * Maybe these two calls should be merged.
   */
  add_client_to_list(cptr);
  hAddClient(cptr);
/*    nextping = CurrentTime; */

  return (s_state(&cli_socket(cptr)) == SS_CONNECTED) ?
    completed_connection(cptr) : 1;
}

/** Find the real hostname for the host running the server (or one which
 * matches the server's name) and its primary IP#.  Hostname is stored
 * in the client structure passed as a pointer.
 */
void init_server_identity(void)
{
  const struct LocalConf* conf = conf_get_local();
  assert(0 != conf);

  ircd_strncpy(cli_name(&me), conf->name, HOSTLEN);
  SetYXXServerName(&me, conf->numeric);
}

/** Process events on a client socket.
 * @param ev Socket event structure that has a struct Connection as
 *   its associated data.
 */
static void client_sock_callback(struct Event* ev)
{
  struct Client* cptr;
  struct Connection* con;
  char *fmt = "%s";
  char *fallback = 0;

  assert(0 != ev_socket(ev));
  assert(0 != s_data(ev_socket(ev)));

  con = (struct Connection*) s_data(ev_socket(ev));

  assert(0 != con_client(con) || ev_type(ev) == ET_DESTROY);

  cptr = con_client(con);

  assert(0 == cptr || con == cli_connect(cptr));

  switch (ev_type(ev)) {
  case ET_DESTROY:
    con_freeflag(con) &= ~FREEFLAG_SOCKET;

    if (!con_freeflag(con) && !cptr)
      free_connection(con);
#if defined(USE_SSL)
    ssl_free(ev_socket(ev));
#endif
    break;

  case ET_CONNECT: /* socket connection completed */
    if (!completed_connection(cptr) || IsDead(cptr))
      fallback = cli_info(cptr);
    break;

  case ET_ERROR: /* an error occurred */
    fallback = cli_info(cptr);
    cli_error(cptr) = ev_data(ev);
    /* If the OS told us we have a bad file descriptor, we should
     * record that for future reference.
     */
    if (cli_error(cptr) == EBADF)
      cli_fd(cptr) = -1;
    if (s_state(&(con_socket(con))) == SS_CONNECTING) {
      completed_connection(cptr);
      /* for some reason, the os_get_sockerr() in completed_connection()
       * can return 0 even when ev_data(ev) indicates a real error, so
       * re-assign the client error here.
       */
      cli_error(cptr) = ev_data(ev);
      break;
    }
    /*FALLTHROUGH*/
  case ET_EOF: /* end of file on socket */
    Debug((DEBUG_ERROR, "READ ERROR: fd = %d %d", cli_fd(cptr),
	   cli_error(cptr)));
    SetFlag(cptr, FLAG_DEADSOCKET);
    if ((IsServer(cptr) || IsHandshake(cptr)) && cli_error(cptr) == 0) {
      exit_client_msg(cptr, cptr, &me, "Server %s closed the connection (%s)",
		      cli_name(cptr), cli_serv(cptr)->last_error_msg);
      return;
    } else {
      fmt = "Read error: %s";
      fallback = "EOF from client";
    }
    break;

  case ET_WRITE: /* socket is writable */
    ClrFlag(cptr, FLAG_BLOCKED);
    if (cli_listing(cptr) && MsgQLength(&(cli_sendQ(cptr))) < 2048)
      list_next_channels(cptr);
    Debug((DEBUG_SEND, "Sending queued data to %C", cptr));
    send_queued(cptr);
    break;

  case ET_READ: /* socket is readable */
    if (!IsDead(cptr)) {
      Debug((DEBUG_DEBUG, "Reading data from %C", cptr));
      if (read_packet(cptr, 1) == 0) /* error while reading packet */
	fallback = "EOF from client";
    }
    break;

  default:
    assert(0 && "Unrecognized socket event in client_sock_callback()");
    break;
  }

  assert(0 == cptr || 0 == cli_connect(cptr) || con == cli_connect(cptr));

  if (fallback) {
    const char* msg = (cli_error(cptr)) ? strerror(cli_error(cptr)) : fallback;
    if (!msg)
      msg = "Unknown error";
    exit_client_msg(cptr, cptr, &me, fmt, msg);
  }
}

/** Process a timer on client socket.
 * @param ev Timer event that has a struct Connection as its
 * associated data.
 */
static void client_timer_callback(struct Event* ev)
{
  struct Client* cptr;
  struct Connection* con;

  assert(0 != ev_timer(ev));
  assert(0 != t_data(ev_timer(ev)));
  assert(ET_DESTROY == ev_type(ev) || ET_EXPIRE == ev_type(ev));

  con = (struct Connection*) t_data(ev_timer(ev));

  assert(0 != con_client(con) || ev_type(ev) == ET_DESTROY);

  cptr = con_client(con);

  assert(0 == cptr || con == cli_connect(cptr));

  if (ev_type(ev)== ET_DESTROY) {
    con_freeflag(con) &= ~FREEFLAG_TIMER; /* timer has expired... */

    if (!con_freeflag(con) && !cptr)
      free_connection(con); /* client is being destroyed */
  } else {
    Debug((DEBUG_LIST, "Client process timer for %C expired; processing",
	   cptr));
    read_packet(cptr, 0); /* read_packet will re-add timer if needed */
  }

  assert(0 == cptr || 0 == cli_connect(cptr) || con == cli_connect(cptr));
}
Exemple #18
0
/*
 * nick_from_server()
 */
static void
nick_from_server(struct Client *client_p, struct Client *source_p, int parc,
                 char *parv[], time_t newts, const char *svsid, char *nick, char *ngecos)
{
  int samenick = 0;

  if (IsServer(source_p))
  {
    /* A server introducing a new client, change source */
    source_p = make_client(client_p);
    dlinkAdd(source_p, &source_p->node, &global_client_list);

    if (parc > 2)
      source_p->hopcount = atoi(parv[2]);
    if (newts)
      source_p->tsinfo = newts;
    else
    {
      newts = source_p->tsinfo = CurrentTime;
      ts_warn("Remote nick %s (%s) introduced without a TS", nick, parv[0]);
    }

    strlcpy(source_p->svid, svsid, sizeof(source_p->svid));
    strlcpy(source_p->info, ngecos, sizeof(source_p->info));
    /* copy the nick in place */
    strlcpy(source_p->name, nick, sizeof(source_p->name));
    hash_add_client(source_p);

    if (parc > 8)
    {
      const char *m;

      /* parse usermodes */
      for (m = &parv[4][1]; *m; ++m)
      {
        unsigned int flag = user_modes[(unsigned char)*m];

        if ((flag & UMODE_INVISIBLE) && !HasUMode(source_p, UMODE_INVISIBLE))
          ++Count.invisi;
        if ((flag & UMODE_OPER) && !HasUMode(source_p, UMODE_OPER))
          ++Count.oper;

        source_p->umodes |= flag & SEND_UMODES;
      }

      register_remote_user(source_p, parv[5], parv[6],
                           parv[7], ngecos);
      return;
    }
  }
  else if (source_p->name[0])
  {
    samenick = !irccmp(source_p->name, nick);

    /* Client changing their nick */
    if (!samenick)
    {
      DelUMode(source_p, UMODE_REGISTERED);
      watch_check_hash(source_p, RPL_LOGOFF);
      source_p->tsinfo = newts ? newts : CurrentTime;
    }

    sendto_common_channels_local(source_p, 1, 0, ":%s!%s@%s NICK :%s",
                                 source_p->name,source_p->username,
                                 source_p->host, nick);

    add_history(source_p, 1);
    sendto_server(client_p, CAP_TS6, NOCAPS,
                  ":%s NICK %s :%lu",
                  ID(source_p), nick, (unsigned long)source_p->tsinfo);
    sendto_server(client_p, NOCAPS, CAP_TS6,
                  ":%s NICK %s :%lu",
                  source_p->name, nick, (unsigned long)source_p->tsinfo);
  }

  /* set the new nick name */
  if (source_p->name[0])
    hash_del_client(source_p);

  strlcpy(source_p->name, nick, sizeof(source_p->name));
  hash_add_client(source_p);

  if (!samenick)
    watch_check_hash(source_p, RPL_LOGON);
}
Exemple #19
0
/** Handle a SERVER message from another server.
 *
 * \a parv has the following elements:
 * \li \a parv[1] is the server name
 * \li \a parv[2] is the hop count to the server
 * \li \a parv[3] is the start timestamp for the server
 * \li \a parv[4] is the link timestamp
 * \li \a parv[5] is the protocol version (P10 or J10)
 * \li \a parv[6] is the numnick mask for the server
 * \li \a parv[7] is a string of flags like +hs to mark hubs and services
 * \li \a parv[\a parc - 1] is the server description
 *
 * See @ref m_functions for discussion of the arguments.
 * @param[in] cptr Client that sent us the message.
 * @param[in] sptr Original source of message.
 * @param[in] parc Number of arguments.
 * @param[in] parv Argument vector.
 */
int ms_server(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  int              i;
  char*            host;
  struct Client*   acptr;
  struct Client*   bcptr;
  int              hop;
  int              ret;
  unsigned short   prot;
  time_t           start_timestamp;
  time_t           timestamp;

  if (parc < 8)
  {
    return need_more_params(sptr, "SERVER");
    return exit_client(cptr, cptr, &me, "Need more parameters");
  }
  host = clean_servername(parv[1]);
  if (!host)
  {
    sendto_opmask(0, SNO_OLDSNO, "Bogus server name (%s) from %s",
                  host, cli_name(cptr));
    return exit_client_msg(cptr, cptr, &me, "Bogus server name (%s)", host);
  }

  /*
   * 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]);
  else if (prot < atoi(MINOR_PROTOCOL))
    return exit_new_server(cptr, sptr, host, timestamp,
                           "Incompatible protocol: %s", parv[5]);

  Debug((DEBUG_INFO, "Got SERVER %s with timestamp [%s] age %Tu (%Tu)",
	 host, parv[4], start_timestamp, cli_serv(&me)->timestamp));

  if (timestamp < OLDEST_TS)
    return exit_client_msg(cptr, sptr, &me,
        "Bogus timestamps (%s %s)", parv[3], parv[4]);

  if (parv[parc - 1][0] == '\0')
    return exit_client_msg(cptr, cptr, &me,
                           "No server info specified for %s", host);

  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;

  /*
   * Server is informing about a new server behind
   * this link. Create REMOTE server structure,
   * add it to list and propagate word to my other
   * server links...
   */

  acptr = make_client(cptr, STAT_SERVER);
  make_server(acptr);
  cli_serv(acptr)->prot = prot;
  cli_serv(acptr)->timestamp = timestamp;
  cli_hopcount(acptr) = hop;
  ircd_strncpy(cli_name(acptr), host, HOSTLEN);
  ircd_strncpy(cli_info(acptr), parv[parc-1], REALLEN);
  cli_serv(acptr)->up = sptr;
  cli_serv(acptr)->updown = add_dlink(&(cli_serv(sptr))->down, acptr);
  /* Use cptr, because we do protocol 9 -> 10 translation
     for numeric nicks ! */
  SetServerYXX(cptr, acptr, parv[6]);
  update_uworld_flags(cptr);

  if (*parv[7] == '+')
    set_server_flags(acptr, parv[7] + 1);

  Count_newremoteserver(UserStats);
  add_client_to_list(acptr);
  hAddClient(acptr);
  if (*parv[5] == 'J')
  {
    SetBurst(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(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
   * different names to different servers (domain name matching).
   */
  for (i = 0; i <= HighestFd; i++)
  {
    if (!(bcptr = LocalClientArray[i]) || !IsServer(bcptr) ||
        bcptr == cptr || IsMe(bcptr))
      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 :%s",
                  cli_name(acptr), hop + 1, parv[4], parv[5],
                  NumServCap(acptr), IsHub(acptr) ? "h" : "",
                  IsService(acptr) ? "s" : "", IsIPv6(acptr) ? "6" : "",
                  cli_info(acptr));
  }
  return 0;
}
Exemple #20
0
/*
 * m_nick 
 * parv[0] = sender prefix 
 * parv[1] = nickname 
 * parv[2] = hopcount when new user; TS when nick change 
 * parv[3] = TS
 * ---- new user only below ---- 
 * parv[4] = umode 
 * parv[5] = username 
 * parv[6] = hostname 
 * parv[7] = server 
 * parv[8] = serviceid
 * parv[9] = IP
 * parv[10] = ircname
 * -- endif
 */
int m_nick(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
    struct simBan *ban;
    aClient    *acptr, *uplink;
    Link       *lp, *lp2;
    char        nick[NICKLEN + 2];
    ts_val      newts = 0;
    int         sameuser = 0, samenick = 0;
  
    if (parc < 2)
    {
	sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN),
		   me.name, parv[0]);
	return 0;
    }
  
    if (!IsServer(sptr) && IsServer(cptr) && parc > 2)
	newts = atol(parv[2]);
    else if (IsServer(sptr) && parc > 3)
	newts = atol(parv[3]);
    else
	parc = 2;
    /*
     * parc == 2 on a normal client sign on (local) and a normal client 
     * nick change 
     * parc == 4 on a normal server-to-server client nick change
     * parc == 11 on a normal TS style server-to-server NICK introduction
     */
    if ((IsServer(sptr) || (parc > 4)) && (parc < 11))
    {
	/*
	 * We got the wrong number of params. Someone is trying to trick
	 * us. Kill it. -ThemBones As discussed with ThemBones, not much
	 * point to this code now sending a whack of global kills would
	 * also be more annoying then its worth, just note the problem,
	 * and continue -Dianora
	 */
	sendto_realops("IGNORING BAD NICK: %s[%s@%s] on %s (from %s)", parv[1],
		       (parc >= 6) ? parv[5] : "-",
		       (parc >= 7) ? parv[6] : "-",
		       (parc >= 8) ? parv[7] : "-", parv[0]);
	return 0;
     
    }
   
    strncpyzt(nick, parv[1], NICKLEN + 1);
    /*
     * if do_nick_name() returns a null name OR if the server sent a
     * nick name and do_nick_name() changed it in some way (due to rules
     * of nick creation) then reject it. If from a server and we reject
     * it, and KILL it. -avalon 4/4/92
     */
    if (do_nick_name(nick) == 0 || (IsServer(cptr) && strcmp(nick, parv[1])))
    {
	sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME),
		   me.name, parv[0], parv[1], "Erroneous Nickname");
	
	if (IsServer(cptr))
	{
	    ircstp->is_kill++;
        sendto_realops_lev(DEBUG_LEV, "Bad Nick: %s From: %s Via: %s",
			       parv[1], parv[0],
			       get_client_name(cptr, HIDEME));
	    sendto_one(cptr, ":%s KILL %s :%s (Bad Nick)",
		       me.name, parv[1], me.name);
	    if (sptr != cptr) { /* bad nick change */     
		sendto_serv_butone(cptr, ":%s KILL %s :%s (Bad Nick)", me.name,
				   parv[0], me.name);
		sptr->flags |= FLAGS_KILLED;
		return exit_client(cptr, sptr, &me, "BadNick");
	    }
	}
	return 0;
    }
    /*
     * Check against nick name collisions.
     * 
     * Put this 'if' here so that the nesting goes nicely on the screen
     * :) We check against server name list before determining if the
     * nickname is present in the nicklist (due to the way the below
     * for loop is constructed). -avalon
     */
    do
    {
	if ((acptr = find_server(nick, NULL)))
	    if (MyConnect(sptr))
	    {
		sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), me.name,
			   BadPtr(parv[0]) ? "*" : parv[0], nick);
		return 0;
	    }
	
	/* 
	 * acptr already has result from find_server
	 * Well. unless we have a capricious server on the net, a nick can
	 * never be the same as a server name - Dianora
	 * That's not the only case; maybe someone broke do_nick_name
	 * or changed it so they could use "." in nicks on their network 
	 * - sedition
	 */
     
	if (acptr)
	{
	    /*
	     * We have a nickname trying to use the same name as a
	     * server. Send out a nick collision KILL to remove the
	     * nickname. As long as only a KILL is sent out, there is no
	     * danger of the server being disconnected.  Ultimate way to
	     * jupiter a nick ? >;-). -avalon
	     */
	    sendto_realops_lev(SKILL_LEV, "Nick collision on %s", sptr->name);
	    ircstp->is_kill++;
	    sendto_one(cptr, ":%s KILL %s :%s (Nick Collision)", me.name, 
		       sptr->name, me.name);
	    sptr->flags |= FLAGS_KILLED;
	    return exit_client(cptr, sptr, &me, "Nick/Server collision");
	}
	
	if (!(acptr = find_client(nick, NULL)))
	    break;
     
	/*
	 * If acptr == sptr, then we have a client doing a nick change
	 * between *equivalent* nicknames as far as server is concerned
	 * (user is changing the case of his/her nickname or somesuch)
	 */
	if (acptr == sptr)
	{
	    if (strcmp(acptr->name, nick) == 0) 
		return 0;
	    else
		break;
	} /* If user is changing nick to itself no point in propogating */
     
	/*
	 * Note: From this point forward it can be assumed that acptr !=
	 * sptr (point to different client structures).
	 *
	 * If the older one is "non-person", the new entry is just 
	 * allowed to overwrite it. Just silently drop non-person, and
	 * proceed with the nick. This should take care of the "dormant
	 * nick" way of generating collisions...
	 */
	if (IsUnknown(acptr))
	{
	    if (MyConnect(acptr))
	    {
		exit_client(NULL, acptr, &me, "Overridden");
		break;
	    }
	    else if (!(acptr->user))
	    {
		sendto_realops_lev(SKILL_LEV, "Nick Collision on %s", parv[1]);
		sendto_serv_butone(NULL, ":%s KILL %s :%s (Nick Collision)",
				   me.name, acptr->name, me.name);
		acptr->flags |= FLAGS_KILLED;
		/* Having no USER struct should be ok... */
		return exit_client(cptr, acptr, &me,
				   "Got TS NICK before Non-TS USER");
	    }
	}
     
	if (!IsServer(cptr))
	{
	    /*
	     * NICK is coming from local client connection. Just send
	     * error reply and ignore the command.
	     * parv[0] is empty on connecting clients
	     */
	    sendto_one(sptr, err_str(ERR_NICKNAMEINUSE),
		       me.name, BadPtr(parv[0]) ? "*" : parv[0], nick);
	    return 0;
	}
	/*
	 * NICK was coming from a server connection. Means that the same
	 * nick is registered for different users by different server.
	 * This is either a race condition (two users coming online about
	 * same time, or net reconnecting) or just two net fragments
	 * becoming joined and having same nicks in use. We cannot have
	 * TWO users with same nick--purge this NICK from the system with
	 * a KILL... >;)
	 *
	 * Changed to something reasonable like IsServer(sptr) (true if
	 * "NICK new", false if ":old NICK new") -orabidoo
	 */
     
	if (IsServer(sptr))
	{
	    /*
	     * A new NICK being introduced by a neighbouring server (e.g.
	     * message type "NICK new" received)
	     */
	    if (!newts || !acptr->tsinfo || (newts == acptr->tsinfo))
	    {
		sendto_realops_lev(SKILL_LEV, "Nick collision on %s", parv[1]);
		ircstp->is_kill++;
		sendto_one(acptr, err_str(ERR_NICKCOLLISION),
			   me.name, acptr->name, acptr->name);
		sendto_serv_butone(NULL, ":%s KILL %s :%s (Nick Collision)",
				   me.name, acptr->name, me.name);
		acptr->flags |= FLAGS_KILLED;
		return exit_client(cptr, acptr, &me, "Nick collision");
	    }
	    else
	    {
		/* XXX This looks messed up to me XXX - Raist */
		sameuser = (acptr->user) &&
		    mycmp(acptr->user->username, parv[5]) == 0 &&
		    mycmp(acptr->user->host, parv[6]) == 0;
		if ((sameuser && newts < acptr->tsinfo) || 
		    (!sameuser && newts > acptr->tsinfo))
		{
		    return 0;
		}
		else
		{
		    sendto_realops_lev(SKILL_LEV, "Nick collision on %s",parv[1]);
		    ircstp->is_kill++;
		    sendto_one(acptr, err_str(ERR_NICKCOLLISION),
			       me.name, acptr->name, acptr->name);
		    sendto_serv_butone(sptr, ":%s KILL %s :%s (Nick Collision)",
				       me.name, acptr->name, me.name);
		    acptr->flags |= FLAGS_KILLED;
		    (void) exit_client(cptr, acptr, &me, "Nick collision");
		    break;
		}
	    }
	}
	/*
	 * * A NICK change has collided (e.g. message type * ":old NICK
	 * new". This requires more complex cleanout. * Both clients must be
	 * purged from this server, the "new" * must be killed from the
	 * incoming connection, and "old" must * be purged from all outgoing
	 * connections.
	 */
	if (!newts || !acptr->tsinfo || (newts == acptr->tsinfo) ||
	    !sptr->user)
	{
	    sendto_realops_lev(SKILL_LEV, "Nick change collision: %s", parv[1]);
	    ircstp->is_kill++;
	    sendto_one(acptr, err_str(ERR_NICKCOLLISION),
		       me.name, acptr->name, acptr->name);
	    sendto_serv_butone(NULL, ":%s KILL %s :%s (Nick Collision)",me.name,
			       sptr->name, me.name);
	    ircstp->is_kill++;
	    sendto_serv_butone(NULL, ":%s KILL %s :%s (Nick Collision)",me.name,
			       acptr->name, me.name);
	    acptr->flags |= FLAGS_KILLED;
	    (void) exit_client(NULL, acptr, &me, "Nick collision(new)");
	    sptr->flags |= FLAGS_KILLED;
	    return exit_client(cptr, sptr, &me, "Nick collision(old)");
	}
	else
	{
	    /* XXX This looks messed up XXX */
	    sameuser = mycmp(acptr->user->username, sptr->user->username) == 0
		&& mycmp(acptr->user->host, sptr->user->host) == 0;
	    if ((sameuser && newts < acptr->tsinfo) ||
		(!sameuser && newts > acptr->tsinfo)) {
		if (sameuser)
		    sendto_realops_lev(SKILL_LEV, 
				   "Nick change collision from %s to %s",
				   sptr->name, acptr->name);
		ircstp->is_kill++;
		sendto_serv_butone(cptr, ":%s KILL %s :%s (Nick Collision)", me.name,
				   sptr->name, me.name);
		sptr->flags |= FLAGS_KILLED;
		if (sameuser)
		    return exit_client(cptr, sptr, &me, "Nick collision(old)");
		else
		    return exit_client(cptr, sptr, &me, "Nick collision(new)");
	    } 
	    else
	    {
		sendto_realops_lev(SKILL_LEV, "Nick collision on %s", acptr->name);
		
		ircstp->is_kill++;
		sendto_one(acptr, err_str(ERR_NICKCOLLISION),
			   me.name, acptr->name, acptr->name);
		sendto_serv_butone(sptr, ":%s KILL %s :%s (Nick Collision)",me.name,
				   acptr->name, me.name);
		acptr->flags |= FLAGS_KILLED;
		(void) exit_client(cptr, acptr, &me, "Nick collision");
	    }
	}
    } while (0);
    
    if (IsServer(sptr))
    {
	uplink = find_server(parv[7], NULL);
	if(!uplink)
	{
	    /* if we can't find the server this nick is on, 
	     * complain loudly and ignore it. - lucas */
	    sendto_realops("Remote nick %s on UNKNOWN server %s",
			   nick, parv[7]);
	    return 0;
	}
	sptr = make_client(cptr, uplink);
	
	/* If this is on a U: lined server, it's a U: lined client. */
	if(IsULine(uplink))
	    sptr->flags|=FLAGS_ULINE;
     
	add_client_to_list(sptr);
	if (parc > 2)
	    sptr->hopcount = atoi(parv[2]);
	if (newts)
	{
	    sptr->tsinfo = newts;
	}
	else
	{
	    newts = sptr->tsinfo = (ts_val) timeofday;
	    ts_warn("Remote nick %s introduced without a TS", nick);
	}
	/* copy the nick in place */
	(void) strcpy(sptr->name, nick);
	(void) add_to_client_hash_table(nick, sptr);
	if (parc >= 10)
	{
	    int *s, flag;
	    char *m;
       
	    /* parse the usermodes -orabidoo */
	    m = &parv[4][1];
	    while (*m)
	    {
		for (s = user_modes; (flag = *s); s += 2)
		    if (*m == *(s + 1))
		    {
			if ((flag == UMODE_o) || (flag == UMODE_O))
			    Count.oper++;
			sptr->umode |= flag & SEND_UMODES;
			break;
		    }
		m++;
	    }
	    if (parc==10)
	    {
		return do_user(nick, cptr, sptr, parv[5], parv[6],
			       parv[7], strtoul(parv[8], NULL, 0),
			       "0.0.0.0", parv[9]);
	    } else if (parc==11)
	    {
		return do_user(nick, cptr, sptr, parv[5], parv[6], parv[7],
			       strtoul(parv[8], NULL, 0),
			       parv[9], parv[10]);
	    }
	}
    }
    else if (sptr->name[0])
    {
#ifdef DONT_CHECK_QLINE_REMOTE
	if (MyConnect(sptr))
	{
#endif
	    if ((ban = check_mask_simbanned(nick, SBAN_NICK)))
	    {
#ifndef DONT_CHECK_QLINE_REMOTE
		if (!MyConnect(sptr))
		    sendto_realops("Restricted nick %s from %s on %s", nick,
				   (*sptr->name != 0 && !IsServer(sptr)) ?
				   sptr->name : "<unregistered>",
				   (sptr->user == NULL) ? ((IsServer(sptr)) ?
							   parv[6] : me.name) :
				   sptr->user->server);
#endif
		
		if (MyConnect(sptr) && (!IsServer(cptr)) && (!IsOper(cptr))
		    && (!IsULine(sptr)))
		{
		    sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name,
			       BadPtr(parv[0]) ? "*" : parv[0], nick,
			       BadPtr(ban->reason) ? "Erroneous Nickname" :
			       ban->reason);
                    if (call_hooks(CHOOK_FORBID, cptr, nick, ban) != FLUSH_BUFFER)
		        sendto_realops_lev(REJ_LEV,
			    	           "Forbidding restricted nick %s from %s",
				           nick, get_client_name(cptr, FALSE));
		    return 0;
		}
	    }
#ifdef DONT_CHECK_QLINE_REMOTE
	}
#endif
	if (MyConnect(sptr))
	{
	    if (IsRegisteredUser(sptr))
	    {
	 
		/* before we change their nick, make sure they're not banned
		 * on any channels, and!! make sure they're not changing to
		 * a banned nick -sed */
		/* a little cleaner - lucas */
	 
		for (lp = sptr->user->channel; lp; lp = lp->next)
		{
		    if (can_send(sptr, lp->value.chptr, NULL))
		    { 
			sendto_one(sptr, err_str(ERR_BANNICKCHANGE), me.name,
				   sptr->name, lp->value.chptr->chname);
			return 0;
		    }
		    if (nick_is_banned(lp->value.chptr, nick, sptr) != NULL)
		    {
			sendto_one(sptr, err_str(ERR_BANONCHAN), me.name,
				   sptr->name, nick, lp->value.chptr->chname);
			return 0;
		    }
		}
#ifdef ANTI_NICK_FLOOD
		if ((sptr->last_nick_change + MAX_NICK_TIME) < NOW)
		    sptr->number_of_nick_changes = 0;
		sptr->last_nick_change = NOW;
		sptr->number_of_nick_changes++;
	 
		if (sptr->number_of_nick_changes > MAX_NICK_CHANGES && 
		    !IsAnOper(sptr))
		{
		    sendto_one(sptr,
			       ":%s NOTICE %s :*** Notice -- Too many nick "
			       "changes. Wait %d seconds before trying again.",
			       me.name, sptr->name, MAX_NICK_TIME);
		    return 0;
		}
#endif
		/* If it changed nicks, -r it */
		if ((sptr->umode & UMODE_r) && (mycmp(parv[0], nick) != 0))
		{
		    unsigned int oldumode;
		    char mbuf[BUFSIZE];

		    oldumode = sptr->umode;
		    sptr->umode &= ~UMODE_r;
		    send_umode(sptr, sptr, oldumode, ALL_UMODES, mbuf);
		}

                /* LOCAL NICKHANGE */
                /*
                 * Client just changing his/her nick. If he/she is on a
                 * channel, send note of change to all clients on that channel.
                 * Propagate notice to other servers.
                 */
                /* if the nickname is different, set the TS */
                if (mycmp(parv[0], nick))
                {
                  sptr->tsinfo = newts ? newts : (ts_val) timeofday;
                }

		sendto_common_channels(sptr, ":%s NICK :%s", parv[0], 
				       nick);
		if (sptr->user)
		{
		    add_history(sptr, 1);
			
		    sendto_serv_butone(cptr, ":%s NICK %s :%ld",
				       parv[0], nick, sptr->tsinfo);
		}
	    }
	}
	else
	{
            /* REMOTE NICKCHANGE */
            /*
             * Client just changing his/her nick. If he/she is on a
             * channel, send note of change to all clients on that channel.
             * Propagate notice to other servers.
             */
            /* if the nickname is different, set the TS */
            if (mycmp(parv[0], nick))
            {
              sptr->tsinfo = newts ? newts : (ts_val) timeofday;
            }

	    sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick);
	    if (sptr->user)
	    {
		add_history(sptr, 1);
		
		sendto_serv_butone(cptr, ":%s NICK %s :%ld",
				   parv[0], nick, sptr->tsinfo);
	    }

	    /* If it changed nicks, -r it */
	    if (mycmp(parv[0], nick))
		sptr->umode &= ~UMODE_r;

	    /*
	     * Flush the banserial for the channels the user is in, since this
	     * could be a SVSNICK induced nick change, which overrides any ban
	     * checking on the originating server.
	     */
	    flush_user_banserial(sptr);
	}
        /* Remove dccallow entries for users who don't share common channel(s) unless they only change their nick capitalization -Kobi_S */
        if(sptr->user && mycmp(parv[0], nick))
        {
            for(lp = sptr->user->dccallow; lp; lp = lp2)
            {
                lp2 = lp->next;
                if(lp->flags == DCC_LINK_ME)
                    continue;
                if(!find_shared_chan(sptr, lp->value.cptr))
                {
                    sendto_one(lp->value.cptr, ":%s %d %s :%s has been removed from "
                               "your DCC allow list for signing off",
                               me.name, RPL_DCCINFO, lp->value.cptr->name, parv[0]);
                    del_dccallow(lp->value.cptr, sptr, 1);
                }
            }
        }
    } 
    else
    {
	/* Client setting NICK the first time */
	if (MyConnect(sptr))
	{
	    if ((ban = check_mask_simbanned(nick, SBAN_NICK)))
	    {
		if (MyConnect(sptr) && (!IsServer(cptr)) && (!IsOper(cptr))
		    && (!IsULine(sptr)))
		{
		    sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name,
			       BadPtr(parv[0]) ? "*" : parv[0], nick,
			       BadPtr(ban->reason) ? "Erroneous Nickname" :
			       ban->reason);
                    if (call_hooks(CHOOK_FORBID, cptr, nick, ban) != FLUSH_BUFFER)
		        sendto_realops_lev(REJ_LEV,
				           "Forbidding restricted nick %s from %s", nick,
				           get_client_name(cptr, FALSE));
		    return 0;
		}
	    }
	}
	
	strcpy(sptr->name, nick);
	sptr->tsinfo = timeofday;
	if (sptr->user)
	{
	    /* USER already received, now we have NICK */
       
	    if (register_user(cptr, sptr, nick, sptr->user->username, NULL)
		== FLUSH_BUFFER)
		return FLUSH_BUFFER;
	}
    }

    /* Finally set new nick name. */
    if (sptr->name[0])
    {
        del_from_client_hash_table(sptr->name, sptr);
        samenick = mycmp(sptr->name, nick) ? 0 : 1;
        if (IsPerson(sptr))
        {
            if (!samenick)
                hash_check_watch(sptr, RPL_LOGOFF);
#ifdef RWHO_PROBABILITY
            probability_change(sptr->name, nick);
#endif
        }
    }
    strcpy(sptr->name, nick);
    add_to_client_hash_table(nick, sptr);
    if (IsPerson(sptr) && !samenick)
	hash_check_watch(sptr, RPL_LOGON);
    return 0;
}
void MyDataImporter::run()
{
  try{
    string buffer;
    string ndays;
    ifstream inputFile(_conf_file.c_str());
    if (inputFile)
    {
      inputFile >> ndays;
  //     inputFile.getline();
      _num_days = atoi(ndays.c_str());
      cout << "number of days: " << _num_days << endl;
      int progress=1;
      getline(inputFile,buffer);
      getline(inputFile,buffer);
      while (!inputFile.eof())
      {
// 	cout << "buffer: \"" << buffer << "\"" << endl;

	if (buffer.find("CLIENTS")<string::npos)
	{
// 	  cout << "client section" << endl;
	  progress = 1;
	  getline(inputFile,buffer);
	  continue;
	}
	if (buffer.find("REQUESTS")<string::npos)
	{
// 	  cout << "request section" << endl;
	  progress = 2;
	  getline(inputFile,buffer);
	  continue;
	}
	if (buffer.find("NURSES")<string::npos)
  //       if (buffer[0]=='N')
	{
// 	  cout << "nurse section" << endl;
	  progress = 3;
	  getline(inputFile,buffer);
	  continue;
	}
	switch (progress)
	{
	  case 1:
	    //cout << "making client" << endl;
	    make_client(buffer);
	    break;
	  case 2:
	    make_request(buffer);
	    break;
	  case 3:
	    make_nurse(buffer);
	    break;
	}
	getline(inputFile,buffer);
      }
      make_nurse(buffer);
    } else {
      throw Error(0,"cannot open data file",0);
    }
    vector<double> dists;
    for (unsigned int i=0; i<_coords.size();i++)
    {
      for (unsigned int j=0; j<_coords.size(); j++)
      {
	dists.push_back(10*sqrt(pow((_coords[j].first-_coords[i].first),2.0)+pow((_coords[j].second-_coords[i].second),2.0)));
      }
    }
    _distance_matrix = new DistanceMatrix(_ids,dists);
  } catch (Error& e)
Exemple #22
0
/*
** m_nick
**	parv[0] = sender prefix
**	parv[1] = nickname
**  if from new client  -taz
**	parv[2] = nick password
**  if from server:
**      parv[2] = hopcount
**      parv[3] = timestamp
**      parv[4] = username
**      parv[5] = hostname
**      parv[6] = servername
**  if NICK version 1:
**      parv[7] = servicestamp
**	parv[8] = info
**  if NICK version 2:
**	parv[7] = servicestamp
**      parv[8] = umodes
**	parv[9] = virthost, * if none
**	parv[10] = info
**  if NICKIP:
**      parv[10] = ip
**      parv[11] = info
*/
DLLFUNC CMD_FUNC(m_nick)
{
	aTKline *tklban;
	int ishold;
	aClient *acptr, *serv = NULL;
	aClient *acptrs;
	char nick[NICKLEN + 2], *s;
	Membership *mp;
	time_t lastnick = (time_t) 0;
	int  differ = 1, update_watch = 1;
	unsigned char newusr = 0, removemoder = 1;
	/*
	 * If the user didn't specify a nickname, complain
	 */
	if (parc < 2)
	{
		sendto_one(sptr, err_str(ERR_NONICKNAMEGIVEN),
		    me.name, parv[0]);
		return 0;
	}

	strncpyzt(nick, parv[1], NICKLEN + 1);

	if (MyConnect(sptr) && sptr->user && !IsAnOper(sptr))
	{
		if ((sptr->user->flood.nick_c >= NICK_COUNT) && 
		    (TStime() - sptr->user->flood.nick_t < NICK_PERIOD))
		{
			/* Throttle... */
			sendto_one(sptr, err_str(ERR_NCHANGETOOFAST), me.name, sptr->name, nick,
				(int)(NICK_PERIOD - (TStime() - sptr->user->flood.nick_t)));
			return 0;
		}
	}

	/* For a local clients, do proper nickname checking via do_nick_name()
	 * and reject the nick if it returns false.
	 * For remote clients, do a quick check by using do_remote_nick_name(),
	 * if this returned false then reject and kill it. -- Syzop
	 */
	if ((IsServer(cptr) && !do_remote_nick_name(nick)) ||
	    (!IsServer(cptr) && !do_nick_name(nick)))
	{
		sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME),
		    me.name, parv[0], parv[1], "Illegal characters");

		if (IsServer(cptr))
		{
			ircstp->is_kill++;
			sendto_failops("Bad Nick: %s From: %s %s",
			    parv[1], parv[0], get_client_name(cptr, FALSE));
			sendto_one(cptr, ":%s KILL %s :%s (%s <- %s[%s])",
			    me.name, parv[1], me.name, parv[1],
			    nick, cptr->name);
			if (sptr != cptr)
			{	/* bad nick change */
				sendto_serv_butone(cptr,
				    ":%s KILL %s :%s (%s <- %s!%s@%s)",
				    me.name, parv[0], me.name,
				    get_client_name(cptr, FALSE),
				    parv[0],
				    sptr->user ? sptr->username : "",
				    sptr->user ? sptr->user->server :
				    cptr->name);
				sptr->flags |= FLAGS_KILLED;
				return exit_client(cptr, sptr, &me, "BadNick");
			}
		}
		return 0;
	}

	/* Kill quarantined opers early... */
	if (IsServer(cptr) && (sptr->from->flags & FLAGS_QUARANTINE) &&
	    (parc >= 11) && strchr(parv[8], 'o'))
	{
		ircstp->is_kill++;
		/* Send kill to uplink only, hasn't been broadcasted to the rest, anyway */
		sendto_one(cptr, ":%s KILL %s :%s (Quarantined: no global oper privileges allowed)",
			me.name, parv[1], me.name);
		sendto_realops("QUARANTINE: Oper %s on server %s killed, due to quarantine",
			parv[1], sptr->name);
		/* (nothing to exit_client or to free, since user was never added) */
		return 0;
	}

	/*
	   ** Protocol 4 doesn't send the server as prefix, so it is possible
	   ** the server doesn't exist (a lagged net.burst), in which case
	   ** we simply need to ignore the NICK. Also when we got that server
	   ** name (again) but from another direction. --Run
	 */
	/*
	   ** We should really only deal with this for msgs from servers.
	   ** -- Aeto
	 */
	if (IsServer(cptr) &&
	    (parc > 7
	    && (!(serv = (aClient *)find_server_b64_or_real(parv[6]))
	    || serv->from != cptr->from)))
	{
		sendto_realops("Cannot find server %s (%s)", parv[6],
		    backupbuf);
		return 0;
	}
	/*
	   ** Check against nick name collisions.
	   **
	   ** Put this 'if' here so that the nesting goes nicely on the screen :)
	   ** We check against server name list before determining if the nickname
	   ** is present in the nicklist (due to the way the below for loop is
	   ** constructed). -avalon
	 */
	/* I managed to f**k this up i guess --stskeeps */
	if ((acptr = find_server(nick, NULL)))
	{
		if (MyConnect(sptr))
		{
#ifdef GUEST
			if (IsUnknown(sptr))
			{
				RunHook4(HOOKTYPE_GUEST, cptr, sptr, parc, parv);
				return 0;
			}
#endif
			sendto_one(sptr, err_str(ERR_NICKNAMEINUSE), me.name,
			    BadPtr(parv[0]) ? "*" : parv[0], nick);
			return 0;	/* NICK message ignored */
		}
	}

	/*
	   ** Check for a Q-lined nickname. If we find it, and it's our
	   ** client, just reject it. -Lefler
	   ** Allow opers to use Q-lined nicknames. -Russell
	 */
	if (!stricmp("ircd", nick))
	{
		sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name,
		    BadPtr(parv[0]) ? "*" : parv[0], nick,
		    "Reserved for internal IRCd purposes");
		return 0;
	}
	if (!stricmp("irc", nick))
	{
		sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME), me.name,
		    BadPtr(parv[0]) ? "*" : parv[0], nick,
		    "Reserved for internal IRCd purposes");
		return 0;
	}
	if (MyClient(sptr)) /* local client changin nick afterwards.. */
	{
		int xx;
		spamfilter_build_user_string(spamfilter_user, nick, sptr);
		xx = dospamfilter(sptr, spamfilter_user, SPAMF_USER, NULL, 0, NULL);
		if (xx < 0)
			return xx;
	}
	if (!IsULine(sptr) && (tklban = find_qline(sptr, nick, &ishold)))
	{
		if (IsServer(sptr) && !ishold) /* server introducing new client */
		{
			acptrs =
			    (aClient *)find_server_b64_or_real(sptr->user ==
			    NULL ? (char *)parv[6] : (char *)sptr->user->
			    server);
			/* (NEW: no unregistered q:line msgs anymore during linking) */
			if (!acptrs || (acptrs->serv && acptrs->serv->flags.synced))
				sendto_snomask(SNO_QLINE, "Q:lined nick %s from %s on %s", nick,
				    (*sptr->name != 0
				    && !IsServer(sptr) ? sptr->name : "<unregistered>"),
				    acptrs ? acptrs->name : "unknown server");
		}
		
		if (IsServer(cptr) && IsPerson(sptr) && !ishold) /* remote user changing nick */
		{
			sendto_snomask(SNO_QLINE, "Q:lined nick %s from %s on %s", nick,
				sptr->name, sptr->srvptr ? sptr->srvptr->name : "<unknown>");
		}

		if (!IsServer(cptr)) /* local */
		{
			if (ishold)
			{
				sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME),
				    me.name, BadPtr(parv[0]) ? "*" : parv[0],
				    nick, tklban->reason);
				return 0;
			}
			if (!IsOper(cptr))
			{
				sptr->since += 4; /* lag them up */
				sendto_one(sptr, err_str(ERR_ERRONEUSNICKNAME),
				    me.name, BadPtr(parv[0]) ? "*" : parv[0],
				    nick, tklban->reason);
				sendto_snomask(SNO_QLINE, "Forbidding Q-lined nick %s from %s.",
				    nick, get_client_name(cptr, FALSE));
				return 0;	/* NICK message ignored */
			}
		}
	}
	/*
	   ** acptr already has result from previous find_server()
	 */
	if (acptr)
	{
		/*
		   ** We have a nickname trying to use the same name as
		   ** a server. Send out a nick collision KILL to remove
		   ** the nickname. As long as only a KILL is sent out,
		   ** there is no danger of the server being disconnected.
		   ** Ultimate way to jupiter a nick ? >;-). -avalon
		 */
		sendto_failops("Nick collision on %s(%s <- %s)",
		    sptr->name, acptr->from->name,
		    get_client_name(cptr, FALSE));
		ircstp->is_kill++;
		sendto_one(cptr, ":%s KILL %s :%s (%s <- %s)",
		    me.name, sptr->name, me.name, acptr->from->name,
		    /* NOTE: Cannot use get_client_name
		       ** twice here, it returns static
		       ** string pointer--the other info
		       ** would be lost
		     */
		    get_client_name(cptr, FALSE));
		sptr->flags |= FLAGS_KILLED;
		return exit_client(cptr, sptr, &me, "Nick/Server collision");
	}

	if (MyClient(cptr) && !IsOper(cptr))
		cptr->since += 3;	/* Nick-flood prot. -Donwulff */

	if (!(acptr = find_client(nick, NULL)))
		goto nickkilldone;	/* No collisions, all clear... */
	/*
	   ** If the older one is "non-person", the new entry is just
	   ** allowed to overwrite it. Just silently drop non-person,
	   ** and proceed with the nick. This should take care of the
	   ** "dormant nick" way of generating collisions...
	 */
	/* Moved before Lost User Field to fix some bugs... -- Barubary */
	if (IsUnknown(acptr) && MyConnect(acptr))
	{
		/* This may help - copying code below */
		if (acptr == cptr)
			return 0;
		acptr->flags |= FLAGS_KILLED;
		exit_client(NULL, acptr, &me, "Overridden");
		goto nickkilldone;
	}
	/* A sanity check in the user field... */
	if (acptr->user == NULL)
	{
		/* This is a Bad Thing */
		sendto_failops("Lost user field for %s in change from %s",
		    acptr->name, get_client_name(cptr, FALSE));
		ircstp->is_kill++;
		sendto_one(acptr, ":%s KILL %s :%s (Lost user field!)",
		    me.name, acptr->name, me.name);
		acptr->flags |= FLAGS_KILLED;
		/* Here's the previous versions' desynch.  If the old one is
		   messed up, trash the old one and accept the new one.
		   Remember - at this point there is a new nick coming in!
		   Handle appropriately. -- Barubary */
		exit_client(NULL, acptr, &me, "Lost user field");
		goto nickkilldone;
	}
	/*
	   ** If acptr == sptr, then we have a client doing a nick
	   ** change between *equivalent* nicknames as far as server
	   ** is concerned (user is changing the case of his/her
	   ** nickname or somesuch)
	 */
	if (acptr == sptr) {
		if (strcmp(acptr->name, nick) != 0)
		{
			/* Allows change of case in his/her nick */
			removemoder = 0; /* don't set the user -r */
			goto nickkilldone;	/* -- go and process change */
		} else
			/*
			 ** This is just ':old NICK old' type thing.
			 ** Just forget the whole thing here. There is
			 ** no point forwarding it to anywhere,
			 ** especially since servers prior to this
			 ** version would treat it as nick collision.
			 */
			return 0;	/* NICK Message ignored */
	}
	/*
	   ** Note: From this point forward it can be assumed that
	   ** acptr != sptr (point to different client structures).
	 */
	/*
	   ** Decide, we really have a nick collision and deal with it
	 */
	if (!IsServer(cptr))
	{
		/*
		   ** NICK is coming from local client connection. Just
		   ** send error reply and ignore the command.
		 */
#ifdef GUEST
		if (IsUnknown(sptr))
		{
			RunHook4(HOOKTYPE_GUEST, cptr, sptr, parc, parv);
			return 0;
		}
#endif
		sendto_one(sptr, err_str(ERR_NICKNAMEINUSE),
		    /* parv[0] is empty when connecting */
		    me.name, BadPtr(parv[0]) ? "*" : parv[0], nick);
		return 0;	/* NICK message ignored */
	}
	/*
	   ** NICK was coming from a server connection.
	   ** This means we have a race condition (two users signing on
	   ** at the same time), or two net fragments reconnecting with
	   ** the same nick.
	   ** The latter can happen because two different users connected
	   ** or because one and the same user switched server during a
	   ** net break.
	   ** If we have the old protocol (no TimeStamp and no user@host)
	   ** or if the TimeStamps are equal, we kill both (or only 'new'
	   ** if it was a "NICK new"). Otherwise we kill the youngest
	   ** when user@host differ, or the oldest when they are the same.
	   ** --Run
	   **
	 */
	if (IsServer(sptr))
	{
		/*
		   ** A new NICK being introduced by a neighbouring
		   ** server (e.g. message type "NICK new" received)
		 */
		if (parc > 3)
		{
			lastnick = TS2ts(parv[3]);
			if (parc > 5)
				differ = (mycmp(acptr->user->username, parv[4])
				    || mycmp(acptr->user->realhost, parv[5]));
		}
		sendto_failops("Nick collision on %s (%s %ld <- %s %ld)",
		    acptr->name, acptr->from->name, acptr->lastnick,
		    cptr->name, lastnick);
		/*
		   **    I'm putting the KILL handling here just to make it easier
		   ** to read, it's hard to follow it the way it used to be.
		   ** Basically, this is what it will do.  It will kill both
		   ** users if no timestamp is given, or they are equal.  It will
		   ** kill the user on our side if the other server is "correct"
		   ** (user@host differ and their user is older, or user@host are
		   ** the same and their user is younger), otherwise just kill the
		   ** user an reintroduce our correct user.
		   **    The old code just sat there and "hoped" the other server
		   ** would kill their user.  Not anymore.
		   **                                               -- binary
		 */
		if (!(parc > 3) || (acptr->lastnick == lastnick))
		{
			ircstp->is_kill++;
			sendto_serv_butone(NULL,
			    ":%s KILL %s :%s (Nick Collision)",
			    me.name, acptr->name, me.name);
			acptr->flags |= FLAGS_KILLED;
			(void)exit_client(NULL, acptr, &me,
			    "Nick collision with no timestamp/equal timestamps");
			return 0;	/* We killed both users, now stop the process. */
		}

		if ((differ && (acptr->lastnick > lastnick)) ||
		    (!differ && (acptr->lastnick < lastnick)) || acptr->from == cptr)	/* we missed a QUIT somewhere ? */
		{
			ircstp->is_kill++;
			sendto_serv_butone(cptr,
			    ":%s KILL %s :%s (Nick Collision)",
			    me.name, acptr->name, me.name);
			acptr->flags |= FLAGS_KILLED;
			(void)exit_client(NULL, acptr, &me, "Nick collision");
			goto nickkilldone;	/* OK, we got rid of the "wrong" user,
						   ** now we're going to add the user the
						   ** other server introduced.
						 */
		}

		if ((differ && (acptr->lastnick < lastnick)) ||
		    (!differ && (acptr->lastnick > lastnick)))
		{
			/*
			 * Introduce our "correct" user to the other server
			 */

			sendto_one(cptr, ":%s KILL %s :%s (Nick Collision)",
			    me.name, parv[1], me.name);
			send_umode(NULL, acptr, 0, SEND_UMODES, buf);
			sendto_one_nickcmd(cptr, acptr, buf);
			if (acptr->user->away)
				sendto_one(cptr, ":%s AWAY :%s", acptr->name,
				    acptr->user->away);
			send_user_joins(cptr, acptr);
			return 0;	/* Ignore the NICK */
		}
		return 0;
	}
	else
	{
		/*
		   ** A NICK change has collided (e.g. message type ":old NICK new").
		 */
		if (parc > 2)
			lastnick = TS2ts(parv[2]);
		differ = (mycmp(acptr->user->username, sptr->user->username) ||
		    mycmp(acptr->user->realhost, sptr->user->realhost));
		sendto_failops
		    ("Nick change collision from %s to %s (%s %ld <- %s %ld)",
		    sptr->name, acptr->name, acptr->from->name, acptr->lastnick,
		    sptr->from->name, lastnick);
		if (!(parc > 2) || lastnick == acptr->lastnick)
		{
			ircstp->is_kill += 2;
			sendto_serv_butone(NULL,	/* First kill the new nick. */
			    ":%s KILL %s :%s (Self Collision)",
			    me.name, acptr->name, me.name);
			sendto_serv_butone(cptr,	/* Tell my servers to kill the old */
			    ":%s KILL %s :%s (Self Collision)",
			    me.name, sptr->name, me.name);
			sptr->flags |= FLAGS_KILLED;
			acptr->flags |= FLAGS_KILLED;
			(void)exit_client(NULL, sptr, &me, "Self Collision");
			(void)exit_client(NULL, acptr, &me, "Self Collision");
			return 0;	/* Now that I killed them both, ignore the NICK */
		}
		if ((differ && (acptr->lastnick > lastnick)) ||
		    (!differ && (acptr->lastnick < lastnick)))
		{
			/* sptr (their user) won, let's kill acptr (our user) */
			ircstp->is_kill++;
			sendto_serv_butone(cptr,
			    ":%s KILL %s :%s (Nick collision: %s <- %s)",
			    me.name, acptr->name, me.name,
			    acptr->from->name, sptr->from->name);
			acptr->flags |= FLAGS_KILLED;
			(void)exit_client(NULL, acptr, &me, "Nick collision");
			goto nickkilldone;	/* their user won, introduce new nick */
		}
		if ((differ && (acptr->lastnick < lastnick)) ||
		    (!differ && (acptr->lastnick > lastnick)))
		{
			/* acptr (our user) won, let's kill sptr (their user),
			   ** and reintroduce our "correct" user
			 */
			ircstp->is_kill++;
			/* Kill the user trying to change their nick. */
			sendto_serv_butone(cptr,
			    ":%s KILL %s :%s (Nick collision: %s <- %s)",
			    me.name, sptr->name, me.name,
			    sptr->from->name, acptr->from->name);
			sptr->flags |= FLAGS_KILLED;
			(void)exit_client(NULL, sptr, &me, "Nick collision");
			/*
			 * Introduce our "correct" user to the other server
			 */
			/* Kill their user. */
			sendto_one(cptr, ":%s KILL %s :%s (Nick Collision)",
			    me.name, parv[1], me.name);
			send_umode(NULL, acptr, 0, SEND_UMODES, buf);
			sendto_one_nickcmd(cptr, acptr, buf);
			if (acptr->user->away)
				sendto_one(cptr, ":%s AWAY :%s", acptr->name,
				    acptr->user->away);

			send_user_joins(cptr, acptr);
			return 0;	/* their user lost, ignore the NICK */
		}

	}
	return 0;		/* just in case */
      nickkilldone:
	if (IsServer(sptr))
	{
		/* A server introducing a new client, change source */

		sptr = make_client(cptr, serv);
		add_client_to_list(sptr);
		if (parc > 2)
			sptr->hopcount = TS2ts(parv[2]);
		if (parc > 3)
			sptr->lastnick = TS2ts(parv[3]);
		else		/* Little bit better, as long as not all upgraded */
			sptr->lastnick = TStime();
		if (sptr->lastnick < 0)
		{
			sendto_realops
			    ("Negative timestamp recieved from %s, resetting to TStime (%s)",
			    cptr->name, backupbuf);
			sptr->lastnick = TStime();
		}
		newusr = 1;
	}
	else if (sptr->name[0] && IsPerson(sptr))
	{
		/*
		   ** If the client belongs to me, then check to see
		   ** if client is currently on any channels where it
		   ** is currently banned.  If so, do not allow the nick
		   ** change to occur.
		   ** Also set 'lastnick' to current time, if changed.
		 */
		if (MyClient(sptr))
		{
			for (mp = sptr->user->channel; mp; mp = mp->next)
			{
				if (!is_skochanop(sptr, mp->chptr) && is_banned(sptr, mp->chptr, BANCHK_NICK))
				{
					sendto_one(sptr,
					    err_str(ERR_BANNICKCHANGE),
					    me.name, parv[0],
					    mp->chptr->chname);
					return 0;
				}
				if (CHECK_TARGET_NICK_BANS && !is_skochanop(sptr, mp->chptr) && is_banned_with_nick(sptr, mp->chptr, BANCHK_NICK, nick))
				{
					sendto_one(sptr,
					    ":%s 437 %s %s :Cannot change to a nickname banned on channel",
					    me.name, parv[0],
					    mp->chptr->chname);
					return 0;
				}
				if (!IsOper(sptr) && !IsULine(sptr)
				    && mp->chptr->mode.mode & MODE_NONICKCHANGE
				    && !is_chanownprotop(sptr, mp->chptr))
				{
					sendto_one(sptr,
					    err_str(ERR_NONICKCHANGE),
					    me.name, parv[0],
					    mp->chptr->chname);
					return 0;
				}
			}

			if (TStime() - sptr->user->flood.nick_t >= NICK_PERIOD)
			{
				sptr->user->flood.nick_t = TStime();
				sptr->user->flood.nick_c = 1;
			} else
				sptr->user->flood.nick_c++;

			sendto_snomask(SNO_NICKCHANGE, "*** Notice -- %s (%s@%s) has changed his/her nickname to %s",
				sptr->name, sptr->user->username, sptr->user->realhost, nick);

			RunHook2(HOOKTYPE_LOCAL_NICKCHANGE, sptr, nick);
		} else {
			if (!IsULine(sptr))
				sendto_snomask(SNO_FNICKCHANGE, "*** Notice -- %s (%s@%s) has changed his/her nickname to %s",
					sptr->name, sptr->user->username, sptr->user->realhost, nick);

			RunHook3(HOOKTYPE_REMOTE_NICKCHANGE, cptr, sptr, nick);
		}
		/*
		 * Client just changing his/her nick. If he/she is
		 * on a channel, send note of change to all clients
		 * on that channel. Propagate notice to other servers.
		 */
		if (mycmp(parv[0], nick) ||
		    /* Next line can be removed when all upgraded  --Run */
		    (!MyClient(sptr) && parc > 2
		    && TS2ts(parv[2]) < sptr->lastnick))
			sptr->lastnick = (MyClient(sptr)
			    || parc < 3) ? TStime() : TS2ts(parv[2]);
		if (sptr->lastnick < 0)
		{
			sendto_realops("Negative timestamp (%s)", backupbuf);
			sptr->lastnick = TStime();
		}
		add_history(sptr, 1);
		sendto_common_channels(sptr, ":%s NICK :%s", parv[0], nick);
		sendto_serv_butone_token(cptr, parv[0], MSG_NICK, TOK_NICK,
		    "%s %ld", nick, sptr->lastnick);
		if (removemoder)
			sptr->umodes &= ~UMODE_REGNICK;
	}
	else if (!sptr->name[0])
	{
#ifdef NOSPOOF
		/*
		 * Client setting NICK the first time.
		 *
		 * Generate a random string for them to pong with.
		 */
		sptr->nospoof = getrandom32();

		if (PINGPONG_WARNING)
			sendto_one(sptr, ":%s NOTICE %s :*** If you are having problems"
			    " connecting due to ping timeouts, please"
			    " type /quote pong %X or /raw pong %X now.",
			    me.name, nick, sptr->nospoof, sptr->nospoof);

		sendto_one(sptr, "PING :%X", sptr->nospoof);
#endif /* NOSPOOF */
#ifdef CONTACT_EMAIL
		sendto_one(sptr,
		    ":%s NOTICE %s :*** If you need assistance with a"
		    " connection problem, please email " CONTACT_EMAIL
		    " with the name and version of the client you are"
		    " using, and the server you tried to connect to: %s",
		    me.name, nick, me.name);
#endif /* CONTACT_EMAIL */
#ifdef CONTACT_URL
		sendto_one(sptr,
		    ":%s NOTICE %s :*** If you need assistance with"
		    " connecting to this server, %s, please refer to: "
		    CONTACT_URL, me.name, nick, me.name);
#endif /* CONTACT_URL */

		/* Copy password to the passwd field if it's given after NICK
		 * - originally by taz, modified by Wizzu
		 */
		if ((parc > 2) && (strlen(parv[2]) <= PASSWDLEN)
		    && !(sptr->listener->umodes & LISTENER_JAVACLIENT))
		{
			if (sptr->passwd)
				MyFree(sptr->passwd);
			sptr->passwd = MyMalloc(strlen(parv[2]) + 1);
			(void)strcpy(sptr->passwd, parv[2]);
		}
		/* This had to be copied here to avoid problems.. */
		(void)strcpy(sptr->name, nick);
		if (sptr->user && IsNotSpoof(sptr))
		{
			/*
			   ** USER already received, now we have NICK.
			   ** *NOTE* For servers "NICK" *must* precede the
			   ** user message (giving USER before NICK is possible
			   ** only for local client connection!). register_user
			   ** may reject the client and call exit_client for it
			   ** --must test this and exit m_nick too!!!
			 */
#ifndef NOSPOOF
			if (USE_BAN_VERSION && MyConnect(sptr))
				sendto_one(sptr, ":IRC!IRC@%s PRIVMSG %s :\1VERSION\1",
					me.name, nick);
#endif
			sptr->lastnick = TStime();	/* Always local client */
			if (register_user(cptr, sptr, nick,
			    sptr->user->username, NULL, NULL, NULL) == FLUSH_BUFFER)
				return FLUSH_BUFFER;
			strcpy(nick, sptr->name); /* don't ask, but I need this. do not remove! -- Syzop */
			update_watch = 0;
			newusr = 1;
		}
	}
	/*
	 *  Finally set new nick name.
	 */
	if (update_watch && sptr->name[0])
	{
		(void)del_from_client_hash_table(sptr->name, sptr);
		if (IsPerson(sptr))
			hash_check_watch(sptr, RPL_LOGOFF);
	}
	(void)strcpy(sptr->name, nick);
	(void)add_to_client_hash_table(nick, sptr);
	if (IsServer(cptr) && parc > 7)
	{
		parv[3] = nick;
		do_cmd(cptr, sptr, "USER", parc - 3, &parv[3]);
		if (GotNetInfo(cptr) && !IsULine(sptr))
			sendto_fconnectnotice(sptr->name, sptr->user, sptr, 0, NULL);
	}
	else if (IsPerson(sptr) && update_watch)
		hash_check_watch(sptr, RPL_LOGON);

#ifdef NEWCHFLOODPROT
	if (sptr->user && !newusr && !IsULine(sptr))
	{
		for (mp = sptr->user->channel; mp; mp = mp->next)
		{
			aChannel *chptr = mp->chptr;
			if (chptr && !(mp->flags & (CHFL_CHANOP|CHFL_VOICE|CHFL_CHANOWNER|CHFL_HALFOP|CHFL_CHANPROT)) &&
			    chptr->mode.floodprot && do_chanflood(chptr->mode.floodprot, FLD_NICK) && MyClient(sptr))
			{
				do_chanflood_action(chptr, FLD_NICK, "nick");
			}
		}	
	}
#endif
	if (newusr && !MyClient(sptr) && IsPerson(sptr))
	{
		RunHook(HOOKTYPE_REMOTE_CONNECT, sptr);
	}

	return 0;
}
Exemple #23
0
void manage_window(xcb_window_t win, rule_consequence_t *csq, int fd)
{
	monitor_t *m = mon;
	desktop_t *d = mon->desk;
	node_t *f = mon->desk->focus;

	parse_rule_consequence(fd, csq);

	if (!csq->manage) {
		free(csq->layer);
		free(csq->state);
		window_show(win);
		return;
	}

	if (csq->node_desc[0] != '\0') {
		coordinates_t ref = {m, d, f};
		coordinates_t trg = {NULL, NULL, NULL};
		if (node_from_desc(csq->node_desc, &ref, &trg) == SELECTOR_OK) {
			m = trg.monitor;
			d = trg.desktop;
			f = trg.node;
		}
	} else if (csq->desktop_desc[0] != '\0') {
		coordinates_t ref = {m, d, NULL};
		coordinates_t trg = {NULL, NULL, NULL};
		if (desktop_from_desc(csq->desktop_desc, &ref, &trg) == SELECTOR_OK) {
			m = trg.monitor;
			d = trg.desktop;
			f = trg.desktop->focus;
		}
	} else if (csq->monitor_desc[0] != '\0') {
		coordinates_t ref = {m, NULL, NULL};
		coordinates_t trg = {NULL, NULL, NULL};
		if (monitor_from_desc(csq->monitor_desc, &ref, &trg) == SELECTOR_OK) {
			m = trg.monitor;
			d = trg.monitor->desk;
			f = trg.monitor->desk->focus;
		}
	}

	if (csq->sticky) {
		m = mon;
		d = mon->desk;
		f = mon->desk->focus;
	}

	if (csq->split_dir[0] != '\0' && f != NULL) {
		direction_t dir;
		if (parse_direction(csq->split_dir, &dir)) {
			presel_dir(m, d, f, dir);
		}
	}

	if (csq->split_ratio != 0 && f != NULL) {
		presel_ratio(m, d, f, csq->split_ratio);
	}

	node_t *n = make_node(win);
	client_t *c = make_client();
	c->border_width = csq->border ? d->border_width : 0;
	n->client = c;
	initialize_client(n);
	initialize_floating_rectangle(n);

	if (c->floating_rectangle.x == 0 && c->floating_rectangle.y == 0) {
		csq->center = true;
	}

	monitor_t *mm = monitor_from_client(c);
	embrace_client(mm, c);
	adapt_geometry(&mm->rectangle, &m->rectangle, n);

	if (csq->center) {
		window_center(m, c);
	}

	snprintf(c->class_name, sizeof(c->class_name), "%s", csq->class_name);
	snprintf(c->instance_name, sizeof(c->instance_name), "%s", csq->instance_name);

	f = insert_node(m, d, n, f);
	clients_count++;

	put_status(SBSC_MASK_NODE_MANAGE, "node_manage 0x%08X 0x%08X 0x%08X 0x%08X\n", m->id, d->id, win, f!=NULL?f->id:0);

	if (f != NULL && f->client != NULL && csq->state != NULL && *(csq->state) == STATE_FLOATING) {
		c->layer = f->client->layer;
	}

	if (csq->layer != NULL) {
		c->layer = *(csq->layer);
	}

	if (csq->state != NULL) {
		set_state(m, d, n, *(csq->state));
	}

	set_hidden(m, d, n, csq->hidden);
	set_sticky(m, d, n, csq->sticky);
	set_private(m, d, n, csq->private);
	set_locked(m, d, n, csq->locked);

	arrange(m, d);

	uint32_t values[] = {CLIENT_EVENT_MASK | (focus_follows_pointer ? XCB_EVENT_MASK_ENTER_WINDOW : 0)};
	xcb_change_window_attributes(dpy, win, XCB_CW_EVENT_MASK, values);

	if (d == m->desk) {
		show_node(d, n);
	} else {
		hide_node(d, n);
	}

	if (!csq->hidden && csq->focus) {
		if (d == mon->desk || csq->follow) {
			focus_node(m, d, n);
		} else {
			activate_node(m, d, n);
		}
	} else {
		stack(d, n, false);
	}

	ewmh_set_wm_desktop(n, d);
	ewmh_update_client_list(false);
	free(csq->layer);
	free(csq->state);
}
Exemple #24
0
void manage_window(xcb_window_t win, rule_consequence_t *csq, int fd)
{
	monitor_t *m = mon;
	desktop_t *d = mon->desk;
	node_t *f = mon->desk->focus;

	parse_rule_consequence(fd, csq);

	if (!csq->manage) {
		free(csq->layer);
		free(csq->state);
		window_show(win);
		return;
	}

	if (csq->node_desc[0] != '\0') {
		coordinates_t ref = {m, d, f};
		coordinates_t trg = {NULL, NULL, NULL};
		if (node_from_desc(csq->node_desc, &ref, &trg)) {
			m = trg.monitor;
			d = trg.desktop;
			f = trg.node;
		}
	} else if (csq->desktop_desc[0] != '\0') {
		coordinates_t ref = {m, d, NULL};
		coordinates_t trg = {NULL, NULL, NULL};
		if (desktop_from_desc(csq->desktop_desc, &ref, &trg)) {
			m = trg.monitor;
			d = trg.desktop;
			f = trg.desktop->focus;
		}
	} else if (csq->monitor_desc[0] != '\0') {
		coordinates_t ref = {m, NULL, NULL};
		coordinates_t trg = {NULL, NULL, NULL};
		if (monitor_from_desc(csq->monitor_desc, &ref, &trg)) {
			m = trg.monitor;
			d = trg.monitor->desk;
			f = trg.monitor->desk->focus;
		}
	}

	if (csq->sticky) {
		m = mon;
		d = mon->desk;
		f = mon->desk->focus;
	}

	if (csq->split_dir[0] != '\0' && f != NULL) {
		direction_t dir;
		if (parse_direction(csq->split_dir, &dir)) {
			presel_dir(m, d, f, dir);
		}
	}

	if (csq->split_ratio != 0 && f != NULL) {
		presel_ratio(m, d, f, csq->split_ratio);
	}

	node_t *n = make_node(win);
	client_t *c = make_client();
	c->border_width = csq->border ? d->border_width : 0;
	n->client = c;
	initialize_client(n);
	update_floating_rectangle(n);

	if (c->floating_rectangle.x == 0 && c->floating_rectangle.y == 0) {
		csq->center = true;
	}

	c->min_width = csq->min_width;
	c->max_width = csq->max_width;
	c->min_height = csq->min_height;
	c->max_height = csq->max_height;

	monitor_t *mm = monitor_from_client(c);
	embrace_client(mm, c);
	adapt_geometry(&mm->rectangle, &m->rectangle, n);

	if (csq->center) {
		window_center(m, c);
	}

	snprintf(c->class_name, sizeof(c->class_name), "%s", csq->class_name);
	snprintf(c->instance_name, sizeof(c->instance_name), "%s", csq->instance_name);

	f = insert_node(m, d, n, f);
	clients_count++;

	put_status(SBSC_MASK_NODE_MANAGE, "node_manage %s %s 0x%X 0x%X\n", m->name, d->name, win, f!=NULL?f->id:0);

	if (f != NULL && f->client != NULL && csq->state != NULL && *(csq->state) == STATE_FLOATING) {
		c->last_layer = c->layer = f->client->layer;
	}

	if (csq->layer != NULL) {
		c->last_layer = c->layer = *(csq->layer);
	}

	if (csq->state != NULL) {
		set_state(m, d, n, *(csq->state));
		c->last_state = c->state;
	}

	set_locked(m, d, n, csq->locked);
	set_sticky(m, d, n, csq->sticky);
	set_private(m, d, n, csq->private);

	arrange(m, d);

	bool give_focus = (csq->focus && (d == mon->desk || csq->follow));

	if (give_focus) {
		focus_node(m, d, n);
	} else if (csq->focus) {
		activate_node(m, d, n);
	} else {
		stack(d, n, false);
	}

	uint32_t values[] = {CLIENT_EVENT_MASK | (focus_follows_pointer ? XCB_EVENT_MASK_ENTER_WINDOW : 0)};
	xcb_change_window_attributes(dpy, win, XCB_CW_EVENT_MASK, values);

	if (d == m->desk) {
		window_show(n->id);
	} else {
		window_hide(n->id);
	}

	/* the same function is already called in `focus_node` but has no effects on unmapped windows */
	if (give_focus) {
		xcb_set_input_focus(dpy, XCB_INPUT_FOCUS_POINTER_ROOT, win, XCB_CURRENT_TIME);
	}

	ewmh_set_wm_desktop(n, d);
	ewmh_update_client_list(false);
	free(csq->layer);
	free(csq->state);
}
Exemple #25
0
/*
 * add_connection - creates a client which has just connected to us on 
 * the given fd. The sockhost field is initialized with the ip# of the host.
 * An unique id is calculated now, in case it is needed for auth.
 * The client is sent to the auth module for verification, and not put in
 * any client list yet.
 */
void
add_connection(struct Listener *listener, struct irc_ssaddr *irn, int fd)
{
  struct Client *new_client;

  assert(NULL != listener);

  new_client = make_client(NULL);

  fd_open(&new_client->localClient->fd, fd, 1,
          (listener->flags & LISTENER_SSL) ?
	  "Incoming SSL connection" : "Incoming connection");

  /* 
   * copy address to 'sockhost' as a string, copy it to host too
   * so we have something valid to put into error messages...
   */
  memcpy(&new_client->ip, irn, sizeof(struct irc_ssaddr));

  irc_getnameinfo((struct sockaddr*)&new_client->ip,
        new_client->ip.ss_len,  new_client->sockhost, 
        HOSTIPLEN, NULL, 0, NI_NUMERICHOST);
  new_client->aftype = new_client->ip.ss.ss_family;
#ifdef IPV6
  if (new_client->sockhost[0] == ':')
    strlcat(new_client->host, "0", HOSTLEN+1);

  if (new_client->aftype == AF_INET6 && 
      ConfigFileEntry.dot_in_ip6_addr == 1)
  {
    strlcat(new_client->host, new_client->sockhost,HOSTLEN+1);
    strlcat(new_client->host, ".", HOSTLEN+1);
  }
  else
#endif
    strlcat(new_client->host, new_client->sockhost,HOSTLEN+1);

  new_client->connect_id = ++connect_id;
  new_client->localClient->listener = listener;
  ++listener->ref_count;

#ifdef HAVE_LIBCRYPTO
  if (listener->flags & LISTENER_SSL)
  {
    if ((new_client->localClient->fd.ssl = SSL_new(ServerInfo.ctx)) == NULL)
    {
      ilog(L_CRIT, "SSL_new() ERROR! -- %s",
           ERR_error_string(ERR_get_error(), NULL));

      SetDead(new_client);
      exit_client(new_client, new_client, "SSL_new failed");
      return;
    }

    SSL_set_fd(new_client->localClient->fd.ssl, fd);
    ssl_handshake(0, new_client);
  }
  else
#endif
    execute_callback(auth_cb, new_client);
}
Exemple #26
0
int main(int argc, char *argv[])
{
	int status, maxfd, i, fd, added;
	struct Client *c;

	memset(clients, 0, sizeof(struct Client *)*MAX_CLIENTS);

	if (argc != 2) {
		fprintf(stderr, "Usage: %s <port>\n", argv[0]);
		exit(EXIT_FAILURE);
	}

	setup_and_listen(argv[1]);

	while(1) {
		FD_ZERO(&rfds);
		FD_ZERO(&wfds);
		FD_SET(server->fd, &rfds);
		maxfd = server->fd;

		for (i = 0; i < MAX_CLIENTS; i++) {
			c = clients[i];

			if (c) {
				if (c->to_reply == 1) {
					FD_SET(c->fd, &wfds);
					c->to_reply = 0;
				} else {
					FD_SET(c->fd, &rfds);
				}

				if (fd > maxfd) {
					maxfd = c->fd;
				}
			}
		}

		/* TODO: also add exception set */
		status = select(maxfd+1, &rfds, &wfds, NULL, NULL);
		if (status < 0) {
			err(EXIT_FAILURE, "Socket select error");
		}

		if (FD_ISSET(server->fd, &rfds)) {
			fd = accept4(server->fd, server->addr->ai_addr, &(server->addr->ai_addrlen), SOCK_NONBLOCK);
			if (fd < 0) {
				if (errno == EAGAIN || errno == EWOULDBLOCK) {
					continue;
				}
				err(EXIT_FAILURE, "Socket accept error");
			}

			added = 0;
			for (i = 0; i < MAX_CLIENTS; i++) {
				if (clients[i] == 0) {
					clients[i] = make_client(fd);
					added = 1;
					if (fd > maxfd) {
						maxfd = fd;
					}
					break;
				}
			}

			if (!added) {
				fprintf(stderr, "Could not find room for client fd: %d\n", fd);
				continue;
			}

			printf("Accepted connection! (fd: %d)\n", fd);

			continue;
		}

		for (i = 0; i < MAX_CLIENTS; i++) {
			c = clients[i];

			if (c == 0) {
				continue;
			}

			if (FD_ISSET(c->fd, &wfds)) {
				respond(c);
			} else if (FD_ISSET(c->fd, &rfds) && c->cstate == CONNECTED) {
				read_response(c);
			}
		}
	}
}
Exemple #27
0
void add_connection(struct Listener* listener, int fd, void *ssl) {
#else
void add_connection(struct Listener* listener, int fd) {
#endif
  struct irc_sockaddr addr;
  struct Client      *new_client;
  time_t             next_target = 0;
#if defined(USE_SSL)
  char *sslfp;
#endif

  const char* const throttle_message =
         "ERROR :Your host is trying to (re)connect too fast -- throttled\r\n";
       /* 12345678901234567890123456789012345679012345678901234567890123456 */
  const char* const register_message =
         "ERROR :Unable to complete your registration\r\n";

  assert(0 != listener);

  /*
   * Removed preliminary access check. Full check is performed in m_server and
   * m_user instead. Also connection time out help to get rid of unwanted
   * connections.
   */
  if (!os_get_peername(fd, &addr) || !os_set_nonblocking(fd)) {
    ++ServerStats->is_ref;
#if defined(USE_SSL)
    ssl_murder(ssl, fd, NULL);
#else
    close(fd);
#endif
    return;
  }
  /*
   * Disable IP (*not* TCP) options.  In particular, this makes it impossible
   * to use source routing to connect to the server.  If we didn't do this
   * (and if intermediate networks didn't drop source-routed packets), an
   * attacker could successfully IP spoof us...and even return the anti-spoof
   * ping, because the options would cause the packet to be routed back to
   * the spoofer's machine.  When we disable the IP options, we delete the
   * source route, and the normal routing takes over.
   */
  os_disable_options(fd);

  if (listener_server(listener))
  {
    new_client = make_client(0, STAT_UNKNOWN_SERVER);
  }
  else
  {
    /*
     * Add this local client to the IPcheck registry.
     *
     * If they're throttled, murder them, but tell them why first.
     */
    if (!IPcheck_local_connect(&addr.addr, &next_target))
    {
      ++ServerStats->is_ref;
#if defined(USE_SSL)
      ssl_murder(ssl, fd, throttle_message);
#else
      write(fd, throttle_message, strlen(throttle_message));
      close(fd);
#endif
      return;
    }
    new_client = make_client(0, STAT_UNKNOWN_USER);
    SetIPChecked(new_client);
  }

  /*
   * Copy ascii address to 'sockhost' just in case. Then we have something
   * valid to put into error messages...
   */
  ircd_ntoa_r(cli_sock_ip(new_client), &addr.addr);
  strcpy(cli_sockhost(new_client), cli_sock_ip(new_client));
  memcpy(&cli_ip(new_client), &addr.addr, sizeof(cli_ip(new_client)));

  if (next_target)
    cli_nexttarget(new_client) = next_target;

  cli_fd(new_client) = fd;
  if (!socket_add(&(cli_socket(new_client)), client_sock_callback,
		  (void*) cli_connect(new_client), SS_CONNECTED, 0, fd)) {
    ++ServerStats->is_ref;
#if defined(USE_SSL)
    ssl_murder(ssl, fd, register_message);
#else
    write(fd, register_message, strlen(register_message));
    close(fd);
#endif
    cli_fd(new_client) = -1;
    return;
  }
#if defined(USE_SSL)
  if (ssl) {
    cli_socket(new_client).s_ssl = ssl;
    sslfp = ssl_get_fingerprint(ssl);
    if (sslfp)
      ircd_strncpy(cli_sslclifp(new_client), sslfp, BUFSIZE+1);
  }
#endif
  cli_freeflag(new_client) |= FREEFLAG_SOCKET;
  cli_listener(new_client) = listener;
  ++listener->ref_count;

  Count_newunknown(UserStats);
  /* if we've made it this far we can put the client on the auth query pile */
  start_auth(new_client);
}

/** Determines whether to tell the events engine we're interested in
 * writable events.
 * @param cptr Client for which to decide this.
 */
void update_write(struct Client* cptr)
{
  /* If there are messages that need to be sent along, or if the client
   * is in the middle of a /list, then we need to tell the engine that
   * we're interested in writable events--otherwise, we need to drop
   * that interest.
   */
  socket_events(&(cli_socket(cptr)),
		((MsgQLength(&cli_sendQ(cptr)) || cli_listing(cptr)) ?
		 SOCK_ACTION_ADD : SOCK_ACTION_DEL) | SOCK_EVENT_WRITABLE);
}
Exemple #28
0
void io_loop()
{
char to_send[200];
time_t lasttime = 0;
long lastrecvK = 0;
int  lrv = 0;
time_t      lasttimeofday;
int delay = 0;

 while(1)
 {
   lasttimeofday = timeofday;

   if ((timeofday = time(NULL)) == -1) 
   {
#ifdef USE_SYSLOG
      syslog(LOG_WARNING, "Clock Failure (%d), TS can be corrupted", errno);
#endif
      sendto_ops("Clock Failure (%d), TS can be corrupted", errno);
   }

   if (timeofday < lasttimeofday) 
   {
      ircsprintf(to_send, "System clock is running backwards - (%d < %d)",
		 timeofday, lasttimeofday);
      report_error(to_send, &me);
   }

   NOW = timeofday;

   /*
    * This chunk of code determines whether or not "life sucks", that
    * is to say if the traffic level is so high that standard server
    * commands should be restricted
    * 
    * Changed by Taner so that it tells you what's going on as well as
    * allows forced on (long LCF), etc...
    */

   if ((timeofday - lasttime) >= LCF) 
   {
      lrv = LRV * LCF;
      lasttime = timeofday;
      currlife = (me.receiveK - lastrecvK) / LCF;
      if ((me.receiveK - lrv) > lastrecvK || HTMLOCK == YES) 
      {
	 if (!lifesux) 
 	 {
	    /*
	     * In the original +th code Taner had
	     * 
	     * LCF << 1;  / * add hysteresis * /
	     * 
	     * which does nothing... so, the hybrid team changed it to
	     * 
	     * LCF <<= 1;  / * add hysteresis * /
	     * 
	     * suddenly, there were reports of clients mysteriously just
	     * dropping off... Neither rodder or I can see why it makes
	     * a difference, but lets try it this way...
	     * 
	     * The original dog3 code, does not have an LCF variable
	     * 
	     * -Dianora
	     * 
	     */
	    lifesux = 1;

	    if (noisy_htm) 
	       sendto_ops("Entering high-traffic mode - (%dk/s > %dk/s)", currlife, LRV);
	 }
	 else 
	 {
	    lifesux++;		/* Ok, life really sucks! */
	    LCF += 2;		/* Wait even longer */
	    if (noisy_htm) 
	       sendto_ops("Still high-traffic mode %d%s (%d delay): %dk/s",
			  lifesux, (lifesux > 9) ? " (TURBO)" : "", (int) LCF, currlife);

	   /* Reset htm here, because its been on a little too long.
	    * Bad Things(tm) tend to happen with HTM on too long -epi */

	    if (lifesux>15) 
	    {
	       if (noisy_htm) 
		  sendto_ops("Resetting HTM and raising limit to: %dk/s\n", LRV + 5);
	       LCF=LOADCFREQ;
	       lifesux=0;
	       LRV+=5;
	    }
	 }
      }
      else 
      {
	 LCF = LOADCFREQ;
	 if (lifesux) 
	 {
	    lifesux = 0;
	    if (noisy_htm)
	       sendto_ops("Resuming standard operation . . . .");
	 }
      }
      lastrecvK = me.receiveK;
   }
   /*
    * * We only want to connect if a connection is due, not every
    * time through.  Note, if there are no active C lines, this call
    * to Tryconnections is made once only; it will return 0. - avalon
    */

   if (nextconnect && timeofday >= nextconnect)
      nextconnect = try_connections(timeofday);

   /* DNS checks. One to timeout queries, one for cache expiries.*/

   if (timeofday >= nextdnscheck)
      nextdnscheck = timeout_query_list(timeofday);
   if (timeofday >= nextexpire)
      nextexpire = expire_cache(timeofday);

   /*
    * * take the smaller of the two 'timed' event times as the time
    * of next event (stops us being late :) - avalon WARNING -
    * nextconnect can return 0!
    */

   if (nextconnect)
      delay = MIN(nextping, nextconnect);
   else
      delay = nextping;
   delay = MIN(nextdnscheck, delay);
   delay = MIN(nextexpire, delay);
   delay -= timeofday;

   /*
    * * Adjust delay to something reasonable [ad hoc values] (one
    * might think something more clever here... --msa) 
    * We don't really need to check that often and as long 
    * as we don't delay too long, everything should be ok. 
    * waiting too long can cause things to timeout... 
    * i.e. PINGS -> a disconnection :( 
    * - avalon
    */
   if (delay < 1)
      delay = 1;
   else
      delay = MIN(delay, TIMESEC);
   /*
    * We want to read servers on every io_loop, as well as "busy"
    * clients (which again, includes servers. If "lifesux", then we
    * read servers AGAIN, and then flush any data to servers. -Taner
    */

#ifndef NO_PRIORITY
   read_message(0, &serv_fdlist);
   read_message(1, &busycli_fdlist);
   if (lifesux) 
   {
      (void) read_message(1, &serv_fdlist);
      if (lifesux > 9) 		/* life really sucks */
      {
	 (void) read_message(1, &busycli_fdlist);
	 (void) read_message(1, &serv_fdlist);
      }
      flush_fdlist_connections(&serv_fdlist);
   }

   if ((timeofday = time(NULL)) == -1) 
   {
	#ifdef USE_SYSLOG
           syslog(LOG_WARNING, "Clock Failure (%d), TS can be corrupted", errno);
	#endif
      sendto_ops("Clock Failure (%d), TS can be corrupted", errno);
   }
   /*
    * CLIENT_SERVER = TRUE: If we're in normal mode, or if "lifesux"
    * and a few seconds have passed, then read everything.
    * CLIENT_SERVER = FALSE: If it's been more than lifesux*2 seconds
    * (that is, at most 1 second, or at least 2s when lifesux is != 0)
    * check everything. -Taner
    */
   { 
      static time_t lasttime = 0;

# ifdef CLIENT_SERVER
      if (!lifesux || (lasttime + lifesux) < timeofday) {
# else
      if ((lasttime + (lifesux + 1)) < timeofday) {
# endif
	 (void) read_message(delay ? delay : 1, NULL);	/* check everything! */
	 lasttime = timeofday;
      }
   }
#else
   (void) read_message(delay, NULL);	/* check everything! */
#endif
   /*
    * * ...perhaps should not do these loops every time, but only if
    * there is some chance of something happening (but, note that
    * conf->hold times may be changed elsewhere--so precomputed next
    * event time might be too far away... (similarly with ping
    * times) --msa
    */

   if ((timeofday >= nextping))
      nextping = check_pings(timeofday);

   if (dorehash && !lifesux) 
   {
      (void) rehash(&me, &me, 1);
      dorehash = 0;
   }
   /*
    * 
    * Flush output buffers on all connections now if they 
    * have data in them (or at least try to flush)  -avalon
    *
    * flush_connections(me.fd);
    *
    * avalon, what kind of crack have you been smoking? why
    * on earth would we flush_connections blindly when
    * we already check to see if we can write (and do)
    * in read_message? There is no point, as this causes
    * lots and lots of unnecessary sendto's which 
    * 99% of the time will fail because if we couldn't
    * empty them in read_message we can't empty them here.
    * one effect: during htm, output to normal lusers
    * will lag.
    */

    /* Now we've made this call a bit smarter. */
    /* Only flush non-blocked sockets. */

    flush_connections(me.fd);

#ifndef NO_PRIORITY
   check_fdlists();
#endif

#ifdef	LOCKFILE
   /*
    * * If we have pending klines and CHECK_PENDING_KLINES minutes
    * have passed, try writing them out.  -ThemBones
    */

   if ((pending_klines) && ((timeofday - pending_kline_time)
			    >= (CHECK_PENDING_KLINES * 60)))
      do_pending_klines();
#endif
 }
}
/*
 * open_debugfile
 * 
 * If the -t option is not given on the command line when the server is
 * started, all debugging output is sent to the file set by LPATH in
 * config.h Here we just open that file and make sure it is opened to
 * fd 2 so that any fprintf's to stderr also goto the logfile.  If the
 * debuglevel is not set from the command line by -x, use /dev/null as
 * the dummy logfile as long as DEBUGMODE has been defined, else dont
 * waste the fd.
 */
static void
open_debugfile()
{
#ifdef	DEBUGMODE
int         fd;
aClient    *cptr;

   if (debuglevel >= 0) 
   {
      cptr = make_client(NULL, NULL);
      cptr->fd = 2;
      SetLog(cptr);
      cptr->port = debuglevel;
      cptr->flags = 0;
      cptr->acpt = cptr;
      local[2] = cptr;
      (void) strcpy(cptr->sockhost, me.sockhost);

      (void) printf("isatty = %d ttyname = %#x\n",
		    isatty(2), (u_int) ttyname(2));
      if (!(bootopt & BOOT_TTY)) 	/*) leave debugging output on fd */ 
      {
	 (void) truncate(LOGFILE, 0);
	 if ((fd = open(LOGFILE, O_WRONLY | O_CREAT, 0600)) < 0)
	    if ((fd = open("/dev/null", O_WRONLY)) < 0)
	       exit(-1);
	 if (fd != 2) 
    	 {
	    (void) dup2(fd, 2);
	    (void) close(fd);
	 }
	 strncpyzt(cptr->name, LOGFILE, sizeof(cptr->name));
      }
      else if (isatty(2) && ttyname(2))
	 strncpyzt(cptr->name, ttyname(2), sizeof(cptr->name));
      else
	 (void) strcpy(cptr->name, "FD2-Pipe");
      Debug((DEBUG_FATAL, "Debug: File <%s> Level: %d at %s",
	     cptr->name, cptr->port, myctime(time(NULL))));
   }
   else
      local[2] = NULL;
#endif
   return;
}
Exemple #29
0
/*
** mo_jupe
**      parv[0] = sender prefix
**      parv[1] = server we're juping
**      parv[2] = reason for jupe
*/
static void mo_jupe(struct Client *client_p, struct Client *source_p,
                    int parc, char *parv[])
{
  struct Client *target_p;
  struct Client *ajupe;
  dlink_node *m;
  char reason[REALLEN+2];

  if(!ServerInfo.hub)
    return;

  if(!IsOperAdmin(source_p))
    {
      sendto_one(source_p, ":%s NOTICE %s :You must be an admin to use this command",
                 me.name, parv[0]);
      return;
    }

  if (bogus_host(parv[1]))
    {
      sendto_one(source_p, ":%s NOTICE %s :Invalid servername: %s",
                 me.name, parv[0], parv[1]);
      return;
    }

  if(match(parv[1], me.name))
  {
    sendto_one(source_p, ":%s NOTICE %s :I cant jupe myself!",
	       me.name, source_p->name);
    return;
  }

  sendto_wallops_flags(UMODE_WALLOP, &me,
                       "JUPE for %s requested by %s: %s",
			 parv[1], get_oper_name(source_p), parv[2]);

  sendto_server(NULL, NOCAPS, NOCAPS, 
                ":%s WALLOPS :JUPE for %s requested by %s!%s@%s: %s",
                parv[0], parv[1], source_p->name, 
                source_p->username, source_p->host, parv[2]);
  ilog(L_NOTICE, "JUPE for %s requested by %s: %s",
                parv[1], get_oper_name(source_p), parv[2]);

  target_p= find_server(parv[1]);

  if(target_p)
    exit_client(client_p, target_p, &me, parv[2]);

  sendto_server(NULL, NOCAPS, NOCAPS,
                ":%s SERVER %s 1 :JUPED: %s",
                me.name, parv[1], parv[2]);

  sendto_realops_flags(UMODE_ALL, L_ALL,
                       "Link with %s established: (JUPED) link",
		       parv[1]);

  ajupe = make_client(NULL);

  /* make_client() adds client to unknown_list */
  m = dlinkFind(&unknown_list, ajupe);
  if(m != NULL)
    dlinkDelete(m, &unknown_list);
  free_dlink_node(m);

  make_server(ajupe);
  ajupe->hopcount = 1;
  strlcpy(ajupe->name,parv[1],HOSTLEN);

  /* we need to give 7 chars to prepend "JUPED: " */
  if(strlen(parv[2]) > (REALLEN-7))
    parv[2][REALLEN-7] = '\0';
  ircsprintf(reason, "%s %s", "JUPED:", parv[2]);
  
  strlcpy(ajupe->info,reason,REALLEN);
  ajupe->serv->up = me.name;
  ajupe->servptr = &me;
  SetServer(ajupe);
  SetDead(ajupe);
  
  Count.server++;
  Count.myserver++;

  /* Some day, all these lists will be consolidated *sigh* */
  add_client_to_list(ajupe);
  add_to_client_hash_table(ajupe->name, ajupe);
  dlinkAdd(ajupe, &ajupe->lnode, &ajupe->servptr->serv->servers);
  add_server_to_list(ajupe);
}
Exemple #30
0
void restore(char *file_path)
{
    if (file_path == NULL)
        return;

    FILE *snapshot = fopen(file_path, "r");
    if (snapshot == NULL) {
        warn("restore: can't open file\n");
        return;
    }

    char line[MAXLEN];
    monitor_t *m = NULL;
    desktop_t *d = NULL;
    node_t *n = NULL;
    num_clients = 0;
    unsigned int level, last_level = 0, max_uid = 0;
    bool aborted = false;

    while (!aborted && fgets(line, sizeof(line), snapshot) != NULL) {
        unsigned int len = strlen(line);
        level = 0;
        while (level < strlen(line) && isspace(line[level]))
            level++;
        if (level == 0) {
            if (m == NULL)
                m = mon_head;
            else
                m = m->next;
            if (len >= 2)
                switch (line[len - 2]) {
                    case '#':
                        mon = m;
                        break;
                    case '~':
                        last_mon = m;
                        break;
                }
        } else if (level == 2) {
            if (d == NULL)
                d = m->desk_head;
            else
                d = d->next;
            int i = len - 1;
            while (i > 0 && !isupper(line[i]))
                i--;
            if (line[i] == 'M')
                d->layout = LAYOUT_MONOCLE;
            else if (line[i] == 'T')
                d->layout = LAYOUT_TILED;
            if (len >= 2)
                switch (line[len - 2]) {
                    case '@':
                        m->desk = d;
                        break;
                    case '~':
                        m->last_desk = d;
                        break;
                }
        } else {
            node_t *birth = make_node();
            if (level == 4) {
                empty_desktop(d);
                d->root = birth;
            } else {
                if (level > last_level) {
                    n->first_child = birth;
                } else {
                    do {
                        n = n->parent;
                    } while (n != NULL && n->second_child != NULL);
                    if (n == NULL) {
                        warn("restore: file is malformed\n");
                        aborted = true;
                    }
                    n->second_child = birth;
                }
                birth->parent = n;
            }
            n = birth;

            if (isupper(line[level])) {
                char st;
                sscanf(line + level, "%c %lf", &st, &n->split_ratio);
                if (st == 'H')
                    n->split_type = TYPE_HORIZONTAL;
                else if (st == 'V')
                    n->split_type = TYPE_VERTICAL;
            } else {
                client_t *c = make_client(XCB_NONE);
                num_clients++;
                char ba, floating, transient, fullscreen, urgent, locked;
                sscanf(line + level, "%c %s %X %u %u %hux%hu%hi%hi %c%c%c%c%c", &ba, c->class_name, &c->window, &c->uid, &c->border_width, &c->floating_rectangle.width, &c->floating_rectangle.height, &c->floating_rectangle.x, &c->floating_rectangle.y, &floating, &transient, &fullscreen, &urgent, &locked);
                if (ba == 'a')
                    c->born_as = MODE_AUTOMATIC;
                else if (ba == 'm')
                    c->born_as = MODE_MANUAL;
                c->floating = (floating == '-' ? false : true);
                c->transient = (transient == '-' ? false : true);
                c->fullscreen = (fullscreen == '-' ? false : true);
                c->urgent = (urgent == '-' ? false : true);
                c->locked = (locked == '-' ? false : true);
                if (c->uid > max_uid)
                    max_uid = c->uid;
                n->client = c;
                if (len >= 2)
                    switch (line[len - 2]) {
                        case '*':
                            d->focus = n;
                            break;
                        case '~':
                            d->last_focus = n;
                            break;
                    }
            }
        }
        last_level = level;
    }

    if (!aborted) {
        client_uid = max_uid + 1;
        for (monitor_t *m = mon_head; m != NULL; m = m->next)
            for (desktop_t *d = m->desk_head; d != NULL; d = d->next)
                for (node_t *n = first_extrema(d->root); n != NULL; n = next_leaf(n)) {
                    uint32_t values[] = {(focus_follows_pointer ? CLIENT_EVENT_MASK_FFP : CLIENT_EVENT_MASK)};
                    xcb_change_window_attributes(dpy, n->client->window, XCB_CW_EVENT_MASK, values);
                    if (n->client->floating) {
                        n->vacant = true;
                        update_vacant_state(n->parent);
                    }
                }
    }

    fclose(snapshot);
}