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-2012 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 28697 2015-10-02 20:57:42Z 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 %" RBTT_FMT " seconds. %llu/%llu send/recv.",
1318 source_p->name,
1319 (rb_current_time() - source_p->localClient->firsttime),
1320 sendb, recvb);
1321
1322 ilog(L_SERVER, "%s was connected for %" RBTT_FMT " seconds. %llu/%llu send/recv.",
1323 source_p->name, (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 time_t 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 % " RBTT_FMT " day%s, %2" RBTT_FMT "%02" RBTT_FMT "%02" RBTT_FMT,
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