ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/server.c
Revision: 1793
Committed: Sun Mar 31 14:06:08 2013 UTC (12 years, 5 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid/trunk/src/s_serv.c
File size: 43841 byte(s)
Log Message:
- Replaced all occurrences of ircsprintf with sprintf/snprintf
  and killed sprintf_irc.(c|h)

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

Properties

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