haesbaert / mdnsd Goto Github PK
View Code? Open in Web Editor NEWMdns daemon for OpenBSD.
Home Page: www.haesbaert.org/openmdns
Mdns daemon for OpenBSD.
Home Page: www.haesbaert.org/openmdns
It would be nice to have reflector functionality like avahi so that received broadcasts on one interface go to all other interfaces allowed.
Some services should, it seems, be served at the dummy port 0, but this is forbidden by mdnsctl
.
I think that the ._device-info._tcp
service is supposed to be served at port 0 (Macs, for example, advertise this service as a way of broadcasting information about the host). Unfortunately, I can't find chapter and verse which states this. However the following observations might be relevant:
_device-info._tcp
, but without mentioning specifically the port number.dns-sd
manpage mentions, under its -R
documentation on ‘register a service’, that the port must be in the range 0 to 65535.Port 0 is forbidden by mdnsctl
because of the call:
res.port = strtonum(word, 1, UINT16_MAX, &errstr);
at line 309 of parser.c
. Perhaps explicit
res.port = strtonum(word, 0, 65535, &errstr);
would be better.
Currently we are preserving domain name cases.
Every strcmp should be replaced by strcasecmp.
Trying to run mdnsd on FreeBSD 11.2-RELEASE-p9 with a GENERIC Kernel, in a jail mounted on the loopback interface:
lo1: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
inet 172.16.10.10 netmask 0xfffffff0
groups: lo
Results in this error:
# mdnsd -d lo1
startup
cache_insert: (new, cleaned up) (0x801c1c800) files [lo1:00:00:00:00:00:00]._workstation._tcp.local (SRV)
cache_insert: (new, cleaned up) (0x801c1cc00) files [lo1:00:00:00:00:00:00]._workstation._tcp.local (TXT)
using iface lo1 index 4
cache_insert: (new, cleaned up) (0x801c1d800) files.local (A)
cache_insert: (new, cleaned up) (0x801c1dc00) 10.10.16.172.in-addr.arpa (PTR)
cache_insert: (new, cleaned up) (0x801c1e000) files.local (HINFO)
opened raw socket with kernel on fd 5
mdns sock bound to 0.0.0.0:5353
if_fsm: event 'UP' resulted in action 'START' and changing state for interface lo1 from 'DOWN' to 'ACTIVE'
pkt_sendto: insane mtu
Can't send packet through lo1
can't send probe packet
pkt_sendto: insane mtu
Can't send packet through lo1
can't send probe packet
…
can't send announce packet
Changing the default mtu
on the host works:
# ifconfig lo1 mtu 1500
# iocage console files
# ifconfig lo1
lo1: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 1500
options=600003<RXCSUM,TXCSUM,RXCSUM_IPV6,TXCSUM_IPV6>
inet 172.16.10.10 netmask 0xfffffff0
groups: lo
# mdnsd -d lo1
startup
cache_insert: (new, cleaned up) (0x801c1c800) files [lo1:00:00:00:00:00:00]._workstation._tcp.local (SRV)
cache_insert: (new, cleaned up) (0x801c1cc00) files [lo1:00:00:00:00:00:00]._workstation._tcp.local (TXT)
using iface lo1 index 4
cache_insert: (new, cleaned up) (0x801c1d800) files.local (A)
cache_insert: (new, cleaned up) (0x801c1dc00) 10.10.16.172.in-addr.arpa (PTR)
cache_insert: (new, cleaned up) (0x801c1e000) files.local (HINFO)
opened raw socket with kernel on fd 5
mdns sock bound to 0.0.0.0:5353
if_fsm: event 'UP' resulted in action 'START' and changing state for interface lo1 from 'DOWN' to 'ACTIVE'
But, now all the other jails must use the lower mtu
setting.
I'd noticed lots of invalid packet classes (packet.c, pkt_parse_rr() checking rr->rrs.class) on my machine. Turns out this comes from T_OPT packets, which are different from others.
I'm still working on a patch, but in short, rr->rrs.type needs to be checked for T_OPT (41) before reading for cacheflush and rr->rrs.class. (I.e., after the dname read, which will be blank.) Otherwise, these values are not meaningful, as the T_OPT (RFC 2671) doesn't set the fields appropriately.
Hi,
I've built openmdnsd on FreeBSD (to replace avahi) and have found that I can't publish a service with two TXT records. In order to publish Apple's TimeMachine share on my NAS running netatalk I would normally use the avahi record:
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
<name replace-wildcards="yes">%h</name>
<service>
<type>_adisk._tcp</type>
<port>9</port>
<txt-record>sys=waMA=3c:d9:2b:04:2b:6f,adVF=0x100</txt-record>
<txt-record>dk0=adVF=0xa1,adVN=tm,adVU=12D28B6D-AFD0-1D56-7161-723FBFE36EDC</txt-record>
</service>
</service-group>
But doing the following with mdnsctl:
mdnsctl publish nas-01 adisk tcp 9 "sys=waMA=3c:d9:2b:04:2b:6f,adVF=0x100" "dk0=adVF=0xa1,adVN=tm,adVU=12D28B6D-AFD0-1D56-7161-723FBFE36EDC"
throws a superfluous argument error.
Running two mdnsctl commands with a TXT record in each throws a collision error.
Can you permit multiple TXT records on the command line?
Thanks.
In the pkg-readme
, it should also be mentioned that net.inet.ip.mforwarding
needs to be enabled.
net.inet.ip6.mforwarding
is also mentioned in the multicast(4)
man page, but doesn't seem to exist (?).
On second thought, there may be a of rule I was missing, but the above sysctl did fix the issue for me. I will try to investigate further and report back.
the version of the code in OpenBSD 6.3 is still openmdns-0.7p0 -- is there something that needs to be done to get the most current code into the package repository?
It's marked as "Maintainer: Gonzalo L. R. [email protected]"
Easy pickings. Doing mdnsd is much harder because it setsockopts in a way that can't be done within a pledge.
I ran a "Slow comprehensive scan" in Zenmap and mdnsd crashed in the result.
mdnsd -d:
using iface rl0 index 1 startup publish_insert: type: A name: katarzyna.local publish_insert: type: PTR name: 254.0.0.10.in-addr.arpa publish_insert: type: HINFO name: katarzyna.local opened raw socket with kernel on fd 5 mdns sock bound to 0.0.0.0:5353 if_fsm: event 'UP' resulted in action 'START' and changing state for interface rl0 from 'DOWN' to 'ACTIVE' looking up premysl-laptop.local (A 1) cache_lookup premysl-laptop.local (A) query_fsm control_send_rr (A) premysl-laptop.local question_remove premysl-laptop.local (A) pkt_parse_question: Non unicast question from 10.0.0.1:49644 with ephemeral source port, droping packet pkt_parse_question: Non unicast question from 10.0.0.1:49900 with ephemeral source port, droping packet pkt_parse_question: Non unicast question from 10.0.0.1:50156 with ephemeral source port, droping packet pkt_parse_question: Non unicast question from 10.0.0.1:53378 with ephemeral source port, droping packet pkt_parse_question: Non unicast question from 10.0.0.1:53378 with ephemeral source port, droping packet Unknown 390 pkt_parse_rr: Unknown () Invalid packet class 8192 Can't parse AR RR pkt_parse_question: Non unicast question from 10.0.0.1:53378 with ephemeral source port, droping packet pkt_parse_question: Non unicast question from 10.0.0.1:53378 with ephemeral source port, droping packet pkt_parse_header: bad packet size 3485373366 Segmentation fault
I can't tell yet whether this is an issue with mdnsd or with the OpenBSD "tl" ethernet driver, but after a number of IPv6 address changes (autoconf privacy enabled) mdnsd stops responding and does not appear to have refreshed for an extended period. If it is shut down it logs an error on attempting to write the "goodbye" messages:
Oct 31 12:20:21 pigeon mdnsd: cache_process: refresh Macadamia.local (AAAA)
Oct 31 12:26:32 pigeon mdnsd: cache_process: refresh silversword._device-info._tcp.local (TXT)
[... no mdnsd refresh entries, a few more errors from the shutdown omitted here ...]
Nov 1 09:30:25 pigeon mdnsd: rr_send_an error 85.42.168.192.in-addr.arpa (PTR)
Nov 1 09:30:25 pigeon mdnsd: rr_send_an error pigeon.local (HINFO)
Nov 1 09:30:25 pigeon mdnsd: terminating
turning off the IPv6 address refresh seems to stop the problem.
I'll continue to investigate.
I've found the mdnsd, at least as packaged for FreeBSD 12.1-RELEASE-p3,
SHA256 (haesbaert-mdnsd-0.7_GH0.tar.gz) = cb552f3431e57a3ad09b011f91ebdb8cc100a5c38978fcdb0fea27fc5ebd2880
SIZE (haesbaert-mdnsd-0.7_GH0.tar.gz) = 2935140
leaks memory until swap space fills and it crashes with a calloc() failure.
Running it on valgrind shows that the main leaks are of AN RR entries (packet.c:257), and AR RR entries (packet.c:281). I haven't tracked down what's in those RR entries that are lost.
Running mdnsd
in the foreground I see a lot of pkt_parse_rr: edns0 'owner-option'
and there are quite a few AN RRs of type T_A and T_AAAA which have 0 as the IP address. None of the counts obviously add up to the number of leaked blocks.
==16672== HEAP SUMMARY:
==16672== in use at exit: 3,095,498 bytes in 3,539 blocks
==16672== total heap usage: 11,050 allocs, 7,511 frees, 5,430,492 bytes allocated
==16672==
==16672== 320 bytes in 1 blocks are definitely lost in loss record 21 of 42
==16672== at 0x71E35B7: calloc (vg_replace_malloc.c:884)
==16672== by 0x40DD87: pge_from_ms (mdns.c:766)
==16672== by 0x40EA71: pge_new_workstation (mdns.c:1112)
==16672== by 0x406A48: if_new (interface.c:437)
==16672== by 0x404983: conf_init_ifaces (mdnsd.c:88)
==16672== by 0x405002: main (mdnsd.c:324)
==16672==
==16672== 320 bytes in 1 blocks are definitely lost in loss record 22 of 42
==16672== at 0x71E35B7: calloc (vg_replace_malloc.c:884)
==16672== by 0x40E786: pge_initprimary (mdns.c:1050)
==16672== by 0x40500A: main (mdnsd.c:327)
==16672==
==16672== 466,200 (257,520 direct, 208,680 indirect) bytes in 290 blocks are definitely lost in loss record 40 of 42
==16672== at 0x71E35B7: calloc (vg_replace_malloc.c:884)
==16672== by 0x406FE4: recv_packet (packet.c:281)
==16672== by 0x7219B96: ??? (in /usr/local/lib/libevent-2.1.so.7.0.0)
==16672== by 0x7215173: event_base_loop (in /usr/local/lib/libevent-2.1.so.7.0.0)
==16672== by 0x7214CAA: event_dispatch (in /usr/local/lib/libevent-2.1.so.7.0.0)
==16672== by 0x4050AE: main (mdnsd.c:359)
==16672==
==16672== 2,430,456 (340,992 direct, 2,089,464 indirect) bytes in 384 blocks are definitely lost in loss record 42 of 42
==16672== at 0x71E35B7: calloc (vg_replace_malloc.c:884)
==16672== by 0x406EFB: recv_packet (packet.c:257)
==16672== by 0x7219B96: ??? (in /usr/local/lib/libevent-2.1.so.7.0.0)
==16672== by 0x7215173: event_base_loop (in /usr/local/lib/libevent-2.1.so.7.0.0)
==16672== by 0x7214CAA: event_dispatch (in /usr/local/lib/libevent-2.1.so.7.0.0)
==16672== by 0x4050AE: main (mdnsd.c:359)
==16672==
==16672== LEAK SUMMARY:
==16672== definitely lost: 599,152 bytes in 676 blocks
==16672== indirectly lost: 2,298,144 bytes in 2,588 blocks
==16672== possibly lost: 0 bytes in 0 blocks
==16672== still reachable: 198,202 bytes in 275 blocks
==16672== suppressed: 0 bytes in 0 blocks
In mdns.c, it seems that the "goodbye" and "refresh" messages should not be logged using log_warnx() which produces LOG_CRIT level messages. Since these are really an expected part of normal operations they should probably be logged with log_info() or log_debug().
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).
Hey there,
You mention in one of your goals libc integration. What is the status of this? I couldn't find any reference to that in OBSD manpages.
Thanks,
The manpage gives a brief example of using mdnsctl
to publish a service. The example is perhaps a little too brief.
From the name, and from the (of course, only roughly standardised) behaviour of other fooctl
tools on various unixes, I expected that the mdnsctl publish
command would communicate with the running daemon, adjust its configuration, and exit. The manpage, and its publish
example, did not make me think otherwise. When I saw the process ‘hanging’, I went to the mdnsctl
source to confirm that the main()
did indeed intend to be in a forever-loop.
Looking at closed issue #6 , I can see that I am not the only one to be confused about this.
It would be good if the manpage (i) gave a slightly fuller explanation, which mentioned that the process is supposed to ‘hang’, that (ii) it's useful to redirect the output, and that (iii) there will indeed be one process per published service, by design.
mdnsd -d cat /tmp/list
with more than 30 interfaces causes mdnsd to segfault.
It seems to be problematic to run mdnsd both in the host and in a jail: the jail instance takes over and the host is no longer accessible by its .local name. That makes sense because the IP stack is shared between host and jails. But mdnsctl proxy can only advertise services, not hosts. I would like to have a similar feature to advertise the jail hostname/IP address mappings, so that one instance is enough. Avahi for example does it if you have multiple hosts listed in /etc/avahi/hosts.
From GCC 7.0:
control.c: In function 'control_group_add':
control.c:340:13: warning: variable 'pg' set but not used [-Wunused-but-set-variable]
struct pg *pg;
^~
packet.c: In function 'pkt_parse_rr':
packet.c:962:55: warning: variable 'pl' set but not used [-Wunused-but-set-variable]
u_int16_t us, rdlen = 0, tmplen, i, code, plen, erc, pl;
^~
packet.c:962:50: warning: variable 'erc' set but not used [-Wunused-but-set-variable]
u_int16_t us, rdlen = 0, tmplen, i, code, plen, erc, pl;
^~~
mdns.c: In function 'pge_kill':
mdns.c:959:13: warning: variable 'pg' set but not used [-Wunused-but-set-variable]
struct pg *pg;
^~
mdnsd.c: In function 'fetchhinfo':
mdnsd.c:210:39: warning: '%s' directive output may be truncated writing up to 255 bytes into a region of size between 0 and 255 [-Wformat-truncation=]
snprintf(hi->os, sizeof(hi->os), "%s %s", utsname.sysname,
^~
utsname.release);
~~~~~~~
mdnsd.c:210:2: note: 'snprintf' output between 2 and 512 bytes into a destination of size 256
snprintf(hi->os, sizeof(hi->os), "%s %s", utsname.sysname,
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
utsname.release);
~~~~~~~~~~~~~~~~
From scan-build 4.0:
mdnsl.c:347:4: warning: Value stored to 'r' is never read
r = mdns_handle_lookup(m, &rr, ev);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mdnsl.c:356:4: warning: Value stored to 'r' is never read
r = mdns_handle_browse(m, &rr, ev);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mdnsl.c:365:4: warning: Value stored to 'r' is never read
r = mdns_handle_resolve(m, &ms, ev);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mdnsl.c:383:4: warning: Value stored to 'r' is never read
r = mdns_handle_group(m, groupname, ev);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
mdnsl.c:544:2: warning: Value stored to 'p' is never read
p = start = namecp;
^ ~~~~~~~~~~~~~~
control.c:359:2: warning: Value stored to 'pg' is never read
pg = pg_get(1, msg, c);
^ ~~~~~~~~~~~~~~~~~
packet.c:559:4: warning: Value stored to 'n' is never read
n = 0;
^ ~
packet.c:1167:7: warning: Use of memory after it is freed
if (qst->flags & QST_FLAG_UNIRESP) {
^~~~~~~~~~
packet.c:1296:3: warning: Value stored to 'len' is never read
len -= INT16SZ;
^ ~~~~~~~
packet.c:1361:3: warning: Value stored to 'len' is never read
len -= oslen;
^ ~~~~~
packet.c:1375:3: warning: Value stored to 'len' is never read
len -= rdlen;
^ ~~~~~
packet.c:1386:3: warning: Value stored to 'len' is never read
len -= rdlen;
^ ~~~~~
packet.c:1411:3: warning: Value stored to 'len' is never read
len -= n;
^ ~
packet.c:1452:2: warning: Value stored to 'len' is never read
len -= n;
^ ~
mdns.c:485:3: warning: Use of memory after it is freed
question_remove(rrs);
^~~~~~~~~~~~~~~~~~~~
mdns.c:961:2: warning: Value stored to 'pg' is never read
pg = pge->pg;
^ ~~~~~~~
mdns.c:1129:3: warning: Use of memory after it is freed
pge_kill(pge);
^~~~~~~~~~~~~
It would be nice if mdnsd
wrote its PID to a /var/run
file, so that the daemon can be conveniently killed within an rc
script.
It would appear that calling pidfile(3) somewhere near the beginning of main
would be sufficient to set this up rather nicely.
Hi!
I also found that label compression code compares only full labels, not parts of it. For example the second domain name in response with a single answer:
a._tcp.local PTR b._tcp.local
can be compressed like this:
0000000: 01 62 c0 0e
It won't even handle this case:
a.b._tcp.local PTR b._tcp.local
I've seen several mdns implementations and I wonder: why doesn't anybody use dn_expand() and dn_comp()? Is there something wrong with them? I think, they should be available on OpenBSD...
Hi!
Probably you should replace condition in rr_rdata_cmp() this way:
(RR_INADDRANY(rra) || RR_INADDRANY(rra)) -> (RR_INADDRANY(rra) || RR_INADDRANY(rrb))
When publishing a service with something like the below command, the prompt never appears again.
root@ap:~ # mdnsctl publish MySite http tcp 80 "WWW"
Group MySite is probing...
Group MySite is announcing...
Group MySite published.
Running openmdns on OpenBSD 5.7 GENERIC#837
Let me know if there is more information I can provide.
I didn't have this problem on FreeBSD 11.0, but on OpenBSD 6.1 despite mdnsd's doing the proper IP_ADD_MEMBERSHIP, it doesn't receive any multicast packets. If you run "tcpdump -i port 5353" then the promiscuous mode will enable it to see the packets, but with "tcpdump -p -i port 5353" you don't see them. Hosts that cache the initial packets sent will see the system for a while, but then the cache entries time out and further queries are not answered.
I could easily believe this is something I've done wrong in my OpenBSD configuration, but I don't know what...
multicast=YES in /etc/rc.conf.local
ifconfig tl0
tl0: flags=208843<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST,AUTOCONF6> mtu 1500
lladdr 00:80:5f:bd:53:49
index 1 priority 0 llprio 3
groups: egress
media: Ethernet autoselect (100baseTX full-duplex)
status: active
inet6 fe80::280:...%tl0 prefixlen 64 scopeid 0x1
inet6 2602:24a:... prefixlen 64 autoconf pltime 604764 vltime 2591964
inet6 2602:24a:... prefixlen 64 autoconf autoconfprivacy pltime 58831 vltime 577557
inet 192.168.42.88 netmask 0xffffff00 broadcast 192.168.42.255
malloc() warning: unknown char in MALLOC_OPTIONS
malloc() warning: unknown char in MALLOC_OPTIONS
startup
cache_insert: (new, cleaned up) (0x86ab1400) pigeon [tl0:00:80:5f:bd:53:49]._workstation._tcp.local (SRV)
cache_insert: (new, cleaned up) (0x840f3400) pigeon [tl0:00:80:5f:bd:53:49]._workstation._tcp.local (TXT)
using iface tl0 index 1
cache_insert: (new, cleaned up) (0x840f6000) pigeon.local (A)
cache_insert: (new, cleaned up) (0x86aac000) 88.42.168.192.in-addr.arpa (PTR)
cache_insert: (new, cleaned up) (0x86ab1800) pigeon.local (HINFO)
opened raw socket with kernel on fd 5
mdns sock bound to 0.0.0.0:5353
if_fsm: event 'UP' resulted in action 'START' and changing state for interface tl0 from 'DOWN' to 'ACTIVE'
In mdnsd/packet.c, when logging a failure from pkt_parse_rr(...)
, it would be helpful to log the source address of the bad packet to identify the responsible system.
I shall submit a PR with a fix for this.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.