mdnsd
mdnsd copied to clipboard
IPv6 not implemented
Both the responder and resolver don't seem to be working over IPv6: the responder does not respond, and the resolver won't resolv AAAA records (there's actually no way to query them via CLI).
Also, a lookups to FF02::FB should be sent.
I never actually got to implement ipv6, it was one of the last things in my TODO.
I tried to implement this, but the latest git -master won't build for me:
$ make
cc -O2 -pipe -g -Wall -I/home/hugo/mdns/mdnsd -I../ -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual -Wsign-compare -c log.c
In file included from log.h:24,
from log.c:33:
mdnsd.h:85: error: expected specifier-qualifier-list before 'RB_ENTRY'
mdnsd.h:144: error: expected specifier-qualifier-list before 'RB_ENTRY'
*** Error 1 in /home/hugo/mdns/mdnsd (<sys.mk>:87 'log.o')
Ah, people have been fixing things in the ports tree, so we need to sync the code + patches in ports in the git repo.
I noticed all the patches from ports have been applies to master. Maybe it's time to update the port to make is nice and clean now that the patches are upstream?
I'll see if I can do something with the IPv6 issue - no promises though (I'm not much of a C expert).
I agree, I've just released 0.6 and there should be no more need for the patches in ports.
@hobarrera if you post your code I might help you out with it. :)
I just had a quick look to see if it was actually easy to implement the IPv6 part, at least for collecting the information for the "face" (interface.c:if_new). It looks as though the IPv6 version of SIOCGIFADDR doesn't work, and it certainly appears to be deprecated since it can only return a single address and the IPv6 configuration may have many addresses on an interface -- though the only one you probably care about is the link-local one (and I believe there should be exactly one of those).
The only way I've found to get the IPv6 addresses that's reliable is to use SIOCGIFCONF, which returns an ifreq structure for each address for each interface -- though the documentation is wrong for it -- it doesn't return an array of ifreq objects, you have to calculate the size of each one and walk through the buffer filled with them. The sizes of the sockaddrs in them are different depending on the address family.
More on the SIOCGIFCONF etc. The code in kiface.c (from ripd's kroute.c) appears to predate the getifaddrs() call, which should probably replace the sysctl() calls in fetchifs(), and fetches all the addresses associated with each interface. If the addresses from that are kept, rather than trying to do SIOCGIFADDR calls then a bunch if the code in interface.c can also go away, and the addition and deletion of addresses on an interface can be handled properly. Unfortunately I discovered that the current code can't cope with an interface that has multiple IPv4 addresses.
Sadly, it's not only the kernel interface that needs to support ipv6, it needs also support for the protocol itself. Getting addresses and so on shouldn't be much work though.
I've started work on plumbing in IPv6 at https://github.com/twinshadow/mdnsd/tree/ipv6
Right now, mdnsd will bind an IPv4 and IPv6 listening socket, but only the IPv4 is wired-up and mdnsctl can parse both IPv4 and IPv6 <address> input, but nothing resolves becuase T_AAAA packets are still a no-op in packet.c.
Feedback appreciated. I've built and tested on OpenBSD6.6 and FreeBSD-current, but I don't have a lot of interesting mdns traffic happening on my network. Next steps will be refactoring struct iface and associated code, which is the other 90% of the work :)
About all I have to show is some debug output from mdnsd in response to ./mdnsctl rlookup fe80::ba:57ff:febb:8bdc, but as I stated earlier, nothing is wired up so rlookup fails.
startup
[...]
mdns sock bound to 0.0.0.0:5353
mdns sock bound to :::5353
[...]
cache_insert: (new, cleaned up) (0x80078b400) C.D.B.8.B.B.E.F.F.F.7.5.A.B.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.8.E.F.ip6.arpa (PTR)
cache_insert: (new, cleaned up) (0x800767c00) 103.32.168.192.in-addr.arpa (PTR)
cache_insert: (new, cleaned up) (0x80078c000) C.D.B.8.B.B.E.F.F.F.7.5.A.B.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.8.E.F.ip6.arpa (NSEC)
cache_insert: (new, cleaned up) (0x80078bc00) 103.32.168.192.in-addr.arpa (NSEC)
[... cache_insert worked before, just showing that the
address is advertised by another mdns server ...]
looking up C.D.B.8.B.B.E.F.F.F.7.5.A.B.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.E.F.in6.arpa (PTR 1)
control_send_rr (PTR) C.D.B.8.B.B.E.F.F.F.7.5.A.B.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.E.F.in6.arpa
question_remove C.D.B.8.B.B.E.F.F.F.7.5.A.B.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.E.F.in6.arpa (PTR)
I'll try to have a look soon-- I have a FreeBSD 12.0 32-bit system plus a load of macOS/iOS devices on a network with IPv6 enabled. There are some windows boxes too, but not sure how IPv6 they use.
-- Nick Briggs
On Oct 4, 2019, at 3:04 PM, Anthony Cornehl [email protected] wrote:
I've started work on plumbing in IPv6 at https://github.com/twinshadow/mdnsd/tree/ipv6 https://github.com/twinshadow/mdnsd/tree/ipv6 Right now, mdnsd will bind an IPv4 and IPv6 listening socket, but only the IPv4 is wired-up and mdnsctl can parse both IPv4 and IPv6
input, but nothing resolves becuase T_AAAA packets are still a no-op in packet.c.Feedback appreciated. I've built and tested on OpenBSD6.6 and FreeBSD-current, but I don't have a lot of interesting mdns traffic happening on my network. Next steps will be refactoring struct iface and associated code, which is the other 90% of the work :)
About all I have to show is some debug output from mdnsd in response to ./mdnsctl rlookup fe80::ba:57ff:febb:8bdc, but as I stated earlier, nothing is wired up so rlookup fails.
startup [...] mdns sock bound to 0.0.0.0:5353
mdns sock bound to :::5353
[...] cache_insert: (new, cleaned up) (0x80078b400) C.D.B.8.B.B.E.F.F.F.7.5.A.B.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.8.E.F.ip6.arpa (PTR) cache_insert: (new, cleaned up) (0x800767c00) 103.32.168.192.in-addr.arpa (PTR) cache_insert: (new, cleaned up) (0x80078c000) C.D.B.8.B.B.E.F.F.F.7.5.A.B.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.8.E.F.ip6.arpa (NSEC) cache_insert: (new, cleaned up) (0x80078bc00) 103.32.168.192.in-addr.arpa (NSEC) [... cache_insert worked before, just showing that the address is advertised by another mdns server ...] looking up C.D.B.8.B.B.E.F.F.F.7.5.A.B.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.E.F.in6.arpa (PTR 1)
control_send_rr (PTR) C.D.B.8.B.B.E.F.F.F.7.5.A.B.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.E.F.in6.arpa
question_remove C.D.B.8.B.B.E.F.F.F.7.5.A.B.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.E.F.in6.arpa (PTR)
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/haesbaert/mdnsd/issues/4?email_source=notifications&email_token=AB6DAWKW46VFCVCXY37JCWTQM64XRA5CNFSM4APUQ5KKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEAM772I#issuecomment-538574825, or mute the thread https://github.com/notifications/unsubscribe-auth/AB6DAWIJJRSCWKIF76HU7F3QM64XRANCNFSM4APUQ5KA.
The first thing I ran into was in mdnsd/mdnsd.c:155 where you are using a "struct sockaddr addr" for storage on the stack. It's not big enough (should probably be sockaddr_storage) so the stack gets corrupted. That will need a cast for the addr arg to bind(). Then you can lose the cast at 195 in the call to sstop().
It might also be clearer to throw in a "socklen_t socklen" and assign the length in the switch(af)... rather than checking af again at 178.
Once it's running... it gets a little confused when IPv6 address changes (or additions) happen:
cache_insert: (new, cleaned up) (0x282f6d80) HP8D0CC5.local (A) if_fsm: interface bge0, event 'UP' not expected in state 'ACTIVE' RTM_NEWADDR
when it acquired the 2602: address resulting in bge0 looking like:
bge0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
options=8009b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,LINKSTATE>
ether 00:12:79:c0:c8:26
inet 192.168.42.90 netmask 0xffffff00 broadcast 192.168.42.255
inet6 fe80::212:79ff:fec0:c826%bge0 prefixlen 64 scopeid 0x1
inet6 2602:24a:de47:d2c0:212:79ff:fec0:c826 prefixlen 64 autoconf
media: Ethernet autoselect (100baseTX
It's also logging a lot of
pkt_parse_rr: edns0 'owner-option'
but that's not the IPv6 code's problem.
-- Nick
On Oct 4, 2019, at 3:04 PM, Anthony Cornehl [email protected] wrote:
I've started work on plumbing in IPv6 at https://github.com/twinshadow/mdnsd/tree/ipv6 https://github.com/twinshadow/mdnsd/tree/ipv6 Right now, mdnsd will bind an IPv4 and IPv6 listening socket, but only the IPv4 is wired-up and mdnsctl can parse both IPv4 and IPv6
input, but nothing resolves becuase T_AAAA packets are still a no-op in packet.c.Feedback appreciated. I've built and tested on OpenBSD6.6 and FreeBSD-current, but I don't have a lot of interesting mdns traffic happening on my network. Next steps will be refactoring struct iface and associated code, which is the other 90% of the work :)
About all I have to show is some debug output from mdnsd in response to ./mdnsctl rlookup fe80::ba:57ff:febb:8bdc, but as I stated earlier, nothing is wired up so rlookup fails.
startup [...] mdns sock bound to 0.0.0.0:5353
mdns sock bound to :::5353
[...] cache_insert: (new, cleaned up) (0x80078b400) C.D.B.8.B.B.E.F.F.F.7.5.A.B.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.8.E.F.ip6.arpa (PTR) cache_insert: (new, cleaned up) (0x800767c00) 103.32.168.192.in-addr.arpa (PTR) cache_insert: (new, cleaned up) (0x80078c000) C.D.B.8.B.B.E.F.F.F.7.5.A.B.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.8.E.F.ip6.arpa (NSEC) cache_insert: (new, cleaned up) (0x80078bc00) 103.32.168.192.in-addr.arpa (NSEC) [... cache_insert worked before, just showing that the address is advertised by another mdns server ...] looking up C.D.B.8.B.B.E.F.F.F.7.5.A.B.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.E.F.in6.arpa (PTR 1)
control_send_rr (PTR) C.D.B.8.B.B.E.F.F.F.7.5.A.B.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.E.F.in6.arpa
question_remove C.D.B.8.B.B.E.F.F.F.7.5.A.B.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.E.F.in6.arpa (PTR)
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/haesbaert/mdnsd/issues/4?email_source=notifications&email_token=AB6DAWKW46VFCVCXY37JCWTQM64XRA5CNFSM4APUQ5KKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEAM772I#issuecomment-538574825, or mute the thread https://github.com/notifications/unsubscribe-auth/AB6DAWIJJRSCWKIF76HU7F3QM64XRANCNFSM4APUQ5KA.
The first thing I ran into was in mdnsd/mdnsd.c:155 where you are using a "struct sockaddr addr" for storage on the stack. It's not big enough (should probably be sockaddr_storage) so the stack gets corrupted. That will need a cast for the addr arg to bind(). Then you can lose the cast at 195 in the call to sstop(). It might also be clearer to throw in a "socklen_t socklen" and assign the length in the switch(af)... rather than checking af again at 178.
Thanks for catching that! Changes are now in the branch.
Once it's running... it gets a little confused when IPv6 address changes (or additions) happen: cache_insert: (new, cleaned up) (0x282f6d80) HP8D0CC5.local (A) if_fsm: interface bge0, event 'UP' not expected in state 'ACTIVE' RTM_NEWADDR when it acquired the 2602: address resulting in bge0 looking like: bge0: flags=8843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500 options=8009b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,LINKSTATE> ether 00:12:79:c0:c8:26 inet 192.168.42.90 netmask 0xffffff00 broadcast 192.168.42.255 inet6 fe80::212:79ff:fec0:c826%bge0 prefixlen 64 scopeid 0x1 inet6 2602:24a:de47:d2c0:212:79ff:fec0:c826 prefixlen 64 autoconf media: Ethernet autoselect (100baseTX
) status: active nd6 options=23<PERFORMNUD,ACCEPT_RTADV,AUTO_LINKLOCAL>
That may be some issue with the event code, which I plan on going into next.
As for the interface structure, struct iface, the challenge faced with changing it is that it will have to handle multiple IP addresses where it currently only handles a single IP address. I anticipate a large amount of existing code will need to be refactored to make this work, so I'm going to think about this change and take more notes before I commit anything.
edit: removed the diff and code example
@twinshadow -- I looked at the change you made regarding the sockaddr_storage. You left it passing sizeof(sockaddr), being the size of a generic sockaddr_storage, which results in an invalid argument error from the bind() call. The size passed must match the size of the type of sockaddr being passed in. Try:
@@ -155,18 +157,19 @@ mdns_sock(sa_family_t af)
struct sockaddr_storage addr;
struct sockaddr_in *sa4 = (struct sockaddr_in*)&addr;
struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)&addr;
+ socklen_t socklen;
char addrstr[INET6_ADDRSTRLEN];
switch(af) {
case AF_INET:
sa4->sin_family = af;
- sa4->sin_len = sizeof(struct sockaddr_in);
+ sa4->sin_len = socklen = sizeof(struct sockaddr_in);
sa4->sin_port = htons(MDNS_PORT);
sa4->sin_addr.s_addr = INADDR_ANY;
break;
case AF_INET6:
sa6->sin6_family = af;
- sa6->sin6_len = sizeof(struct sockaddr_in6);
+ sa6->sin6_len = socklen = sizeof(struct sockaddr_in6);
sa6->sin6_port = htons(MDNS_PORT);
memcpy(&sa6->sin6_addr.s6_addr, &in6addr_any, sizeof(in6addr_any));
break;
@@ -175,7 +178,7 @@ mdns_sock(sa_family_t af)
if ((sock = socket(af, SOCK_DGRAM, IPPROTO_UDP)) == -1)
fatal("socket");
- if (bind(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr)) == -1)
+ if (bind(sock, (struct sockaddr *)&addr, socklen) == -1)
fatal("bind");
if (if_set_opt(af, sock) == -1)