Shared printer Avahi service problem.

Welcome to the forum everyone.

I ran into a problem that unfortunately I can't solve, even though I'm already trying everything.
I looked through the forums but couldn't find a solution.
A FreeBSD 13.2 system operating as a NAS, including printer and scanner sharing.
The network is heterogeneous. (Linux, iPhone, etc.).

The printer and scanner service runs in jail, with a VNET and bridge solution.
For iPhones and Macs, the Airprint service provides access using CUPS, DBUS and avahi, which works perfectly, but only if I start avahi manually.

If I start from /etc/rc.conf avahi starts, but does not advertise the machines on the network.
A service avahi-daemon restart command immediately solves the problem and the printer and scanner services work perfectly.

The settings are:
Code:
### /etc/jail.conf

exec.clean;
exec.start = "/bin/sh /etc/rc";
exec.stop = "/bin/sh /etc/rc.shutdown";
allow.raw_sockets;
allow.mount;
allow.mount.tmpfs;
allow.mount.devfs;
allow.mount.nullfs;
allow.mount.fdescfs;
allow.mount.fusefs;
allow.mount.procfs;
allow.mount.zfs;
mount.devfs;
mount.fdescfs;
mount.procfs;
allow.reserved_ports;
allow.chflags;
devfs_ruleset = "100";
enforce_statfs = "0";
allow.sysvipc;
sysvmsg =  "new";
sysvsem = "new";
sysvshm = "new";

vnet;
$domain = "fnas.home";
host.hostname = "${name}.${domain}";

samba {
    path = "/jail/$name";
    vnet.interface = "epair20b";
    exec.prestart  += "ifconfig epair20 create up";
    exec.prestart  += "ifconfig bridge0 addm epair20a";
    exec.start     += "ifconfig epair20b inet 172.16.0.20/16 up";
    exec.start     += "route add default 172.16.0.1";
    exec.poststop   = "ifconfig epair20b -vnet samba";
    exec.poststop   = "ifconfig bridge0 deletem epair20a";
    exec.poststop  += "sleep 2";
    exec.poststop   = "ifconfig epair20a destroy";
    exec.consolelog = "/var/log/jail/jail_${name}.log";
    mount.fstab    += "/etc/jail.conf.d/fstab.${name}";
    persist;
}
Code:
# usbconfig
ugen1.2: <HP Deskjet 1510 series> at usbus1, cfg=0 md=HOST spd=HIGH (480Mbps) pwr=ON (2mA)

Code:
# ps ax
PID TT  STAT    TIME COMMAND
1332  -  IsJ  0:00,05 /usr/local/bin/dbus-daemon --system
1348  -  SJ   0:00,17 avahi-daemon: running [samba.local] (avahi-daemon)
1351  -  IsJ  0:00,07 /usr/local/sbin/cupsd -C /usr/local/etc/cups/cupsd.conf -s /usr/local/etc/cups/cups-files.conf
Code:
## /etc/rc.conf
dbus_enable="YES"
avahi_daemon_enable="YES"
cupsd_enable="YES"
saned_enable="YES"

With the basic startup, the printer and scanner are not found for the network clients, but if I restart the avahi daemon manually, everything is fine.
You can solve it with your own script, but I would be interested in why it doesn't work by default.
Thank you very much if someone answers.
Best regards.
 

Attachments

  • airprint.png
    airprint.png
    60.9 KB · Views: 71
I know about Zeroconf, which includes Avahi, but I haven't been able to understand it enough to make any of them work.

it could be because there's a few Avahi components with different functions, and a different one needs to be turned on instead.

Maybe, Thread cups.89283 may be of help. They set up CUPS with Avahi.
 
I speak from a place of total ignorance. Is the network connection still unavailable when Avahi is started?
 
Honestly I don't know. I think that if you configure the network in jail.conf by exec.start maybe avahi start too early. I've try to configure mdnsresponder instead of avahi and it works even if the network is set with exec.start
 
In my experience avahi doesn't work unless the interface is up when avahi starts, and your interface stays up during the run of avahi. Your jail config appends your interface config to exec.start after you run etc/rc, which means avahi will start before your interface is prepared. avahi also has a setting (use-iff-running) which might may or may not help your situation (though probably not since you are using an epair).

