Sorry if this has already been asked in some other way, I couldn't find out, and have had pretty terrible experiences trying to figure out how to properly use avahi.

I have avahi working properly, and can use it to detect my wifi enabled Brother scanner. I can figure out its IP address by issuing

avahi-browse -arp|grep -i brother

So I can then modify my sane config file (technically it's the brother config file that sane uses: /etc/opt/brother/scanner/brscan4//brsanenetdevice4.cfg and add the scanner's IP address.

However, if the network goes down, and the scanner is given a new IP address by the router, that means I have to go through this process again. So here I am, thinking, "isn't this the whole point of avahi?? To not have to enter IP addresses?" So I try adding the avahi hostname to the file instead of the IP address:

DEVICE=brother-scanner-avahi , "MFC-avahi" , Unknown , IP-ADDRESS=BRNXXXXXXX.local

instead of

DEVICE=brother-scanner-101 , "MFC-101" , Unknown , IP-ADDRESS= 

But this doesn't work. Well, brsaneconfig4 -p does, because it just hands off the request to ping which can handle the avahi hostname just fine. xsane (0.998) just says:

Failed to open device 'brother4:net1;dev2': Invalid argument

So, my thought is to somehow set some internal static IP to "resolve" to the avahi ip. Is there some way to do this? For example, if I wanted:

to just be an alias for the (dynamic) resolved avahi IP address name of the device. Kind of like the reverse of what the hosts file does. I'm thinking this might involve bind or squid or something else like those, with which I have no experience, so I wouldn't know where to begin.

This is a fedora linux machine.

Edit: I would like to avoid doing this on the router, by the way, as I want to know if this is even possible to achieve this way.

  • You can set up hostname resolution in the form printername.local via avahi, see e.g. here. I haven't done this myself, because I prefer to configure the router to (a) give out always the same IP addresses to well-known device and (b) do the DNS resolution, so I can't give details or debug any particular problems. – dirkt Aug 8 '17 at 12:44
  • @dirkt yes this part already works. What I want to do is to have either xsane accept the avahi name (scanner.local) or find a way to map that avahi name to a static, internal ip that doesn't change, so I can specify that in the config file – insaner Aug 9 '17 at 20:20
  • So either (a) make sure xsane uses the resolver properly (read code and submit a patchif necessary), or (b) make sure the scanner always gets the same IP address (which means configuring the DHCP server in the router). How should "mapping an avahi name to a static IP" even work? – dirkt Aug 9 '17 at 20:39
  • A friend sent me a link to a potential solution, but did not want to write up an answer here. Once I try it out and see whether it works I will post that up. Until then, I await a solution to be posted. – insaner Aug 9 '17 at 21:36

In brsanenetdevice4.cfg you can use a hostname instead of an IP address, but the name of the configuration variable is NODENAME.

For example, modifying your case above you would use:

DEVICE=brother-scanner-avahi , "MFC-avahi" , Unknown , NODENAME=BRNXXXXXXX.local

and it will be resolved using avahi just like when you print.


Ok, on the hint by a friend who pointed out another SU answer to a related question (Using iptables to redirect IP address), and some experimentation and trial and error, I figured it out. Here it is, in case it helps anyone out too:

The trick is to use iptables NAT. First, we choose our (unassigned/available) IP to use as our alias. Something like (something you know the router won't be using). NOTE: do not use the range 127.0.0.x because it will not work!

Then you add that to the sane definition for the scanner. In my case, the file is /etc/opt/brother/scanner/brscan4/brsanenetdevice4.cfg. So I added this line:

DEVICE=brother-scanner-avahi-alias , "MFC-avahi-alias" , Unknown , IP-ADDRESS=

I then created a script containing the following:

BROTHER_SCANNER_IP=`avahi-browse -rpt _ipp._tcp|grep $BROTHER_UNIQ_STR|awk 'BEGIN {FS=";"} /^=/ { print  $8}'`
# $7 is the .local hostname
# avahi-browse -rpt _ipp._tcp|grep $BROTHER_UNIQ_STR|awk 'BEGIN {FS=";"} /^=/ { print $7, $8}'

# to complete this: iptables-save >/somepath/iptables.save Add to cron upon start up iptables-restore </somepath/iptables.save

echo Brother scanner IP: \'$BROTHER_SCANNER_IP\'
if [[ $BROTHER_SCANNER_IP =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
    # enable IP forwarding in kernel:
    sysctl net.ipv4.ip_forward=1
    # To make it permanent, edit /etc/sysctl.conf and ensure that the line "net.ipv4.ip_forward = 1" is there and not commented out.

    iptables -t nat -A OUTPUT -d $ALIAS_IP -j DNAT --to-destination $BROTHER_SCANNER_IP

    # Print the OUTPUT rules after our changes:
    # iptables -t nat -L
    iptables -t nat -L OUTPUT

    # If you really mess up, or want to get rid of all your rules (careful with this command!!)
    # TO DELETE ALL RULES ("F"lush) run: iptables -t nat -F OUTPUT
    echo "ERROR: bad ip address"
    exit 1

Run that script, and now sane should be able to detect your scanner via the alias IP address. You can then add the script to a cron job, or a boot script (autostart, or whatever your system uses), and that will take care of things for you every time.

The script must be run as super user (root) or sudo.

Hope that helps someone out there.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.