Make queues disappear correctly on interfaces being destroyed.
authorpelikan <pelikan@openbsd.org>
Fri, 3 Jan 2014 12:43:09 +0000 (12:43 +0000)
committerpelikan <pelikan@openbsd.org>
Fri, 3 Jan 2014 12:43:09 +0000 (12:43 +0000)
ok henning

sys/net/pf_if.c
sys/net/pf_ioctl.c
sys/net/pfvar.h

index 6c533cf..14e42de 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pf_if.c,v 1.68 2013/10/17 16:27:42 bluhm Exp $ */
+/*     $OpenBSD: pf_if.c,v 1.69 2014/01/03 12:43:09 pelikan Exp $ */
 
 /*
  * Copyright 2005 Henning Brauer <henning@openbsd.org>
@@ -242,9 +242,15 @@ pfi_detach_ifnet(struct ifnet *ifp)
        hook_disestablish(ifp->if_addrhooks, kif->pfik_ah_cookie);
        pfi_kif_update(kif);
 
+       if (HFSC_ENABLED(&ifp->if_snd)) {
+               pf_remove_queues(ifp);
+               pf_free_queues(pf_queues_active, ifp);
+       }
+
        kif->pfik_ifp = NULL;
        ifp->if_pf_kif = NULL;
        pfi_kif_unref(kif, PFI_KIF_REF_NONE);
+
        splx(s);
 }
 
index 6cbe616..af7dae5 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pf_ioctl.c,v 1.265 2013/11/13 18:25:57 deraadt Exp $ */
+/*     $OpenBSD: pf_ioctl.c,v 1.266 2014/01/03 12:43:09 pelikan Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -100,10 +100,8 @@ int                         pf_disable_altq(struct pf_altq *);
 #endif /* ALTQ */
 int                     pf_begin_rules(u_int32_t *, const char *);
 int                     pf_rollback_rules(u_int32_t, char *);
-int                     pf_free_queues(char *);
-int                     pf_remove_queues(void);
 int                     pf_create_queues(void);
-int                     pf_commit_queues(char *);
+int                     pf_commit_queues(void);
 int                     pf_setup_pfsync_matching(struct pf_ruleset *);
 void                    pf_hash_rule(MD5_CTX *, struct pf_rule *);
 void                    pf_hash_rule_addr(MD5_CTX *, struct pf_rule_addr *);
@@ -716,20 +714,22 @@ pf_rollback_rules(u_int32_t ticket, char *anchor)
                rs->rules.inactive.rcount--;
        }
        rs->rules.inactive.open = 0;
-       return (pf_free_queues(anchor));
-}
-
-int
-pf_free_queues(char *anchor)
-{
-       struct pf_queuespec     *q;
 
        /* queue defs only in the main ruleset */
        if (anchor[0])
                return (0);
+       return (pf_free_queues(pf_queues_inactive, NULL));
+}
 
-       while ((q = TAILQ_FIRST(pf_queues_inactive)) != NULL) {
-               TAILQ_REMOVE(pf_queues_inactive, q, entries);
+int
+pf_free_queues(struct pf_queuehead *where, struct ifnet *ifp)
+{
+       struct pf_queuespec     *q, *qtmp;
+
+       TAILQ_FOREACH_SAFE(q, where, entries, qtmp) {
+               if (ifp && q->kif->pfik_ifp != ifp)
+                       continue;
+               TAILQ_REMOVE(where, q, entries);
                pfi_kif_unref(q->kif, PFI_KIF_REF_RULE);
                pool_put(&pf_queue_pl, q);
        }
@@ -737,21 +737,27 @@ pf_free_queues(char *anchor)
 }
 
 int
-pf_remove_queues(void)
+pf_remove_queues(struct ifnet *ifp)
 {
        struct pf_queuespec     *q;
        int                      error = 0;
 
        /* remove queues */
-       TAILQ_FOREACH_REVERSE(q, pf_queues_active, pf_queuehead, entries)
+       TAILQ_FOREACH_REVERSE(q, pf_queues_active, pf_queuehead, entries) {
+               if (ifp && q->kif->pfik_ifp != ifp)
+                       continue;
                if ((error = hfsc_delqueue(q)) != 0)
                        return (error);
+       }
 
        /* put back interfaces in normal queueing mode */       
-       TAILQ_FOREACH(q, pf_queues_active, entries)
+       TAILQ_FOREACH(q, pf_queues_active, entries) {
+               if (ifp && q->kif->pfik_ifp != ifp)
+                       continue;
                if (q->parent_qid == 0)
                        if ((error = hfsc_detach(q->kif->pfik_ifp)) != 0)
                                return (error);
+       }
 
        return (0);
 }
@@ -777,23 +783,19 @@ pf_create_queues(void)
 }
 
 int
-pf_commit_queues(char *anchor)
+pf_commit_queues(void)
 {
        struct pf_queuehead     *qswap;
        int error;
 
-       /* queue defs only in the main ruleset */
-       if (anchor[0])
-               return (0);
-
-       if ((error = pf_remove_queues()) != 0)
+       if ((error = pf_remove_queues(NULL)) != 0)
                return (error);
 
        /* swap */
        qswap = pf_queues_active;
        pf_queues_active = pf_queues_inactive;
        pf_queues_inactive = qswap;
-       pf_free_queues(anchor);
+       pf_free_queues(pf_queues_inactive, NULL);
 
        return (pf_create_queues());
 }
@@ -929,7 +931,11 @@ pf_commit_rules(u_int32_t ticket, char *anchor)
        rs->rules.inactive.open = 0;
        pf_remove_if_empty_ruleset(rs);
        splx(s);
-       return (pf_commit_queues(anchor));
+
+       /* queue defs only in the main ruleset */
+       if (anchor[0])
+               return (0);
+       return (pf_commit_queues());
 }
 
 int
@@ -1134,7 +1140,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
                else {
                        pf_status.running = 0;
                        pf_status.since = time_second;
-                       pf_remove_queues();
+                       pf_remove_queues(NULL);
                        DPFPRINTF(LOG_NOTICE, "pf: stopped");
                }
                break;
index 93b1fc3..c3f262b 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: pfvar.h,v 1.393 2013/12/22 16:49:29 deraadt Exp $ */
+/*     $OpenBSD: pfvar.h,v 1.394 2014/01/03 12:43:09 pelikan Exp $ */
 
 /*
  * Copyright (c) 2001 Daniel Hartmeier
@@ -1792,6 +1792,9 @@ extern int                         altqs_inactive_open;
 extern u_int32_t                ticket_pabuf;
 extern struct pf_altqqueue     *pf_altqs_active;
 extern struct pf_altqqueue     *pf_altqs_inactive;
+extern int                      pf_free_queues(struct pf_queuehead *,
+                                   struct ifnet *);
+extern int                      pf_remove_queues(struct ifnet *);
 extern int                      pf_tbladdr_setup(struct pf_ruleset *,
                                    struct pf_addr_wrap *);
 extern void                     pf_tbladdr_remove(struct pf_addr_wrap *);