ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid-8/src/s_serv.c
Revision: 1302
Committed: Wed Mar 21 17:48:54 2012 UTC (14 years, 5 months ago) by michael
Content type: text/x-csrc
File size: 42077 byte(s)
Log Message:
- remove servlink in preparation for tls links/compression

File Contents

# User Rev Content
1 adx 30 /*
2     * ircd-hybrid: an advanced Internet Relay Chat Daemon(ircd).
3     * s_serv.c: Server related functions.
4     *
5     * Copyright (C) 2005 by the past and present ircd coders, and others.
6     *
7     * This program is free software; you can redistribute it and/or modify
8     * it under the terms of the GNU General Public License as published by
9     * the Free Software Foundation; either version 2 of the License, or
10     * (at your option) any later version.
11     *
12     * This program is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with this program; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20     * USA
21     *
22 knight 31 * $Id$
23 adx 30 */
24    
25     #include "stdinc.h"
26     #ifdef HAVE_LIBCRYPTO
27     #include <openssl/rsa.h>
28     #include "rsa.h"
29     #endif
30 michael 1011 #include "list.h"
31 adx 30 #include "channel.h"
32     #include "channel_mode.h"
33     #include "client.h"
34     #include "dbuf.h"
35     #include "event.h"
36     #include "fdlist.h"
37     #include "hash.h"
38     #include "irc_string.h"
39     #include "sprintf_irc.h"
40     #include "ircd.h"
41     #include "ircd_defs.h"
42     #include "s_bsd.h"
43     #include "numeric.h"
44     #include "packet.h"
45     #include "irc_res.h"
46     #include "s_conf.h"
47     #include "s_serv.h"
48     #include "s_log.h"
49     #include "s_user.h"
50     #include "send.h"
51     #include "memory.h"
52     #include "channel.h" /* chcap_usage_counts stuff...*/
53 michael 1243 #include "parse.h"
54 adx 30
55     #define MIN_CONN_FREQ 300
56    
57     static dlink_list cap_list = { NULL, NULL, 0 };
58     static void server_burst(struct Client *);
59     static void burst_all(struct Client *);
60     static void send_tb(struct Client *client_p, struct Channel *chptr);
61    
62     static CNCB serv_connect_callback;
63    
64     static void start_io(struct Client *);
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    
760     assert(client_p != NULL);
761    
762     strlcpy(inpath_ip, get_client_name(client_p, SHOW_IP), sizeof(inpath_ip));
763    
764     inpath = get_client_name(client_p, MASK_IP); /* "refresh" inpath with host */
765     host = client_p->name;
766    
767     if ((conf = find_conf_name(&client_p->localClient->confs, host, SERVER_TYPE))
768     == NULL)
769     {
770     /* This shouldn't happen, better tell the ops... -A1kmm */
771     sendto_realops_flags(UMODE_ALL, L_ALL, "Warning: Lost connect{} block "
772     "for server %s(this shouldn't happen)!", host);
773     exit_client(client_p, &me, "Lost connect{} block!");
774     return;
775     }
776    
777     MyFree(client_p->localClient->passwd);
778     client_p->localClient->passwd = NULL;
779    
780     /* Its got identd, since its a server */
781     SetGotId(client_p);
782    
783     /* If there is something in the serv_list, it might be this
784     * connecting server..
785     */
786     if (!ServerInfo.hub && serv_list.head)
787     {
788     if (client_p != serv_list.head->data || serv_list.head->next)
789     {
790 michael 896 ++ServerStats.is_ref;
791 adx 30 sendto_one(client_p, "ERROR :I'm a leaf not a hub");
792     exit_client(client_p, &me, "I'm a leaf");
793     return;
794     }
795     }
796    
797 michael 1115 aconf = map_to_conf(conf);
798 adx 30
799 michael 1302 if (IsUnknown(client_p))
800 adx 30 {
801     /* jdc -- 1. Use EmptyString(), not [0] index reference.
802     * 2. Check aconf->spasswd, not aconf->passwd.
803     */
804     if (!EmptyString(aconf->spasswd))
805 michael 1115 sendto_one(client_p, "PASS %s TS %d %s",
806     aconf->spasswd, TS_CURRENT, me.id);
807 adx 30
808     /* Pass my info to the new server
809     *
810     * Pass on ZIP if supported
811     * Pass on TB if supported.
812     * - Dianora
813     */
814    
815 michael 1119 send_capabilities(client_p, aconf,
816 michael 1302 (IsConfTopicBurst(aconf) ? CAP_TBURST|CAP_TB : 0));
817 adx 30
818     sendto_one(client_p, "SERVER %s 1 :%s%s",
819 michael 1118 me.name, ConfigServerHide.hidden ? "(H) " : "", me.info);
820 adx 30 }
821    
822 michael 1115 sendto_one(client_p, "SVINFO %d %d 0 :%lu", TS_CURRENT, TS_MIN,
823 adx 30 (unsigned long)CurrentTime);
824    
825     /* assumption here is if they passed the correct TS version, they also passed an SID */
826     if (IsCapable(client_p, CAP_TS6))
827     hash_add_id(client_p);
828    
829     /* XXX Does this ever happen? I don't think so -db */
830     detach_conf(client_p, OPER_TYPE);
831    
832     /* *WARNING*
833     ** In the following code in place of plain server's
834     ** name we send what is returned by get_client_name
835     ** which may add the "sockhost" after the name. It's
836     ** *very* *important* that there is a SPACE between
837     ** the name and sockhost (if present). The receiving
838     ** server will start the information field from this
839     ** first blank and thus puts the sockhost into info.
840     ** ...a bit tricky, but you have been warned, besides
841     ** code is more neat this way... --msa
842     */
843     client_p->servptr = &me;
844    
845     if (IsClosing(client_p))
846     return;
847    
848     SetServer(client_p);
849    
850     /* Update the capability combination usage counts. -A1kmm */
851     set_chcap_usage_counts(client_p);
852    
853     /* Some day, all these lists will be consolidated *sigh* */
854 michael 889 dlinkAdd(client_p, &client_p->lnode, &me.serv->server_list);
855 adx 30
856 michael 1126 assert(dlinkFind(&unknown_list, client_p));
857 adx 30
858 michael 1126 dlink_move_node(&client_p->localClient->lclient_node,
859     &unknown_list, &serv_list);
860 adx 30
861     Count.myserver++;
862    
863     dlinkAdd(client_p, make_dlink_node(), &global_serv_list);
864     hash_add_client(client_p);
865    
866     /* doesnt duplicate client_p->serv if allocated this struct already */
867     make_server(client_p);
868    
869     /* fixing eob timings.. -gnp */
870 michael 1241 client_p->localClient->firsttime = CurrentTime;
871 adx 30
872 michael 1157
873     if (find_matching_name_conf(SERVICE_TYPE, client_p->name, NULL, NULL, 0))
874 michael 1219 AddFlag(client_p, FLAGS_SERVICE);
875 michael 1157
876 adx 30 /* Show the real host/IP to admins */
877     sendto_realops_flags(UMODE_ALL, L_ADMIN,
878     "Link with %s established: (%s) link",
879     inpath_ip,show_capabilities(client_p));
880     /* Now show the masked hostname/IP to opers */
881     sendto_realops_flags(UMODE_ALL, L_OPER,
882     "Link with %s established: (%s) link",
883     inpath,show_capabilities(client_p));
884 michael 1247 ilog(LOG_TYPE_IRCD, "Link with %s established: (%s) link",
885 adx 30 inpath_ip, show_capabilities(client_p));
886    
887     client_p->serv->sconf = conf;
888    
889 michael 1302 fd_note(&client_p->localClient->fd, "Server: %s", client_p->name);
890 adx 30
891     /* Old sendto_serv_but_one() call removed because we now
892     ** need to send different names to different servers
893     ** (domain name matching) Send new server to other servers.
894     */
895     DLINK_FOREACH(ptr, serv_list.head)
896     {
897     target_p = ptr->data;
898    
899     if (target_p == client_p)
900     continue;
901    
902     if (IsCapable(target_p, CAP_TS6) && HasID(client_p))
903     sendto_one(target_p, ":%s SID %s 2 %s :%s%s",
904     me.id, client_p->name, client_p->id,
905     IsHidden(client_p) ? "(H) " : "",
906     client_p->info);
907     else
908     sendto_one(target_p,":%s SERVER %s 2 :%s%s",
909     me.name, client_p->name,
910     IsHidden(client_p) ? "(H) " : "",
911     client_p->info);
912     }
913    
914     /* Pass on my client information to the new server
915     **
916     ** First, pass only servers (idea is that if the link gets
917     ** cancelled beacause the server was already there,
918     ** there are no NICK's to be cancelled...). Of course,
919     ** if cancellation occurs, all this info is sent anyway,
920     ** and I guess the link dies when a read is attempted...? --msa
921     **
922     ** Note: Link cancellation to occur at this point means
923     ** that at least two servers from my fragment are building
924     ** up connection this other fragment at the same time, it's
925     ** a race condition, not the normal way of operation...
926     **
927     ** ALSO NOTE: using the get_client_name for server names--
928     ** see previous *WARNING*!!! (Also, original inpath
929     ** is destroyed...)
930     */
931    
932     DLINK_FOREACH_PREV(ptr, global_serv_list.tail)
933     {
934     target_p = ptr->data;
935    
936     /* target_p->from == target_p for target_p == client_p */
937 michael 1118 if (IsMe(target_p) || target_p->from == client_p)
938 adx 30 continue;
939    
940     if (IsCapable(client_p, CAP_TS6))
941     {
942     if (HasID(target_p))
943     sendto_one(client_p, ":%s SID %s %d %s :%s%s",
944     ID(target_p->servptr), target_p->name, target_p->hopcount+1,
945     target_p->id, IsHidden(target_p) ? "(H) " : "",
946     target_p->info);
947     else /* introducing non-ts6 server */
948     sendto_one(client_p, ":%s SERVER %s %d :%s%s",
949     ID(target_p->servptr), target_p->name, target_p->hopcount+1,
950     IsHidden(target_p) ? "(H) " : "", target_p->info);
951     }
952     else
953     sendto_one(client_p, ":%s SERVER %s %d :%s%s",
954     target_p->servptr->name, target_p->name, target_p->hopcount+1,
955     IsHidden(target_p) ? "(H) " : "", target_p->info);
956     }
957    
958     server_burst(client_p);
959     }
960    
961     /* server_burst()
962     *
963     * inputs - struct Client pointer server
964     * -
965     * output - none
966     * side effects - send a server burst
967     * bugs - still too long
968     */
969     static void
970     server_burst(struct Client *client_p)
971     {
972     /* Send it in the shortened format with the TS, if
973     ** it's a TS server; walk the list of channels, sending
974     ** all the nicks that haven't been sent yet for each
975     ** channel, then send the channel itself -- it's less
976     ** obvious than sending all nicks first, but on the
977     ** receiving side memory will be allocated more nicely
978     ** saving a few seconds in the handling of a split
979     ** -orabidoo
980     */
981    
982 michael 885 burst_all(client_p);
983 adx 30
984     /* EOB stuff is now in burst_all */
985     /* Always send a PING after connect burst is done */
986     sendto_one(client_p, "PING :%s", ID_or_name(&me, client_p));
987     }
988    
989     /* burst_all()
990     *
991     * inputs - pointer to server to send burst to
992     * output - NONE
993     * side effects - complete burst of channels/nicks is sent to client_p
994     */
995     static void
996     burst_all(struct Client *client_p)
997     {
998 michael 329 dlink_node *ptr = NULL;
999 adx 30
1000 michael 329 DLINK_FOREACH(ptr, global_channel_list.head)
1001 adx 30 {
1002 michael 329 struct Channel *chptr = ptr->data;
1003 adx 30
1004     if (dlink_list_length(&chptr->members) != 0)
1005     {
1006     burst_members(client_p, chptr);
1007     send_channel_modes(client_p, chptr);
1008 michael 329
1009     if (IsCapable(client_p, CAP_TBURST) ||
1010     IsCapable(client_p, CAP_TB))
1011 adx 30 send_tb(client_p, chptr);
1012     }
1013     }
1014    
1015     /* also send out those that are not on any channel
1016     */
1017     DLINK_FOREACH(ptr, global_client_list.head)
1018     {
1019 michael 329 struct Client *target_p = ptr->data;
1020 adx 30
1021 michael 1219 if (!HasFlag(target_p, FLAGS_BURSTED) && target_p->from != client_p)
1022 adx 30 sendnick_TS(client_p, target_p);
1023    
1024 michael 1219 DelFlag(target_p, FLAGS_BURSTED);
1025 adx 30 }
1026    
1027     /* We send the time we started the burst, and let the remote host determine an EOB time,
1028     ** as otherwise we end up sending a EOB of 0 Sending here means it gets sent last -- fl
1029     */
1030     /* Its simpler to just send EOB and use the time its been connected.. --fl_ */
1031     if (IsCapable(client_p, CAP_EOB))
1032     sendto_one(client_p, ":%s EOB", ID_or_name(&me, client_p));
1033     }
1034    
1035     /*
1036     * send_tb
1037     *
1038 michael 329 * inputs - pointer to Client
1039     * - pointer to channel
1040     * output - NONE
1041     * side effects - Called on a server burst when
1042     * server is CAP_TB|CAP_TBURST capable
1043 adx 30 */
1044     static void
1045     send_tb(struct Client *client_p, struct Channel *chptr)
1046     {
1047 michael 329 /*
1048 michael 337 * We may also send an empty topic here, but only if topic_time isn't 0,
1049     * i.e. if we had a topic that got unset. This is required for syncing
1050     * topics properly.
1051     *
1052     * Imagine the following scenario: Our downlink introduces a channel
1053     * to us with a TS that is equal to ours, but the channel topic on
1054     * their side got unset while the servers were in splitmode, which means
1055     * their 'topic' is newer. They simply wanted to unset it, so we have to
1056     * deal with it in a more sophisticated fashion instead of just resetting
1057     * it to their old topic they had before. Read m_tburst.c:ms_tburst
1058     * for further information -Michael
1059 michael 329 */
1060 michael 337 if (chptr->topic_time != 0)
1061 adx 30 {
1062 michael 329 if (IsCapable(client_p, CAP_TBURST))
1063     sendto_one(client_p, ":%s TBURST %lu %s %lu %s :%s",
1064     me.name, (unsigned long)chptr->channelts, chptr->chname,
1065 michael 337 (unsigned long)chptr->topic_time,
1066 michael 1203 chptr->topic_info,
1067     chptr->topic);
1068 michael 329 else if (IsCapable(client_p, CAP_TB))
1069 adx 30 {
1070 michael 329 if (ConfigChannel.burst_topicwho)
1071     {
1072     sendto_one(client_p, ":%s TB %s %lu %s :%s",
1073     me.name, chptr->chname,
1074     (unsigned long)chptr->topic_time,
1075 michael 1203 chptr->topic_info, chptr->topic);
1076 michael 329 }
1077     else
1078     {
1079     sendto_one(client_p, ":%s TB %s %lu :%s",
1080     me.name, chptr->chname,
1081 michael 337 (unsigned long)chptr->topic_time,
1082 michael 1203 chptr->topic);
1083 michael 329 }
1084 adx 30 }
1085     }
1086     }
1087    
1088     /* burst_members()
1089     *
1090     * inputs - pointer to server to send members to
1091     * - dlink_list pointer to membership list to send
1092     * output - NONE
1093     * side effects -
1094     */
1095     static void
1096     burst_members(struct Client *client_p, struct Channel *chptr)
1097     {
1098     struct Client *target_p;
1099     struct Membership *ms;
1100     dlink_node *ptr;
1101    
1102     DLINK_FOREACH(ptr, chptr->members.head)
1103     {
1104     ms = ptr->data;
1105     target_p = ms->client_p;
1106    
1107 michael 1219 if (!HasFlag(target_p, FLAGS_BURSTED))
1108 adx 30 {
1109 michael 1219 AddFlag(target_p, FLAGS_BURSTED);
1110 adx 30
1111     if (target_p->from != client_p)
1112     sendnick_TS(client_p, target_p);
1113     }
1114     }
1115     }
1116    
1117     /* New server connection code
1118     * Based upon the stuff floating about in s_bsd.c
1119     * -- adrian
1120     */
1121    
1122     /* serv_connect() - initiate a server connection
1123     *
1124     * inputs - pointer to conf
1125     * - pointer to client doing the connect
1126     * output -
1127     * side effects -
1128     *
1129     * This code initiates a connection to a server. It first checks to make
1130     * sure the given server exists. If this is the case, it creates a socket,
1131     * creates a client, saves the socket information in the client, and
1132     * initiates a connection to the server through comm_connect_tcp(). The
1133     * completion of this goes through serv_completed_connection().
1134     *
1135     * We return 1 if the connection is attempted, since we don't know whether
1136     * it suceeded or not, and 0 if it fails in here somewhere.
1137     */
1138     int
1139     serv_connect(struct AccessItem *aconf, struct Client *by)
1140     {
1141     struct ConfItem *conf;
1142     struct Client *client_p;
1143     char buf[HOSTIPLEN];
1144    
1145     /* conversion structs */
1146     struct sockaddr_in *v4;
1147     /* Make sure aconf is useful */
1148     assert(aconf != NULL);
1149    
1150     if(aconf == NULL)
1151     return (0);
1152    
1153     /* XXX should be passing struct ConfItem in the first place */
1154     conf = unmap_conf_item(aconf);
1155    
1156     /* log */
1157 michael 1123 getnameinfo((struct sockaddr *)&aconf->ipnum, aconf->ipnum.ss_len,
1158     buf, sizeof(buf), NULL, 0, NI_NUMERICHOST);
1159 michael 1247 ilog(LOG_TYPE_IRCD, "Connect to %s[%s] @%s", aconf->user, aconf->host,
1160 adx 30 buf);
1161    
1162     /* Still processing a DNS lookup? -> exit */
1163 michael 992 if (aconf->dns_pending)
1164 adx 30 {
1165 michael 992 sendto_realops_flags(UMODE_ALL, L_ALL,
1166     "Error connecting to %s: DNS lookup for connect{} in progress.",
1167     conf->name);
1168 adx 30 return (0);
1169     }
1170    
1171 michael 992 if (aconf->dns_failed)
1172     {
1173     sendto_realops_flags(UMODE_ALL, L_ALL,
1174     "Error connecting to %s: DNS lookup for connect{} failed.",
1175     conf->name);
1176     return (0);
1177     }
1178    
1179 adx 30 /* Make sure this server isn't already connected
1180     * Note: aconf should ALWAYS be a valid C: line
1181     */
1182 michael 1169 if ((client_p = hash_find_server(conf->name)) != NULL)
1183 adx 30 {
1184     sendto_realops_flags(UMODE_ALL, L_ADMIN,
1185     "Server %s already present from %s",
1186     conf->name, get_client_name(client_p, SHOW_IP));
1187     sendto_realops_flags(UMODE_ALL, L_OPER,
1188     "Server %s already present from %s",
1189     conf->name, get_client_name(client_p, MASK_IP));
1190     if (by && IsClient(by) && !MyClient(by))
1191     sendto_one(by, ":%s NOTICE %s :Server %s already present from %s",
1192     me.name, by->name, conf->name,
1193     get_client_name(client_p, MASK_IP));
1194     return (0);
1195     }
1196    
1197     /* Create a local client */
1198     client_p = make_client(NULL);
1199    
1200     /* Copy in the server, hostname, fd */
1201     strlcpy(client_p->name, conf->name, sizeof(client_p->name));
1202     strlcpy(client_p->host, aconf->host, sizeof(client_p->host));
1203    
1204     /* We already converted the ip once, so lets use it - stu */
1205 michael 1115 strlcpy(client_p->sockhost, buf, sizeof(client_p->sockhost));
1206 adx 30
1207     /* create a socket for the server connection */
1208     if (comm_open(&client_p->localClient->fd, aconf->ipnum.ss.ss_family,
1209     SOCK_STREAM, 0, NULL) < 0)
1210     {
1211     /* Eek, failure to create the socket */
1212     report_error(L_ALL,
1213     "opening stream socket to %s: %s", conf->name, errno);
1214     SetDead(client_p);
1215     exit_client(client_p, &me, "Connection failed");
1216     return (0);
1217     }
1218    
1219     /* servernames are always guaranteed under HOSTLEN chars */
1220     fd_note(&client_p->localClient->fd, "Server: %s", conf->name);
1221    
1222     /* Attach config entries to client here rather than in
1223     * serv_connect_callback(). This to avoid null pointer references.
1224     */
1225     if (!attach_connect_block(client_p, conf->name, aconf->host))
1226     {
1227     sendto_realops_flags(UMODE_ALL, L_ALL,
1228     "Host %s is not enabled for connecting:no C/N-line",
1229     conf->name);
1230     if (by && IsClient(by) && !MyClient(by))
1231     sendto_one(by, ":%s NOTICE %s :Connect to host %s failed.",
1232     me.name, by->name, client_p->name);
1233     SetDead(client_p);
1234     exit_client(client_p, client_p, "Connection failed");
1235     return (0);
1236     }
1237    
1238     /* at this point we have a connection in progress and C/N lines
1239     * attached to the client, the socket info should be saved in the
1240     * client and it should either be resolved or have a valid address.
1241     *
1242     * The socket has been connected or connect is in progress.
1243     */
1244     make_server(client_p);
1245    
1246     if (by && IsClient(by))
1247     strlcpy(client_p->serv->by, by->name, sizeof(client_p->serv->by));
1248     else
1249     strlcpy(client_p->serv->by, "AutoConn.", sizeof(client_p->serv->by));
1250    
1251     SetConnecting(client_p);
1252     dlinkAdd(client_p, &client_p->node, &global_client_list);
1253     /* from def_fam */
1254     client_p->localClient->aftype = aconf->aftype;
1255    
1256     /* Now, initiate the connection */
1257     /* XXX assume that a non 0 type means a specific bind address
1258     * for this connect.
1259     */
1260     switch (aconf->aftype)
1261     {
1262     case AF_INET:
1263     v4 = (struct sockaddr_in*)&aconf->my_ipnum;
1264     if (v4->sin_addr.s_addr != 0)
1265     {
1266     struct irc_ssaddr ipn;
1267     memset(&ipn, 0, sizeof(struct irc_ssaddr));
1268     ipn.ss.ss_family = AF_INET;
1269     ipn.ss_port = 0;
1270     memcpy(&ipn, &aconf->my_ipnum, sizeof(struct irc_ssaddr));
1271     comm_connect_tcp(&client_p->localClient->fd, aconf->host, aconf->port,
1272     (struct sockaddr *)&ipn, ipn.ss_len,
1273     serv_connect_callback, client_p, aconf->aftype,
1274     CONNECTTIMEOUT);
1275     }
1276     else if (ServerInfo.specific_ipv4_vhost)
1277     {
1278     struct irc_ssaddr ipn;
1279     memset(&ipn, 0, sizeof(struct irc_ssaddr));
1280     ipn.ss.ss_family = AF_INET;
1281     ipn.ss_port = 0;
1282     memcpy(&ipn, &ServerInfo.ip, sizeof(struct irc_ssaddr));
1283     comm_connect_tcp(&client_p->localClient->fd, aconf->host, aconf->port,
1284     (struct sockaddr *)&ipn, ipn.ss_len,
1285     serv_connect_callback, client_p, aconf->aftype,
1286     CONNECTTIMEOUT);
1287     }
1288     else
1289     comm_connect_tcp(&client_p->localClient->fd, aconf->host, aconf->port,
1290     NULL, 0, serv_connect_callback, client_p, aconf->aftype,
1291     CONNECTTIMEOUT);
1292     break;
1293     #ifdef IPV6
1294     case AF_INET6:
1295     {
1296     struct irc_ssaddr ipn;
1297     struct sockaddr_in6 *v6;
1298     struct sockaddr_in6 *v6conf;
1299    
1300     memset(&ipn, 0, sizeof(struct irc_ssaddr));
1301     v6conf = (struct sockaddr_in6 *)&aconf->my_ipnum;
1302     v6 = (struct sockaddr_in6 *)&ipn;
1303    
1304     if (memcmp(&v6conf->sin6_addr, &v6->sin6_addr,
1305     sizeof(struct in6_addr)) != 0)
1306     {
1307     memcpy(&ipn, &aconf->my_ipnum, sizeof(struct irc_ssaddr));
1308     ipn.ss.ss_family = AF_INET6;
1309     ipn.ss_port = 0;
1310     comm_connect_tcp(&client_p->localClient->fd,
1311     aconf->host, aconf->port,
1312     (struct sockaddr *)&ipn, ipn.ss_len,
1313     serv_connect_callback, client_p,
1314     aconf->aftype, CONNECTTIMEOUT);
1315     }
1316     else if (ServerInfo.specific_ipv6_vhost)
1317     {
1318     memcpy(&ipn, &ServerInfo.ip6, sizeof(struct irc_ssaddr));
1319     ipn.ss.ss_family = AF_INET6;
1320     ipn.ss_port = 0;
1321     comm_connect_tcp(&client_p->localClient->fd,
1322     aconf->host, aconf->port,
1323     (struct sockaddr *)&ipn, ipn.ss_len,
1324     serv_connect_callback, client_p,
1325     aconf->aftype, CONNECTTIMEOUT);
1326     }
1327     else
1328     comm_connect_tcp(&client_p->localClient->fd,
1329     aconf->host, aconf->port,
1330     NULL, 0, serv_connect_callback, client_p,
1331     aconf->aftype, CONNECTTIMEOUT);
1332     }
1333     #endif
1334     }
1335     return (1);
1336     }
1337    
1338     /* serv_connect_callback() - complete a server connection.
1339     *
1340     * This routine is called after the server connection attempt has
1341     * completed. If unsucessful, an error is sent to ops and the client
1342     * is closed. If sucessful, it goes through the initialisation/check
1343     * procedures, the capabilities are sent, and the socket is then
1344     * marked for reading.
1345     */
1346     static void
1347     serv_connect_callback(fde_t *fd, int status, void *data)
1348     {
1349     struct Client *client_p = data;
1350     struct ConfItem *conf=NULL;
1351     struct AccessItem *aconf=NULL;
1352    
1353     /* First, make sure its a real client! */
1354     assert(client_p != NULL);
1355     assert(&client_p->localClient->fd == fd);
1356    
1357     /* Next, for backward purposes, record the ip of the server */
1358     memcpy(&client_p->localClient->ip, &fd->connect.hostaddr,
1359     sizeof(struct irc_ssaddr));
1360     /* Check the status */
1361     if (status != COMM_OK)
1362     {
1363     /* We have an error, so report it and quit
1364     * Admins get to see any IP, mere opers don't *sigh*
1365     */
1366     if (ConfigServerHide.hide_server_ips)
1367     sendto_realops_flags(UMODE_ALL, L_ADMIN,
1368     "Error connecting to %s: %s",
1369     client_p->name, comm_errstr(status));
1370     else
1371     sendto_realops_flags(UMODE_ALL, L_ADMIN,
1372     "Error connecting to %s[%s]: %s", client_p->name,
1373     client_p->host, comm_errstr(status));
1374    
1375     sendto_realops_flags(UMODE_ALL, L_OPER,
1376     "Error connecting to %s: %s",
1377     client_p->name, comm_errstr(status));
1378    
1379     /* If a fd goes bad, call dead_link() the socket is no
1380     * longer valid for reading or writing.
1381     */
1382     dead_link_on_write(client_p, 0);
1383     return;
1384     }
1385    
1386     /* COMM_OK, so continue the connection procedure */
1387     /* Get the C/N lines */
1388     conf = find_conf_name(&client_p->localClient->confs,
1389     client_p->name, SERVER_TYPE);
1390     if (conf == NULL)
1391     {
1392     sendto_realops_flags(UMODE_ALL, L_ADMIN,
1393     "Lost connect{} block for %s", get_client_name(client_p, HIDE_IP));
1394     sendto_realops_flags(UMODE_ALL, L_OPER,
1395     "Lost connect{} block for %s", get_client_name(client_p, MASK_IP));
1396    
1397     exit_client(client_p, &me, "Lost connect{} block");
1398     return;
1399     }
1400    
1401     aconf = (struct AccessItem *)map_to_conf(conf);
1402     /* Next, send the initial handshake */
1403     SetHandshake(client_p);
1404    
1405     #ifdef HAVE_LIBCRYPTO
1406 michael 1302 /* TBD: initialization */
1407 adx 30 #endif
1408    
1409     /* jdc -- Check and send spasswd, not passwd. */
1410 michael 1115 if (!EmptyString(aconf->spasswd))
1411 adx 30 /* Send TS 6 form only if id */
1412     sendto_one(client_p, "PASS %s TS %d %s",
1413     aconf->spasswd, TS_CURRENT, me.id);
1414    
1415     /* Pass my info to the new server
1416     *
1417     * Pass on ZIP if supported
1418     * Pass on TB if supported.
1419     * - Dianora
1420     */
1421 michael 1119 send_capabilities(client_p, aconf,
1422 michael 1302 (IsConfTopicBurst(aconf) ? CAP_TBURST|CAP_TB : 0));
1423 adx 30
1424     sendto_one(client_p, "SERVER %s 1 :%s%s",
1425 michael 1118 me.name, ConfigServerHide.hidden ? "(H) " : "",
1426 adx 30 me.info);
1427    
1428     /* If we've been marked dead because a send failed, just exit
1429     * here now and save everyone the trouble of us ever existing.
1430     */
1431     if (IsDead(client_p))
1432     {
1433     sendto_realops_flags(UMODE_ALL, L_ADMIN,
1434     "%s[%s] went dead during handshake",
1435     client_p->name,
1436     client_p->host);
1437     sendto_realops_flags(UMODE_ALL, L_OPER,
1438     "%s went dead during handshake", client_p->name);
1439     return;
1440     }
1441    
1442     /* don't move to serv_list yet -- we haven't sent a burst! */
1443     /* If we get here, we're ok, so lets start reading some data */
1444     comm_setselect(fd, COMM_SELECT_READ, read_packet, client_p, 0);
1445     }
1446    
1447     struct Client *
1448     find_servconn_in_progress(const char *name)
1449     {
1450     dlink_node *ptr;
1451     struct Client *cptr;
1452    
1453     DLINK_FOREACH(ptr, unknown_list.head)
1454     {
1455     cptr = ptr->data;
1456    
1457     if (cptr && cptr->name[0])
1458 michael 1118 if (match(name, cptr->name))
1459 adx 30 return cptr;
1460     }
1461    
1462     return NULL;
1463     }

Properties

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