GithubHelp home page GithubHelp logo

multicast-dns's Introduction

multicast-dns

Low level multicast-dns implementation in pure javascript

npm install multicast-dns

build status

Usage

var mdns = require('multicast-dns')()

mdns.on('response', function(response) {
  console.log('got a response packet:', response)
})

mdns.on('query', function(query) {
  console.log('got a query packet:', query)
})

// lets query for an A record for 'brunhilde.local'
mdns.query({
  questions:[{
    name: 'brunhilde.local',
    type: 'A'
  }]
})

Running the above (change brunhilde.local to your-own-hostname.local) will print an echo of the query packet first

got a query packet: { type: 'query',
  questions: [ { name: 'brunhilde.local', type: 'A', class: 1 } ],
  answers: [],
  authorities: [],
  additionals: [] }

And then a response packet

got a response packet: { type: 'response',
  questions: [],
  answers:
   [ { name: 'brunhilde.local',
       type: 'A',
       class: 'IN',
       ttl: 120,
       flush: true,
       data: '192.168.1.5' } ],
  authorities: [],
  additionals:
   [ { name: 'brunhilde.local',
       type: 'A',
       class: 'IN',
       ttl: 120,
       flush: true,
       data: '192.168.1.5' },
     { name: 'brunhilde.local',
       type: 'AAAA',
       class: 'IN',
       ttl: 120,
       flush: true,
       data: 'fe80::5ef9:38ff:fe8c:ceaa' } ] }

CLI

npm install -g multicast-dns
multicast-dns brunhilde.local
> 192.168.1.1

API

A packet has the following format

{
  questions: [{
    name: 'brunhilde.local',
    type: 'A'
  }],
  answers: [{
    name: 'brunhilde.local',
    type: 'A',
    ttl: seconds,
    data: (record type specific data)
  }],
  additionals: [
    (same format as answers)
  ],
  authorities: [
    (same format as answers)
  ]
}

Currently data from SRV, A, PTR, TXT, AAAA and HINFO records is passed

mdns = multicastdns([options])

Creates a new mdns instance. Options can contain the following

{
  multicast: true // use udp multicasting
  interface: '192.168.0.2' // explicitly specify a network interface. defaults to all
  port: 5353, // set the udp port
  ip: '224.0.0.251', // set the udp ip
  ttl: 255, // set the multicast ttl
  loopback: true, // receive your own packets
  reuseAddr: true // set the reuseAddr option when creating the socket (requires node >=0.11.13)
}

mdns.on('query', (packet, rinfo))

Emitted when a query packet is received.

mdns.on('query', function(query) {
  if (query.questions[0] && query.questions[0].name === 'brunhilde.local') {
    mdns.respond(someResponse) // see below
  }
})

mdns.on('response', (packet, rinfo))

Emitted when a response packet is received.

The response might not be a response to a query you send as this is the result of someone multicasting a response.

mdns.query(packet, [cb])

Send a dns query. The callback will be called when the packet was sent.

The following shorthands are equivalent

mdns.query('brunhilde.local', 'A')
mdns.query([{name:'brunhilde.local', type:'A'}])
mdns.query({
  questions: [{name:'brunhilde.local', type:'A'}]
})

mdns.respond(packet, [cb])

Send a dns response. The callback will be called when the packet was sent.

// reply with a SRV and a A record as an answer
mdns.respond({
  answers: [{
    name: 'my-service',
    type: 'SRV',
    data: {
      port: 9999,
      weight: 0,
      priority: 10,
      target: 'my-service.example.com'
    }
  }, {
    name: 'brunhilde.local',
    type: 'A',
    ttl: 300,
    data: '192.168.1.5'
  }]
})

The following shorthands are equivalent

mdns.respond([{name:'brunhilde.local', type:'A', data:'192.158.1.5'}])
mdns.respond({
  answers: [{name:'brunhilde.local', type:'A', data:'192.158.1.5'}]
})

mdns.destroy()

Destroy the mdns instance. Closes the udp socket.

Development

To start hacking on this module you can use this example to get started

git clone git://github.com/mafintosh/multicast-dns.git
npm install
node example.js
node cli.js $(hostname).local

License

MIT

multicast-dns's People

Contributors

amilajack avatar beaugunderson avatar bnielsen1965 avatar daviddias avatar huanvu avatar lukaaash avatar maboiteaspam avatar mafintosh avatar rangermauve avatar richardschneider avatar roguism avatar techniq avatar thosil avatar watson avatar wyckster avatar xat 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  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

multicast-dns's Issues

Error: addMembership ENOBUFS

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)

macOS: Cannot decode name (bad pointer)

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.

Reverse lookups and PTR packages

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.

reuseAddr

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?

Support condensed IPv6 representation.

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?

No responses on Windows

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.

Service advertisement

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?)

Any reason for this not to work if Apple bonjour is installed (W7) ?

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 ?

Detect services on two interfaces?

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?

Server crashing on setMulticastInterface throwing EADDRNOTAVAIL

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

SRV record causes crash

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)

malformed packet

example

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"
    }
  ]
});

It is possible to send a query with question of record type "ANY"?

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?

Can't install mdns package on ububtu 22.04 and nodejs v20.13.0

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

type is always 'query'?

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:

q.type = 'query'

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?

Not detecting responses from IPv6 addresses

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.

Fails to parse larger responses

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)

Can crash with uncaught exception without a gateway

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.)

Try to get some information but they are missed

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

Fails to bind

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.

Add bin to resolve hostnames

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.

Get specific endpoint

Is there any way to get an endpoint for the server? eg. response for '/play' would be different from '/server-info'?

Support TXT data objects

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'
  }
}])

allInterfaces - won't work with nodejs version 18.

in nodejs 18, os.networkInterfaces() now set familly to be either 4 or 6 instead of 'IPv6' || 'IPv4'

image

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)

How to make a new instance of mdns ?

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.

Windows 10 Bash on Windows Error: addMembership EINVAL


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.

On windows listener is not working

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?

Unable to use it with react native !

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

The current version may still have problems when multiple interfaces are present

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:

  1. for bind:
    For UDP sockets, ... If address is not specified, the operating system will attempt to listen on all addresses. Once binding is complete, a 'listening' event is emitted and the optional callback function is called.
  2. for addMembership:
    ... If the multicastInterface argument is not specified, the operating system will choose one interface and will add membership to it. To add membership to every available interface, call addMembership multiple times, once per interface.

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 ...

Should ANY be the default query type?

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 ๐Ÿ˜ƒ

Feature request

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.

Does not work when options.interface is specified

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.

Automatic ipv6 support?

Currently we need to specify ip and interface.

throw new Error('For IPv6 multicast you must specify ip and interface')

But I am not sure why.

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

small typo, if the socket was not yet consumed, socket.destroy throws exception

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)

Running in Docker/Kubernetes

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!

mDNS scan

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

crash when multiple ip on same interface

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.

dgram.createSocket is not a function

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.

Query packets aren't received by other hosts on local network

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:

screen shot 2015-09-13 at 09 42 27

Any pointers on why this doesn't work as I was expecting?

Multicast with VLAN does not see responses

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.

Not broadcasting on all interfaces

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?

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.