Changeset View
Changeset View
Standalone View
Standalone View
head/sys/netpfil/pf/pf_ioctl.c
Show First 20 Lines • Show All 997 Lines • ▼ Show 20 Lines | pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flags, struct thread *td) | ||||
/* XXX keep in sync with switch() below */ | /* XXX keep in sync with switch() below */ | ||||
if (securelevel_gt(td->td_ucred, 2)) | if (securelevel_gt(td->td_ucred, 2)) | ||||
switch (cmd) { | switch (cmd) { | ||||
case DIOCGETRULES: | case DIOCGETRULES: | ||||
case DIOCGETRULE: | case DIOCGETRULE: | ||||
case DIOCGETADDRS: | case DIOCGETADDRS: | ||||
case DIOCGETADDR: | case DIOCGETADDR: | ||||
case DIOCGETSTATE: | |||||
case DIOCSETSTATUSIF: | case DIOCSETSTATUSIF: | ||||
case DIOCGETSTATUS: | case DIOCGETSTATUS: | ||||
case DIOCCLRSTATUS: | case DIOCCLRSTATUS: | ||||
case DIOCNATLOOK: | case DIOCNATLOOK: | ||||
case DIOCSETDEBUG: | case DIOCSETDEBUG: | ||||
case DIOCGETSTATES: | case DIOCGETSTATES: | ||||
case DIOCGETTIMEOUT: | case DIOCGETTIMEOUT: | ||||
case DIOCCLRRULECTRS: | |||||
case DIOCGETLIMIT: | case DIOCGETLIMIT: | ||||
case DIOCGETALTQS: | case DIOCGETALTQS: | ||||
case DIOCGETALTQ: | case DIOCGETALTQ: | ||||
case DIOCGETQSTATS: | case DIOCGETQSTATS: | ||||
case DIOCGETRULESETS: | case DIOCGETRULESETS: | ||||
case DIOCGETRULESET: | case DIOCGETRULESET: | ||||
case DIOCRGETTABLES: | case DIOCRGETTABLES: | ||||
case DIOCRGETTSTATS: | case DIOCRGETTSTATS: | ||||
Show All 26 Lines | default: | ||||
return (EPERM); | return (EPERM); | ||||
} | } | ||||
if (!(flags & FWRITE)) | if (!(flags & FWRITE)) | ||||
switch (cmd) { | switch (cmd) { | ||||
case DIOCGETRULES: | case DIOCGETRULES: | ||||
case DIOCGETADDRS: | case DIOCGETADDRS: | ||||
case DIOCGETADDR: | case DIOCGETADDR: | ||||
case DIOCGETSTATE: | |||||
case DIOCGETSTATUS: | case DIOCGETSTATUS: | ||||
case DIOCGETSTATES: | case DIOCGETSTATES: | ||||
case DIOCGETTIMEOUT: | case DIOCGETTIMEOUT: | ||||
case DIOCGETLIMIT: | case DIOCGETLIMIT: | ||||
case DIOCGETALTQS: | case DIOCGETALTQS: | ||||
case DIOCGETALTQ: | case DIOCGETALTQ: | ||||
case DIOCGETQSTATS: | case DIOCGETQSTATS: | ||||
case DIOCGETRULESETS: | case DIOCGETRULESETS: | ||||
▲ Show 20 Lines • Show All 325 Lines • ▼ Show 20 Lines | if (pr->action == PF_GET_CLR_CNTR) { | ||||
rule->packets[0] = rule->packets[1] = 0; | rule->packets[0] = rule->packets[1] = 0; | ||||
rule->bytes[0] = rule->bytes[1] = 0; | rule->bytes[0] = rule->bytes[1] = 0; | ||||
counter_u64_zero(rule->states_tot); | counter_u64_zero(rule->states_tot); | ||||
} | } | ||||
PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
break; | break; | ||||
} | } | ||||
case DIOCCHANGERULE: { | |||||
struct pfioc_rule *pcr = (struct pfioc_rule *)addr; | |||||
struct pf_ruleset *ruleset; | |||||
struct pf_rule *oldrule = NULL, *newrule = NULL; | |||||
struct pfi_kif *kif = NULL; | |||||
struct pf_pooladdr *pa; | |||||
u_int32_t nr = 0; | |||||
int rs_num; | |||||
if (pcr->action < PF_CHANGE_ADD_HEAD || | |||||
pcr->action > PF_CHANGE_GET_TICKET) { | |||||
error = EINVAL; | |||||
break; | |||||
} | |||||
if (pcr->rule.return_icmp >> 8 > ICMP_MAXTYPE) { | |||||
error = EINVAL; | |||||
break; | |||||
} | |||||
if (pcr->action != PF_CHANGE_REMOVE) { | |||||
#ifndef INET | |||||
if (pcr->rule.af == AF_INET) { | |||||
error = EAFNOSUPPORT; | |||||
break; | |||||
} | |||||
#endif /* INET */ | |||||
#ifndef INET6 | |||||
if (pcr->rule.af == AF_INET6) { | |||||
error = EAFNOSUPPORT; | |||||
break; | |||||
} | |||||
#endif /* INET6 */ | |||||
newrule = malloc(sizeof(*newrule), M_PFRULE, M_WAITOK); | |||||
bcopy(&pcr->rule, newrule, sizeof(struct pf_rule)); | |||||
if (newrule->ifname[0]) | |||||
kif = malloc(sizeof(*kif), PFI_MTYPE, M_WAITOK); | |||||
newrule->states_cur = counter_u64_alloc(M_WAITOK); | |||||
newrule->states_tot = counter_u64_alloc(M_WAITOK); | |||||
newrule->src_nodes = counter_u64_alloc(M_WAITOK); | |||||
newrule->cuid = td->td_ucred->cr_ruid; | |||||
newrule->cpid = td->td_proc ? td->td_proc->p_pid : 0; | |||||
TAILQ_INIT(&newrule->rpool.list); | |||||
} | |||||
#define ERROUT(x) { error = (x); goto DIOCCHANGERULE_error; } | |||||
PF_RULES_WLOCK(); | |||||
if (!(pcr->action == PF_CHANGE_REMOVE || | |||||
pcr->action == PF_CHANGE_GET_TICKET) && | |||||
pcr->pool_ticket != V_ticket_pabuf) | |||||
ERROUT(EBUSY); | |||||
ruleset = pf_find_ruleset(pcr->anchor); | |||||
if (ruleset == NULL) | |||||
ERROUT(EINVAL); | |||||
rs_num = pf_get_ruleset_number(pcr->rule.action); | |||||
if (rs_num >= PF_RULESET_MAX) | |||||
ERROUT(EINVAL); | |||||
if (pcr->action == PF_CHANGE_GET_TICKET) { | |||||
pcr->ticket = ++ruleset->rules[rs_num].active.ticket; | |||||
ERROUT(0); | |||||
} else if (pcr->ticket != | |||||
ruleset->rules[rs_num].active.ticket) | |||||
ERROUT(EINVAL); | |||||
if (pcr->action != PF_CHANGE_REMOVE) { | |||||
if (newrule->ifname[0]) { | |||||
newrule->kif = pfi_kif_attach(kif, | |||||
newrule->ifname); | |||||
pfi_kif_ref(newrule->kif); | |||||
} else | |||||
newrule->kif = NULL; | |||||
if (newrule->rtableid > 0 && | |||||
newrule->rtableid >= rt_numfibs) | |||||
error = EBUSY; | |||||
#ifdef ALTQ | |||||
/* set queue IDs */ | |||||
if (newrule->qname[0] != 0) { | |||||
if ((newrule->qid = | |||||
pf_qname2qid(newrule->qname)) == 0) | |||||
error = EBUSY; | |||||
else if (newrule->pqname[0] != 0) { | |||||
if ((newrule->pqid = | |||||
pf_qname2qid(newrule->pqname)) == 0) | |||||
error = EBUSY; | |||||
} else | |||||
newrule->pqid = newrule->qid; | |||||
} | |||||
#endif /* ALTQ */ | |||||
if (newrule->tagname[0]) | |||||
if ((newrule->tag = | |||||
pf_tagname2tag(newrule->tagname)) == 0) | |||||
error = EBUSY; | |||||
if (newrule->match_tagname[0]) | |||||
if ((newrule->match_tag = pf_tagname2tag( | |||||
newrule->match_tagname)) == 0) | |||||
error = EBUSY; | |||||
if (newrule->rt && !newrule->direction) | |||||
error = EINVAL; | |||||
if (!newrule->log) | |||||
newrule->logif = 0; | |||||
if (newrule->logif >= PFLOGIFS_MAX) | |||||
error = EINVAL; | |||||
if (pf_addr_setup(ruleset, &newrule->src.addr, newrule->af)) | |||||
error = ENOMEM; | |||||
if (pf_addr_setup(ruleset, &newrule->dst.addr, newrule->af)) | |||||
error = ENOMEM; | |||||
if (pf_anchor_setup(newrule, ruleset, pcr->anchor_call)) | |||||
error = EINVAL; | |||||
TAILQ_FOREACH(pa, &V_pf_pabuf, entries) | |||||
if (pa->addr.type == PF_ADDR_TABLE) { | |||||
pa->addr.p.tbl = | |||||
pfr_attach_table(ruleset, | |||||
pa->addr.v.tblname); | |||||
if (pa->addr.p.tbl == NULL) | |||||
error = ENOMEM; | |||||
} | |||||
newrule->overload_tbl = NULL; | |||||
if (newrule->overload_tblname[0]) { | |||||
if ((newrule->overload_tbl = pfr_attach_table( | |||||
ruleset, newrule->overload_tblname)) == | |||||
NULL) | |||||
error = EINVAL; | |||||
else | |||||
newrule->overload_tbl->pfrkt_flags |= | |||||
PFR_TFLAG_ACTIVE; | |||||
} | |||||
pf_mv_pool(&V_pf_pabuf, &newrule->rpool.list); | |||||
if (((((newrule->action == PF_NAT) || | |||||
(newrule->action == PF_RDR) || | |||||
(newrule->action == PF_BINAT) || | |||||
(newrule->rt > PF_NOPFROUTE)) && | |||||
!newrule->anchor)) && | |||||
(TAILQ_FIRST(&newrule->rpool.list) == NULL)) | |||||
error = EINVAL; | |||||
if (error) { | |||||
pf_free_rule(newrule); | |||||
PF_RULES_WUNLOCK(); | |||||
break; | |||||
} | |||||
newrule->rpool.cur = TAILQ_FIRST(&newrule->rpool.list); | |||||
newrule->evaluations = 0; | |||||
newrule->packets[0] = newrule->packets[1] = 0; | |||||
newrule->bytes[0] = newrule->bytes[1] = 0; | |||||
} | |||||
pf_empty_pool(&V_pf_pabuf); | |||||
if (pcr->action == PF_CHANGE_ADD_HEAD) | |||||
oldrule = TAILQ_FIRST( | |||||
ruleset->rules[rs_num].active.ptr); | |||||
else if (pcr->action == PF_CHANGE_ADD_TAIL) | |||||
oldrule = TAILQ_LAST( | |||||
ruleset->rules[rs_num].active.ptr, pf_rulequeue); | |||||
else { | |||||
oldrule = TAILQ_FIRST( | |||||
ruleset->rules[rs_num].active.ptr); | |||||
while ((oldrule != NULL) && (oldrule->nr != pcr->nr)) | |||||
oldrule = TAILQ_NEXT(oldrule, entries); | |||||
if (oldrule == NULL) { | |||||
if (newrule != NULL) | |||||
pf_free_rule(newrule); | |||||
PF_RULES_WUNLOCK(); | |||||
error = EINVAL; | |||||
break; | |||||
} | |||||
} | |||||
if (pcr->action == PF_CHANGE_REMOVE) { | |||||
pf_unlink_rule(ruleset->rules[rs_num].active.ptr, | |||||
oldrule); | |||||
ruleset->rules[rs_num].active.rcount--; | |||||
} else { | |||||
if (oldrule == NULL) | |||||
TAILQ_INSERT_TAIL( | |||||
ruleset->rules[rs_num].active.ptr, | |||||
newrule, entries); | |||||
else if (pcr->action == PF_CHANGE_ADD_HEAD || | |||||
pcr->action == PF_CHANGE_ADD_BEFORE) | |||||
TAILQ_INSERT_BEFORE(oldrule, newrule, entries); | |||||
else | |||||
TAILQ_INSERT_AFTER( | |||||
ruleset->rules[rs_num].active.ptr, | |||||
oldrule, newrule, entries); | |||||
ruleset->rules[rs_num].active.rcount++; | |||||
} | |||||
nr = 0; | |||||
TAILQ_FOREACH(oldrule, | |||||
ruleset->rules[rs_num].active.ptr, entries) | |||||
oldrule->nr = nr++; | |||||
ruleset->rules[rs_num].active.ticket++; | |||||
pf_calc_skip_steps(ruleset->rules[rs_num].active.ptr); | |||||
pf_remove_if_empty_ruleset(ruleset); | |||||
PF_RULES_WUNLOCK(); | |||||
break; | |||||
#undef ERROUT | |||||
DIOCCHANGERULE_error: | |||||
PF_RULES_WUNLOCK(); | |||||
if (newrule != NULL) { | |||||
counter_u64_free(newrule->states_cur); | |||||
counter_u64_free(newrule->states_tot); | |||||
counter_u64_free(newrule->src_nodes); | |||||
free(newrule, M_PFRULE); | |||||
} | |||||
if (kif != NULL) | |||||
free(kif, PFI_MTYPE); | |||||
break; | |||||
} | |||||
case DIOCCLRSTATES: { | case DIOCCLRSTATES: { | ||||
struct pf_state *s; | struct pf_state *s; | ||||
struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr; | struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr; | ||||
u_int i, killed = 0; | u_int i, killed = 0; | ||||
for (i = 0; i <= pf_hashmask; i++) { | for (i = 0; i <= pf_hashmask; i++) { | ||||
struct pf_idhash *ih = &V_pf_idhash[i]; | struct pf_idhash *ih = &V_pf_idhash[i]; | ||||
▲ Show 20 Lines • Show All 90 Lines • ▼ Show 20 Lines | relock_DIOCKILLSTATES: | ||||
} | } | ||||
} | } | ||||
PF_HASHROW_UNLOCK(ih); | PF_HASHROW_UNLOCK(ih); | ||||
} | } | ||||
psk->psk_killed = killed; | psk->psk_killed = killed; | ||||
break; | break; | ||||
} | } | ||||
case DIOCADDSTATE: { | |||||
struct pfioc_state *ps = (struct pfioc_state *)addr; | |||||
struct pfsync_state *sp = &ps->state; | |||||
if (sp->timeout >= PFTM_MAX) { | |||||
error = EINVAL; | |||||
break; | |||||
} | |||||
if (pfsync_state_import_ptr != NULL) { | |||||
PF_RULES_RLOCK(); | |||||
error = pfsync_state_import_ptr(sp, PFSYNC_SI_IOCTL); | |||||
PF_RULES_RUNLOCK(); | |||||
} else | |||||
error = EOPNOTSUPP; | |||||
break; | |||||
} | |||||
case DIOCGETSTATE: { | |||||
struct pfioc_state *ps = (struct pfioc_state *)addr; | |||||
struct pf_state *s; | |||||
s = pf_find_state_byid(ps->state.id, ps->state.creatorid); | |||||
if (s == NULL) { | |||||
error = ENOENT; | |||||
break; | |||||
} | |||||
pfsync_state_export(&ps->state, s); | |||||
PF_STATE_UNLOCK(s); | |||||
break; | |||||
} | |||||
case DIOCGETSTATES: { | case DIOCGETSTATES: { | ||||
struct pfioc_states *ps = (struct pfioc_states *)addr; | struct pfioc_states *ps = (struct pfioc_states *)addr; | ||||
struct pf_state *s; | struct pf_state *s; | ||||
struct pfsync_state *pstore, *p; | struct pfsync_state *pstore, *p; | ||||
int i, nr; | int i, nr; | ||||
if (ps->ps_len == 0) { | if (ps->ps_len == 0) { | ||||
nr = uma_zone_get_cur(V_pf_state_z); | nr = uma_zone_get_cur(V_pf_state_z); | ||||
▲ Show 20 Lines • Show All 214 Lines • ▼ Show 20 Lines | case DIOCSETDEBUG: { | ||||
u_int32_t *level = (u_int32_t *)addr; | u_int32_t *level = (u_int32_t *)addr; | ||||
PF_RULES_WLOCK(); | PF_RULES_WLOCK(); | ||||
V_pf_status.debug = *level; | V_pf_status.debug = *level; | ||||
PF_RULES_WUNLOCK(); | PF_RULES_WUNLOCK(); | ||||
break; | break; | ||||
} | } | ||||
case DIOCCLRRULECTRS: { | |||||
/* obsoleted by DIOCGETRULE with action=PF_GET_CLR_CNTR */ | |||||
struct pf_ruleset *ruleset = &pf_main_ruleset; | |||||
struct pf_rule *rule; | |||||
PF_RULES_WLOCK(); | |||||
TAILQ_FOREACH(rule, | |||||
ruleset->rules[PF_RULESET_FILTER].active.ptr, entries) { | |||||
rule->evaluations = 0; | |||||
rule->packets[0] = rule->packets[1] = 0; | |||||
rule->bytes[0] = rule->bytes[1] = 0; | |||||
} | |||||
PF_RULES_WUNLOCK(); | |||||
break; | |||||
} | |||||
case DIOCGIFSPEED: { | case DIOCGIFSPEED: { | ||||
struct pf_ifspeed *psp = (struct pf_ifspeed *)addr; | struct pf_ifspeed *psp = (struct pf_ifspeed *)addr; | ||||
struct pf_ifspeed ps; | struct pf_ifspeed ps; | ||||
struct ifnet *ifp; | struct ifnet *ifp; | ||||
if (psp->ifname[0] != 0) { | if (psp->ifname[0] != 0) { | ||||
/* Can we completely trust user-land? */ | /* Can we completely trust user-land? */ | ||||
strlcpy(ps.ifname, psp->ifname, IFNAMSIZ); | strlcpy(ps.ifname, psp->ifname, IFNAMSIZ); | ||||
▲ Show 20 Lines • Show All 138 Lines • ▼ Show 20 Lines | if (altq == NULL) { | ||||
error = EBUSY; | error = EBUSY; | ||||
break; | break; | ||||
} | } | ||||
bcopy(altq, &pa->altq, sizeof(struct pf_altq)); | bcopy(altq, &pa->altq, sizeof(struct pf_altq)); | ||||
PF_RULES_RUNLOCK(); | PF_RULES_RUNLOCK(); | ||||
break; | break; | ||||
} | } | ||||
case DIOCCHANGEALTQ: | |||||
/* CHANGEALTQ not supported yet! */ | |||||
error = ENODEV; | |||||
break; | |||||
case DIOCGETQSTATS: { | case DIOCGETQSTATS: { | ||||
struct pfioc_qstats *pq = (struct pfioc_qstats *)addr; | struct pfioc_qstats *pq = (struct pfioc_qstats *)addr; | ||||
struct pf_altq *altq; | struct pf_altq *altq; | ||||
u_int32_t nr; | u_int32_t nr; | ||||
int nbytes; | int nbytes; | ||||
PF_RULES_RLOCK(); | PF_RULES_RLOCK(); | ||||
if (pq->ticket != V_ticket_altqs_active) { | if (pq->ticket != V_ticket_altqs_active) { | ||||
▲ Show 20 Lines • Show All 135 Lines • ▼ Show 20 Lines | case DIOCGETADDR: { | ||||
if (pa == NULL) { | if (pa == NULL) { | ||||
PF_RULES_RUNLOCK(); | PF_RULES_RUNLOCK(); | ||||
error = EBUSY; | error = EBUSY; | ||||
break; | break; | ||||
} | } | ||||
bcopy(pa, &pp->addr, sizeof(struct pf_pooladdr)); | bcopy(pa, &pp->addr, sizeof(struct pf_pooladdr)); | ||||
pf_addr_copyout(&pp->addr.addr); | pf_addr_copyout(&pp->addr.addr); | ||||
PF_RULES_RUNLOCK(); | PF_RULES_RUNLOCK(); | ||||
break; | |||||
} | |||||
case DIOCCHANGEADDR: { | |||||
struct pfioc_pooladdr *pca = (struct pfioc_pooladdr *)addr; | |||||
struct pf_pool *pool; | |||||
struct pf_pooladdr *oldpa = NULL, *newpa = NULL; | |||||
struct pf_ruleset *ruleset; | |||||
struct pfi_kif *kif = NULL; | |||||
if (pca->action < PF_CHANGE_ADD_HEAD || | |||||
pca->action > PF_CHANGE_REMOVE) { | |||||
error = EINVAL; | |||||
break; | |||||
} | |||||
if (pca->addr.addr.type != PF_ADDR_ADDRMASK && | |||||
pca->addr.addr.type != PF_ADDR_DYNIFTL && | |||||
pca->addr.addr.type != PF_ADDR_TABLE) { | |||||
error = EINVAL; | |||||
break; | |||||
} | |||||
if (pca->action != PF_CHANGE_REMOVE) { | |||||
#ifndef INET | |||||
if (pca->af == AF_INET) { | |||||
error = EAFNOSUPPORT; | |||||
break; | |||||
} | |||||
#endif /* INET */ | |||||
#ifndef INET6 | |||||
if (pca->af == AF_INET6) { | |||||
error = EAFNOSUPPORT; | |||||
break; | |||||
} | |||||
#endif /* INET6 */ | |||||
newpa = malloc(sizeof(*newpa), M_PFRULE, M_WAITOK); | |||||
bcopy(&pca->addr, newpa, sizeof(struct pf_pooladdr)); | |||||
if (newpa->ifname[0]) | |||||
kif = malloc(sizeof(*kif), PFI_MTYPE, M_WAITOK); | |||||
newpa->kif = NULL; | |||||
} | |||||
#define ERROUT(x) { error = (x); goto DIOCCHANGEADDR_error; } | |||||
PF_RULES_WLOCK(); | |||||
ruleset = pf_find_ruleset(pca->anchor); | |||||
if (ruleset == NULL) | |||||
ERROUT(EBUSY); | |||||
pool = pf_get_pool(pca->anchor, pca->ticket, pca->r_action, | |||||
pca->r_num, pca->r_last, 1, 1); | |||||
if (pool == NULL) | |||||
ERROUT(EBUSY); | |||||
if (pca->action != PF_CHANGE_REMOVE) { | |||||
if (newpa->ifname[0]) { | |||||
newpa->kif = pfi_kif_attach(kif, newpa->ifname); | |||||
pfi_kif_ref(newpa->kif); | |||||
kif = NULL; | |||||
} | |||||
switch (newpa->addr.type) { | |||||
case PF_ADDR_DYNIFTL: | |||||
error = pfi_dynaddr_setup(&newpa->addr, | |||||
pca->af); | |||||
break; | |||||
case PF_ADDR_TABLE: | |||||
newpa->addr.p.tbl = pfr_attach_table(ruleset, | |||||
newpa->addr.v.tblname); | |||||
if (newpa->addr.p.tbl == NULL) | |||||
error = ENOMEM; | |||||
break; | |||||
} | |||||
if (error) | |||||
goto DIOCCHANGEADDR_error; | |||||
} | |||||
switch (pca->action) { | |||||
case PF_CHANGE_ADD_HEAD: | |||||
oldpa = TAILQ_FIRST(&pool->list); | |||||
break; | |||||
case PF_CHANGE_ADD_TAIL: | |||||
oldpa = TAILQ_LAST(&pool->list, pf_palist); | |||||
break; | |||||
default: | |||||
oldpa = TAILQ_FIRST(&pool->list); | |||||
for (int i = 0; oldpa && i < pca->nr; i++) | |||||
oldpa = TAILQ_NEXT(oldpa, entries); | |||||
if (oldpa == NULL) | |||||
ERROUT(EINVAL); | |||||
} | |||||
if (pca->action == PF_CHANGE_REMOVE) { | |||||
TAILQ_REMOVE(&pool->list, oldpa, entries); | |||||
switch (oldpa->addr.type) { | |||||
case PF_ADDR_DYNIFTL: | |||||
pfi_dynaddr_remove(oldpa->addr.p.dyn); | |||||
break; | |||||
case PF_ADDR_TABLE: | |||||
pfr_detach_table(oldpa->addr.p.tbl); | |||||
break; | |||||
} | |||||
if (oldpa->kif) | |||||
pfi_kif_unref(oldpa->kif); | |||||
free(oldpa, M_PFRULE); | |||||
} else { | |||||
if (oldpa == NULL) | |||||
TAILQ_INSERT_TAIL(&pool->list, newpa, entries); | |||||
else if (pca->action == PF_CHANGE_ADD_HEAD || | |||||
pca->action == PF_CHANGE_ADD_BEFORE) | |||||
TAILQ_INSERT_BEFORE(oldpa, newpa, entries); | |||||
else | |||||
TAILQ_INSERT_AFTER(&pool->list, oldpa, | |||||
newpa, entries); | |||||
} | |||||
pool->cur = TAILQ_FIRST(&pool->list); | |||||
PF_ACPY(&pool->counter, &pool->cur->addr.v.a.addr, pca->af); | |||||
PF_RULES_WUNLOCK(); | |||||
break; | |||||
#undef ERROUT | |||||
DIOCCHANGEADDR_error: | |||||
if (newpa != NULL) { | |||||
if (newpa->kif) | |||||
pfi_kif_unref(newpa->kif); | |||||
free(newpa, M_PFRULE); | |||||
} | |||||
PF_RULES_WUNLOCK(); | |||||
if (kif != NULL) | |||||
free(kif, PFI_MTYPE); | |||||
break; | break; | ||||
} | } | ||||
case DIOCGETRULESETS: { | case DIOCGETRULESETS: { | ||||
struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; | struct pfioc_ruleset *pr = (struct pfioc_ruleset *)addr; | ||||
struct pf_ruleset *ruleset; | struct pf_ruleset *ruleset; | ||||
struct pf_anchor *anchor; | struct pf_anchor *anchor; | ||||
▲ Show 20 Lines • Show All 1,601 Lines • Show Last 20 Lines |