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 Conn_SetPassword(Client_Conn(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)
405 assert(Client != NULL);
408 if (Client_Type(Client) == CLIENT_GOTNICK ||
410 Client_Type(Client) == CLIENT_UNKNOWN ||
412 Client_Type(Client) == CLIENT_GOTPASS)
416 return IRC_WriteStrClient(Client,
417 ERR_NEEDMOREPARAMS_MSG,
421 /* User name: only alphanumeric characters and limited
422 punctuation is allowed.*/
425 if ((*ptr < '0' || *ptr > '9') &&
426 (*ptr < 'A' || *ptr > 'Z') &&
427 (*ptr < 'a' || *ptr > 'z') &&
428 (*ptr != '+') && (*ptr != '-') &&
429 (*ptr != '.') && (*ptr != '_')) {
430 Conn_Close(Client_Conn(Client), NULL,
431 "Invalid user name", true);
438 ptr = Client_User(Client);
439 if (!ptr || !*ptr || *ptr == '~')
440 Client_SetUser(Client, Req->argv[0], false);
442 Client_SetUser(Client, Req->argv[0], false);
444 Client_SetOrigUser(Client, Req->argv[0]);
446 /* "Real name" or user info text: Don't set it to the empty
447 * string, the original ircd can't deal with such "real names"
448 * (e. g. "USER user * * :") ... */
450 Client_SetInfo(Client, Req->argv[3]);
452 Client_SetInfo(Client, "-");
454 LogDebug("Connection %d: got valid USER command ...",
455 Client_Conn(Client));
456 if (Client_Type(Client) == CLIENT_GOTNICK)
457 return Login_User(Client);
459 Client_SetType(Client, CLIENT_GOTUSER);
462 } else if (Client_Type(Client) == CLIENT_SERVER ||
463 Client_Type(Client) == CLIENT_SERVICE) {
464 /* Server/service updating an user */
466 return IRC_WriteStrClient(Client,
467 ERR_NEEDMOREPARAMS_MSG,
470 c = Client_Search(Req->prefix);
472 return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
476 Client_SetUser(c, Req->argv[0], true);
477 Client_SetOrigUser(c, Req->argv[0]);
478 Client_SetHostname(c, Req->argv[1]);
479 Client_SetInfo(c, Req->argv[3]);
481 LogDebug("Connection %d: got valid USER command for \"%s\".",
482 Client_Conn(Client), Client_Mask(c));
484 /* RFC 1459 style user registration?
485 * Introduce client to network: */
486 if (Client_Type(c) == CLIENT_GOTNICK)
487 Client_Introduce(Client, c, CLIENT_USER);
490 } else if (Client_Type(Client) == CLIENT_USER) {
491 /* Already registered connection */
492 return IRC_WriteStrClient(Client, ERR_ALREADYREGISTRED_MSG,
495 /* Unexpected/invalid connection state? */
496 return IRC_WriteStrClient(Client, ERR_NOTREGISTERED_MSG,
503 * Handler for the IRC "SERVICE" command.
505 * This function implements IRC Services registration using the SERVICE command
506 * defined in RFC 2812 3.1.6 and RFC 2813 4.1.4.
508 * At the moment ngIRCd doesn't support directly linked services, so this
509 * function returns ERR_ERRONEUSNICKNAME when the SERVICE command has not been
510 * received from a peer server.
512 * @param Client The client from which this command has been received.
513 * @param Req Request structure with prefix and all parameters.
514 * @returns CONNECTED or DISCONNECTED..
517 IRC_SERVICE(CLIENT *Client, REQUEST *Req)
520 char *nick, *user, *host, *info, *modes, *ptr;
523 assert(Client != NULL);
526 if (Client_Type(Client) != CLIENT_GOTPASS &&
527 Client_Type(Client) != CLIENT_SERVER)
528 return IRC_WriteStrClient(Client, ERR_ALREADYREGISTRED_MSG,
532 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
533 Client_ID(Client), Req->command);
535 if (Client_Type(Client) != CLIENT_SERVER)
536 return IRC_WriteStrClient(Client, ERR_ERRONEUSNICKNAME_MSG,
537 Client_ID(Client), Req->argv[0]);
539 /* Bad number of parameters? */
541 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
542 Client_ID(Client), Req->command);
545 user = NULL; host = NULL;
546 token = atoi(Req->argv[1]);
547 hops = atoi(Req->argv[4]);
550 /* Validate service name ("nick name") */
551 c = Client_Search(nick);
553 /* Nick name collission: disconnect (KILL) both clients! */
554 Log(LOG_ERR, "Server %s introduces already registered service \"%s\"!",
555 Client_ID(Client), nick);
556 Kill_Nick(nick, "Nick collision");
560 /* Get the server to which the service is connected */
561 intr_c = Client_GetFromToken(Client, token);
563 Log(LOG_ERR, "Server %s introduces service \"%s\" on unknown server!?",
564 Client_ID(Client), nick);
565 Kill_Nick(nick, "Unknown server");
569 /* Get user and host name */
570 ptr = strchr(nick, '@');
576 host = Client_Hostname(intr_c);
577 ptr = strchr(nick, '!');
585 /* According to RFC 2812/2813 parameter 4 <type> "is currently reserved
586 * for future usage"; but we use it to transfer the modes and check
587 * that the first character is a '+' sign and ignore it otherwise. */
588 modes = (Req->argv[3][0] == '+') ? ++Req->argv[3] : "";
590 c = Client_NewRemoteUser(intr_c, nick, hops, user, host,
591 token, modes, info, true);
593 /* Couldn't create client structure, so KILL the service to
594 * keep network status consistent ... */
595 Log(LOG_ALERT, "Can't create client structure! (on connection %d)",
596 Client_Conn(Client));
597 Kill_Nick(nick, "Server error");
601 Client_Introduce(Client, c, CLIENT_SERVICE);
607 * Handler for the IRC "WEBIRC" command.
609 * See doc/Protocol.txt, section II.4:
610 * "Update webchat/proxy client information".
612 * @param Client The client from which this command has been received.
613 * @param Req Request structure with prefix and all parameters.
614 * @returns CONNECTED or DISCONNECTED.
617 IRC_WEBIRC(CLIENT *Client, REQUEST *Req)
619 /* Exactly 4 parameters are requited */
621 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
622 Client_ID(Client), Req->command);
624 if (!Conf_WebircPwd[0] || strcmp(Req->argv[0], Conf_WebircPwd) != 0)
625 return IRC_WriteStrClient(Client, ERR_PASSWDMISMATCH_MSG,
628 LogDebug("Connection %d: got valid WEBIRC command: user=%s, host=%s, ip=%s",
629 Client_Conn(Client), Req->argv[1], Req->argv[2], Req->argv[3]);
631 Client_SetUser(Client, Req->argv[1], true);
632 Client_SetOrigUser(Client, Req->argv[1]);
633 Client_SetHostname(Client, Req->argv[2]);
639 * Handler for the IRC "QUIT" command.
641 * See RFC 2812, 3.1.7 "Quit", and RFC 2813, 4.1.5 "Quit".
643 * @param Client The client from which this command has been received.
644 * @param Req Request structure with prefix and all parameters.
645 * @returns CONNECTED or DISCONNECTED.
648 IRC_QUIT( CLIENT *Client, REQUEST *Req )
651 char quitmsg[LINE_LEN];
653 assert(Client != NULL);
656 /* Wrong number of arguments? */
658 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
659 Client_ID(Client), Req->command);
662 strlcpy(quitmsg, Req->argv[0], sizeof quitmsg);
664 if (Client_Type(Client) == CLIENT_SERVER) {
666 target = Client_Search(Req->prefix);
669 "Got QUIT from %s for unknown client!?",
674 if (target != Client) {
675 Client_Destroy(target, "Got QUIT command.",
676 Req->argc == 1 ? quitmsg : NULL, true);
679 Conn_Close(Client_Conn(Client), "Got QUIT command.",
680 Req->argc == 1 ? quitmsg : NULL, true);
684 if (Req->argc == 1 && quitmsg[0] != '\"') {
685 /* " " to avoid confusion */
686 strlcpy(quitmsg, "\"", sizeof quitmsg);
687 strlcat(quitmsg, Req->argv[0], sizeof quitmsg-1);
688 strlcat(quitmsg, "\"", sizeof quitmsg );
691 /* User, Service, or not yet registered */
692 Conn_Close(Client_Conn(Client), "Got QUIT command.",
693 Req->argc == 1 ? quitmsg : NULL, true);
703 * Handler for HTTP command, e.g. GET and POST
705 * We handle these commands here to avoid the quite long timeout when
706 * some user tries to access this IRC daemon using an web browser ...
708 * @param Client The client from which this command has been received.
709 * @param Req Request structure with prefix and all parameters.
710 * @returns CONNECTED or DISCONNECTED.
713 IRC_QUIT_HTTP( CLIENT *Client, REQUEST *Req )
716 Req->argv[0] = "Oops, HTTP request received? This is IRC!";
717 return IRC_QUIT(Client, Req);
718 } /* IRC_QUIT_HTTP */
724 * Handler for the IRC "PING" command.
726 * See RFC 2812, 3.7.2 "Ping message".
728 * @param Client The client from which this command has been received.
729 * @param Req Request structure with prefix and all parameters.
730 * @returns CONNECTED or DISCONNECTED.
733 IRC_PING(CLIENT *Client, REQUEST *Req)
735 CLIENT *target, *from;
737 assert(Client != NULL);
741 return IRC_WriteStrClient(Client, ERR_NOORIGIN_MSG,
744 /* Don't ignore additional arguments when in "strict" mode */
746 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
747 Client_ID(Client), Req->command);
751 /* A target has been specified ... */
752 target = Client_Search(Req->argv[1]);
754 if (!target || Client_Type(target) != CLIENT_SERVER)
755 return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
756 Client_ID(Client), Req->argv[1]);
758 if (target != Client_ThisServer()) {
759 /* Ok, we have to forward the PING */
760 if (Client_Type(Client) == CLIENT_SERVER)
761 from = Client_Search(Req->prefix);
765 return IRC_WriteStrClient(Client,
766 ERR_NOSUCHSERVER_MSG,
767 Client_ID(Client), Req->prefix);
769 return IRC_WriteStrClientPrefix(target, from,
770 "PING %s :%s", Req->argv[0],
775 if (Client_Type(Client) == CLIENT_SERVER) {
777 from = Client_Search(Req->prefix);
781 from = Client_ThisServer();
783 return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
784 Client_ID(Client), Req->prefix);
786 Log(LOG_DEBUG, "Connection %d: got PING, sending PONG ...",
787 Client_Conn(Client));
790 return IRC_WriteStrClient(Client, "PONG %s :%s",
791 Client_ID(from), Client_ID(Client));
793 /* Some clients depend on the argument being returned in the PONG
794 * reply (not mentioned in any RFC, though) */
795 return IRC_WriteStrClient(Client, "PONG %s :%s",
796 Client_ID(from), Req->argv[0]);
802 * Handler for the IRC "PONG" command.
804 * See RFC 2812, 3.7.3 "Pong message".
806 * @param Client The client from which this command has been received.
807 * @param Req Request structure with prefix and all parameters.
808 * @returns CONNECTED or DISCONNECTED.
811 IRC_PONG(CLIENT *Client, REQUEST *Req)
813 CLIENT *target, *from;
820 assert(Client != NULL);
823 /* Wrong number of arguments? */
825 if (Client_Type(Client) == CLIENT_USER)
826 return IRC_WriteStrClient(Client, ERR_NOORIGIN_MSG,
832 if (Client_Type(Client) == CLIENT_USER)
833 return IRC_WriteStrClient(Client,
834 ERR_NEEDMOREPARAMS_MSG,
842 if (Req->argc == 2 && Client_Type(Client) == CLIENT_SERVER) {
843 target = Client_Search(Req->argv[0]);
845 return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
846 Client_ID(Client), Req->argv[0]);
848 from = Client_Search(Req->prefix);
850 if (target != Client_ThisServer() && target != from) {
851 /* Ok, we have to forward the message. */
853 return IRC_WriteStrClient(Client,
854 ERR_NOSUCHSERVER_MSG,
855 Client_ID(Client), Req->prefix);
857 if (Client_Type(Client_NextHop(target)) != CLIENT_SERVER)
861 return IRC_WriteStrClientPrefix(target, from,
862 "PONG %s :%s", s, Req->argv[1]);
866 /* The connection timestamp has already been updated when the data has
867 * been read from so socket, so we don't need to update it here. */
869 conn = Client_Conn(Client);
872 /* Check authentication PING-PONG ... */
873 auth_ping = Conn_GetAuthPing(conn);
875 LogDebug("AUTH PONG: waiting for token \"%ld\", got \"%s\" ...",
876 auth_ping, Req->argv[0]);
877 if (auth_ping == atoi(Req->argv[0])) {
878 Conn_SetAuthPing(conn, 0);
879 if (Client_Type(Client) == CLIENT_WAITAUTHPING)
882 if (!IRC_WriteStrClient(Client,
883 "To connect, type /QUOTE PONG %ld",
889 if (Client_Type(Client) == CLIENT_SERVER && Conn_LastPing(conn) == 0) {
891 "Synchronization with \"%s\" done (connection %d): %ld seconds [%ld users, %ld channels]",
892 Client_ID(Client), conn, time(NULL) - Conn_GetSignon(conn),
893 Client_UserCount(), Channel_CountVisible(NULL));
894 Conn_UpdatePing(conn);
896 LogDebug("Connection %d: received PONG. Lag: %ld seconds.",
897 conn, time(NULL) - Conn_LastPing(conn));
904 * Kill all users with a specific nick name in the network.
906 * @param Nick Nick name.
907 * @param Reason Reason for the KILL.
910 Kill_Nick(char *Nick, char *Reason)
914 assert (Nick != NULL);
915 assert (Reason != NULL);
922 Log(LOG_ERR, "User(s) with nick \"%s\" will be disconnected: %s",
925 IRC_KILL(Client_ThisServer(), &r);