What you could do is configure your interface as part of exec.created, which is run before exec.start and after the jail is created (see jail 8), or (as Eresia suggested) you could configure your interface as normal in your jail rc.conf file and let netif bring it up.

I also noticed in your jail config that you sometimes append and sometimes overwrite (for example, your poststop commands overwrite each other since they are not all +=), not sure if you were doing this intentionally or not but I thought I would point it out.
 
In my experience avahi doesn't work unless the interface is up when avahi starts, and your interface stays up during the run of avahi. Your jail config appends your interface config to exec.start after you run etc/rc, which means avahi will start before your interface is prepared. avahi also has a setting (use-iff-running) which might may or may not help your situation (though probably not since you are using an epair).

What you could do is configure your interface as part of exec.created, which is run before exec.start and after the jail is created (see jail 8), or (as Eresia suggested) you could configure your interface as normal in your jail rc.conf file and let netif bring it up.

I also noticed in your jail config that you sometimes append and sometimes overwrite (for example, your poststop commands overwrite each other since they are not all +=), not sure if you were doing this intentionally or not but I thought I would point it out.
thank you very much for your answer.
Yes, the jail.conf was wrong, but that's not the problem.
I read on many forums and unfortunately there is a problem with Avahi everywhere.
Even if it starts, after a few minutes (3-5) you have to restart the service, because it does not advertise the shares on the network.
I've tried everything, but I ended up writing a small script that restarts the avah daemon every 3 minutes.
I created an avahi-relod rc file for it and registered it in rc.conf.
This is how sharing runs and works in the background.
Not elegant, I know, but useful.
Thank you very much for your help and tips.
I fixed the conf file (poststop +=).
 
Why not restart the service once after 5 minutes instead of periodically?
On the other hand, think about sharing your script for the benefit of others. It's work done for a known issue.
 
Why not restart the service once after 5 minutes instead of periodically?
On the other hand, think about sharing your script for the benefit of others. It's work done for a known issue.
This is how I solved it:
I create an "avahi_reload" file in /etc/rc.d.
This will control the script, which will restart the avahi daemon.
It is specified that it will only run after the jails are started. (rcorder).
Options:
start, stop, restart, status.

/etc/rc.d/avahi_reload
Code:
#!/bin/sh

# PROVIDE: avahi_reload
# REQUIRE: DAEMON jail
# KEYWORD: FreeBSD
#
# Avahi's mDNSResponder, a Zeroconf (Bonjour) service reloader for jails.
#
# avahi_reload_enable="YES"
#

. /etc/rc.subr

name=avahi_reload
desc="Avahi's mDNSResponder, a Zeroconf (Bonjour) service reloader."
rcvar=avahi_reload_enable

start_cmd="${name}_start"
stop_cmd="${name}_stop"
restart_cmd="${name}_restart"
status_cmd="${name}_status"

load_rc_config $name
: ${avahi_reload_enable:=no}

avahi_reload_start() {
    if ! pgrep -f avahi-reload >/dev/null
     then /usr/local/bin/avahi-reload start >/dev/null &
          _checkretval="$?"
          if [ "$_checkretval" = "0" ]
             then echo "Starting avahi-reload."
          fi
     else _avahipid="$(pgrep -f avahi-reload)"
          echo "The avahi-reload is already running as pid ""$_avahipid""."
          echo "To restart, use the << service ahavi_reload restart >> command."
  fi
}

avahi_reload_stop() {
  if pgrep -f avahi-reload >/dev/null
     then /usr/local/bin/avahi-reload stop
          avahi_pid="$(pgrep -f /usr/local/bin/avahi-reload)"
          child_pid="$(pgrep -P "$avahi_pid")"
          kill -9 "$avahi_pid" >/dev/null
          kill -9 "$child_pid" >/dev/null
          echo "Stopping avahi-reload."
     else echo "The avahi-reload is not running."
  fi
}

