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);