Author: will
Date: Wed Jul  4 03:36:46 2018
New Revision: 335928
URL: https://svnweb.freebsd.org/changeset/base/335928

Log:
  Revert r335833.
  
  Several third-parties use at least some of these ioctls.  While it would be
  better for regression testing if they were used in base (or at least in the
  test suite), it's currently not worth the trouble to push through removal.
  
  Submitted by: antoine, markj

Modified:
  head/share/man/man4/pf.4
  head/sys/net/pfvar.h
  head/sys/netpfil/pf/pf_ioctl.c

Modified: head/share/man/man4/pf.4
==============================================================================
--- head/share/man/man4/pf.4    Wed Jul  4 03:24:11 2018        (r335927)
+++ head/share/man/man4/pf.4    Wed Jul  4 03:36:46 2018        (r335928)
@@ -139,8 +139,9 @@ Clear the buffer address pool and get a
 .Va ticket
 for subsequent
 .Dv DIOCADDADDR ,
+.Dv DIOCADDRULE ,
 and
-.Dv DIOCADDRULE
+.Dv DIOCCHANGERULE
 calls.
 .It Dv DIOCADDADDR Fa "struct pfioc_pooladdr *pp"
 .Pp
@@ -148,6 +149,8 @@ Add the pool address
 .Va addr
 to the buffer address pool to be used in the following
 .Dv DIOCADDRULE
+or
+.Dv DIOCCHANGERULE
 call.
 All other members of the structure are ignored.
 .It Dv DIOCADDRULE Fa "struct pfioc_rule *pr"
@@ -316,6 +319,21 @@ This ioctl returns
 if the given anchor does not exist or
 .Er EBUSY
 if another process is concurrently updating a ruleset.
+.It Dv DIOCADDSTATE Fa "struct pfioc_state *ps"
+Add a state entry.
+.Bd -literal
+struct pfioc_state {
+       struct pfsync_state     state;
+};
+.Ed
+.It Dv DIOCGETSTATE Fa "struct pfioc_state *ps"
+Extract the entry identified by the
+.Va id
+and
+.Va creatorid
+fields of the
+.Va state
+structure from the state table.
 .It Dv DIOCKILLSTATES Fa "struct pfioc_state_kill *psk"
 Remove matching entries from the state table.
 This ioctl returns the number of killed states in
@@ -421,6 +439,11 @@ On exit,
 is always set to the total size required to hold all state table entries
 (i.e., it is set to
 .Li sizeof(struct pf_state) * nr ) .
+.It Dv DIOCCHANGERULE Fa "struct pfioc_rule *pcr"
+Add or remove the
+.Va rule
+in the ruleset specified by
+.Va rule.action .
 .Pp
 The type of operation to be performed is indicated by
 .Va action ,
@@ -452,6 +475,15 @@ indicates the rule number against which
 or
 .Dv PF_CHANGE_REMOVE
 actions are applied.
