In pfe_filter.c there is a call to DIOCXCOMMIT ioctl to commit pf rules 
generated by relayd but in pfe_filter.c:551 there is only a warning about the 
transaction failing.
If transaction_commit fails with EBUSY relayd thinks that the pf rules has been 
committed but they are not;
at this moment relayd is desyncronized.
With this patch we try to recommit pf rules another time if DIOCXCOMMIT fails 
with EBUSY, otherwise we fatalx.
I think that it is better to exit the process instead of having a relayd 
process desynchronized.
 Opininions ? Better ideas on how to workaround this problem ?
  Cheers
   Giovanni
Index: pfe_filter.c
===================================================================
RCS file: /cvs/src/usr.sbin/relayd/pfe_filter.c,v
retrieving revision 1.52
diff -u -p -r1.52 pfe_filter.c
--- pfe_filter.c	19 Oct 2012 16:49:50 -0000	1.52
+++ pfe_filter.c	18 Mar 2013 08:06:42 -0000
@@ -354,9 +354,22 @@ transaction_init(struct relayd *env, con
 int
 transaction_commit(struct relayd *env)
 {
+int timer = 0;
+
 	if (ioctl(env->sc_pf->dev, DIOCXCOMMIT,
-	    &env->sc_pf->pft) == -1)
-		return (-1);
+	    &env->sc_pf->pft) == -1) {
+		/*
+		 * if DIOCXCOMMIT fails with EBUSY retry after some milliseconds
+		 */
+		if(errno == EBUSY) {
+			timer = arc4random_uniform(10000);
+			usleep(timer);
+			if (ioctl(env->sc_pf->dev, DIOCXCOMMIT,
+	    		&env->sc_pf->pft) == -1)
+				return (-1);
+		}
+		return (0);
+	}
 
 	return (0);
 }
@@ -509,7 +522,7 @@ sync_ruleset(struct relayd *env, struct 
 		log_debug("%s: rule added to anchor \"%s\"", __func__, anchor);
 	}
 	if (transaction_commit(env) == -1)
-		log_warn("%s: add rules transaction failed", __func__);
+		fatalx("add rules transaction failed");
 	return;
 
  toolong:

Reply via email to