]> jfr.im git - irc/rqf/shadowircd.git/blobdiff - src/s_serv.c
Branch merge.
[irc/rqf/shadowircd.git] / src / s_serv.c
index 0b417680c73043d24b8df2802d0d9d1103815119..0f6839ab814397b70c9a38a688bb4f69de647642 100644 (file)
@@ -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" : "?"));
-
-               rb_connect_tcp(client_p->localClient->F,
-                               (struct sockaddr *) &theiripnum,
-                               NULL, 0,
-                               serv_connect_callback, client_p,
-                               ConfigFileEntry.connect_timeout);
-                return 1;
-       }
+                       ((struct sockaddr_in *)&client_p->localClient->ip)->sin_port = htons(server_p->port);
 
-       /* 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,
+               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 ? "IPv6" :
+                               server_p->aftype == AF_INET6 ? T_AAAA :
 #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;
+                               T_A);
+               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)
        {