int pf_anchor_setup(struct pf_rule *r, const struct pf_ruleset *s, const char *name) { char *p, *path; struct pf_ruleset *ruleset; r->anchor = NULL; r->anchor_relative = 0; r->anchor_wildcard = 0; if (!name[0]) return (0); path = (char *)rs_malloc(MAXPATHLEN); if (path == NULL) return (1); if (name[0] == '/') strlcpy(path, name + 1, MAXPATHLEN); else { /* relative path */ r->anchor_relative = 1; if (s->anchor == NULL || !s->anchor->path[0]) path[0] = 0; else strlcpy(path, s->anchor->path, MAXPATHLEN); while (name[0] == '.' && name[1] == '.' && name[2] == '/') { if (!path[0]) { DPFPRINTF(LOG_NOTICE, "pf_anchor_setup: .. beyond root"); rs_free(path); return (1); } if ((p = strrchr(path, '/')) != NULL) *p = 0; else path[0] = 0; r->anchor_relative++; name += 3; } if (path[0]) strlcat(path, "/", MAXPATHLEN); strlcat(path, name, MAXPATHLEN); } if ((p = strrchr(path, '/')) != NULL && !strcmp(p, "/*")) { r->anchor_wildcard = 1; *p = 0; } ruleset = pf_find_or_create_ruleset(path); rs_free(path); if (ruleset == NULL || ruleset->anchor == NULL) { DPFPRINTF(LOG_NOTICE, "pf_anchor_setup: ruleset"); return (1); } r->anchor = ruleset->anchor; r->anchor->refcnt++; return (0); }
int pfi_dynaddr_setup(struct pf_addr_wrap *aw, sa_family_t af) { struct pfi_dynaddr *dyn; char tblname[PF_TABLE_NAME_SIZE]; struct pf_ruleset *ruleset = NULL; int s, rv = 0; if (aw->type != PF_ADDR_DYNIFTL) return (0); if ((dyn = pool_get(&pfi_addr_pl, PR_NOWAIT)) == NULL) return (1); bzero(dyn, sizeof(*dyn)); s = splsoftnet(); if (!strcmp(aw->v.ifname, "self")) dyn->pfid_kif = pfi_kif_get(IFG_ALL); else dyn->pfid_kif = pfi_kif_get(aw->v.ifname); if (dyn->pfid_kif == NULL) { rv = 1; goto _bad; } pfi_kif_ref(dyn->pfid_kif, PFI_KIF_REF_RULE); dyn->pfid_net = pfi_unmask(&aw->v.a.mask); if (af == AF_INET && dyn->pfid_net == 32) dyn->pfid_net = 128; strlcpy(tblname, aw->v.ifname, sizeof(tblname)); if (aw->iflags & PFI_AFLAG_NETWORK) strlcat(tblname, ":network", sizeof(tblname)); if (aw->iflags & PFI_AFLAG_BROADCAST) strlcat(tblname, ":broadcast", sizeof(tblname)); if (aw->iflags & PFI_AFLAG_PEER) strlcat(tblname, ":peer", sizeof(tblname)); if (aw->iflags & PFI_AFLAG_NOALIAS) strlcat(tblname, ":0", sizeof(tblname)); if (dyn->pfid_net != 128) snprintf(tblname + strlen(tblname), sizeof(tblname) - strlen(tblname), "/%d", dyn->pfid_net); if ((ruleset = pf_find_or_create_ruleset(PF_RESERVED_ANCHOR)) == NULL) { rv = 1; goto _bad; } if ((dyn->pfid_kt = pfr_attach_table(ruleset, tblname)) == NULL) { rv = 1; goto _bad; } dyn->pfid_kt->pfrkt_flags |= PFR_TFLAG_ACTIVE; dyn->pfid_iflags = aw->iflags; dyn->pfid_af = af; TAILQ_INSERT_TAIL(&dyn->pfid_kif->pfik_dynaddrs, dyn, entry); aw->p.dyn = dyn; pfi_kif_update(dyn->pfid_kif); splx(s); return (0); _bad: if (dyn->pfid_kt != NULL) pfr_detach_table(dyn->pfid_kt); if (ruleset != NULL) pf_remove_if_empty_ruleset(ruleset); if (dyn->pfid_kif != NULL) pfi_kif_unref(dyn->pfid_kif, PFI_KIF_REF_RULE); pool_put(&pfi_addr_pl, dyn); splx(s); return (rv); }