On Thu, Dec 17, 2020 at 12:15:16PM +0100, Otto Moerbeek wrote:
> Hi,

> 
> as noted on misc dig does not like to talk to local link addresses.
> This fixes that case. While investigating I also found another bug:

Thanks for looking into this. Looks like I got distracted while
ripping out isc_sockaddr and did not fully clean it up. Probably
because I found another isc_indirection to delete :/

I'd rather like to get rid of isc_sockaddr_fromin* completely, see
diff at the end.

> selecting v6 or v4 addresses only from resolv.conf via the -4 or -6
> command line argument does not work as expected.

Nice catch.

> 
> This fixes both. I did not test binding to a src address with this.
> This is likely as broken as it was before.

My diff fixes that, too.

I still need to keep isc_sockaddr_fromin* because it's used for
+subnet i.e. ecs. Which is broken, too. I'm having a look now.

> 
>       -Otto
> 

> Index: lib/lwres/lwconfig.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/dig/lib/lwres/lwconfig.c,v
> retrieving revision 1.6
> diff -u -p -r1.6 lwconfig.c
> --- lib/lwres/lwconfig.c      25 Feb 2020 05:00:43 -0000      1.6
> +++ lib/lwres/lwconfig.c      17 Dec 2020 11:06:49 -0000
> @@ -231,7 +231,7 @@ lwres_conf_parsenameserver(lwres_conf_t 
>  
>       res = lwres_create_addr(word, &address, 1);
>       use_ipv4 = confdata->flags & LWRES_USEIPV4;
> -     use_ipv6 = confdata->flags & LWRES_USEIPV4;
> +     use_ipv6 = confdata->flags & LWRES_USEIPV6;
>       if (res == LWRES_R_SUCCESS &&
>           ((address.family == LWRES_ADDRTYPE_V4 && use_ipv4) ||
>           (address.family == LWRES_ADDRTYPE_V6 && use_ipv6))) {
> 

OK florian for this

OK for this version for the rest?


diff --git dig.c dig.c
index a0988a0567b..6b142a03239 100644
--- dig.c
+++ dig.c
@@ -17,7 +17,10 @@
 /* $Id: dig.c,v 1.18 2020/09/15 11:47:42 florian Exp $ */
 
 /*! \file */
-#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netdb.h>
 
 #include <errno.h>
 #include <stdlib.h>
@@ -1275,10 +1278,7 @@ dash_option(char *option, char *next, dig_lookup_t 
**lookup,
        dns_rdatatype_t rdtype;
        dns_rdataclass_t rdclass;
        char textname[MXNAME];
-       struct in_addr in4;
-       struct in6_addr in6;
-       in_port_t srcport;
-       char *hash, *cmd;
+       char *cmd;
        uint32_t num;
        const char *errstr;
 
@@ -1346,28 +1346,39 @@ dash_option(char *option, char *next, dig_lookup_t 
**lookup,
        if (value == NULL)
                goto invalid_option;
        switch (opt) {
-       case 'b':
+       case 'b': {
+               struct addrinfo *ai = NULL, hints;
+               int error;
+               char *hash;
+
+               memset(&hints, 0, sizeof(hints));
+               hints.ai_flags = AI_NUMERICHOST;
+               hints.ai_socktype = SOCK_STREAM;
+
                hash = strchr(value, '#');
                if (hash != NULL) {
-                       num = strtonum(hash + 1, 0, MAXPORT, &errstr);
-                       if (errstr != NULL)
-                               fatal("port number is %s: '%s'", errstr,
-                                   hash + 1);
-                       srcport = num;
                        *hash = '\0';
+                       error = getaddrinfo(value, hash + 1, &hints, &ai);
+                       *hash = '#';
                } else
-                       srcport = 0;
-               if (have_ipv6 && inet_pton(AF_INET6, value, &in6) == 1)
-                       isc_sockaddr_fromin6(&bind_address, &in6, srcport);
-               else if (have_ipv4 && inet_pton(AF_INET, value, &in4) == 1)
-                       isc_sockaddr_fromin(&bind_address, &in4, srcport);
-               else
+                       error = getaddrinfo(value, NULL, &hints, &ai);
+
+               if (error)
+                       fatal("invalid address %s: %s", value,
+                           gai_strerror(error));
+               if (ai == NULL || ai->ai_addrlen > sizeof(bind_address))
+                       fatal("invalid address %s", value);
+               if (!have_ipv4 && ai->ai_family == AF_INET)
+                       fatal("invalid address %s", value);
+               if (!have_ipv6 && ai->ai_family == AF_INET6)
                        fatal("invalid address %s", value);
 
-               if (hash != NULL)
-                       *hash = '#';
+               memset(&bind_address, 0, sizeof(bind_address));
+               memcpy(&bind_address, ai->ai_addr, ai->ai_addrlen);
+
                specified_source = 1;
                return (value_from_next);
+       }
        case 'c':
                if ((*lookup)->rdclassset) {
                        fprintf(stderr, ";; Warning, extra class option\n");
diff --git dighost.c dighost.c
index 52afde3d7d3..3974843600d 100644
--- dighost.c
+++ dighost.c
@@ -498,6 +498,7 @@ get_addresses(const char *hostname, in_port_t dstport,
 {
        struct addrinfo *ai = NULL, *tmpai, hints;
        int result, i;
+       char dport[sizeof("65535")];
 
        REQUIRE(hostname != NULL);
        REQUIRE(addrs != NULL);
@@ -515,7 +516,8 @@ get_addresses(const char *hostname, in_port_t dstport,
        }
        hints.ai_socktype = SOCK_STREAM;
 
-       result = getaddrinfo(hostname, NULL, &hints, &ai);
+       snprintf(dport, sizeof(dport), "%d", dstport);
+       result = getaddrinfo(hostname, dport, &hints, &ai);
        switch (result) {
        case 0:
                break;
@@ -532,16 +534,10 @@ get_addresses(const char *hostname, in_port_t dstport,
                if (tmpai->ai_family != AF_INET &&
                    tmpai->ai_family != AF_INET6)
                        continue;
-               if (tmpai->ai_family == AF_INET) {
-                       struct sockaddr_in *sin;
-                       sin = (struct sockaddr_in *)tmpai->ai_addr;
-                       isc_sockaddr_fromin(&addrs[i], &sin->sin_addr, dstport);
-               } else {
-                       struct sockaddr_in6 *sin6;
-                       sin6 = (struct sockaddr_in6 *)tmpai->ai_addr;
-                       isc_sockaddr_fromin6(&addrs[i], &sin6->sin6_addr,
-                                            dstport);
-               }
+               if (tmpai->ai_addrlen > sizeof(addrs[i]))
+                       continue;
+               memset(&addrs[i], 0, sizeof(addrs[i]));
+               memcpy(&addrs[i], tmpai->ai_addr, tmpai->ai_addrlen);
                i++;
 
        }


-- 
I'm not entirely sure you are real.

Reply via email to