+.\" It Dv DIOCCHANGEALTQ Fa "struct pfioc_altq *pcr"
+.It Dv DIOCCHANGEADDR Fa "struct pfioc_pooladdr *pca"
+Add or remove the pool address
+.Va addr
+from the rule specified by
+.Va r_action ,
+.Va r_num ,
+and
+.Va anchor .
 .It Dv DIOCSETTIMEOUT Fa "struct pfioc_tm *pt"
 .Bd -literal
 struct pfioc_tm {
@@ -478,6 +510,8 @@ Get the state timeout of
 The value will be placed into the
 .Va seconds
 field.
+.It Dv DIOCCLRRULECTRS
+Clear per-rule statistics.
 .It Dv DIOCSETLIMIT Fa "struct pfioc_limit *pl"
 Set the hard limits on the memory pools used by the packet filter.
 .Bd -literal

Modified: head/sys/net/pfvar.h
==============================================================================
--- head/sys/net/pfvar.h        Wed Jul  4 03:24:11 2018        (r335927)
+++ head/sys/net/pfvar.h        Wed Jul  4 03:36:46 2018        (r335928)
@@ -1385,17 +1385,19 @@ struct pfioc_iface {
 #define DIOCGETRULE    _IOWR('D',  7, struct pfioc_rule)
 /* XXX cut 8 - 17 */
 #define DIOCCLRSTATES  _IOWR('D', 18, struct pfioc_state_kill)
-/* XXX cut 19 */
+#define DIOCGETSTATE   _IOWR('D', 19, struct pfioc_state)
 #define DIOCSETSTATUSIF _IOWR('D', 20, struct pfioc_if)
 #define DIOCGETSTATUS  _IOWR('D', 21, struct pf_status)
 #define DIOCCLRSTATUS  _IO  ('D', 22)
 #define DIOCNATLOOK    _IOWR('D', 23, struct pfioc_natlook)
 #define DIOCSETDEBUG   _IOWR('D', 24, u_int32_t)
 #define DIOCGETSTATES  _IOWR('D', 25, struct pfioc_states)
+#define DIOCCHANGERULE _IOWR('D', 26, struct pfioc_rule)
 /* XXX cut 26 - 28 */
 #define DIOCSETTIMEOUT _IOWR('D', 29, struct pfioc_tm)
 #define DIOCGETTIMEOUT _IOWR('D', 30, struct pfioc_tm)
-/* XXX cut 31-38 */
+#define DIOCADDSTATE   _IOWR('D', 37, struct pfioc_state)
+#define DIOCCLRRULECTRS        _IO  ('D', 38)
 #define DIOCGETLIMIT   _IOWR('D', 39, struct pfioc_limit)
 #define DIOCSETLIMIT   _IOWR('D', 40, struct pfioc_limit)
 #define DIOCKILLSTATES _IOWR('D', 41, struct pfioc_state_kill)
@@ -1404,12 +1406,13 @@ struct pfioc_iface {
 #define DIOCADDALTQ    _IOWR('D', 45, struct pfioc_altq)
 #define DIOCGETALTQS   _IOWR('D', 47, struct pfioc_altq)
 #define DIOCGETALTQ    _IOWR('D', 48, struct pfioc_altq)
-/* XXX cut 49 */
+#define DIOCCHANGEALTQ _IOWR('D', 49, struct pfioc_altq)
 #define DIOCGETQSTATS  _IOWR('D', 50, struct pfioc_qstats)
 #define DIOCBEGINADDRS _IOWR('D', 51, struct pfioc_pooladdr)
 #define DIOCADDADDR    _IOWR('D', 52, struct pfioc_pooladdr)
 #define DIOCGETADDRS   _IOWR('D', 53, struct pfioc_pooladdr)
 #define DIOCGETADDR    _IOWR('D', 54, struct pfioc_pooladdr)
+#define DIOCCHANGEADDR _IOWR('D', 55, struct pfioc_pooladdr)
 /* XXX cut 55 - 57 */
 #define        DIOCGETRULESETS _IOWR('D', 58, struct pfioc_ruleset)
 #define        DIOCGETRULESET  _IOWR('D', 59, struct pfioc_ruleset)

Modified: head/sys/netpfil/pf/pf_ioctl.c
==============================================================================
--- head/sys/netpfil/pf/pf_ioctl.c      Wed Jul  4 03:24:11 2018        
(r335927)
+++ head/sys/netpfil/pf/pf_ioctl.c      Wed Jul  4 03:36:46 2018        
(r335928)
@@ -1003,6 +1003,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, in
                case DIOCGETRULE:
                case DIOCGETADDRS:
                case DIOCGETADDR:
+               case DIOCGETSTATE:
                case DIOCSETSTATUSIF:
                case DIOCGETSTATUS:
                case DIOCCLRSTATUS:
@@ -1010,6 +1011,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, in
                case DIOCSETDEBUG:
                case DIOCGETSTATES:
                case DIOCGETTIMEOUT:
+               case DIOCCLRRULECTRS:
                case DIOCGETLIMIT:
                case DIOCGETALTQS:
                case DIOCGETALTQ:
@@ -1052,6 +1054,7 @@ pfioctl(struct cdev *dev, u_long cmd, caddr_t addr, in
                case DIOCGETRULES:
                case DIOCGETADDRS:
                case DIOCGETADDR:
+               case DIOCGETSTATE:
                case DIOCGETSTATUS:
                case DIOCGETSTATES:
                case DIOCGETTIMEOUT:
@@ -1393,6 +1396,227 @@ DIOCADDRULE_error:
                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: {
                struct pf_state         *s;
                struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
@@ -1499,6 +1723,38 @@ relock_DIOCKILLSTATES:
                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: {
                struct pfioc_states     *ps = (struct pfioc_states *)addr;
                struct pf_state         *s;
@@ -1729,6 +1985,22 @@ DIOCGETSTATES_full:
                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: {
                struct pf_ifspeed       *psp = (struct pf_ifspeed *)addr;
                struct pf_ifspeed       ps;
@@ -1883,6 +2155,11 @@ DIOCGETSTATES_full:
                break;
        }
 
+       case DIOCCHANGEALTQ:
+               /* CHANGEALTQ not supported yet! */
+               error = ENODEV;
+               break;
+
        case DIOCGETQSTATS: {
                struct pfioc_qstats     *pq = (struct pfioc_qstats *)addr;
                struct pf_altq          *altq;
@@ -2034,6 +2311,137 @@ DIOCGETSTATES_full:
                bcopy(pa, &pp->addr, sizeof(struct pf_pooladdr));
                pf_addr_copyout(&pp->addr.addr);
                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;
        }
 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to