How can I lookup host name from snap core using avahi (mDNS)?

I’m not really sure of the interfaces of snap… maybe I should read the doc through. I will try to make a simple ping snap package. Thanks for advice.

Now I create a snap ‘my-ping’ to learn how can I lookup the host name from the snap package using avahi. It contains ping, avahi-resolve and avahi-browse to check the functionality.

My snapcfaft.yaml is here:

name: my-ping
version: '0.1'
summary: My ping snap
description: |
  ping snap package.

grade: devel
confinement: devmode

parts:
  ping:
    plugin: nil
    stage-packages:
      - coreutils
      - avahi-daemon
      - avahi-utils
    stage:
      - bin
      - lib
      - usr
      - etc
    prime:
      - bin
      - lib
      - usr
      - etc
      
apps:
  ping:
    command: ping
    plugs: [network, network-bind, network-observe, avahi-observe]
  avahi-resolve:
    command: avahi-resolve
    plugs: [network, network-bind, network-observe, avahi-observe]
  avahi-browse:
    command: avahi-browse
    plugs: [network, network-bind, network-observe, avahi-observe]

After install it, I tried

$ my-ping.avahi-resolve -n carbon.local
Failed to create client object: Daemon not running

It’s reasonable, we have to connect my-ping:avahi-observe to avahi:avahi-observe.

$ snap connect my-ping:avahi-observe avahi
$ snap interfaces my-ping
Slot                 Plug
avahi:avahi-observe  my-ping
:network             avahi,my-ping,snapweb,tork-ros-roomblock
:network-bind        avahi,my-ping,snapweb,tork-ros-roomblock
-                    my-ping:network-observe

However, I still have a problem, the command never returns.

$ my-ping.avahi-resolve -n carbon.local
(Never come back until Ctrl-C)

The /var/log/syslog saids:

Feb  5 12:38:42 lidarkick avahi.avahi-daemon[7692]: dbus-protocol.c: interface=org.freedesktop.Avahi.Server, path=/, member=GetAPIVersion
Feb  5 12:38:42 lidarkick avahi.avahi-daemon[7692]: dbus-protocol.c: interface=org.freedesktop.Avahi.Server, path=/, member=GetState
Feb  5 12:38:42 lidarkick avahi.avahi-daemon[7692]: dbus-protocol.c: interface=org.freedesktop.Avahi.Server, path=/, member=HostNameResolverNew
Feb  5 12:38:42 lidarkick kernel: [ 4511.723096] audit: type=1107 audit(1517801922.269:746): pid=1113 uid=100 auid=4294967295 ses=4294967295 msg='apparmor="DENIED" operation="dbus_signal"  bus="system" path="/Client5/HostNameResolver1" interface="org.freedesktop.Avahi.HostNameResolver" member="Found" mask="send" name=":1.28" pid=7692 label="snap.avahi.avahi-daemon" peer_pid=12085 peer_label="snap.my-ping.avahi-resolve"
Feb  5 12:38:42 lidarkick kernel: [ 4511.723096]  exe="/usr/bin/dbus-daemon" sauid=100 hostname=? addr=? terminal=?'

It may complains about Dbus, but I have no idea to solve this. How can I setup my package to resolve the host name using avahi package?

Thanks,

perhaps @ondra has an idea here ?

@7675t I just tested with simple avahi client snap and you are right, there is problem with avahi interface. I will see if I can find time to prepare PR for it.
In the mean time file bug against snapd here https://bugs.launchpad.net/snappy/+filebug

@ondra - if it would help, if you can give me all the denials, I can roll this in into the next batch of policy updates for 2.32.

Thanks @ondra and @ogra

I filed this in your link. https://bugs.launchpad.net/snappy/+bug/1747794
Thank you for maintaining your quite useful apps.

