static int recursive_ruleset_purge(char *an, char *rs) { struct pfioc_trans_e *t_e = NULL; struct pfioc_trans *t = NULL; struct pfioc_ruleset *prs = NULL; /* purge rules */ errno = 0; if ((t = calloc(1, sizeof(struct pfioc_trans))) == NULL) goto no_mem; if ((t_e = calloc(2, sizeof(struct pfioc_trans_e))) == NULL) goto no_mem; t->size = 2; t->esize = sizeof(struct pfioc_trans_e); t->array = t_e; t_e[0].type = PF_TRANS_RULESET; snprintf(t_e[0].anchor, sizeof(t_e[0].anchor), "%s/%s", an, rs); t_e[1].type = PF_TRANS_TABLE; if ((ioctl(dev, DIOCXBEGIN, t) || ioctl(dev, DIOCXCOMMIT, t)) && errno != EINVAL) goto cleanup; /* purge any children */ if ((prs = calloc(1, sizeof(struct pfioc_ruleset))) == NULL) goto no_mem; snprintf(prs->path, sizeof(prs->path), "%s/%s", an, rs); if (ioctl(dev, DIOCGETRULESETS, prs)) { if (errno != EINVAL) goto cleanup; errno = 0; } else { int nr = prs->nr; while (nr) { prs->nr = 0; if (ioctl(dev, DIOCGETRULESET, prs)) goto cleanup; if (recursive_ruleset_purge(prs->path, prs->name)) goto cleanup; nr--; } } no_mem: if (errno == ENOMEM) syslog(LOG_ERR, "calloc failed"); cleanup: free(t); free(t_e); free(prs); return (errno); }
/* * Search for rulesets left by other authpf processes (either because they * died ungracefully or were terminated) and remove them. */ static int remove_stale_rulesets(void) { struct pfioc_ruleset prs; u_int32_t nr; memset(&prs, 0, sizeof(prs)); strlcpy(prs.path, anchorname, sizeof(prs.path)); if (ioctl(dev, DIOCGETRULESETS, &prs)) { if (errno == EINVAL) return (0); else return (1); } nr = prs.nr; while (nr) { char *s, *t; pid_t pid; prs.nr = nr - 1; if (ioctl(dev, DIOCGETRULESET, &prs)) return (1); errno = 0; if ((t = strchr(prs.name, '(')) == NULL) t = prs.name; else t++; pid = strtoul(t, &s, 10); if (!prs.name[0] || errno || (*s && (t == prs.name || *s != ')'))) return (1); if ((kill(pid, 0) && errno != EPERM) || pid == getpid()) { if (recursive_ruleset_purge(anchorname, prs.name)) return (1); } nr--; } return (0); }