mafintosh / multicast-dns Goto Github PK
View Code? Open in Web Editor NEWLow level multicast-dns implementation in pure javascript
License: MIT License
Low level multicast-dns implementation in pure javascript
License: MIT License
When there are multiple IPs defined on the same interface, multicast-dns crash with this error:
events.js:160
throw er; // Unhandled 'error' event
^
Error: addMembership EADDRINUSE
at exports._errnoException (util.js:1020:11)
at Socket.addMembership (dgram.js:506:11)
at Socket.<anonymous> (/home/tsi/projects/multicast-dns/index.js:57:18)
at emitNone (events.js:91:20)
at Socket.emit (events.js:185:7)
at startListening (dgram.js:121:10)
at _handle.lookup (dgram.js:226:7)
at _combinedTickCallback (internal/process/next_tick.js:83:11)
at process._tickCallback (internal/process/next_tick.js:104:9)
npm ERR! Test failed. See above for more details.
It appears with version 6.2.0.
Problem is that socket.addMembership() could only be done once per interface
And the function allInterfaces() return all IPs regardless of the interface they belongs to.
I'll provide shortly a PR.
Lets say I know the ip of brunhilde.local
and want to know its host name (i.e. brunhilde.local
!). So I build up my query like this:
mdns.query({questions:[{name:'26.178.168.192.in-addr.arpa.',type:'PTR'}]});
What I can see when I monitor the network using Wireshark is that the mDNS query is malformed and type
and class
are missing:
26.178.168.192.in-addr.arpa: type Unused, class Unknown (3072), "QM" question
A valid query (e.g. generated using dig -p 5353 @224.0.0.251 -x 192.168.178.26
) would be as the following:
26.178.168.192.in-addr.arpa: type PTR, class IN, "QM" question
unfortunately I didn't have enough time to get deep into the code to see if I'm doing something wrong (or undesired) or is it a valid bug. Any help is appreciated.
Hi,
I'm wondering if you might have some examples of how to use this library inside Docker/Kubernetes environment? I running into issues when trying to set it up in such an environment.
I tried running the container with such parameters:
index.js
const mdnsService = require('multicast-dns')
const port = process.env.PORT || 53
const server = mdnsService({
port
})
server.on('query', function (query) {
console.log('DNS Query:', query.questions)
})
console.log(`Box up & running on port ${port}.`);
['SIGHUP', 'SIGINT', 'SIGQUIT', 'SIGILL', 'SIGTRAP', 'SIGABRT',
'SIGBUS', 'SIGFPE', 'SIGUSR1', 'SIGSEGV', 'SIGUSR2', 'SIGTERM'
].forEach(function (sig) {
process.on(sig, function () {
console.log('Box is shutting down.')
server.destroy()
})
})
Dockerfile
FROM node:current-alpine3.13
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
# update and install dependency
RUN apk update && apk upgrade
RUN apk add git
# copy the app, note .dockerignore
COPY package*.json /usr/src/app/
RUN npm install
COPY . /usr/src/app/
CMD [ "node", "index.js" ]
Commands to build & run the container:
docker build -t multicast-dns .
docker run -it -e PORT=53 -p 53:53/udp -p 53:53/tcp multicast-dns
Command to test the app:
dig @127.0.0.1 +tries=1 +time=1 some.domain.name.com
The above command works fine when I run this app via node index.js
and I can see the log statement for the DNS query. But when I run it in docker, it looks like my diq requests are not coming through.
Thanks in advance for your help!
Hello,
I am wondering if this is the normal behavior not to catch any error that might be thrown from call to setMulticastInterface
socket.setMulticastInterface(opts.interface || defaultInterface())
As specified in dgram's documentation, a call to setMulticastInterface might throw a System Error such as EADDRNOTAVAIL or EPROTONOSUP
https://nodejs.org/api/dgram.html#dgram_call_results
For now i didn't find a way to properly catch this exception in my program other than using process.on('uncaugthException') which i find ugly
Am I missing something or is it the only way ?
Ty for your time
https://github.com/mafintosh/multicast-dns/blob/master/package.json#L11
update to version 5.2.2 or higher.
I find it very helpful on machines without multicast dns support (i.e Windows or Linux without Avahi installed) to use your library to resolve hostnames. Currently I have a simple script to do this (as mdns-resolve
):
#!/usr/bin/env node
var mdns = require('multicast-dns')();
if (process.argv.length < 3) {
console.log('Hostname required');
process.exit(1);
}
var hostname = process.argv[2];
mdns.on('response', function(response) {
response.answers.forEach(function(answer) {
if (answer.name === hostname) {
console.log(answer.data);
process.exit();
}
});
});
mdns.query(hostname, 'A');
// Give responses 3 seconds to respond
setTimeout(function() {
console.log('Hostname not found');
process.exit();
}, 3000);
I was debating on creating a separate NPM package that uses this library, but I thought it might be worthwhile to add it here instead. That way if someone installs using npm install -g multicast-dns
the cli/bin
script would be available. I wanted your feedback on this before I decided which route to go (PR to add the feature here or create a separate NPM package).
I also wasn't sure how rich of a cli should be exposed (should just A
records be looked up, or allow specifying others, etc. I didn't want to add any dependencies like yargs
for this unless the extra capabilities seemed worthwhile. I was also between names for the program: mdns-resolve
, mdns-lookup
, mdns-query
, or just expose multicast-dns
as the name to match the library.
Firstly, I apologise that this is a really basic question. I have two machines on the same network. On machine 1 I have this script, which just listens for all queries:
var mdns = require('multicast-dns')()
mdns.on('query', function (query) {
console.log('got a query packet:', query)
});
On the other machine I have this script, which makes a query every second:
var mdns = require('multicast-dns')()
mdns.on('response', function(response) {
console.log('got a response packet:', response)
})
setInterval(function () {
mdns.query({
questions:[{
name: 'myservice.local',
type: 'A'
}]
})
}, 1000);
I was expecting the query from machine 2 to be received at machine 1 but there's no output at all from machine 1. I can see the DNS packets being sent from machine 2 in Wireshark:
Any pointers on why this doesn't work as I was expecting?
Is there any way to get an endpoint for the server? eg. response for '/play'
would be different from '/server-info'
?
When responding with a TXT
record this module currently expects the data
property to be a string, e.g:
mdns.respond([{
name: 'foo',
type: 'TXT',
data: 'cn=0,1,2,3...'
}])
How about allowing it to be an object just as with the SRV
record?
mdns.respond([{
name: 'foo',
type: 'TXT',
data: {
cn: '0,1,2,3',
model: 'AppleTV3,2'
}
}])
Repost from watson/bonjour#44 as I think the issue is a better fit here.
I'm trying to detect an IKEA TRADFRI gateway using bonjour without any success. When inspecting the traffic with Wireshark, I do see a response from that gateway but it seems to be the only one using IPv6 addresses. As a result it doesn't show up in the detected services.
Here's the dissected packet from Wireshark:
Frame 5023: 769 bytes on wire (6152 bits), 769 bytes captured (6152 bits) on interface 0
Ethernet II, Src: MurataMa_25:7a:41 (b0:72:bf:25:7a:41), Dst: IPv6mcast_fb (33:33:00:00:00:fb)
Internet Protocol Version 6, Src: 2003:e6:c3f6:f311:b272:bfff:fe25:7a41, Dst: ff02::fb
User Datagram Protocol, Src Port: 5353, Dst Port: 5353
Multicast Domain Name System (response)
Transaction ID: 0x0000
Flags: 0x8400 Standard query response, No error
Questions: 0
Answer RRs: 8
Authority RRs: 0
Additional RRs: 2
Answers
_services._dns-sd._udp.local: type PTR, class IN, _coap._udp.local
_coap._udp.local: type PTR, class IN, gw-b072bf257a41._coap._udp.local
gw-b072bf257a41._coap._udp.local: type TXT, class IN, cache flush
gw-b072bf257a41._coap._udp.local: type SRV, class IN, cache flush, priority 0, weight 0, port 5684, target TRADFRI-Gateway-b072bf257a41.local
_services._dns-sd._udp.local: type PTR, class IN, _hap._tcp.local
_hap._tcp.local: type PTR, class IN, TRADFRI gateway._hap._tcp.local
TRADFRI gateway._hap._tcp.local: type TXT, class IN, cache flush
TRADFRI gateway._hap._tcp.local: type SRV, class IN, cache flush, priority 0, weight 0, port 80, target TRADFRI-Gateway-b072bf257a41.local
Additional records
TRADFRI-Gateway-b072bf257a41.local: type A, class IN, cache flush, addr 192.168.2.102
TRADFRI-Gateway-b072bf257a41.local: type AAAA, class IN, cache flush, addr fe80::b272:bfff:fe25:7a41
I believe the issue comes from the server socket only listening on IPv4. Since the gateway only sends messages to the IPv6 address, they'll get lost. It should be possible to listen to both addresses, using code similar to this:
var d = require("dgram");
var s = d.createSocket({type:"udp4",reuseAddr:true});
s.bind(9000);
var s6 = d.createSocket({type:"udp6",reuseAddr:true});
s6.bind(9000);
I'll be happy to prepare a PR if that's something you want to support.
I am getting this error on Mac:
Error: Cannot decode name (bad pointer)
at name.decode (โฆ/node_modules/dns-packet/index.js:83:15)
at rnsec.decode (โฆ/node_modules/dns-packet/index.js:1147:28)
at answer.decode (โฆ/node_modules/dns-packet/index.js:1451:18)
at decodeList (โฆ/node_modules/dns-packet/index.js:1625:19)
at exports.decode (โฆ/node_modules/dns-packet/index.js:1566:12)
at Socket.<anonymous> (โฆ/node_modules/multicast-dns/index.js:40:24)
at Socket.emit (node:events:513:28)
at UDP.onMessage [as onmessage] (node:dgram:930:8)```
This is the packet in hex:
000084000000000600000000045f686170045f746370056c6f63616c00000c000100001194001411496e646f6f7243616d20324b2d30413143c00c09496e646f6f7263616dc016002f8001000000780005c0a5000140c027002f8001000011940009c02700050000800040c03b00018001000000780004c0a801f3c0270021800100000078000800000000b6f8c03bc0270010800100001194004c0463233d310466663d321469643d34413a34413a33373a37383a34443a3030086d643d54383430300670763d312e310573233d31340473663d300563693d31370b73683d4a6b6e5466773d3d
The service that is advertised in the broken package just works fine on Linux.
hello, maybe someone can help me to deal with this issue...
i want to discover a amazon fire device. the dns search on the shell (on mac) works very well with this command
dns-sd -B _amzn-wplay._tcp local
This comand response with an instance name like this "amzn.dmgr:649079E36FF650C95604A3397843E704:QZT4YaSve2:325301"
the next call receive the device info
dns-sd -L "amzn.dmgr:649079E36FF650C95604A3397843E704:QZT4YaSve2:325301" _amzn-wplay
and response with
... can be reached at 192-168-5-103.local.:53725 ...
so how can i archive the same result with multicast dns ?
currently i just use the basic sample script with my custom name
mdns.query({ questions:[{ name: '_amzn-wplay._tcp.local', type: 'A' }] })
he will find the device but no addition information are given
got a response packet: { id: 0, type: 'response', flags: 1024, questions: [], answers: [ { name: '192-168-5-103.local', type: 'A', class: 1, ttl: 3600, flush: true, data: '192.168.5.103' } ], authorities: [], additionals: [] }
any ideas ? thanks a lot
I'm trying to create an app to listen for "query" and "response" from the network. With mdns.query()
call in addition it works fine but without the function call it does not work.
It used to work but somehow now it stops.
What could be the reason?
found this while doing some research, thought it was worth referencing somewhere
https://tools.ietf.org/html/rfc6762
Currently we need to specify ip
and interface
.
throw new Error('For IPv6 multicast you must specify
ip
andinterface
')
But I am not sure why.
ff0x::fb
, the equivalent of 224.0.0.251
, can be used as default address.::/0
, the equivalent of 0.0.0.0
, can be used as default external interface.::1
, the equivalent of 127.0.0.1
, can be used as default internal interface.Couldn't extend those defaults for Ipv6 be used to enable IPv6 without a special interface definition?
Note: I just read that for ipv6, the interface needs to be a zone which could be assigned by using the interfaces name: ::%network_name
(reference: https://stackoverflow.com/questions/38448369/ipv6-multicast-with-node-js)
cc. @konobi
When runing comand npm i mdns
(or npm ci
when node is added to package.js) getting error
rutkauskaser@MED-RUTKAUSKASE:~/Desktop/dpv/server/telemedicine/backend$ npm i
npm warn deprecated [email protected]: Please see https://github.com/lydell/urix#deprecated
npm warn deprecated [email protected]: See https://github.com/lydell/source-map-url#deprecated
npm warn deprecated [email protected]: See https://github.com/lydell/source-map-resolve#deprecated
npm warn deprecated [email protected]: TSLint has been deprecated in favor of ESLint. Please see palantir/tslint#4534 for more information.
npm warn deprecated [email protected]: https://github.com/lydell/resolve-url#deprecated
npm error code 1
npm error path /home/rutkauskaser/Desktop/dpv/server/telemedicine/backend/node_modules/mdns
npm error command failed
npm error command sh -c node-gyp rebuild
npm error make: Entering directory '/home/rutkauskaser/Desktop/dpv/server/telemedicine/backend/node_modules/mdns/build'
npm error CXX(target) Release/obj.target/dns_sd_bindings/src/dns_sd.o
npm error make: Leaving directory '/home/rutkauskaser/Desktop/dpv/server/telemedicine/backend/node_modules/mdns/build'
npm error gyp info it worked if it ends with ok
npm error gyp info using [email protected]
npm error gyp info using [email protected] | linux | x64
npm error gyp info find Python using Python version 3.10.12 found at "/usr/bin/python3"
npm error gyp info spawn /usr/bin/python3
npm error gyp info spawn args [
npm error gyp info spawn args '/home/rutkauskaser/Desktop/dpv/server/telemedicine/backend/node_modules/node-gyp/gyp/gyp_main.py',
npm error gyp info spawn args 'binding.gyp',
npm error gyp info spawn args '-f',
npm error gyp info spawn args 'make',
npm error gyp info spawn args '-I',
npm error gyp info spawn args '/home/rutkauskaser/Desktop/dpv/server/telemedicine/backend/node_modules/mdns/build/config.gypi',
npm error gyp info spawn args '-I',
npm error gyp info spawn args '/home/rutkauskaser/Desktop/dpv/server/telemedicine/backend/node_modules/node-gyp/addon.gypi',
npm error gyp info spawn args '-I',
npm error gyp info spawn args '/home/rutkauskaser/.cache/node-gyp/20.13.0/include/node/common.gypi',
npm error gyp info spawn args '-Dlibrary=shared_library',
npm error gyp info spawn args '-Dvisibility=default',
npm error gyp info spawn args '-Dnode_root_dir=/home/rutkauskaser/.cache/node-gyp/20.13.0',
npm error gyp info spawn args '-Dnode_gyp_dir=/home/rutkauskaser/Desktop/dpv/server/telemedicine/backend/node_modules/node-gyp',
npm error gyp info spawn args '-Dnode_lib_file=/home/rutkauskaser/.cache/node-gyp/20.13.0/<(target_arch)/node.lib',
npm error gyp info spawn args '-Dmodule_root_dir=/home/rutkauskaser/Desktop/dpv/server/telemedicine/backend/node_modules/mdns',
npm error gyp info spawn args '-Dnode_engine=v8',
npm error gyp info spawn args '--depth=.',
npm error gyp info spawn args '--no-parallel',
npm error gyp info spawn args '--generator-output',
npm error gyp info spawn args 'build',
npm error gyp info spawn args '-Goutput_dir=.'
npm error gyp info spawn args ]
npm error gyp info spawn make
npm error gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
npm error cc1plus: error: /usr/local/include/x86_64-linux-gnu: Permission denied
npm error make: *** [dns_sd_bindings.target.mk:176: Release/obj.target/dns_sd_bindings/src/dns_sd.o] Error 1
npm error gyp ERR! build error
npm error gyp ERR! stack Error: make
failed with exit code: 2
npm error gyp ERR! stack at ChildProcess.onExit (/home/rutkauskaser/Desktop/dpv/server/telemedicine/backend/node_modules/node-gyp/lib/build.js:194:23)
npm error gyp ERR! stack at ChildProcess.emit (node:events:519:28)
npm error gyp ERR! stack at ChildProcess._handle.onexit (node:internal/child_process:294:12)
npm error gyp ERR! System Linux 6.5.0-35-generic
npm error gyp ERR! command "/home/rutkauskaser/.nvm/versions/node/v20.13.0/bin/node" "/home/rutkauskaser/Desktop/dpv/server/telemedicine/backend/node_modules/.bin/node-gyp" "rebuild"
npm error gyp ERR! cwd /home/rutkauskaser/Desktop/dpv/server/telemedicine/backend/node_modules/mdns
npm error gyp ERR! node -v v20.13.0
npm error gyp ERR! node-gyp -v v8.4.1
npm error gyp ERR! not ok
npm error A complete log of this run can be found in: /home/rutkauskaser/.npm/_logs/2024-05-23T14_20_14_199Z-debug-0.log
About my local setup environment:
OS: Ubuntu 22.04
Node: v20.13.0
NPM: 10.7.0
On node v0.11.13 and above dgram.createSocket has a new option reuseAddr
which is set to false by default (on prior versions it was true). This leads to the same problem like descriped here mdns-js/node-mdns-js#31
The problem could be solved with code like this:
if (semver.gte(process.versions.node, '0.11.13')) {
socket = dgram.createSocket({type:'udp4', reuseAddr:true})
} else {
socket = dgram.createSocket('udp4')
}
or like that:
if (typeof opts.reuseAddr !== 'undefined') {
socket = dgram.createSocket({type:'udp4', reuseAddr:opts.reuseAddr})
} else {
socket = dgram.createSocket('udp4')
}
Do you want a PR for one of those?
This project currently assumes IPv6 addresses are of the format a:b:c:d:e:f:g:h
, incorrectly en/decoding condensed addresses with ::
. Personally, I'd prefer letting another package handle the logic of address parsing, assuming you're okay with the added dependency?
Today A
is the default query type, e.g. mdns.query('foo')
is equivalent to mdns.query('foo', 'A')
. Wouldn't it make more sense that ANY
was the default?
I'll happily make a PR if this is the case ๐
Is it possible to create a mdns advertisement similarly to how node_mdns does, or is this simply a higher abstraction for something like mdns.on('query', function(query) { ... })
that replies to specific questions of a type (SRV
?)
Error: addMembership ENODEV
at new errnoException (dgram.js:457:11)
at Socket.addMembership (dgram.js:399:11)
at Socket. (/home/blubb/node_modules/multicast-dns/index.js:46:16)
Occurs if I use the module without router / gateway. (Which isn't that problem, but the error is uncatchable. If you put the addMembership / socket part in a try / catch block and emit the error, it works fine.)
Thank you for bumping dns-packet
in #74 for version 7.
Could you also release a security bump for version 6? This currently affects webpack-dev-server
via a different (no longer maintained) library, that still makes use of multicast-dns
version 6
:
https://github.com/watson/bonjour/blob/bdc467a4f3c7b9fe8bc54468b6fc4d80b8f1c098/package.json#L11
More details can be found at webpack/webpack-dev-server#3340.
I think something in the documentation may be incorrect. In creating a new mdns instance this is one of the option choices:
interface: '192.168.0.2' // explicitly specify a network interface. defaults to all
We were finding that we were only seeing it available on one interface. Looking at index.js:
socket.addMembership(ip, opts.interface)
According to documentation on dgram (the socket), addMembership defaults to a single interface (chosen by the operating system), and if multiple interfaces are desired addMembership should be called multiple times, once per interface. What do you think about taking an array of addresses and calling addMembership on each?
Hello,
first i have tried this library and it works as expected in node environment but when I used this library in react native (android) project its response is not proper no query & response is coming .And yes i have imported all node core modules in my project using this method(https://github.com/parshap/node-libs-react-native) . please help i am new to react native and I want IP of my mDNS device
So I was looking through the code to see why none of the queries get send out correctly. I was following the example quite literally and using Wireshark I could see that the packages were not valid mdns queries.
Then I came across this line of code:
Line 110 in 52bf467
Maybe I'm not fully understanding the code. But doesn't this line override the given type to query
instead of A
or PTR
or whatever is being passed?
I played a little with multicast-dns, but when i start/stop my bonjour service (mDnsresponder.exe) , it seems that no service/devices can be discovered (until i reboot my computer / shutdown bonjour).
Yet, reusseaddr is properly set on the socket. Is there any reason you could think of, for Apple bonjour Service to mess with multicast-dns ?
I've seend that mdnsreponder bind 5353 UDP on all network interfaces i'v got (and not on 0.0.0.0) -when you bind only 0.0.0.0, maybe some kind of priority rule ?
Using this via mdns-proxy.
Binding appears inconsistent sometimes in that a call to on.('query', {}) appears to run straight through and exits. Same result even when an interface (ipv4) is specified.
this is a packet that should have 4 answers (SRV, TXT, PTR, PTR) plus some additionals (some AAAAs and some As)
it works without the additionals (maybe the AAAAs hose it?)
this is blocking switching mdns-swarm to this library :)
here's a packet that explodes if you get a chance to dig in before i do:
mdns.respond({
"answers": [
{
"name": "ferdinand._simple-swarm._tcp.local",
"type": "SRV",
"data": {
"target": "ferdinand.local",
"port": 58510
}
},
{
"name": "ferdinand._simple-swarm._tcp.local",
"type": "TXT",
"data": "host=ci96qkft60000v5rc5h0awour"
},
{
"name": "_simple-swarm._tcp.local",
"type": "PTR",
"data": "ferdinand._simple-swarm._tcp.local"
},
{
"name": "_services._dns-sd._udp.local",
"type": "PTR",
"data": "_simple-swarm._tcp.local"
}
],
"additionals": [
{
"name": "ferdinand.local",
"type": "AAAA",
"data": "2604:4080:1110:8250:baf6:b1ff:fe15:4885"
},
{
"name": "ferdinand.local",
"type": "AAAA",
"data": "2604:4080:1110:8250:18fc:7342:4ed4:24e2"
},
{
"name": "ferdinand.local",
"type": "AAAA",
"data": "fd4c:d904:6dc2:bffd:d0a4:4cb4:f4fb:36a1"
},
{
"name": "ferdinand.local",
"type": "A",
"data": "192.168.1.39"
},
{
"name": "ferdinand.local",
"type": "A",
"data": "172.16.230.1"
},
{
"name": "ferdinand.local",
"type": "A",
"data": "172.16.59.1"
}
]
});
This error has started in the last 2 weeks on one particular machine and I'm not sure why. I have seen it in dat-next and dat-next-next.. the excerpts below are from trying to do a simple clone. I used the same key on a different machine and both worked fine, so it's an issue with the environment not the key.
Some info on the machine that I see the problem occurring on:
lsb_release -a
No LSB modules are available.
Distributor ID: Debian
Description: Debian GNU/Linux 8.7 (jessie)
Release: 8.7
Codename: jessie
uname -mrs
Linux 4.10.13-feral x86_64
npm list -g dat-next
โโโ [email protected]
npm list -g dat-next-next
โโโ [email protected]
error with dat-next
dat-next <key> <dir>
Starting Dat program...
events.js:160
throw er; // Unhandled 'error' event
^
Error: addMembership ENOBUFS
at exports._errnoException (util.js:1022:11)
at Socket.addMembership (dgram.js:508:11)
at Socket.<anonymous> (/path/to/node_modules/dat-next/node_modules/multicast-dns/index.js:53:16)
at emitNone (events.js:91:20)
at Socket.emit (events.js:185:7)
at startListening (dgram.js:121:10)
at dgram.js:228:7
at _combinedTickCallback (internal/process/next_tick.js:77:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
and with dat-next-next
dat-next-next <key>
Syncing dat ...
Key is: <key>
Downloading at 0 B/s, Uploading at 0 B (0 peers)
events.js:160
throw er; // Unhandled 'error' event
lo 1 ff02::1
bond0 1 ff02::1
Key is: <key>
Downloading at 0 B/s, Uploading at 0 B (0 peers)
events.js:160
throw er; // Unhandled 'error' event
^
Error: addMembership ENOBUFS
at exports._errnoException (util.js:1022:11)
at Socket.addMembership (dgram.js:508:11)
at Socket.<anonymous> (/path/to/node_modules/dat-next-next/node_modules/multicast-dns/index.js:53:16)
at emitNone (events.js:91:20)
at Socket.emit (events.js:185:7)
at startListening (dgram.js:121:10)
at dgram.js:228:7
at _combinedTickCallback (internal/process/next_tick.js:77:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
The last couple of months I've been testing multicast-dns on a Raspberry Pi. Unfortunately though, it does not correctly seem to capture the responses.
Our configuration is as follows. The wired_eth0
is the main interface, and the lan@wired_eth0
is a tagged VLAN on the main interface.
# ip a
2: wired_eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether b8:27:eb:2d:f6:c1 brd ff:ff:ff:ff:ff:ff
inet 192.168.10.101/24 brd 192.168.10.255 scope global dynamic wired_eth0
valid_lft 2035sec preferred_lft 2035sec
4: lan@wired_eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether b8:27:eb:2d:f6:c1 brd ff:ff:ff:ff:ff:ff
inet 10.90.90.1/24 brd 10.90.90.255 scope global lan
valid_lft forever preferred_lft forever
inet6 fe80::ba27:ebff:fe2d:f6c1/64 scope link
valid_lft forever preferred_lft forever
Now when I setup a very simple script with interface
set to 10.90.90.1
, it does seem to send out the queries correctly - but it does not see the response. Sample options:
this.discovery = mdns({
interface: '10.90.90.1'
});
Following a tcpdump where the response is not seen.
# tcpdump -i wired_eth0 -e -vvv multicast and not broadcast
tcpdump: listening on wired_eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
18:27:19.470121 b8:27:eb:2d:f6:c1 (oui Unknown) > 01:00:5e:00:00:fb (oui Unknown), ethertype 802.1Q (0x8100), length 89: vlan 10, p 0, ethertype IPv4, (tos 0x0, ttl 255, id 38349, offset 0, flags [DF], proto UDP (17), length 71)
10.90.90.1.mdns > 224.0.0.251.mdns: [udp sum ok] 0 PTR (QM)? _mielesemiprof._tcp.local. (43)
18:27:19.470593 00:1d:63:43:be:fd (oui Unknown) > 01:00:5e:00:00:fb (oui Unknown), ethertype 802.1Q (0x8100), length 329: vlan 10, p 0, ethertype IPv4, (tos 0x0, ttl 255, id 1849, offset 0, flags [DF], proto UDP (17), length 311)
10.90.90.240.mdns > 224.0.0.251.mdns: [udp sum ok] 0*- [0q] 4/0/2 _mielesemiprof._tcp.local. [10m] PTR Miele PWM907._mielesemiprof._tcp.local., Miele PWM907._mielesemiprof._tcp.local. [10m] SRV Miele-001D63FFFE43BEFC.local.:443 0 0, Miele-001D63FFFE43BEFC.local. (Cache flush) [10m] A 10.90.90.240, Miele PWM907._mielesemiprof._tcp.local. (Cache flush) [10m] TXT "txtvers=1" "group=" "path=/" "security=1" "pairing=false" "devicetype=3" "con=2" "subtype=0" "s=0" ar: Miele PWM907._mielesemiprof._tcp.local. (Cache flush) [10m] NSEC, Miele-001D63FFFE43BEFC.local. (Cache flush) [10m] NSEC (283)
After a lot of debugging, I found out the following: if I change this line to something like:
socket.setMulticastInterface(opts.multicastInterface || opts.interface || defaultInterface())
and then pass the following options to the mdns instance:
this.discovery = mdns({
multicastInterface: '10.90.90.1'
});
It works flawless. The responses come in just fine now. The tcpdump now looks exactly the same as when it did not work.
The main question is: is there any other way to fix this without changing anything in the multicast-dns library, and if not - would this be an accepted PR? I don't know why this works, as I don't understand it that good.
Hello,
After I run mdns.destroy();
I would like to re-run the mdns after a button click event.
Author advises me to make a new instance.
But I do as README said.
mdns = multicastdns();
But it gets error
Uncaught ReferenceError: multicastdns is not defined
Thank for helping.
This test returns a large(ish) query response and it fails:
test('Large responses', function (dns, t) {
dns.once('query', function (packet) {
dns.respond([
{
'name': '_p2p._udp.local',
'type': 'PTR',
'class': 'IN',
'ttl': 120,
'data': '9ylx0fzon1twp35eu8a4l0jl2il46phj432r83l8lzi98kppee5x9n4k8nu8cci._p2p._udp.local'
},
{
'name': '9ylx0fzon1twp35eu8a4l0jl2il46phj432r83l8lzi98kppee5x9n4k8nu8cci._p2p._udp.local',
'type': 'TXT',
'class': 'IN',
'ttl': 120,
'data': 'dnsaddr=/ip4/127.0.0.1/tcp/51845/p2p/12D3KooWDr7hckmrxYszeZ6JowJ3pJK5LfExPuaWbocxTfM1au6a'
},
{
'name': '9ylx0fzon1twp35eu8a4l0jl2il46phj432r83l8lzi98kppee5x9n4k8nu8cci._p2p._udp.local',
'type': 'TXT',
'class': 'IN',
'ttl': 120,
'data': 'dnsaddr=/ip4/192.168.1.251/tcp/51845/p2p/12D3KooWDr7hckmrxYszeZ6JowJ3pJK5LfExPuaWbocxTfM1au6a'
},
{
'name': '9ylx0fzon1twp35eu8a4l0jl2il46phj432r83l8lzi98kppee5x9n4k8nu8cci._p2p._udp.local',
'type': 'TXT',
'class': 'IN',
'ttl': 120,
'data': 'dnsaddr=/ip4/147.75.87.27/tcp/4001/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb/p2p-circuit/p2p/12D3KooWDr7hckmrxYszeZ6JowJ3pJK5LfExPuaWbocxTfM1au6a'
},
{
'name': '9ylx0fzon1twp35eu8a4l0jl2il46phj432r83l8lzi98kppee5x9n4k8nu8cci._p2p._udp.local',
'type': 'TXT',
'class': 'IN',
'ttl': 120,
'data': 'dnsaddr=/ip4/147.75.87.27/udp/4001/quic/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb/p2p-circuit/p2p/12D3KooWDr7hckmrxYszeZ6JowJ3pJK5LfExPuaWbocxTfM1au6a'
},
{
'name': '9ylx0fzon1twp35eu8a4l0jl2il46phj432r83l8lzi98kppee5x9n4k8nu8cci._p2p._udp.local',
'type': 'TXT',
'class': 'IN',
'ttl': 120,
'data': 'dnsaddr=/ip4/147.75.87.27/udp/4001/quic-v1/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb/p2p-circuit/p2p/12D3KooWDr7hckmrxYszeZ6JowJ3pJK5LfExPuaWbocxTfM1au6a'
},
{
'name': '9ylx0fzon1twp35eu8a4l0jl2il46phj432r83l8lzi98kppee5x9n4k8nu8cci._p2p._udp.local',
'type': 'TXT',
'class': 'IN',
'ttl': 120,
'data': 'dnsaddr=/ip4/147.75.87.27/udp/4001/quic-v1/webtransport/certhash/uEiAeYwv8lXhTZqCmK5a5TksTil8ioZv_MMlAhx6iY7RVAA/certhash/uEiD-mObH5TisfL1p392GcBqckf1B2PA8SjUxtIZk3ACxdg/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb/p2p-circuit/p2p/12D3KooWDr7hckmrxYszeZ6JowJ3pJK5LfExPuaWbocxTfM1au6a'
},
{
'name': '9ylx0fzon1twp35eu8a4l0jl2il46phj432r83l8lzi98kppee5x9n4k8nu8cci._p2p._udp.local',
'type': 'TXT',
'class': 'IN',
'ttl': 120,
'data': 'dnsaddr=/ip6/2604:1380:4602:5c00::3/tcp/4001/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb/p2p-circuit/p2p/12D3KooWDr7hckmrxYszeZ6JowJ3pJK5LfExPuaWbocxTfM1au6a'
},
{
'name': '9ylx0fzon1twp35eu8a4l0jl2il46phj432r83l8lzi98kppee5x9n4k8nu8cci._p2p._udp.local',
'type': 'TXT',
'class': 'IN',
'ttl': 120,
'data': 'dnsaddr=/ip6/2604:1380:4602:5c00::3/udp/4001/quic/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb/p2p-circuit/p2p/12D3KooWDr7hckmrxYszeZ6JowJ3pJK5LfExPuaWbocxTfM1au6a'
},
{
'name': '9ylx0fzon1twp35eu8a4l0jl2il46phj432r83l8lzi98kppee5x9n4k8nu8cci._p2p._udp.local',
'type': 'TXT',
'class': 'IN',
'ttl': 120,
'data': 'dnsaddr=/ip6/2604:1380:4602:5c00::3/udp/4001/quic-v1/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb/p2p-circuit/p2p/12D3KooWDr7hckmrxYszeZ6JowJ3pJK5LfExPuaWbocxTfM1au6a'
},
{
'name': '9ylx0fzon1twp35eu8a4l0jl2il46phj432r83l8lzi98kppee5x9n4k8nu8cci._p2p._udp.local',
'type': 'TXT',
'class': 'IN',
'ttl': 120,
'data': 'dnsaddr=/ip6/2604:1380:4602:5c00::3/udp/4001/quic-v1/webtransport/certhash/uEiAeYwv8lXhTZqCmK5a5TksTil8ioZv_MMlAhx6iY7RVAA/certhash/uEiD-mObH5TisfL1p392GcBqckf1B2PA8SjUxtIZk3ACxdg/p2p/QmbLHAnMoJPWSCR5Zhtx6BHJX9KiKNN6tpvbUcqanj75Nb/p2p-circuit/p2p/12D3KooWDr7hckmrxYszeZ6JowJ3pJK5LfExPuaWbocxTfM1au6a'
}
])
})
dns.once('response', function (packet) {
t.ok(packet.flag_aa, 'should be set')
dns.destroy(function () {
t.end()
})
})
dns.query('foo', 'A')
})
The buffer sent here is 2790 bytes which is well under the maximum of ~64k but it fails to be decoded with a buffer overflow from dns-packet
:
not ok 36 Error: Buffer overflow
---
operator: error
expected: |-
undefined
actual: |-
[Error: Buffer overflow]
at: EventEmitter.<anonymous> (/Users/alex/Documents/Workspaces/mafintosh/multicast-dns/test.js:28:13)
stack: |-
Error: Buffer overflow buf.byteLenth 2790 remaining 33 len 115
at rtxt.decode (/Users/alex/Documents/Workspaces/mafintosh/multicast-dns/node_modules/dns-packet/index.js:372:13)
at answer.decode (/Users/alex/Documents/Workspaces/mafintosh/multicast-dns/node_modules/dns-packet/index.js:1583:18)
at decodeList (/Users/alex/Documents/Workspaces/mafintosh/multicast-dns/node_modules/dns-packet/index.js:1757:19)
at exports.decode (/Users/alex/Documents/Workspaces/mafintosh/multicast-dns/node_modules/dns-packet/index.js:1698:12)
at Socket.<anonymous> (/Users/alex/Documents/Workspaces/mafintosh/multicast-dns/index.js:40:24)
at Socket.emit (node:events:513:28)
at UDP.onMessage [as onmessage] (node:dgram:933:8)
in nodejs 18, os.networkInterfaces() now set familly to be either 4 or 6 instead of 'IPv6' || 'IPv4'
As a consequence allInterfaces() method is failing.
function allInterfaces () {
var networks = os.networkInterfaces()
var names = Object.keys(networks)
var res = []
for (var i = 0; i < names.length; i++) {
var net = networks[names[i]]
for (var j = 0; j < net.length; j++) {
var iface = net[j]
if (iface.family === 'IPv4') {
res.push(iface.address)
// could only addMembership once per interface (https://nodejs.org/api/dgram.html#dgram_socket_addmembership_multicastaddress_multicastinterface)
break
}
}
}
return res
}
We need to replace
if (iface.family === 'IPv4')
with
if (iface.family === 'IPv4' || iface.family === 4)
When options.interface is specified:
require("multicast-dns")({interface:"192.168.1.1"})
it didn't work (no error, just no services found) while in the very same system omitting the options worked. The system actually has only one interface 192.168.1.1.
Hello, I'm using this module for a project and I don't really know how the MDNS protocol works.
I haven't found a way to do this, but I think it's part of the MDNS specification.
The question type comes from the "dns-packet" node module, intended for the DNS protocol, but at this point I think the specifications of both modules are different. In this case we can create another type for the type field of a question.
And is there another known difference between DNS and MDNS that can create similar issues?
Hi,
I'm using multicast-dns along with bonjour in an Electron app (built with electron-builder).
While on OS X it works like a charm, on Windows machines I see my initial query, but I don't receive any response (the firewall is disabled). On some of these machines, if I launch the Bonjour Browser utility before my app, then the app will subsequently display responses.
Please note that the Windows machines I've tested are VirtualBox VMs and have multiple interfaces (the first NAT, the second bridged - the latter being the one that should receive the responses). Using wireshark I can see the incoming mdns traffic on port 5353 with destination 224.0.0.251.
Is there something I'm patently overlooking, or something I could try?
Thanks in advance.
I'm using Windows 10 and I would like to detect services on an Ethernet interface and wireless interface. I have an audio device that can be connected directly to my computer or can be connected to a wireless router. However, I have problems when the npcap loopback adapter is enabled. So I would like to avoid attempting to find services on that. Is there a way to use the interface option to detect on two interfaces?
events.js:163
throw er; // Unhandled 'error' event
^
Error: addMembership EINVAL
at exports._errnoException (util.js:1050:11)
at Socket.addMembership (dgram.js:502:11)
at Socket.<anonymous> (/mnt/e/test/node_modules/multicast-dns/index.js:53:16)
at emitNone (events.js:91:20)
at Socket.emit (events.js:188:7)
at startListening (dgram.js:117:10)
at _handle.lookup (dgram.js:222:7)
at _combinedTickCallback (internal/process/next_tick.js:83:11)
at process._tickCallback (internal/process/next_tick.js:104:9)
webpack/webpack-dev-server#955 looks kind of similar but that's for webpack-dev-server.js
which I am not using.
There are cases in which a host has multiple interfaces (e.g., the host is a host for virtual machines, etc.). However the bind
and addMembership
API has different semantics according the to manual:
bind
:addMembership
:Therefore, due to this semantics mismatch, maybe the current listening
handler:
socket.on('listening', function () {
if (!port) port = me.port = socket.address().port
if (opts.multicast !== false) {
try {
socket.addMembership(ip, opts.interface);
} catch (err) {
that.emit('error', err)
}
socket.setMulticastTTL(opts.ttl || 255)
socket.setMulticastLoopback(opts.loopback !== false)
}
})
Should be changed into something like:
socket.on('listening', function () {
if (!port) port = me.port = socket.address().port
if (opts.multicast !== false) {
try {
if (opts.interfaces) {
opts.interfaces.forEach(mi => {
socket.addMembership(ip, mi);
});
} else {
socket.addMembership(ip, opts.interface)
}
} catch (err) {
that.emit('error', err)
}
socket.setMulticastTTL(opts.ttl || 255)
socket.setMulticastLoopback(opts.loopback !== false)
}
})
where opts.interfaces
can be used to specify a list of interfaces that the current instance wish to listen to and keep the opts.interface
null (or undefined) when multiple interfaces are to be handled ?
(see also #41)
My suggestion haven't been tested in an active project, but it will be in a few days ...
Hi,
there s a small typo in the destroy method.
If the socket has not yet send any message,
it is not yet open,
thus, if destroy is invoked,
it throws an exception such
dgram.js:461
throw new Error('Not running'); // error message from dgram_legacy.js
^
Error: Not running
at Socket._healthCheck (dgram.js:461:11)
at Socket.close (dgram.js:354:8)
at EventEmitter.that.destroy (/home/mh-cbon/projects/bonjour-over-http/node_modules/multicast-dns/index.js:106:12)
at Bonjour.destroy (/home/mh-cbon/projects/bonjour-over-http/node_modules/bonjour/index.js:38:21)
at Object.destroy (/home/mh-cbon/projects/bonjour-over-http/index.js:133:15)
at process.tearDown (/home/mh-cbon/projects/bonjour-over-http/bin.js:117:15)
at emitOne (events.js:77:13)
at process.emit (events.js:169:7)
I added support for SRV records to the mdns-proxy (which multicast-dns supports), but results in a crash with this error:
resolved: _kerberos._udp.NETWORK.LOCAL [SRV] [ { name: '_kerberos._udp.NETWORK.LOCAL',
type: 'SRV',
ttl: 1800,
data:
{ name: 'domctrlr.network.local',
port: 88,
priority: 0,
weight: 100 } } ]
C:\Users\mhansen\AppData\Roaming\npm\node_modules\mdns-proxy\node_modules\multicast-dns\packets.js:33
var list = n.split('.')
^
TypeError: Cannot read property 'split' of undefined
at Object.name.encode (C:\Users\mhansen\AppData\Roaming\npm\node_modules\mdns-proxy\node_modules\multicast-dns\packets.js:33:15)
at Object.rsrv.encode (C:\Users\mhansen\AppData\Roaming\npm\node_modules\mdns-proxy\node_modules\multicast-dns\packets.js:203:8)
at Object.answer.encode (C:\Users\mhansen\AppData\Roaming\npm\node_modules\mdns-proxy\node_modules\multicast-dns\packets.js:329:7)
at encodeList (C:\Users\mhansen\AppData\Roaming\npm\node_modules\mdns-proxy\node_modules\multicast-dns\packets.js:381:9)
at Object.exports.encode (C:\Users\mhansen\AppData\Roaming\npm\node_modules\mdns-proxy\node_modules\multicast-dns\packets.js:410:12)
at C:\Users\mhansen\AppData\Roaming\npm\node_modules\mdns-proxy\node_modules\multicast-dns\index.js:62:29
at apply (C:\Users\mhansen\AppData\Roaming\npm\node_modules\mdns-proxy\node_modules\thunky\index.js:16:28)
at C:\Users\mhansen\AppData\Roaming\npm\node_modules\mdns-proxy\node_modules\thunky\index.js:27:3
at EventEmitter.that.send (C:\Users\mhansen\AppData\Roaming\npm\node_modules\mdns-proxy\node_modules\multicast-dns\index.js:60:5)
at EventEmitter.that.response.that.respond (C:\Users\mhansen\AppData\Roaming\npm\node_modules\mdns-proxy\node_modules\multicast-dns\index.js:73:10)
I seem to be missing something, not sure if this is a bug or a documentation error.
I am running a React Typescript project and want to do a simple query.
My code is as follows
import makeMdns, { Options } from "multicast-dns";
const options: Options = {
loopback: false,
}
const mdns = makeMdns(options);
mdns.on('response', function(response) {
console.log('got a response packet:', response)
})
mdns.on('query', function(query) {
console.log('got a query packet:', query)
})
mdns.query('bob');
When the page renders, I immediately get the error TypeError: dgram.createSocket is not a function
push../node_modules/multicast-dns/index.js.module.exports
D:/Dev/pixelcade/node_modules/multicast-dns/index.js:25
22 | throw new Error('For IPv6 multicast you must specify `ip` and `interface`')
23 | }
24 |
> 25 | var socket = opts.socket || dgram.createSocket({
| ^ 26 | type: type,
27 | reuseAddr: opts.reuseAddr !== false,
28 | toString: function () {
I can verify that dgram is not installed in my node_modules, and adding it manually doesn't seem to work either.
As a side note; I am on windows and using YARN rather than NPM.
Hello,
After I run mdns.destroy();
I would like to re-run the mdns after a button click event.
How to re-run the mdns flow ?
Thank for helping.
Hello,
I have been trying to wrap my head around this since it seems like it should be something very simple.
I am basically trying to find a way to scan the network and find any mDNS client available. No matter what the name is of the client.
What I believe DNS-SD would do in a way as well. I cannot find something that provides any name format that would work as a wild card.
My goal would be to have something similar to the Bonjour browser program that can scan a network and find the client devices along with their IP
I feel like multicast-dns is very close to what I would need, I just don't know how to make it work like this.
Thank you
For a monitoring project, I need to get the source address from the ip packet.
However, I can not find this in the queries and answers object.
So, my suggestion is, if possible, to add source address and maybe even TTL to the object.
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.