@jdstrand I just run tests with following fix: https://github.com/kubiko/snapd/tree/fix-avahi-observe
This seems to fix the problem.
All denials are about slot provider (avahi daemon) not being able to send given dbus messages. Looks like peer_name is not provided but required by the profile, so it blocks sending
I created test ‘avahi-client’ snap to test this case (once lp builds it it should be added to the store)

1 Like

@7675t this has been now merged in and it should be in next milestone
thanks for reporting this!

Thank you for your quick support, impressive!

Fix is now available in edge channel
$ snap refresh core --edge
You can use my test client:
$ snap install avahi-client
connect interfaces
$ avahi-client.browse -a

Thanks, it works perfectly. (I mean, avahi part of my problem)

Now I wonder how I can run ping command from the snap package using avahi,
but it may be a separated question.

you can run ping directly, all you need is to add network-observe plug for your application, then you will have permissions to call ping

I can run ping by IP address, but how can I run ping by host name distributed by avahi? like:

$ my-ping.ping 192.168.0.18
PING 192.168.0.18 (192.168.0.18) 56(84) bytes of data.
64 bytes from 192.168.0.18: icmp_seq=1 ttl=64 time=11.9 ms

$ my-ping.avahi-resolve -n remote.local
remote.local	192.168.0.18

$ my-ping.ping remote.local
ping: unknown host remote.local

If I could edit /etc/nsswitch.conf, it seems to be easy to add mdns entry, but I can’t edit that file.
So glibc gethostbyname() would only look into /etc/hosts and DNS then it fails.

I may be misunderstanding something… I appreciate any kind of advice. Thanks!

Hi @7675t

Sorry for silence, I wan enjoying holidays without internet :slight_smile:
Anyway I have checked and made some changes to my example snaps. And we are very close to make this use case also work.
So install latest avahi and avahi-client from --edge channel and connect all needed interfaces.
$ snap connect avahi-client:avahi-control avahi; snap connect avahi-client:avahi-observe avahi; snap connect avahi-client:network-observe core
For your testing you will need to, for the moment, bind mount one file
$ sudo mount -o bind /snap/avahi-client/current/nsswitch.conf /etc/nsswitch.conf

Now you should be able to run:
$ sudo avahi-client.ping <something.local>

To get this working properly you need to follow landing of this feature: layouts-re-mapping-snap-directories

Once this lands you will be able to add to your snapcraft.yaml

layouts:
    /etc/nsswitch.conf:
        bind-file: $SNAP/nsswitch.conf

this will create impression for file overlay only inside the snap context without affecting rest of the system, without need to run that manual bind mount

Please note that this should be singular, ie layout:.

@jdstrand aha this could explain why I had trouble testing it. Thanks bunch for pointing this out!

Also thanks for quick manual review!
All is now working :smiley:

1 Like

@7675t so all is ready now to test. Thanks to @jdstrand pointing out my mistake in layout definition I was able to get it working on edge channel without any additional hack.
Ignore my previous post with bind mount, simply install my example avahi-client snap and you should be able to test ping on local domain

$ snap install avahi --edge
$ snap install avahi-snap --edge
$ snap set avahi host-name=core
$ snap connect avahi-client:avahi-observe avahi; snap connect avahi-client:avahi-control avahi; snap connect avahi-client:network-observe core
$ sudo avahi-client.ping core.local

Mind layout is fresh feature so snapcraft build does not support it yet and you will need to modify manually prime/meta/snap.yaml once you run build and add there:

layout:
  /etc/nsswitch.conf:`
    bind-file: $SNAP/nsswitch.conf`

I think you need the core snap from edge too.

1 Like

Correct, this is only supported from edge core
$ snap refresh core --edge

Thanks @ondra and @jdstrand . We all need a holiday, a very long holiday…

And layout feature is cool, it is the one I wanted to know.
I confirmed your example worked with my RasPi3. Awesome!
Now I’m quite sure I can setup my snap to use avahi name service.

Thank you so much your effort.