ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/branches/8.2.x/src/server.c
Revision: 3320
Committed: Tue Apr 15 15:58:33 2014 UTC (10 years ago) by michael
Content type: text/x-csrc
Original Path: ircd-hybrid/trunk/src/s_serv.c
File size: 29872 byte(s)
Log Message:
- Removed useless header includes

File Contents

# User Rev Content
1 adx 30 /*
2 michael 2916 * ircd-hybrid: an advanced, lightweight Internet Relay Chat Daemon (ircd)
3 adx 30 *
4 michael 2916 * Copyright (c) 1997-2014 ircd-hybrid development team
5 adx 30 *
6     * This program is free software; you can redistribute it and/or modify
7     * it under the terms of the GNU General Public License as published by
8     * the Free Software Foundation; either version 2 of the License, or
9     * (at your option) any later version.
10     *
11     * This program is distributed in the hope that it will be useful,
12     * but WITHOUT ANY WARRANTY; without even the implied warranty of
13     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14     * GNU General Public License for more details.
15     *
16     * You should have received a copy of the GNU General Public License
17     * along with this program; if not, write to the Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19     * USA
20     */
21    
22 michael 2916 /*! \file s_serv.c
23     * \brief Server related functions.
24     * \version $Id$
25     */
26    
27 adx 30 #include "stdinc.h"
28     #ifdef HAVE_LIBCRYPTO
29     #include <openssl/rsa.h>
30     #include "rsa.h"
31     #endif
32 michael 1011 #include "list.h"
33 adx 30 #include "client.h"
34     #include "event.h"
35     #include "hash.h"
36     #include "irc_string.h"
37     #include "ircd.h"
38     #include "ircd_defs.h"
39     #include "s_bsd.h"
40     #include "numeric.h"
41     #include "packet.h"
42 michael 1309 #include "conf.h"
43 adx 30 #include "s_serv.h"
44 michael 1309 #include "log.h"
45 adx 30 #include "s_user.h"
46     #include "send.h"
47     #include "memory.h"
48 michael 2916 #include "channel.h"
49 michael 1243 #include "parse.h"
50 adx 30
51     #define MIN_CONN_FREQ 300
52    
53 michael 2156 dlink_list flatten_links;
54 adx 30 static dlink_list cap_list = { NULL, NULL, 0 };
55     static CNCB serv_connect_callback;
56    
57    
58     /*
59     * write_links_file
60     *
61     * inputs - void pointer which is not used
62     * output - NONE
63     * side effects - called from an event, write out list of linked servers
64     * but in no particular order.
65     */
66     void
67 michael 2156 write_links_file(void *notused)
68 adx 30 {
69 michael 2156 FILE *file = NULL;
70 michael 2216 dlink_node *ptr = NULL, *ptr_next = NULL;
71 michael 3215 char buff[IRCD_BUFSIZE] = "";
72 adx 30
73 michael 2156 if ((file = fopen(LIPATH, "w")) == NULL)
74 adx 30 return;
75    
76 michael 2156 DLINK_FOREACH_SAFE(ptr, ptr_next, flatten_links.head)
77 adx 30 {
78 michael 2156 dlinkDelete(ptr, &flatten_links);
79     MyFree(ptr->data);
80     free_dlink_node(ptr);
81 adx 30 }
82    
83     DLINK_FOREACH(ptr, global_serv_list.head)
84     {
85 michael 1325 const struct Client *target_p = ptr->data;
86 adx 30
87 michael 2156 /*
88     * Skip hidden servers, aswell as ourselves, since we already send
89     * ourselves in /links
90     */
91     if (IsHidden(target_p) || IsMe(target_p))
92 adx 30 continue;
93    
94 michael 1851 if (HasFlag(target_p, FLAGS_SERVICE) && ConfigServerHide.hide_services)
95     continue;
96    
97 michael 1545 /*
98     * Attempt to format the file in such a way it follows the usual links output
99 adx 30 * ie "servername uplink :hops info"
100     * Mostly for aesthetic reasons - makes it look pretty in mIRC ;)
101     * - madmax
102     */
103 michael 2156 snprintf(buff, sizeof(buff), "%s %s :1 %s", target_p->name,
104     me.name, target_p->info);
105 michael 2212 dlinkAddTail(xstrdup(buff), make_dlink_node(), &flatten_links);
106 michael 2156 snprintf(buff, sizeof(buff), "%s %s :1 %s\n", target_p->name,
107     me.name, target_p->info);
108 adx 30
109 michael 1325 fputs(buff, file);
110 adx 30 }
111    
112 michael 1325 fclose(file);
113 adx 30 }
114    
115 michael 2216 void
116     read_links_file(void)
117     {
118     FILE *file = NULL;
119     char *p = NULL;
120 michael 3215 char buff[IRCD_BUFSIZE] = "";
121 michael 2216
122     if ((file = fopen(LIPATH, "r")) == NULL)
123     return;
124    
125     while (fgets(buff, sizeof(buff), file))
126     {
127 michael 3246 if ((p = strchr(buff, '\n')))
128 michael 2216 *p = '\0';
129    
130     dlinkAddTail(xstrdup(buff), make_dlink_node(), &flatten_links);
131     }
132    
133     fclose(file);
134     }
135    
136 adx 30 /* hunt_server()
137     * Do the basic thing in delivering the message (command)
138     * across the relays to the specific server (server) for
139     * actions.
140     *
141     * Note: The command is a format string and *MUST* be
142     * of prefixed style (e.g. ":%s COMMAND %s ...").
143     * Command can have only max 8 parameters.
144     *
145     * server parv[server] is the parameter identifying the
146     * target server.
147     *
148     * *WARNING*
149     * parv[server] is replaced with the pointer to the
150     * real servername from the matched client (I'm lazy
151     * now --msa).
152     *
153     * returns: (see #defines)
154     */
155     int
156 michael 3156 hunt_server(struct Client *source_p, const char *command,
157 michael 1857 const int server, const int parc, char *parv[])
158 adx 30 {
159     struct Client *target_p = NULL;
160     struct Client *target_tmp = NULL;
161     dlink_node *ptr;
162     int wilds;
163    
164 michael 1344 /* Assume it's me, if no server */
165     if (parc <= server || EmptyString(parv[server]))
166     return HUNTED_ISME;
167 adx 30
168 michael 1652 if (!strcmp(parv[server], me.id) || !match(parv[server], me.name))
169 michael 1344 return HUNTED_ISME;
170    
171 adx 30 /* These are to pickup matches that would cause the following
172     * message to go in the wrong direction while doing quick fast
173     * non-matching lookups.
174     */
175     if (MyClient(source_p))
176 michael 1169 target_p = hash_find_client(parv[server]);
177 adx 30 else
178 michael 3156 target_p = find_person(source_p, parv[server]);
179 adx 30
180     if (target_p)
181     if (target_p->from == source_p->from && !MyConnect(target_p))
182     target_p = NULL;
183    
184 michael 1169 if (target_p == NULL && (target_p = hash_find_server(parv[server])))
185 adx 30 if (target_p->from == source_p->from && !MyConnect(target_p))
186     target_p = NULL;
187    
188 michael 1400 wilds = has_wildcards(parv[server]);
189 adx 30
190     /* Again, if there are no wild cards involved in the server
191     * name, use the hash lookup
192     */
193     if (target_p == NULL)
194     {
195     if (!wilds)
196     {
197 michael 1169 if (!(target_p = hash_find_server(parv[server])))
198 adx 30 {
199 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOSUCHSERVER, parv[server]);
200 michael 2182 return HUNTED_NOSUCH;
201 adx 30 }
202     }
203     else
204     {
205     DLINK_FOREACH(ptr, global_client_list.head)
206     {
207     target_tmp = ptr->data;
208    
209 michael 1652 if (!match(parv[server], target_tmp->name))
210 adx 30 {
211     if (target_tmp->from == source_p->from && !MyConnect(target_tmp))
212     continue;
213     target_p = ptr->data;
214    
215 michael 3156 if (IsRegistered(target_p) && (target_p != source_p->from))
216 adx 30 break;
217     }
218     }
219     }
220     }
221    
222 michael 3246 if (target_p)
223 adx 30 {
224 michael 3246 if (!IsRegistered(target_p))
225 adx 30 {
226 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOSUCHSERVER, parv[server]);
227 adx 30 return HUNTED_NOSUCH;
228     }
229    
230     if (IsMe(target_p) || MyClient(target_p))
231     return HUNTED_ISME;
232    
233 michael 1652 if (match(target_p->name, parv[server]))
234 adx 30 parv[server] = target_p->name;
235    
236 michael 3136 /* This is a little kludgy but should work... */
237 michael 3096 sendto_one(target_p, command, ID_or_name(source_p, target_p),
238 adx 30 parv[1], parv[2], parv[3], parv[4],
239     parv[5], parv[6], parv[7], parv[8]);
240 michael 2134 return HUNTED_PASS;
241 michael 2345 }
242 adx 30
243 michael 3109 sendto_one_numeric(source_p, &me, ERR_NOSUCHSERVER, parv[server]);
244 michael 2134 return HUNTED_NOSUCH;
245 adx 30 }
246    
247     /* try_connections()
248     *
249     * inputs - void pointer which is not used
250     * output - NONE
251     * side effects -
252     * scan through configuration and try new connections.
253     * Returns the calendar time when the next call to this
254     * function should be made latest. (No harm done if this
255     * is called earlier or later...)
256     */
257     void
258     try_connections(void *unused)
259     {
260 michael 1632 dlink_node *ptr = NULL;
261     struct MaskItem *conf;
262 adx 30 int confrq;
263    
264     /* TODO: change this to set active flag to 0 when added to event! --Habeeb */
265     if (GlobalSetOptions.autoconn == 0)
266     return;
267    
268     DLINK_FOREACH(ptr, server_items.head)
269     {
270     conf = ptr->data;
271    
272 michael 1636 assert(conf->type == CONF_SERVER);
273 michael 1632
274 michael 2345 /* Also when already connecting! (update holdtimes) --SRB
275 adx 30 */
276 michael 1632 if (!conf->port ||!IsConfAllowAutoConn(conf))
277 adx 30 continue;
278    
279    
280     /* Skip this entry if the use of it is still on hold until
281     * future. Otherwise handle this entry (and set it on hold
282     * until next time). Will reset only hold times, if already
283     * made one successfull connection... [this algorithm is
284     * a bit fuzzy... -- msa >;) ]
285     */
286 michael 1649 if (conf->until > CurrentTime)
287 adx 30 continue;
288    
289 michael 1632 if (conf->class == NULL)
290 adx 30 confrq = DEFAULT_CONNECTFREQUENCY;
291     else
292     {
293 michael 1632 confrq = conf->class->con_freq;
294 michael 1377 if (confrq < MIN_CONN_FREQ)
295 michael 2134 confrq = MIN_CONN_FREQ;
296 adx 30 }
297    
298 michael 1649 conf->until = CurrentTime + confrq;
299 adx 30
300 michael 3246 /*
301     * Found a CONNECT config with port specified, scan clients
302 adx 30 * and see if this server is already connected?
303     */
304 michael 3246 if (hash_find_server(conf->name))
305 adx 30 continue;
306    
307 michael 1632 if (conf->class->ref_count < conf->class->max_total)
308 adx 30 {
309     /* Go to the end of the list, if not already last */
310 michael 3246 if (ptr->next)
311 adx 30 {
312     dlinkDelete(ptr, &server_items);
313     dlinkAddTail(conf, &conf->node, &server_items);
314     }
315    
316     if (find_servconn_in_progress(conf->name))
317     return;
318    
319 michael 3246 /*
320     * We used to only print this if serv_connect() actually
321 adx 30 * succeeded, but since comm_tcp_connect() can call the callback
322     * immediately if there is an error, we were getting error messages
323     * in the wrong order. SO, we just print out the activated line,
324     * and let serv_connect() / serv_connect_callback() print an
325     * error afterwards if it fails.
326     * -- adrian
327     */
328     if (ConfigServerHide.hide_server_ips)
329 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
330     "Connection to %s activated.",
331 adx 30 conf->name);
332     else
333 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
334     "Connection to %s[%s] activated.",
335 michael 1632 conf->name, conf->host);
336 adx 30
337 michael 1632 serv_connect(conf, NULL);
338 adx 30 /* We connect only one at time... */
339     return;
340     }
341     }
342     }
343    
344     int
345 michael 1115 valid_servname(const char *name)
346     {
347     unsigned int length = 0;
348     unsigned int dots = 0;
349     const char *p = name;
350    
351     for (; *p; ++p)
352     {
353     if (!IsServChar(*p))
354 michael 1118 return 0;
355 michael 1115
356     ++length;
357    
358     if (*p == '.')
359     ++dots;
360     }
361    
362 michael 3246 return dots && length <= HOSTLEN;
363 michael 1115 }
364    
365     int
366 michael 1302 check_server(const char *name, struct Client *client_p)
367 adx 30 {
368     dlink_node *ptr;
369 michael 1632 struct MaskItem *conf = NULL;
370     struct MaskItem *server_conf = NULL;
371 adx 30 int error = -1;
372    
373 michael 3246 assert(client_p);
374 adx 30
375     /* loop through looking for all possible connect items that might work */
376     DLINK_FOREACH(ptr, server_items.head)
377     {
378     conf = ptr->data;
379    
380 michael 1652 if (match(name, conf->name))
381 adx 30 continue;
382    
383     error = -3;
384    
385     /* XXX: Fix me for IPv6 */
386     /* XXX sockhost is the IPv4 ip as a string */
387 michael 2345 if (!match(conf->host, client_p->host) ||
388 michael 1652 !match(conf->host, client_p->sockhost))
389 adx 30 {
390     error = -2;
391    
392 michael 1632 if (!match_conf_password(client_p->localClient->passwd, conf))
393 michael 1414 return -2;
394 adx 30
395 michael 2228 if (!EmptyString(conf->certfp))
396 michael 2229 if (EmptyString(client_p->certfp) || strcasecmp(client_p->certfp, conf->certfp))
397 michael 2228 return -4;
398    
399 michael 1414 server_conf = conf;
400 adx 30 }
401     }
402    
403     if (server_conf == NULL)
404 michael 2182 return error;
405 adx 30
406     attach_conf(client_p, server_conf);
407    
408    
409 michael 3246 if (server_conf)
410 adx 30 {
411     struct sockaddr_in *v4;
412     #ifdef IPV6
413     struct sockaddr_in6 *v6;
414     #endif
415 michael 1632 switch (server_conf->aftype)
416 adx 30 {
417     #ifdef IPV6
418 michael 2345 case AF_INET6:
419 michael 1632 v6 = (struct sockaddr_in6 *)&server_conf->addr;
420 adx 30
421     if (IN6_IS_ADDR_UNSPECIFIED(&v6->sin6_addr))
422 michael 1632 memcpy(&server_conf->addr, &client_p->localClient->ip, sizeof(struct irc_ssaddr));
423 adx 30 break;
424     #endif
425     case AF_INET:
426 michael 1632 v4 = (struct sockaddr_in *)&server_conf->addr;
427 adx 30
428     if (v4->sin_addr.s_addr == INADDR_NONE)
429 michael 2345 memcpy(&server_conf->addr, &client_p->localClient->ip, sizeof(struct irc_ssaddr));
430 adx 30 break;
431     }
432     }
433    
434 michael 2182 return 0;
435 adx 30 }
436    
437     /* add_capability()
438     *
439     * inputs - string name of CAPAB
440     * - int flag of capability
441     * output - NONE
442     * side effects - Adds given capability name and bit mask to
443     * current supported capabilities. This allows
444     * modules to dynamically add or subtract their capability.
445     */
446     void
447     add_capability(const char *capab_name, int cap_flag, int add_to_default)
448     {
449 michael 885 struct Capability *cap = MyMalloc(sizeof(*cap));
450 adx 30
451 michael 1646 cap->name = xstrdup(capab_name);
452 adx 30 cap->cap = cap_flag;
453     dlinkAdd(cap, &cap->node, &cap_list);
454 michael 885
455 adx 30 if (add_to_default)
456     default_server_capabs |= cap_flag;
457     }
458    
459     /* delete_capability()
460     *
461     * inputs - string name of CAPAB
462     * output - NONE
463     * side effects - delete given capability from ones known.
464     */
465     int
466     delete_capability(const char *capab_name)
467     {
468     dlink_node *ptr;
469     dlink_node *next_ptr;
470     struct Capability *cap;
471    
472     DLINK_FOREACH_SAFE(ptr, next_ptr, cap_list.head)
473     {
474     cap = ptr->data;
475    
476     if (cap->cap != 0)
477     {
478     if (irccmp(cap->name, capab_name) == 0)
479     {
480 michael 2134 default_server_capabs &= ~(cap->cap);
481     dlinkDelete(ptr, &cap_list);
482     MyFree(cap->name);
483     MyFree(cap);
484 adx 30 }
485     }
486     }
487    
488 michael 896 return 0;
489 adx 30 }
490    
491     /*
492     * find_capability()
493     *
494     * inputs - string name of capab to find
495     * output - 0 if not found CAPAB otherwise
496     * side effects - none
497     */
498 michael 1877 unsigned int
499 adx 30 find_capability(const char *capab)
500     {
501 michael 896 const dlink_node *ptr = NULL;
502 adx 30
503     DLINK_FOREACH(ptr, cap_list.head)
504     {
505 michael 896 const struct Capability *cap = ptr->data;
506 adx 30
507 michael 896 if (cap->cap && !irccmp(cap->name, capab))
508     return cap->cap;
509 adx 30 }
510 michael 896
511     return 0;
512 adx 30 }
513    
514     /* send_capabilities()
515     *
516     * inputs - Client pointer to send to
517     * - int flag of capabilities that this server can send
518     * output - NONE
519     * side effects - send the CAPAB line to a server -orabidoo
520     *
521     */
522     void
523 michael 1632 send_capabilities(struct Client *client_p, int cap_can_send)
524 adx 30 {
525 michael 3246 char msgbuf[IRCD_BUFSIZE] = "";
526     char *t = msgbuf;
527 adx 30 int tl;
528 michael 3246 dlink_node *ptr = NULL;
529 adx 30
530     DLINK_FOREACH(ptr, cap_list.head)
531     {
532 michael 3246 struct Capability *cap = ptr->data;
533 adx 30
534     if (cap->cap & (cap_can_send|default_server_capabs))
535     {
536 michael 1793 tl = sprintf(t, "%s ", cap->name);
537 adx 30 t += tl;
538     }
539     }
540    
541 michael 319 *(t - 1) = '\0';
542 adx 30 sendto_one(client_p, "CAPAB :%s", msgbuf);
543     }
544    
545     /*
546     * show_capabilities - show current server capabilities
547     *
548     * inputs - pointer to a struct Client
549     * output - pointer to static string
550     * side effects - build up string representing capabilities of server listed
551     */
552     const char *
553 michael 2282 show_capabilities(const struct Client *target_p)
554 adx 30 {
555 michael 2309 static char msgbuf[IRCD_BUFSIZE] = "";
556 michael 2282 const dlink_node *ptr = NULL;
557 adx 30
558 michael 2309 strlcpy(msgbuf, "TS", sizeof(msgbuf));
559    
560 adx 30 DLINK_FOREACH(ptr, cap_list.head)
561     {
562     const struct Capability *cap = ptr->data;
563    
564 michael 2282 if (!IsCapable(target_p, cap->cap))
565     continue;
566    
567     strlcat(msgbuf, " ", sizeof(msgbuf));
568     strlcat(msgbuf, cap->name, sizeof(msgbuf));
569 adx 30 }
570 michael 1302
571     return msgbuf;
572 adx 30 }
573    
574     /* make_server()
575     *
576     * inputs - pointer to client struct
577     * output - pointer to struct Server
578     * side effects - add's an Server information block to a client
579     * if it was not previously allocated.
580     */
581     struct Server *
582     make_server(struct Client *client_p)
583     {
584     if (client_p->serv == NULL)
585     client_p->serv = MyMalloc(sizeof(struct Server));
586    
587     return client_p->serv;
588     }
589    
590     /* New server connection code
591     * Based upon the stuff floating about in s_bsd.c
592     * -- adrian
593     */
594    
595     /* serv_connect() - initiate a server connection
596     *
597 michael 2345 * inputs - pointer to conf
598 adx 30 * - pointer to client doing the connect
599     * output -
600     * side effects -
601     *
602     * This code initiates a connection to a server. It first checks to make
603     * sure the given server exists. If this is the case, it creates a socket,
604     * creates a client, saves the socket information in the client, and
605     * initiates a connection to the server through comm_connect_tcp(). The
606     * completion of this goes through serv_completed_connection().
607     *
608     * We return 1 if the connection is attempted, since we don't know whether
609     * it suceeded or not, and 0 if it fails in here somewhere.
610     */
611     int
612 michael 1632 serv_connect(struct MaskItem *conf, struct Client *by)
613 adx 30 {
614 michael 3246 struct Client *client_p = NULL;
615     char buf[HOSTIPLEN + 1] = "";
616 adx 30
617     /* conversion structs */
618     struct sockaddr_in *v4;
619 michael 3246
620 michael 1632 /* Make sure conf is useful */
621 michael 3246 assert(conf);
622 adx 30
623 michael 1632 getnameinfo((struct sockaddr *)&conf->addr, conf->addr.ss_len,
624 michael 1123 buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);
625 michael 1632 ilog(LOG_TYPE_IRCD, "Connect to %s[%s] @%s", conf->name, conf->host,
626 adx 30 buf);
627    
628     /* Still processing a DNS lookup? -> exit */
629 michael 1632 if (conf->dns_pending)
630 adx 30 {
631 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
632 michael 992 "Error connecting to %s: DNS lookup for connect{} in progress.",
633     conf->name);
634 michael 3246 return 0;
635 adx 30 }
636    
637 michael 1632 if (conf->dns_failed)
638 michael 992 {
639 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
640 michael 992 "Error connecting to %s: DNS lookup for connect{} failed.",
641     conf->name);
642 michael 3246 return 0;
643 michael 992 }
644    
645 adx 30 /* Make sure this server isn't already connected
646 michael 1632 * Note: conf should ALWAYS be a valid C: line
647 adx 30 */
648 michael 3246 if ((client_p = hash_find_server(conf->name)))
649 michael 2345 {
650 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
651 michael 2134 "Server %s already present from %s",
652     conf->name, get_client_name(client_p, SHOW_IP));
653 michael 1618 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
654 michael 2134 "Server %s already present from %s",
655     conf->name, get_client_name(client_p, MASK_IP));
656 adx 30 if (by && IsClient(by) && !MyClient(by))
657 michael 3110 sendto_one_notice(by, &me, ":Server %s already present from %s",
658     conf->name, get_client_name(client_p, MASK_IP));
659 michael 2134 return 0;
660 adx 30 }
661 michael 2345
662 adx 30 /* Create a local client */
663     client_p = make_client(NULL);
664    
665     /* Copy in the server, hostname, fd */
666     strlcpy(client_p->name, conf->name, sizeof(client_p->name));
667 michael 1632 strlcpy(client_p->host, conf->host, sizeof(client_p->host));
668 adx 30
669     /* We already converted the ip once, so lets use it - stu */
670 michael 1115 strlcpy(client_p->sockhost, buf, sizeof(client_p->sockhost));
671 adx 30
672 michael 2345 /* create a socket for the server connection */
673 michael 1632 if (comm_open(&client_p->localClient->fd, conf->addr.ss.ss_family,
674 adx 30 SOCK_STREAM, 0, NULL) < 0)
675     {
676     /* Eek, failure to create the socket */
677 michael 2134 report_error(L_ALL, "opening stream socket to %s: %s",
678     conf->name, errno);
679 adx 30 SetDead(client_p);
680 michael 3171 exit_client(client_p, "Connection failed");
681 michael 2134 return 0;
682 adx 30 }
683    
684     /* servernames are always guaranteed under HOSTLEN chars */
685     fd_note(&client_p->localClient->fd, "Server: %s", conf->name);
686    
687     /* Attach config entries to client here rather than in
688     * serv_connect_callback(). This to avoid null pointer references.
689     */
690 michael 1632 if (!attach_connect_block(client_p, conf->name, conf->host))
691 adx 30 {
692 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
693 michael 2134 "Host %s is not enabled for connecting: no connect{} block",
694     conf->name);
695 michael 2345 if (by && IsClient(by) && !MyClient(by))
696 michael 3110 sendto_one_notice(by, &me, ":Connect to host %s failed.", client_p->name);
697    
698 adx 30 SetDead(client_p);
699 michael 3171 exit_client(client_p, "Connection failed");
700 michael 2134 return 0;
701 adx 30 }
702    
703     /* at this point we have a connection in progress and C/N lines
704     * attached to the client, the socket info should be saved in the
705     * client and it should either be resolved or have a valid address.
706     *
707     * The socket has been connected or connect is in progress.
708     */
709     make_server(client_p);
710    
711     if (by && IsClient(by))
712     strlcpy(client_p->serv->by, by->name, sizeof(client_p->serv->by));
713     else
714     strlcpy(client_p->serv->by, "AutoConn.", sizeof(client_p->serv->by));
715    
716     SetConnecting(client_p);
717     dlinkAdd(client_p, &client_p->node, &global_client_list);
718     /* from def_fam */
719 michael 1632 client_p->localClient->aftype = conf->aftype;
720 adx 30
721     /* Now, initiate the connection */
722 michael 2345 /* XXX assume that a non 0 type means a specific bind address
723 adx 30 * for this connect.
724     */
725 michael 1632 switch (conf->aftype)
726 adx 30 {
727     case AF_INET:
728 michael 1632 v4 = (struct sockaddr_in*)&conf->bind;
729 michael 3246 if (v4->sin_addr.s_addr)
730 adx 30 {
731     struct irc_ssaddr ipn;
732     memset(&ipn, 0, sizeof(struct irc_ssaddr));
733     ipn.ss.ss_family = AF_INET;
734     ipn.ss_port = 0;
735 michael 1632 memcpy(&ipn, &conf->bind, sizeof(struct irc_ssaddr));
736 michael 2134 comm_connect_tcp(&client_p->localClient->fd, conf->host, conf->port,
737 michael 2345 (struct sockaddr *)&ipn, ipn.ss_len,
738 michael 2134 serv_connect_callback, client_p, conf->aftype,
739     CONNECTTIMEOUT);
740 adx 30 }
741     else if (ServerInfo.specific_ipv4_vhost)
742     {
743     struct irc_ssaddr ipn;
744     memset(&ipn, 0, sizeof(struct irc_ssaddr));
745     ipn.ss.ss_family = AF_INET;
746     ipn.ss_port = 0;
747     memcpy(&ipn, &ServerInfo.ip, sizeof(struct irc_ssaddr));
748 michael 1632 comm_connect_tcp(&client_p->localClient->fd, conf->host, conf->port,
749 adx 30 (struct sockaddr *)&ipn, ipn.ss_len,
750 michael 1632 serv_connect_callback, client_p, conf->aftype,
751 michael 2134 CONNECTTIMEOUT);
752 adx 30 }
753     else
754 michael 2345 comm_connect_tcp(&client_p->localClient->fd, conf->host, conf->port,
755     NULL, 0, serv_connect_callback, client_p, conf->aftype,
756 adx 30 CONNECTTIMEOUT);
757     break;
758     #ifdef IPV6
759     case AF_INET6:
760     {
761 michael 2182 struct irc_ssaddr ipn;
762     struct sockaddr_in6 *v6;
763     struct sockaddr_in6 *v6conf;
764 adx 30
765 michael 2182 memset(&ipn, 0, sizeof(struct irc_ssaddr));
766     v6conf = (struct sockaddr_in6 *)&conf->bind;
767     v6 = (struct sockaddr_in6 *)&ipn;
768 adx 30
769 michael 3246 if (memcmp(&v6conf->sin6_addr, &v6->sin6_addr, sizeof(struct in6_addr)))
770 adx 30 {
771 michael 2182 memcpy(&ipn, &conf->bind, sizeof(struct irc_ssaddr));
772     ipn.ss.ss_family = AF_INET6;
773     ipn.ss_port = 0;
774     comm_connect_tcp(&client_p->localClient->fd,
775     conf->host, conf->port,
776 michael 2345 (struct sockaddr *)&ipn, ipn.ss_len,
777 michael 2182 serv_connect_callback, client_p,
778     conf->aftype, CONNECTTIMEOUT);
779     }
780     else if (ServerInfo.specific_ipv6_vhost)
781     {
782     memcpy(&ipn, &ServerInfo.ip6, sizeof(struct irc_ssaddr));
783     ipn.ss.ss_family = AF_INET6;
784     ipn.ss_port = 0;
785     comm_connect_tcp(&client_p->localClient->fd,
786     conf->host, conf->port,
787     (struct sockaddr *)&ipn, ipn.ss_len,
788     serv_connect_callback, client_p,
789     conf->aftype, CONNECTTIMEOUT);
790     }
791     else
792     comm_connect_tcp(&client_p->localClient->fd,
793 michael 2345 conf->host, conf->port,
794 michael 2182 NULL, 0, serv_connect_callback, client_p,
795     conf->aftype, CONNECTTIMEOUT);
796 adx 30 }
797     #endif
798     }
799 michael 2182 return 1;
800 adx 30 }
801    
802 michael 1303 #ifdef HAVE_LIBCRYPTO
803     static void
804     finish_ssl_server_handshake(struct Client *client_p)
805     {
806 michael 1632 struct MaskItem *conf = NULL;
807 michael 1303
808     conf = find_conf_name(&client_p->localClient->confs,
809 michael 1632 client_p->name, CONF_SERVER);
810 michael 1303 if (conf == NULL)
811     {
812 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
813 michael 1303 "Lost connect{} block for %s", get_client_name(client_p, HIDE_IP));
814 michael 1618 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
815 michael 1303 "Lost connect{} block for %s", get_client_name(client_p, MASK_IP));
816    
817 michael 3171 exit_client(client_p, "Lost connect{} block");
818 michael 1303 return;
819     }
820    
821 michael 2134 sendto_one(client_p, "PASS %s TS %d %s", conf->spasswd, TS_CURRENT, me.id);
822 michael 1303
823 michael 1632 send_capabilities(client_p, 0);
824 michael 1303
825     sendto_one(client_p, "SERVER %s 1 :%s%s",
826     me.name, ConfigServerHide.hidden ? "(H) " : "",
827     me.info);
828    
829     /* If we've been marked dead because a send failed, just exit
830     * here now and save everyone the trouble of us ever existing.
831     */
832     if (IsDead(client_p))
833     {
834 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
835 michael 1303 "%s[%s] went dead during handshake",
836     client_p->name,
837     client_p->host);
838 michael 1618 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
839 michael 1303 "%s went dead during handshake", client_p->name);
840     return;
841     }
842    
843     /* don't move to serv_list yet -- we haven't sent a burst! */
844     /* If we get here, we're ok, so lets start reading some data */
845     comm_setselect(&client_p->localClient->fd, COMM_SELECT_READ, read_packet, client_p, 0);
846     }
847    
848     static void
849 michael 1306 ssl_server_handshake(fde_t *fd, struct Client *client_p)
850 michael 1303 {
851 michael 2463 X509 *cert = NULL;
852     int ret = 0;
853 michael 1303
854 michael 2463 if ((ret = SSL_connect(client_p->localClient->fd.ssl)) <= 0)
855 michael 1303 {
856 michael 2463 switch (SSL_get_error(client_p->localClient->fd.ssl, ret))
857 michael 1303 {
858     case SSL_ERROR_WANT_WRITE:
859     comm_setselect(&client_p->localClient->fd, COMM_SELECT_WRITE,
860 michael 1308 (PF *)ssl_server_handshake, client_p, 0);
861 michael 1303 return;
862     case SSL_ERROR_WANT_READ:
863     comm_setselect(&client_p->localClient->fd, COMM_SELECT_READ,
864 michael 1308 (PF *)ssl_server_handshake, client_p, 0);
865 michael 1303 return;
866     default:
867 michael 1308 {
868     const char *sslerr = ERR_error_string(ERR_get_error(), NULL);
869 michael 1618 sendto_realops_flags(UMODE_ALL, L_ALL, SEND_NOTICE,
870 michael 1308 "Error connecting to %s: %s", client_p->name,
871     sslerr ? sslerr : "unknown SSL error");
872 michael 3171 exit_client(client_p, "Error during SSL handshake");
873 michael 1303 return;
874 michael 1308 }
875 michael 1303 }
876     }
877    
878 michael 2463 if ((cert = SSL_get_peer_certificate(client_p->localClient->fd.ssl)))
879     {
880     int res = SSL_get_verify_result(client_p->localClient->fd.ssl);
881     char buf[EVP_MAX_MD_SIZE * 2 + 1] = { '\0' };
882     unsigned char md[EVP_MAX_MD_SIZE] = { '\0' };
883    
884     if (res == X509_V_OK || res == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN ||
885     res == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE ||
886     res == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT)
887     {
888     unsigned int i = 0, n = 0;
889    
890     if (X509_digest(cert, EVP_sha256(), md, &n))
891     {
892     for (; i < n; ++i)
893     snprintf(buf + 2 * i, 3, "%02X", md[i]);
894     client_p->certfp = xstrdup(buf);
895     }
896     }
897     else
898     ilog(LOG_TYPE_IRCD, "Server %s!%s@%s gave bad SSL client certificate: %d",
899     client_p->name, client_p->username, client_p->host, res);
900     X509_free(cert);
901     }
902    
903 michael 1303 finish_ssl_server_handshake(client_p);
904     }
905    
906     static void
907 michael 1632 ssl_connect_init(struct Client *client_p, struct MaskItem *conf, fde_t *fd)
908 michael 1303 {
909     if ((client_p->localClient->fd.ssl = SSL_new(ServerInfo.client_ctx)) == NULL)
910     {
911     ilog(LOG_TYPE_IRCD, "SSL_new() ERROR! -- %s",
912     ERR_error_string(ERR_get_error(), NULL));
913     SetDead(client_p);
914 michael 3171 exit_client(client_p, "SSL_new failed");
915 michael 1303 return;
916     }
917    
918     SSL_set_fd(fd->ssl, fd->fd);
919 michael 1306
920 michael 1632 if (!EmptyString(conf->cipher_list))
921     SSL_set_cipher_list(client_p->localClient->fd.ssl, conf->cipher_list);
922 michael 1306
923     ssl_server_handshake(NULL, client_p);
924 michael 1303 }
925     #endif
926    
927 adx 30 /* serv_connect_callback() - complete a server connection.
928 michael 2345 *
929 adx 30 * This routine is called after the server connection attempt has
930     * completed. If unsucessful, an error is sent to ops and the client
931     * is closed. If sucessful, it goes through the initialisation/check
932     * procedures, the capabilities are sent, and the socket is then
933     * marked for reading.
934     */
935     static void
936     serv_connect_callback(fde_t *fd, int status, void *data)
937     {
938     struct Client *client_p = data;
939 michael 1632 struct MaskItem *conf = NULL;
940 adx 30
941     /* First, make sure its a real client! */
942 michael 3246 assert(client_p);
943 adx 30 assert(&client_p->localClient->fd == fd);
944    
945     /* Next, for backward purposes, record the ip of the server */
946     memcpy(&client_p->localClient->ip, &fd->connect.hostaddr,
947     sizeof(struct irc_ssaddr));
948 michael 3246
949 adx 30 /* Check the status */
950     if (status != COMM_OK)
951     {
952     /* We have an error, so report it and quit
953     * Admins get to see any IP, mere opers don't *sigh*
954     */
955     if (ConfigServerHide.hide_server_ips)
956 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
957 adx 30 "Error connecting to %s: %s",
958     client_p->name, comm_errstr(status));
959     else
960 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
961 michael 2134 "Error connecting to %s[%s]: %s", client_p->name,
962     client_p->host, comm_errstr(status));
963 adx 30
964 michael 1618 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
965 michael 2134 "Error connecting to %s: %s",
966     client_p->name, comm_errstr(status));
967 adx 30
968     /* If a fd goes bad, call dead_link() the socket is no
969     * longer valid for reading or writing.
970     */
971     dead_link_on_write(client_p, 0);
972     return;
973     }
974    
975     /* COMM_OK, so continue the connection procedure */
976     /* Get the C/N lines */
977     conf = find_conf_name(&client_p->localClient->confs,
978 michael 2134 client_p->name, CONF_SERVER);
979 adx 30 if (conf == NULL)
980     {
981 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
982 michael 2134 "Lost connect{} block for %s", get_client_name(client_p, HIDE_IP));
983 michael 1618 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
984 michael 2134 "Lost connect{} block for %s", get_client_name(client_p, MASK_IP));
985 adx 30
986 michael 3171 exit_client(client_p, "Lost connect{} block");
987 adx 30 return;
988     }
989    
990     /* Next, send the initial handshake */
991     SetHandshake(client_p);
992    
993     #ifdef HAVE_LIBCRYPTO
994 michael 1632 if (IsConfSSL(conf))
995 michael 1303 {
996 michael 1632 ssl_connect_init(client_p, conf, fd);
997 michael 1303 return;
998     }
999 adx 30 #endif
1000    
1001 michael 2134 sendto_one(client_p, "PASS %s TS %d %s", conf->spasswd, TS_CURRENT, me.id);
1002 adx 30
1003 michael 1632 send_capabilities(client_p, 0);
1004 adx 30
1005 michael 2134 sendto_one(client_p, "SERVER %s 1 :%s%s", me.name,
1006     ConfigServerHide.hidden ? "(H) " : "", me.info);
1007 adx 30
1008     /* If we've been marked dead because a send failed, just exit
1009     * here now and save everyone the trouble of us ever existing.
1010     */
1011 michael 2345 if (IsDead(client_p))
1012 adx 30 {
1013 michael 1618 sendto_realops_flags(UMODE_ALL, L_ADMIN, SEND_NOTICE,
1014 michael 2134 "%s[%s] went dead during handshake",
1015 adx 30 client_p->name,
1016 michael 2134 client_p->host);
1017 michael 1618 sendto_realops_flags(UMODE_ALL, L_OPER, SEND_NOTICE,
1018 michael 2134 "%s went dead during handshake", client_p->name);
1019 adx 30 return;
1020     }
1021    
1022     /* don't move to serv_list yet -- we haven't sent a burst! */
1023     /* If we get here, we're ok, so lets start reading some data */
1024     comm_setselect(fd, COMM_SELECT_READ, read_packet, client_p, 0);
1025     }
1026    
1027     struct Client *
1028     find_servconn_in_progress(const char *name)
1029     {
1030     dlink_node *ptr;
1031     struct Client *cptr;
1032    
1033     DLINK_FOREACH(ptr, unknown_list.head)
1034     {
1035     cptr = ptr->data;
1036    
1037     if (cptr && cptr->name[0])
1038 michael 1652 if (!match(name, cptr->name))
1039 adx 30 return cptr;
1040     }
1041 michael 2345
1042 adx 30 return NULL;
1043     }

Properties

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