/[svn]/branches/newio/src/s_serv.c
ViewVC logotype

Contents of /branches/newio/src/s_serv.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2692 - (show annotations)
Tue Dec 17 18:56:15 2013 UTC (8 years, 11 months ago) by michael
File MIME type: text/x-chdr
File size: 28703 byte(s)
- Avoid magically sized temporary buffers

1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 *
4 * Copyright (C) 1997-2013 ircd-hybrid development team
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 * USA
20 */
21
22 /*! \file s_serv.c
23 * \brief Server related functions.
24 * \version $Id$
25 */
26
27 #include "stdinc.h"
28 #ifdef HAVE_LIBCRYPTO
29 #include <openssl/rsa.h>
30 #include "rsa.h"
31 #endif
32 #include "list.h"
33 #include "channel.h"
34 #include "channel_mode.h"
35 #include "client.h"
36 #include "dbuf.h"
37 #include "ioengine.h"
38 #include "hash.h"
39 #include "irc_string.h"
40 #include "ircd.h"
41 #include "ircd_defs.h"
42 #include "s_bsd.h"
43 #include "numeric.h"
44 #include "packet.h"
45 #include "irc_res.h"
46 #include "conf.h"
47 #include "s_serv.h"
48 #include "log.h"
49 #include "s_misc.h"
50 #include "s_user.h"
51 #include "send.h"
52 #include "memory.h"
53 #include "channel.h" /* chcap_usage_counts stuff...*/
54 #include "parse.h"
55 #include "ssl.h"
56
57
58 struct Timer connect_timer;
59
60 dlink_list flatten_links;
61 static dlink_list cap_list;
62 static void server_burst(struct Client *);
63 static void burst_all(struct Client *);
64 static void send_tb(struct Client *client_p, struct Channel *chptr);
65 static void burst_members(struct Client *, struct Channel *);
66
67 /*
68 * write_links_file
69 *
70 * inputs - void pointer which is not used
71 * output - NONE
72 * side effects - called from an event, write out list of linked servers
73 * but in no particular order.
74 */
75 void
76 write_links_file(struct Event *ev)
77 {
78 FILE *file = NULL;
79 dlink_node *ptr = NULL, *ptr_next = NULL;
80 char buff[IRCD_BUFSIZE] = { '\0' };
81
82 if ((file = fopen(LIPATH, "w")) == NULL)
83 return;
84
85 DLINK_FOREACH_SAFE(ptr, ptr_next, flatten_links.head)
86 {
87 dlinkDelete(ptr, &flatten_links);
88 MyFree(ptr->data);
89 free_dlink_node(ptr);
90 }
91
92 DLINK_FOREACH(ptr, global_serv_list.head)
93 {
94 const struct Client *target_p = ptr->data;
95
96 /*
97 * Skip hidden servers, aswell as ourselves, since we already send
98 * ourselves in /links
99 */
100 if (IsHidden(target_p) || IsMe(target_p))
101 continue;
102
103 if (HasFlag(target_p, FLAGS_SERVICE) && ConfigServerHide.hide_services)
104 continue;
105
106 /*
107 * Attempt to format the file in such a way it follows the usual links output
108 * ie "servername uplink :hops info"
109 * Mostly for aesthetic reasons - makes it look pretty in mIRC ;)
110 * - madmax
111 */
112 snprintf(buff, sizeof(buff), "%s %s :1 %s", target_p->name,
113 me.name, target_p->info);
114 dlinkAddTail(xstrdup(buff), make_dlink_node(), &flatten_links);
115 snprintf(buff, sizeof(buff), "%s %s :1 %s\n", target_p->name,
116 me.name, target_p->info);
117
118 fputs(buff, file);
119 }
120
121 fclose(file);
122 }
123
124 void
125 read_links_file(void)
126 {
127 FILE *file = NULL;
128 char *p = NULL;
129 char buff[IRCD_BUFSIZE] = { '\0' };
130
131 if ((file = fopen(LIPATH, "r")) == NULL)
132 return;
133
134 while (fgets(buff, sizeof(buff), file))
135 {
136 if ((p = strchr(buff, '\n')) != NULL)
137 *p = '\0';
138
139 dlinkAddTail(xstrdup(buff), make_dlink_node(), &flatten_links);
140 }
141
142 fclose(file);
143 }
144
145 /* hunt_server()
146 * Do the basic thing in delivering the message (command)
147 * across the relays to the specific server (server) for
148 * actions.
149 *
150 * Note: The command is a format string and *MUST* be
151 * of prefixed style (e.g. ":%s COMMAND %s ...").
152 * Command can have only max 8 parameters.
153 *
154 * server parv[server] is the parameter identifying the
155 * target server.
156 *
157 * *WARNING*
158 * parv[server] is replaced with the pointer to the
159 * real servername from the matched client (I'm lazy
160 * now --msa).
161 *
162 * returns: (see #defines)
163 */
164 int
165 hunt_server(struct Client *client_p, struct Client *source_p, const char *command,
166 const int server, const int parc, char *parv[])
167 {
168 struct Client *target_p = NULL;
169 struct Client *target_tmp = NULL;
170 dlink_node *ptr;
171 int wilds;
172
173 /* Assume it's me, if no server */
174 if (parc <= server || EmptyString(parv[server]))
175 return HUNTED_ISME;
176
177 if (!strcmp(parv[server], me.id) || !match(parv[server], me.name))
178 return HUNTED_ISME;
179
180 /* These are to pickup matches that would cause the following
181 * message to go in the wrong direction while doing quick fast
182 * non-matching lookups.
183 */
184 if (MyClient(source_p))
185 target_p = hash_find_client(parv[server]);
186 else
187 target_p = find_person(client_p, parv[server]);
188
189 if (target_p)
190 if (target_p->from == source_p->from && !MyConnect(target_p))
191 target_p = NULL;
192
193 if (target_p == NULL && (target_p = hash_find_server(parv[server])))
194 if (target_p->from == source_p->from && !MyConnect(target_p))
195 target_p = NULL;
196
197 wilds = has_wildcards(parv[server]);
198
199 /* Again, if there are no wild cards involved in the server
200 * name, use the hash lookup
201 */
202 if (target_p == NULL)
203 {
204 if (!wilds)
205 {
206 if (!(target_p = hash_find_server(parv[server])))
207 {
208 sendto_one(source_p, form_str(ERR_NOSUCHSERVER),
209 me.name, source_p->name, parv[server]);
210 return HUNTED_NOSUCH;
211 }
212 }
213 else
214 {
215 DLINK_FOREACH(ptr, global_client_list.head)
216 {
217 target_tmp = ptr->data;
218
219 if (!match(parv[server], target_tmp->name))
220 {
221 if (target_tmp->from == source_p->from && !MyConnect(target_tmp))
222 continue;
223 target_p = ptr->data;
224
225 if (IsRegistered(target_p) && (target_p != client_p))
226 break;
227 }
228 }
229 }
230 }
231
232 if (target_p != NULL)
233 {
234 if(!IsRegistered(target_p))
235 {
236 sendto_one(source_p, form_str(ERR_NOSUCHSERVER),
237 me.name, source_p->name, parv[server]);
238 return HUNTED_NOSUCH;
239 }
240
241 if (IsMe(target_p) || MyClient(target_p))
242 return HUNTED_ISME;
243
244 if (match(target_p->name, parv[server]))
245 parv[server] = target_p->name;
246
247 /* This is a little kludgy but should work... */
248 if (IsClient(source_p) &&
249 ((MyConnect(target_p) && IsCapable(target_p, CAP_TS6)) ||
250 (!MyConnect(target_p) && IsCapable(target_p->from, CAP_TS6))))
251 parv[0] = ID(source_p);
252
253 sendto_one(target_p, command, parv[0],
254 parv[1], parv[2], parv[3], parv[4],
255 parv[5], parv[6], parv[7], parv[8]);
256 return HUNTED_PASS;
257 }
258
259 sendto_one(source_p, form_str(ERR_NOSUCHSERVER),
260 me.name, source_p->name, parv[server]);
261 return HUNTED_NOSUCH;
262 }
263
264 /* try_connections()
265 *
266 * inputs - void pointer which is not used
267 * output - NONE
268 * side effects -
269 * scan through configuration and try new connections.
270 * Returns the calendar time when the next call to this
271 * function should be made latest. (No harm done if this
272 * is called earlier or later...)
273 */
274 void
275 try_connections(struct Event *ev)
276 {
277 dlink_node *ptr = NULL;
278 time_t next = 0;
279 int hold = 0;
280 int done = 0;
281
282 assert(ET_EXPIRE == ev_type(ev));
283 assert(ev_timer(ev));
284
285 next = CurrentTime + DEFAULT_CONNECTFREQUENCY;
286
287 DLINK_FOREACH(ptr, server_items.head)
288 {
289 struct MaskItem *conf = ptr->data;
290
291 assert(conf->type == CONF_SERVER);
292
293 if (!conf->port || !IsConfAllowAutoConn(conf))
294 continue;
295
296 /* Do we need to postpone this connection further? */
297 hold = conf->until > CurrentTime;
298
299 /* Update next possible connection check time. */
300 if (hold && next > conf->until)
301 next = conf->until;
302
303 if (hold || done || hash_find_server(conf->name) ||
304 !(conf->class->ref_count < conf->class->max_total))
305 continue;
306
307 dlinkDelete(ptr, &server_items);
308 dlinkAddTail(conf, &conf->node, &server_items);
309
310 /* Activate the connection itself. */
311 if (connect_server(conf, 0))
312 {
313 if (ConfigServerHide.hide_server_ips)
314 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
315 "Connection to %s activated.",
316 conf->name);
317 else
318 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
319 "Connection to %s[%s] activated.",
320 conf->name, conf->host);
321 }
322
323 /* And stop looking for further candidates. */
324 done = 1;
325 }
326
327 timer_add(&connect_timer, try_connections, 0, TT_ABSOLUTE, next);
328 }
329
330 int
331 valid_servname(const char *name)
332 {
333 unsigned int length = 0;
334 unsigned int dots = 0;
335 const char *p = name;
336
337 for (; *p; ++p)
338 {
339 if (!IsServChar(*p))
340 return 0;
341
342 ++length;
343
344 if (*p == '.')
345 ++dots;
346 }
347
348 return dots != 0 && length <= HOSTLEN;
349 }
350
351 int
352 check_server(const char *name, struct Client *client_p)
353 {
354 dlink_node *ptr;
355 struct MaskItem *conf = NULL;
356 struct MaskItem *server_conf = NULL;
357 int error = -1;
358
359 assert(client_p != NULL);
360
361 /* loop through looking for all possible connect items that might work */
362 DLINK_FOREACH(ptr, server_items.head)
363 {
364 conf = ptr->data;
365
366 if (match(name, conf->name))
367 continue;
368
369 error = -3;
370
371 /* XXX: Fix me for IPv6 */
372 /* XXX sockhost is the IPv4 ip as a string */
373 if (!match(conf->host, client_p->host) ||
374 !match(conf->host, client_p->sockhost))
375 {
376 error = -2;
377
378 if (!match_conf_password(client_p->localClient->passwd, conf))
379 return -2;
380
381 if (!EmptyString(conf->certfp))
382 if (EmptyString(client_p->certfp) || strcasecmp(client_p->certfp, conf->certfp))
383 return -4;
384
385 server_conf = conf;
386 }
387 }
388
389 if (server_conf == NULL)
390 return error;
391
392 attach_conf(client_p, server_conf);
393
394
395 if (server_conf != NULL)
396 {
397 struct sockaddr_in *v4;
398 struct sockaddr_in6 *v6;
399
400 switch (server_conf->aftype)
401 {
402 case AF_INET6:
403 v6 = (struct sockaddr_in6 *)&server_conf->addr;
404
405 if (IN6_IS_ADDR_UNSPECIFIED(&v6->sin6_addr))
406 memcpy(&server_conf->addr, &client_p->localClient->ip, sizeof(struct irc_ssaddr));
407 break;
408
409 case AF_INET:
410 v4 = (struct sockaddr_in *)&server_conf->addr;
411
412 if (v4->sin_addr.s_addr == INADDR_NONE)
413 memcpy(&server_conf->addr, &client_p->localClient->ip, sizeof(struct irc_ssaddr));
414 break;
415 }
416 }
417
418 return 0;
419 }
420
421 /* add_capability()
422 *
423 * inputs - string name of CAPAB
424 * - int flag of capability
425 * output - NONE
426 * side effects - Adds given capability name and bit mask to
427 * current supported capabilities. This allows
428 * modules to dynamically add or subtract their capability.
429 */
430 void
431 add_capability(const char *capab_name, int cap_flag, int add_to_default)
432 {
433 struct Capability *cap = MyMalloc(sizeof(*cap));
434
435 cap->name = xstrdup(capab_name);
436 cap->cap = cap_flag;
437 dlinkAdd(cap, &cap->node, &cap_list);
438
439 if (add_to_default)
440 default_server_capabs |= cap_flag;
441 }
442
443 /* delete_capability()
444 *
445 * inputs - string name of CAPAB
446 * output - NONE
447 * side effects - delete given capability from ones known.
448 */
449 int
450 delete_capability(const char *capab_name)
451 {
452 dlink_node *ptr;
453 dlink_node *next_ptr;
454 struct Capability *cap;
455
456 DLINK_FOREACH_SAFE(ptr, next_ptr, cap_list.head)
457 {
458 cap = ptr->data;
459
460 if (cap->cap != 0)
461 {
462 if (irccmp(cap->name, capab_name) == 0)
463 {
464 default_server_capabs &= ~(cap->cap);
465 dlinkDelete(ptr, &cap_list);
466 MyFree(cap->name);
467 MyFree(cap);
468 }
469 }
470 }
471
472 return 0;
473 }
474
475 /*
476 * find_capability()
477 *
478 * inputs - string name of capab to find
479 * output - 0 if not found CAPAB otherwise
480 * side effects - none
481 */
482 unsigned int
483 find_capability(const char *capab)
484 {
485 const dlink_node *ptr = NULL;
486
487 DLINK_FOREACH(ptr, cap_list.head)
488 {
489 const struct Capability *cap = ptr->data;
490
491 if (cap->cap && !irccmp(cap->name, capab))
492 return cap->cap;
493 }
494
495 return 0;
496 }
497
498 /* send_capabilities()
499 *
500 * inputs - Client pointer to send to
501 * - int flag of capabilities that this server can send
502 * output - NONE
503 * side effects - send the CAPAB line to a server -orabidoo
504 *
505 */
506 void
507 send_capabilities(struct Client *client_p, int cap_can_send)
508 {
509 struct Capability *cap=NULL;
510 char msgbuf[IRCD_BUFSIZE];
511 char *t;
512 int tl;
513 dlink_node *ptr;
514
515 t = msgbuf;
516
517 DLINK_FOREACH(ptr, cap_list.head)
518 {
519 cap = ptr->data;
520
521 if (cap->cap & (cap_can_send|default_server_capabs))
522 {
523 tl = sprintf(t, "%s ", cap->name);
524 t += tl;
525 }
526 }
527
528 *(t - 1) = '\0';
529 sendto_one(client_p, "CAPAB :%s", msgbuf);
530 }
531
532 /* sendnick_TS()
533 *
534 * inputs - client (server) to send nick towards
535 * - client to send nick for
536 * output - NONE
537 * side effects - NICK message is sent towards given client_p
538 */
539 void
540 sendnick_TS(struct Client *client_p, struct Client *target_p)
541 {
542 char ubuf[IRCD_BUFSIZE];
543
544 if (!IsClient(target_p))
545 return;
546
547 send_umode(NULL, target_p, 0, SEND_UMODES, ubuf);
548
549 if (ubuf[0] == '\0')
550 {
551 ubuf[0] = '+';
552 ubuf[1] = '\0';
553 }
554
555 if (IsCapable(client_p, CAP_SVS))
556 {
557 if (HasID(target_p) && IsCapable(client_p, CAP_TS6))
558 sendto_one(client_p, ":%s UID %s %d %Tu %s %s %s %s %s %s :%s",
559 target_p->servptr->id,
560 target_p->name, target_p->hopcount + 1,
561 target_p->tsinfo,
562 ubuf, target_p->username, target_p->host,
563 (MyClient(target_p) && IsIPSpoof(target_p)) ?
564 "0" : target_p->sockhost, target_p->id,
565 target_p->svid, target_p->info);
566 else
567 sendto_one(client_p, "NICK %s %d %Tu %s %s %s %s %s :%s",
568 target_p->name, target_p->hopcount + 1,
569 target_p->tsinfo,
570 ubuf, target_p->username, target_p->host,
571 target_p->servptr->name, target_p->svid,
572 target_p->info);
573 }
574 else
575 {
576 if (HasID(target_p) && IsCapable(client_p, CAP_TS6))
577 sendto_one(client_p, ":%s UID %s %d %Tu %s %s %s %s %s :%s",
578 target_p->servptr->id,
579 target_p->name, target_p->hopcount + 1,
580 target_p->tsinfo,
581 ubuf, target_p->username, target_p->host,
582 (MyClient(target_p) && IsIPSpoof(target_p)) ?
583 "0" : target_p->sockhost, target_p->id, target_p->info);
584 else
585 sendto_one(client_p, "NICK %s %d %Tu %s %s %s %s :%s",
586 target_p->name, target_p->hopcount + 1,
587 target_p->tsinfo,
588 ubuf, target_p->username, target_p->host,
589 target_p->servptr->name, target_p->info);
590 }
591
592 if (!EmptyString(target_p->certfp))
593 sendto_one(client_p, ":%s CERTFP %s",
594 ID_or_name(target_p, client_p), target_p->certfp);
595
596 if (target_p->away[0])
597 sendto_one(client_p, ":%s AWAY :%s", ID_or_name(target_p, client_p),
598 target_p->away);
599
600 }
601
602 /*
603 * show_capabilities - show current server capabilities
604 *
605 * inputs - pointer to a struct Client
606 * output - pointer to static string
607 * side effects - build up string representing capabilities of server listed
608 */
609 const char *
610 show_capabilities(const struct Client *target_p)
611 {
612 static char msgbuf[IRCD_BUFSIZE] = "";
613 const dlink_node *ptr = NULL;
614
615 strlcpy(msgbuf, "TS", sizeof(msgbuf));
616
617 DLINK_FOREACH(ptr, cap_list.head)
618 {
619 const struct Capability *cap = ptr->data;
620
621 if (!IsCapable(target_p, cap->cap))
622 continue;
623
624 strlcat(msgbuf, " ", sizeof(msgbuf));
625 strlcat(msgbuf, cap->name, sizeof(msgbuf));
626 }
627
628 return msgbuf;
629 }
630
631 /* make_server()
632 *
633 * inputs - pointer to client struct
634 * output - pointer to struct Server
635 * side effects - add's an Server information block to a client
636 * if it was not previously allocated.
637 */
638 struct Server *
639 make_server(struct Client *client_p)
640 {
641 if (client_p->serv == NULL)
642 client_p->serv = MyMalloc(sizeof(struct Server));
643
644 client_p->serv->last_error_msg = xstrdup("<>"); /* String must be non-empty */
645
646 return client_p->serv;
647 }
648
649 /* server_estab()
650 *
651 * inputs - pointer to a struct Client
652 * output -
653 * side effects -
654 */
655 void
656 server_estab(struct Client *client_p)
657 {
658 struct Client *target_p;
659 struct MaskItem *conf = NULL;
660 char *host;
661 const char *inpath;
662 static char inpath_ip[HOSTLEN * 2 + USERLEN + 6];
663 dlink_node *ptr;
664 #ifdef HAVE_LIBCRYPTO
665 const COMP_METHOD *compression = NULL, *expansion = NULL;
666 #endif
667
668 assert(client_p != NULL);
669
670 strlcpy(inpath_ip, get_client_name(client_p, SHOW_IP), sizeof(inpath_ip));
671
672 inpath = get_client_name(client_p, MASK_IP); /* "refresh" inpath with host */
673 host = client_p->name;
674
675 if ((conf = find_conf_name(&client_p->localClient->confs, host, CONF_SERVER))
676 == NULL)
677 {
678 /* This shouldn't happen, better tell the ops... -A1kmm */
679 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
680 "Warning: Lost connect{} block "
681 "for server %s(this shouldn't happen)!", host);
682 exit_client(client_p, client_p, &me, "Lost connect{} block!");
683 return;
684 }
685
686 MyFree(client_p->localClient->passwd);
687 client_p->localClient->passwd = NULL;
688
689 /* Its got identd, since its a server */
690 SetGotId(client_p);
691
692 /* If there is something in the serv_list, it might be this
693 * connecting server..
694 */
695 if (!ServerInfo.hub && serv_list.head)
696 {
697 if (client_p != serv_list.head->data || serv_list.head->next)
698 {
699 ++ServerStats.is_ref;
700 sendto_one(client_p, "ERROR :I'm a leaf not a hub");
701 exit_client(client_p, client_p, &me, "I'm a leaf");
702 return;
703 }
704 }
705
706 if (IsUnknown(client_p))
707 {
708 sendto_one(client_p, "PASS %s TS %d %s", conf->spasswd, TS_CURRENT, me.id);
709
710 send_capabilities(client_p, 0);
711
712 sendto_one(client_p, "SERVER %s 1 :%s%s",
713 me.name, ConfigServerHide.hidden ? "(H) " : "", me.info);
714 }
715
716 sendto_one(client_p, "SVINFO %d %d 0 :%Tu", TS_CURRENT, TS_MIN, CurrentTime);
717
718 /* assumption here is if they passed the correct TS version, they also passed an SID */
719 if (IsCapable(client_p, CAP_TS6))
720 hash_add_id(client_p);
721
722 detach_conf(client_p, CONF_CLIENT|CONF_OPER);
723
724 /* *WARNING*
725 ** In the following code in place of plain server's
726 ** name we send what is returned by get_client_name
727 ** which may add the "sockhost" after the name. It's
728 ** *very* *important* that there is a SPACE between
729 ** the name and sockhost (if present). The receiving
730 ** server will start the information field from this
731 ** first blank and thus puts the sockhost into info.
732 ** ...a bit tricky, but you have been warned, besides
733 ** code is more neat this way... --msa
734 */
735 client_p->servptr = &me;
736
737 SetServer(client_p);
738
739 /* Update the capability combination usage counts. -A1kmm */
740 set_chcap_usage_counts(client_p);
741
742 /* Some day, all these lists will be consolidated *sigh* */
743 dlinkAdd(client_p, &client_p->lnode, &me.serv->server_list);
744
745 assert(dlinkFind(&unknown_list, client_p));
746
747 dlink_move_node(&client_p->localClient->lclient_node,
748 &unknown_list, &serv_list);
749
750 Count.myserver++;
751
752 dlinkAdd(client_p, make_dlink_node(), &global_serv_list);
753
754 hash_add_client(client_p);
755
756 /* doesnt duplicate client_p->serv if allocated this struct already */
757 make_server(client_p);
758
759 /* fixing eob timings.. -gnp */
760 client_p->localClient->firsttime = CurrentTime;
761
762 if (find_matching_name_conf(CONF_SERVICE, client_p->name, NULL, NULL, 0))
763 AddFlag(client_p, FLAGS_SERVICE);
764
765 /* Show the real host/IP to admins */
766 #ifdef HAVE_LIBCRYPTO
767 if (client_p->localClient->socket.ssl)
768 {
769 compression = SSL_get_current_compression(client_p->localClient->socket.ssl);
770 expansion = SSL_get_current_expansion(client_p->localClient->socket.ssl);
771
772 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
773 "Link with %s established: [SSL: %s, Compression/Expansion method: %s/%s] (Capabilities: %s)",
774 inpath_ip, ssl_get_cipher(client_p->localClient->socket.ssl),
775 compression ? SSL_COMP_get_name(compression) : "NONE",
776 expansion ? SSL_COMP_get_name(expansion) : "NONE",
777 show_capabilities(client_p));
778 /* Now show the masked hostname/IP to opers */
779 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
780 "Link with %s established: [SSL: %s, Compression/Expansion method: %s/%s] (Capabilities: %s)",
781 inpath, ssl_get_cipher(client_p->localClient->socket.ssl),
782 compression ? SSL_COMP_get_name(compression) : "NONE",
783 expansion ? SSL_COMP_get_name(expansion) : "NONE",
784 show_capabilities(client_p));
785 ilog(LOG_TYPE_IRCD, "Link with %s established: [SSL: %s, Compression/Expansion method: %s/%s] (Capabilities: %s)",
786 inpath_ip, ssl_get_cipher(client_p->localClient->socket.ssl),
787 compression ? SSL_COMP_get_name(compression) : "NONE",
788 expansion ? SSL_COMP_get_name(expansion) : "NONE",
789 show_capabilities(client_p));
790 }
791 else
792 #endif
793 {
794 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
795 "Link with %s established: (Capabilities: %s)",
796 inpath_ip, show_capabilities(client_p));
797 /* Now show the masked hostname/IP to opers */
798 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
799 "Link with %s established: (Capabilities: %s)",
800 inpath, show_capabilities(client_p));
801 ilog(LOG_TYPE_IRCD, "Link with %s established: (Capabilities: %s)",
802 inpath_ip, show_capabilities(client_p));
803 }
804
805 /* Old sendto_serv_but_one() call removed because we now
806 ** need to send different names to different servers
807 ** (domain name matching) Send new server to other servers.
808 */
809 DLINK_FOREACH(ptr, serv_list.head)
810 {
811 target_p = ptr->data;
812
813 if (target_p == client_p)
814 continue;
815
816 if (IsCapable(target_p, CAP_TS6) && HasID(client_p))
817 sendto_one(target_p, ":%s SID %s 2 %s :%s%s",
818 me.id, client_p->name, client_p->id,
819 IsHidden(client_p) ? "(H) " : "",
820 client_p->info);
821 else
822 sendto_one(target_p,":%s SERVER %s 2 :%s%s",
823 me.name, client_p->name,
824 IsHidden(client_p) ? "(H) " : "",
825 client_p->info);
826 }
827
828 /*
829 * Pass on my client information to the new server
830 *
831 * First, pass only servers (idea is that if the link gets
832 * cancelled beacause the server was already there,
833 * there are no NICK's to be cancelled...). Of course,
834 * if cancellation occurs, all this info is sent anyway,
835 * and I guess the link dies when a read is attempted...? --msa
836 *
837 * Note: Link cancellation to occur at this point means
838 * that at least two servers from my fragment are building
839 * up connection this other fragment at the same time, it's
840 * a race condition, not the normal way of operation...
841 *
842 * ALSO NOTE: using the get_client_name for server names--
843 * see previous *WARNING*!!! (Also, original inpath
844 * is destroyed...)
845 */
846
847 DLINK_FOREACH_PREV(ptr, global_serv_list.tail)
848 {
849 target_p = ptr->data;
850
851 /* target_p->from == target_p for target_p == client_p */
852 if (IsMe(target_p) || target_p->from == client_p)
853 continue;
854
855 if (IsCapable(client_p, CAP_TS6))
856 {
857 if (HasID(target_p))
858 sendto_one(client_p, ":%s SID %s %d %s :%s%s",
859 ID(target_p->servptr), target_p->name, target_p->hopcount+1,
860 target_p->id, IsHidden(target_p) ? "(H) " : "",
861 target_p->info);
862 else /* introducing non-ts6 server */
863 sendto_one(client_p, ":%s SERVER %s %d :%s%s",
864 ID(target_p->servptr), target_p->name, target_p->hopcount+1,
865 IsHidden(target_p) ? "(H) " : "", target_p->info);
866 }
867 else
868 sendto_one(client_p, ":%s SERVER %s %d :%s%s",
869 target_p->servptr->name, target_p->name, target_p->hopcount+1,
870 IsHidden(target_p) ? "(H) " : "", target_p->info);
871
872 if (HasFlag(target_p, FLAGS_EOB))
873 sendto_one(client_p, ":%s EOB", ID_or_name(client_p, target_p));
874 }
875
876 server_burst(client_p);
877 }
878
879 /* server_burst()
880 *
881 * inputs - struct Client pointer server
882 * -
883 * output - none
884 * side effects - send a server burst
885 * bugs - still too long
886 */
887 static void
888 server_burst(struct Client *client_p)
889 {
890 /* Send it in the shortened format with the TS, if
891 ** it's a TS server; walk the list of channels, sending
892 ** all the nicks that haven't been sent yet for each
893 ** channel, then send the channel itself -- it's less
894 ** obvious than sending all nicks first, but on the
895 ** receiving side memory will be allocated more nicely
896 ** saving a few seconds in the handling of a split
897 ** -orabidoo
898 */
899
900 burst_all(client_p);
901
902 /* EOB stuff is now in burst_all */
903 /* Always send a PING after connect burst is done */
904 sendto_one(client_p, "PING :%s", ID_or_name(&me, client_p));
905 }
906
907 /* burst_all()
908 *
909 * inputs - pointer to server to send burst to
910 * output - NONE
911 * side effects - complete burst of channels/nicks is sent to client_p
912 */
913 static void
914 burst_all(struct Client *client_p)
915 {
916 dlink_node *ptr = NULL;
917
918 DLINK_FOREACH(ptr, global_channel_list.head)
919 {
920 struct Channel *chptr = ptr->data;
921
922 if (dlink_list_length(&chptr->members) != 0)
923 {
924 burst_members(client_p, chptr);
925 send_channel_modes(client_p, chptr);
926
927 if (IsCapable(client_p, CAP_TBURST))
928 send_tb(client_p, chptr);
929 }
930 }
931
932 /* also send out those that are not on any channel
933 */
934 DLINK_FOREACH(ptr, global_client_list.head)
935 {
936 struct Client *target_p = ptr->data;
937
938 if (!HasFlag(target_p, FLAGS_BURSTED) && target_p->from != client_p)
939 sendnick_TS(client_p, target_p);
940
941 DelFlag(target_p, FLAGS_BURSTED);
942 }
943
944 if (IsCapable(client_p, CAP_EOB))
945 sendto_one(client_p, ":%s EOB", ID_or_name(&me, client_p));
946 }
947
948 /*
949 * send_tb
950 *
951 * inputs - pointer to Client
952 * - pointer to channel
953 * output - NONE
954 * side effects - Called on a server burst when
955 * server is CAP_TBURST capable
956 */
957 static void
958 send_tb(struct Client *client_p, struct Channel *chptr)
959 {
960 /*
961 * We may also send an empty topic here, but only if topic_time isn't 0,
962 * i.e. if we had a topic that got unset. This is required for syncing
963 * topics properly.
964 *
965 * Imagine the following scenario: Our downlink introduces a channel
966 * to us with a TS that is equal to ours, but the channel topic on
967 * their side got unset while the servers were in splitmode, which means
968 * their 'topic' is newer. They simply wanted to unset it, so we have to
969 * deal with it in a more sophisticated fashion instead of just resetting
970 * it to their old topic they had before. Read m_tburst.c:ms_tburst
971 * for further information -Michael
972 */
973 if (chptr->topic_time != 0)
974 sendto_one(client_p, ":%s TBURST %Tu %s %Tu %s :%s",
975 ID_or_name(&me, client_p),
976 chptr->channelts, chptr->chname,
977 chptr->topic_time,
978 chptr->topic_info,
979 chptr->topic);
980 }
981
982 /* burst_members()
983 *
984 * inputs - pointer to server to send members to
985 * - dlink_list pointer to membership list to send
986 * output - NONE
987 * side effects -
988 */
989 static void
990 burst_members(struct Client *client_p, struct Channel *chptr)
991 {
992 struct Client *target_p;
993 struct Membership *ms;
994 dlink_node *ptr;
995
996 DLINK_FOREACH(ptr, chptr->members.head)
997 {
998 ms = ptr->data;
999 target_p = ms->client_p;
1000
1001 if (!HasFlag(target_p, FLAGS_BURSTED))
1002 {
1003 AddFlag(target_p, FLAGS_BURSTED);
1004
1005 if (target_p->from != client_p)
1006 sendnick_TS(client_p, target_p);
1007 }
1008 }
1009 }
1010
1011 struct Client *
1012 find_servconn_in_progress(const char *name)
1013 {
1014 dlink_node *ptr;
1015 struct Client *cptr;
1016
1017 DLINK_FOREACH(ptr, unknown_list.head)
1018 {
1019 cptr = ptr->data;
1020
1021 if (cptr && cptr->name[0])
1022 if (!match(name, cptr->name))
1023 return cptr;
1024 }
1025
1026 return NULL;
1027 }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision

svnadmin@ircd-hybrid.org
ViewVC Help
Powered by ViewVC 1.1.28