Exemplo n.º 1
0
/**
 * Kill an client identified by its nick name.
 *
 * Please note that after killig a client, its CLIENT cond CONNECTION
 * structures are invalid. So the caller must make sure on its own not to
 * access data of probably killed clients after calling this function!
 *
 * @param Client The client from which the command leading to the KILL has
 *		been received, or NULL. The KILL will no be forwarded in this
 *		direction. Only relevant when From is set, too.
 * @param From The client from which the command originated, or NULL for
		the local server.
 * @param Nick The nick name to kill.
 * @param Reason Text to send as reason to the client and other servers.
 */
GLOBAL bool
IRC_KillClient(CLIENT *Client, CLIENT *From, const char *Nick, const char *Reason)
{
	const char *msg;
	CONN_ID my_conn, conn;
	CLIENT *c;

	/* Do we know such a client in the network? */
	c = Client_Search(Nick);
	if (!c) {
		LogDebug("Client with nick \"%s\" is unknown, not forwaring.", Nick);
		return CONNECTED;
	}

	/* Inform other servers */
	IRC_WriteStrServersPrefix(From ? Client : NULL,
				  From ? From : Client_ThisServer(),
				  "KILL %s :%s", Nick, Reason);

	if (Client_Type(c) != CLIENT_USER && Client_Type(c) != CLIENT_GOTNICK) {
		/* Target of this KILL is not a regular user, this is
		 * invalid! So we ignore this case if we received a
		 * regular KILL from the network and try to kill the
		 * client/connection anyway (but log an error!) if the
		 * origin is the local server. */

		if (Client != Client_ThisServer()) {
			/* Invalid KILL received from remote */
			if (Client_Type(c) == CLIENT_SERVER)
				msg = ERR_CANTKILLSERVER_MSG;
			else
				msg = ERR_NOPRIVILEGES_MSG;
			return IRC_WriteErrClient(Client, msg, Client_ID(Client));
		}

		Log(LOG_ERR,
		    "Got KILL for invalid client type: %d, \"%s\"!",
		    Client_Type(c), Nick);
	}

	/* Save ID of this connection */
	my_conn = Client_Conn(Client);

	/* Kill the client NOW:
	 *  - Close the local connection (if there is one),
	 *  - Destroy the CLIENT structure for remote clients.
	 * Note: Conn_Close() removes the CLIENT structure as well. */
	conn = Client_Conn(c);
	if(conn > NONE)
		Conn_Close(conn, NULL, Reason, true);
	else
		Client_Destroy(c, NULL, Reason, false);

	/* Are we still connected or were we killed, too? */
	if (my_conn > NONE && Conn_GetClient(my_conn))
		return CONNECTED;
	else
		return DISCONNECTED;
}
Exemplo n.º 2
0
Arquivo: client.c Projeto: kazcw/pande
GLOBAL void
Client_Exit( void )
{
	CLIENT *c, *next;
	int cnt;

	if( NGIRCd_SignalRestart ) Client_Destroy( This_Server, "Server going down (restarting).", NULL, false );
	else Client_Destroy( This_Server, "Server going down.", NULL, false );
	
	cnt = 0;
	c = My_Clients;
	while(c) {
		cnt++;
		next = (CLIENT *)c->next;
		Free_Client(&c);
		c = next;
	}
	if (cnt)
		Log(LOG_INFO, "Freed %d client structure%s.",
		    cnt, cnt == 1 ? "" : "s");
} /* Client_Exit */
Exemplo n.º 3
0
/**
 * Handler for the IRC "QUIT" command.
 *
 * See RFC 2812, 3.1.7 "Quit", and RFC 2813, 4.1.5 "Quit".
 *
 * @param Client	The client from which this command has been received.
 * @param Req		Request structure with prefix and all parameters.
 * @returns		CONNECTED or DISCONNECTED.
 */
