Git Product home page Git Product logo

mdnsd's Introduction

mdnsd - embeddable Multicast DNS Daemon

License svg Repology svg GitHub svg Coverity svg

About

Jeremie Miller's original mDNS/mDNS-SD library daemon.

Download a versioned relased tarball (not a GitHub zip) to unlock a fully supported version. Hardcore devs. can proceed to clone the GIT repository, see below for help.

Usage

mdnsd by default reads service definitions from /etc/mdns.d/*, but a different path can be given, which may be a directory or a single file.

Usage: mdnsd [-hnpsv] [-i IFACE] [-l LEVEL] [-t TTL] [PATH]

    -h        This help text
    -i IFACE  Announce services only on this interface, default: all
    -l LEVEL  Set log level: none, err, notice (default), info, debug
    -n        Run in foreground, do not detach from controlling terminal
    -s        Use syslog even if running in foreground
    -t TTL    Set TTL of mDNS packets, default: 1 (link-local only)
    -v        Show program version

Bug report address: https://github.com/troglobit/mdnsd/issues

By default mdnsd daemonizes, detaches from the controlling terminal and continues running in the background, logging errors (or debug messages if enabled) to the systmem log. There is no output to be expected. On GNU/Linux, use mdns-scan, the bundled mquery tool, or Wireshark to verify your setup. Other operating systems have their own set of tools for mDNS-SD and mdnsd may not even have a place there.

mdnsd runs on all multicast enabled system interfaces. It can be limted to run on only one using the -i IFACE command line option. Starting mdnsd early in the boot process, when the interface may not yet have acquired an IP address, or the interface itself may not even exist yet, mdnsd handles this by periodically probing for interface changes.

See the file API.md for pointers on how to use the mDNS library.

Service Records

This section provides a couple of service record examples. The syntax of the files is fairly free form. Optional directives: name, txt, target, and cname.

Note: you need at least one service record for mdnsd to respond to queries from, e.g., mdns-scan.

FTP service example:

# /etc/mdns.d/ftp.service -- mDNS-SD advertisement of FTP service
name Troglobit FTP Server
type _ftp._tcp
port 21
txt server=uftpd
txt version=2.6
target ftp.luthien.local
cname ftp.local

HTTP service example:

# /etc/mdns.d/http.service -- mDNS-SD advertisement of HTTP service
name Troglobit HTTP Server
type _http._tcp
port 80
txt server=merecat
txt version=2.31
target www.luthien.local
cname home.local

SSH service example:

# /etc/mdns.d/http.service -- mDNS-SD advertisement of SSH service
name Dropbear SSH Server
type _ssh._tcp
port 22

Build & Install

This project is built for and developed on GNU/Linux systems, but should work on any UNIX1 like system. Use the standard GNU configure script to create a Makefile for your system and then call make.

./configure
make all
make install

Users who checked out the source from GitHub must run ./autogen.sh first to create the configure script. This requires GNU autotools and pkg-config to be installed on the build system. For the test suite you also need libcmocka-dev.

If you install to the default location used by the configure script, the library is installed in /usr/local/lib, which may not be in the default search path for your system. Depending on the C library used, the file /etc/ld.so.conf may exist (there may also be a sub-directory). If /usr/local/lib is already listed there, you may need to update the cache:

ldconfig -v |grep mdnsd

If you don't get any output from the above command, the ld.so.conf needs updating, or you may not be using the GNU C library.

Origin & References

This mDNS-SD implementation was developed by Jeremie Miller in 2003, originally announced on the rendezvous-dev mailing list. The original name was 'mhttp'. It has many forks and has been used by many other applications over the years.

The GitHub project is an attempt by Joachim Wiberg to clean up the original code base, develop it further, and maintain it for the long haul under the name mdnsd.

Footnotes

  1. Builds and runs fine on: FreeBSD, NetBSD, OpenBSD, DragonFly BSD, and Illumos/SmartOS. โ†ฉ

mdnsd's People

Contributors

alexmyczko avatar bong1991 avatar chrisbeaumont67 avatar dbrignoli avatar fzs avatar jpfr avatar laroche avatar monkeybreaker avatar mterron avatar p-fleer avatar pro avatar sinisterchipmunk avatar thom-nic avatar troglobit avatar wolframroesler avatar xovis-jburella avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mdnsd's Issues

Make version number available to applications

Looking for a way to display the mDNS version number in application software. Could be something simple like

#define MDNSD_VERSION "0.10"

in the header file.

It'll have to be updated every time a new version is released, of course. This could be done manually (you'll need to remember) or automatically (you'd need a script to patch the header file, maybe using git describe, and run it via a CI job or commit hook or whatever).

I can implement it and submit a PR. Just let me know if the solution suggested above is OK for you.

For the record, what I actually need is a way to extract the version number from a copy of the source code, so I can check which version we've got in our code base and compare it to the latest version here on GitHub. For that purpose it'd be sufficient to put the version number into the readme file, but I think the solution suggested above would be more useful for other applications.

usage description wrong

Hey,

just a minor wrong printf in the usage description. In line 92 of mdnsd.c it still says mhttp. To get rid of it for all time, you could make
printf("usage: %s 'unique name' 12.34.56.78 80 '/optionalpath'\n", argv[0]);

Best regards

Detect IP address changes

So, I'm running on a device that may boot up with no Ethernet connected, or it could be boot on a DHCP network, then be disconnected and reconnected to a switch without DHCP, falling back to a ZeroConf IP address, etc. Currently I'm using busybox ifplugd to detect interface events, which in turn trigger udhcpc and zcip (the ZeroConf daemon) to restart. udhcpc and zcip then fire their own scripts when e.g. a DHCP lease is obtained or a ZeroConf IP is allocated.

In mdnsd.c, it looks like ina is assigned once in main() and it's assumed that address will not change. I see SIGHUP will re-read config files but not reload IP address. So I'm left with killing/restarting mdnsd when any IP address changes.

I don't know if the easiest solution is rtnetlink notification, calling getifaddrs() periodically and comparing the result, or letting an external program signal that the IP address has changed.

I also noticed that mdnsd quit with an error Failed writing to socket: Invalid argument presumably when the interface was unplugged. Or maybe there's no "easy" way to handle this, and the right answer is just killing and restarting mdnsd.

I imagine this could be related to #8 but that issue didn't mention address changes.

Does not reply to queries for A records

I've tried ping foo.local when mdnsd announces a record with foo.local as target. Putting it in here mainly for my own bookkeeping.

Blocker for the v0.8 release.

Support multiple IP addresses per interface

The setup:

  • interface vlan1
    • 192.168.2.200
    • 169.254.29.54 (link local address

mdnsd sends out a query for its own services, presumably to avoid conflicts. The queries have the source address 169.254.29.54:5353 and destination 224.0.0.251:5353. mdnsd somehow responds to its own query, and it says it has the IP-address 192.168.2.200. The response however has the source address 169.254.29.54:5353.

The log files are filled with messages like these:

Jan  1 00:10:56 ptwos-coronet-61-9f-20 mdnsd[1424]: vlan1: conlicting name detected ptwos-coronet-61-9f-20-167._ssh._tcp.local. for type 16, reloading config ...
Jan  1 00:10:56 ptwos-coronet-61-9f-20 mdnsd[1424]: vlan1: conlicting name detected ptwos-coronet-61-9f-20-168._ssh._tcp.local. for type 33, reloading config ...
Jan  1 00:10:56 ptwos-coronet-61-9f-20 mdnsd[1424]: vlan1: conlicting name detected ptwos-coronet-61-9f-20-168.local. for type 1, reloading config ...
Jan  1 00:10:56 ptwos-coronet-61-9f-20 mdnsd[1424]: vlan1: conlicting name detected ptwos-coronet-61-9f-20-168._ssh._tcp.local. for type 16, reloading config ...
Jan  1 00:10:57 ptwos-coronet-61-9f-20 mdnsd[1424]: vlan1: conlicting name detected ptwos-coronet-61-9f-20-169._ssh._tcp.local. for type 33, reloading config ...
Jan  1 00:10:57 ptwos-coronet-61-9f-20 mdnsd[1424]: vlan1: conlicting name detected ptwos-coronet-61-9f-20-169.local. for type 1, reloading config ...
Jan  1 00:10:57 ptwos-coronet-61-9f-20 mdnsd[1424]: vlan1: conlicting name detected ptwos-coronet-61-9f-20-169._ssh._tcp.local. for type 16, reloading config ...
Jan  1 00:10:58 ptwos-coronet-61-9f-20 mdnsd[1424]: vlan1: conlicting name detected ptwos-coronet-61-9f-20-170._ssh._tcp.local. for type 33, reloading config ...
Jan  1 00:10:58 ptwos-coronet-61-9f-20 mdnsd[1424]: vlan1: conlicting name detected ptwos-coronet-61-9f-20-170.local. for type 1, reloading config ...
Jan  1 00:10:58 ptwos-coronet-61-9f-20 mdnsd[1424]: vlan1: conlicting name detected ptwos-coronet-61-9f-20-170._ssh._tcp.local. for type 16, reloading config ...

If I drop either address from the interface, it has no problems.

Add support for IPv6

... should be fairly simple actually. Replace all the relevant parts of the code with struct sockaddr_storage

Use config files to define DNS-SD services

mdnsd currently assumes you want to advertise a single HTTP service however mDNS/DNS-SD allows one to advertise multiple services (e.g. http, tftp, ssh.) Since SO_REUSEADDR is being used I think one could run multiple mdnsd processes, each specifying a different service.

So at minimum, as you mentioned in #4 this could get facelifted to use getopt, and take the service type as an optional flag.

However it should, I think, also be possible to respond with multiple DNS records as well e.g. when looking up foo.local you could return multiple A or AAAA records. I'm not sure how practical that becomes w/r/t specifying everything as options. Furthermore I'm trying to think through "what happens if/when the network changes?" e.g. if mdnsd is started before ethernet is plugged in, wifi goes up or down, DHCP lease acquired or lost. I would have to kill and restart mdnsd when any of those changes occur.

I am wondering (and I understand this would be a bit of work!) if it would make sense for mdnsd to take a config file (bind9 format?) and respond to queries for any names in that file. In that case, if network configuration changes, the file could be re-written/ read by mdnsd (use SIGUSR1 to re-read?) and potentially avoid restarting the daemon.

IP address selection and operation while no address

As reported by @thom-nic in #14 (comment), mdnsd picks the first address returned by getaddrinfo() and happily runs even when the (any) interface still hasn't got a valid address.

As @thom-nic points out, announcing mDNS records with address 0.0.0.0 is not ideal since it'll take the TTL before they expire.

  1. When starting up we should handle the "no address yet" case by deferring our transmitting any records (we can enter the main loop and receive packets, but not send)
  2. When we get an address we should not just accept the first non-zero address, but ask for more until we get "the best" address (a future version of mdnsd would need to announce more records I think, at least for both IPv4 and IPv6)
  3. If we lose our address at runtime, and don't have any other valid address, we should revoke our records and goto 1.

Continuous Multicast DNS Querying

Hi I would like to know whether Continuous Multicast DNS Querying feature is implemented in this stack. If yes, could you please tell me how to find where this information is located

API mdns_set_ip() is broken, endian trouble

The way IP addresses are handled in libmdnsd is broken. Currently the daemon has to employ ugly tactics like this (below) to avoid clobbering the address on the network. Refactor needed!

	mdnsd_set_raw(d, r, (char *)&addr, 4);
//	mdnsd_set_ip(d, r, mdnsd_get_address(d));

Double conf_init in case of config reload: is it needed?

mdnsd/src/mdnsd.c

Lines 432 to 440 in 4570d3e

if (reload) {
sys_init();
for (iface = iface_iterator(1); iface; iface = iface_iterator(0)) {
records_clear(iface->mdns);
conf_init(iface, path, hostnm);
}
pidfile(PACKAGE_NAME);
reload = 0;
}

Why does this reload case do a sys_init (which runs conf_init on each interface), and then removes all records and calls a conf_init again on every interface? I am a bit confused as to why this is necessary.

Unfortunately neither the commit nor the PR introducing the records_clear has any information as to why removing all records is necessary. But if it is, then does this really need to happen in two loops over the interfaces? Wouldn't the records_clear rather have to be in sys_init or conf_init? It is initialization, after all (according to the name).

Regression introduced in v0.11

Hi,

First of all, thank you for maintaining this great library. Second, I won't be able to describe precisely my issue, because I did not still fully grasped but I hope providing enough information to help fixing this issue. I, of course will try to help, but my understanding of the library is limited for the moment.

I deployed v0.11, and after some time (15min to some hours) mdnsd was crashing, I saw that a SIGSEGV was thrown.

Looking at the reason of this SIGSEGV, I got a double free. Continue my debugging, the back-trace showed the following:

  1. (src/mdnsd.c) main -> L.458
  2. (src/mdnsd.c) free_iface -> L.112
  3. (libmdnsd/mdnsd.c) mdnsd_free -> L.755
  4. (libmdnsd/mdnsd.c) _free_record -> L.399

As far as I understood the issue, it seems that function free_iface doesn't clean correctly the iface (I my be wrong).
It is not easy to reproduce, but a brutal way I found out is to simply comment the entire if. It is a bit brutal, but the moment you start the application it will SIGSEGV, with the details I show before.

I was able for the moment to find a workaround, which for the moment seems to work (4 days running, no crash observed so far). In function free_iface, after the if condition, I call iface_free(iface). This function comes from addr.c and seems to clean "correctly" the interface.

I am not sure this is the correct fix, but for the moment It seems to work.

BTW, I put regression in the name of the issue, because I tested commenting the same if with the commit before 872d508, and no SIGSEGV observed.

No support for key-only TXT strings

I noticed that the library will ignore txt entries that have only a key but no value, i.e. are of the form txt key. Is there a reason other than it not being implemented?
It looks like the implementation was done according to RFC 1464 and not the mDNS-SD RFC 6763. While the former specifies to ignore TXT strings that have no unquoted = in them, the latter explicitly allows key-only entries as boolean flags.

Why is IP_PKTINFO set?

At some point the socket option IP_PKTINFO was getting set on the server's socket. I found no explanation for this. Since the code doesn't even use sendmsg or recvmsg, can this be removed?

if (setsockopt(sd, IPPROTO_IP, IP_PKTINFO, &flag, sizeof(flag)))

Not responding to multicast requests while on link-local network?

On a DHCP network, mdnsd is super reliable however if I only have a link-local address, I see mdnsd do an initial publish on startup. After that point, it never appears to receive any multicast requests (nothing is logged.) As a result, I can resolve the .local name for a couple minutes until the TTL expires from the initial broadcast, then nothing.

My setup: crossover link, direct from device to ethernet port on my laptop. Can ping device from laptop.

Initial startup, everything looks good: (wireshark from my laptop on left, device shell on right.) I started testing c854aac in this example:
screen shot 2018-08-10 at 9 35 45 am

After TTL expires, try again: Queries but no responses. You can see I can still ping the device by IP address from the terminal.
screen shot 2018-08-10 at 9 43 37 am

Another thing I noticed (only on 0dca088) when on link-local: without the -a option, mdnsd seems to have a hard time figuring out the IP address (for binding the listen socket?)

$ mdnsd -i eth0 -n -l info
mdnsd 0.8-dev starting.
mdnsd_out(): Send Publish PTR: Name: _ssh._tcp.local., rdlen: 0, rdata: (null), rdname: foobar._ssh._tcp.local.
mdnsd_out(): Send Publish PTR: Name: _services._dns-sd._udp.local., rdlen: 0, rdata: (null), rdname: _ssh._tcp.local.
mdnsd_out(): Send Publish PTR: Name: _http._tcp.local., rdlen: 0, rdata: (null), rdname: foobar._http._tcp.local.
mdnsd_out(): Send Publish PTR: Name: _services._dns-sd._udp.local., rdlen: 0, rdata: (null), rdname: _http._tcp.local.
_r_out(): Appending name: foobar.local., type 1 to outbound message ...
Failed writing to socket: Network is unreachable
mdnsd 0.8-dev exiting.

If I give the -p option, it restarts and then publishes the records, but then same behavior after TTL expires:

$ mdnsd -i eth0 -n -l info -p
mdnsd 0.8-dev starting.
mdnsd_out(): Send Publish PTR: Name: _ssh._tcp.local., rdlen: 0, rdata: (null), rdname: foobar._ssh._tcp.local.
mdnsd_out(): Send Publish PTR: Name: _services._dns-sd._udp.local., rdlen: 0, rdata: (null), rdname: _ssh._tcp.local.
mdnsd_out(): Send Publish PTR: Name: _http._tcp.local., rdlen: 0, rdata: (null), rdname: foobar._http._tcp.local.
mdnsd_out(): Send Publish PTR: Name: _services._dns-sd._udp.local., rdlen: 0, rdata: (null), rdname: _http._tcp.local.
_r_out(): Appending name: foobar.local., type 1 to outbound message ...
Failed writing to socket: Network is unreachable
mdnsd 0.8-dev starting.
mdnsd_out(): Send Probing: Name: foobar._ssh._tcp.local., Type: 16
mdnsd_out(): Send Probing: Name: foobar._ssh._tcp.local., Type: 33
mdnsd_out(): Send Probing: Name: foobar._http._tcp.local., Type: 16

.....

If I give -a then it doesn't complain about not binding to the socket, but same behavior as before - it doesn't appear to be receiving any requests: Packets 2-10 are initial broadcast, second set are queries from my laptop after TTL expired. No responses and nothing logged on the device:
screen shot 2018-08-10 at 10 01 06 am

On the device:

$ ip a show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq qlen 1000
    link/ether 54:4a:16:bb:00:00 brd ff:ff:ff:ff:ff:ff
    inet 169.254.42.227/16 brd 169.254.255.255 scope link eth0
       valid_lft forever preferred_lft forever
    inet6 2002:4857:5d6d:1:564a:16ff:febb:0/64 scope global dynamic 
       valid_lft 86362sec preferred_lft 86362sec
    inet6 fe80::564a:16ff:febb:0/64 scope link 
       valid_lft forever preferred_lft forever

Getting it set up on a Raspberry Pi

subject

How do I do that? I tried installing it by following the instructions. When I tried running it, I got an error message stating that it couldn't find its library.

Can't "make" in termux android

Hello, i have problem while make in termux. Here step has been done:

./configure --prefix=$PWD/build CC=clang
make all

make  all-recursive
make[1]: Entering directory '/data/data/com.termux/files/home/github/mdnsd-0.11'
Making all in examples
make[2]: Entering directory '/data/data/com.termux/files/home/github/mdnsd-0.11/examples'
make[2]: Nothing to be done for 'all'.
make[2]: Leaving directory '/data/data/com.termux/files/home/github/mdnsd-0.11/examples'
Making all in libmdnsd
make[2]: Entering directory '/data/data/com.termux/files/home/github/mdnsd-0.11/libmdnsd'
  CC       libmdnsd_la-log.lo
log.c:51:18: error: use of undeclared identifier 'prioritynames'
        for (int i = 0; prioritynames[i].c_name; i++) {
                        ^
log.c:52:27: error: use of undeclared identifier 'prioritynames'
                size_t len = MAX(strlen(prioritynames[i].c_name),
                                        ^
log.c:52:27: error: use of undeclared identifier 'prioritynames'
log.c:55:20: error: use of undeclared identifier 'prioritynames'
                if (!strncasecmp(prioritynames[i].c_name, level, len)) {
                                 ^
log.c:56:10: error: use of undeclared identifier 'prioritynames'
                        lvl = prioritynames[i].c_val;
                              ^
log.c:119:18: error: use of undeclared identifier 'INTERNAL_NOPRI'
        if (loglevel == INTERNAL_NOPRI)
                        ^
6 errors generated.
make[2]: *** [Makefile:458: libmdnsd_la-log.lo] Error 1
make[2]: Leaving directory '/data/data/com.termux/files/home/github/mdnsd-0.11/libmdnsd'
make[1]: *** [Makefile:516: all-recursive] Error 1
make[1]: Leaving directory '/data/data/com.termux/files/home/github/mdnsd-0.11'
make: *** [Makefile:380: all] Error 2

I tried clang in ubuntu images via termux it works, after sometimes then I asume that ubuntu has linux environment but clang termux isn't

Termux syslog:

$prefix/include/syslog.h 

Termux Ubuntu syslog:

/usr/include/aarch64-linux-gnu/sys/syslog.h

Buildroot support

It seems that there are some Linux distributions that provide the mdnsd package.

Packaging status

Will there be an official support for Buildroot?

Here is an example:

################################################################################
#
# mdnsd
#
################################################################################

MDNSD_VERSION = 1173d85c288ca6eda187ec2ce1dfe113e005ecdd
MDNSD_SITE = $(call github,troglobit,mdnsd,$(MDNSD_VERSION))
MDNSD_LICENSE = BSD-3-Clause
MDNSD_LICENSE_FILES = LICENSE

MDNSD_AUTORECONF = YES

define MDNSD_REMOVE_EXAMPLES
	$(RM) $(TARGET_DIR)/etc/mdns.d/ssh.service
endef
MDNSD_POST_INSTALL_TARGET_HOOKS += MDNSD_REMOVE_EXAMPLES

$(eval $(autotools-package))

Publishing colliding records

Hey!

I found an issue, when _namehash % SPRIME leads to the same index and the name of records stored at that index differ.

mdnsd_find tries to find matching records by only comparing the type. This function is used by the function record in conf.c. When mdnsd_find finds a record now with matching type (E.g. Type SRV), then it enters the while loop (~conf.c:129) and it will never create a new record using mdnsd_shared or unique, although, we do not want to update an existing entry but rather create a new one.

In my case, I added three services, of which 2 of them had the same index and only one of them was correctly announced. Upon dns-sd query, it was shown but mdnsd was not able to answer when some instance requested the TXT record.

Adding strcmp(data->name, name) == 0 to mdnsd_find as a requirement, fixes the issue. mdnsd_shared takes care of placing it into the linked list at index _namehash(host) % SPRIME.

mdns_record_t *mdnsd_find(mdns_daemon_t *d, const char *name, unsigned short type)
{
	mdns_record_t *r;

	r = mdnsd_get_published(d, name);
	while (r) {
		const mdns_answer_t *data;

		data = mdnsd_record_data(r);
		// Search for a record with the same type and name. Records with different names might be in the same linked list
		// when the hash functions % SPRIME assigns them the same index (hash collision)
		if (data->type == type && strcmp(data->name, name) == 0)
			return r;

		r = mdnsd_record_next(r);
	}

	return NULL;
}

Static analysis reports garbage value in _lmatch

I'm validating mDNS with clang-tidy and fixed a lot of findings already, but there's one that requires more intimate knowledge of the _lmatch function than I have. The reported problem is:

warning: The left operand of '==' is a garbage value [clang-analyzer-core.UndefinedBinaryOperatorResult]

Here's the full checker output:

clang-tidy-9 -header-filter=.* -p=/home/wolfram/fw/sourceSDK/build -quiet -config={"Checks":"*,-android-*,-llvm-include-order,-llvm-header-guard,-readability-else-after-return,-readability-magic-numbers,-readability-inconsistent-declaration-parameter-name,-readability-isolate-declaration,-readability-braces-around-statements,-readability-named-parameter,-cppcoreguidelines-avoid-magic-numbers,-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,-clang-analyzer-security.insecureAPI.strcpy,-clang-analyzer-optin.performance.Padding,-hicpp-signed-bitwise,-hicpp-braces-around-statements,-hicpp-multiway-paths-covered,-hicpp-no-assembler,-google-readability-braces-around-statements,-google-readability-todo,-bugprone-suspicious-string-compare,-cert-msc30-c,-cert-msc50-cpp","CheckOptions":[{"key":"misc-throw-by-value-catch-by-reference.CheckThrowTemporaries","value":"1"}]} /home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:179:10: warning: The left operand of '==' is a garbage value [clang-analyzer-core.UndefinedBinaryOperatorResult]
        if (*l1 == 0 && *l2 == 0)
                ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:465:12: note: Calling '_host'
        short2net(_host(m, &(m->_buf), name) + 6, &mybuf);
                  ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:192:6: note: Assuming 'name' is not equal to null
        if (name == 0)
            ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:192:2: note: Taking false branch
        if (name == 0)
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:196:2: note: Loop condition is true.  Entering loop body
        while (name[y]) {
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:197:7: note: Assuming the condition is false
                if (name[y] == '.') {
                    ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:197:3: note: Taking false branch
                if (name[y] == '.') {
                ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:206:3: note: Taking false branch
                if (x++ == 255)
                ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:196:2: note: Loop condition is false. Execution continues on line 212
        while (name[y]) {
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:213:6: note: 'x' is not equal to 1
        if (x == 1)
            ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:213:2: note: Taking false branch
        if (x == 1)
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:219:2: note: Loop condition is true.  Entering loop body
        for (x = 0; label[x]; x += label[x] + 1) {
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:220:15: note: 'y' is < MAX_NUM_LABELS
                for (y = 0; y < MAX_NUM_LABELS && m->_labels[y]; y++) {
                            ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:220:15: note: Left side of '&&' is true
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:220:3: note: Loop condition is true.  Entering loop body
                for (y = 0; y < MAX_NUM_LABELS && m->_labels[y]; y++) {
                ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:221:8: note: Calling '_lmatch'
                        if (_lmatch(m, label + x, m->_labels[y])) {
                            ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:157:2: note: Taking false branch
        if (*l1 & 0xc0)
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:159:6: note: Assuming the condition is false
        if (*l2 & 0xc0)
            ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:159:2: note: Taking false branch
        if (*l2 & 0xc0)
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:163:6: note: 'l1' is not equal to 'l2'
        if (l1 == l2)
            ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:163:2: note: Taking false branch
        if (l1 == l2)
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:167:6: note: Assuming the condition is false
        if (*l1 != *l2)
            ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:167:2: note: Taking false branch
        if (*l1 != *l2)
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:169:2: note: Loop condition is true.  Entering loop body
        for (len = 1; len <= *l1; len++) {
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:170:7: note: Assuming the condition is false
                if (l1[len] != l2[len])
                    ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:170:3: note: Taking false branch
                if (l1[len] != l2[len])
                ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:169:2: note: Loop condition is false. Execution continues on line 175
        for (len = 1; len <= *l1; len++) {
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:179:6: note: Left side of '&&' is true
        if (*l1 == 0 && *l2 == 0)
            ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:179:18: note: Assuming the condition is false
        if (*l1 == 0 && *l2 == 0)
                        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:179:2: note: Taking false branch
        if (*l1 == 0 && *l2 == 0)
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:183:9: note: Calling '_lmatch'
        return _lmatch(m, l1, l2);
               ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:157:2: note: Taking false branch
        if (*l1 & 0xc0)
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:159:6: note: Assuming the condition is true
        if (*l2 & 0xc0)
            ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:159:2: note: Taking true branch
        if (*l2 & 0xc0)
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:160:10: note: Calling '_lmatch'
                return _lmatch(m, l1, (char *)m->_buf + _ldecomp(l2));
                       ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:157:2: note: Taking false branch
        if (*l1 & 0xc0)
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:159:6: note: Assuming the condition is false
        if (*l2 & 0xc0)
            ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:159:2: note: Taking false branch
        if (*l2 & 0xc0)
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:163:6: note: 'l1' is not equal to 'l2'
        if (l1 == l2)
            ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:163:2: note: Taking false branch
        if (l1 == l2)
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:167:6: note: Assuming the condition is false
        if (*l1 != *l2)
            ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:167:2: note: Taking false branch
        if (*l1 != *l2)
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:169:2: note: Loop condition is false. Execution continues on line 175
        for (len = 1; len <= *l1; len++) {
        ^
/home/wolfram/fw/sourceSDK/core/src/apps/mdns/libmdnsd/1035.c:179:10: note: The left operand of '==' is a garbage value
        if (*l1 == 0 && *l2 == 0)
                ^

Please note that line numbers refer to our copy of 10.35.c which is not necessarily identical to the one on master.

Troubleshoot running single tests

As discussed in #54, running single tests works a bit sketchy at the moment.

  1. Works (all tests):

    make check
    
  2. Works (single test):

    cd test/
    unshare -mrun ./discover.sh
    
  3. Works (single test):

    make check TESTS=addr
    
  4. Does not work:

    make check TESTS=discover.sh
    

autogen.sh fails with "'LIBTOOL' is undefined"

Apologies if I'm doing something obviously wrong, I'm not well versed in native linux development.

# ./autogen.sh 
autoreconf: Entering directory `.'
autoreconf: configure.ac: not using Gettext
autoreconf: running: aclocal --force --warnings=portability -I m4
autoreconf: configure.ac: tracing
autoreconf: configure.ac: not using Libtool
autoreconf: running: /usr/bin/autoconf --force --warnings=portability
autoreconf: running: /usr/bin/autoheader --force --warnings=portability
autoreconf: running: automake --add-missing --force-missing --warnings=portability
libmdnsd/Makefile.am:1: error: Libtool library used but 'LIBTOOL' is undefined
libmdnsd/Makefile.am:1:   The usual way to define 'LIBTOOL' is to add 'LT_INIT'
libmdnsd/Makefile.am:1:   to 'configure.ac' and run 'aclocal' and 'autoconf' again.
libmdnsd/Makefile.am:1:   If 'LT_INIT' is in 'configure.ac', make sure
libmdnsd/Makefile.am:1:   its definition is in aclocal's search path.
autoreconf: automake failed with exit status: 1

# uname -a
Linux 3a10646176c4 4.9.87-linuxkit-aufs #1 SMP Wed Mar 14 15:12:16 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux

Resource record comparison is broken

The _a_match function in libmdnsd/mdnsd.c seems broken. I have a hard time understanding what it is supposed to do, even though it seems simple enough. But I guess it is supposed to return 1 if the input record is identical to the input stored answer, and 0otherwise.

In that case the comparison of A and AAAA records is broken because it will always return 1 for these types of records.

mdnsd/libmdnsd/mdnsd.c

Lines 205 to 206 in 46e13a0

if (r->type == QTYPE_A || !memcmp(&r->known.a.ip, &a->ip, 4))
return 1;

name conflict detection in v0.11 is causing a loop

Edit: updated the title and description because the real issue is not just the typo.

Typo in warning:
conlicting -> conflicting

WARN("%s: conlicting name detected %s for type %d, reloading config ...", iface->ifname, name, type);

Also, I found that mdnsd v0.11 gets into a loop where conflict detection keeps being triggered, presumably because mdnsd is responding to its own query?
Example log snippet:

eth0: conlicting name detected foobar._http._tcp.local. for type 33, reloading config ...
eth0: conlicting name detected foobar.local. for type 1, reloading config ...
eth0: conlicting name detected foobar._http._tcp.local. for type 16, reloading config ...
eth0: conlicting name detected foobar-2._http._tcp.local. for type 33, reloading config ...
eth0: conlicting name detected foobar-2.local. for type 1, reloading config ...
eth0: conlicting name detected foobar-2._http._tcp.local. for type 16, reloading config ...
eth0: conlicting name detected foobar-3._http._tcp.local. for type 33, reloading config ...
eth0: conlicting name detected foobar-3.local. for type 1, reloading config ...
eth0: conlicting name detected foobar-3._http._tcp.local. for type 16, reloading config ...
eth0: conlicting name detected foobar-4._http._tcp.local. for type 33, reloading config ...
eth0: conlicting name detected foobar-4.local. for type 1, reloading config ...
eth0: conlicting name detected foobar-4._http._tcp.local. for type 16, reloading config ...
eth0: conlicting name detected foobar-5._http._tcp.local. for type 33, reloading config ...
eth0: conlicting name detected foobar-5.local. for type 1, reloading config ...
eth0: conlicting name detected foobar-5._http._tcp.local. for type 16, reloading config ...
eth0: conlicting name detected foobar-6._http._tcp.local. for type 33, reloading config ...
eth0: conlicting name detected foobar-6.local. for type 1, reloading config ...
eth0: conlicting name detected foobar-6._http._tcp.local. for type 16, reloading config ...
eth0: conlicting name detected foobar-7._http._tcp.local. for type 33, reloading config ...
eth0: conlicting name detected foobar-7.local. for type 1, reloading config ...
eth0: conlicting name detected foobar-7._http._tcp.local. for type 16, reloading config ...
eth0: conlicting name detected foobar-8._http._tcp.local. for type 33, reloading config ...
eth0: conlicting name detected foobar-8.local. for type 1, reloading config ...
eth0: conlicting name detected foobar-8._http._tcp.local. for type 16, reloading config ...

In this case I was invoking the program as simply mdnsd. I noticed if I called it as mdnsd -i eth0 behavior appears to change.

I also noticed another difference between v0.10 and v0.11. The host running mdnsd has both an autoIP address and a DHCP address. output from ip a:

2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq qlen 1000
    link/ether 6c:ec:eb:a8:1b:e5 brd ff:ff:ff:ff:ff:ff
    inet 169.254.17.246/16 brd 169.254.255.255 scope link eth0
       valid_lft forever preferred_lft forever
    inet 10.0.42.195/23 brd 10.0.43.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::6eec:ebff:fea8:1be5/64 scope link
       valid_lft forever preferred_lft forever

When I query using resolvectl from another host, v0.11 gives the autoIP address:

$ resolvectl query -p mdns foobar.local
foobar.local: 169.254.17.246                 -- link: eno1

-- Information acquired via protocol mDNS/IPv4 in 1.5ms.
-- Data is authenticated: no

When running v0.10 I get the DHCP address:

$ resolvectl query -p mdns foobar.local
foobar.local: 10.0.42.195 -- link: eno1

-- Information acquired via protocol mDNS/IPv4 in 1.5ms.
-- Data is authenticated: no

Add support for running on multiple interfaces

The Apple mDNSResponder creates a socket on all interfaces from getifaddrs(), as long as the interface has the IFF_MULTICAST flag and an IP address. We should do this too since there a many multi-homed applications for which mdnsd may be a great fit.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.