Index: src/iface.c
===================================================================
RCS file: /cvsroot/mpd/mpd/src/iface.c,v
retrieving revision 1.228
retrieving revision 1.230
diff -u -p -r1.228 -r1.230
--- src/iface.c	17 May 2017 08:47:53 -0000	1.228
+++ src/iface.c	1 Jul 2017 21:32:07 -0000	1.230
@@ -141,6 +141,7 @@
   static int	IfaceAllocACL (struct acl_pool ***ap, int start, char * ifname, int number);
   static int	IfaceFindACL (struct acl_pool *ap, char * ifname, int number);
   static char *	IfaceParseACL (char * src, IfaceState iface);
+  static char *	IfaceFixAclForDelete(char *r, char *buf, size_t len);
 #endif
 
   static int	IfaceSetName(Bund b, const char * ifname);
@@ -602,18 +603,18 @@ IfaceUp(Bund b, int ready)
   while (acls != NULL) {
     /* allow both %aX and `peer_addr` macros */
     buf = IfaceParseACL(acls->rule, iface);
-    strcpy(acls->rule, buf);
+    acl = Mdup2(MB_IPFW, acls, sizeof(struct acl), sizeof(struct acl) + strlen(buf));
+    strcpy(acl->rule, buf);
     Freee(buf);
-    acl = Mdup(MB_IPFW, acls, sizeof(struct acl) + strlen(acls->rule));
     acl->next = iface->tables;
     iface->tables = acl;
-    if (strncmp(acls->rule, "peer_addr", 9) == 0) {
+    if (strncmp(acl->rule, "peer_addr", 9) == 0) {
 	char hisaddr[20];
 	ExecCmd(LG_IFACE2, b->name, "%s table %d add %s",
-	    PATH_IPFW, acls->real_number,
+	    PATH_IPFW, acl->real_number,
 	    u_addrtoa(&iface->peer_addr, hisaddr, sizeof(hisaddr)));
     } else {
-	ExecCmd(LG_IFACE2, b->name, "%s table %d add %s", PATH_IPFW, acls->real_number, acls->rule);
+	ExecCmd(LG_IFACE2, b->name, "%s table %d add %s", PATH_IPFW, acl->real_number, acl->rule);
     }
     acls = acls->next;
   };
@@ -697,8 +698,10 @@ IfaceDown(Bund b)
         PATH_IPFW, acl->real_number,
         u_addrtoa(&iface->peer_addr, hisaddr, sizeof(hisaddr)));
     } else {
+      char buf[ACL_LEN];
       ExecCmd(LG_IFACE2, b->name, "%s table %d delete %s",
-        PATH_IPFW, acl->real_number, acl->rule);
+        PATH_IPFW, acl->real_number,
+        IfaceFixAclForDelete(acl->rule, buf, sizeof(buf)));
     }
     aclnext = acl->next;
     Freee(acl);
@@ -946,6 +949,60 @@ IfaceParseACL (char * src, IfaceState if
     Freee(buf1);
     return(buf);
 }
+
+/*
+ * IfaceFixAclForDelete()
+ *
+ * Removes values from ipfw 'table-key value [...]' expression r, if any.
+ * Returns buf pointer for modified expression or original r pointer
+ * if no modifications were performed when no values were found or
+ * buf found too short.
+ *
+ * len is size of buf. Strings are zero-terminated.
+ * r and buf must point to non-overlapping memory areas.
+ */
+
+static char*
+IfaceFixAclForDelete(char *r, char *buf, size_t len)
+{
+  static const char sep[] = " \t";
+  char *limit, *s;
+  int  i, state = 0; 
+
+/*
+ * Possible state values:
+ *
+ * -1: skip value (otherwise copy);
+ *  0: first iteration, do copy;
+ *  1: not first iteration, do copy.
+*/
+
+  s = buf;
+  limit = buf + len;
+
+  for (r += strspn(r, sep);		/* Skip leading spaces. 	    */
+       *r;				/* Check for end of string. 	    */
+       r += i, r += strspn(r, sep))	/* Advance and skip spaces again.   */
+  {
+    i = strcspn(r, sep);		/* Find separator or end of string. */
+    if (state == 0 && r[i] == '\0')	/* No separators in the rule?	    */
+      return r;
+    if (state < 0) {			/* Skip value.			    */
+      state = 1;
+      continue;
+    }
+    if (limit - s < i + 1 + state)	/* Check space.			    */
+      return r;
+    if (state != 0)			/* Insert separator.		    */
+      *s++ = ' ';
+    memcpy(s, r, i);			/* Copy IP address from the rule.   */
+    s += i;
+    state = -1;
+  }
+  *s = '\0';
+
+  return buf;
+}
 #endif /* USE_IPFW */
 
 /*
Index: src/mbuf.c
===================================================================
RCS file: /cvsroot/mpd/mpd/src/mbuf.c,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -p -r1.30 -r1.31
--- src/mbuf.c	14 Jun 2011 10:40:19 -0000	1.30
+++ src/mbuf.c	29 Jun 2017 08:21:35 -0000	1.31
@@ -55,6 +55,20 @@ Mdup(const char *type, const void *src, 
 }
 
 void *
+Mdup2(const char *type, const void *src, size_t oldsize, size_t newsize)
+{
+    const char	**memory;
+    if ((memory = MALLOC(type, sizeof(char *) + newsize)) == NULL) {
+	Perror("Mdup2: malloc");
+	DoExit(EX_ERRDEAD);
+    }
+
+    memory[0] = type;
+    memcpy(memory + 1, src, oldsize < newsize ? oldsize : newsize);
+    return(memory + 1);
+}
+
+void *
 Mstrdup(const char *type, const void *src)
 {
     return (Mdup(type, src, strlen(src) + 1));
Index: src/mbuf.h
===================================================================
RCS file: /cvsroot/mpd/mpd/src/mbuf.h,v
retrieving revision 1.25
retrieving revision 1.26
diff -u -p -r1.25 -r1.26
--- src/mbuf.h	7 Oct 2013 11:52:35 -0000	1.25
+++ src/mbuf.h	29 Jun 2017 08:21:35 -0000	1.26
@@ -73,6 +73,7 @@
 
   extern void	*Malloc(const char *type, size_t size) __malloc_like;
   extern void	*Mdup(const char *type, const void *src, size_t size) __malloc_like;
+  extern void	*Mdup2(const char *type, const void *src, size_t oldsize, size_t newsize) __malloc_like;
   extern void	*Mstrdup(const char *type, const void *src) __malloc_like;
   extern void	Freee(void *ptr);
 