GLOBAL bool
IRC_QUIT( CLIENT *Client, REQUEST *Req )
{
	CLIENT *target;
	char quitmsg[LINE_LEN];

	assert(Client != NULL);
	assert(Req != NULL);

	/* Wrong number of arguments? */
	if (Req->argc > 1)
		return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
					  Client_ID(Client), Req->command);

	if (Req->argc == 1)
		strlcpy(quitmsg, Req->argv[0], sizeof quitmsg);

	if (Client_Type(Client) == CLIENT_SERVER) {
		/* Server */
		target = Client_Search(Req->prefix);
		if (!target) {
			Log(LOG_WARNING,
			    "Got QUIT from %s for unknown client!?",
			    Client_ID(Client));
			return CONNECTED;
		}

		if (target != Client) {
			Client_Destroy(target, "Got QUIT command.",
				       Req->argc == 1 ? quitmsg : NULL, true);
			return CONNECTED;
		} else {
			Conn_Close(Client_Conn(Client), "Got QUIT command.",
				   Req->argc == 1 ? quitmsg : NULL, true);
			return DISCONNECTED;
		}
	} else {
		if (Req->argc == 1 && quitmsg[0] != '\"') {
			/* " " to avoid confusion */
			strlcpy(quitmsg, "\"", sizeof quitmsg);
			strlcat(quitmsg, Req->argv[0], sizeof quitmsg-1);
			strlcat(quitmsg, "\"", sizeof quitmsg );
		}

		/* User, Service, or not yet registered */
		Conn_Close(Client_Conn(Client), "Got QUIT command.",
			   Req->argc == 1 ? quitmsg : NULL, true);

		return DISCONNECTED;
	}
} /* IRC_QUIT */
Exemplo n.º 4
0
Arquivo: irc.c Projeto: LucentW/ngircd
/**
 * Handler for the IRC "ERROR" command.
 *
 * @param Client The client from which this command has been received.
 * @param Req Request structure with prefix and all parameters.
 * @return CONNECTED or DISCONNECTED.
*/
GLOBAL bool
IRC_ERROR(CLIENT *Client, REQUEST *Req)
{
	char *msg;

	assert( Client != NULL );
	assert( Req != NULL );

	if (Client_Type(Client) != CLIENT_GOTPASS
	    && Client_Type(Client) != CLIENT_GOTPASS_2813
	    && Client_Type(Client) != CLIENT_UNKNOWNSERVER
	    && Client_Type(Client) != CLIENT_SERVER
	    && Client_Type(Client) != CLIENT_SERVICE) {
		LogDebug("Ignored ERROR command from \"%s\" ...",
			 Client_Mask(Client));
		IRC_SetPenalty(Client, 2);
		return CONNECTED;
	}

	if (Req->argc < 1) {
		msg = "Got ERROR command";
		Log(LOG_NOTICE, "Got ERROR from \"%s\"!",
		    Client_Mask(Client));
	} else {
		msg = Req->argv[0];
		Log(LOG_NOTICE, "Got ERROR from \"%s\": \"%s\"!",
		    Client_Mask(Client), msg);
	}

	if (Client_Conn(Client) != NONE) {
		Client_Destroy(Client, NULL, msg, false);
		return DISCONNECTED;
	}

	return CONNECTED;
} /* IRC_ERROR */
Exemplo n.º 5
0
/**
 * Handler for the IRC "KILL" command.
 *
 * This function implements the IRC command "KILL" wich is used to selectively
 * disconnect clients. It can be used by IRC operators and servers, for example
 * to "solve" nick collisions after netsplits. See RFC 2812 section 3.7.1.
 *
 * Please note that this function is also called internally, without a real
 * KILL command being received over the network! Client is Client_ThisServer()
 * in this case, and the prefix in Req is NULL.
 *
 * @param Client	The client from which this command has been received
 *			or Client_ThisServer() when generated interanlly.
 * @param Req		Request structure with prefix and all parameters.
 * @returns		CONNECTED or DISCONNECTED.
 */
