ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/s_serv.c
Revision: 1308
Committed: Sat Mar 24 13:37:05 2012 UTC (13 years, 5 months ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid-8/src/s_serv.c
File size: 47095 byte(s)
Log Message:
- ssl_server_handshake(): better error reporting

File Contents

# User Rev Content
1 adx 30 /*
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 knight 31 * $Id$
23 adx 30 */
24    
25     #include "stdinc.h"
26     #ifdef HAVE_LIBCRYPTO
27     #include <openssl/rsa.h>
28     #include "rsa.h"
29     #endif
30 michael 1011 #include "list.h"
31 adx 30 #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 michael 1303 #include "s_misc.h"
50 adx 30 #include "s_user.h"
51     #include "send.h"
52     #include "memory.h"
53     #include "channel.h" /* chcap_usage_counts stuff...*/
54 michael 1243 #include "parse.h"
55 adx 30
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 michael 1169 target_p = hash_find_client(parv[server]);
202 adx 30 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 michael 1169 if (target_p == NULL && (target_p = hash_find_server(parv[server])))
210 adx 30 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 michael 1169 if (!(target_p = hash_find_server(parv[server])))
224 adx 30 {
225     sendto_one(source_p, form_str(ERR_NOSUCHSERVER),
226 michael 1234 me.name, source_p->name, parv[server]);
227 adx 30 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 michael 1234 me.name, source_p->name, parv[server]);
255 adx 30 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 michael 1234 me.name, source_p->name, parv[server]);
278 adx 30 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 michael 1013 aconf = map_to_conf(conf);
308 adx 30
309     /* Also when already connecting! (update holdtimes) --SRB
310     */
311 michael 1013 if (!(aconf->status & CONF_SERVER) || !aconf->port ||
312 adx 30 !(IsConfAllowAutoConn(aconf)))
313     continue;
314    
315 michael 1013 cltmp = map_to_conf(aconf->class_ptr);
316 adx 30
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 michael 1169 if (hash_find_server(conf->name) != NULL)
341 adx 30 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 michael 1115 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 michael 1118 return 0;
388 michael 1115
389     ++length;
390    
391     if (*p == '.')
392     ++dots;
393     }
394    
395 michael 1118 return dots != 0 && length <= HOSTLEN;
396 michael 1115 }
397    
398     int
399 michael 1302 check_server(const char *name, struct Client *client_p)
400 adx 30 {
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 michael 1013 aconf = map_to_conf(conf);
421 adx 30
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 michael 885 server_aconf = map_to_conf(server_conf);
483 adx 30
484     if (!IsConfTopicBurst(server_aconf))
485 michael 329 {
486 adx 30 ClearCap(client_p, CAP_TB);
487 michael 329 ClearCap(client_p, CAP_TBURST);
488     }
489 adx 30
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 michael 885 struct Capability *cap = MyMalloc(sizeof(*cap));
531 adx 30
532     DupString(cap->name, capab_name);
533     cap->cap = cap_flag;
534     dlinkAdd(cap, &cap->node, &cap_list);
535 michael 885
536 adx 30 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 michael 896 return 0;
571 adx 30 }
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 michael 896 const dlink_node *ptr = NULL;
584 adx 30
585     DLINK_FOREACH(ptr, cap_list.head)
586     {
587 michael 896 const struct Capability *cap = ptr->data;
588 adx 30
589 michael 896 if (cap->cap && !irccmp(cap->name, capab))
590     return cap->cap;
591 adx 30 }
592 michael 896
593     return 0;
594 adx 30 }
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 michael 1302 int cap_can_send)
608 adx 30 {
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 michael 319 *(t - 1) = '\0';
629 adx 30 sendto_one(client_p, "CAPAB :%s", msgbuf);
630     }
631    
632     /* sendnick_TS()
633     *
634     * inputs - client (server) to send nick towards
635 adx 386 * - client to send nick for
636 adx 30 * 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 michael 1294 send_umode(NULL, target_p, 0, SEND_UMODES, ubuf);
648 adx 30
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 michael 1196 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 adx 30 else
676 michael 1196 {
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 adx 386
693 adx 30 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 michael 1302
724 adx 30 *(t - 1) = '\0';
725 michael 1302 return msgbuf;
726 adx 30 }
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 michael 1305 #ifdef HAVE_LIBCRYPTO
761     const COMP_METHOD *compression = NULL, *expansion = NULL;
762     #endif
763 adx 30
764     assert(client_p != NULL);
765    
766     strlcpy(inpath_ip, get_client_name(client_p, SHOW_IP), sizeof(inpath_ip));
767    
768     inpath = get_client_name(client_p, MASK_IP); /* "refresh" inpath with host */
769     host = client_p->name;
770    
771     if ((conf = find_conf_name(&client_p->localClient->confs, host, SERVER_TYPE))
772     == NULL)
773     {
774     /* This shouldn't happen, better tell the ops... -A1kmm */
775     sendto_realops_flags(UMODE_ALL, L_ALL, "Warning: Lost connect{} block "
776     "for server %s(this shouldn't happen)!", host);
777     exit_client(client_p, &me, "Lost connect{} block!");
778     return;
779     }
780    
781     MyFree(client_p->localClient->passwd);
782     client_p->localClient->passwd = NULL;
783    
784     /* Its got identd, since its a server */
785     SetGotId(client_p);
786    
787     /* If there is something in the serv_list, it might be this
788     * connecting server..
789     */
790     if (!ServerInfo.hub && serv_list.head)
791     {
792     if (client_p != serv_list.head->data || serv_list.head->next)
793     {
794 michael 896 ++ServerStats.is_ref;
795 adx 30 sendto_one(client_p, "ERROR :I'm a leaf not a hub");
796     exit_client(client_p, &me, "I'm a leaf");
797     return;
798     }
799     }
800    
801 michael 1115 aconf = map_to_conf(conf);
802 adx 30
803 michael 1302 if (IsUnknown(client_p))
804 adx 30 {
805     /* jdc -- 1. Use EmptyString(), not [0] index reference.
806     * 2. Check aconf->spasswd, not aconf->passwd.
807     */
808     if (!EmptyString(aconf->spasswd))
809 michael 1115 sendto_one(client_p, "PASS %s TS %d %s",
810     aconf->spasswd, TS_CURRENT, me.id);
811 adx 30
812     /* Pass my info to the new server
813     *
814     * Pass on ZIP if supported
815     * Pass on TB if supported.
816     * - Dianora
817     */
818    
819 michael 1119 send_capabilities(client_p, aconf,
820 michael 1302 (IsConfTopicBurst(aconf) ? CAP_TBURST|CAP_TB : 0));
821 adx 30
822     sendto_one(client_p, "SERVER %s 1 :%s%s",
823 michael 1118 me.name, ConfigServerHide.hidden ? "(H) " : "", me.info);
824 adx 30 }
825    
826 michael 1115 sendto_one(client_p, "SVINFO %d %d 0 :%lu", TS_CURRENT, TS_MIN,
827 adx 30 (unsigned long)CurrentTime);
828    
829     /* assumption here is if they passed the correct TS version, they also passed an SID */
830     if (IsCapable(client_p, CAP_TS6))
831     hash_add_id(client_p);
832    
833     /* XXX Does this ever happen? I don't think so -db */
834     detach_conf(client_p, OPER_TYPE);
835    
836     /* *WARNING*
837     ** In the following code in place of plain server's
838     ** name we send what is returned by get_client_name
839     ** which may add the "sockhost" after the name. It's
840     ** *very* *important* that there is a SPACE between
841     ** the name and sockhost (if present). The receiving
842     ** server will start the information field from this
843     ** first blank and thus puts the sockhost into info.
844     ** ...a bit tricky, but you have been warned, besides
845     ** code is more neat this way... --msa
846     */
847     client_p->servptr = &me;
848    
849     if (IsClosing(client_p))
850     return;
851    
852     SetServer(client_p);
853    
854     /* Update the capability combination usage counts. -A1kmm */
855     set_chcap_usage_counts(client_p);
856    
857     /* Some day, all these lists will be consolidated *sigh* */
858 michael 889 dlinkAdd(client_p, &client_p->lnode, &me.serv->server_list);
859 adx 30
860 michael 1126 assert(dlinkFind(&unknown_list, client_p));
861 adx 30
862 michael 1126 dlink_move_node(&client_p->localClient->lclient_node,
863     &unknown_list, &serv_list);
864 adx 30
865     Count.myserver++;
866    
867     dlinkAdd(client_p, make_dlink_node(), &global_serv_list);
868     hash_add_client(client_p);
869    
870     /* doesnt duplicate client_p->serv if allocated this struct already */
871     make_server(client_p);
872    
873     /* fixing eob timings.. -gnp */
874 michael 1241 client_p->localClient->firsttime = CurrentTime;
875 adx 30
876 michael 1157 if (find_matching_name_conf(SERVICE_TYPE, client_p->name, NULL, NULL, 0))
877 michael 1219 AddFlag(client_p, FLAGS_SERVICE);
878 michael 1157
879 adx 30 /* Show the real host/IP to admins */
880 michael 1305 #ifdef HAVE_LIBCRYPTO
881 michael 1303 if (client_p->localClient->fd.ssl)
882     {
883 michael 1305 compression = SSL_get_current_compression(client_p->localClient->fd.ssl);
884     expansion = SSL_get_current_expansion(client_p->localClient->fd.ssl);
885    
886 michael 1303 sendto_realops_flags(UMODE_ALL, L_ADMIN,
887 michael 1305 "Link with %s established: [SSL: %s, Compression/Expansion method: %s/%s] (Capabilities: %s)",
888 michael 1303 inpath_ip, ssl_get_cipher(client_p->localClient->fd.ssl),
889 michael 1305 compression ? SSL_COMP_get_name(compression) : "NONE",
890     expansion ? SSL_COMP_get_name(expansion) : "NONE",
891 michael 1303 show_capabilities(client_p));
892     /* Now show the masked hostname/IP to opers */
893     sendto_realops_flags(UMODE_ALL, L_OPER,
894 michael 1305 "Link with %s established: [SSL: %s, Compression/Expansion method: %s/%s] (Capabilities: %s)",
895 michael 1303 inpath, ssl_get_cipher(client_p->localClient->fd.ssl),
896 michael 1305 compression ? SSL_COMP_get_name(compression) : "NONE",
897     expansion ? SSL_COMP_get_name(expansion) : "NONE",
898 michael 1303 show_capabilities(client_p));
899 michael 1305 ilog(LOG_TYPE_IRCD, "Link with %s established: [SSL: %s, Compression/Expansion method: %s/%s] (Capabilities: %s)",
900 michael 1303 inpath_ip, ssl_get_cipher(client_p->localClient->fd.ssl),
901 michael 1305 compression ? SSL_COMP_get_name(compression) : "NONE",
902     expansion ? SSL_COMP_get_name(expansion) : "NONE",
903 michael 1303 show_capabilities(client_p));
904     }
905     else
906 michael 1305 #endif
907 michael 1303 {
908     sendto_realops_flags(UMODE_ALL, L_ADMIN,
909     "Link with %s established: (Capabilities: %s)",
910     inpath_ip,show_capabilities(client_p));
911     /* Now show the masked hostname/IP to opers */
912     sendto_realops_flags(UMODE_ALL, L_OPER,
913     "Link with %s established: (Capabilities: %s)",
914     inpath,show_capabilities(client_p));
915     ilog(LOG_TYPE_IRCD, "Link with %s established: (Capabilities: %s)",
916     inpath_ip, show_capabilities(client_p));
917     }
918 adx 30
919     client_p->serv->sconf = conf;
920    
921 michael 1302 fd_note(&client_p->localClient->fd, "Server: %s", client_p->name);
922 adx 30
923     /* Old sendto_serv_but_one() call removed because we now
924     ** need to send different names to different servers
925     ** (domain name matching) Send new server to other servers.
926     */
927     DLINK_FOREACH(ptr, serv_list.head)
928     {
929     target_p = ptr->data;
930    
931     if (target_p == client_p)
932     continue;
933    
934     if (IsCapable(target_p, CAP_TS6) && HasID(client_p))
935     sendto_one(target_p, ":%s SID %s 2 %s :%s%s",
936     me.id, client_p->name, client_p->id,
937     IsHidden(client_p) ? "(H) " : "",
938     client_p->info);
939     else
940     sendto_one(target_p,":%s SERVER %s 2 :%s%s",
941     me.name, client_p->name,
942     IsHidden(client_p) ? "(H) " : "",
943     client_p->info);
944     }
945    
946     /* Pass on my client information to the new server
947     **
948     ** First, pass only servers (idea is that if the link gets
949     ** cancelled beacause the server was already there,
950     ** there are no NICK's to be cancelled...). Of course,
951     ** if cancellation occurs, all this info is sent anyway,
952     ** and I guess the link dies when a read is attempted...? --msa
953     **
954     ** Note: Link cancellation to occur at this point means
955     ** that at least two servers from my fragment are building
956     ** up connection this other fragment at the same time, it's
957     ** a race condition, not the normal way of operation...
958     **
959     ** ALSO NOTE: using the get_client_name for server names--
960     ** see previous *WARNING*!!! (Also, original inpath
961     ** is destroyed...)
962     */
963    
964     DLINK_FOREACH_PREV(ptr, global_serv_list.tail)
965     {
966     target_p = ptr->data;
967    
968     /* target_p->from == target_p for target_p == client_p */
969 michael 1118 if (IsMe(target_p) || target_p->from == client_p)
970 adx 30 continue;
971    
972     if (IsCapable(client_p, CAP_TS6))
973     {
974     if (HasID(target_p))
975     sendto_one(client_p, ":%s SID %s %d %s :%s%s",
976     ID(target_p->servptr), target_p->name, target_p->hopcount+1,
977     target_p->id, IsHidden(target_p) ? "(H) " : "",
978     target_p->info);
979     else /* introducing non-ts6 server */
980     sendto_one(client_p, ":%s SERVER %s %d :%s%s",
981     ID(target_p->servptr), target_p->name, target_p->hopcount+1,
982     IsHidden(target_p) ? "(H) " : "", target_p->info);
983     }
984     else
985     sendto_one(client_p, ":%s SERVER %s %d :%s%s",
986     target_p->servptr->name, target_p->name, target_p->hopcount+1,
987     IsHidden(target_p) ? "(H) " : "", target_p->info);
988     }
989    
990     server_burst(client_p);
991     }
992    
993     /* server_burst()
994     *
995     * inputs - struct Client pointer server
996     * -
997     * output - none
998     * side effects - send a server burst
999     * bugs - still too long
1000     */
1001     static void
1002     server_burst(struct Client *client_p)
1003     {
1004     /* Send it in the shortened format with the TS, if
1005     ** it's a TS server; walk the list of channels, sending
1006     ** all the nicks that haven't been sent yet for each
1007     ** channel, then send the channel itself -- it's less
1008     ** obvious than sending all nicks first, but on the
1009     ** receiving side memory will be allocated more nicely
1010     ** saving a few seconds in the handling of a split
1011     ** -orabidoo
1012     */
1013    
1014 michael 885 burst_all(client_p);
1015 adx 30
1016     /* EOB stuff is now in burst_all */
1017     /* Always send a PING after connect burst is done */
1018     sendto_one(client_p, "PING :%s", ID_or_name(&me, client_p));
1019     }
1020    
1021     /* burst_all()
1022     *
1023     * inputs - pointer to server to send burst to
1024     * output - NONE
1025     * side effects - complete burst of channels/nicks is sent to client_p
1026     */
1027     static void
1028     burst_all(struct Client *client_p)
1029     {
1030 michael 329 dlink_node *ptr = NULL;
1031 adx 30
1032 michael 329 DLINK_FOREACH(ptr, global_channel_list.head)
1033 adx 30 {
1034 michael 329 struct Channel *chptr = ptr->data;
1035 adx 30
1036     if (dlink_list_length(&chptr->members) != 0)
1037     {
1038     burst_members(client_p, chptr);
1039     send_channel_modes(client_p, chptr);
1040 michael 329
1041     if (IsCapable(client_p, CAP_TBURST) ||
1042     IsCapable(client_p, CAP_TB))
1043 adx 30 send_tb(client_p, chptr);
1044     }
1045     }
1046    
1047     /* also send out those that are not on any channel
1048     */
1049     DLINK_FOREACH(ptr, global_client_list.head)
1050     {
1051 michael 329 struct Client *target_p = ptr->data;
1052 adx 30
1053 michael 1219 if (!HasFlag(target_p, FLAGS_BURSTED) && target_p->from != client_p)
1054 adx 30 sendnick_TS(client_p, target_p);
1055    
1056 michael 1219 DelFlag(target_p, FLAGS_BURSTED);
1057 adx 30 }
1058    
1059     /* We send the time we started the burst, and let the remote host determine an EOB time,
1060     ** as otherwise we end up sending a EOB of 0 Sending here means it gets sent last -- fl
1061     */
1062     /* Its simpler to just send EOB and use the time its been connected.. --fl_ */
1063     if (IsCapable(client_p, CAP_EOB))
1064     sendto_one(client_p, ":%s EOB", ID_or_name(&me, client_p));
1065     }
1066    
1067     /*
1068     * send_tb
1069     *
1070 michael 329 * inputs - pointer to Client
1071     * - pointer to channel
1072     * output - NONE
1073     * side effects - Called on a server burst when
1074     * server is CAP_TB|CAP_TBURST capable
1075 adx 30 */
1076     static void
1077     send_tb(struct Client *client_p, struct Channel *chptr)
1078     {
1079 michael 329 /*
1080 michael 337 * We may also send an empty topic here, but only if topic_time isn't 0,
1081     * i.e. if we had a topic that got unset. This is required for syncing
1082     * topics properly.
1083     *
1084     * Imagine the following scenario: Our downlink introduces a channel
1085     * to us with a TS that is equal to ours, but the channel topic on
1086     * their side got unset while the servers were in splitmode, which means
1087     * their 'topic' is newer. They simply wanted to unset it, so we have to
1088     * deal with it in a more sophisticated fashion instead of just resetting
1089     * it to their old topic they had before. Read m_tburst.c:ms_tburst
1090     * for further information -Michael
1091 michael 329 */
1092 michael 337 if (chptr->topic_time != 0)
1093 adx 30 {
1094 michael 329 if (IsCapable(client_p, CAP_TBURST))
1095     sendto_one(client_p, ":%s TBURST %lu %s %lu %s :%s",
1096     me.name, (unsigned long)chptr->channelts, chptr->chname,
1097 michael 337 (unsigned long)chptr->topic_time,
1098 michael 1203 chptr->topic_info,
1099     chptr->topic);
1100 michael 329 else if (IsCapable(client_p, CAP_TB))
1101 adx 30 {
1102 michael 329 if (ConfigChannel.burst_topicwho)
1103     {
1104     sendto_one(client_p, ":%s TB %s %lu %s :%s",
1105     me.name, chptr->chname,
1106     (unsigned long)chptr->topic_time,
1107 michael 1203 chptr->topic_info, chptr->topic);
1108 michael 329 }
1109     else
1110     {
1111     sendto_one(client_p, ":%s TB %s %lu :%s",
1112     me.name, chptr->chname,
1113 michael 337 (unsigned long)chptr->topic_time,
1114 michael 1203 chptr->topic);
1115 michael 329 }
1116 adx 30 }
1117     }
1118     }
1119    
1120     /* burst_members()
1121     *
1122     * inputs - pointer to server to send members to
1123     * - dlink_list pointer to membership list to send
1124     * output - NONE
1125     * side effects -
1126     */
1127     static void
1128     burst_members(struct Client *client_p, struct Channel *chptr)
1129     {
1130     struct Client *target_p;
1131     struct Membership *ms;
1132     dlink_node *ptr;
1133    
1134     DLINK_FOREACH(ptr, chptr->members.head)
1135     {
1136     ms = ptr->data;
1137     target_p = ms->client_p;
1138    
1139 michael 1219 if (!HasFlag(target_p, FLAGS_BURSTED))
1140 adx 30 {
1141 michael 1219 AddFlag(target_p, FLAGS_BURSTED);
1142 adx 30
1143     if (target_p->from != client_p)
1144     sendnick_TS(client_p, target_p);
1145     }
1146     }
1147     }
1148    
1149     /* New server connection code
1150     * Based upon the stuff floating about in s_bsd.c
1151     * -- adrian
1152     */
1153    
1154     /* serv_connect() - initiate a server connection
1155     *
1156     * inputs - pointer to conf
1157     * - pointer to client doing the connect
1158     * output -
1159     * side effects -
1160     *
1161     * This code initiates a connection to a server. It first checks to make
1162     * sure the given server exists. If this is the case, it creates a socket,
1163     * creates a client, saves the socket information in the client, and
1164     * initiates a connection to the server through comm_connect_tcp(). The
1165     * completion of this goes through serv_completed_connection().
1166     *
1167     * We return 1 if the connection is attempted, since we don't know whether
1168     * it suceeded or not, and 0 if it fails in here somewhere.
1169     */
1170     int
1171     serv_connect(struct AccessItem *aconf, struct Client *by)
1172     {
1173     struct ConfItem *conf;
1174     struct Client *client_p;
1175     char buf[HOSTIPLEN];
1176    
1177     /* conversion structs */
1178     struct sockaddr_in *v4;
1179     /* Make sure aconf is useful */
1180     assert(aconf != NULL);
1181    
1182     if(aconf == NULL)
1183     return (0);
1184    
1185     /* XXX should be passing struct ConfItem in the first place */
1186     conf = unmap_conf_item(aconf);
1187    
1188     /* log */
1189 michael 1123 getnameinfo((struct sockaddr *)&aconf->ipnum, aconf->ipnum.ss_len,
1190     buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);
1191 michael 1247 ilog(LOG_TYPE_IRCD, "Connect to %s[%s] @%s", aconf->user, aconf->host,
1192 adx 30 buf);
1193    
1194     /* Still processing a DNS lookup? -> exit */
1195 michael 992 if (aconf->dns_pending)
1196 adx 30 {
1197 michael 992 sendto_realops_flags(UMODE_ALL, L_ALL,
1198     "Error connecting to %s: DNS lookup for connect{} in progress.",
1199     conf->name);
1200 adx 30 return (0);
1201     }
1202    
1203 michael 992 if (aconf->dns_failed)
1204     {
1205     sendto_realops_flags(UMODE_ALL, L_ALL,
1206     "Error connecting to %s: DNS lookup for connect{} failed.",
1207     conf->name);
1208     return (0);
1209     }
1210    
1211 adx 30 /* Make sure this server isn't already connected
1212     * Note: aconf should ALWAYS be a valid C: line
1213     */
1214 michael 1169 if ((client_p = hash_find_server(conf->name)) != NULL)
1215 adx 30 {
1216     sendto_realops_flags(UMODE_ALL, L_ADMIN,
1217     "Server %s already present from %s",
1218     conf->name, get_client_name(client_p, SHOW_IP));
1219     sendto_realops_flags(UMODE_ALL, L_OPER,
1220     "Server %s already present from %s",
1221     conf->name, get_client_name(client_p, MASK_IP));
1222     if (by && IsClient(by) && !MyClient(by))
1223     sendto_one(by, ":%s NOTICE %s :Server %s already present from %s",
1224     me.name, by->name, conf->name,
1225     get_client_name(client_p, MASK_IP));
1226     return (0);
1227     }
1228    
1229     /* Create a local client */
1230     client_p = make_client(NULL);
1231    
1232     /* Copy in the server, hostname, fd */
1233     strlcpy(client_p->name, conf->name, sizeof(client_p->name));
1234     strlcpy(client_p->host, aconf->host, sizeof(client_p->host));
1235    
1236     /* We already converted the ip once, so lets use it - stu */
1237 michael 1115 strlcpy(client_p->sockhost, buf, sizeof(client_p->sockhost));
1238 adx 30
1239     /* create a socket for the server connection */
1240     if (comm_open(&client_p->localClient->fd, aconf->ipnum.ss.ss_family,
1241     SOCK_STREAM, 0, NULL) < 0)
1242     {
1243     /* Eek, failure to create the socket */
1244     report_error(L_ALL,
1245     "opening stream socket to %s: %s", conf->name, errno);
1246     SetDead(client_p);
1247     exit_client(client_p, &me, "Connection failed");
1248     return (0);
1249     }
1250    
1251     /* servernames are always guaranteed under HOSTLEN chars */
1252     fd_note(&client_p->localClient->fd, "Server: %s", conf->name);
1253    
1254     /* Attach config entries to client here rather than in
1255     * serv_connect_callback(). This to avoid null pointer references.
1256     */
1257     if (!attach_connect_block(client_p, conf->name, aconf->host))
1258     {
1259     sendto_realops_flags(UMODE_ALL, L_ALL,
1260     "Host %s is not enabled for connecting:no C/N-line",
1261     conf->name);
1262     if (by && IsClient(by) && !MyClient(by))
1263     sendto_one(by, ":%s NOTICE %s :Connect to host %s failed.",
1264     me.name, by->name, client_p->name);
1265     SetDead(client_p);
1266     exit_client(client_p, client_p, "Connection failed");
1267     return (0);
1268     }
1269    
1270     /* at this point we have a connection in progress and C/N lines
1271     * attached to the client, the socket info should be saved in the
1272     * client and it should either be resolved or have a valid address.
1273     *
1274     * The socket has been connected or connect is in progress.
1275     */
1276     make_server(client_p);
1277    
1278     if (by && IsClient(by))
1279     strlcpy(client_p->serv->by, by->name, sizeof(client_p->serv->by));
1280     else
1281     strlcpy(client_p->serv->by, "AutoConn.", sizeof(client_p->serv->by));
1282    
1283     SetConnecting(client_p);
1284     dlinkAdd(client_p, &client_p->node, &global_client_list);
1285     /* from def_fam */
1286     client_p->localClient->aftype = aconf->aftype;
1287    
1288     /* Now, initiate the connection */
1289     /* XXX assume that a non 0 type means a specific bind address
1290     * for this connect.
1291     */
1292     switch (aconf->aftype)
1293     {
1294     case AF_INET:
1295     v4 = (struct sockaddr_in*)&aconf->my_ipnum;
1296     if (v4->sin_addr.s_addr != 0)
1297     {
1298     struct irc_ssaddr ipn;
1299     memset(&ipn, 0, sizeof(struct irc_ssaddr));
1300     ipn.ss.ss_family = AF_INET;
1301     ipn.ss_port = 0;
1302     memcpy(&ipn, &aconf->my_ipnum, sizeof(struct irc_ssaddr));
1303     comm_connect_tcp(&client_p->localClient->fd, aconf->host, aconf->port,
1304     (struct sockaddr *)&ipn, ipn.ss_len,
1305     serv_connect_callback, client_p, aconf->aftype,
1306     CONNECTTIMEOUT);
1307     }
1308     else if (ServerInfo.specific_ipv4_vhost)
1309     {
1310     struct irc_ssaddr ipn;
1311     memset(&ipn, 0, sizeof(struct irc_ssaddr));
1312     ipn.ss.ss_family = AF_INET;
1313     ipn.ss_port = 0;
1314     memcpy(&ipn, &ServerInfo.ip, sizeof(struct irc_ssaddr));
1315     comm_connect_tcp(&client_p->localClient->fd, aconf->host, aconf->port,
1316     (struct sockaddr *)&ipn, ipn.ss_len,
1317     serv_connect_callback, client_p, aconf->aftype,
1318     CONNECTTIMEOUT);
1319     }
1320     else
1321     comm_connect_tcp(&client_p->localClient->fd, aconf->host, aconf->port,
1322     NULL, 0, serv_connect_callback, client_p, aconf->aftype,
1323     CONNECTTIMEOUT);
1324     break;
1325     #ifdef IPV6
1326     case AF_INET6:
1327     {
1328     struct irc_ssaddr ipn;
1329     struct sockaddr_in6 *v6;
1330     struct sockaddr_in6 *v6conf;
1331    
1332     memset(&ipn, 0, sizeof(struct irc_ssaddr));
1333     v6conf = (struct sockaddr_in6 *)&aconf->my_ipnum;
1334     v6 = (struct sockaddr_in6 *)&ipn;
1335    
1336     if (memcmp(&v6conf->sin6_addr, &v6->sin6_addr,
1337     sizeof(struct in6_addr)) != 0)
1338     {
1339     memcpy(&ipn, &aconf->my_ipnum, sizeof(struct irc_ssaddr));
1340     ipn.ss.ss_family = AF_INET6;
1341     ipn.ss_port = 0;
1342     comm_connect_tcp(&client_p->localClient->fd,
1343     aconf->host, aconf->port,
1344     (struct sockaddr *)&ipn, ipn.ss_len,
1345     serv_connect_callback, client_p,
1346     aconf->aftype, CONNECTTIMEOUT);
1347     }
1348     else if (ServerInfo.specific_ipv6_vhost)
1349     {
1350     memcpy(&ipn, &ServerInfo.ip6, sizeof(struct irc_ssaddr));
1351     ipn.ss.ss_family = AF_INET6;
1352     ipn.ss_port = 0;
1353     comm_connect_tcp(&client_p->localClient->fd,
1354     aconf->host, aconf->port,
1355     (struct sockaddr *)&ipn, ipn.ss_len,
1356     serv_connect_callback, client_p,
1357     aconf->aftype, CONNECTTIMEOUT);
1358     }
1359     else
1360     comm_connect_tcp(&client_p->localClient->fd,
1361     aconf->host, aconf->port,
1362     NULL, 0, serv_connect_callback, client_p,
1363     aconf->aftype, CONNECTTIMEOUT);
1364     }
1365     #endif
1366     }
1367     return (1);
1368     }
1369    
1370 michael 1303 #ifdef HAVE_LIBCRYPTO
1371     static void
1372     finish_ssl_server_handshake(struct Client *client_p)
1373     {
1374     struct ConfItem *conf=NULL;
1375     struct AccessItem *aconf=NULL;
1376    
1377     conf = find_conf_name(&client_p->localClient->confs,
1378     client_p->name, SERVER_TYPE);
1379     if (conf == NULL)
1380     {
1381     sendto_realops_flags(UMODE_ALL, L_ADMIN,
1382     "Lost connect{} block for %s", get_client_name(client_p, HIDE_IP));
1383     sendto_realops_flags(UMODE_ALL, L_OPER,
1384     "Lost connect{} block for %s", get_client_name(client_p, MASK_IP));
1385    
1386     exit_client(client_p, &me, "Lost connect{} block");
1387     return;
1388     }
1389    
1390     aconf = map_to_conf(conf);
1391    
1392     /* jdc -- Check and send spasswd, not passwd. */
1393     if (!EmptyString(aconf->spasswd))
1394     sendto_one(client_p, "PASS %s TS %d %s",
1395     aconf->spasswd, TS_CURRENT, me.id);
1396    
1397     send_capabilities(client_p, aconf,
1398     (IsConfTopicBurst(aconf) ? CAP_TBURST|CAP_TB : 0));
1399    
1400     sendto_one(client_p, "SERVER %s 1 :%s%s",
1401     me.name, ConfigServerHide.hidden ? "(H) " : "",
1402     me.info);
1403    
1404     /* If we've been marked dead because a send failed, just exit
1405     * here now and save everyone the trouble of us ever existing.
1406     */
1407     if (IsDead(client_p))
1408     {
1409     sendto_realops_flags(UMODE_ALL, L_ADMIN,
1410     "%s[%s] went dead during handshake",
1411     client_p->name,
1412     client_p->host);
1413     sendto_realops_flags(UMODE_ALL, L_OPER,
1414     "%s went dead during handshake", client_p->name);
1415     return;
1416     }
1417    
1418     /* don't move to serv_list yet -- we haven't sent a burst! */
1419     /* If we get here, we're ok, so lets start reading some data */
1420     comm_setselect(&client_p->localClient->fd, COMM_SELECT_READ, read_packet, client_p, 0);
1421     }
1422    
1423     static void
1424 michael 1306 ssl_server_handshake(fde_t *fd, struct Client *client_p)
1425 michael 1303 {
1426     int ret;
1427     int err;
1428    
1429     ret = SSL_connect(client_p->localClient->fd.ssl);
1430    
1431     if (ret <= 0)
1432     {
1433     switch ((err = SSL_get_error(client_p->localClient->fd.ssl, ret)))
1434     {
1435     case SSL_ERROR_WANT_WRITE:
1436     comm_setselect(&client_p->localClient->fd, COMM_SELECT_WRITE,
1437 michael 1308 (PF *)ssl_server_handshake, client_p, 0);
1438 michael 1303 return;
1439     case SSL_ERROR_WANT_READ:
1440     comm_setselect(&client_p->localClient->fd, COMM_SELECT_READ,
1441 michael 1308 (PF *)ssl_server_handshake, client_p, 0);
1442 michael 1303 return;
1443     default:
1444 michael 1308 {
1445     const char *sslerr = ERR_error_string(ERR_get_error(), NULL);
1446     sendto_realops_flags(UMODE_ALL, L_ALL,
1447     "Error connecting to %s: %s", client_p->name,
1448     sslerr ? sslerr : "unknown SSL error");
1449 michael 1303 exit_client(client_p, client_p, "Error during SSL handshake");
1450     return;
1451 michael 1308 }
1452 michael 1303 }
1453     }
1454    
1455     finish_ssl_server_handshake(client_p);
1456     }
1457    
1458     static void
1459 michael 1306 ssl_connect_init(struct Client *client_p, struct AccessItem *aconf, fde_t *fd)
1460 michael 1303 {
1461     if ((client_p->localClient->fd.ssl = SSL_new(ServerInfo.client_ctx)) == NULL)
1462     {
1463     ilog(LOG_TYPE_IRCD, "SSL_new() ERROR! -- %s",
1464     ERR_error_string(ERR_get_error(), NULL));
1465     SetDead(client_p);
1466     exit_client(client_p, client_p, "SSL_new failed");
1467     return;
1468     }
1469    
1470     SSL_set_fd(fd->ssl, fd->fd);
1471 michael 1306
1472     if (!EmptyString(aconf->cipher_list))
1473     SSL_set_cipher_list(client_p->localClient->fd.ssl, aconf->cipher_list);
1474    
1475     ssl_server_handshake(NULL, client_p);
1476 michael 1303 }
1477     #endif
1478    
1479 adx 30 /* serv_connect_callback() - complete a server connection.
1480     *
1481     * This routine is called after the server connection attempt has
1482     * completed. If unsucessful, an error is sent to ops and the client
1483     * is closed. If sucessful, it goes through the initialisation/check
1484     * procedures, the capabilities are sent, and the socket is then
1485     * marked for reading.
1486     */
1487     static void
1488     serv_connect_callback(fde_t *fd, int status, void *data)
1489     {
1490     struct Client *client_p = data;
1491     struct ConfItem *conf=NULL;
1492     struct AccessItem *aconf=NULL;
1493    
1494     /* First, make sure its a real client! */
1495     assert(client_p != NULL);
1496     assert(&client_p->localClient->fd == fd);
1497    
1498     /* Next, for backward purposes, record the ip of the server */
1499     memcpy(&client_p->localClient->ip, &fd->connect.hostaddr,
1500     sizeof(struct irc_ssaddr));
1501     /* Check the status */
1502     if (status != COMM_OK)
1503     {
1504     /* We have an error, so report it and quit
1505     * Admins get to see any IP, mere opers don't *sigh*
1506     */
1507     if (ConfigServerHide.hide_server_ips)
1508     sendto_realops_flags(UMODE_ALL, L_ADMIN,
1509     "Error connecting to %s: %s",
1510     client_p->name, comm_errstr(status));
1511     else
1512     sendto_realops_flags(UMODE_ALL, L_ADMIN,
1513     "Error connecting to %s[%s]: %s", client_p->name,
1514     client_p->host, comm_errstr(status));
1515    
1516     sendto_realops_flags(UMODE_ALL, L_OPER,
1517     "Error connecting to %s: %s",
1518     client_p->name, comm_errstr(status));
1519    
1520     /* If a fd goes bad, call dead_link() the socket is no
1521     * longer valid for reading or writing.
1522     */
1523     dead_link_on_write(client_p, 0);
1524     return;
1525     }
1526    
1527     /* COMM_OK, so continue the connection procedure */
1528     /* Get the C/N lines */
1529     conf = find_conf_name(&client_p->localClient->confs,
1530     client_p->name, SERVER_TYPE);
1531     if (conf == NULL)
1532     {
1533     sendto_realops_flags(UMODE_ALL, L_ADMIN,
1534     "Lost connect{} block for %s", get_client_name(client_p, HIDE_IP));
1535     sendto_realops_flags(UMODE_ALL, L_OPER,
1536     "Lost connect{} block for %s", get_client_name(client_p, MASK_IP));
1537    
1538     exit_client(client_p, &me, "Lost connect{} block");
1539     return;
1540     }
1541    
1542 michael 1303 aconf = map_to_conf(conf);
1543 adx 30 /* Next, send the initial handshake */
1544     SetHandshake(client_p);
1545    
1546     #ifdef HAVE_LIBCRYPTO
1547 michael 1303 if (IsConfSSL(aconf))
1548     {
1549 michael 1306 ssl_connect_init(client_p, aconf, fd);
1550 michael 1303 return;
1551     }
1552 adx 30 #endif
1553    
1554     /* jdc -- Check and send spasswd, not passwd. */
1555 michael 1115 if (!EmptyString(aconf->spasswd))
1556 adx 30 sendto_one(client_p, "PASS %s TS %d %s",
1557     aconf->spasswd, TS_CURRENT, me.id);
1558    
1559 michael 1119 send_capabilities(client_p, aconf,
1560 michael 1302 (IsConfTopicBurst(aconf) ? CAP_TBURST|CAP_TB : 0));
1561 adx 30
1562     sendto_one(client_p, "SERVER %s 1 :%s%s",
1563 michael 1118 me.name, ConfigServerHide.hidden ? "(H) " : "",
1564 adx 30 me.info);
1565    
1566     /* If we've been marked dead because a send failed, just exit
1567     * here now and save everyone the trouble of us ever existing.
1568     */
1569     if (IsDead(client_p))
1570     {
1571     sendto_realops_flags(UMODE_ALL, L_ADMIN,
1572     "%s[%s] went dead during handshake",
1573     client_p->name,
1574     client_p->host);
1575     sendto_realops_flags(UMODE_ALL, L_OPER,
1576     "%s went dead during handshake", client_p->name);
1577     return;
1578     }
1579    
1580     /* don't move to serv_list yet -- we haven't sent a burst! */
1581     /* If we get here, we're ok, so lets start reading some data */
1582     comm_setselect(fd, COMM_SELECT_READ, read_packet, client_p, 0);
1583     }
1584    
1585     struct Client *
1586     find_servconn_in_progress(const char *name)
1587     {
1588     dlink_node *ptr;
1589     struct Client *cptr;
1590    
1591     DLINK_FOREACH(ptr, unknown_list.head)
1592     {
1593     cptr = ptr->data;
1594    
1595     if (cptr && cptr->name[0])
1596 michael 1118 if (match(name, cptr->name))
1597 adx 30 return cptr;
1598     }
1599    
1600     return NULL;
1601     }

Properties

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