2 * ngIRCd -- The Next Generation IRC Daemon
3 * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * Please read the file COPYING, README and AUTHORS for more information.
25 #include "conn-func.h"
35 #include "irc-write.h"
38 #include "irc-login.h"
40 static void Kill_Nick PARAMS(( char *Nick, char *Reason ));
43 * Handler for the IRC "PASS" command.
45 * See RFC 2813 section 4.1.1, and RFC 2812 section 3.1.1.
47 * @param Client The client from which this command has been received.
48 * @param Req Request structure with prefix and all parameters.
49 * @returns CONNECTED or DISCONNECTED.
52 IRC_PASS( CLIENT *Client, REQUEST *Req )
54 char *type, *orig_flags;
55 int protohigh, protolow;
57 assert( Client != NULL );
58 assert( Req != NULL );
60 /* Return an error if this is not a local client */
61 if (Client_Conn(Client) <= NONE)
62 return IRC_WriteStrClient(Client, ERR_UNKNOWNCOMMAND_MSG,
63 Client_ID(Client), Req->command);
65 if (Client_Type(Client) == CLIENT_UNKNOWN && Req->argc == 1) {
66 /* Not yet registered "unknown" connection, PASS with one
67 * argument: either a regular client, service, or server
68 * using the old RFC 1459 section 4.1.1 syntax. */
69 LogDebug("Connection %d: got PASS command (RFC 1459) ...",
71 } else if ((Client_Type(Client) == CLIENT_UNKNOWN ||
72 Client_Type(Client) == CLIENT_UNKNOWNSERVER) &&
73 (Req->argc == 3 || Req->argc == 4)) {
74 /* Not yet registered "unknown" connection or outgoing server
75 * link, PASS with three or four argument: server using the
76 * RFC 2813 section 4.1.1 syntax. */
77 LogDebug("Connection %d: got PASS command (RFC 2813, new server link) ...",
79 } else if (Client_Type(Client) == CLIENT_UNKNOWN ||
80 Client_Type(Client) == CLIENT_UNKNOWNSERVER) {
81 /* Unregistered connection, but wrong number of arguments: */
82 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
83 Client_ID(Client), Req->command);
85 /* Registered connection, PASS command is not allowed! */
86 return IRC_WriteStrClient(Client, ERR_ALREADYREGISTRED_MSG,
90 Client_SetPassword(Client, Req->argv[0]);
92 /* Protocol version */
93 if (Req->argc >= 2 && strlen(Req->argv[1]) >= 4) {
99 Req->argv[1][4] = '\0';
100 protolow = atoi(&Req->argv[1][2]);
101 Req->argv[1][2] = '\0';
102 protohigh = atoi(Req->argv[1]);
104 Req->argv[1][2] = c2;
105 Req->argv[1][4] = c4;
107 Client_SetType(Client, CLIENT_GOTPASS_2813);
109 protohigh = protolow = 0;
110 Client_SetType(Client, CLIENT_GOTPASS);
113 /* Protocol type, see doc/Protocol.txt */
114 if (Req->argc >= 2 && strlen(Req->argv[1]) > 4)
115 type = &Req->argv[1][4];
119 /* Protocol flags/options */
121 orig_flags = Req->argv[3];
125 /* Implementation, version and IRC+ flags */
126 if (Req->argc >= 3) {
127 char *impl, *ptr, *serverver, *flags;
130 ptr = strchr(impl, '|');
134 if (type && strcmp(type, PROTOIRCPLUS) == 0) {
135 /* The peer seems to be a server which supports the
136 * IRC+ protocol (see doc/Protocol.txt). */
137 serverver = ptr ? ptr + 1 : "?";
138 flags = strchr(ptr ? serverver : impl, ':');
145 "Peer on conenction %d announces itself as %s-%s using protocol %d.%d/IRC+ (flags: \"%s\").",
146 Client_Conn(Client), impl, serverver,
147 protohigh, protolow, flags);
149 /* The peer seems to be a server supporting the
150 * "original" IRC protocol (RFC 2813). */
151 if (strchr(orig_flags, 'Z'))
156 "Peer on connection %d announces itself as \"%s\" using protocol %d.%d (flags: \"%s\").",
157 Client_Conn(Client), impl,
158 protohigh, protolow, flags);
160 Client_SetFlags(Client, flags);
168 * Handler for the IRC "NICK" command.
170 * See RFC 2812, 3.1.2 "Nick message", and RFC 2813, 4.1.3 "Nick".
172 * This function implements the IRC command "NICK" which is used to register
173 * with the server, to change already registered nicknames and to introduce
174 * new users which are connected to other servers.
176 * @param Client The client from which this command has been received.
177 * @param Req Request structure with prefix and all parameters.
178 * @returns CONNECTED or DISCONNECTED.
181 IRC_NICK( CLIENT *Client, REQUEST *Req )
183 CLIENT *intr_c, *target, *c;
184 char *nick, *user, *hostname, *modes, *info;
187 assert( Client != NULL );
188 assert( Req != NULL );
190 /* Some IRC clients, for example BitchX, send the NICK and USER
191 * commands in the wrong order ... */
192 if(Client_Type(Client) == CLIENT_UNKNOWN
193 || Client_Type(Client) == CLIENT_GOTPASS
194 || Client_Type(Client) == CLIENT_GOTNICK
196 || Client_Type(Client) == CLIENT_GOTUSER
198 || Client_Type(Client) == CLIENT_USER
199 || Client_Type(Client) == CLIENT_SERVICE
200 || (Client_Type(Client) == CLIENT_SERVER && Req->argc == 1))
202 /* User registration or change of nickname */
204 /* Wrong number of arguments? */
206 return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG,
210 /* Search "target" client */
211 if( Client_Type( Client ) == CLIENT_SERVER )
213 target = Client_Search( Req->prefix );
215 return IRC_WriteStrClient( Client,
222 /* Is this a restricted client? */
223 if( Client_HasMode( Client, 'r' ))
224 return IRC_WriteStrClient( Client,
226 Client_ID( Client ));
232 /* If the clients tries to change to its own nickname we won't
233 * do anything. This is how the original ircd behaves and some
234 * clients (for example Snak) expect it to be like this.
235 * But I doubt that this is "really the right thing" ... */
236 if( strcmp( Client_ID( target ), Req->argv[0] ) == 0 )
240 /* Check that the new nickname is available. Special case:
241 * the client only changes from/to upper to lower case. */
242 if( strcasecmp( Client_ID( target ), Req->argv[0] ) != 0 )
244 if( ! Client_CheckNick( target, Req->argv[0] ))
248 if (Client_Type(target) != CLIENT_USER &&
249 Client_Type(target) != CLIENT_SERVICE &&
250 Client_Type(target) != CLIENT_SERVER) {
252 LogDebug("Connection %d: got valid NICK command ...",
253 Client_Conn( Client ));
255 /* Register new nickname of this client */
256 Client_SetID( target, Req->argv[0] );
260 Conn_SetAuthPing(Client_Conn(Client), rand());
261 IRC_WriteStrClient(Client, "PING :%ld",
262 Conn_GetAuthPing(Client_Conn(Client)));
263 LogDebug("Connection %d: sent AUTH PING %ld ...",
265 Conn_GetAuthPing(Client_Conn(Client)));
269 /* If we received a valid USER command already then
270 * register the new client! */
271 if( Client_Type( Client ) == CLIENT_GOTUSER )
272 return Login_User( Client );
274 Client_SetType( Client, CLIENT_GOTNICK );
276 /* Nickname change */
277 if (Client_Conn(target) > NONE) {
280 "%s \"%s\" changed nick (connection %d): \"%s\" -> \"%s\".",
281 Client_TypeText(target), Client_Mask(target),
282 Client_Conn(target), Client_ID(target),
284 Conn_UpdateIdle(Client_Conn(target));
287 LogDebug("%s \"%s\" changed nick: \"%s\" -> \"%s\".",
288 Client_TypeText(target),
289 Client_Mask(target), Client_ID(target),
293 /* Inform all users and servers (which have to know)
294 * of this nickname change */
295 if( Client_Type( Client ) == CLIENT_USER )
296 IRC_WriteStrClientPrefix( Client, Client,
299 IRC_WriteStrServersPrefix( Client, target,
300 "NICK :%s", Req->argv[0] );
301 IRC_WriteStrRelatedPrefix( target, target, false,
302 "NICK :%s", Req->argv[0] );
304 /* Register old nickname for WHOWAS queries */
305 Client_RegisterWhowas( target );
307 /* Save new nickname */
308 Client_SetID( target, Req->argv[0] );
310 IRC_SetPenalty( target, 2 );
314 } else if(Client_Type(Client) == CLIENT_SERVER ||
315 Client_Type(Client) == CLIENT_SERVICE) {
316 /* Server or service introduces new client */
318 /* Bad number of parameters? */
319 if (Req->argc != 2 && Req->argc != 7)
320 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
321 Client_ID(Client), Req->command);
323 if (Req->argc >= 7) {
324 /* RFC 2813 compatible syntax */
326 hops = atoi(Req->argv[1]);
328 hostname = Req->argv[3];
329 token = atoi(Req->argv[4]);
330 modes = Req->argv[5] + 1;
333 /* RFC 1459 compatible syntax */
337 hostname = Client_ID(Client);
338 token = atoi(Req->argv[1]);
343 c = Client_Search(nick);
346 * the new nick is already present on this server:
347 * the new and the old one have to be disconnected now.
349 Log( LOG_ERR, "Server %s introduces already registered nick \"%s\"!", Client_ID( Client ), Req->argv[0] );
350 Kill_Nick( Req->argv[0], "Nick collision" );
354 /* Find the Server this client is connected to */
355 intr_c = Client_GetFromToken(Client, token);
358 Log( LOG_ERR, "Server %s introduces nick \"%s\" on unknown server!?", Client_ID( Client ), Req->argv[0] );
359 Kill_Nick( Req->argv[0], "Unknown server" );
363 c = Client_NewRemoteUser(intr_c, nick, hops, user, hostname,
364 token, modes, info, true);
367 /* out of memory, need to disconnect client to keep network state consistent */
368 Log( LOG_ALERT, "Can't create client structure! (on connection %d)", Client_Conn( Client ));
369 Kill_Nick( Req->argv[0], "Server error" );
373 /* RFC 2813: client is now fully registered, inform all the
374 * other servers about the new user.
375 * RFC 1459: announce the new client only after receiving the
376 * USER command, first we need more information! */
378 LogDebug("Client \"%s\" is being registered (RFC 1459) ...",
380 Client_SetType(c, CLIENT_GOTNICK);
382 Client_Introduce(Client, c, CLIENT_USER);
386 else return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
391 * Handler for the IRC "USER" command.
393 * See RFC 2812, 3.1.3 "User message".
395 * @param Client The client from which this command has been received.
396 * @param Req Request structure with prefix and all parameters.
397 * @returns CONNECTED or DISCONNECTED.
400 IRC_USER(CLIENT * Client, REQUEST * Req)
407 assert(Client != NULL);
410 if (Client_Type(Client) == CLIENT_GOTNICK ||
412 Client_Type(Client) == CLIENT_UNKNOWN ||
414 Client_Type(Client) == CLIENT_GOTPASS)
418 return IRC_WriteStrClient(Client,
419 ERR_NEEDMOREPARAMS_MSG,
425 ptr = Client_User(Client);
426 if (!ptr || !*ptr || *ptr == '~')
427 Client_SetUser(Client, Req->argv[0], false);
429 Client_SetUser(Client, Req->argv[0], false);
431 Client_SetOrigUser(Client, Req->argv[0]);
433 /* "Real name" or user info text: Don't set it to the empty
434 * string, the original ircd can't deal with such "real names"
435 * (e. g. "USER user * * :") ... */
437 Client_SetInfo(Client, Req->argv[3]);
439 Client_SetInfo(Client, "-");
441 LogDebug("Connection %d: got valid USER command ...",
442 Client_Conn(Client));
443 if (Client_Type(Client) == CLIENT_GOTNICK)
444 return Login_User(Client);
446 Client_SetType(Client, CLIENT_GOTUSER);
449 } else if (Client_Type(Client) == CLIENT_SERVER ||
450 Client_Type(Client) == CLIENT_SERVICE) {
451 /* Server/service updating an user */
453 return IRC_WriteStrClient(Client,
454 ERR_NEEDMOREPARAMS_MSG,
457 c = Client_Search(Req->prefix);
459 return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
463 Client_SetUser(c, Req->argv[0], true);
464 Client_SetOrigUser(c, Req->argv[0]);
465 Client_SetHostname(c, Req->argv[1]);
466 Client_SetInfo(c, Req->argv[3]);
468 LogDebug("Connection %d: got valid USER command for \"%s\".",
469 Client_Conn(Client), Client_Mask(c));
471 /* RFC 1459 style user registration?
472 * Introduce client to network: */
473 if (Client_Type(c) == CLIENT_GOTNICK)
474 Client_Introduce(Client, c, CLIENT_USER);
477 } else if (Client_Type(Client) == CLIENT_USER) {
478 /* Already registered connection */
479 return IRC_WriteStrClient(Client, ERR_ALREADYREGISTRED_MSG,
482 /* Unexpected/invalid connection state? */
483 return IRC_WriteStrClient(Client, ERR_NOTREGISTERED_MSG,
490 * Handler for the IRC "SERVICE" command.
492 * This function implements IRC Services registration using the SERVICE command
493 * defined in RFC 2812 3.1.6 and RFC 2813 4.1.4.
495 * At the moment ngIRCd doesn't support directly linked services, so this
496 * function returns ERR_ERRONEUSNICKNAME when the SERVICE command has not been
497 * received from a peer server.
499 * @param Client The client from which this command has been received.
500 * @param Req Request structure with prefix and all parameters.
501 * @returns CONNECTED or DISCONNECTED..
504 IRC_SERVICE(CLIENT *Client, REQUEST *Req)
507 char *nick, *user, *host, *info, *modes, *ptr;
510 assert(Client != NULL);
513 if (Client_Type(Client) != CLIENT_GOTPASS &&
514 Client_Type(Client) != CLIENT_SERVER)
515 return IRC_WriteStrClient(Client, ERR_ALREADYREGISTRED_MSG,
519 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
520 Client_ID(Client), Req->command);
522 if (Client_Type(Client) != CLIENT_SERVER)
523 return IRC_WriteStrClient(Client, ERR_ERRONEUSNICKNAME_MSG,
524 Client_ID(Client), Req->argv[0]);
526 /* Bad number of parameters? */
528 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
529 Client_ID(Client), Req->command);
532 user = NULL; host = NULL;
533 token = atoi(Req->argv[1]);
534 hops = atoi(Req->argv[4]);
537 /* Validate service name ("nick name") */
538 c = Client_Search(nick);
540 /* Nick name collission: disconnect (KILL) both clients! */
541 Log(LOG_ERR, "Server %s introduces already registered service \"%s\"!",
542 Client_ID(Client), nick);
543 Kill_Nick(nick, "Nick collision");
547 /* Get the server to which the service is connected */
548 intr_c = Client_GetFromToken(Client, token);
550 Log(LOG_ERR, "Server %s introduces service \"%s\" on unknown server!?",
551 Client_ID(Client), nick);
552 Kill_Nick(nick, "Unknown server");
556 /* Get user and host name */
557 ptr = strchr(nick, '@');
563 host = Client_Hostname(intr_c);
564 ptr = strchr(nick, '!');
572 /* According to RFC 2812/2813 parameter 4 <type> "is currently reserved
573 * for future usage"; but we use it to transfer the modes and check
574 * that the first character is a '+' sign and ignore it otherwise. */
575 modes = (Req->argv[3][0] == '+') ? ++Req->argv[3] : "";
577 c = Client_NewRemoteUser(intr_c, nick, hops, user, host,
578 token, modes, info, true);
580 /* Couldn't create client structure, so KILL the service to
581 * keep network status consistent ... */
582 Log(LOG_ALERT, "Can't create client structure! (on connection %d)",
583 Client_Conn(Client));
584 Kill_Nick(nick, "Server error");
588 Client_Introduce(Client, c, CLIENT_SERVICE);
594 * Handler for the IRC "WEBIRC" command.
596 * See doc/Protocol.txt, section II.4:
597 * "Update webchat/proxy client information".
599 * @param Client The client from which this command has been received.
600 * @param Req Request structure with prefix and all parameters.
601 * @returns CONNECTED or DISCONNECTED.
604 IRC_WEBIRC(CLIENT *Client, REQUEST *Req)
606 /* Exactly 4 parameters are requited */
608 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
609 Client_ID(Client), Req->command);
611 if (!Conf_WebircPwd[0] || strcmp(Req->argv[0], Conf_WebircPwd) != 0)
612 return IRC_WriteStrClient(Client, ERR_PASSWDMISMATCH_MSG,
615 LogDebug("Connection %d: got valid WEBIRC command: user=%s, host=%s, ip=%s",
616 Client_Conn(Client), Req->argv[1], Req->argv[2], Req->argv[3]);
618 Client_SetUser(Client, Req->argv[1], true);
619 Client_SetOrigUser(Client, Req->argv[1]);
620 Client_SetHostname(Client, Req->argv[2]);
626 * Handler for the IRC "QUIT" command.
628 * See RFC 2812, 3.1.7 "Quit", and RFC 2813, 4.1.5 "Quit".
630 * @param Client The client from which this command has been received.
631 * @param Req Request structure with prefix and all parameters.
632 * @returns CONNECTED or DISCONNECTED.
635 IRC_QUIT( CLIENT *Client, REQUEST *Req )
638 char quitmsg[LINE_LEN];
640 assert(Client != NULL);
643 /* Wrong number of arguments? */
645 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
646 Client_ID(Client), Req->command);
649 strlcpy(quitmsg, Req->argv[0], sizeof quitmsg);
651 if (Client_Type(Client) == CLIENT_SERVER) {
653 target = Client_Search(Req->prefix);
656 "Got QUIT from %s for unknown client!?",
661 if (target != Client) {
662 Client_Destroy(target, "Got QUIT command.",
663 Req->argc == 1 ? quitmsg : NULL, true);
666 Conn_Close(Client_Conn(Client), "Got QUIT command.",
667 Req->argc == 1 ? quitmsg : NULL, true);
671 if (Req->argc == 1 && quitmsg[0] != '\"') {
672 /* " " to avoid confusion */
673 strlcpy(quitmsg, "\"", sizeof quitmsg);
674 strlcat(quitmsg, Req->argv[0], sizeof quitmsg-1);
675 strlcat(quitmsg, "\"", sizeof quitmsg );
678 /* User, Service, or not yet registered */
679 Conn_Close(Client_Conn(Client), "Got QUIT command.",
680 Req->argc == 1 ? quitmsg : NULL, true);
690 * Handler for HTTP command, e.g. GET and POST
692 * We handle these commands here to avoid the quite long timeout when
693 * some user tries to access this IRC daemon using an web browser ...
695 * @param Client The client from which this command has been received.
696 * @param Req Request structure with prefix and all parameters.
697 * @returns CONNECTED or DISCONNECTED.
700 IRC_QUIT_HTTP( CLIENT *Client, REQUEST *Req )
703 Req->argv[0] = "Oops, HTTP request received? This is IRC!";
704 return IRC_QUIT(Client, Req);
705 } /* IRC_QUIT_HTTP */
711 * Handler for the IRC "PING" command.
713 * See RFC 2812, 3.7.2 "Ping message".
715 * @param Client The client from which this command has been received.
716 * @param Req Request structure with prefix and all parameters.
717 * @returns CONNECTED or DISCONNECTED.
720 IRC_PING(CLIENT *Client, REQUEST *Req)
722 CLIENT *target, *from;
724 assert(Client != NULL);
728 return IRC_WriteStrClient(Client, ERR_NOORIGIN_MSG,
731 /* Don't ignore additional arguments when in "strict" mode */
733 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
734 Client_ID(Client), Req->command);
738 /* A target has been specified ... */
739 target = Client_Search(Req->argv[1]);
741 if (!target || Client_Type(target) != CLIENT_SERVER)
742 return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
743 Client_ID(Client), Req->argv[1]);
745 if (target != Client_ThisServer()) {
746 /* Ok, we have to forward the PING */
747 if (Client_Type(Client) == CLIENT_SERVER)
748 from = Client_Search(Req->prefix);
752 return IRC_WriteStrClient(Client,
753 ERR_NOSUCHSERVER_MSG,
754 Client_ID(Client), Req->prefix);
756 return IRC_WriteStrClientPrefix(target, from,
757 "PING %s :%s", Req->argv[0],
762 if (Client_Type(Client) == CLIENT_SERVER) {
764 from = Client_Search(Req->prefix);
768 from = Client_ThisServer();
770 return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
771 Client_ID(Client), Req->prefix);
773 Log(LOG_DEBUG, "Connection %d: got PING, sending PONG ...",
774 Client_Conn(Client));
777 return IRC_WriteStrClient(Client, "PONG %s :%s",
778 Client_ID(from), Client_ID(Client));
780 /* Some clients depend on the argument being returned in the PONG
781 * reply (not mentioned in any RFC, though) */
782 return IRC_WriteStrClient(Client, "PONG %s :%s",
783 Client_ID(from), Req->argv[0]);
789 * Handler for the IRC "PONG" command.
791 * See RFC 2812, 3.7.3 "Pong message".
793 * @param Client The client from which this command has been received.
794 * @param Req Request structure with prefix and all parameters.
795 * @returns CONNECTED or DISCONNECTED.
798 IRC_PONG(CLIENT *Client, REQUEST *Req)
800 CLIENT *target, *from;
807 assert(Client != NULL);
810 /* Wrong number of arguments? */
812 if (Client_Type(Client) == CLIENT_USER)
813 return IRC_WriteStrClient(Client, ERR_NOORIGIN_MSG,
819 if (Client_Type(Client) == CLIENT_USER)
820 return IRC_WriteStrClient(Client,
821 ERR_NEEDMOREPARAMS_MSG,
829 if (Req->argc == 2 && Client_Type(Client) == CLIENT_SERVER) {
830 target = Client_Search(Req->argv[0]);
832 return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
833 Client_ID(Client), Req->argv[0]);
835 from = Client_Search(Req->prefix);
837 if (target != Client_ThisServer() && target != from) {
838 /* Ok, we have to forward the message. */
840 return IRC_WriteStrClient(Client,
841 ERR_NOSUCHSERVER_MSG,
842 Client_ID(Client), Req->prefix);
844 if (Client_Type(Client_NextHop(target)) != CLIENT_SERVER)
848 return IRC_WriteStrClientPrefix(target, from,
849 "PONG %s :%s", s, Req->argv[1]);
853 /* The connection timestamp has already been updated when the data has
854 * been read from so socket, so we don't need to update it here. */
856 conn = Client_Conn(Client);
859 /* Check authentication PING-PONG ... */
860 auth_ping = Conn_GetAuthPing(conn);
862 LogDebug("AUTH PONG: waiting for token \"%ld\", got \"%s\" ...",
863 auth_ping, Req->argv[0]);
864 if (auth_ping == atoi(Req->argv[0])) {
865 Conn_SetAuthPing(conn, 0);
866 if (Client_Type(Client) == CLIENT_WAITAUTHPING)
869 if (!IRC_WriteStrClient(Client,
870 "To connect, type /QUOTE PONG %ld",
876 if (Client_Type(Client) == CLIENT_SERVER && Conn_LastPing(conn) == 0) {
878 "Synchronization with \"%s\" done (connection %d): %ld seconds [%ld users, %ld channels]",
879 Client_ID(Client), conn, time(NULL) - Conn_GetSignon(conn),
880 Client_UserCount(), Channel_CountVisible(NULL));
881 Conn_UpdatePing(conn);
883 LogDebug("Connection %d: received PONG. Lag: %ld seconds.",
884 conn, time(NULL) - Conn_LastPing(conn));
891 * Kill all users with a specific nick name in the network.
893 * @param Nick Nick name.
894 * @param Reason Reason for the KILL.
897 Kill_Nick(char *Nick, char *Reason)
901 assert (Nick != NULL);
902 assert (Reason != NULL);
909 Log(LOG_ERR, "User(s) with nick \"%s\" will be disconnected: %s",
912 IRC_KILL(Client_ThisServer(), &r);