On Thu, Nov 03, 2022 at 10:27:53PM +0000, Klemens Nanni wrote:
> RFC 2132 "DHCP Options and BOOTP Vendor Extensions"
> 3.8. Domain Name Server Option says:
> 
>    The domain name server option specifies a list of Domain Name System
>    (STD 13, RFC 1035 [8]) name servers available to the client.  Servers
>    SHOULD be listed in order of preference.
> 
> I'm on a wifi with three name servers in its DHCP OFFER, which tcpdump',
> `route monitor' and and `dhcpleasctl -l athn0' show in the same order.
> 
> But in my case, resolvd writes them in reverse order, making our
> resolver query the least preferred one first as per resolv.conf(5):
> 
>       Up to ASR_MAXNS (currently 5) name servers may be listed, one
>       per line.  If there are multiple servers, the resolver
>       library queries them in the order listed.
> 
> I have yet into a specific problem due to this, but this behaviour did
> surprise me.
> 
> Looking at resolvd(8), this is because it sorts the list of name servers
> by prio (makes sense) as well as IP (why?).
> 
> If I sort them only by prio and switch to mergesort(3) to have a stable
> function, the resulting order in resolv.conf is exactly what I see in
> the DHCP OFFER, as expected.

New diff zapping duplicate IPs in a only prio-sorted list,
`route nameserver lo0 2.2.2.2 1.1.1.1 1.1.1.1' now yields

        nameserver 127.0.0.1 # resolvd: unwind
        #nameserver 2.2.2.2 # resolvd: lo0
        #nameserver 1.1.1.1 # resolvd: lo0
        #nameserver 8.8.4.4 # resolvd: athn0
        #nameserver 8.8.8.8 # resolvd: athn0
        lookup file bind

instead of

        nameserver 127.0.0.1 # resolvd: unwind
        #nameserver 1.1.1.1 # resolvd: lo0
        #nameserver 2.2.2.2 # resolvd: lo0
        #nameserver 8.8.4.4 # resolvd: athn0
        #nameserver 8.8.8.8 # resolvd: athn0
        lookup file bind

Did I miss anything

Index: resolvd.c
===================================================================
RCS file: /cvs/src/sbin/resolvd/resolvd.c,v
retrieving revision 1.28
diff -u -p -r1.28 resolvd.c
--- resolvd.c   2 Sep 2022 09:39:55 -0000       1.28
+++ resolvd.c   5 Nov 2022 11:10:08 -0000
@@ -503,17 +503,22 @@ handle_route_message(struct rt_msghdr *r
                return;
        }
 
-       /* Sort proposals, based upon priority and IP */
-       qsort(learning, ASR_MAXNS, sizeof(learning[0]), cmp);
+       /* Sort proposals, based upon priority */
+       if (mergesort(learning, ASR_MAXNS, sizeof(learning[0]), cmp) == -1)
+               lerr(1, "mergesort");
 
-       /* Eliminate duplicates */
+       /* Eliminate duplicate IPs per interface */
        for (i = 0; i < ASR_MAXNS - 1; i++) {
+               int j;
+
                if (learning[i].prio == 0)
                        continue;
-               if (learning[i].if_index == learning[i+1].if_index &&
-                   strcmp(learning[i].ip, learning[i+1].ip) == 0) {
-                       zeroslot(&learning[i + 1]);
-                       i--;    /* backup and re-check */
+
+               for (j = i + 1; j < ASR_MAXNS; j++) {
+                       if (learning[i].if_index == learning[j].if_index &&
+                           strcmp(learning[i].ip, learning[j].ip) == 0) {
+                               zeroslot(&learning[j]);
+                       }
                }
        }
 
@@ -694,10 +699,7 @@ cmp(const void *a, const void *b)
 {
        const struct rdns_proposal      *rpa = a, *rpb = b;
 
-       if (rpa->prio == rpb->prio)
-               return strcmp(rpa->ip, rpb->ip);
-       else
-               return rpa->prio < rpb->prio ? -1 : 1;
+       return (rpa->prio < rpb->prio) ? -1 : (rpa->prio > rpb->prio);
 }
 
 #ifndef SMALL

Reply via email to