diff --git a/include/client.h b/include/client.h index 6f3d62a0..90c01614 100644 --- a/include/client.h +++ b/include/client.h @@ -265,6 +265,8 @@ struct LocalUser struct ZipStats zipstats; + struct DNSQuery *dnsquery; /* for outgoing server's name lookup */ + time_t last_away; /* Away since... */ time_t last; diff --git a/src/client.c b/src/client.c index b7153339..b45acb2f 100644 --- a/src/client.c +++ b/src/client.c @@ -1402,6 +1402,11 @@ exit_unknown_client(struct Client *client_p, struct Client *source_p, struct Cli const char *comment) { delete_auth_queries(source_p); + if (source_p->localClient->dnsquery) + { + delete_resolver_queries(source_p->localClient->dnsquery); + rb_free(source_p->localClient->dnsquery); + } del_unknown_ip(source_p); rb_dlinkDelete(&source_p->localClient->tnode, &unknown_list); diff --git a/src/s_serv.c b/src/s_serv.c index 0b417680..0f6839ab 100644 --- a/src/s_serv.c +++ b/src/s_serv.c @@ -1443,6 +1443,125 @@ fork_server(struct Client *server) * -- 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", + get_server_name(client_p, HIDE_IP)); + 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(myipnum)); + ((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(myipnum)); + ((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(myipnum)); + ((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" : "?")); + + 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 */ + inetntop_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); + + + 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", + get_server_name(client_p, HIDE_IP)); + 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 */ + inetntop_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 * @@ -1464,9 +1583,8 @@ int serv_connect(struct server_conf *server_p, struct Client *by) { struct Client *client_p; - struct rb_sockaddr_storage myipnum, theiripnum; + struct rb_sockaddr_storage theiripnum; rb_fde_t *F; - char vhoststr[HOSTIPLEN]; char note[HOSTLEN + 10]; s_assert(server_p != NULL); @@ -1487,24 +1605,6 @@ serv_connect(struct server_conf *server_p, struct Client *by) return 0; } - if (rb_inet_pton_sock(server_p->host, (struct sockaddr *)&theiripnum) <= 0) - { - sendto_realops_snomask(SNO_GENERAL, L_ALL, - "Server %s host is a DNS name which is currently not implemented", - server_p->name); - if(by && IsPerson(by) && !MyClient(by)) - sendto_one_notice(by, ":Server %s host is a DNS name which is currently not implemented", - server_p->name); - return 0; - } - -#ifdef RB_IPV6 - if(theiripnum.ss_family == AF_INET6) - ((struct sockaddr_in6 *)&theiripnum)->sin6_port = htons(server_p->port); - else -#endif - ((struct sockaddr_in *)&theiripnum)->sin_port = htons(server_p->port); - /* create a socket for the server connection */ if((F = rb_socket(server_p->aftype, SOCK_STREAM, 0, NULL)) == NULL) { @@ -1525,7 +1625,6 @@ serv_connect(struct server_conf *server_p, struct Client *by) strlcpy(client_p->name, server_p->name, sizeof(client_p->name)); strlcpy(client_p->host, server_p->host, sizeof(client_p->host)); strlcpy(client_p->sockhost, server_p->host, sizeof(client_p->sockhost)); - memcpy(&client_p->localClient->ip, &theiripnum, sizeof(client_p->localClient->ip)); client_p->localClient->F = F; /* @@ -1571,63 +1670,37 @@ serv_connect(struct server_conf *server_p, struct Client *by) SetConnecting(client_p); rb_dlinkAddTail(client_p, &client_p->node, &global_client_list); - if(ServerConfVhosted(server_p)) + if (rb_inet_pton_sock(server_p->host, (struct sockaddr *)&theiripnum) > 0) { - memcpy(&myipnum, &server_p->my_ipnum, sizeof(myipnum)); - ((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(myipnum)); - ((struct sockaddr_in *)&myipnum)->sin_port = 0; - myipnum.ss_family = AF_INET; - SET_SS_LEN(&myipnum, sizeof(struct sockaddr_in)); - } - + memcpy(&client_p->localClient->ip, &theiripnum, sizeof(client_p->localClient->ip)); #ifdef RB_IPV6 - else if((server_p->aftype == AF_INET6) && ServerInfo.specific_ipv6_vhost) - { - memcpy(&myipnum, &ServerInfo.ip6, sizeof(myipnum)); - ((struct sockaddr_in6 *)&myipnum)->sin6_port = 0; - myipnum.ss_family = AF_INET6; - SET_SS_LEN(&myipnum, sizeof(struct sockaddr_in6)); - } + 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); + + return serv_connect_resolved(client_p); + } else { - /* log */ - ilog(L_SERVER, "Connecting to %s[%s] port %d (%s)", server_p->name, server_p->host, server_p->port, #ifdef RB_IPV6 - server_p->aftype == AF_INET6 ? "IPv6" : + if(theiripnum.ss_family == AF_INET6) + ((struct sockaddr_in6 *)&client_p->localClient->ip)->sin6_port = htons(server_p->port); + else #endif - (server_p->aftype == AF_INET ? "IPv4" : "?")); + ((struct sockaddr_in *)&client_p->localClient->ip)->sin_port = htons(server_p->port); - rb_connect_tcp(client_p->localClient->F, - (struct sockaddr *) &theiripnum, - NULL, 0, - serv_connect_callback, client_p, - ConfigFileEntry.connect_timeout); - return 1; + 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 : +#endif + T_A); + return 1; } - - /* log */ - inetntop_sock((struct sockaddr *)&myipnum, vhoststr, sizeof vhoststr); - ilog(L_SERVER, "Connecting to %s[%s] port %d (%s) (vhost %s)", server_p->name, server_p->host, server_p->port, -#ifdef RB_IPV6 - server_p->aftype == AF_INET6 ? "IPv6" : -#endif - (server_p->aftype == AF_INET ? "IPv4" : "?"), vhoststr); - - - rb_connect_tcp(client_p->localClient->F, - (struct sockaddr *) &theiripnum, - (struct sockaddr *) &myipnum, GET_SS_LEN(&myipnum), - serv_connect_callback, client_p, - ConfigFileEntry.connect_timeout); - - return 1; } /* @@ -1662,14 +1735,6 @@ serv_connect_callback(rb_fde_t *F, int status, void *data) return; } -#if 0 - /* Next, for backward purposes, record the ip of the server */ - memcpy(&client_p->localClient->ip, &F->connect.hostaddr, sizeof client_p->localClient->ip); - /* Set sockhost properly now -- jilles */ - inetntop_sock((struct sockaddr *)&F->connect.hostaddr, - client_p->sockhost, sizeof client_p->sockhost); -#endif - /* Check the status */ if(status != RB_OK) {