ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/s_serv.c
Revision: 1303
Committed: Fri Mar 23 10:52:19 2012 UTC (12 years ago) by michael
Content type: text/x-csrc
File size: 45810 byte(s)
Log Message:
- Implement basic tls connections for server-server links

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

Properties

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