Restore stats_spy hook that was removed in commit 401f2454671ca233e35b0e6e4f3fa4c43cd...
[seven-1.x.git] / src / s_serv.c
blob13847898534622619236ae57cd4320e6321931a1
1 /*
2 * ircd-ratbox: A slightly useful ircd.
3 * s_serv.c: Server related functions.
5 * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
6 * Copyright (C) 1996-2002 Hybrid Development Team
7 * Copyright (C) 2002-2005 ircd-ratbox development team
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22 * USA
25 #include "stdinc.h"
27 #ifdef HAVE_LIBCRYPTO
28 #include <openssl/rsa.h>
29 #endif
31 #include "tools.h"
32 #include "s_serv.h"
33 #include "class.h"
34 #include "client.h"
35 #include "common.h"
36 #include "event.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 "numeric.h"
43 #include "packet.h"
44 #include "res.h"
45 #include "commio.h"
46 #include "s_conf.h"
47 #include "s_newconf.h"
48 #include "s_log.h"
49 #include "s_stats.h"
50 #include "s_user.h"
51 #include "scache.h"
52 #include "send.h"
53 #include "client.h"
54 #include "memory.h"
55 #include "channel.h" /* chcap_usage_counts stuff... */
56 #include "hook.h"
57 #include "msg.h"
59 extern char *crypt();
61 #ifndef INADDR_NONE
62 #define INADDR_NONE ((unsigned int) 0xffffffff)
63 #endif
65 #ifndef HAVE_SOCKETPAIR
66 static int inet_socketpair(int d, int type, int protocol, int sv[2]);
67 #endif
69 int MaxConnectionCount = 1;
70 int MaxClientCount = 1;
71 int refresh_user_links = 0;
73 static char buf[BUFSIZE];
75 static void start_io(struct Client *server);
77 static SlinkRplHnd slink_error;
78 static SlinkRplHnd slink_zipstats;
80 * list of recognized server capabilities. "TS" is not on the list
81 * because all servers that we talk to already do TS, and the kludged
82 * extra argument to "PASS" takes care of checking that. -orabidoo
84 struct Capability captab[] = {
85 /* name cap */
86 { "QS", CAP_QS },
87 { "EX", CAP_EX },
88 { "CHW", CAP_CHW},
89 { "IE", CAP_IE},
90 { "KLN", CAP_KLN},
91 { "KNOCK", CAP_KNOCK},
92 { "ZIP", CAP_ZIP},
93 { "TB", CAP_TB},
94 { "UNKLN", CAP_UNKLN},
95 { "CLUSTER", CAP_CLUSTER},
96 { "ENCAP", CAP_ENCAP },
97 { "SERVICES", CAP_SERVICE },
98 { "RSFNC", CAP_RSFNC },
99 { "SAVE", CAP_SAVE },
100 { "EUID", CAP_EUID },
101 { "REMOVE", CAP_REMOVE },
102 {0, 0}
105 struct SlinkRplDef slinkrpltab[] = {
106 {SLINKRPL_ERROR, slink_error, SLINKRPL_FLAG_DATA},
107 {SLINKRPL_ZIPSTATS, slink_zipstats, SLINKRPL_FLAG_DATA},
108 {0, 0, 0},
111 static int fork_server(struct Client *client_p);
113 static CNCB serv_connect_callback;
115 void
116 slink_error(unsigned int rpl, unsigned int len, unsigned char *data, struct Client *server_p)
118 s_assert(rpl == SLINKRPL_ERROR);
120 s_assert(len < 256);
121 data[len - 1] = '\0';
123 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "SlinkError for %s: %s", server_p->name, data);
124 exit_client(server_p, server_p, &me, "servlink error -- terminating link");
127 void
128 slink_zipstats(unsigned int rpl, unsigned int len, unsigned char *data, struct Client *server_p)
130 struct ZipStats zipstats;
131 u_int32_t in = 0, in_wire = 0, out = 0, out_wire = 0;
132 int i = 0;
134 s_assert(rpl == SLINKRPL_ZIPSTATS);
135 s_assert(len == 16);
136 s_assert(IsCapable(server_p, CAP_ZIP));
138 /* Yes, it needs to be done this way, no we cannot let the compiler
139 * work with the pointer to the structure. This works around a GCC
140 * bug on SPARC that affects all versions at the time of this writing.
141 * I will feed you to the creatures living in RMS's beard if you do
142 * not leave this as is, without being sure that you are not causing
143 * regression for most of our installed SPARC base.
144 * -jmallett, 04/27/2002
146 memcpy(&zipstats, &server_p->localClient->zipstats, sizeof(struct ZipStats));
148 in |= (data[i++] << 24);
149 in |= (data[i++] << 16);
150 in |= (data[i++] << 8);
151 in |= (data[i++]);
153 in_wire |= (data[i++] << 24);
154 in_wire |= (data[i++] << 16);
155 in_wire |= (data[i++] << 8);
156 in_wire |= (data[i++]);
158 out |= (data[i++] << 24);
159 out |= (data[i++] << 16);
160 out |= (data[i++] << 8);
161 out |= (data[i++]);
163 out_wire |= (data[i++] << 24);
164 out_wire |= (data[i++] << 16);
165 out_wire |= (data[i++] << 8);
166 out_wire |= (data[i++]);
168 zipstats.in += in;
169 zipstats.inK += zipstats.in >> 10;
170 zipstats.in &= 0x03ff;
172 zipstats.in_wire += in_wire;
173 zipstats.inK_wire += zipstats.in_wire >> 10;
174 zipstats.in_wire &= 0x03ff;
176 zipstats.out += out;
177 zipstats.outK += zipstats.out >> 10;
178 zipstats.out &= 0x03ff;
180 zipstats.out_wire += out_wire;
181 zipstats.outK_wire += zipstats.out_wire >> 10;
182 zipstats.out_wire &= 0x03ff;
184 if(zipstats.inK > 0)
185 zipstats.in_ratio =
186 (((double) (zipstats.inK - zipstats.inK_wire) /
187 (double) zipstats.inK) * 100.00);
188 else
189 zipstats.in_ratio = 0;
191 if(zipstats.outK > 0)
192 zipstats.out_ratio =
193 (((double) (zipstats.outK - zipstats.outK_wire) /
194 (double) zipstats.outK) * 100.00);
195 else
196 zipstats.out_ratio = 0;
198 memcpy(&server_p->localClient->zipstats, &zipstats, sizeof(struct ZipStats));
201 void
202 collect_zipstats(void *unused)
204 dlink_node *ptr;
205 struct Client *target_p;
207 DLINK_FOREACH(ptr, serv_list.head)
209 target_p = ptr->data;
210 if(IsCapable(target_p, CAP_ZIP))
212 /* only bother if we haven't already got something queued... */
213 if(!target_p->localClient->slinkq)
215 target_p->localClient->slinkq = MyMalloc(1); /* sigh.. */
216 target_p->localClient->slinkq[0] = SLINKCMD_ZIPSTATS;
217 target_p->localClient->slinkq_ofs = 0;
218 target_p->localClient->slinkq_len = 1;
219 send_queued_slink_write(target_p->localClient->ctrlfd, target_p);
226 * hunt_server - Do the basic thing in delivering the message (command)
227 * across the relays to the specific server (server) for
228 * actions.
230 * Note: The command is a format string and *MUST* be
231 * of prefixed style (e.g. ":%s COMMAND %s ...").
232 * Command can have only max 8 parameters.
234 * server parv[server] is the parameter identifying the
235 * target server.
237 * *WARNING*
238 * parv[server] is replaced with the pointer to the
239 * real servername from the matched client (I'm lazy
240 * now --msa).
242 * returns: (see #defines)
245 hunt_server(struct Client *client_p, struct Client *source_p,
246 const char *command, int server, int parc, const char *parv[])
248 struct Client *target_p;
249 int wilds;
250 dlink_node *ptr;
251 const char *old;
252 char *new;
255 * Assume it's me, if no server
257 if(parc <= server || EmptyString(parv[server]) ||
258 match(me.name, parv[server]) || match(parv[server], me.name) ||
259 (strcmp(parv[server], me.id) == 0))
260 return (HUNTED_ISME);
262 new = LOCAL_COPY(parv[server]);
265 * These are to pickup matches that would cause the following
266 * message to go in the wrong direction while doing quick fast
267 * non-matching lookups.
269 if(MyClient(source_p))
270 target_p = find_named_client(new);
271 else
272 target_p = find_client(new);
274 if(target_p)
275 if(target_p->from == source_p->from && !MyConnect(target_p))
276 target_p = NULL;
278 if(target_p == NULL && (target_p = find_server(source_p, new)))
279 if(target_p->from == source_p->from && !MyConnect(target_p))
280 target_p = NULL;
282 collapse(new);
283 wilds = (strchr(new, '?') || strchr(new, '*'));
286 * Again, if there are no wild cards involved in the server
287 * name, use the hash lookup
289 if(!target_p)
291 if(!wilds)
293 if(MyClient(source_p) || !IsDigit(parv[server][0]))
294 sendto_one_numeric(source_p, ERR_NOSUCHSERVER,
295 form_str(ERR_NOSUCHSERVER),
296 parv[server]);
297 return (HUNTED_NOSUCH);
299 else
301 target_p = NULL;
303 DLINK_FOREACH(ptr, global_client_list.head)
305 if(match(new, ((struct Client *) (ptr->data))->name))
307 target_p = ptr->data;
308 break;
314 if(target_p)
316 if(!IsRegistered(target_p))
318 sendto_one_numeric(source_p, ERR_NOSUCHSERVER,
319 form_str(ERR_NOSUCHSERVER),
320 parv[server]);
321 return HUNTED_NOSUCH;
324 if(IsMe(target_p) || MyClient(target_p))
325 return HUNTED_ISME;
327 old = parv[server];
328 parv[server] = get_id(target_p, target_p);
330 sendto_one(target_p, command, get_id(source_p, target_p),
331 parv[1], parv[2], parv[3], parv[4], parv[5], parv[6], parv[7], parv[8]);
332 parv[server] = old;
333 return (HUNTED_PASS);
336 if(!IsDigit(parv[server][0]))
337 sendto_one_numeric(source_p, ERR_NOSUCHSERVER,
338 form_str(ERR_NOSUCHSERVER), parv[server]);
339 return (HUNTED_NOSUCH);
343 * try_connections - scan through configuration and try new connections.
344 * Returns the calendar time when the next call to this
345 * function should be made latest. (No harm done if this
346 * is called earlier or later...)
348 void
349 try_connections(void *unused)
351 struct Client *client_p;
352 struct server_conf *server_p = NULL;
353 struct server_conf *tmp_p;
354 struct Class *cltmp;
355 dlink_node *ptr;
356 int connecting = FALSE;
357 int confrq = 0;
358 time_t next = 0;
360 DLINK_FOREACH(ptr, server_conf_list.head)
362 tmp_p = ptr->data;
364 if(ServerConfIllegal(tmp_p) || !ServerConfAutoconn(tmp_p))
365 continue;
367 cltmp = tmp_p->class;
370 * Skip this entry if the use of it is still on hold until
371 * future. Otherwise handle this entry (and set it on hold
372 * until next time). Will reset only hold times, if already
373 * made one successfull connection... [this algorithm is
374 * a bit fuzzy... -- msa >;) ]
376 if(tmp_p->hold > CurrentTime)
378 if(next > tmp_p->hold || next == 0)
379 next = tmp_p->hold;
380 continue;
383 confrq = get_con_freq(cltmp);
384 tmp_p->hold = CurrentTime + confrq;
387 * Found a CONNECT config with port specified, scan clients
388 * and see if this server is already connected?
390 client_p = find_server(NULL, tmp_p->name);
392 if(!client_p && (CurrUsers(cltmp) < MaxUsers(cltmp)) && !connecting)
394 server_p = tmp_p;
396 /* We connect only one at time... */
397 connecting = TRUE;
400 if((next > tmp_p->hold) || (next == 0))
401 next = tmp_p->hold;
404 /* TODO: change this to set active flag to 0 when added to event! --Habeeb */
405 if(GlobalSetOptions.autoconn == 0)
406 return;
408 if(!connecting)
409 return;
411 /* move this connect entry to end.. */
412 dlinkDelete(&server_p->node, &server_conf_list);
413 dlinkAddTail(server_p, &server_p->node, &server_conf_list);
416 * We used to only print this if serv_connect() actually
417 * suceeded, but since comm_tcp_connect() can call the callback
418 * immediately if there is an error, we were getting error messages
419 * in the wrong order. SO, we just print out the activated line,
420 * and let serv_connect() / serv_connect_callback() print an
421 * error afterwards if it fails.
422 * -- adrian
424 #ifndef HIDE_SERVERS_IPS
425 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
426 "Connection to %s[%s] activated.",
427 server_p->name, server_p->host);
428 #else
429 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
430 "Connection to %s activated",
431 server_p->name);
432 #endif
434 serv_connect(server_p, 0);
438 check_server(const char *name, struct Client *client_p)
440 struct server_conf *server_p = NULL;
441 struct server_conf *tmp_p;
442 dlink_node *ptr;
443 int error = -1;
445 s_assert(NULL != client_p);
446 if(client_p == NULL)
447 return error;
449 if(!(client_p->localClient->passwd))
450 return -2;
452 if(strlen(name) > HOSTLEN)
453 return -4;
455 DLINK_FOREACH(ptr, server_conf_list.head)
457 tmp_p = ptr->data;
459 if(ServerConfIllegal(tmp_p))
460 continue;
462 if(!match(tmp_p->name, name))
463 continue;
465 error = -3;
467 /* XXX: Fix me for IPv6 */
468 /* XXX sockhost is the IPv4 ip as a string */
469 if(match(tmp_p->host, client_p->host) ||
470 match(tmp_p->host, client_p->sockhost))
472 error = -2;
474 if(ServerConfEncrypted(tmp_p))
476 if(!strcmp(tmp_p->passwd, crypt(client_p->localClient->passwd,
477 tmp_p->passwd)))
479 server_p = tmp_p;
480 break;
483 else if(!strcmp(tmp_p->passwd, client_p->localClient->passwd))
485 server_p = tmp_p;
486 break;
491 if(server_p == NULL)
492 return error;
494 attach_server_conf(client_p, server_p);
496 /* clear ZIP/TB if they support but we dont want them */
497 #ifdef HAVE_LIBZ
498 if(!ServerConfCompressed(server_p))
499 #endif
500 ClearCap(client_p, CAP_ZIP);
502 if(!ServerConfTb(server_p))
503 ClearCap(client_p, CAP_TB);
505 return 0;
509 * send_capabilities
511 * inputs - Client pointer to send to
512 * - int flag of capabilities that this server has
513 * output - NONE
514 * side effects - send the CAPAB line to a server -orabidoo
517 void
518 send_capabilities(struct Client *client_p, int cap_can_send)
520 struct Capability *cap;
521 char msgbuf[BUFSIZE];
522 char *t;
523 int tl;
525 t = msgbuf;
527 for (cap = captab; cap->name; ++cap)
529 if(cap->cap & cap_can_send)
531 tl = ircsprintf(t, "%s ", cap->name);
532 t += tl;
536 t--;
537 *t = '\0';
539 sendto_one(client_p, "CAPAB :%s", msgbuf);
542 /* burst_modes_TS5()
544 * input - client to burst to, channel name, list to burst, mode flag
545 * output -
546 * side effects - client is sent a list of +b, or +e, or +I modes
548 static void
549 burst_modes_TS5(struct Client *client_p, char *chname, dlink_list *list, char flag)
551 dlink_node *ptr;
552 struct Ban *banptr;
553 char mbuf[MODEBUFLEN];
554 char pbuf[BUFSIZE];
555 int tlen;
556 int mlen;
557 int cur_len;
558 char *mp;
559 char *pp;
560 int count = 0;
562 mlen = ircsprintf(buf, ":%s MODE %s +", me.name, chname);
563 cur_len = mlen;
565 mp = mbuf;
566 pp = pbuf;
568 DLINK_FOREACH(ptr, list->head)
570 banptr = ptr->data;
571 tlen = strlen(banptr->banstr) + 3;
573 /* uh oh */
574 if(tlen > MODEBUFLEN)
575 continue;
577 if((count >= MAXMODEPARAMS) || ((cur_len + tlen + 2) > (BUFSIZE - 3)))
579 sendto_one(client_p, "%s%s %s", buf, mbuf, pbuf);
581 mp = mbuf;
582 pp = pbuf;
583 cur_len = mlen;
584 count = 0;
587 *mp++ = flag;
588 *mp = '\0';
589 pp += ircsprintf(pp, "%s ", banptr->banstr);
590 cur_len += tlen;
591 count++;
594 if(count != 0)
595 sendto_one(client_p, "%s%s %s", buf, mbuf, pbuf);
598 /* burst_modes_TS6()
600 * input - client to burst to, channel name, list to burst, mode flag
601 * output -
602 * side effects - client is sent a list of +b, +e, or +I modes
604 static void
605 burst_modes_TS6(struct Client *client_p, struct Channel *chptr,
606 dlink_list *list, char flag)
608 dlink_node *ptr;
609 struct Ban *banptr;
610 char *t;
611 int tlen;
612 int mlen;
613 int cur_len;
615 cur_len = mlen = ircsprintf(buf, ":%s BMASK %ld %s %c :",
616 me.id, (long) chptr->channelts, chptr->chname, flag);
617 t = buf + mlen;
619 DLINK_FOREACH(ptr, list->head)
621 banptr = ptr->data;
623 tlen = strlen(banptr->banstr) + 1;
625 /* uh oh */
626 if(cur_len + tlen > BUFSIZE - 3)
628 /* the one we're trying to send doesnt fit at all! */
629 if(cur_len == mlen)
631 s_assert(0);
632 continue;
635 /* chop off trailing space and send.. */
636 *(t-1) = '\0';
637 sendto_one(client_p, "%s", buf);
638 cur_len = mlen;
639 t = buf + mlen;
642 ircsprintf(t, "%s ", banptr->banstr);
643 t += tlen;
644 cur_len += tlen;
647 /* cant ever exit the loop above without having modified buf,
648 * chop off trailing space and send.
650 *(t-1) = '\0';
651 sendto_one(client_p, "%s", buf);
655 * burst_TS5
657 * inputs - client (server) to send nick towards
658 * - client to send nick for
659 * output - NONE
660 * side effects - NICK message is sent towards given client_p
662 static void
663 burst_TS5(struct Client *client_p)
665 static char ubuf[12];
666 struct Client *target_p;
667 struct Channel *chptr;
668 struct membership *msptr;
669 hook_data_client hclientinfo;
670 hook_data_channel hchaninfo;
671 dlink_node *ptr;
672 dlink_node *uptr;
673 char *t;
674 int tlen, mlen;
675 int cur_len = 0;
677 hclientinfo.client = hchaninfo.client = client_p;
679 DLINK_FOREACH(ptr, global_client_list.head)
681 target_p = ptr->data;
683 if(!IsPerson(target_p))
684 continue;
686 send_umode(NULL, target_p, 0, 0, ubuf);
687 if(!*ubuf)
689 ubuf[0] = '+';
690 ubuf[1] = '\0';
693 sendto_one(client_p, "NICK %s %d %ld %s %s %s %s :%s",
694 target_p->name, target_p->hopcount + 1,
695 (long) target_p->tsinfo, ubuf,
696 target_p->username, target_p->host,
697 target_p->user->server, target_p->info);
699 if(IsDynSpoof(target_p))
700 sendto_one(client_p, ":%s ENCAP * REALHOST %s",
701 target_p->name, target_p->orighost);
702 if(!EmptyString(target_p->user->suser))
703 sendto_one(client_p, ":%s ENCAP * LOGIN %s",
704 target_p->name, target_p->user->suser);
705 if(target_p->operflags)
707 /* :nenolod ENCAP * OPER AbCDEfG */
708 sendto_one(client_p, ":%s ENCAP * OPER %s", target_p->name,
709 get_oper_privs(target_p->operflags));
712 if(ConfigFileEntry.burst_away && !EmptyString(target_p->user->away))
713 sendto_one(client_p, ":%s AWAY :%s",
714 target_p->name, target_p->user->away);
716 hclientinfo.target = target_p;
717 call_hook(h_burst_client, &hclientinfo);
720 DLINK_FOREACH(ptr, global_channel_list.head)
722 chptr = ptr->data;
724 if(*chptr->chname != '#')
725 continue;
727 cur_len = mlen = ircsprintf(buf, ":%s SJOIN %ld %s %s :", me.name,
728 (long) chptr->channelts, chptr->chname,
729 channel_modes(chptr, client_p));
731 t = buf + mlen;
733 DLINK_FOREACH(uptr, chptr->members.head)
735 msptr = uptr->data;
737 tlen = strlen(msptr->client_p->name) + 1;
738 if(is_real_chanop(msptr))
739 tlen++;
740 if(is_voiced(msptr))
741 tlen++;
743 if(cur_len + tlen >= BUFSIZE - 3)
745 t--;
746 *t = '\0';
747 sendto_one(client_p, "%s", buf);
748 cur_len = mlen;
749 t = buf + mlen;
752 ircsprintf(t, "%s%s ", find_channel_status(msptr, 1),
753 msptr->client_p->name);
755 cur_len += tlen;
756 t += tlen;
759 if (dlink_list_length(&chptr->members) > 0)
761 /* remove trailing space */
762 t--;
763 *t = '\0';
765 sendto_one(client_p, "%s", buf);
767 burst_modes_TS5(client_p, chptr->chname, &chptr->banlist, 'b');
769 if(IsCapable(client_p, CAP_EX))
770 burst_modes_TS5(client_p, chptr->chname, &chptr->exceptlist, 'e');
772 if(IsCapable(client_p, CAP_IE))
773 burst_modes_TS5(client_p, chptr->chname, &chptr->invexlist, 'I');
775 burst_modes_TS5(client_p, chptr->chname, &chptr->quietlist, 'q');
777 if(IsCapable(client_p, CAP_TB) && chptr->topic != NULL)
778 sendto_one(client_p, ":%s TB %s %ld %s%s:%s",
779 me.name, chptr->chname, (long) chptr->topic_time,
780 ConfigChannel.burst_topicwho ? chptr->topic_info : "",
781 ConfigChannel.burst_topicwho ? " " : "",
782 chptr->topic);
784 hchaninfo.chptr = chptr;
785 call_hook(h_burst_channel, &hchaninfo);
788 hclientinfo.target = NULL;
789 call_hook(h_burst_finished, &hclientinfo);
793 * burst_TS6
795 * inputs - client (server) to send nick towards
796 * - client to send nick for
797 * output - NONE
798 * side effects - NICK message is sent towards given client_p
800 static void
801 burst_TS6(struct Client *client_p)
803 static char ubuf[12];
804 struct Client *target_p;
805 struct Channel *chptr;
806 struct membership *msptr;
807 hook_data_client hclientinfo;
808 hook_data_channel hchaninfo;
809 dlink_node *ptr;
810 dlink_node *uptr;
811 char *t;
812 int tlen, mlen;
813 int cur_len = 0;
815 hclientinfo.client = hchaninfo.client = client_p;
817 DLINK_FOREACH(ptr, global_client_list.head)
819 target_p = ptr->data;
821 if(!IsPerson(target_p))
822 continue;
824 send_umode(NULL, target_p, 0, 0, ubuf);
825 if(!*ubuf)
827 ubuf[0] = '+';
828 ubuf[1] = '\0';
831 if(has_id(target_p) && IsCapable(client_p, CAP_EUID))
832 sendto_one(client_p, ":%s EUID %s %d %ld %s %s %s %s %s %s %s :%s",
833 target_p->servptr->id, target_p->name,
834 target_p->hopcount + 1,
835 (long) target_p->tsinfo, ubuf,
836 target_p->username, target_p->host,
837 IsIPSpoof(target_p) ? "0" : target_p->sockhost,
838 target_p->id,
839 IsDynSpoof(target_p) ? target_p->orighost : "*",
840 EmptyString(target_p->user->suser) ? "*" : target_p->user->suser,
841 target_p->info);
842 else if(has_id(target_p))
843 sendto_one(client_p, ":%s UID %s %d %ld %s %s %s %s %s :%s",
844 target_p->servptr->id, target_p->name,
845 target_p->hopcount + 1,
846 (long) target_p->tsinfo, ubuf,
847 target_p->username, target_p->host,
848 IsIPSpoof(target_p) ? "0" : target_p->sockhost,
849 target_p->id, target_p->info);
850 else
851 sendto_one(client_p, "NICK %s %d %ld %s %s %s %s :%s",
852 target_p->name,
853 target_p->hopcount + 1,
854 (long) target_p->tsinfo,
855 ubuf,
856 target_p->username, target_p->host,
857 target_p->user->server, target_p->info);
859 if(!has_id(target_p) || !IsCapable(client_p, CAP_EUID))
861 if(IsDynSpoof(target_p))
862 sendto_one(client_p, ":%s ENCAP * REALHOST %s",
863 use_id(target_p), target_p->orighost);
864 if(!EmptyString(target_p->user->suser))
865 sendto_one(client_p, ":%s ENCAP * LOGIN %s",
866 use_id(target_p), target_p->user->suser);
869 if(target_p->operflags)
871 /* :nenolod ENCAP * OPER AbCDEfG */
872 sendto_one(client_p, ":%s ENCAP * OPER %s", use_id(target_p),
873 get_oper_privs(target_p->operflags));
876 if(ConfigFileEntry.burst_away && !EmptyString(target_p->user->away))
877 sendto_one(client_p, ":%s AWAY :%s",
878 use_id(target_p),
879 target_p->user->away);
881 hclientinfo.target = target_p;
882 call_hook(h_burst_client, &hclientinfo);
885 DLINK_FOREACH(ptr, global_channel_list.head)
887 chptr = ptr->data;
889 if(*chptr->chname != '#')
890 continue;
892 cur_len = mlen = ircsprintf(buf, ":%s SJOIN %ld %s %s :", me.id,
893 (long) chptr->channelts, chptr->chname,
894 channel_modes(chptr, client_p));
896 t = buf + mlen;
898 DLINK_FOREACH(uptr, chptr->members.head)
900 msptr = uptr->data;
902 tlen = strlen(use_id(msptr->client_p)) + 1;
903 if(is_real_chanop(msptr))
904 tlen++;
905 if(is_voiced(msptr))
906 tlen++;
908 if(cur_len + tlen >= BUFSIZE - 3)
910 *(t-1) = '\0';
911 sendto_one(client_p, "%s", buf);
912 cur_len = mlen;
913 t = buf + mlen;
916 ircsprintf(t, "%s%s ", find_channel_status(msptr, 1),
917 use_id(msptr->client_p));
919 cur_len += tlen;
920 t += tlen;
923 if (dlink_list_length(&chptr->members) > 0)
925 /* remove trailing space */
926 *(t-1) = '\0';
928 sendto_one(client_p, "%s", buf);
930 if(dlink_list_length(&chptr->banlist) > 0)
931 burst_modes_TS6(client_p, chptr, &chptr->banlist, 'b');
933 if(IsCapable(client_p, CAP_EX) &&
934 dlink_list_length(&chptr->exceptlist) > 0)
935 burst_modes_TS6(client_p, chptr, &chptr->exceptlist, 'e');
937 if(IsCapable(client_p, CAP_IE) &&
938 dlink_list_length(&chptr->invexlist) > 0)
939 burst_modes_TS6(client_p, chptr, &chptr->invexlist, 'I');
941 if(dlink_list_length(&chptr->quietlist) > 0)
942 burst_modes_TS6(client_p, chptr, &chptr->quietlist, 'q');
944 if(IsCapable(client_p, CAP_TB) && chptr->topic != NULL)
945 sendto_one(client_p, ":%s TB %s %ld %s%s:%s",
946 me.id, chptr->chname, (long) chptr->topic_time,
947 ConfigChannel.burst_topicwho ? chptr->topic_info : "",
948 ConfigChannel.burst_topicwho ? " " : "",
949 chptr->topic);
951 hchaninfo.chptr = chptr;
952 call_hook(h_burst_channel, &hchaninfo);
955 hclientinfo.target = NULL;
956 call_hook(h_burst_finished, &hclientinfo);
960 * show_capabilities - show current server capabilities
962 * inputs - pointer to an struct Client
963 * output - pointer to static string
964 * side effects - build up string representing capabilities of server listed
966 const char *
967 show_capabilities(struct Client *target_p)
969 static char msgbuf[BUFSIZE];
970 struct Capability *cap;
971 char *t;
972 int tl;
974 t = msgbuf;
975 tl = ircsprintf(msgbuf, "TS ");
976 t += tl;
978 if(!IsServer(target_p) || !target_p->serv->caps) /* short circuit if no caps */
980 msgbuf[2] = '\0';
981 return msgbuf;
984 for (cap = captab; cap->cap; ++cap)
986 if(cap->cap & target_p->serv->caps)
988 tl = ircsprintf(t, "%s ", cap->name);
989 t += tl;
993 t--;
994 *t = '\0';
996 return msgbuf;
1000 * server_estab
1002 * inputs - pointer to a struct Client
1003 * output -
1004 * side effects -
1007 server_estab(struct Client *client_p)
1009 struct Client *target_p;
1010 struct server_conf *server_p;
1011 hook_data_client hdata;
1012 char *host;
1013 dlink_node *ptr;
1015 s_assert(NULL != client_p);
1016 if(client_p == NULL)
1017 return -1;
1018 ClearAccess(client_p);
1020 host = client_p->name;
1022 if((server_p = client_p->localClient->att_sconf) == NULL)
1024 /* This shouldn't happen, better tell the ops... -A1kmm */
1025 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
1026 "Warning: Lost connect{} block for server %s!", host);
1027 return exit_client(client_p, client_p, client_p, "Lost connect{} block!");
1030 /* We shouldn't have to check this, it should already done before
1031 * server_estab is called. -A1kmm
1033 if(client_p->localClient->passwd)
1035 memset(client_p->localClient->passwd, 0, strlen(client_p->localClient->passwd));
1036 MyFree(client_p->localClient->passwd);
1037 client_p->localClient->passwd = NULL;
1040 /* Its got identd , since its a server */
1041 SetGotId(client_p);
1043 /* If there is something in the serv_list, it might be this
1044 * connecting server..
1046 if(!ServerInfo.hub && serv_list.head)
1048 if(client_p != serv_list.head->data || serv_list.head->next)
1050 ServerStats->is_ref++;
1051 sendto_one(client_p, "ERROR :I'm a leaf not a hub");
1052 return exit_client(client_p, client_p, client_p, "I'm a leaf");
1056 if(IsUnknown(client_p))
1059 * jdc -- 1. Use EmptyString(), not [0] index reference.
1060 * 2. Check ->spasswd, not ->passwd.
1062 if(!EmptyString(server_p->spasswd))
1064 /* kludge, if we're not using TS6, dont ever send
1065 * ourselves as being TS6 capable.
1067 if(ServerInfo.use_ts6)
1068 sendto_one(client_p, "PASS %s TS %d :%s",
1069 server_p->spasswd, TS_CURRENT, me.id);
1070 else
1071 sendto_one(client_p, "PASS %s :TS",
1072 server_p->spasswd);
1075 /* pass info to new server */
1076 send_capabilities(client_p, default_server_capabs
1077 | (ServerConfCompressed(server_p) ? CAP_ZIP_SUPPORTED : 0)
1078 | (ServerConfTb(server_p) ? CAP_TB : 0));
1080 sendto_one(client_p, "SERVER %s 1 :%s%s",
1081 me.name,
1082 ConfigServerHide.hidden ? "(H) " : "",
1083 (me.info[0]) ? (me.info) : "IRCers United");
1086 if(!comm_set_buffers(client_p->localClient->fd, READBUF_SIZE))
1087 report_error(SETBUF_ERROR_MSG,
1088 get_server_name(client_p, SHOW_IP),
1089 log_client_name(client_p, SHOW_IP), errno);
1091 /* Hand the server off to servlink now */
1092 if(IsCapable(client_p, CAP_ZIP))
1094 if(fork_server(client_p) < 0)
1096 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
1097 "Warning: fork failed for server %s -- check servlink_path (%s)",
1098 get_server_name(client_p, HIDE_IP),
1099 ConfigFileEntry.servlink_path);
1100 return exit_client(client_p, client_p, client_p, "Fork failed");
1102 start_io(client_p);
1103 SetServlink(client_p);
1106 sendto_one(client_p, "SVINFO %d %d 0 :%ld", TS_CURRENT, TS_MIN, CurrentTime);
1108 client_p->servptr = &me;
1110 if(IsAnyDead(client_p))
1111 return CLIENT_EXITED;
1113 SetServer(client_p);
1115 /* Update the capability combination usage counts */
1116 set_chcap_usage_counts(client_p);
1118 dlinkAdd(client_p, &client_p->lnode, &me.serv->servers);
1119 dlinkMoveNode(&client_p->localClient->tnode, &unknown_list, &serv_list);
1120 dlinkAddTailAlloc(client_p, &global_serv_list);
1122 if(has_id(client_p))
1123 add_to_id_hash(client_p->id, client_p);
1125 add_to_client_hash(client_p->name, client_p);
1126 /* doesnt duplicate client_p->serv if allocated this struct already */
1127 make_server(client_p);
1128 client_p->serv->up = me.name;
1129 client_p->serv->upid = me.id;
1131 client_p->serv->caps = client_p->localClient->caps;
1133 if(client_p->localClient->fullcaps)
1135 DupString(client_p->serv->fullcaps, client_p->localClient->fullcaps);
1136 MyFree(client_p->localClient->fullcaps);
1137 client_p->localClient->fullcaps = NULL;
1140 /* add it to scache */
1141 find_or_add(client_p->name);
1142 client_p->localClient->firsttime = CurrentTime;
1143 /* fixing eob timings.. -gnp */
1145 /* Show the real host/IP to admins */
1146 sendto_realops_snomask(SNO_GENERAL, L_ALL,
1147 "Link with %s established: (%s) link",
1148 get_server_name(client_p, SHOW_IP),
1149 show_capabilities(client_p));
1151 ilog(L_SERVER, "Link with %s established: (%s) link",
1152 log_client_name(client_p, SHOW_IP), show_capabilities(client_p));
1154 hdata.client = &me;
1155 hdata.target = client_p;
1156 call_hook(h_server_introduced, &hdata);
1158 if(HasServlink(client_p))
1160 /* we won't overflow FD_DESC_SZ here, as it can hold
1161 * client_p->name + 64
1163 comm_note(client_p->localClient->fd, "slink data: %s", client_p->name);
1164 comm_note(client_p->localClient->ctrlfd, "slink ctrl: %s", client_p->name);
1166 else
1167 comm_note(client_p->localClient->fd, "Server: %s", client_p->name);
1170 ** Old sendto_serv_but_one() call removed because we now
1171 ** need to send different names to different servers
1172 ** (domain name matching) Send new server to other servers.
1174 DLINK_FOREACH(ptr, serv_list.head)
1176 target_p = ptr->data;
1178 if(target_p == client_p)
1179 continue;
1181 if(has_id(target_p) && has_id(client_p))
1183 sendto_one(target_p, ":%s SID %s 2 %s :%s%s",
1184 me.id, client_p->name, client_p->id,
1185 IsHidden(client_p) ? "(H) " : "", client_p->info);
1187 if(IsCapable(target_p, CAP_ENCAP) &&
1188 !EmptyString(client_p->serv->fullcaps))
1189 sendto_one(target_p, ":%s ENCAP * GCAP :%s",
1190 client_p->id, client_p->serv->fullcaps);
1192 else
1194 sendto_one(target_p, ":%s SERVER %s 2 :%s%s",
1195 me.name, client_p->name,
1196 IsHidden(client_p) ? "(H) " : "", client_p->info);
1198 if(IsCapable(target_p, CAP_ENCAP) &&
1199 !EmptyString(client_p->serv->fullcaps))
1200 sendto_one(target_p, ":%s ENCAP * GCAP :%s",
1201 client_p->name, client_p->serv->fullcaps);
1206 ** Pass on my client information to the new server
1208 ** First, pass only servers (idea is that if the link gets
1209 ** cancelled beacause the server was already there,
1210 ** there are no NICK's to be cancelled...). Of course,
1211 ** if cancellation occurs, all this info is sent anyway,
1212 ** and I guess the link dies when a read is attempted...? --msa
1214 ** Note: Link cancellation to occur at this point means
1215 ** that at least two servers from my fragment are building
1216 ** up connection this other fragment at the same time, it's
1217 ** a race condition, not the normal way of operation...
1219 ** ALSO NOTE: using the get_client_name for server names--
1220 ** see previous *WARNING*!!! (Also, original inpath
1221 ** is destroyed...)
1223 DLINK_FOREACH(ptr, global_serv_list.head)
1225 target_p = ptr->data;
1227 /* target_p->from == target_p for target_p == client_p */
1228 if(IsMe(target_p) || target_p->from == client_p)
1229 continue;
1231 /* presumption, if target has an id, so does its uplink */
1232 if(has_id(client_p) && has_id(target_p))
1233 sendto_one(client_p, ":%s SID %s %d %s :%s%s",
1234 target_p->serv->upid, target_p->name,
1235 target_p->hopcount + 1, target_p->id,
1236 IsHidden(target_p) ? "(H) " : "", target_p->info);
1237 else
1238 sendto_one(client_p, ":%s SERVER %s %d :%s%s",
1239 target_p->serv->up,
1240 target_p->name, target_p->hopcount + 1,
1241 IsHidden(target_p) ? "(H) " : "", target_p->info);
1243 if(IsCapable(client_p, CAP_ENCAP) &&
1244 !EmptyString(target_p->serv->fullcaps))
1245 sendto_one(client_p, ":%s ENCAP * GCAP :%s",
1246 get_id(target_p, client_p),
1247 target_p->serv->fullcaps);
1250 if(has_id(client_p))
1251 burst_TS6(client_p);
1252 else
1253 burst_TS5(client_p);
1255 /* Always send a PING after connect burst is done */
1256 sendto_one(client_p, "PING :%s", get_id(&me, client_p));
1258 free_pre_client(client_p);
1260 return 0;
1263 static void
1264 start_io(struct Client *server)
1266 unsigned char *iobuf;
1267 int c = 0;
1268 int linecount = 0;
1269 int linelen;
1271 iobuf = MyMalloc(256); /* XXX: This seems arbitrary. Perhaps make it IRCD_BUFSIZE? --nenolod */
1273 if(IsCapable(server, CAP_ZIP))
1275 /* ziplink */
1276 iobuf[c++] = SLINKCMD_SET_ZIP_OUT_LEVEL;
1277 iobuf[c++] = 0; /* | */
1278 iobuf[c++] = 1; /* \ len is 1 */
1279 iobuf[c++] = ConfigFileEntry.compression_level;
1280 iobuf[c++] = SLINKCMD_START_ZIP_IN;
1281 iobuf[c++] = SLINKCMD_START_ZIP_OUT;
1284 while (MyConnect(server))
1286 linecount++;
1288 iobuf = MyRealloc(iobuf, (c + READBUF_SIZE + 64));
1290 /* store data in c+3 to allow for SLINKCMD_INJECT_RECVQ and len u16 */
1291 linelen = linebuf_get(&server->localClient->buf_recvq, (char *) (iobuf + c + 3), READBUF_SIZE, LINEBUF_PARTIAL, LINEBUF_RAW); /* include partial lines */
1293 if(linelen)
1295 iobuf[c++] = SLINKCMD_INJECT_RECVQ;
1296 iobuf[c++] = (linelen >> 8);
1297 iobuf[c++] = (linelen & 0xff);
1298 c += linelen;
1300 else
1301 break;
1304 while (MyConnect(server))
1306 linecount++;
1308 iobuf = MyRealloc(iobuf, (c + BUF_DATA_SIZE + 64));
1310 /* store data in c+3 to allow for SLINKCMD_INJECT_RECVQ and len u16 */
1311 linelen = linebuf_get(&server->localClient->buf_sendq,
1312 (char *) (iobuf + c + 3), READBUF_SIZE,
1313 LINEBUF_PARTIAL, LINEBUF_PARSED); /* include partial lines */
1315 if(linelen)
1317 iobuf[c++] = SLINKCMD_INJECT_SENDQ;
1318 iobuf[c++] = (linelen >> 8);
1319 iobuf[c++] = (linelen & 0xff);
1320 c += linelen;
1322 else
1323 break;
1326 /* start io */
1327 iobuf[c++] = SLINKCMD_INIT;
1329 server->localClient->slinkq = iobuf;
1330 server->localClient->slinkq_ofs = 0;
1331 server->localClient->slinkq_len = c;
1333 /* schedule a write */
1334 send_queued_slink_write(server->localClient->ctrlfd, server);
1338 * fork_server
1340 * inputs - struct Client *server
1341 * output - success: 0 / failure: -1
1342 * side effect - fork, and exec SERVLINK to handle this connection
1344 static int
1345 fork_server(struct Client *server)
1347 int ret;
1348 int i;
1349 int ctrl_fds[2];
1350 int data_fds[2];
1352 char fd_str[4][6];
1353 char *kid_argv[7];
1354 char slink[] = "-slink";
1357 /* ctrl */
1358 #ifdef HAVE_SOCKETPAIR
1359 if(socketpair(AF_UNIX, SOCK_STREAM, 0, ctrl_fds) < 0)
1360 #else
1361 if(inet_socketpair(AF_INET,SOCK_STREAM, 0, ctrl_fds) < 0)
1362 #endif
1363 goto fork_error;
1367 /* data */
1368 #ifdef HAVE_SOCKETPAIR
1369 if(socketpair(AF_UNIX, SOCK_STREAM, 0, data_fds) < 0)
1370 #else
1371 if(inet_socketpair(AF_INET,SOCK_STREAM, 0, data_fds) < 0)
1372 #endif
1373 goto fork_error;
1376 #ifdef __CYGWIN__
1377 if((ret = vfork()) < 0)
1378 #else
1379 if((ret = fork()) < 0)
1380 #endif
1381 goto fork_error;
1382 else if(ret == 0)
1384 /* set our fds as non blocking and close everything else */
1385 for (i = 0; i < HARD_FDLIMIT; i++)
1389 if((i == ctrl_fds[1]) || (i == data_fds[1]) || (i == server->localClient->fd))
1391 comm_set_nb(i);
1393 else
1395 #ifdef __CYGWIN__
1396 if(i > 2) /* don't close std* */
1397 #endif
1398 close(i);
1402 ircsnprintf(fd_str[0], sizeof(fd_str[0]), "%d", ctrl_fds[1]);
1403 ircsnprintf(fd_str[1], sizeof(fd_str[1]), "%d", data_fds[1]);
1404 ircsnprintf(fd_str[2], sizeof(fd_str[2]), "%d", server->localClient->fd);
1405 kid_argv[0] = slink;
1406 kid_argv[1] = fd_str[0];
1407 kid_argv[2] = fd_str[1];
1408 kid_argv[3] = fd_str[2];
1409 kid_argv[4] = NULL;
1411 /* exec servlink program */
1412 execv(ConfigFileEntry.servlink_path, kid_argv);
1414 /* We're still here, abort. */
1415 _exit(1);
1417 else
1419 comm_close(server->localClient->fd);
1421 /* close the childs end of the pipes */
1422 close(ctrl_fds[1]);
1423 close(data_fds[1]);
1425 s_assert(server->localClient);
1426 server->localClient->ctrlfd = ctrl_fds[0];
1427 server->localClient->fd = data_fds[0];
1429 if(!comm_set_nb(server->localClient->fd))
1431 report_error(NONB_ERROR_MSG,
1432 get_server_name(server, SHOW_IP),
1433 log_client_name(server, SHOW_IP),
1434 errno);
1437 if(!comm_set_nb(server->localClient->ctrlfd))
1439 report_error(NONB_ERROR_MSG,
1440 get_server_name(server, SHOW_IP),
1441 log_client_name(server, SHOW_IP),
1442 errno);
1445 comm_open(server->localClient->ctrlfd, FD_SOCKET, NULL);
1446 comm_open(server->localClient->fd, FD_SOCKET, NULL);
1448 read_ctrl_packet(server->localClient->ctrlfd, server);
1449 read_packet(server->localClient->fd, server);
1452 return 0;
1454 fork_error:
1455 /* this is ugly, but nicer than repeating
1456 * about 50 close() statements everywhre... */
1457 close(data_fds[0]);
1458 close(data_fds[1]);
1459 close(ctrl_fds[0]);
1460 close(ctrl_fds[1]);
1461 return -1;
1465 * New server connection code
1466 * Based upon the stuff floating about in s_bsd.c
1467 * -- adrian
1471 * serv_connect() - initiate a server connection
1473 * inputs - pointer to conf
1474 * - pointer to client doing the connet
1475 * output -
1476 * side effects -
1478 * This code initiates a connection to a server. It first checks to make
1479 * sure the given server exists. If this is the case, it creates a socket,
1480 * creates a client, saves the socket information in the client, and
1481 * initiates a connection to the server through comm_connect_tcp(). The
1482 * completion of this goes through serv_completed_connection().
1484 * We return 1 if the connection is attempted, since we don't know whether
1485 * it suceeded or not, and 0 if it fails in here somewhere.
1488 serv_connect(struct server_conf *server_p, struct Client *by)
1490 struct Client *client_p;
1491 struct irc_sockaddr_storage myipnum;
1492 int fd;
1494 s_assert(server_p != NULL);
1495 if(server_p == NULL)
1496 return 0;
1499 * Make sure this server isn't already connected
1501 if((client_p = find_server(NULL, server_p->name)))
1503 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
1504 "Server %s already present from %s",
1505 server_p->name, get_server_name(client_p, SHOW_IP));
1506 if(by && IsPerson(by) && !MyClient(by))
1507 sendto_one_notice(by, ":Server %s already present from %s",
1508 server_p->name, get_server_name(client_p, SHOW_IP));
1509 return 0;
1512 /* create a socket for the server connection */
1513 if((fd = comm_socket(server_p->aftype, SOCK_STREAM, 0, NULL)) < 0)
1515 /* Eek, failure to create the socket */
1516 report_error("opening stream socket to %s: %s",
1517 server_p->name, server_p->name, errno);
1518 return 0;
1521 /* servernames are always guaranteed under HOSTLEN chars */
1522 comm_note(fd, "Server: %s", server_p->name);
1524 /* Create a local client */
1525 client_p = make_client(NULL);
1527 /* Copy in the server, hostname, fd
1528 * The sockhost may be a hostname, this will be corrected later
1529 * -- jilles
1531 strlcpy(client_p->name, server_p->name, sizeof(client_p->name));
1532 strlcpy(client_p->host, server_p->host, sizeof(client_p->host));
1533 strlcpy(client_p->sockhost, server_p->host, sizeof(client_p->sockhost));
1534 client_p->localClient->fd = fd;
1537 * Set up the initial server evilness, ripped straight from
1538 * connect_server(), so don't blame me for it being evil.
1539 * -- adrian
1542 if(!comm_set_buffers(client_p->localClient->fd, READBUF_SIZE))
1544 report_error(SETBUF_ERROR_MSG,
1545 get_server_name(client_p, SHOW_IP),
1546 log_client_name(client_p, SHOW_IP),
1547 errno);
1551 * Attach config entries to client here rather than in
1552 * serv_connect_callback(). This to avoid null pointer references.
1554 attach_server_conf(client_p, server_p);
1557 * at this point we have a connection in progress and C/N lines
1558 * attached to the client, the socket info should be saved in the
1559 * client and it should either be resolved or have a valid address.
1561 * The socket has been connected or connect is in progress.
1563 make_server(client_p);
1564 if(by && IsPerson(by))
1566 strcpy(client_p->serv->by, by->name);
1567 if(client_p->serv->user)
1568 free_user(client_p->serv->user, NULL);
1569 client_p->serv->user = by->user;
1570 by->user->refcnt++;
1572 else
1574 strcpy(client_p->serv->by, "AutoConn.");
1575 if(client_p->serv->user)
1576 free_user(client_p->serv->user, NULL);
1577 client_p->serv->user = NULL;
1579 client_p->serv->up = me.name;
1580 client_p->serv->upid = me.id;
1581 SetConnecting(client_p);
1582 dlinkAddTail(client_p, &client_p->node, &global_client_list);
1584 /* log */
1585 ilog(L_SERVER, "Connecting to %s[%s] port %d (%s)", server_p->name, server_p->host, server_p->port,
1586 #ifdef IPV6
1587 server_p->aftype == AF_INET6 ? "IPv6" :
1588 #endif
1589 (server_p->aftype == AF_INET ? "IPv4" : "?"));
1591 if(ServerConfVhosted(server_p))
1593 memcpy(&myipnum, &server_p->my_ipnum, sizeof(myipnum));
1594 ((struct sockaddr_in *)&myipnum)->sin_port = 0;
1595 myipnum.ss_family = server_p->aftype;
1598 else if(server_p->aftype == AF_INET && ServerInfo.specific_ipv4_vhost)
1600 memcpy(&myipnum, &ServerInfo.ip, sizeof(myipnum));
1601 ((struct sockaddr_in *)&myipnum)->sin_port = 0;
1602 myipnum.ss_family = AF_INET;
1603 SET_SS_LEN(myipnum, sizeof(struct sockaddr_in));
1606 #ifdef IPV6
1607 else if((server_p->aftype == AF_INET6) && ServerInfo.specific_ipv6_vhost)
1609 memcpy(&myipnum, &ServerInfo.ip6, sizeof(myipnum));
1610 ((struct sockaddr_in6 *)&myipnum)->sin6_port = 0;
1611 myipnum.ss_family = AF_INET6;
1612 SET_SS_LEN(myipnum, sizeof(struct sockaddr_in6));
1614 #endif
1615 else
1617 comm_connect_tcp(client_p->localClient->fd, server_p->host,
1618 server_p->port, NULL, 0, serv_connect_callback,
1619 client_p, server_p->aftype,
1620 ConfigFileEntry.connect_timeout);
1621 return 1;
1624 comm_connect_tcp(client_p->localClient->fd, server_p->host,
1625 server_p->port, (struct sockaddr *) &myipnum,
1626 GET_SS_LEN(myipnum), serv_connect_callback, client_p,
1627 myipnum.ss_family, ConfigFileEntry.connect_timeout);
1629 return 1;
1633 * serv_connect_callback() - complete a server connection.
1635 * This routine is called after the server connection attempt has
1636 * completed. If unsucessful, an error is sent to ops and the client
1637 * is closed. If sucessful, it goes through the initialisation/check
1638 * procedures, the capabilities are sent, and the socket is then
1639 * marked for reading.
1641 static void
1642 serv_connect_callback(int fd, int status, void *data)
1644 struct Client *client_p = data;
1645 struct server_conf *server_p;
1646 char *errstr;
1648 /* First, make sure its a real client! */
1649 s_assert(client_p != NULL);
1650 s_assert(client_p->localClient->fd == fd);
1652 if(client_p == NULL)
1653 return;
1655 /* while we were waiting for the callback, its possible this already
1656 * linked in.. --fl
1658 if(find_server(NULL, client_p->name) != NULL)
1660 exit_client(client_p, client_p, &me, "Server Exists");
1661 return;
1664 /* Next, for backward purposes, record the ip of the server */
1665 memcpy(&client_p->localClient->ip, &fd_table[fd].connect.hostaddr, sizeof client_p->localClient->ip);
1666 /* Set sockhost properly now -- jilles */
1667 inetntop_sock((struct sockaddr *)&fd_table[fd].connect.hostaddr,
1668 client_p->sockhost, sizeof client_p->sockhost);
1670 /* Check the status */
1671 if(status != COMM_OK)
1673 /* COMM_ERR_TIMEOUT wont have an errno associated with it,
1674 * the others will.. --fl
1676 if(status == COMM_ERR_TIMEOUT)
1678 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
1679 "Error connecting to %s[%s]: %s",
1680 client_p->name,
1681 #ifdef HIDE_SERVERS_IPS
1682 "255.255.255.255",
1683 #else
1684 client_p->host,
1685 #endif
1686 comm_errstr(status));
1687 ilog(L_SERVER, "Error connecting to %s[%s]: %s",
1688 client_p->name, client_p->sockhost,
1689 comm_errstr(status));
1691 else
1693 errstr = strerror(comm_get_sockerr(fd));
1694 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
1695 "Error connecting to %s[%s]: %s (%s)",
1696 client_p->name,
1697 #ifdef HIDE_SERVERS_IPS
1698 "255.255.255.255",
1699 #else
1700 client_p->host,
1701 #endif
1702 comm_errstr(status), errstr);
1703 ilog(L_SERVER, "Error connecting to %s[%s]: %s (%s)",
1704 client_p->name, client_p->sockhost,
1705 comm_errstr(status), errstr);
1708 exit_client(client_p, client_p, &me, comm_errstr(status));
1709 return;
1712 /* COMM_OK, so continue the connection procedure */
1713 /* Get the C/N lines */
1714 if((server_p = client_p->localClient->att_sconf) == NULL)
1716 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "Lost connect{} block for %s",
1717 get_server_name(client_p, HIDE_IP));
1718 exit_client(client_p, client_p, &me, "Lost connect{} block");
1719 return;
1722 /* Next, send the initial handshake */
1723 SetHandshake(client_p);
1725 /* kludge, if we're not using TS6, dont ever send
1726 * ourselves as being TS6 capable.
1728 if(!EmptyString(server_p->spasswd))
1730 if(ServerInfo.use_ts6)
1731 sendto_one(client_p, "PASS %s TS %d :%s",
1732 server_p->spasswd, TS_CURRENT, me.id);
1733 else
1734 sendto_one(client_p, "PASS %s :TS",
1735 server_p->spasswd);
1738 /* pass my info to the new server */
1739 send_capabilities(client_p, default_server_capabs
1740 | (ServerConfCompressed(server_p) ? CAP_ZIP_SUPPORTED : 0)
1741 | (ServerConfTb(server_p) ? CAP_TB : 0));
1743 sendto_one(client_p, "SERVER %s 1 :%s%s",
1744 me.name,
1745 ConfigServerHide.hidden ? "(H) " : "", me.info);
1748 * If we've been marked dead because a send failed, just exit
1749 * here now and save everyone the trouble of us ever existing.
1751 if(IsAnyDead(client_p))
1753 sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
1754 "%s went dead during handshake", client_p->name);
1755 exit_client(client_p, client_p, &me, "Went dead during handshake");
1756 return;
1759 /* don't move to serv_list yet -- we haven't sent a burst! */
1761 /* If we get here, we're ok, so lets start reading some data */
1762 read_packet(fd, client_p);
1765 #ifndef HAVE_SOCKETPAIR
1766 static int
1767 inet_socketpair(int d, int type, int protocol, int sv[2])
1769 struct sockaddr_in addr1, addr2, addr3;
1770 int addr3_len = sizeof(addr3);
1771 int fd, rc;
1772 int port_no = 20000;
1774 if(d != AF_INET || type != SOCK_STREAM || protocol)
1776 errno = EAFNOSUPPORT;
1777 return -1;
1779 if(((sv[0] = socket(AF_INET, SOCK_STREAM, 0)) < 0) || ((sv[1] = socket(AF_INET, SOCK_STREAM, 0)) < 0))
1780 return -1;
1782 addr1.sin_port = htons(port_no);
1783 addr1.sin_family = AF_INET;
1784 addr1.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1785 while ((rc = bind (sv[0], (struct sockaddr *) &addr1, sizeof (addr1))) < 0 && errno == EADDRINUSE)
1786 addr1.sin_port = htons(++port_no);
1788 if(rc < 0)
1789 return -1;
1791 if(listen(sv[0], 1) < 0)
1793 close(sv[0]);
1794 close(sv[1]);
1795 return -1;
1798 addr2.sin_port = htons(port_no);
1799 addr2.sin_family = AF_INET;
1800 addr2.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1801 if(connect (sv[1], (struct sockaddr *) &addr2, sizeof (addr2)) < 0)
1803 close(sv[0]);
1804 close(sv[1]);
1805 return -1;
1808 if((fd = accept(sv[1], (struct sockaddr *) &addr3, &addr3_len)) < 0)
1810 close(sv[0]);
1811 close(sv[1]);
1812 return -1;
1814 close(sv[0]);
1815 sv[0] = fd;
1817 return(0);
1820 #endif