GLOBAL bool
IRC_KILL( CLIENT *Client, REQUEST *Req )
{
	CLIENT *prefix, *c;
	char reason[COMMAND_LEN], *msg;
	CONN_ID my_conn, conn;

	assert (Client != NULL);
	assert (Req != NULL);

	if (Client_Type(Client) != CLIENT_SERVER && !Client_OperByMe(Client))
		return IRC_WriteStrClient(Client, ERR_NOPRIVILEGES_MSG,
					  Client_ID(Client));

	if (Req->argc != 2)
		return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
					  Client_ID(Client), Req->command);

	/* Get prefix (origin); use the client if no prefix is given. */
	if (Req->prefix)
		prefix = Client_Search(Req->prefix);
	else
		prefix = Client;

	/* Log a warning message and use this server as origin when the
	 * prefix (origin) is invalid. */
	if (!prefix) {
		Log(LOG_WARNING, "Got KILL with invalid prefix: \"%s\"!",
		    Req->prefix );
		prefix = Client_ThisServer();
	}

	if (Client != Client_ThisServer())
		Log(LOG_NOTICE|LOG_snotice,
		    "Got KILL command from \"%s\" for \"%s\": %s",
		    Client_Mask(prefix), Req->argv[0], Req->argv[1]);

	/* Build reason string: Prefix the "reason" if the originator is a
	 * regular user, so users can't spoof KILLs of servers. */
	if (Client_Type(Client) == CLIENT_USER)
		snprintf(reason, sizeof(reason), "KILLed by %s: %s",
			 Client_ID(Client), Req->argv[1]);
	else
		strlcpy(reason, Req->argv[1], sizeof(reason));

	/* Inform other servers */
	IRC_WriteStrServersPrefix(Client, prefix, "KILL %s :%s",
				  Req->argv[0], reason);

	/* Save ID of this connection */
	my_conn = Client_Conn( Client );

	/* Do we host such a client? */
	c = Client_Search( Req->argv[0] );
	if( c )
	{
		if(( Client_Type( c ) != CLIENT_USER ) &&
		   ( Client_Type( c ) != CLIENT_GOTNICK ))
		{
			/* Target of this KILL is not a regular user, this is
			 * invalid! So we ignore this case if we received a
			 * regular KILL from the network and try to kill the
			 * client/connection anyway (but log an error!) if the
			 * origin is the local server. */

			if( Client != Client_ThisServer( ))
			{
				/* Invalid KILL received from remote */
				if( Client_Type( c ) == CLIENT_SERVER )
					msg = ERR_CANTKILLSERVER_MSG;
				else
					msg = ERR_NOPRIVILEGES_MSG;
				return IRC_WriteStrClient( Client, msg,
					Client_ID( Client ));
			}

			Log( LOG_ERR, "Got KILL for invalid client type: %d, \"%s\"!",
			     Client_Type( c ), Req->argv[0] );
		}

		/* Kill the client NOW:
		 *  - Close the local connection (if there is one),
		 *  - Destroy the CLIENT structure for remote clients.
		 * Note: Conn_Close() removes the CLIENT structure as well. */
		conn = Client_Conn( c );
		if(conn > NONE)
			Conn_Close(conn, NULL, reason, true);
		else
			Client_Destroy(c, NULL, reason, false);
	}
	else
		Log( LOG_NOTICE, "Client with nick \"%s\" is unknown here.", Req->argv[0] );

	/* Are we still connected or were we killed, too? */
	if(( my_conn > NONE ) && ( Conn_GetClient( my_conn )))
		return CONNECTED;
	else
		return DISCONNECTED;
} /* IRC_KILL */
Exemplo n.º 6
0
Arquivo: client.c Projeto: kazcw/pande
GLOBAL void
Client_Destroy( CLIENT *Client, const char *LogMsg, const char *FwdMsg, bool SendQuit )
{
	/* remove a client */
	
	CLIENT *last, *c;
	char msg[COMMAND_LEN];
	const char *txt;

	assert( Client != NULL );

	txt = LogMsg ? LogMsg : FwdMsg;
	if (!txt)
		txt = "Reason unknown";

	/* netsplit message */
	if( Client->type == CLIENT_SERVER ) {
		strlcpy(msg, This_Server->id, sizeof (msg));
		strlcat(msg, " ", sizeof (msg));
		strlcat(msg, Client->id, sizeof (msg));
	}

	last = NULL;
	c = My_Clients;
	while( c )
	{
		if(( Client->type == CLIENT_SERVER ) && ( c->introducer == Client ) && ( c != Client ))
		{
			/*
			 * The client that is about to be removed is a server,
			 * the client we are checking right now is a child of that
			 * server and thus has to be removed, too.
			 *
			 * Call Client_Destroy() recursively with the server as the
			 * new "object to be removed". This starts the cycle again, until
			 * all servers that are linked via the original server have been
			 * removed.
			 */
			Client_Destroy( c, NULL, msg, false );
			last = NULL;
			c = My_Clients;
			continue;
		}
		if( c == Client )
		{
			/* found  the client: remove it */
			if( last ) last->next = c->next;
			else My_Clients = (CLIENT *)c->next;

			if(c->type == CLIENT_USER || c->type == CLIENT_SERVICE)
				Destroy_UserOrService(c, txt, FwdMsg, SendQuit);
			else if( c->type == CLIENT_SERVER )
			{
				if (c != This_Server) {
					if (c->conn_id != NONE)
						Log(LOG_NOTICE|LOG_snotice,
						    "Server \"%s\" unregistered (connection %d): %s.",
						c->id, c->conn_id, txt);
					else
						Log(LOG_NOTICE|LOG_snotice,
						    "Server \"%s\" unregistered: %s.",
						    c->id, txt);
				}

				/* inform other servers */
				if( ! NGIRCd_SignalQuit )
				{
					if( FwdMsg ) IRC_WriteStrServersPrefix( Client_NextHop( c ), c, "SQUIT %s :%s", c->id, FwdMsg );
					else IRC_WriteStrServersPrefix( Client_NextHop( c ), c, "SQUIT %s :", c->id );
				}
			}
			else
			{
				if (c->conn_id != NONE) {
					if (c->id[0])
						Log(LOG_NOTICE,
						    "Client \"%s\" unregistered (connection %d): %s.",
						    c->id, c->conn_id, txt);
					else
						Log(LOG_NOTICE,
						    "Client unregistered (connection %d): %s.",
						    c->conn_id, txt);
				} else {
					Log(LOG_WARNING,
					    "Unregistered unknown client \"%s\": %s",
					    c->id[0] ? c->id : "(No Nick)", txt);
				}
			}

			Free_Client(&c);
			break;
		}
		last = c;
		c = (CLIENT *)c->next;
	}
} /* Client_Destroy */
Exemplo n.º 7
0
Arquivo: dht.c Projeto: nja/dumhet
void Dht_DestroyClient(void *client)
{
    Client_Destroy((Client *)client);
}
Exemplo n.º 8
0
/**
 * Handler for the IRC command "SQUIT".
 * See RFC 2813 section 4.1.2 and RFC 2812 section 3.1.8.
 */
