* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
- *
- * $Id: s_serv.c 3550 2007-08-09 06:47:26Z nenolod $
*/
#include "stdinc.h"
#include "ircd_defs.h"
#include "numeric.h"
#include "packet.h"
-#include "res.h"
#include "s_conf.h"
#include "s_newconf.h"
#include "logger.h"
* extra argument to "PASS" takes care of checking that. -orabidoo
*/
struct CapabilityIndex *serv_capindex = NULL;
+struct CapabilityIndex *cli_capindex = NULL;
unsigned int CAP_CAP;
unsigned int CAP_QS;
unsigned int CAP_BAN;
unsigned int CAP_MLOCK;
+unsigned int CLICAP_MULTI_PREFIX;
+unsigned int CLICAP_ACCOUNT_NOTIFY;
+unsigned int CLICAP_EXTENDED_JOIN;
+unsigned int CLICAP_AWAY_NOTIFY;
+unsigned int CLICAP_USERHOST_IN_NAMES;
+unsigned int CLICAP_CAP_NOTIFY;
+unsigned int CLICAP_CHGHOST;
+unsigned int CLICAP_ECHO_MESSAGE;
+
/*
* initialize our builtin capability table. --nenolod
*/
CAP_CAP = capability_put_anonymous(serv_capindex);
CAP_TS6 = capability_put_anonymous(serv_capindex);
- CAP_QS = capability_put(serv_capindex, "QS");
- CAP_EX = capability_put(serv_capindex, "EX");
- CAP_CHW = capability_put(serv_capindex, "CHW");
- CAP_IE = capability_put(serv_capindex, "IE");
- CAP_KLN = capability_put(serv_capindex, "KLN");
- CAP_KNOCK = capability_put(serv_capindex, "KNOCK");
- CAP_ZIP = capability_put(serv_capindex, "ZIP");
- CAP_TB = capability_put(serv_capindex, "TB");
- CAP_UNKLN = capability_put(serv_capindex, "UNKLN");
- CAP_CLUSTER = capability_put(serv_capindex, "CLUSTER");
- CAP_ENCAP = capability_put(serv_capindex, "ENCAP");
- CAP_SERVICE = capability_put(serv_capindex, "SERVICES");
- CAP_RSFNC = capability_put(serv_capindex, "RSFNC");
- CAP_SAVE = capability_put(serv_capindex, "SAVE");
- CAP_EUID = capability_put(serv_capindex, "EUID");
- CAP_EOPMOD = capability_put(serv_capindex, "EOPMOD");
- CAP_BAN = capability_put(serv_capindex, "BAN");
- CAP_MLOCK = capability_put(serv_capindex, "MLOCK");
+ CAP_QS = capability_put(serv_capindex, "QS", NULL);
+ CAP_EX = capability_put(serv_capindex, "EX", NULL);
+ CAP_CHW = capability_put(serv_capindex, "CHW", NULL);
+ CAP_IE = capability_put(serv_capindex, "IE", NULL);
+ CAP_KLN = capability_put(serv_capindex, "KLN", NULL);
+ CAP_KNOCK = capability_put(serv_capindex, "KNOCK", NULL);
+ CAP_ZIP = capability_put(serv_capindex, "ZIP", NULL);
+ CAP_TB = capability_put(serv_capindex, "TB", NULL);
+ CAP_UNKLN = capability_put(serv_capindex, "UNKLN", NULL);
+ CAP_CLUSTER = capability_put(serv_capindex, "CLUSTER", NULL);
+ CAP_ENCAP = capability_put(serv_capindex, "ENCAP", NULL);
+ CAP_SERVICE = capability_put(serv_capindex, "SERVICES", NULL);
+ CAP_RSFNC = capability_put(serv_capindex, "RSFNC", NULL);
+ CAP_SAVE = capability_put(serv_capindex, "SAVE", NULL);
+ CAP_EUID = capability_put(serv_capindex, "EUID", NULL);
+ CAP_EOPMOD = capability_put(serv_capindex, "EOPMOD", NULL);
+ CAP_BAN = capability_put(serv_capindex, "BAN", NULL);
+ CAP_MLOCK = capability_put(serv_capindex, "MLOCK", NULL);
capability_require(serv_capindex, "QS");
capability_require(serv_capindex, "EX");
capability_require(serv_capindex, "IE");
capability_require(serv_capindex, "ENCAP");
+
+ cli_capindex = capability_index_create("client capabilities");
+
+ CLICAP_MULTI_PREFIX = capability_put(cli_capindex, "multi-prefix", NULL);
+ CLICAP_ACCOUNT_NOTIFY = capability_put(cli_capindex, "account-notify", NULL);
+ CLICAP_EXTENDED_JOIN = capability_put(cli_capindex, "extended-join", NULL);
+ CLICAP_AWAY_NOTIFY = capability_put(cli_capindex, "away-notify", NULL);
+ CLICAP_USERHOST_IN_NAMES = capability_put(cli_capindex, "userhost-in-names", NULL);
+ CLICAP_CAP_NOTIFY = capability_put(cli_capindex, "cap-notify", NULL);
+ CLICAP_CHGHOST = capability_put(cli_capindex, "chghost", NULL);
+ CLICAP_ECHO_MESSAGE = capability_put(cli_capindex, "echo-message", NULL);
}
static CNCB serv_connect_callback;
struct server_conf *tmp_p;
struct Class *cltmp;
rb_dlink_node *ptr;
- int connecting = FALSE;
+ bool connecting = false;
int confrq = 0;
time_t next = 0;
continue;
/* don't allow ssl connections if ssl isn't setup */
- if(ServerConfSSL(tmp_p) && (!ssl_ok || !get_ssld_count()))
+ if(ServerConfSSL(tmp_p) && (!ircd_ssl_ok || !get_ssld_count()))
continue;
cltmp = tmp_p->class;
server_p = tmp_p;
/* We connect only one at time... */
- connecting = TRUE;
+ connecting = true;
}
if((next > tmp_p->hold) || (next == 0))
* - int flag of capabilities that this server has
* output - NONE
* side effects - send the CAPAB line to a server -orabidoo
- *
*/
void
send_capabilities(struct Client *client_p, unsigned int cap_can_send)
int mlen;
int cur_len;
- cur_len = mlen = rb_sprintf(buf, ":%s BMASK %ld %s %c :",
+ cur_len = mlen = sprintf(buf, ":%s BMASK %ld %s %c :",
me.id, (long) chptr->channelts, chptr->chname, flag);
t = buf + mlen;
}
if (banptr->forward)
- rb_sprintf(t, "%s$%s ", banptr->banstr, banptr->forward);
+ sprintf(t, "%s$%s ", banptr->banstr, banptr->forward);
else
- rb_sprintf(t, "%s ", banptr->banstr);
+ sprintf(t, "%s ", banptr->banstr);
t += tlen;
cur_len += tlen;
}
if(*chptr->chname != '#')
continue;
- cur_len = mlen = rb_sprintf(buf, ":%s SJOIN %ld %s %s :", me.id,
+ cur_len = mlen = sprintf(buf, ":%s SJOIN %ld %s %s :", me.id,
(long) chptr->channelts, chptr->chname,
channel_modes(chptr, client_p));
t = buf + mlen;
}
- rb_sprintf(t, "%s%s ", find_channel_status(msptr, 1),
+ sprintf(t, "%s%s ", find_channel_status(msptr, 1),
use_id(msptr->client_p));
cur_len += tlen;
hdata.target = client_p;
call_hook(h_server_introduced, &hdata);
- rb_snprintf(note, sizeof(note), "Server: %s", client_p->name);
+ snprintf(note, sizeof(note), "Server: %s", client_p->name);
rb_note(client_p->localClient->F, note);
/*
* -- adrian
*/
-static int
-serv_connect_resolved(struct Client *client_p)
-{
- struct rb_sockaddr_storage myipnum;
- char vhoststr[HOSTIPLEN];
- struct server_conf *server_p;
- uint16_t port;
-
- if((server_p = client_p->localClient->att_sconf) == NULL)
- {
- sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) ? L_NETWIDE : L_ALL, "Lost connect{} block for %s",
- client_p->name);
- exit_client(client_p, client_p, &me, "Lost connect{} block");
- return 0;
- }
-
-#ifdef RB_IPV6
- if(client_p->localClient->ip.ss_family == AF_INET6)
- port = ntohs(((struct sockaddr_in6 *)&client_p->localClient->ip)->sin6_port);
- else
-#endif
- port = ntohs(((struct sockaddr_in *)&client_p->localClient->ip)->sin_port);
-
- if(ServerConfVhosted(server_p))
- {
- memcpy(&myipnum, &server_p->my_ipnum, sizeof(server_p->my_ipnum));
- ((struct sockaddr_in *)&myipnum)->sin_port = 0;
- myipnum.ss_family = server_p->aftype;
-
- }
- else if(server_p->aftype == AF_INET && ServerInfo.specific_ipv4_vhost)
- {
- memcpy(&myipnum, &ServerInfo.ip, sizeof(ServerInfo.ip));
- ((struct sockaddr_in *)&myipnum)->sin_port = 0;
- myipnum.ss_family = AF_INET;
- SET_SS_LEN(&myipnum, sizeof(struct sockaddr_in));
- }
-
-#ifdef RB_IPV6
- else if((server_p->aftype == AF_INET6) && ServerInfo.specific_ipv6_vhost)
- {
- memcpy(&myipnum, &ServerInfo.ip6, sizeof(ServerInfo.ip6));
- ((struct sockaddr_in6 *)&myipnum)->sin6_port = 0;
- myipnum.ss_family = AF_INET6;
- SET_SS_LEN(&myipnum, sizeof(struct sockaddr_in6));
- }
-#endif
- else
- {
- /* log */
- ilog(L_SERVER, "Connecting to %s[%s] port %d (%s)", client_p->name, client_p->sockhost, port,
-#ifdef RB_IPV6
- server_p->aftype == AF_INET6 ? "IPv6" :
-#endif
- (server_p->aftype == AF_INET ? "IPv4" : "?"));
-
- if(ServerConfSSL(server_p))
- {
- rb_connect_tcp(client_p->localClient->F, (struct sockaddr *)&client_p->localClient->ip,
- NULL, 0, serv_connect_ssl_callback,
- client_p, ConfigFileEntry.connect_timeout);
- }
- else
- rb_connect_tcp(client_p->localClient->F, (struct sockaddr *)&client_p->localClient->ip,
- NULL, 0, serv_connect_callback,
- client_p, ConfigFileEntry.connect_timeout);
- return 1;
- }
-
- /* log */
- rb_inet_ntop_sock((struct sockaddr *)&myipnum, vhoststr, sizeof vhoststr);
- ilog(L_SERVER, "Connecting to %s[%s] port %d (%s) (vhost %s)", client_p->name, client_p->sockhost, port,
-#ifdef RB_IPV6
- server_p->aftype == AF_INET6 ? "IPv6" :
-#endif
- (server_p->aftype == AF_INET ? "IPv4" : "?"), vhoststr);
-
-
- if(ServerConfSSL(server_p))
- rb_connect_tcp(client_p->localClient->F, (struct sockaddr *)&client_p->localClient->ip,
- (struct sockaddr *) &myipnum,
- GET_SS_LEN(&myipnum), serv_connect_ssl_callback, client_p,
- ConfigFileEntry.connect_timeout);
- else
- rb_connect_tcp(client_p->localClient->F, (struct sockaddr *)&client_p->localClient->ip,
- (struct sockaddr *) &myipnum,
- GET_SS_LEN(&myipnum), serv_connect_callback, client_p,
- ConfigFileEntry.connect_timeout);
-
- return 1;
-}
-
-static void
-serv_connect_dns_callback(void *vptr, struct DNSReply *reply)
-{
- struct Client *client_p = vptr;
- uint16_t port;
-
- rb_free(client_p->localClient->dnsquery);
- client_p->localClient->dnsquery = NULL;
-
- if (reply == NULL)
- {
- sendto_realops_snomask(SNO_GENERAL, is_remote_connect(client_p) ? L_NETWIDE : L_ALL, "Cannot resolve hostname for %s",
- client_p->name);
- ilog(L_SERVER, "Cannot resolve hostname for %s",
- log_client_name(client_p, HIDE_IP));
- exit_client(client_p, client_p, &me, "Cannot resolve hostname");
- return;
- }
-#ifdef RB_IPV6
- if(reply->addr.ss_family == AF_INET6)
- port = ((struct sockaddr_in6 *)&client_p->localClient->ip)->sin6_port;
- else
-#endif
- port = ((struct sockaddr_in *)&client_p->localClient->ip)->sin_port;
- memcpy(&client_p->localClient->ip, &reply->addr, sizeof(client_p->localClient->ip));
-#ifdef RB_IPV6
- if(reply->addr.ss_family == AF_INET6)
- ((struct sockaddr_in6 *)&client_p->localClient->ip)->sin6_port = port;
- else
-#endif
- ((struct sockaddr_in *)&client_p->localClient->ip)->sin_port = port;
- /* Set sockhost properly now -- jilles */
- rb_inet_ntop_sock((struct sockaddr *)&client_p->localClient->ip,
- client_p->sockhost, sizeof client_p->sockhost);
- serv_connect_resolved(client_p);
-}
-
/*
* serv_connect() - initiate a server connection
*
serv_connect(struct server_conf *server_p, struct Client *by)
{
struct Client *client_p;
- struct rb_sockaddr_storage theiripnum;
- rb_fde_t *F;
+ struct rb_sockaddr_storage myipnum;
char note[HOSTLEN + 10];
+ rb_fde_t *F;
s_assert(server_p != NULL);
if(server_p == NULL)
return 0;
+ /* log */
+ rb_inet_ntop_sock((struct sockaddr *)&server_p->my_ipnum, buf, sizeof(buf));
+ ilog(L_SERVER, "Connect to *[%s] @%s", server_p->name, buf);
+
/*
* Make sure this server isn't already connected
*/
}
/* create a socket for the server connection */
- if((F = rb_socket(server_p->aftype, SOCK_STREAM, 0, NULL)) == NULL)
+ if((F = rb_socket(GET_SS_FAMILY(&server_p->my_ipnum), SOCK_STREAM, 0, NULL)) == NULL)
{
ilog_error("opening a stream socket");
return 0;
}
- rb_snprintf(note, sizeof note, "Server: %s", server_p->name);
+ /* servernames are always guaranteed under HOSTLEN chars */
+ snprintf(note, sizeof(note), "Server: %s", server_p->name);
rb_note(F, note);
/* Create a local client */
client_p = make_client(NULL);
- /* Copy in the server, hostname, fd
- * The sockhost may be a hostname, this will be corrected later
- * -- jilles
- */
+ /* Copy in the server, hostname, fd */
rb_strlcpy(client_p->name, server_p->name, sizeof(client_p->name));
rb_strlcpy(client_p->host, server_p->host, sizeof(client_p->host));
- rb_strlcpy(client_p->sockhost, server_p->host, sizeof(client_p->sockhost));
+ rb_strlcpy(client_p->sockhost, buf, sizeof(client_p->sockhost));
client_p->localClient->F = F;
- add_to_cli_connid_hash(client_p);
+ /* shove the port number into the sockaddr */
+#ifdef RB_IPV6
+ if(GET_SS_FAMILY(&server_p->my_ipnum) == AF_INET6)
+ ((struct sockaddr_in6 *)&server_p->my_ipnum)->sin6_port = htons(server_p->port);
+ else
+#endif
+ ((struct sockaddr_in *)&server_p->my_ipnum)->sin_port = htons(server_p->port);
/*
* Set up the initial server evilness, ripped straight from
* The socket has been connected or connect is in progress.
*/
make_server(client_p);
- if(by && IsPerson(by))
- {
- rb_strlcpy(client_p->serv->by, by->name,
- sizeof client_p->serv->by);
- if(client_p->serv->user)
- free_user(client_p->serv->user, NULL);
- client_p->serv->user = by->user;
- by->user->refcnt++;
- }
+ if(by && IsClient(by))
+ strcpy(client_p->serv->by, by->name);
else
- {
- rb_strlcpy(client_p->serv->by, "AutoConn.",
- sizeof client_p->serv->by);
- if(client_p->serv->user)
- free_user(client_p->serv->user, NULL);
- client_p->serv->user = NULL;
- }
+ strcpy(client_p->serv->by, "AutoConn.");
+
SetConnecting(client_p);
rb_dlinkAddTail(client_p, &client_p->node, &global_client_list);
- if (rb_inet_pton_sock(server_p->host, (struct sockaddr *)&theiripnum) > 0)
+ if(ServerConfVhosted(server_p))
{
- memcpy(&client_p->localClient->ip, &theiripnum, sizeof(client_p->localClient->ip));
-#ifdef RB_IPV6
- if(theiripnum.ss_family == AF_INET6)
- ((struct sockaddr_in6 *)&client_p->localClient->ip)->sin6_port = htons(server_p->port);
- else
-#endif
- ((struct sockaddr_in *)&client_p->localClient->ip)->sin_port = htons(server_p->port);
+ memcpy(&myipnum, &server_p->my_ipnum, sizeof(myipnum));
+ ((struct sockaddr_in *)&myipnum)->sin_port = 0;
+ SET_SS_FAMILY(&myipnum, GET_SS_FAMILY(&server_p->my_ipnum));
- return serv_connect_resolved(client_p);
}
- else
+ else if(GET_SS_FAMILY(&server_p->my_ipnum) == AF_INET && ServerInfo.specific_ipv4_vhost)
{
-#ifdef RB_IPV6
- if(theiripnum.ss_family == AF_INET6)
- ((struct sockaddr_in6 *)&client_p->localClient->ip)->sin6_port = htons(server_p->port);
- else
-#endif
- ((struct sockaddr_in *)&client_p->localClient->ip)->sin_port = htons(server_p->port);
+ memcpy(&myipnum, &ServerInfo.ip, sizeof(myipnum));
+ ((struct sockaddr_in *)&myipnum)->sin_port = 0;
+ SET_SS_FAMILY(&myipnum, AF_INET);
+ SET_SS_LEN(&myipnum, sizeof(struct sockaddr_in));
+ }
- client_p->localClient->dnsquery = rb_malloc(sizeof(struct DNSQuery));
- client_p->localClient->dnsquery->ptr = client_p;
- client_p->localClient->dnsquery->callback = serv_connect_dns_callback;
- gethost_byname_type(server_p->host, client_p->localClient->dnsquery,
#ifdef RB_IPV6
- server_p->aftype == AF_INET6 ? T_AAAA :
+ else if((GET_SS_FAMILY(&server_p->my_ipnum) == AF_INET6) && ServerInfo.specific_ipv6_vhost)
+ {
+ memcpy(&myipnum, &ServerInfo.ip6, sizeof(myipnum));
+ ((struct sockaddr_in6 *)&myipnum)->sin6_port = 0;
+ SET_SS_FAMILY(&myipnum, AF_INET6);
+ SET_SS_LEN(&myipnum, sizeof(struct sockaddr_in6));
+ }
#endif
- T_A);
+ else
+ {
+ if(ServerConfSSL(server_p))
+ {
+ rb_connect_tcp(client_p->localClient->F,
+ (struct sockaddr *)&server_p->my_ipnum, NULL, 0,
+ serv_connect_ssl_callback, client_p,
+ ConfigFileEntry.connect_timeout);
+ }
+ else
+ rb_connect_tcp(client_p->localClient->F,
+ (struct sockaddr *)&server_p->my_ipnum, NULL, 0,
+ serv_connect_callback, client_p,
+ ConfigFileEntry.connect_timeout);
+
return 1;
}
+ if(ServerConfSSL(server_p))
+ rb_connect_tcp(client_p->localClient->F, (struct sockaddr *)&server_p->my_ipnum,
+ (struct sockaddr *)&myipnum,
+ GET_SS_LEN(&myipnum), serv_connect_ssl_callback, client_p,
+ ConfigFileEntry.connect_timeout);
+ else
+ rb_connect_tcp(client_p->localClient->F, (struct sockaddr *)&server_p->my_ipnum,
+ (struct sockaddr *)&myipnum,
+ GET_SS_LEN(&myipnum), serv_connect_callback, client_p,
+ ConfigFileEntry.connect_timeout);
+
+ return 1;
}
static void
return;
}
- del_from_cli_connid_hash(client_p);
client_p->localClient->F = xF[0];
- add_to_cli_connid_hash(client_p);
client_p->localClient->ssl_ctl = start_ssld_connect(F, xF[1], rb_get_fd(xF[0]));
+ if(!client_p->localClient->ssl_ctl)
+ {
+ serv_connect_callback(client_p->localClient->F, RB_ERROR, data);
+ return;
+ }
SetSSL(client_p);
serv_connect_callback(client_p->localClient->F, RB_OK, client_p);
}