ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/s_serv.c
Revision: 2156
Committed: Fri May 31 20:53:11 2013 UTC (12 years, 2 months ago) by michael
Content type: text/x-csrc
File size: 43305 byte(s)
Log Message:
- Cleanup flattened links code

File Contents

# Content
1 /*
2 * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3 * s_serv.c: Server related functions.
4 *
5 * Copyright (C) 2005 by the past and present ircd coders, and others.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 * USA
21 *
22 * $Id$
23 */
24
25 #include "stdinc.h"
26 #ifdef HAVE_LIBCRYPTO
27 #include <openssl/rsa.h>
28 #include "rsa.h"
29 #endif
30 #include "list.h"
31 #include "channel.h"
32 #include "channel_mode.h"
33 #include "client.h"
34 #include "dbuf.h"
35 #include "event.h"
36 #include "fdlist.h"
37 #include "hash.h"
38 #include "irc_string.h"
39 #include "ircd.h"
40 #include "ircd_defs.h"
41 #include "s_bsd.h"
42 #include "numeric.h"
43 #include "packet.h"
44 #include "irc_res.h"
45 #include "conf.h"
46 #include "s_serv.h"
47 #include "log.h"
48 #include "s_misc.h"
49 #include "s_user.h"
50 #include "send.h"
51 #include "memory.h"
52 #include "channel.h" /* chcap_usage_counts stuff...*/
53 #include "parse.h"
54
55 #define MIN_CONN_FREQ 300
56
57 dlink_list flatten_links;
58 static dlink_list cap_list = { NULL, NULL, 0 };
59 static void server_burst(struct Client *);
60 static void burst_all(struct Client *);
61 static void send_tb(struct Client *client_p, struct Channel *chptr);
62
63 static CNCB serv_connect_callback;
64
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(void *notused)
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 dlinkAdd(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 /* hunt_server()
125 * Do the basic thing in delivering the message (command)
126 * across the relays to the specific server (server) for
127 * actions.
128 *
129 * Note: The command is a format string and *MUST* be
130 * of prefixed style (e.g. ":%s COMMAND %s ...").
131 * Command can have only max 8 parameters.
132 *
133 * server parv[server] is the parameter identifying the
134 * target server.
135 *
136 * *WARNING*
137 * parv[server] is replaced with the pointer to the
138 * real servername from the matched client (I'm lazy
139 * now --msa).
140 *
141 * returns: (see #defines)
142 */
143 int
144 hunt_server(struct Client *client_p, struct Client *source_p, const char *command,
145 const int server, const int parc, char *parv[])
146 {
147 struct Client *target_p = NULL;
148 struct Client *target_tmp = NULL;
149 dlink_node *ptr;
150 int wilds;
151
152 /* Assume it's me, if no server */
153 if (parc <= server || EmptyString(parv[server]))
154 return HUNTED_ISME;
155
156 if (!strcmp(parv[server], me.id) || !match(parv[server], me.name))
157 return HUNTED_ISME;
158
159 /* These are to pickup matches that would cause the following
160 * message to go in the wrong direction while doing quick fast
161 * non-matching lookups.
162 */
163 if (MyClient(source_p))
164 target_p = hash_find_client(parv[server]);
165 else
166 target_p = find_person(client_p, parv[server]);
167
168 if (target_p)
169 if (target_p->from == source_p->from && !MyConnect(target_p))
170 target_p = NULL;
171
172 if (target_p == NULL && (target_p = hash_find_server(parv[server])))
173 if (target_p->from == source_p->from && !MyConnect(target_p))
174 target_p = NULL;
175
176 wilds = has_wildcards(parv[server]);
177
178 /* Again, if there are no wild cards involved in the server
179 * name, use the hash lookup
180 */
181 if (target_p == NULL)
182 {
183 if (!wilds)
184 {
185 if (!(target_p = hash_find_server(parv[server])))
186 {
187 sendto_one(source_p, form_str(ERR_NOSUCHSERVER),
188 me.name, source_p->name, parv[server]);
189 return(HUNTED_NOSUCH);
190 }
191 }
192 else
193 {
194 DLINK_FOREACH(ptr, global_client_list.head)
195 {
196 target_tmp = ptr->data;
197
198 if (!match(parv[server], target_tmp->name))
199 {
200 if (target_tmp->from == source_p->from && !MyConnect(target_tmp))
201 continue;
202 target_p = ptr->data;
203
204 if (IsRegistered(target_p) && (target_p != client_p))
205 break;
206 }
207 }
208 }
209 }
210
211 if (target_p != NULL)
212 {
213 if(!IsRegistered(target_p))
214 {
215 sendto_one(source_p, form_str(ERR_NOSUCHSERVER),
216 me.name, source_p->name, parv[server]);
217 return HUNTED_NOSUCH;
218 }
219
220 if (IsMe(target_p) || MyClient(target_p))
221 return HUNTED_ISME;
222
223 if (match(target_p->name, parv[server]))
224 parv[server] = target_p->name;
225
226 /* This is a little kludgy but should work... */
227 if (IsClient(source_p) &&
228 ((MyConnect(target_p) && IsCapable(target_p, CAP_TS6)) ||
229 (!MyConnect(target_p) && IsCapable(target_p->from, CAP_TS6))))
230 parv[0] = ID(source_p);
231
232 sendto_one(target_p, command, parv[0],
233 parv[1], parv[2], parv[3], parv[4],
234 parv[5], parv[6], parv[7], parv[8]);
235 return HUNTED_PASS;
236 }
237
238 sendto_one(source_p, form_str(ERR_NOSUCHSERVER),
239 me.name, source_p->name, parv[server]);
240 return HUNTED_NOSUCH;
241 }
242
243 /* try_connections()
244 *
245 * inputs - void pointer which is not used
246 * output - NONE
247 * side effects -
248 * scan through configuration and try new connections.
249 * Returns the calendar time when the next call to this
250 * function should be made latest. (No harm done if this
251 * is called earlier or later...)
252 */
253 void
254 try_connections(void *unused)
255 {
256 dlink_node *ptr = NULL;
257 struct MaskItem *conf;
258 int confrq;
259
260 /* TODO: change this to set active flag to 0 when added to event! --Habeeb */
261 if (GlobalSetOptions.autoconn == 0)
262 return;
263
264 DLINK_FOREACH(ptr, server_items.head)
265 {
266 conf = ptr->data;
267
268 assert(conf->type == CONF_SERVER);
269
270 /* Also when already connecting! (update holdtimes) --SRB
271 */
272 if (!conf->port ||!IsConfAllowAutoConn(conf))
273 continue;
274
275
276 /* Skip this entry if the use of it is still on hold until
277 * future. Otherwise handle this entry (and set it on hold
278 * until next time). Will reset only hold times, if already
279 * made one successfull connection... [this algorithm is
280 * a bit fuzzy... -- msa >;) ]
281 */
282 if (conf->until > CurrentTime)
283 continue;
284
285 if (conf->class == NULL)
286 confrq = DEFAULT_CONNECTFREQUENCY;
287 else
288 {
289 confrq = conf->class->con_freq;
290 if (confrq < MIN_CONN_FREQ)
291 confrq = MIN_CONN_FREQ;
292 }
293
294 conf->until = CurrentTime + confrq;
295
296 /* Found a CONNECT config with port specified, scan clients
297 * and see if this server is already connected?
298 */
299 if (hash_find_server(conf->name) != NULL)
300 continue;
301
302 if (conf->class->ref_count < conf->class->max_total)
303 {
304 /* Go to the end of the list, if not already last */
305 if (ptr->next != NULL)
306 {
307 dlinkDelete(ptr, &server_items);
308 dlinkAddTail(conf, &conf->node, &server_items);
309 }
310
311 if (find_servconn_in_progress(conf->name))
312 return;
313
314 /* We used to only print this if serv_connect() actually
315 * succeeded, but since comm_tcp_connect() can call the callback
316 * immediately if there is an error, we were getting error messages
317 * in the wrong order. SO, we just print out the activated line,
318 * and let serv_connect() / serv_connect_callback() print an
319 * error afterwards if it fails.
320 * -- adrian
321 */
322 if (ConfigServerHide.hide_server_ips)
323 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
324 "Connection to %s activated.",
325 conf->name);
326 else
327 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
328 "Connection to %s[%s] activated.",
329 conf->name, conf->host);
330
331 serv_connect(conf, NULL);
332 /* We connect only one at time... */
333 return;
334 }
335 }
336 }
337
338 int
339 valid_servname(const char *name)
340 {
341 unsigned int length = 0;
342 unsigned int dots = 0;
343 const char *p = name;
344
345 for (; *p; ++p)
346 {
347 if (!IsServChar(*p))
348 return 0;
349
350 ++length;
351
352 if (*p == '.')
353 ++dots;
354 }
355
356 return dots != 0 && length <= HOSTLEN;
357 }
358
359 int
360 check_server(const char *name, struct Client *client_p)
361 {
362 dlink_node *ptr;
363 struct MaskItem *conf = NULL;
364 struct MaskItem *server_conf = NULL;
365 int error = -1;
366
367 assert(client_p != NULL);
368
369 /* loop through looking for all possible connect items that might work */
370 DLINK_FOREACH(ptr, server_items.head)
371 {
372 conf = ptr->data;
373
374 if (match(name, conf->name))
375 continue;
376
377 error = -3;
378
379 /* XXX: Fix me for IPv6 */
380 /* XXX sockhost is the IPv4 ip as a string */
381 if (!match(conf->host, client_p->host) ||
382 !match(conf->host, client_p->sockhost))
383 {
384 error = -2;
385
386 if (!match_conf_password(client_p->localClient->passwd, conf))
387 return -2;
388
389 server_conf = conf;
390 }
391 }
392
393 if (server_conf == NULL)
394 return(error);
395
396 attach_conf(client_p, server_conf);
397
398
399 if (server_conf != NULL)
400 {
401 struct sockaddr_in *v4;
402 #ifdef IPV6
403 struct sockaddr_in6 *v6;
404 #endif
405 switch (server_conf->aftype)
406 {
407 #ifdef IPV6
408 case AF_INET6:
409 v6 = (struct sockaddr_in6 *)&server_conf->addr;
410
411 if (IN6_IS_ADDR_UNSPECIFIED(&v6->sin6_addr))
412 memcpy(&server_conf->addr, &client_p->localClient->ip, sizeof(struct irc_ssaddr));
413 break;
414 #endif
415 case AF_INET:
416 v4 = (struct sockaddr_in *)&server_conf->addr;
417
418 if (v4->sin_addr.s_addr == INADDR_NONE)
419 memcpy(&server_conf->addr, &client_p->localClient->ip, sizeof(struct irc_ssaddr));
420 break;
421 }
422 }
423
424 return(0);
425 }
426
427 /* add_capability()
428 *
429 * inputs - string name of CAPAB
430 * - int flag of capability
431 * output - NONE
432 * side effects - Adds given capability name and bit mask to
433 * current supported capabilities. This allows
434 * modules to dynamically add or subtract their capability.
435 */
436 void
437 add_capability(const char *capab_name, int cap_flag, int add_to_default)
438 {
439 struct Capability *cap = MyMalloc(sizeof(*cap));
440
441 cap->name = xstrdup(capab_name);
442 cap->cap = cap_flag;
443 dlinkAdd(cap, &cap->node, &cap_list);
444
445 if (add_to_default)
446 default_server_capabs |= cap_flag;
447 }
448
449 /* delete_capability()
450 *
451 * inputs - string name of CAPAB
452 * output - NONE
453 * side effects - delete given capability from ones known.
454 */
455 int
456 delete_capability(const char *capab_name)
457 {
458 dlink_node *ptr;
459 dlink_node *next_ptr;
460 struct Capability *cap;
461
462 DLINK_FOREACH_SAFE(ptr, next_ptr, cap_list.head)
463 {
464 cap = ptr->data;
465
466 if (cap->cap != 0)
467 {
468 if (irccmp(cap->name, capab_name) == 0)
469 {
470 default_server_capabs &= ~(cap->cap);
471 dlinkDelete(ptr, &cap_list);
472 MyFree(cap->name);
473 MyFree(cap);
474 }
475 }
476 }
477
478 return 0;
479 }
480
481 /*
482 * find_capability()
483 *
484 * inputs - string name of capab to find
485 * output - 0 if not found CAPAB otherwise
486 * side effects - none
487 */
488 unsigned int
489 find_capability(const char *capab)
490 {
491 const dlink_node *ptr = NULL;
492
493 DLINK_FOREACH(ptr, cap_list.head)
494 {
495 const struct Capability *cap = ptr->data;
496
497 if (cap->cap && !irccmp(cap->name, capab))
498 return cap->cap;
499 }
500
501 return 0;
502 }
503
504 /* send_capabilities()
505 *
506 * inputs - Client pointer to send to
507 * - int flag of capabilities that this server can send
508 * output - NONE
509 * side effects - send the CAPAB line to a server -orabidoo
510 *
511 */
512 void
513 send_capabilities(struct Client *client_p, int cap_can_send)
514 {
515 struct Capability *cap=NULL;
516 char msgbuf[IRCD_BUFSIZE];
517 char *t;
518 int tl;
519 dlink_node *ptr;
520
521 t = msgbuf;
522
523 DLINK_FOREACH(ptr, cap_list.head)
524 {
525 cap = ptr->data;
526
527 if (cap->cap & (cap_can_send|default_server_capabs))
528 {
529 tl = sprintf(t, "%s ", cap->name);
530 t += tl;
531 }
532 }
533
534 *(t - 1) = '\0';
535 sendto_one(client_p, "CAPAB :%s", msgbuf);
536 }
537
538 /* sendnick_TS()
539 *
540 * inputs - client (server) to send nick towards
541 * - client to send nick for
542 * output - NONE
543 * side effects - NICK message is sent towards given client_p
544 */
545 void
546 sendnick_TS(struct Client *client_p, struct Client *target_p)
547 {
548 static char ubuf[12];
549
550 if (!IsClient(target_p))
551 return;
552
553 send_umode(NULL, target_p, 0, SEND_UMODES, ubuf);
554
555 if (ubuf[0] == '\0')
556 {
557 ubuf[0] = '+';
558 ubuf[1] = '\0';
559 }
560
561 if (IsCapable(client_p, CAP_SVS))
562 {
563 if (HasID(target_p) && IsCapable(client_p, CAP_TS6))
564 sendto_one(client_p, ":%s UID %s %d %lu %s %s %s %s %s %s :%s",
565 target_p->servptr->id,
566 target_p->name, target_p->hopcount + 1,
567 (unsigned long) target_p->tsinfo,
568 ubuf, target_p->username, target_p->host,
569 (MyClient(target_p) && IsIPSpoof(target_p)) ?
570 "0" : target_p->sockhost, target_p->id,
571 target_p->svid, target_p->info);
572 else
573 sendto_one(client_p, "NICK %s %d %lu %s %s %s %s %s :%s",
574 target_p->name, target_p->hopcount + 1,
575 (unsigned long) target_p->tsinfo,
576 ubuf, target_p->username, target_p->host,
577 target_p->servptr->name, target_p->svid,
578 target_p->info);
579 }
580 else
581 {
582 if (HasID(target_p) && IsCapable(client_p, CAP_TS6))
583 sendto_one(client_p, ":%s UID %s %d %lu %s %s %s %s %s :%s",
584 target_p->servptr->id,
585 target_p->name, target_p->hopcount + 1,
586 (unsigned long) target_p->tsinfo,
587 ubuf, target_p->username, target_p->host,
588 (MyClient(target_p) && IsIPSpoof(target_p)) ?
589 "0" : target_p->sockhost, target_p->id, target_p->info);
590 else
591 sendto_one(client_p, "NICK %s %d %lu %s %s %s %s :%s",
592 target_p->name, target_p->hopcount + 1,
593 (unsigned long) target_p->tsinfo,
594 ubuf, target_p->username, target_p->host,
595 target_p->servptr->name, target_p->info);
596 }
597
598 if (target_p->away[0])
599 sendto_one(client_p, ":%s AWAY :%s", ID_or_name(target_p, client_p),
600 target_p->away);
601
602 }
603
604 /*
605 * show_capabilities - show current server capabilities
606 *
607 * inputs - pointer to a struct Client
608 * output - pointer to static string
609 * side effects - build up string representing capabilities of server listed
610 */
611 const char *
612 show_capabilities(struct Client *target_p)
613 {
614 static char msgbuf[IRCD_BUFSIZE];
615 char *t = msgbuf;
616 dlink_node *ptr;
617
618 t += sprintf(msgbuf, "TS ");
619
620 DLINK_FOREACH(ptr, cap_list.head)
621 {
622 const struct Capability *cap = ptr->data;
623
624 if (IsCapable(target_p, cap->cap))
625 t += sprintf(t, "%s ", cap->name);
626 }
627
628 *(t - 1) = '\0';
629 return msgbuf;
630 }
631
632 /* make_server()
633 *
634 * inputs - pointer to client struct
635 * output - pointer to struct Server
636 * side effects - add's an Server information block to a client
637 * if it was not previously allocated.
638 */
639 struct Server *
640 make_server(struct Client *client_p)
641 {
642 if (client_p->serv == NULL)
643 client_p->serv = MyMalloc(sizeof(struct Server));
644
645 return client_p->serv;
646 }
647
648 /* server_estab()
649 *
650 * inputs - pointer to a struct Client
651 * output -
652 * side effects -
653 */
654 void
655 server_estab(struct Client *client_p)
656 {
657 struct Client *target_p;
658 struct MaskItem *conf = NULL;
659 char *host;
660 const char *inpath;
661 static char inpath_ip[HOSTLEN * 2 + USERLEN + 6];
662 dlink_node *ptr;
663 #ifdef HAVE_LIBCRYPTO
664 const COMP_METHOD *compression = NULL, *expansion = NULL;
665 #endif
666
667 assert(client_p != NULL);
668
669 strlcpy(inpath_ip, get_client_name(client_p, SHOW_IP), sizeof(inpath_ip));
670
671 inpath = get_client_name(client_p, MASK_IP); /* "refresh" inpath with host */
672 host = client_p->name;
673
674 if ((conf = find_conf_name(&client_p->localClient->confs, host, CONF_SERVER))
675 == NULL)
676 {
677 /* This shouldn't happen, better tell the ops... -A1kmm */
678 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
679 "Warning: Lost connect{} block "
680 "for server %s(this shouldn't happen)!", host);
681 exit_client(client_p, &me, "Lost connect{} block!");
682 return;
683 }
684
685 MyFree(client_p->localClient->passwd);
686 client_p->localClient->passwd = NULL;
687
688 /* Its got identd, since its a server */
689 SetGotId(client_p);
690
691 /* If there is something in the serv_list, it might be this
692 * connecting server..
693 */
694 if (!ServerInfo.hub && serv_list.head)
695 {
696 if (client_p != serv_list.head->data || serv_list.head->next)
697 {
698 ++ServerStats.is_ref;
699 sendto_one(client_p, "ERROR :I'm a leaf not a hub");
700 exit_client(client_p, &me, "I'm a leaf");
701 return;
702 }
703 }
704
705 if (IsUnknown(client_p))
706 {
707 sendto_one(client_p, "PASS %s TS %d %s", conf->spasswd, TS_CURRENT, me.id);
708
709 send_capabilities(client_p, 0);
710
711 sendto_one(client_p, "SERVER %s 1 :%s%s",
712 me.name, ConfigServerHide.hidden ? "(H) " : "", me.info);
713 }
714
715 sendto_one(client_p, "SVINFO %d %d 0 :%lu", TS_CURRENT, TS_MIN,
716 (unsigned long)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 /* XXX Does this ever happen? I don't think so -db */
723 detach_conf(client_p, CONF_OPER);
724
725 /* *WARNING*
726 ** In the following code in place of plain server's
727 ** name we send what is returned by get_client_name
728 ** which may add the "sockhost" after the name. It's
729 ** *very* *important* that there is a SPACE between
730 ** the name and sockhost (if present). The receiving
731 ** server will start the information field from this
732 ** first blank and thus puts the sockhost into info.
733 ** ...a bit tricky, but you have been warned, besides
734 ** code is more neat this way... --msa
735 */
736 client_p->servptr = &me;
737
738 if (IsClosing(client_p))
739 return;
740
741 SetServer(client_p);
742
743 /* Update the capability combination usage counts. -A1kmm */
744 set_chcap_usage_counts(client_p);
745
746 /* Some day, all these lists will be consolidated *sigh* */
747 dlinkAdd(client_p, &client_p->lnode, &me.serv->server_list);
748
749 assert(dlinkFind(&unknown_list, client_p));
750
751 dlink_move_node(&client_p->localClient->lclient_node,
752 &unknown_list, &serv_list);
753
754 Count.myserver++;
755
756 dlinkAdd(client_p, make_dlink_node(), &global_serv_list);
757 hash_add_client(client_p);
758
759 /* doesnt duplicate client_p->serv if allocated this struct already */
760 make_server(client_p);
761
762 /* fixing eob timings.. -gnp */
763 client_p->localClient->firsttime = CurrentTime;
764
765 if (find_matching_name_conf(CONF_SERVICE, client_p->name, NULL, NULL, 0))
766 AddFlag(client_p, FLAGS_SERVICE);
767
768 /* Show the real host/IP to admins */
769 #ifdef HAVE_LIBCRYPTO
770 if (client_p->localClient->fd.ssl)
771 {
772 compression = SSL_get_current_compression(client_p->localClient->fd.ssl);
773 expansion = SSL_get_current_expansion(client_p->localClient->fd.ssl);
774
775 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
776 "Link with %s established: [SSL: %s, Compression/Expansion method: %s/%s] (Capabilities: %s)",
777 inpath_ip, ssl_get_cipher(client_p->localClient->fd.ssl),
778 compression ? SSL_COMP_get_name(compression) : "NONE",
779 expansion ? SSL_COMP_get_name(expansion) : "NONE",
780 show_capabilities(client_p));
781 /* Now show the masked hostname/IP to opers */
782 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
783 "Link with %s established: [SSL: %s, Compression/Expansion method: %s/%s] (Capabilities: %s)",
784 inpath, ssl_get_cipher(client_p->localClient->fd.ssl),
785 compression ? SSL_COMP_get_name(compression) : "NONE",
786 expansion ? SSL_COMP_get_name(expansion) : "NONE",
787 show_capabilities(client_p));
788 ilog(LOG_TYPE_IRCD, "Link with %s established: [SSL: %s, Compression/Expansion method: %s/%s] (Capabilities: %s)",
789 inpath_ip, ssl_get_cipher(client_p->localClient->fd.ssl),
790 compression ? SSL_COMP_get_name(compression) : "NONE",
791 expansion ? SSL_COMP_get_name(expansion) : "NONE",
792 show_capabilities(client_p));
793 }
794 else
795 #endif
796 {
797 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
798 "Link with %s established: (Capabilities: %s)",
799 inpath_ip, show_capabilities(client_p));
800 /* Now show the masked hostname/IP to opers */
801 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
802 "Link with %s established: (Capabilities: %s)",
803 inpath, show_capabilities(client_p));
804 ilog(LOG_TYPE_IRCD, "Link with %s established: (Capabilities: %s)",
805 inpath_ip, show_capabilities(client_p));
806 }
807
808 fd_note(&client_p->localClient->fd, "Server: %s", client_p->name);
809
810 /* Old sendto_serv_but_one() call removed because we now
811 ** need to send different names to different servers
812 ** (domain name matching) Send new server to other servers.
813 */
814 DLINK_FOREACH(ptr, serv_list.head)
815 {
816 target_p = ptr->data;
817
818 if (target_p == client_p)
819 continue;
820
821 if (IsCapable(target_p, CAP_TS6) && HasID(client_p))
822 sendto_one(target_p, ":%s SID %s 2 %s :%s%s",
823 me.id, client_p->name, client_p->id,
824 IsHidden(client_p) ? "(H) " : "",
825 client_p->info);
826 else
827 sendto_one(target_p,":%s SERVER %s 2 :%s%s",
828 me.name, client_p->name,
829 IsHidden(client_p) ? "(H) " : "",
830 client_p->info);
831 }
832
833 /* Pass on my client information to the new server
834 **
835 ** First, pass only servers (idea is that if the link gets
836 ** cancelled beacause the server was already there,
837 ** there are no NICK's to be cancelled...). Of course,
838 ** if cancellation occurs, all this info is sent anyway,
839 ** and I guess the link dies when a read is attempted...? --msa
840 **
841 ** Note: Link cancellation to occur at this point means
842 ** that at least two servers from my fragment are building
843 ** up connection this other fragment at the same time, it's
844 ** a race condition, not the normal way of operation...
845 **
846 ** ALSO NOTE: using the get_client_name for server names--
847 ** see previous *WARNING*!!! (Also, original inpath
848 ** is destroyed...)
849 */
850
851 DLINK_FOREACH_PREV(ptr, global_serv_list.tail)
852 {
853 target_p = ptr->data;
854
855 /* target_p->from == target_p for target_p == client_p */
856 if (IsMe(target_p) || target_p->from == client_p)
857 continue;
858
859 if (IsCapable(client_p, CAP_TS6))
860 {
861 if (HasID(target_p))
862 sendto_one(client_p, ":%s SID %s %d %s :%s%s",
863 ID(target_p->servptr), target_p->name, target_p->hopcount+1,
864 target_p->id, IsHidden(target_p) ? "(H) " : "",
865 target_p->info);
866 else /* introducing non-ts6 server */
867 sendto_one(client_p, ":%s SERVER %s %d :%s%s",
868 ID(target_p->servptr), target_p->name, target_p->hopcount+1,
869 IsHidden(target_p) ? "(H) " : "", target_p->info);
870 }
871 else
872 sendto_one(client_p, ":%s SERVER %s %d :%s%s",
873 target_p->servptr->name, target_p->name, target_p->hopcount+1,
874 IsHidden(target_p) ? "(H) " : "", target_p->info);
875
876 if (HasFlag(target_p, FLAGS_EOB))
877 sendto_one(client_p, ":%s EOB", ID_or_name(client_p, target_p));
878 }
879
880 server_burst(client_p);
881 }
882
883 /* server_burst()
884 *
885 * inputs - struct Client pointer server
886 * -
887 * output - none
888 * side effects - send a server burst
889 * bugs - still too long
890 */
891 static void
892 server_burst(struct Client *client_p)
893 {
894 /* Send it in the shortened format with the TS, if
895 ** it's a TS server; walk the list of channels, sending
896 ** all the nicks that haven't been sent yet for each
897 ** channel, then send the channel itself -- it's less
898 ** obvious than sending all nicks first, but on the
899 ** receiving side memory will be allocated more nicely
900 ** saving a few seconds in the handling of a split
901 ** -orabidoo
902 */
903
904 burst_all(client_p);
905
906 /* EOB stuff is now in burst_all */
907 /* Always send a PING after connect burst is done */
908 sendto_one(client_p, "PING :%s", ID_or_name(&me, client_p));
909 }
910
911 /* burst_all()
912 *
913 * inputs - pointer to server to send burst to
914 * output - NONE
915 * side effects - complete burst of channels/nicks is sent to client_p
916 */
917 static void
918 burst_all(struct Client *client_p)
919 {
920 dlink_node *ptr = NULL;
921
922 DLINK_FOREACH(ptr, global_channel_list.head)
923 {
924 struct Channel *chptr = ptr->data;
925
926 if (dlink_list_length(&chptr->members) != 0)
927 {
928 burst_members(client_p, chptr);
929 send_channel_modes(client_p, chptr);
930
931 if (IsCapable(client_p, CAP_TBURST))
932 send_tb(client_p, chptr);
933 }
934 }
935
936 /* also send out those that are not on any channel
937 */
938 DLINK_FOREACH(ptr, global_client_list.head)
939 {
940 struct Client *target_p = ptr->data;
941
942 if (!HasFlag(target_p, FLAGS_BURSTED) && target_p->from != client_p)
943 sendnick_TS(client_p, target_p);
944
945 DelFlag(target_p, FLAGS_BURSTED);
946 }
947
948 if (IsCapable(client_p, CAP_EOB))
949 sendto_one(client_p, ":%s EOB", ID_or_name(&me, client_p));
950 }
951
952 /*
953 * send_tb
954 *
955 * inputs - pointer to Client
956 * - pointer to channel
957 * output - NONE
958 * side effects - Called on a server burst when
959 * server is CAP_TBURST capable
960 */
961 static void
962 send_tb(struct Client *client_p, struct Channel *chptr)
963 {
964 /*
965 * We may also send an empty topic here, but only if topic_time isn't 0,
966 * i.e. if we had a topic that got unset. This is required for syncing
967 * topics properly.
968 *
969 * Imagine the following scenario: Our downlink introduces a channel
970 * to us with a TS that is equal to ours, but the channel topic on
971 * their side got unset while the servers were in splitmode, which means
972 * their 'topic' is newer. They simply wanted to unset it, so we have to
973 * deal with it in a more sophisticated fashion instead of just resetting
974 * it to their old topic they had before. Read m_tburst.c:ms_tburst
975 * for further information -Michael
976 */
977 if (chptr->topic_time != 0)
978 sendto_one(client_p, ":%s TBURST %lu %s %lu %s :%s",
979 ID_or_name(&me, client_p),
980 (unsigned long)chptr->channelts, chptr->chname,
981 (unsigned long)chptr->topic_time,
982 chptr->topic_info,
983 chptr->topic);
984 }
985
986 /* burst_members()
987 *
988 * inputs - pointer to server to send members to
989 * - dlink_list pointer to membership list to send
990 * output - NONE
991 * side effects -
992 */
993 static void
994 burst_members(struct Client *client_p, struct Channel *chptr)
995 {
996 struct Client *target_p;
997 struct Membership *ms;
998 dlink_node *ptr;
999
1000 DLINK_FOREACH(ptr, chptr->members.head)
1001 {
1002 ms = ptr->data;
1003 target_p = ms->client_p;
1004
1005 if (!HasFlag(target_p, FLAGS_BURSTED))
1006 {
1007 AddFlag(target_p, FLAGS_BURSTED);
1008
1009 if (target_p->from != client_p)
1010 sendnick_TS(client_p, target_p);
1011 }
1012 }
1013 }
1014
1015 /* New server connection code
1016 * Based upon the stuff floating about in s_bsd.c
1017 * -- adrian
1018 */
1019
1020 /* serv_connect() - initiate a server connection
1021 *
1022 * inputs - pointer to conf
1023 * - pointer to client doing the connect
1024 * output -
1025 * side effects -
1026 *
1027 * This code initiates a connection to a server. It first checks to make
1028 * sure the given server exists. If this is the case, it creates a socket,
1029 * creates a client, saves the socket information in the client, and
1030 * initiates a connection to the server through comm_connect_tcp(). The
1031 * completion of this goes through serv_completed_connection().
1032 *
1033 * We return 1 if the connection is attempted, since we don't know whether
1034 * it suceeded or not, and 0 if it fails in here somewhere.
1035 */
1036 int
1037 serv_connect(struct MaskItem *conf, struct Client *by)
1038 {
1039 struct Client *client_p;
1040 char buf[HOSTIPLEN + 1];
1041
1042 /* conversion structs */
1043 struct sockaddr_in *v4;
1044 /* Make sure conf is useful */
1045 assert(conf != NULL);
1046
1047
1048 getnameinfo((struct sockaddr *)&conf->addr, conf->addr.ss_len,
1049 buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);
1050 ilog(LOG_TYPE_IRCD, "Connect to %s[%s] @%s", conf->name, conf->host,
1051 buf);
1052
1053 /* Still processing a DNS lookup? -> exit */
1054 if (conf->dns_pending)
1055 {
1056 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1057 "Error connecting to %s: DNS lookup for connect{} in progress.",
1058 conf->name);
1059 return (0);
1060 }
1061
1062 if (conf->dns_failed)
1063 {
1064 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1065 "Error connecting to %s: DNS lookup for connect{} failed.",
1066 conf->name);
1067 return (0);
1068 }
1069
1070 /* Make sure this server isn't already connected
1071 * Note: conf should ALWAYS be a valid C: line
1072 */
1073 if ((client_p = hash_find_server(conf->name)) != NULL)
1074 {
1075 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
1076 "Server %s already present from %s",
1077 conf->name, get_client_name(client_p, SHOW_IP));
1078 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
1079 "Server %s already present from %s",
1080 conf->name, get_client_name(client_p, MASK_IP));
1081 if (by && IsClient(by) && !MyClient(by))
1082 sendto_one(by, ":%s NOTICE %s :Server %s already present from %s",
1083 me.name, by->name, conf->name,
1084 get_client_name(client_p, MASK_IP));
1085 return 0;
1086 }
1087
1088 /* Create a local client */
1089 client_p = make_client(NULL);
1090
1091 /* Copy in the server, hostname, fd */
1092 strlcpy(client_p->name, conf->name, sizeof(client_p->name));
1093 strlcpy(client_p->host, conf->host, sizeof(client_p->host));
1094
1095 /* We already converted the ip once, so lets use it - stu */
1096 strlcpy(client_p->sockhost, buf, sizeof(client_p->sockhost));
1097
1098 /* create a socket for the server connection */
1099 if (comm_open(&client_p->localClient->fd, conf->addr.ss.ss_family,
1100 SOCK_STREAM, 0, NULL) < 0)
1101 {
1102 /* Eek, failure to create the socket */
1103 report_error(L_ALL, "opening stream socket to %s: %s",
1104 conf->name, errno);
1105 SetDead(client_p);
1106 exit_client(client_p, &me, "Connection failed");
1107 return 0;
1108 }
1109
1110 /* servernames are always guaranteed under HOSTLEN chars */
1111 fd_note(&client_p->localClient->fd, "Server: %s", conf->name);
1112
1113 /* Attach config entries to client here rather than in
1114 * serv_connect_callback(). This to avoid null pointer references.
1115 */
1116 if (!attach_connect_block(client_p, conf->name, conf->host))
1117 {
1118 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1119 "Host %s is not enabled for connecting: no connect{} block",
1120 conf->name);
1121 if (by && IsClient(by) && !MyClient(by))
1122 sendto_one(by, ":%s NOTICE %s :Connect to host %s failed.",
1123 me.name, by->name, client_p->name);
1124 SetDead(client_p);
1125 exit_client(client_p, client_p, "Connection failed");
1126 return 0;
1127 }
1128
1129 /* at this point we have a connection in progress and C/N lines
1130 * attached to the client, the socket info should be saved in the
1131 * client and it should either be resolved or have a valid address.
1132 *
1133 * The socket has been connected or connect is in progress.
1134 */
1135 make_server(client_p);
1136
1137 if (by && IsClient(by))
1138 strlcpy(client_p->serv->by, by->name, sizeof(client_p->serv->by));
1139 else
1140 strlcpy(client_p->serv->by, "AutoConn.", sizeof(client_p->serv->by));
1141
1142 SetConnecting(client_p);
1143 dlinkAdd(client_p, &client_p->node, &global_client_list);
1144 /* from def_fam */
1145 client_p->localClient->aftype = conf->aftype;
1146
1147 /* Now, initiate the connection */
1148 /* XXX assume that a non 0 type means a specific bind address
1149 * for this connect.
1150 */
1151 switch (conf->aftype)
1152 {
1153 case AF_INET:
1154 v4 = (struct sockaddr_in*)&conf->bind;
1155 if (v4->sin_addr.s_addr != 0)
1156 {
1157 struct irc_ssaddr ipn;
1158 memset(&ipn, 0, sizeof(struct irc_ssaddr));
1159 ipn.ss.ss_family = AF_INET;
1160 ipn.ss_port = 0;
1161 memcpy(&ipn, &conf->bind, sizeof(struct irc_ssaddr));
1162 comm_connect_tcp(&client_p->localClient->fd, conf->host, conf->port,
1163 (struct sockaddr *)&ipn, ipn.ss_len,
1164 serv_connect_callback, client_p, conf->aftype,
1165 CONNECTTIMEOUT);
1166 }
1167 else if (ServerInfo.specific_ipv4_vhost)
1168 {
1169 struct irc_ssaddr ipn;
1170 memset(&ipn, 0, sizeof(struct irc_ssaddr));
1171 ipn.ss.ss_family = AF_INET;
1172 ipn.ss_port = 0;
1173 memcpy(&ipn, &ServerInfo.ip, sizeof(struct irc_ssaddr));
1174 comm_connect_tcp(&client_p->localClient->fd, conf->host, conf->port,
1175 (struct sockaddr *)&ipn, ipn.ss_len,
1176 serv_connect_callback, client_p, conf->aftype,
1177 CONNECTTIMEOUT);
1178 }
1179 else
1180 comm_connect_tcp(&client_p->localClient->fd, conf->host, conf->port,
1181 NULL, 0, serv_connect_callback, client_p, conf->aftype,
1182 CONNECTTIMEOUT);
1183 break;
1184 #ifdef IPV6
1185 case AF_INET6:
1186 {
1187 struct irc_ssaddr ipn;
1188 struct sockaddr_in6 *v6;
1189 struct sockaddr_in6 *v6conf;
1190
1191 memset(&ipn, 0, sizeof(struct irc_ssaddr));
1192 v6conf = (struct sockaddr_in6 *)&conf->bind;
1193 v6 = (struct sockaddr_in6 *)&ipn;
1194
1195 if (memcmp(&v6conf->sin6_addr, &v6->sin6_addr,
1196 sizeof(struct in6_addr)) != 0)
1197 {
1198 memcpy(&ipn, &conf->bind, sizeof(struct irc_ssaddr));
1199 ipn.ss.ss_family = AF_INET6;
1200 ipn.ss_port = 0;
1201 comm_connect_tcp(&client_p->localClient->fd,
1202 conf->host, conf->port,
1203 (struct sockaddr *)&ipn, ipn.ss_len,
1204 serv_connect_callback, client_p,
1205 conf->aftype, CONNECTTIMEOUT);
1206 }
1207 else if (ServerInfo.specific_ipv6_vhost)
1208 {
1209 memcpy(&ipn, &ServerInfo.ip6, sizeof(struct irc_ssaddr));
1210 ipn.ss.ss_family = AF_INET6;
1211 ipn.ss_port = 0;
1212 comm_connect_tcp(&client_p->localClient->fd,
1213 conf->host, conf->port,
1214 (struct sockaddr *)&ipn, ipn.ss_len,
1215 serv_connect_callback, client_p,
1216 conf->aftype, CONNECTTIMEOUT);
1217 }
1218 else
1219 comm_connect_tcp(&client_p->localClient->fd,
1220 conf->host, conf->port,
1221 NULL, 0, serv_connect_callback, client_p,
1222 conf->aftype, CONNECTTIMEOUT);
1223 }
1224 #endif
1225 }
1226 return (1);
1227 }
1228
1229 #ifdef HAVE_LIBCRYPTO
1230 static void
1231 finish_ssl_server_handshake(struct Client *client_p)
1232 {
1233 struct MaskItem *conf = NULL;
1234
1235 conf = find_conf_name(&client_p->localClient->confs,
1236 client_p->name, CONF_SERVER);
1237 if (conf == NULL)
1238 {
1239 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
1240 "Lost connect{} block for %s", get_client_name(client_p, HIDE_IP));
1241 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
1242 "Lost connect{} block for %s", get_client_name(client_p, MASK_IP));
1243
1244 exit_client(client_p, &me, "Lost connect{} block");
1245 return;
1246 }
1247
1248 sendto_one(client_p, "PASS %s TS %d %s", conf->spasswd, TS_CURRENT, me.id);
1249
1250 send_capabilities(client_p, 0);
1251
1252 sendto_one(client_p, "SERVER %s 1 :%s%s",
1253 me.name, ConfigServerHide.hidden ? "(H) " : "",
1254 me.info);
1255
1256 /* If we've been marked dead because a send failed, just exit
1257 * here now and save everyone the trouble of us ever existing.
1258 */
1259 if (IsDead(client_p))
1260 {
1261 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
1262 "%s[%s] went dead during handshake",
1263 client_p->name,
1264 client_p->host);
1265 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
1266 "%s went dead during handshake", client_p->name);
1267 return;
1268 }
1269
1270 /* don't move to serv_list yet -- we haven't sent a burst! */
1271 /* If we get here, we're ok, so lets start reading some data */
1272 comm_setselect(&client_p->localClient->fd, COMM_SELECT_READ, read_packet, client_p, 0);
1273 }
1274
1275 static void
1276 ssl_server_handshake(fde_t *fd, struct Client *client_p)
1277 {
1278 int ret;
1279 int err;
1280
1281 ret = SSL_connect(client_p->localClient->fd.ssl);
1282
1283 if (ret <= 0)
1284 {
1285 switch ((err = SSL_get_error(client_p->localClient->fd.ssl, ret)))
1286 {
1287 case SSL_ERROR_WANT_WRITE:
1288 comm_setselect(&client_p->localClient->fd, COMM_SELECT_WRITE,
1289 (PF *)ssl_server_handshake, client_p, 0);
1290 return;
1291 case SSL_ERROR_WANT_READ:
1292 comm_setselect(&client_p->localClient->fd, COMM_SELECT_READ,
1293 (PF *)ssl_server_handshake, client_p, 0);
1294 return;
1295 default:
1296 {
1297 const char *sslerr = ERR_error_string(ERR_get_error(), NULL);
1298 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
1299 "Error connecting to %s: %s", client_p->name,
1300 sslerr ? sslerr : "unknown SSL error");
1301 exit_client(client_p, client_p, "Error during SSL handshake");
1302 return;
1303 }
1304 }
1305 }
1306
1307 finish_ssl_server_handshake(client_p);
1308 }
1309
1310 static void
1311 ssl_connect_init(struct Client *client_p, struct MaskItem *conf, fde_t *fd)
1312 {
1313 if ((client_p->localClient->fd.ssl = SSL_new(ServerInfo.client_ctx)) == NULL)
1314 {
1315 ilog(LOG_TYPE_IRCD, "SSL_new() ERROR! -- %s",
1316 ERR_error_string(ERR_get_error(), NULL));
1317 SetDead(client_p);
1318 exit_client(client_p, client_p, "SSL_new failed");
1319 return;
1320 }
1321
1322 SSL_set_fd(fd->ssl, fd->fd);
1323
1324 if (!EmptyString(conf->cipher_list))
1325 SSL_set_cipher_list(client_p->localClient->fd.ssl, conf->cipher_list);
1326
1327 ssl_server_handshake(NULL, client_p);
1328 }
1329 #endif
1330
1331 /* serv_connect_callback() - complete a server connection.
1332 *
1333 * This routine is called after the server connection attempt has
1334 * completed. If unsucessful, an error is sent to ops and the client
1335 * is closed. If sucessful, it goes through the initialisation/check
1336 * procedures, the capabilities are sent, and the socket is then
1337 * marked for reading.
1338 */
1339 static void
1340 serv_connect_callback(fde_t *fd, int status, void *data)
1341 {
1342 struct Client *client_p = data;
1343 struct MaskItem *conf = NULL;
1344
1345 /* First, make sure its a real client! */
1346 assert(client_p != NULL);
1347 assert(&client_p->localClient->fd == fd);
1348
1349 /* Next, for backward purposes, record the ip of the server */
1350 memcpy(&client_p->localClient->ip, &fd->connect.hostaddr,
1351 sizeof(struct irc_ssaddr));
1352 /* Check the status */
1353 if (status != COMM_OK)
1354 {
1355 /* We have an error, so report it and quit
1356 * Admins get to see any IP, mere opers don't *sigh*
1357 */
1358 if (ConfigServerHide.hide_server_ips)
1359 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
1360 "Error connecting to %s: %s",
1361 client_p->name, comm_errstr(status));
1362 else
1363 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
1364 "Error connecting to %s[%s]: %s", client_p->name,
1365 client_p->host, comm_errstr(status));
1366
1367 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
1368 "Error connecting to %s: %s",
1369 client_p->name, comm_errstr(status));
1370
1371 /* If a fd goes bad, call dead_link() the socket is no
1372 * longer valid for reading or writing.
1373 */
1374 dead_link_on_write(client_p, 0);
1375 return;
1376 }
1377
1378 /* COMM_OK, so continue the connection procedure */
1379 /* Get the C/N lines */
1380 conf = find_conf_name(&client_p->localClient->confs,
1381 client_p->name, CONF_SERVER);
1382 if (conf == NULL)
1383 {
1384 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
1385 "Lost connect{} block for %s", get_client_name(client_p, HIDE_IP));
1386 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
1387 "Lost connect{} block for %s", get_client_name(client_p, MASK_IP));
1388
1389 exit_client(client_p, &me, "Lost connect{} block");
1390 return;
1391 }
1392
1393 /* Next, send the initial handshake */
1394 SetHandshake(client_p);
1395
1396 #ifdef HAVE_LIBCRYPTO
1397 if (IsConfSSL(conf))
1398 {
1399 ssl_connect_init(client_p, conf, fd);
1400 return;
1401 }
1402 #endif
1403
1404 sendto_one(client_p, "PASS %s TS %d %s", conf->spasswd, TS_CURRENT, me.id);
1405
1406 send_capabilities(client_p, 0);
1407
1408 sendto_one(client_p, "SERVER %s 1 :%s%s", me.name,
1409 ConfigServerHide.hidden ? "(H) " : "", me.info);
1410
1411 /* If we've been marked dead because a send failed, just exit
1412 * here now and save everyone the trouble of us ever existing.
1413 */
1414 if (IsDead(client_p))
1415 {
1416 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
1417 "%s[%s] went dead during handshake",
1418 client_p->name,
1419 client_p->host);
1420 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
1421 "%s went dead during handshake", client_p->name);
1422 return;
1423 }
1424
1425 /* don't move to serv_list yet -- we haven't sent a burst! */
1426 /* If we get here, we're ok, so lets start reading some data */
1427 comm_setselect(fd, COMM_SELECT_READ, read_packet, client_p, 0);
1428 }
1429
1430 struct Client *
1431 find_servconn_in_progress(const char *name)
1432 {
1433 dlink_node *ptr;
1434 struct Client *cptr;
1435
1436 DLINK_FOREACH(ptr, unknown_list.head)
1437 {
1438 cptr = ptr->data;
1439
1440 if (cptr && cptr->name[0])
1441 if (!match(name, cptr->name))
1442 return cptr;
1443 }
1444
1445 return NULL;
1446 }

Properties

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