GLOBAL bool
IRC_SQUIT(CLIENT * Client, REQUEST * Req)
{
	char msg[COMMAND_LEN], logmsg[COMMAND_LEN];
	CLIENT *from, *target;
	CONN_ID con;
	int loglevel;

	assert(Client != NULL);
	assert(Req != NULL);

	if (Client_Type(Client) != CLIENT_SERVER
	    && !Client_HasMode(Client, 'o'))
		return Op_NoPrivileges(Client, Req);

	/* Bad number of arguments? */
	if (Req->argc != 2)
		return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
					  Client_ID(Client), Req->command);

	if (Client_Type(Client) == CLIENT_SERVER && Req->prefix) {
		from = Client_Search(Req->prefix);
		if (Client_Type(from) != CLIENT_SERVER
		    && !Op_Check(Client, Req))
			return Op_NoPrivileges(Client, Req);
	} else
		from = Client;
	if (!from)
		return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
					  Client_ID(Client), Req->prefix);

	if (Client_Type(Client) == CLIENT_USER)
		loglevel = LOG_NOTICE | LOG_snotice;
	else
		loglevel = LOG_DEBUG;
	Log(loglevel, "Got SQUIT from %s for \"%s\": \"%s\" ...",
	    Client_ID(from), Req->argv[0], Req->argv[1]);

	target = Client_Search(Req->argv[0]);
	if (Client_Type(Client) != CLIENT_SERVER &&
	    target == Client_ThisServer())
		return Op_NoPrivileges(Client, Req);
	if (!target) {
		/* The server is (already) unknown */
		Log(LOG_WARNING,
		    "Got SQUIT from %s for unknown server \"%s\"!?",
		    Client_ID(Client), Req->argv[0]);
		return CONNECTED;
	}

	con = Client_Conn(target);

	if (Req->argv[1][0])
		if (Client_NextHop(from) != Client || con > NONE)
			snprintf(msg, sizeof(msg), "%s (SQUIT from %s)",
				 Req->argv[1], Client_ID(from));
		else
			strlcpy(msg, Req->argv[1], sizeof(msg));
	else
		snprintf(msg, sizeof(msg), "Got SQUIT from %s",
			 Client_ID(from));

	if (con > NONE) {
		/* We are directly connected to the target server, so we
		 * have to tear down the connection and to inform all the
		 * other remaining servers in the network */
		IRC_SendWallops(Client_ThisServer(), Client_ThisServer(),
				"Received SQUIT %s from %s: %s",
				Req->argv[0], Client_ID(from),
				Req->argv[1][0] ? Req->argv[1] : "-");
		Conn_Close(con, NULL, msg, true);
		if (con == Client_Conn(Client))
			return DISCONNECTED;
	} else {
		/* This server is not directly connected, so the SQUIT must
		 * be forwarded ... */
		if (Client_Type(from) != CLIENT_SERVER) {
			/* The origin is not an IRC server, so don't evaluate
			 * this SQUIT but simply forward it */
			IRC_WriteStrClientPrefix(Client_NextHop(target),
			    from, "SQUIT %s :%s", Req->argv[0], Req->argv[1]);
		} else {
			/* SQUIT has been generated by another server, so
			 * remove the target server from the network! */
			logmsg[0] = '\0';
			if (!strchr(msg, '('))
				snprintf(logmsg, sizeof(logmsg),
					 "%s (SQUIT from %s)", Req->argv[1],
					 Client_ID(from));
			Client_Destroy(target, logmsg[0] ? logmsg : msg,
				       msg, false);
		}
	}
	return CONNECTED;
} /* IRC_SQUIT */
Exemplo n.º 9
0
void server_exec(Socket server, SockAddrIn server_addr, ClientSet* clients,
                 NoticeBoard* board)
{
    int i;

    if (listen(server, 5) == -1) {
        error("Could not listen on socket");
        exit(1);
    }

    while (running) {
        usleep(100000);
        /* -- Accepting connections -- */
        socklen_t sz = sizeof(server_addr);
        Socket new_socket = accept(server, (SockAddr*)&server_addr, &sz);
        /* Error handling, most likely EAGAIN since we're using
         * non blocking sockets.
         */
        if (new_socket == -1) {
            if (errno != EAGAIN) {
                error("Could not accept connection");
            }
        } else {
            int j = 0;
            fcntl(new_socket, F_SETFL, O_NONBLOCK);
            Client* c = ClientSet_Add(clients, new_socket);
            if (c == NULL) continue;
            memset(c->properties.nick, 0, NICK_MAXLEN);
            strcpy(c->properties.nick, "user");

            for (i = 0; i < clients->size; i++) {
                if (&clients->clients[i] == c ||
                    clients->clients[i].state == DISCONNECTED) continue;
                if (!strcmp(clients->clients[i].properties.nick,
                    c->properties.nick)) {
                    j++;
                    sprintf(c->properties.nick, "user(%d)", j);
                    i = 0;
                }
            }

            SockAddr peer_address;
            socklen_t addrlen = sizeof(peer_address);
            int has_error = getpeername(new_socket, &peer_address,
                                &addrlen);
            if (has_error == -1) {
                error("Error getting peer name");
            }
            SockAddrIn *addr_in = (struct sockaddr_in *)&peer_address;
            c->ip_string = ipaddr(*addr_in);

            printf("Client connected (%s)\n", c->ip_string);
            send_motd(c);
        }

        /* -- Reading data -- */
        for (i = 0; i < clients->size; i++) {
            if (clients->clients[i].state == DISCONNECTED) {
                Client_Destroy(&clients->clients[i]);
                continue;
            }
            client_exec(&(clients->clients[i]), i, clients, board);
        }
    }
}
Exemplo n.º 10
0
void disconnect(Client* client)
{
    printf("Client disconnected (%s)\n", client->ip_string);
    Client_Destroy(client);
}