1 /*
2  *  ircd-ratbox: A slightly useful ircd.
3  *  client.c: Controls clients.
4  *
5  *  Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6  *  Copyright (C) 1996-2002 Hybrid Development Team
7  *  Copyright (C) 2002-2005 ircd-ratbox development team
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
22  *  USA
23  *
24  *  $Id: client.c 26539 2009-05-14 22:34:30Z androsyn $
25  */
26 #include "ratbox_lib.h"
27 #include "stdinc.h"
28 #include "struct.h"
29 #include "client.h"
30 #include "channel.h"
31 #include "class.h"
32 #include "hash.h"
33 #include "match.h"
34 #include "ircd.h"
35 #include "s_gline.h"
36 #include "numeric.h"
37 #include "packet.h"
38 #include "s_auth.h"
39 #include "s_conf.h"
40 #include "s_newconf.h"
41 #include "s_log.h"
42 #include "s_serv.h"
43 #include "s_stats.h"
44 #include "send.h"
45 #include "whowas.h"
46 #include "s_user.h"
47 #include "hash.h"
48 #include "hostmask.h"
49 #include "listener.h"
50 #include "reject.h"
51 #include "hook.h"
52 #include "monitor.h"
53 #include "parse.h"
54 #include "sslproc.h"
55 
56 #define DEBUG_EXITED_CLIENTS
57 
58 static void check_pings_list(rb_dlink_list *list);
59 static void check_unknowns_list(rb_dlink_list *list);
60 static void free_exited_clients(void *unused);
61 static void exit_aborted_clients(void *unused);
62 
63 static int exit_remote_client(struct Client *, struct Client *, struct Client *, const char *);
64 static int exit_remote_server(struct Client *, struct Client *, struct Client *, const char *);
65 static int exit_local_client(struct Client *, struct Client *, struct Client *, const char *);
66 static int exit_unknown_client(struct Client *, struct Client *, const char *);
67 static int exit_local_server(struct Client *, struct Client *, struct Client *, const char *);
68 static int qs_server(struct Client *);
69 
70 static EVH check_pings;
71 
72 static rb_bh *client_heap = NULL;
73 static rb_bh *lclient_heap = NULL;
74 static rb_bh *user_heap = NULL;
75 static rb_bh *away_heap = NULL;
76 static char current_uid[IDLEN];
77 
78 
79 rb_dlink_list dead_list;
80 #ifdef DEBUG_EXITED_CLIENTS
81 static rb_dlink_list dead_remote_list;
82 #endif
83 
84 struct abort_client
85 {
86 	rb_dlink_node node;
87 	struct Client *client;
88 	char notice[REASONLEN];
89 };
90 
91 static rb_dlink_list abort_list;
92 
93 
94 /*
95  * init_client
96  *
97  * inputs	- NONE
98  * output	- NONE
99  * side effects	- initialize client free memory
100  */
101 void
init_client(void)102 init_client(void)
103 {
104 	/*
105 	 * start off the check ping event ..  -- adrian
106 	 * Every 30 seconds is plenty -- db
107 	 */
108 	client_heap = rb_bh_create(sizeof(struct Client), CLIENT_HEAP_SIZE, "client_heap");
109 	lclient_heap = rb_bh_create(sizeof(struct LocalUser), LCLIENT_HEAP_SIZE, "lclient_heap");
110 	user_heap = rb_bh_create(sizeof(struct User), USER_HEAP_SIZE, "user_heap");
111 	away_heap = rb_bh_create(AWAYLEN, AWAY_HEAP_SIZE, "away_heap");
112 	rb_event_addish("check_pings", check_pings, NULL, 30);
113 	rb_event_addish("free_exited_clients", &free_exited_clients, NULL, 5);
114 	rb_event_addish("exit_aborted_clients", exit_aborted_clients, NULL, 5);
115 	rb_event_add("flood_recalc", flood_recalc, NULL, 1);
116 }
117 
118 
119 /*
120  * make_client - create a new Client struct and set it to initial state.
121  *
122  *      from == NULL,   create local client (a client connected
123  *                      to a socket).
124  *
125  *      from,   create remote client (behind a socket
126  *                      associated with the client defined by
127  *                      'from'). ('from' is a local client!!).
128  */
129 struct Client *
make_client(struct Client * from)130 make_client(struct Client *from)
131 {
132 	struct Client *client_p = NULL;
133 	struct LocalUser *localClient;
134 
135 	client_p = rb_bh_alloc(client_heap);
136 
137 	if(from == NULL)
138 	{
139 		client_p->from = client_p;	/* 'from' of local client is self! */
140 
141 		localClient = rb_bh_alloc(lclient_heap);
142 		SetMyConnect(client_p);
143 		client_p->localClient = localClient;
144 
145 		client_p->localClient->lasttime = client_p->localClient->firsttime =
146 			rb_current_time();
147 
148 		client_p->localClient->F = NULL;
149 
150 		/* as good a place as any... */
151 		rb_dlinkAdd(client_p, &client_p->localClient->tnode, &unknown_list);
152 	}
153 	else
154 	{			/* from is not NULL */
155 		client_p->localClient = NULL;
156 		client_p->from = from;	/* 'from' of local client is self! */
157 	}
158 
159 	SetUnknown(client_p);
160 	strcpy(client_p->username, "unknown");
161 
162 	return client_p;
163 }
164 
165 static void
free_local_client(struct Client * client_p)166 free_local_client(struct Client *client_p)
167 {
168 	s_assert(NULL != client_p);
169 	s_assert(&me != client_p);
170 
171 	if(client_p->localClient == NULL)
172 		return;
173 
174 	/*
175 	 * clean up extra sockets from P-lines which have been discarded.
176 	 */
177 	if(client_p->localClient->listener)
178 	{
179 		s_assert(0 < client_p->localClient->listener->ref_count);
180 		if(0 == --client_p->localClient->listener->ref_count
181 		   && !client_p->localClient->listener->active)
182 			free_listener(client_p->localClient->listener);
183 		client_p->localClient->listener = 0;
184 	}
185 
186 	if(client_p->localClient->F != NULL)
187 	{
188 		del_from_cli_fd_hash(client_p);
189 		rb_close(client_p->localClient->F);
190 	}
191 
192 	if(client_p->localClient->passwd)
193 	{
194 		memset(client_p->localClient->passwd, 0, strlen(client_p->localClient->passwd));
195 		rb_free(client_p->localClient->passwd);
196 	}
197 
198 	rb_free(client_p->localClient->chal_resp);
199 	rb_free(client_p->localClient->fullcaps);
200 	rb_free(client_p->localClient->opername);
201 
202 	if(IsSSL(client_p))
203         	ssld_decrement_clicount(client_p->localClient->ssl_ctl);
204 
205 	if(IsCapable(client_p, CAP_ZIP))
206 		ssld_decrement_clicount(client_p->localClient->z_ctl);
207 	/* not needed per-se, but in case start_auth_query never gets called... */
208 	rb_free(client_p->localClient->lip);
209 
210 	rb_bh_free(lclient_heap, client_p->localClient);
211 	client_p->localClient = NULL;
212 }
213 
214 void
free_client(struct Client * client_p)215 free_client(struct Client *client_p)
216 {
217 	s_assert(NULL != client_p);
218 	s_assert(&me != client_p);
219 	free_local_client(client_p);
220 	rb_bh_free(client_heap, client_p);
221 }
222 
223 /*
224  * check_pings - go through the local client list and check activity
225  * kill off stuff that should die
226  *
227  * inputs       - NOT USED (from event)
228  * output       - next time_t when check_pings() should be called again
229  * side effects -
230  *
231  *
232  * A PING can be sent to clients as necessary.
233  *
234  * Client/Server ping outs are handled.
235  */
236 
237 /*
238  * Addon from adrian. We used to call this after nextping seconds,
239  * however I've changed it to run once a second. This is only for
240  * PING timeouts, not K/etc-line checks (thanks dianora!). Having it
241  * run once a second makes life a lot easier - when a new client connects
242  * and they need a ping in 4 seconds, if nextping was set to 20 seconds
243  * we end up waiting 20 seconds. This is stupid. :-)
244  * I will optimise (hah!) check_pings() once I've finished working on
245  * tidying up other network IO evilnesses.
246  *     -- adrian
247  */
248 
249 static void
check_pings(void * notused)250 check_pings(void *notused)
251 {
252 	check_pings_list(&lclient_list);
253 	check_pings_list(&serv_list);
254 	check_unknowns_list(&unknown_list);
255 }
256 
257 /*
258  * Check_pings_list()
259  *
260  * inputs	- pointer to list to check
261  * output	- NONE
262  * side effects	-
263  */
264 static void
check_pings_list(rb_dlink_list * list)265 check_pings_list(rb_dlink_list *list)
266 {
267 	char scratch[32];	/* way too generous but... */
268 	struct Client *client_p;	/* current local client_p being examined */
269 	int ping = 0;		/* ping time value from client */
270 	rb_dlink_node *ptr, *next_ptr;
271 
272 	RB_DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
273 	{
274 		client_p = ptr->data;
275 
276 		/*
277 		 ** Note: No need to notify opers here. It's
278 		 ** already done when "FLAGS_DEADSOCKET" is set.
279 		 */
280 		if(!MyConnect(client_p) || IsDead(client_p))
281 			continue;
282 
283 		if(!IsRegistered(client_p))
284 			ping = ConfigFileEntry.connect_timeout;
285 		else
286 			ping = get_client_ping(client_p);
287 
288 		if(ping < (rb_current_time() - client_p->localClient->lasttime))
289 		{
290 			/*
291 			 * If the client/server hasnt talked to us in 2*ping seconds
292 			 * and it has a ping time, then close its connection.
293 			 */
294 			if(((rb_current_time() - client_p->localClient->lasttime) >= (2 * ping)
295 			    && (client_p->flags & FLAGS_PINGSENT)))
296 			{
297 				if(IsAnyServer(client_p))
298 				{
299 					sendto_realops_flags(UMODE_ALL, L_ALL,
300 							     "No response from %s, closing link",
301 							     client_p->name);
302 					ilog(L_SERVER,
303 					     "No response from %s, closing link",
304 					     log_client_name(client_p, HIDE_IP));
305 				}
306 				(void)rb_snprintf(scratch, sizeof(scratch),
307 						  "Ping timeout: %d seconds",
308 						  (int)(rb_current_time() -
309 							client_p->localClient->lasttime));
310 
311 				exit_client(client_p, client_p, &me, scratch);
312 				continue;
313 			}
314 			else if((client_p->flags & FLAGS_PINGSENT) == 0)
315 			{
316 				/*
317 				 * if we havent PINGed the connection and we havent
318 				 * heard from it in a while, PING it to make sure
319 				 * it is still alive.
320 				 */
321 				client_p->flags |= FLAGS_PINGSENT;
322 				/* not nice but does the job */
323 				client_p->localClient->lasttime = rb_current_time() - ping;
324 				sendto_one(client_p, "PING :%s", me.name);
325 			}
326 		}
327 		/* ping_timeout: */
328 
329 	}
330 }
331 
332 /*
333  * check_unknowns_list
334  *
335  * inputs	- pointer to list of unknown clients
336  * output	- NONE
337  * side effects	- unknown clients get marked for termination after n seconds
338  */
339 static void
check_unknowns_list(rb_dlink_list * list)340 check_unknowns_list(rb_dlink_list *list)
341 {
342 	rb_dlink_node *ptr, *next_ptr;
343 	struct Client *client_p;
344 
345 	RB_DLINK_FOREACH_SAFE(ptr, next_ptr, list->head)
346 	{
347 		client_p = ptr->data;
348 
349 		if(IsDead(client_p) || IsClosing(client_p))
350 			continue;
351 
352 		/*
353 		 * Check UNKNOWN connections - if they have been in this state
354 		 * for > 30s, close them.
355 		 */
356 
357 		if((rb_current_time() - client_p->localClient->firsttime) > 30)
358 			exit_client(client_p, client_p, &me, "Connection timed out");
359 	}
360 }
361 
362 void
notify_banned_client(struct Client * client_p,struct ConfItem * aconf,int ban)363 notify_banned_client(struct Client *client_p, struct ConfItem *aconf, int ban)
364 {
365 	static const char conn_closed[] = "Connection closed";
366 	static const char d_lined[] = "D-lined";
367 	static const char k_lined[] = "K-lined";
368 	static const char g_lined[] = "G-lined";
369 	const char *reason = NULL;
370 	const char *exit_reason = conn_closed;
371 
372 	if(ConfigFileEntry.kline_with_reason && !EmptyString(aconf->passwd))
373 	{
374 		reason = aconf->passwd;
375 		exit_reason = aconf->passwd;
376 	}
377 	else
378 	{
379 		switch (aconf->status)
380 		{
381 		case D_LINED:
382 			reason = d_lined;
383 			break;
384 		case G_LINED:
385 			reason = g_lined;
386 			break;
387 		default:
388 			reason = k_lined;
389 			break;
390 		}
391 	}
392 
393 	if(ban == D_LINED && !IsClient(client_p))
394 		sendto_one(client_p, "NOTICE DLINE :*** You have been D-lined");
395 	else
396 		sendto_one(client_p, form_str(ERR_YOUREBANNEDCREEP),
397 			   me.name, client_p->name, reason);
398 
399 	exit_client(client_p, client_p, &me,
400 		    EmptyString(ConfigFileEntry.kline_reason) ? exit_reason :
401 		    ConfigFileEntry.kline_reason);
402 }
403 
404 /*
405  * check_banned_lines
406  * inputs	- NONE
407  * output	- NONE
408  * side effects - Check all connections for a pending k/d/gline against the
409  * 		  client, exit the client if found.
410  */
411 void
check_banned_lines(void)412 check_banned_lines(void)
413 {
414 	struct Client *client_p;	/* current local client_p being examined */
415 	struct ConfItem *aconf = NULL;
416 	rb_dlink_node *ptr, *next_ptr;
417 
418 	RB_DLINK_FOREACH_SAFE(ptr, next_ptr, lclient_list.head)
419 	{
420 		client_p = ptr->data;
421 
422 		if(IsMe(client_p))
423 			continue;
424 
425 		/* if there is a returned struct ConfItem then kill it */
426 		if((aconf = find_dline((struct sockaddr *)&client_p->localClient->ip)))
427 		{
428 			if(aconf->status & CONF_EXEMPTDLINE)
429 				continue;
430 
431 			sendto_realops_flags(UMODE_ALL, L_ALL,
432 					     "DLINE active for %s",
433 					     get_client_name(client_p, HIDE_IP));
434 
435 			notify_banned_client(client_p, aconf, D_LINED);
436 			continue;	/* and go examine next fd/client_p */
437 		}
438 
439 		if(!IsClient(client_p))
440 			continue;
441 
442 		if((aconf = find_kline(client_p)) != NULL)
443 		{
444 			if(IsExemptKline(client_p))
445 			{
446 				sendto_realops_flags(UMODE_ALL, L_ALL,
447 						     "KLINE over-ruled for %s, client is kline_exempt [%s@%s]",
448 						     get_client_name(client_p, HIDE_IP),
449 						     aconf->user, aconf->host);
450 				continue;
451 			}
452 
453 			sendto_realops_flags(UMODE_ALL, L_ALL,
454 					     "KLINE active for %s",
455 					     get_client_name(client_p, HIDE_IP));
456 			notify_banned_client(client_p, aconf, K_LINED);
457 			continue;
458 		}
459 		else if((aconf = find_gline(client_p)) != NULL)
460 		{
461 			if(IsExemptKline(client_p))
462 			{
463 				sendto_realops_flags(UMODE_ALL, L_ALL,
464 						     "GLINE over-ruled for %s, client is kline_exempt [%s@%s]",
465 						     get_client_name(client_p, HIDE_IP),
466 						     aconf->user, aconf->host);
467 				continue;
468 			}
469 
470 			if(IsExemptGline(client_p))
471 			{
472 				sendto_realops_flags(UMODE_ALL, L_ALL,
473 						     "GLINE over-ruled for %s, client is gline_exempt [%s@%s]",
474 						     get_client_name(client_p, HIDE_IP),
475 						     aconf->user, aconf->host);
476 				continue;
477 			}
478 
479 			sendto_realops_flags(UMODE_ALL, L_ALL,
480 					     "GLINE active for %s",
481 					     get_client_name(client_p, HIDE_IP));
482 
483 			notify_banned_client(client_p, aconf, G_LINED);
484 			continue;
485 		}
486 		else if((aconf = find_xline(client_p->info, 1)) != NULL)
487 		{
488 			if(IsExemptKline(client_p))
489 			{
490 				sendto_realops_flags(UMODE_ALL, L_ALL,
491 						     "XLINE over-ruled for %s, client is kline_exempt [%s]",
492 						     get_client_name(client_p, HIDE_IP),
493 						     aconf->info.oper);
494 				continue;
495 			}
496 
497 			sendto_realops_flags(UMODE_ALL, L_ALL, "XLINE active for %s",
498 					     get_client_name(client_p, HIDE_IP));
499 
500 			(void)exit_client(client_p, client_p, &me, "Bad user info");
501 			continue;
502 		}
503 	}
504 
505 	/* also check the unknowns list for new dlines */
506 	RB_DLINK_FOREACH_SAFE(ptr, next_ptr, unknown_list.head)
507 	{
508 		client_p = ptr->data;
509 
510 		if((aconf = find_dline((struct sockaddr *)&client_p->localClient->ip)))
511 		{
512 			if(aconf->status & CONF_EXEMPTDLINE)
513 				continue;
514 
515 			notify_banned_client(client_p, aconf, D_LINED);
516 		}
517 	}
518 
519 }
520 
521 /* check_klines_event()
522  *
523  * inputs	-
524  * outputs	-
525  * side effects - check_klines() is called, kline_queued unset
526  */
527 void
check_klines_event(void * unused)528 check_klines_event(void *unused)
529 {
530 	kline_queued = 0;
531 	check_klines();
532 }
533 
534 /* check_klines
535  *
536  * inputs       -
537  * outputs      -
538  * side effects - all clients will be checked for klines
539  */
540 void
check_klines(void)541 check_klines(void)
542 {
543 	struct Client *client_p;
544 	struct ConfItem *aconf;
545 	rb_dlink_node *ptr;
546 	rb_dlink_node *next_ptr;
547 
548 	RB_DLINK_FOREACH_SAFE(ptr, next_ptr, lclient_list.head)
549 	{
550 		client_p = ptr->data;
551 
552 		if(IsMe(client_p) || !IsClient(client_p))
553 			continue;
554 
555 		if((aconf = find_kline(client_p)) != NULL)
556 		{
557 			if(IsExemptKline(client_p))
558 			{
559 				sendto_realops_flags(UMODE_ALL, L_ALL,
560 						     "KLINE over-ruled for %s, client is kline_exempt",
561 						     get_client_name(client_p, HIDE_IP));
562 				continue;
563 			}
564 
565 			sendto_realops_flags(UMODE_ALL, L_ALL,
566 					     "KLINE active for %s",
567 					     get_client_name(client_p, HIDE_IP));
568 
569 			notify_banned_client(client_p, aconf, K_LINED);
570 			continue;
571 		}
572 	}
573 }
574 
575 /*
576  * update_client_exit_stats
577  *
578  * input	- pointer to client
579  * output	- NONE
580  * side effects	-
581  */
582 static void
update_client_exit_stats(struct Client * client_p)583 update_client_exit_stats(struct Client *client_p)
584 {
585 	if(IsServer(client_p))
586 	{
587 		sendto_realops_flags(UMODE_EXTERNAL, L_ALL,
588 				     "Server %s split from %s",
589 				     client_p->name, client_p->servptr->name);
590 		if(HasSentEob(client_p))
591 			eob_count--;
592 	}
593 	else if(IsClient(client_p))
594 	{
595 		--Count.total;
596 		if(IsOper(client_p))
597 			--Count.oper;
598 		if(IsInvisible(client_p))
599 			--Count.invisi;
600 	}
601 
602 	if(splitchecking && !splitmode)
603 		check_splitmode(NULL);
604 }
605 
606 /*
607  * release_client_state
608  *
609  * input	- pointer to client to release
610  * output	- NONE
611  * side effects	-
612  */
613 static void
release_client_state(struct Client * client_p)614 release_client_state(struct Client *client_p)
615 {
616 	if(client_p->user != NULL)
617 	{
618 		free_user(client_p->user, client_p);	/* try this here */
619 	}
620 	if(client_p->serv)
621 	{
622 		if(client_p->serv->fullcaps)
623 			rb_free(client_p->serv->fullcaps);
624 		rb_free(client_p->serv);
625 	}
626 }
627 
628 /*
629  * remove_client_from_list
630  * inputs	- point to client to remove
631  * output	- NONE
632  * side effects - taken the code from ExitOneClient() for this
633  *		  and placed it here. - avalon
634  */
635 static void
remove_client_from_list(struct Client * client_p)636 remove_client_from_list(struct Client *client_p)
637 {
638 	s_assert(NULL != client_p);
639 
640 	if(client_p == NULL)
641 		return;
642 
643 	/* A client made with make_client()
644 	 * is on the unknown_list until removed.
645 	 * If it =does= happen to exit before its removed from that list
646 	 * and its =not= on the global_client_list, it will core here.
647 	 * short circuit that case now -db
648 	 */
649 	if(client_p->node.prev == NULL && client_p->node.next == NULL)
650 		return;
651 
652 	rb_dlinkDelete(&client_p->node, &global_client_list);
653 
654 	update_client_exit_stats(client_p);
655 }
656 
657 
658 /*
659  * find_person	- find person by (nick)name.
660  * inputs	- pointer to name
661  * output	- return client pointer
662  * side effects -
663  */
664 struct Client *
find_person(const char * name)665 find_person(const char *name)
666 {
667 	struct Client *c2ptr;
668 
669 	c2ptr = find_client(name);
670 
671 	if(c2ptr && IsClient(c2ptr))
672 		return (c2ptr);
673 	return (NULL);
674 }
675 
676 struct Client *
find_named_person(const char * name)677 find_named_person(const char *name)
678 {
679 	struct Client *c2ptr;
680 
681 	c2ptr = find_named_client(name);
682 
683 	if(c2ptr && IsClient(c2ptr))
684 		return (c2ptr);
685 	return (NULL);
686 }
687 
688 
689 /*
690  * find_chasing - find the client structure for a nick name (user)
691  *      using history mechanism if necessary. If the client is not found,
692  *      an error message (NO SUCH NICK) is generated. If the client was found
693  *      through the history, chasing will be 1 and otherwise 0.
694  */
695 struct Client *
find_chasing(struct Client * source_p,const char * user,int * chasing)696 find_chasing(struct Client *source_p, const char *user, int *chasing)
697 {
698 	struct Client *who;
699 
700 	if(MyClient(source_p))
701 		who = find_named_person(user);
702 	else
703 		who = find_person(user);
704 
705 	if(chasing)
706 		*chasing = 0;
707 
708 	if(who || IsDigit(*user))
709 		return who;
710 
711 	if(!(who = get_history(user, (long)KILLCHASETIMELIMIT)))
712 	{
713 		sendto_one_numeric(source_p, ERR_NOSUCHNICK, form_str(ERR_NOSUCHNICK), user);
714 		return (NULL);
715 	}
716 	if(chasing)
717 		*chasing = 1;
718 	return who;
719 }
720 
721 /*
722  * get_client_name -  Return the name of the client
723  *    for various tracking and
724  *      admin purposes. The main purpose of this function is to
725  *      return the "socket host" name of the client, if that
726  *        differs from the advertised name (other than case).
727  *        But, this can be used to any client structure.
728  *
729  * NOTE 1:
730  *        Watch out the allocation of "nbuf", if either source_p->name
731  *        or source_p->sockhost gets changed into pointers instead of
732  *        directly allocated within the structure...
733  *
734  * NOTE 2:
735  *        Function return either a pointer to the structure (source_p) or
736  *        to internal buffer (nbuf). *NEVER* use the returned pointer
737  *        to modify what it points!!!
738  */
739 
740 const char *
get_client_name(struct Client * client,int showip)741 get_client_name(struct Client *client, int showip)
742 {
743 	static char empty_name[] = "";
744 	static char nbuf[HOSTLEN * 2 + USERLEN + 5];
745 	const char *name;
746 
747 	s_assert(NULL != client);
748 	if(client == NULL)
749 		return NULL;
750 
751 	if(MyConnect(client))
752 	{
753 		if(EmptyString(client->name))
754 			name = empty_name;
755 		else
756 			name = client->name;
757 
758 		if(!irccmp(name, client->host))
759 			return name;
760 
761 		if(ConfigFileEntry.hide_spoof_ips && showip == SHOW_IP && IsIPSpoof(client))
762 			showip = MASK_IP;
763 		if(IsAnyServer(client))
764 			showip = MASK_IP;
765 
766 		/* And finally, let's get the host information, ip or name */
767 		switch (showip)
768 		{
769 		case SHOW_IP:
770 			rb_snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]",
771 				    name, client->username, client->sockhost);
772 			break;
773 		case MASK_IP:
774 			rb_snprintf(nbuf, sizeof(nbuf), "%s[%s@255.255.255.255]",
775 				    name, client->username);
776 			break;
777 		default:
778 			rb_snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]",
779 				    name, client->username, client->host);
780 		}
781 		return nbuf;
782 	}
783 
784 	/* As pointed out by Adel Mezibra
785 	 * Neph|l|m@EFnet. Was missing a return here.
786 	 */
787 	return client->name;
788 }
789 
790 /* log_client_name()
791  *
792  * This version is the same as get_client_name, but doesnt contain the
793  * code that will hide IPs always.  This should be used for logfiles.
794  */
795 const char *
log_client_name(struct Client * target_p,int showip)796 log_client_name(struct Client *target_p, int showip)
797 {
798 	static const char empty_name[] = "";
799 	static char nbuf[HOSTLEN * 2 + USERLEN + 5];
800 	const char *name;
801 
802 	if(target_p == NULL)
803 		return NULL;
804 
805 	if(EmptyString(target_p->name))
806 		name = empty_name;
807 	else
808 		name = target_p->name;
809 
810 	if(MyConnect(target_p))
811 	{
812 		if(irccmp(name, target_p->host) == 0)
813 			return name;
814 
815 		switch (showip)
816 		{
817 		case SHOW_IP:
818 			rb_snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]", name,
819 				    target_p->username, target_p->sockhost);
820 			break;
821 
822 		case MASK_IP:
823 			rb_snprintf(nbuf, sizeof(nbuf), "%s[%s@255.255.255.255]",
824 				    name, target_p->username);
825 
826 		default:
827 			rb_snprintf(nbuf, sizeof(nbuf), "%s[%s@%s]", name,
828 				    target_p->username, target_p->host);
829 		}
830 
831 		return nbuf;
832 	}
833 
834 	return name;
835 }
836 
837 static void
free_exited_clients(void * unused)838 free_exited_clients(void *unused)
839 {
840 	rb_dlink_node *ptr, *next;
841 	struct Client *target_p;
842 
843 	RB_DLINK_FOREACH_SAFE(ptr, next, dead_list.head)
844 	{
845 		target_p = ptr->data;
846 
847 #ifdef DEBUG_EXITED_CLIENTS
848 		{
849 			struct abort_client *abt;
850 			rb_dlink_node *aptr;
851 			int found = 0;
852 
853 			RB_DLINK_FOREACH(aptr, abort_list.head)
854 			{
855 				abt = aptr->data;
856 				if(abt->client == target_p)
857 				{
858 					s_assert(0);
859 					sendto_realops_flags(UMODE_ALL, L_ALL,
860 							     "On abort_list: %s stat: %u flags: %u/%u handler: %c",
861 							     target_p->name,
862 							     (unsigned int)target_p->status,
863 							     target_p->flags, target_p->operflags,
864 							     target_p->handler);
865 					sendto_realops_flags(UMODE_ALL, L_ALL,
866 							     "Please report this to the ratbox developers!");
867 					found++;
868 				}
869 			}
870 
871 			if(found)
872 			{
873 				rb_dlinkDestroy(ptr, &dead_list);
874 				continue;
875 			}
876 		}
877 #endif
878 
879 		if(ptr->data == NULL)
880 		{
881 			sendto_realops_flags(UMODE_ALL, L_ALL,
882 					     "Warning: null client on dead_list!");
883 			rb_dlinkDestroy(ptr, &dead_list);
884 			continue;
885 		}
886 		release_client_state(target_p);
887 		free_client(target_p);
888 		rb_dlinkDestroy(ptr, &dead_list);
889 	}
890 
891 #ifdef DEBUG_EXITED_CLIENTS
892 	RB_DLINK_FOREACH_SAFE(ptr, next, dead_remote_list.head)
893 	{
894 		target_p = ptr->data;
895 
896 		if(ptr->data == NULL)
897 		{
898 			sendto_realops_flags(UMODE_ALL, L_ALL,
899 					     "Warning: null client on dead_list!");
900 			rb_dlinkDestroy(ptr, &dead_list);
901 			continue;
902 		}
903 		release_client_state(target_p);
904 		free_client(target_p);
905 		rb_dlinkDestroy(ptr, &dead_remote_list);
906 	}
907 #endif
908 
909 }
910 
911 /*
912 ** Recursively send QUITs and SQUITs for source_p and all its dependent clients
913 ** and servers to those servers that need them.  A server needs the client
914 ** QUITs if it can't figure them out from the SQUIT (ie pre-TS4) or if it
915 ** isn't getting the SQUIT because of @#(*&@)# hostmasking.  With TS4, once
916 ** a link gets a SQUIT, it doesn't need any QUIT/SQUITs for clients depending
917 ** on that one -orabidoo
918 */
919 static void
recurse_send_quits(struct Client * client_p,struct Client * source_p,struct Client * to,const char * comment1,const char * comment)920 recurse_send_quits(struct Client *client_p, struct Client *source_p,
921 		   struct Client *to, const char *comment1, const char *comment)
922 {
923 	struct Client *target_p;
924 	rb_dlink_node *ptr, *ptr_next;
925 	/* If this server can handle quit storm (QS) removal
926 	 * of dependents, just send the SQUIT
927 	 */
928 
929 	if(IsCapable(to, CAP_QS))
930 	{
931 		sendto_one(to, "SQUIT %s :%s", get_id(source_p, to), comment);
932 	}
933 	else
934 	{
935 		RB_DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->serv->users.head)
936 		{
937 			target_p = ptr->data;
938 			sendto_one(to, ":%s QUIT :%s", target_p->name, comment1);
939 		}
940 		RB_DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->serv->servers.head)
941 		{
942 			target_p = ptr->data;
943 			recurse_send_quits(client_p, target_p, to, comment1, comment);
944 		}
945 		sendto_one(to, "SQUIT %s :%s", source_p->name, comment);
946 	}
947 }
948 
949 /*
950 ** Remove all clients that depend on source_p; assumes all (S)QUITs have
951 ** already been sent.  we make sure to exit a server's dependent clients
952 ** and servers before the server itself; exit_one_client takes care of
953 ** actually removing things off llists.   tweaked from +CSr31  -orabidoo
954 */
955 /*
956  * added sanity test code.... source_p->serv might be NULL...
957  */
958 static void
recurse_remove_clients(struct Client * source_p,const char * comment)959 recurse_remove_clients(struct Client *source_p, const char *comment)
960 {
961 	struct Client *target_p;
962 	rb_dlink_node *ptr, *ptr_next;
963 
964 	if(IsMe(source_p))
965 		return;
966 
967 	if(source_p->serv == NULL)	/* oooops. uh this is actually a major bug */
968 		return;
969 
970 	/* this is very ugly, but it saves cpu :P */
971 	if(ConfigFileEntry.nick_delay > 0)
972 	{
973 		RB_DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->serv->users.head)
974 		{
975 			target_p = ptr->data;
976 			target_p->flags |= FLAGS_KILLED;
977 			add_nd_entry(target_p->name);
978 
979 			if(!IsDead(target_p) && !IsClosing(target_p))
980 				exit_remote_client(NULL, target_p, &me, comment);
981 		}
982 	}
983 	else
984 	{
985 		RB_DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->serv->users.head)
986 		{
987 			target_p = ptr->data;
988 			target_p->flags |= FLAGS_KILLED;
989 
990 			if(!IsDead(target_p) && !IsClosing(target_p))
991 				exit_remote_client(NULL, target_p, &me, comment);
992 		}
993 	}
994 
995 	RB_DLINK_FOREACH_SAFE(ptr, ptr_next, source_p->serv->servers.head)
996 	{
997 		target_p = ptr->data;
998 		recurse_remove_clients(target_p, comment);
999 		qs_server(target_p);
1000 	}
1001 }
1002 
1003 /*
1004 ** Remove *everything* that depends on source_p, from all lists, and sending
1005 ** all necessary QUITs and SQUITs.  source_p itself is still on the lists,
1006 ** and its SQUITs have been sent except for the upstream one  -orabidoo
1007 */
1008 static void
remove_dependents(struct Client * client_p,struct Client * source_p,const char * comment,const char * comment1)1009 remove_dependents(struct Client *client_p,
1010 		  struct Client *source_p, const char *comment, const char *comment1)
1011 {
1012 	struct Client *to;
1013 	rb_dlink_node *ptr, *next;
1014 
1015 	RB_DLINK_FOREACH_SAFE(ptr, next, serv_list.head)
1016 	{
1017 		to = ptr->data;
1018 
1019 		if(IsMe(to) || to == source_p->from || (to == client_p && IsCapable(to, CAP_QS)))
1020 			continue;
1021 
1022 		recurse_send_quits(client_p, source_p, to, comment1, comment);
1023 	}
1024 
1025 	recurse_remove_clients(source_p, comment1);
1026 }
1027 
1028 void
exit_aborted_clients(void * unused)1029 exit_aborted_clients(void *unused)
1030 {
1031 	struct abort_client *abt;
1032 	rb_dlink_node *ptr, *next;
1033 	RB_DLINK_FOREACH_SAFE(ptr, next, abort_list.head)
1034 	{
1035 		abt = ptr->data;
1036 
1037 #ifdef DEBUG_EXITED_CLIENTS
1038 		{
1039 			if(rb_dlinkFind(abt->client, &dead_list))
1040 			{
1041 				s_assert(0);
1042 				sendto_realops_flags(UMODE_ALL, L_ALL,
1043 						     "On dead_list: %s stat: %u flags: %u/%u handler: %c",
1044 						     abt->client->name,
1045 						     (unsigned int)abt->client->status,
1046 						     abt->client->flags, abt->client->operflags,
1047 						     abt->client->handler);
1048 				sendto_realops_flags(UMODE_ALL, L_ALL,
1049 						     "Please report this to the ratbox developers!");
1050 				continue;
1051 			}
1052 		}
1053 #endif
1054 
1055 		s_assert(*((unsigned long *)abt->client) != 0xdeadbeef);	/* This is lame but its a debug thing */
1056 		rb_dlinkDelete(ptr, &abort_list);
1057 
1058 		if(IsAnyServer(abt->client))
1059 			sendto_realops_flags(UMODE_ALL, L_ALL,
1060 					     "Closing link to %s: %s",
1061 					     abt->client->name, abt->notice);
1062 
1063 		/* its no longer on abort list - we *must* remove
1064 		 * FLAGS_CLOSING otherwise exit_client() will not run --fl
1065 		 */
1066 		abt->client->flags &= ~FLAGS_CLOSING;
1067 		exit_client(abt->client, abt->client, &me, abt->notice);
1068 		rb_free(abt);
1069 	}
1070 }
1071 
1072 
1073 /*
1074  * dead_link - Adds client to a list of clients that need an exit_client()
1075  *
1076  */
1077 void
dead_link(struct Client * client_p,int sendqex)1078 dead_link(struct Client *client_p, int sendqex)
1079 {
1080 	struct abort_client *abt;
1081 
1082 	s_assert(!IsMe(client_p));
1083 	if(IsDead(client_p) || IsClosing(client_p) || IsMe(client_p))
1084 		return;
1085 
1086 	abt = rb_malloc(sizeof(struct abort_client));
1087 
1088 	if(sendqex)
1089 		rb_strlcpy(abt->notice, "Max SendQ exceeded", sizeof(abt->notice));
1090 	else
1091 		rb_snprintf(abt->notice, sizeof(abt->notice), "Write error: %s", strerror(errno));
1092 
1093 	abt->client = client_p;
1094 	SetIOError(client_p);
1095 	SetDead(client_p);
1096 	SetClosing(client_p);
1097 	rb_dlinkAdd(abt, &abt->node, &abort_list);
1098 }
1099 
1100 
1101 /* This does the remove of the user from channels..local or remote */
1102 static inline void
exit_generic_client(struct Client * source_p,const char * comment)1103 exit_generic_client(struct Client *source_p, const char *comment)
1104 {
1105 	sendto_common_channels_local(source_p, ":%s!%s@%s QUIT :%s",
1106 				     source_p->name, source_p->username, source_p->host, comment);
1107 
1108 	remove_user_from_channels(source_p);
1109 
1110 	/* Should not be in any channels now */
1111 	s_assert(source_p->user->channel.head == NULL);
1112 
1113 	/* Clean up allow lists */
1114 	del_all_accepts(source_p);
1115 
1116 	add_history(source_p, 0);
1117 	off_history(source_p);
1118 
1119 	monitor_signoff(source_p);
1120 	dec_global_cidr_count(source_p);
1121 	if(has_id(source_p))
1122 		del_from_hash(HASH_ID, source_p->id, source_p);
1123 
1124 	del_from_hash(HASH_HOSTNAME, source_p->host, source_p);
1125 	del_from_hash(HASH_CLIENT, source_p->name, source_p);
1126 	remove_client_from_list(source_p);
1127 }
1128 
1129 /*
1130  * Assumes IsClient(source_p) && !MyConnect(source_p)
1131  */
1132 
1133 static int
exit_remote_client(struct Client * client_p,struct Client * source_p,struct Client * from,const char * comment)1134 exit_remote_client(struct Client *client_p, struct Client *source_p, struct Client *from,
1135 		   const char *comment)
1136 {
1137 	exit_generic_client(source_p, comment);
1138 
1139 	if(source_p->servptr && source_p->servptr->serv)
1140 	{
1141 		rb_dlinkDelete(&source_p->lnode, &source_p->servptr->serv->users);
1142 	}
1143 
1144 	if((source_p->flags & FLAGS_KILLED) == 0)
1145 	{
1146 		sendto_server(client_p, NULL, CAP_TS6, NOCAPS,
1147 			      ":%s QUIT :%s", use_id(source_p), comment);
1148 		sendto_server(client_p, NULL, NOCAPS, CAP_TS6,
1149 			      ":%s QUIT :%s", source_p->name, comment);
1150 	}
1151 
1152 	SetDead(source_p);
1153 #ifdef DEBUG_EXITED_CLIENTS
1154 	rb_dlinkAddAlloc(source_p, &dead_remote_list);
1155 #else
1156 	rb_dlinkAddAlloc(source_p, &dead_list);
1157 #endif
1158 	return (CLIENT_EXITED);
1159 }
1160 
1161 /*
1162  * This assumes IsUnknown(source_p) == TRUE and MyConnect(source_p) == TRUE
1163  */
1164 
1165 static int
exit_unknown_client(struct Client * client_p,struct Client * source_p,const char * comment)1166 exit_unknown_client(struct Client *client_p, struct Client *source_p, const char *comment)
1167 {
1168 	delete_auth_queries(source_p);
1169 	rb_dlinkDelete(&source_p->localClient->tnode, &unknown_list);
1170 
1171 	if(!IsIOError(source_p))
1172 		sendto_one(source_p, "ERROR :Closing Link: %s (%s)",
1173 			   source_p->user != NULL ? source_p->host : "127.0.0.1", comment);
1174 
1175 	close_connection(source_p);
1176 
1177 	del_from_hash(HASH_HOSTNAME, source_p->host, source_p);
1178 	del_from_hash(HASH_CLIENT, source_p->name, source_p);
1179 	remove_client_from_list(source_p);
1180 	SetDead(source_p);
1181 	rb_dlinkAddAlloc(source_p, &dead_list);
1182 
1183 	/* Note that we don't need to add unknowns to the dead_list */
1184 	return (CLIENT_EXITED);
1185 }
1186 
1187 static int
exit_remote_server(struct Client * client_p,struct Client * source_p,struct Client * from,const char * comment)1188 exit_remote_server(struct Client *client_p, struct Client *source_p, struct Client *from,
1189 		   const char *comment)
1190 {
1191 	static char comment1[(HOSTLEN * 2) + 2];
1192 	static char newcomment[BUFSIZE];
1193 	struct Client *target_p;
1194 
1195 	if(source_p->servptr)
1196 		strcpy(comment1, source_p->servptr->name);
1197 	else
1198 		strcpy(comment1, "<Unknown>");
1199 
1200 	strcat(comment1, " ");
1201 	strcat(comment1, source_p->name);
1202 	if(IsClient(from))
1203 		rb_snprintf(newcomment, sizeof(newcomment), "by %s: %s", from->name, comment);
1204 
1205 	if(source_p->serv != NULL)
1206 		remove_dependents(client_p, source_p, IsClient(from) ? newcomment : comment,
1207 				  comment1);
1208 
1209 	if(source_p->servptr && source_p->servptr->serv)
1210 		rb_dlinkDelete(&source_p->lnode, &source_p->servptr->serv->servers);
1211 	else
1212 		s_assert(0);
1213 
1214 	rb_dlinkFindDestroy(source_p, &global_serv_list);
1215 	target_p = source_p->from;
1216 
1217 	if(target_p != NULL && IsServer(target_p) && target_p != client_p &&
1218 	   !IsMe(target_p) && (source_p->flags & FLAGS_KILLED) == 0)
1219 	{
1220 		sendto_one(target_p, ":%s SQUIT %s :%s",
1221 			   get_id(from, target_p), get_id(source_p, target_p), comment);
1222 	}
1223 
1224 	if(has_id(source_p))
1225 		del_from_hash(HASH_ID, source_p->id, source_p);
1226 
1227 	del_from_hash(HASH_CLIENT, source_p->name, source_p);
1228 	remove_client_from_list(source_p);
1229 
1230 	SetDead(source_p);
1231 #ifdef DEBUG_EXITED_CLIENTS
1232 	rb_dlinkAddAlloc(source_p, &dead_remote_list);
1233 #else
1234 	rb_dlinkAddAlloc(source_p, &dead_list);
1235 #endif
1236 	return 0;
1237 }
1238 
1239 static int
qs_server(struct Client * source_p)1240 qs_server(struct Client *source_p)
1241 {
1242 	struct Client *target_p;
1243 
1244 	if(source_p->servptr && source_p->servptr->serv)
1245 		rb_dlinkDelete(&source_p->lnode, &source_p->servptr->serv->servers);
1246 	else
1247 		s_assert(0);
1248 
1249 	rb_dlinkFindDestroy(source_p, &global_serv_list);
1250 	target_p = source_p->from;
1251 
1252 	if(has_id(source_p))
1253 		del_from_hash(HASH_ID, source_p->id, source_p);
1254 
1255 	del_from_hash(HASH_CLIENT, source_p->name, source_p);
1256 	remove_client_from_list(source_p);
1257 
1258 	SetDead(source_p);
1259 	rb_dlinkAddAlloc(source_p, &dead_list);
1260 	return 0;
1261 }
1262 
1263 static int
exit_local_server(struct Client * client_p,struct Client * source_p,struct Client * from,const char * comment)1264 exit_local_server(struct Client *client_p, struct Client *source_p, struct Client *from,
1265 		  const char *comment)
1266 {
1267 	static char comment1[(HOSTLEN * 2) + 2];
1268 	static char newcomment[BUFSIZE];
1269 	unsigned long long int sendb, recvb;
1270 
1271 	rb_dlinkDelete(&source_p->localClient->tnode, &serv_list);
1272 	rb_dlinkFindDestroy(source_p, &global_serv_list);
1273 
1274 	unset_chcap_usage_counts(source_p);
1275 	sendb = source_p->localClient->sendB;
1276 	recvb = source_p->localClient->receiveB;
1277 
1278 	/* Always show source here, so the server notices show
1279 	 * which side initiated the split -- jilles
1280 	 */
1281 	rb_snprintf(newcomment, sizeof(newcomment), "by %s: %s",
1282 		    from == source_p ? me.name : from->name, comment);
1283 #if 0				/* let's not do this for now -- jilles */
1284 	if(!IsIOError(source_p))
1285 		sendto_one(source_p, "SQUIT %s :%s", use_id(source_p), newcomment);
1286 #endif
1287 	if(client_p != NULL && source_p != client_p && !IsIOError(source_p))
1288 	{
1289 		sendto_one(source_p, "ERROR :Closing Link: 127.0.0.1 %s (%s)",
1290 			   source_p->name, comment);
1291 	}
1292 
1293 	if(source_p->servptr && source_p->servptr->serv)
1294 		rb_dlinkDelete(&source_p->lnode, &source_p->servptr->serv->servers);
1295 	else
1296 		s_assert(0);
1297 
1298 
1299 	close_connection(source_p);
1300 
1301 	if(source_p->localClient->event != NULL)
1302 		rb_event_delete(source_p->localClient->event);
1303 
1304 	if(source_p->servptr)
1305 		strcpy(comment1, source_p->servptr->name);
1306 	else
1307 		strcpy(comment1, "<Unknown>");
1308 
1309 	strcat(comment1, " ");
1310 	strcat(comment1, source_p->name);
1311 
1312 	if(source_p->serv != NULL)
1313 		remove_dependents(client_p, source_p, IsClient(from) ? newcomment : comment,
1314 				  comment1);
1315 
1316 	sendto_realops_flags(UMODE_ALL, L_ALL, "%s was connected"
1317 			     " for %ld seconds.  %llu/%llu send/recv.",
1318 			     source_p->name,
1319 			     (long int)(rb_current_time() - source_p->localClient->firsttime),
1320 			     sendb, recvb);
1321 
1322 	ilog(L_SERVER, "%s was connected for %ld seconds.  %llu/%llu send/recv.",
1323 	     source_p->name, (long int)(rb_current_time() - source_p->localClient->firsttime),
1324 	     sendb, recvb);
1325 
1326 	if(has_id(source_p))
1327 		del_from_hash(HASH_ID, source_p->id, source_p);
1328 
1329 	del_from_hash(HASH_CLIENT, source_p->name, source_p);
1330 	remove_client_from_list(source_p);
1331 
1332 	SetDead(source_p);
1333 	rb_dlinkAddAlloc(source_p, &dead_list);
1334 	return 0;
1335 }
1336 
1337 
1338 /*
1339  * This assumes IsClient(source_p) == TRUE && MyConnect(source_p) == TRUE
1340  */
1341 
1342 static int
exit_local_client(struct Client * client_p,struct Client * source_p,struct Client * from,const char * comment)1343 exit_local_client(struct Client *client_p, struct Client *source_p, struct Client *from,
1344 		  const char *comment)
1345 {
1346 	rb_dlink_node *ptr, *next_ptr;
1347 	unsigned long on_for;
1348 	char tbuf[26];
1349 
1350 	exit_generic_client(source_p, comment);
1351 	clear_monitor(source_p);
1352 
1353 	s_assert(IsClient(source_p));
1354 	rb_dlinkDelete(&source_p->localClient->tnode, &lclient_list);
1355 	rb_dlinkDelete(&source_p->lnode, &me.serv->users);
1356 
1357 	if(IsOper(source_p))
1358 		rb_dlinkFindDestroy(source_p, &oper_list);
1359 
1360 	/* Clean up invitefield */
1361 	RB_DLINK_FOREACH_SAFE(ptr, next_ptr, source_p->localClient->invited.head)
1362 	{
1363 		del_invite(ptr->data, source_p);
1364 	}
1365 
1366 	sendto_realops_flags(UMODE_CCONN, L_ALL,
1367 			     "Client exiting: %s (%s@%s) [%s] [%s]",
1368 			     source_p->name,
1369 			     source_p->username, source_p->host, comment,
1370 			     show_ip(NULL, source_p) ? source_p->sockhost : "255.255.255.255");
1371 
1372 	sendto_realops_flags(UMODE_CCONNEXT, L_ALL,
1373 			     "CLIEXIT %s %s %s %s 0 %s",
1374 			     source_p->name, source_p->username, source_p->host,
1375 			     show_ip(NULL, source_p) ? source_p->sockhost : "255.255.255.255",
1376 			     comment);
1377 
1378 	on_for = rb_current_time() - source_p->localClient->firsttime;
1379 
1380 	ilog(L_USER, "%s (%3lu:%02lu:%02lu): %s!%s@%s %s %llu/%llu",
1381 	     rb_ctime(rb_current_time(), tbuf, sizeof(tbuf)), on_for / 3600,
1382 	     (on_for % 3600) / 60, on_for % 60,
1383 	     source_p->name, source_p->username, source_p->host, source_p->sockhost,
1384 	     source_p->localClient->sendB, source_p->localClient->receiveB);
1385 
1386 	sendto_one(source_p, "ERROR :Closing Link: %s (%s)", source_p->host, comment);
1387 	close_connection(source_p);
1388 
1389 	if(source_p->localClient->event != NULL)
1390 		rb_event_delete(source_p->localClient->event);
1391 
1392 	if((source_p->flags & FLAGS_KILLED) == 0)
1393 	{
1394 		sendto_server(client_p, NULL, CAP_TS6, NOCAPS,
1395 			      ":%s QUIT :%s", use_id(source_p), comment);
1396 		sendto_server(client_p, NULL, NOCAPS, CAP_TS6,
1397 			      ":%s QUIT :%s", source_p->name, comment);
1398 	}
1399 
1400 	SetDead(source_p);
1401 	rb_dlinkAddAlloc(source_p, &dead_list);
1402 	return (CLIENT_EXITED);
1403 }
1404 
1405 
1406 /*
1407 ** exit_client - This is old "m_bye". Name  changed, because this is not a
1408 **        protocol function, but a general server utility function.
1409 **
1410 **        This function exits a client of *any* type (user, server, etc)
1411 **        from this server. Also, this generates all necessary prototol
1412 **        messages that this exit may cause.
1413 **
1414 **   1) If the client is a local client, then this implicitly
1415 **        exits all other clients depending on this connection (e.g.
1416 **        remote clients having 'from'-field that points to this.
1417 **
1418 **   2) If the client is a remote client, then only this is exited.
1419 **
1420 ** For convenience, this function returns a suitable value for
1421 ** m_function return value:
1422 **
1423 **        CLIENT_EXITED        if (client_p == source_p)
1424 **        0                if (client_p != source_p)
1425 */
1426 int
exit_client(struct Client * client_p,struct Client * source_p,struct Client * from,const char * comment)1427 exit_client(struct Client *client_p,	/* The local client originating the
1428 					 * exit or NULL, if this exit is
1429 					 * generated by this server for
1430 					 * internal reasons.
1431 					 * This will not get any of the
1432 					 * generated messages. */
1433 	    struct Client *source_p,	/* Client exiting */
1434 	    struct Client *from,	/* Client firing off this Exit,
1435 					 * never NULL! */
1436 	    const char *comment	/* Reason for the exit */
1437 	)
1438 {
1439 	if(IsClosing(source_p))
1440 		return -1;
1441 
1442 	/* note, this HAS to be here, when we exit a client we attempt to
1443 	 * send them data, if this generates a write error we must *not* add
1444 	 * them to the abort list --fl
1445 	 */
1446 	SetClosing(source_p);
1447 
1448 	if(MyConnect(source_p))
1449 	{
1450 		/* Local clients of various types */
1451 		if(IsClient(source_p))
1452 			return exit_local_client(client_p, source_p, from, comment);
1453 		else if(IsServer(source_p))
1454 			return exit_local_server(client_p, source_p, from, comment);
1455 		/* IsUnknown || IsConnecting || IsHandShake */
1456 		else if(!IsReject(source_p))
1457 			return exit_unknown_client(client_p, source_p, comment);
1458 	}
1459 	else
1460 	{
1461 		/* Remotes */
1462 		if(IsClient(source_p))
1463 			return exit_remote_client(client_p, source_p, from, comment);
1464 		else if(IsServer(source_p))
1465 			return exit_remote_server(client_p, source_p, from, comment);
1466 	}
1467 
1468 	return -1;
1469 }
1470 
1471 /*
1472  * Count up local client memory
1473  */
1474 
1475 /* XXX one common Client list now */
1476 void
count_local_client_memory(size_t * count,size_t * local_client_memory_used)1477 count_local_client_memory(size_t *count, size_t *local_client_memory_used)
1478 {
1479 	size_t lusage;
1480 	rb_bh_usage(lclient_heap, count, NULL, &lusage, NULL);
1481 	*local_client_memory_used = lusage + (*count * (sizeof(void *) + sizeof(struct Client)));
1482 }
1483 
1484 /*
1485  * Count up remote client memory
1486  */
1487 void
count_remote_client_memory(size_t * count,size_t * remote_client_memory_used)1488 count_remote_client_memory(size_t *count, size_t *remote_client_memory_used)
1489 {
1490 	size_t lcount, rcount;
1491 	rb_bh_usage(lclient_heap, &lcount, NULL, NULL, NULL);
1492 	rb_bh_usage(client_heap, &rcount, NULL, NULL, NULL);
1493 	*count = rcount - lcount;
1494 	*remote_client_memory_used = *count * (sizeof(void *) + sizeof(struct Client));
1495 }
1496 
1497 
1498 /*
1499  * accept processing, this adds a form of "caller ID" to ircd
1500  *
1501  * If a client puts themselves into "caller ID only" mode,
1502  * only clients that match a client pointer they have put on
1503  * the accept list will be allowed to message them.
1504  *
1505  * [ source.on_allow_list ] -> [ target1 ] -> [ target2 ]
1506  *
1507  * [target.allow_list] -> [ source1 ] -> [source2 ]
1508  *
1509  * i.e. a target will have a link list of source pointers it will allow
1510  * each source client then has a back pointer pointing back
1511  * to the client that has it on its accept list.
1512  * This allows for exit_one_client to remove these now bogus entries
1513  * from any client having an accept on them.
1514  */
1515 
1516 
1517 /*
1518  * del_all_accepts
1519  *
1520  * inputs	- pointer to exiting client
1521  * output	- NONE
1522  * side effects - Walk through given clients allow_list and on_allow_list
1523  *                remove all references to this client
1524  */
1525 void
del_all_accepts(struct Client * client_p)1526 del_all_accepts(struct Client *client_p)
1527 {
1528 	rb_dlink_node *ptr;
1529 	rb_dlink_node *next_ptr;
1530 	struct Client *target_p;
1531 
1532 	if(MyClient(client_p) && client_p->localClient->allow_list.head)
1533 	{
1534 		/* clear this clients accept list, and remove them from
1535 		 * everyones on_accept_list
1536 		 */
1537 
1538 		RB_DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->localClient->allow_list.head)
1539 		{
1540 			target_p = ptr->data;
1541 			rb_dlinkFindDestroy(client_p, &target_p->on_allow_list);
1542 			rb_dlinkDestroy(ptr, &client_p->localClient->allow_list);
1543 		}
1544 	}
1545 
1546 	/* remove this client from everyones accept list */
1547 	RB_DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->on_allow_list.head)
1548 	{
1549 		target_p = ptr->data;
1550 		rb_dlinkFindDestroy(client_p, &target_p->localClient->allow_list);
1551 		rb_dlinkDestroy(ptr, &client_p->on_allow_list);
1552 	}
1553 }
1554 
1555 
1556 int
show_ip(struct Client * source_p,struct Client * target_p)1557 show_ip(struct Client *source_p, struct Client *target_p)
1558 {
1559 	if(IsAnyServer(target_p))
1560 	{
1561 		return 0;
1562 	}
1563 	else if(IsIPSpoof(target_p))
1564 	{
1565 		/* source == NULL indicates message is being sent
1566 		 * to local opers.
1567 		 */
1568 		if(!ConfigFileEntry.hide_spoof_ips && (source_p == NULL || MyOper(source_p)))
1569 			return 1;
1570 
1571 		return 0;
1572 	}
1573 	else
1574 		return 1;
1575 }
1576 
1577 
1578 int
show_ip_conf(struct ConfItem * aconf,struct Client * source_p)1579 show_ip_conf(struct ConfItem *aconf, struct Client *source_p)
1580 {
1581 	if(IsConfDoSpoofIp(aconf))
1582 	{
1583 		if(!ConfigFileEntry.hide_spoof_ips && MyOper(source_p))
1584 			return 1;
1585 
1586 		return 0;
1587 	}
1588 	else
1589 		return 1;
1590 
1591 }
1592 
1593 
1594 /*
1595  * make_user
1596  *
1597  * inputs	- pointer to client struct
1598  * output	- pointer to struct User
1599  * side effects - add's an User information block to a client
1600  *                if it was not previously allocated.
1601  */
1602 struct User *
make_user(struct Client * client_p)1603 make_user(struct Client *client_p)
1604 {
1605 	struct User *user;
1606 
1607 	user = client_p->user;
1608 	if(!user)
1609 	{
1610 		user = rb_bh_alloc(user_heap);
1611 		client_p->user = user;
1612 	}
1613 	return user;
1614 }
1615 
1616 /*
1617  * make_server
1618  *
1619  * inputs	- pointer to client struct
1620  * output	- pointer to struct Server
1621  * side effects - add's an Server information block to a client
1622  *                if it was not previously allocated.
1623  */
1624 struct Server *
make_server(struct Client * client_p)1625 make_server(struct Client *client_p)
1626 {
1627 	struct Server *serv = client_p->serv;
1628 
1629 	if(!serv)
1630 	{
1631 		serv = rb_malloc(sizeof(struct Server));
1632 		client_p->serv = serv;
1633 	}
1634 	return client_p->serv;
1635 }
1636 
1637 /*
1638  * free_user
1639  *
1640  * inputs	- pointer to user struct
1641  *		- pointer to client struct
1642  * output	- none
1643  * side effects - Decrease user reference count by one and release block,
1644  *                if count reaches 0
1645  */
1646 void
free_user(struct User * user,struct Client * client_p)1647 free_user(struct User *user, struct Client *client_p)
1648 {
1649 	free_away(client_p);
1650 	/*
1651 	 * sanity check
1652 	 */
1653 	if(user->channel.head)
1654 	{
1655 		sendto_realops_flags(UMODE_ALL, L_ALL,
1656 				     "* %#lx user (%s!%s@%s) %#lx %#lx %lu *",
1657 				     (unsigned long)client_p,
1658 				     client_p ? client_p->name : "<noname>",
1659 				     client_p->username,
1660 				     client_p->host,
1661 				     (unsigned long)user,
1662 				     (unsigned long)user->channel.head,
1663 				     rb_dlink_list_length(&user->channel));
1664 		s_assert(!user->channel.head);
1665 	}
1666 
1667 	rb_bh_free(user_heap, user);
1668 }
1669 
1670 void
allocate_away(struct Client * client_p)1671 allocate_away(struct Client *client_p)
1672 {
1673 	if(client_p->user->away == NULL)
1674 		client_p->user->away = rb_bh_alloc(away_heap);
1675 }
1676 
1677 
1678 void
free_away(struct Client * client_p)1679 free_away(struct Client *client_p)
1680 {
1681 	if(client_p->user->away != NULL)
1682 	{
1683 		rb_bh_free(away_heap, client_p->user->away);
1684 		client_p->user->away = NULL;
1685 	}
1686 }
1687 
1688 void
init_uid(void)1689 init_uid(void)
1690 {
1691 	int i;
1692 
1693 	for(i = 0; i < 3; i++)
1694 		current_uid[i] = me.id[i];
1695 
1696 	for(i = 3; i < 9; i++)
1697 		current_uid[i] = 'A';
1698 
1699 	current_uid[9] = '\0';
1700 }
1701 
1702 
1703 char *
generate_uid(void)1704 generate_uid(void)
1705 {
1706 	int i;
1707 
1708 	for(i = 8; i > 3; i--)
1709 	{
1710 		if(current_uid[i] == 'Z')
1711 		{
1712 			current_uid[i] = '0';
1713 			return current_uid;
1714 		}
1715 		else if(current_uid[i] != '9')
1716 		{
1717 			current_uid[i]++;
1718 			return current_uid;
1719 		}
1720 		else
1721 			current_uid[i] = 'A';
1722 	}
1723 
1724 	/* if this next if() triggers, we're fucked. */
1725 	if(current_uid[3] == 'Z')
1726 	{
1727 		current_uid[i] = 'A';
1728 		s_assert(0);
1729 	}
1730 	else
1731 		current_uid[i]++;
1732 
1733 	return current_uid;
1734 }
1735 
1736 /*
1737  * close_connection
1738  *        Close the physical connection. This function must make
1739  *        MyConnect(client_p) == FALSE, and set client_p->from == NULL.
1740  */
1741 void
close_connection(struct Client * client_p)1742 close_connection(struct Client *client_p)
1743 {
1744 	s_assert(client_p != NULL);
1745 	if(client_p == NULL)
1746 		return;
1747 
1748 	s_assert(MyConnect(client_p));
1749 	if(!MyConnect(client_p))
1750 		return;
1751 
1752 	if(IsServer(client_p))
1753 	{
1754 		struct server_conf *server_p;
1755 
1756 		ServerStats.is_sv++;
1757 		ServerStats.is_sbs += client_p->localClient->sendB;
1758 		ServerStats.is_sbr += client_p->localClient->receiveB;
1759 		ServerStats.is_sti += (unsigned long long)(rb_current_time() - client_p->localClient->firsttime);
1760 
1761 		/*
1762 		 * If the connection has been up for a long amount of time, schedule
1763 		 * a 'quick' reconnect, else reset the next-connect cycle.
1764 		 */
1765 		if((server_p = find_server_conf(client_p->name)) != NULL)
1766 		{
1767 			/*
1768 			 * Reschedule a faster reconnect, if this was a automatically
1769 			 * connected configuration entry. (Note that if we have had
1770 			 * a rehash in between, the status has been changed to
1771 			 * CONF_ILLEGAL). But only do this if it was a "good" link.
1772 			 */
1773 			server_p->hold = time(NULL);
1774 			server_p->hold +=
1775 				(server_p->hold - client_p->localClient->lasttime >
1776 				 HANGONGOODLINK) ? HANGONRETRYDELAY : ConFreq(server_p->class);
1777 		}
1778 
1779 	}
1780 	else if(IsClient(client_p))
1781 	{
1782 		ServerStats.is_cl++;
1783 		ServerStats.is_cbs += client_p->localClient->sendB;
1784 		ServerStats.is_cbr += client_p->localClient->receiveB;
1785 		ServerStats.is_cti += (unsigned long long)(rb_current_time() - client_p->localClient->firsttime);
1786 	}
1787 	else
1788 		ServerStats.is_ni++;
1789 
1790 	if(client_p->localClient->F != NULL)
1791 	{
1792 		/* attempt to flush any pending linebufs. Evil, but .. -- adrian */
1793 		if(!IsIOError(client_p))
1794 			send_pop_queue(client_p);
1795 		del_from_cli_fd_hash(client_p);
1796 		rb_close(client_p->localClient->F);
1797 		client_p->localClient->F = NULL;
1798 	}
1799 
1800 	rb_linebuf_donebuf(&client_p->localClient->buf_sendq);
1801 	rb_linebuf_donebuf(&client_p->localClient->buf_recvq);
1802 	detach_conf(client_p);
1803 
1804 	/* XXX shouldnt really be done here. */
1805 	detach_server_conf(client_p);
1806 
1807 	client_p->from = NULL;	/* ...this should catch them! >:) --msa */
1808 	ClearMyConnect(client_p);
1809 	SetIOError(client_p);
1810 }
1811 
1812 
1813 
1814 void
error_exit_client(struct Client * client_p,int error)1815 error_exit_client(struct Client *client_p, int error)
1816 {
1817 	/*
1818 	 * ...hmm, with non-blocking sockets we might get
1819 	 * here from quite valid reasons, although.. why
1820 	 * would select report "data available" when there
1821 	 * wasn't... so, this must be an error anyway...  --msa
1822 	 * actually, EOF occurs when read() returns 0 and
1823 	 * in due course, select() returns that fd as ready
1824 	 * for reading even though it ends up being an EOF. -avalon
1825 	 */
1826 	char errmsg[255];
1827 	int current_error = rb_get_sockerr(client_p->localClient->F);
1828 
1829 	SetIOError(client_p);
1830 
1831 	if(IsServer(client_p) || IsHandshake(client_p))
1832 	{
1833 		int connected = rb_current_time() - client_p->localClient->firsttime;
1834 
1835 		if(error == 0)
1836 		{
1837 			sendto_realops_flags(UMODE_ALL, L_ALL,
1838 					     "Server %s closed the connection", client_p->name);
1839 
1840 			ilog(L_SERVER, "Server %s closed the connection",
1841 			     log_client_name(client_p, SHOW_IP));
1842 		}
1843 		else
1844 		{
1845 			report_error("Lost connection to %s: %s",
1846 				     client_p->name,
1847 				     log_client_name(client_p, SHOW_IP), current_error);
1848 		}
1849 
1850 		sendto_realops_flags(UMODE_ALL, L_ALL,
1851 				     "%s had been connected for %d day%s, %2d:%02d:%02d",
1852 				     client_p->name, connected / 86400,
1853 				     (connected / 86400 == 1) ? "" : "s",
1854 				     (connected % 86400) / 3600,
1855 				     (connected % 3600) / 60, connected % 60);
1856 	}
1857 
1858 	if(error == 0)
1859 		rb_strlcpy(errmsg, "Remote host closed the connection", sizeof(errmsg));
1860 	else
1861 		rb_snprintf(errmsg, sizeof(errmsg), "Read error: %s", strerror(current_error));
1862 
1863 	exit_client(client_p, client_p, &me, errmsg);
1864 }
1865