2727import subprocess
2828import pwd
2929import shutil
30+ import time
3031
3132import qubesdb
3233import sys
@@ -342,6 +343,7 @@ def dns_addresses(family=None):
342343
343344 def main (self ):
344345 self .terminate_requested = False
346+ self .reload_requested = False
345347 self .init ()
346348 self .run_firewall_dir ()
347349 if not self .is_custom_persist_enabled ():
@@ -355,29 +357,45 @@ def main(self):
355357 self .handle_addr (source_addr )
356358 self .update_connected_ips (4 )
357359 self .update_connected_ips (6 )
358- try :
359- for watch_path in iter (self .qdb .read_watch , None ):
360- if watch_path == '/connected-ips' :
361- self .update_connected_ips (4 )
360+ while not self .terminate_requested :
361+ if self .reload_requested :
362+ clock_monotonic = time .clock_gettime (time .CLOCK_MONOTONIC )
363+ clock_monotonic = int (clock_monotonic * 1_000_000 )
364+ self .sd_notify (f'RELOADING=1\n MONOTONIC_USEC={ clock_monotonic } ' )
365+ for source_addr in self .list_targets ():
366+ self .handle_addr (source_addr )
367+ self .reload_requested = False
368+ self .sd_notify ('READY=1' )
369+ try :
370+ watch_path = self .qdb .read_watch ()
371+ except OSError : # EINTR
372+ # signal received, re-check loop condition
373+ continue
362374
363- if watch_path == '/connected-ips6' :
364- self . update_connected_ips ( 6 )
375+ if watch_path is None :
376+ break
365377
366- # ignore writing rules itself - wait for final write at
367- # source_addr level empty write (/qubes-firewall/SOURCE_ADDR)
368- if watch_path .startswith ('/qubes-firewall/' ) and watch_path .count ('/' ) == 2 :
369- source_addr = watch_path .split ('/' )[2 ]
370- self .handle_addr (source_addr )
378+ if watch_path == '/connected-ips' :
379+ self .update_connected_ips (4 )
380+
381+ if watch_path == '/connected-ips6' :
382+ self .update_connected_ips (6 )
383+
384+ # ignore writing rules itself - wait for final write at
385+ # source_addr level empty write (/qubes-firewall/SOURCE_ADDR)
386+ if watch_path .startswith ('/qubes-firewall/' ) and watch_path .count ('/' ) == 2 :
387+ source_addr = watch_path .split ('/' )[2 ]
388+ self .handle_addr (source_addr )
371389
372- except OSError : # EINTR
373- # signal received, don't continue the loop
374- pass
375390
376391 self .cleanup ()
377392
378393 def terminate (self ):
379394 self .terminate_requested = True
380395
396+ def reload (self ):
397+ self .reload_requested = True
398+
381399class NftablesWorker (FirewallWorker ):
382400 supported_rule_opts = ['action' , 'proto' , 'dst4' , 'dst6' , 'dsthost' ,
383401 'dstports' , 'specialtarget' , 'icmptype' ]
@@ -662,6 +680,7 @@ def main():
662680 print ('Sorry, iptables no longer supported' , file = sys .stderr )
663681 sys .exit (1 )
664682 signal .signal (signal .SIGTERM , lambda _signal , _stack : worker .terminate ())
683+ signal .signal (signal .SIGHUP , lambda _signal , _stack : worker .reload ())
665684 worker .main ()
666685
667686
0 commit comments