avahi_reload_restart() {
  if ! pgrep -f avahi-reload >/dev/null
     then echo "The avahi-reload is not running."
          /usr/local/bin/avahi-reload start >/dev/null &
          _checkretval="$?"
          if [ "$_checkretval" = "0" ]
             then echo "Starting avahi-reload."
          fi
     else /usr/local/bin/avahi-reload stop
          avahi_pid="$(pgrep -f /usr/local/bin/avahi-reload)"
          child_pid="$(pgrep -P "$avahi_pid")"
          kill -9 "$avahi_pid" >/dev/null
          kill -9 "$child_pid" >/dev/null
          echo "Stopping avahi-reload."
          /usr/local/bin/avahi-reload start >/dev/null &
          _checkretval="$?"
          if [ "$_checkretval" = "0" ]
             then echo "Restarting avahi-reload."
          fi
  fi
}

avahi_reload_status() {
   if pgrep -f avahi-reload > /dev/null
      then avahipid="$(pgrep -f avahi-reload)"
           echo "The avahi-reload is running as ""$avahipid"" pid."
      else echo "The avahi-reload not running."
   fi
}

load_rc_config $name
: ${avahi_reload_enable:=no}

run_rc_command "$1"

I set it to start by default:

Code:
% sysrc avahi_reload_enable="YES"

Then I create a script in the /usr/local/bin directory called "avahi-reload".
You can set the name of the jail where avahi runs, the time after which the avahi-daemon restarts. (I set it to 3 minutes).
The program also logs to the /var/log directory.

/usr/local/bin/avahi-reload:
Code:
#!/bin/sh

# Avahi's mDNSResponder, a Zeroconf (Bonjour) reloader, for jails.

set_time="120"
wait_time="5"
jail_name="samba"
avahi_log="/var/log/avahi_reload.log"
num="0"

avahi_daemon_start() {
      jexec "$jail_name" \
      /usr/local/sbin/avahi-daemon -D
}

avahi_daemon_stop() {
      jexec "$jail_name" \
      /usr/local/sbin/avahi-daemon -k
}

check_run() {
if [ "$checkretval" = "0" ]
   then echo "$(date) -> avahi-daemon restart..." >> "$avahi_log"
        sleep "$set_time"
   else echo "$(date) -> avahi-daemon error..." >> "$avahi_log"
        echo "$(date) -> i will try again "$(( 3 - num ))" more times." >> "$avahi_log"
        numplus="$(( num + 1 ))"
        num="$numplus"
        sleep "$wait_time"
fi
}

start_cmd() {
while true
   do if [ "$num" -lt "3" ]
         then if pgrep avahi-daemon >/dev/null
                 then avahi_daemon_stop && avahi_daemon_start
                      checkretval="$?"
                      check_run
                 else avahi_daemon_start
                      checkretval="$?"
                      check_run
              fi
         else echo "$(date) -> avahi-daemon error... $num attempts." >> "$avahi_log"
              exit 1
      fi
 done
}

stop_cmd() {
if pgrep avahi-daemon >/dev/null
   then avahi_daemon_stop
        echo "$(date) -> avahi-daemon has stopped..." >> "$avahi_log"
   else echo "$(date) -> avahi daemon is not running..." >> "$avahi_log"
fi
}

restart_cmd() {
stop_cmd && start_cmd
}

if [ -f "$avahi_log" ]
   then logcount="$(sed -n '$=' $avahi_log)"
        if [ "$logcount" -gt "400" ]
           then rm -r "$avahi_log" 1>/dev/null 2>&1
        fi
fi

  if [ ! "$1" ]
     then echo "$(date) -> missing argumentum...error!!!" | tee -a "$avahi_log"
          exit 1
elif [ "$#" -gt "1" ]
     then echo "$(date) -> more than one argument...error!!!" | tee -a "$avahi_log"
          exit 1
  fi

case $1 in
     start ) start_cmd
        ;;
      stop ) stop_cmd
        ;;
   restart ) restart_cmd
        ;;
         * ) echo "$(date) -> bad argument...error!!!" | tee -a "$avahi_log"
             echo "$(date) -> available arguments: < start | stop | restart >." | tee -a "$avahi_log"
             exit 1
        ;;
esac

exit 0

Then i start it:
Code:
% service avahi_reload start
Starting avahi-reload.

Both files run on the host system and log there.
 
Back
Top