ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/trunk/src/server.c
Revision: 1321
Committed: Fri Mar 30 11:23:16 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: 47052 byte(s)
Log Message:
- remove unused variables

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

Properties

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