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)
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 are allowed! */
424 if ((*ptr < '0' || *ptr > '9') &&
425 (*ptr < 'A' || *ptr > 'Z') &&
426 (*ptr < 'a' || *ptr > 'z')) {
427 Conn_Close(Client_Conn(Client), NULL,
428 "Invalid user name", true);
435 ptr = Client_User(Client);
436 if (!ptr || !*ptr || *ptr == '~')
437 Client_SetUser(Client, Req->argv[0], false);
439 Client_SetUser(Client, Req->argv[0], false);
441 Client_SetOrigUser(Client, Req->argv[0]);
443 /* "Real name" or user info text: Don't set it to the empty
444 * string, the original ircd can't deal with such "real names"
445 * (e. g. "USER user * * :") ... */
447 Client_SetInfo(Client, Req->argv[3]);
449 Client_SetInfo(Client, "-");
451 LogDebug("Connection %d: got valid USER command ...",
452 Client_Conn(Client));
453 if (Client_Type(Client) == CLIENT_GOTNICK)
454 return Login_User(Client);
456 Client_SetType(Client, CLIENT_GOTUSER);
459 } else if (Client_Type(Client) == CLIENT_SERVER ||
460 Client_Type(Client) == CLIENT_SERVICE) {
461 /* Server/service updating an user */
463 return IRC_WriteStrClient(Client,
464 ERR_NEEDMOREPARAMS_MSG,
467 c = Client_Search(Req->prefix);
469 return IRC_WriteStrClient(Client, ERR_NOSUCHNICK_MSG,
473 Client_SetUser(c, Req->argv[0], true);
474 Client_SetOrigUser(c, Req->argv[0]);
475 Client_SetHostname(c, Req->argv[1]);
476 Client_SetInfo(c, Req->argv[3]);
478 LogDebug("Connection %d: got valid USER command for \"%s\".",
479 Client_Conn(Client), Client_Mask(c));
481 /* RFC 1459 style user registration?
482 * Introduce client to network: */
483 if (Client_Type(c) == CLIENT_GOTNICK)
484 Client_Introduce(Client, c, CLIENT_USER);
487 } else if (Client_Type(Client) == CLIENT_USER) {
488 /* Already registered connection */
489 return IRC_WriteStrClient(Client, ERR_ALREADYREGISTRED_MSG,
492 /* Unexpected/invalid connection state? */
493 return IRC_WriteStrClient(Client, ERR_NOTREGISTERED_MSG,
500 * Handler for the IRC "SERVICE" command.
502 * This function implements IRC Services registration using the SERVICE command
503 * defined in RFC 2812 3.1.6 and RFC 2813 4.1.4.
505 * At the moment ngIRCd doesn't support directly linked services, so this
506 * function returns ERR_ERRONEUSNICKNAME when the SERVICE command has not been
507 * received from a peer server.
509 * @param Client The client from which this command has been received.
510 * @param Req Request structure with prefix and all parameters.
511 * @returns CONNECTED or DISCONNECTED..
514 IRC_SERVICE(CLIENT *Client, REQUEST *Req)
517 char *nick, *user, *host, *info, *modes, *ptr;
520 assert(Client != NULL);
523 if (Client_Type(Client) != CLIENT_GOTPASS &&
524 Client_Type(Client) != CLIENT_SERVER)
525 return IRC_WriteStrClient(Client, ERR_ALREADYREGISTRED_MSG,
529 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
530 Client_ID(Client), Req->command);
532 if (Client_Type(Client) != CLIENT_SERVER)
533 return IRC_WriteStrClient(Client, ERR_ERRONEUSNICKNAME_MSG,
534 Client_ID(Client), Req->argv[0]);
536 /* Bad number of parameters? */
538 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
539 Client_ID(Client), Req->command);
542 user = NULL; host = NULL;
543 token = atoi(Req->argv[1]);
544 hops = atoi(Req->argv[4]);
547 /* Validate service name ("nick name") */
548 c = Client_Search(nick);
550 /* Nick name collission: disconnect (KILL) both clients! */
551 Log(LOG_ERR, "Server %s introduces already registered service \"%s\"!",
552 Client_ID(Client), nick);
553 Kill_Nick(nick, "Nick collision");
557 /* Get the server to which the service is connected */
558 intr_c = Client_GetFromToken(Client, token);
560 Log(LOG_ERR, "Server %s introduces service \"%s\" on unknown server!?",
561 Client_ID(Client), nick);
562 Kill_Nick(nick, "Unknown server");
566 /* Get user and host name */
567 ptr = strchr(nick, '@');
573 host = Client_Hostname(intr_c);
574 ptr = strchr(nick, '!');
582 /* According to RFC 2812/2813 parameter 4 <type> "is currently reserved
583 * for future usage"; but we use it to transfer the modes and check
584 * that the first character is a '+' sign and ignore it otherwise. */
585 modes = (Req->argv[3][0] == '+') ? ++Req->argv[3] : "";
587 c = Client_NewRemoteUser(intr_c, nick, hops, user, host,
588 token, modes, info, true);
590 /* Couldn't create client structure, so KILL the service to
591 * keep network status consistent ... */
592 Log(LOG_ALERT, "Can't create client structure! (on connection %d)",
593 Client_Conn(Client));
594 Kill_Nick(nick, "Server error");
598 Client_Introduce(Client, c, CLIENT_SERVICE);
604 * Handler for the IRC "WEBIRC" command.
606 * See doc/Protocol.txt, section II.4:
607 * "Update webchat/proxy client information".
609 * @param Client The client from which this command has been received.
610 * @param Req Request structure with prefix and all parameters.
611 * @returns CONNECTED or DISCONNECTED.
614 IRC_WEBIRC(CLIENT *Client, REQUEST *Req)
616 /* Exactly 4 parameters are requited */
618 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
619 Client_ID(Client), Req->command);
621 if (!Conf_WebircPwd[0] || strcmp(Req->argv[0], Conf_WebircPwd) != 0)
622 return IRC_WriteStrClient(Client, ERR_PASSWDMISMATCH_MSG,
625 LogDebug("Connection %d: got valid WEBIRC command: user=%s, host=%s, ip=%s",
626 Client_Conn(Client), Req->argv[1], Req->argv[2], Req->argv[3]);
628 Client_SetUser(Client, Req->argv[1], true);
629 Client_SetOrigUser(Client, Req->argv[1]);
630 Client_SetHostname(Client, Req->argv[2]);
636 * Handler for the IRC "QUIT" command.
638 * See RFC 2812, 3.1.7 "Quit", and RFC 2813, 4.1.5 "Quit".
640 * @param Client The client from which this command has been received.
641 * @param Req Request structure with prefix and all parameters.
642 * @returns CONNECTED or DISCONNECTED.
645 IRC_QUIT( CLIENT *Client, REQUEST *Req )
648 char quitmsg[LINE_LEN];
650 assert(Client != NULL);
653 /* Wrong number of arguments? */
655 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
656 Client_ID(Client), Req->command);
659 strlcpy(quitmsg, Req->argv[0], sizeof quitmsg);
661 if (Client_Type(Client) == CLIENT_SERVER) {
663 target = Client_Search(Req->prefix);
666 "Got QUIT from %s for unknown client!?",
671 if (target != Client) {
672 Client_Destroy(target, "Got QUIT command.",
673 Req->argc == 1 ? quitmsg : NULL, true);
676 Conn_Close(Client_Conn(Client), "Got QUIT command.",
677 Req->argc == 1 ? quitmsg : NULL, true);
681 if (Req->argc == 1 && quitmsg[0] != '\"') {
682 /* " " to avoid confusion */
683 strlcpy(quitmsg, "\"", sizeof quitmsg);
684 strlcat(quitmsg, Req->argv[0], sizeof quitmsg-1);
685 strlcat(quitmsg, "\"", sizeof quitmsg );
688 /* User, Service, or not yet registered */
689 Conn_Close(Client_Conn(Client), "Got QUIT command.",
690 Req->argc == 1 ? quitmsg : NULL, true);
700 * Handler for HTTP command, e.g. GET and POST
702 * We handle these commands here to avoid the quite long timeout when
703 * some user tries to access this IRC daemon using an web browser ...
705 * @param Client The client from which this command has been received.
706 * @param Req Request structure with prefix and all parameters.
707 * @returns CONNECTED or DISCONNECTED.
710 IRC_QUIT_HTTP( CLIENT *Client, REQUEST *Req )
713 Req->argv[0] = "Oops, HTTP request received? This is IRC!";
714 return IRC_QUIT(Client, Req);
715 } /* IRC_QUIT_HTTP */
721 * Handler for the IRC "PING" command.
723 * See RFC 2812, 3.7.2 "Ping message".
725 * @param Client The client from which this command has been received.
726 * @param Req Request structure with prefix and all parameters.
727 * @returns CONNECTED or DISCONNECTED.
730 IRC_PING(CLIENT *Client, REQUEST *Req)
732 CLIENT *target, *from;
734 assert(Client != NULL);
738 return IRC_WriteStrClient(Client, ERR_NOORIGIN_MSG,
741 /* Don't ignore additional arguments when in "strict" mode */
743 return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
744 Client_ID(Client), Req->command);
748 /* A target has been specified ... */
749 target = Client_Search(Req->argv[1]);
751 if (!target || Client_Type(target) != CLIENT_SERVER)
752 return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
753 Client_ID(Client), Req->argv[1]);
755 if (target != Client_ThisServer()) {
756 /* Ok, we have to forward the PING */
757 if (Client_Type(Client) == CLIENT_SERVER)
758 from = Client_Search(Req->prefix);
762 return IRC_WriteStrClient(Client,
763 ERR_NOSUCHSERVER_MSG,
764 Client_ID(Client), Req->prefix);
766 return IRC_WriteStrClientPrefix(target, from,
767 "PING %s :%s", Req->argv[0],
772 if (Client_Type(Client) == CLIENT_SERVER) {
774 from = Client_Search(Req->prefix);
778 from = Client_ThisServer();
780 return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
781 Client_ID(Client), Req->prefix);
783 Log(LOG_DEBUG, "Connection %d: got PING, sending PONG ...",
784 Client_Conn(Client));
787 return IRC_WriteStrClient(Client, "PONG %s :%s",
788 Client_ID(from), Client_ID(Client));
790 /* Some clients depend on the argument being returned in the PONG
791 * reply (not mentioned in any RFC, though) */
792 return IRC_WriteStrClient(Client, "PONG %s :%s",
793 Client_ID(from), Req->argv[0]);
799 * Handler for the IRC "PONG" command.
801 * See RFC 2812, 3.7.3 "Pong message".
803 * @param Client The client from which this command has been received.
804 * @param Req Request structure with prefix and all parameters.
805 * @returns CONNECTED or DISCONNECTED.
808 IRC_PONG(CLIENT *Client, REQUEST *Req)
810 CLIENT *target, *from;
817 assert(Client != NULL);
820 /* Wrong number of arguments? */
822 if (Client_Type(Client) == CLIENT_USER)
823 return IRC_WriteStrClient(Client, ERR_NOORIGIN_MSG,
829 if (Client_Type(Client) == CLIENT_USER)
830 return IRC_WriteStrClient(Client,
831 ERR_NEEDMOREPARAMS_MSG,
839 if (Req->argc == 2 && Client_Type(Client) == CLIENT_SERVER) {
840 target = Client_Search(Req->argv[0]);
842 return IRC_WriteStrClient(Client, ERR_NOSUCHSERVER_MSG,
843 Client_ID(Client), Req->argv[0]);
845 from = Client_Search(Req->prefix);
847 if (target != Client_ThisServer() && target != from) {
848 /* Ok, we have to forward the message. */
850 return IRC_WriteStrClient(Client,
851 ERR_NOSUCHSERVER_MSG,
852 Client_ID(Client), Req->prefix);
854 if (Client_Type(Client_NextHop(target)) != CLIENT_SERVER)
858 return IRC_WriteStrClientPrefix(target, from,
859 "PONG %s :%s", s, Req->argv[1]);
863 /* The connection timestamp has already been updated when the data has
864 * been read from so socket, so we don't need to update it here. */
866 conn = Client_Conn(Client);
869 /* Check authentication PING-PONG ... */
870 auth_ping = Conn_GetAuthPing(conn);
872 LogDebug("AUTH PONG: waiting for token \"%ld\", got \"%s\" ...",
873 auth_ping, Req->argv[0]);
874 if (auth_ping == atoi(Req->argv[0])) {
875 Conn_SetAuthPing(conn, 0);
876 if (Client_Type(Client) == CLIENT_WAITAUTHPING)
879 if (!IRC_WriteStrClient(Client,
880 "To connect, type /QUOTE PONG %ld",
886 if (Client_Type(Client) == CLIENT_SERVER && Conn_LastPing(conn) == 0) {
888 "Synchronization with \"%s\" done (connection %d): %ld seconds [%ld users, %ld channels]",
889 Client_ID(Client), conn, time(NULL) - Conn_GetSignon(conn),
890 Client_UserCount(), Channel_CountVisible(NULL));
891 Conn_UpdatePing(conn);
893 LogDebug("Connection %d: received PONG. Lag: %ld seconds.",
894 conn, time(NULL) - Conn_LastPing(conn));
901 * Kill all users with a specific nick name in the network.
903 * @param Nick Nick name.
904 * @param Reason Reason for the KILL.
907 Kill_Nick(char *Nick, char *Reason)
911 assert (Nick != NULL);
912 assert (Reason != NULL);
919 Log(LOG_ERR, "User(s) with nick \"%s\" will be disconnected: %s",
922 IRC_KILL(Client_ThisServer(), &r);