summaryrefslogtreecommitdiffstats
path: root/sys/contrib/pf/net/pf_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/pf/net/pf_ioctl.c')
-rw-r--r--sys/contrib/pf/net/pf_ioctl.c118
1 files changed, 116 insertions, 2 deletions
diff --git a/sys/contrib/pf/net/pf_ioctl.c b/sys/contrib/pf/net/pf_ioctl.c
index 6314b4c..f9110cb 100644
--- a/sys/contrib/pf/net/pf_ioctl.c
+++ b/sys/contrib/pf/net/pf_ioctl.c
@@ -787,7 +787,12 @@ pf_begin_altq(u_int32_t *ticket)
/* Purge the old altq list */
while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
+#ifdef __FreeBSD__
+ if (altq->qname[0] == 0 &&
+ (altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
+#else
if (altq->qname[0] == 0) {
+#endif
/* detach and destroy the discipline */
error = altq_remove(altq);
} else
@@ -812,7 +817,12 @@ pf_rollback_altq(u_int32_t ticket)
/* Purge the old altq list */
while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
+#ifdef __FreeBSD__
+ if (altq->qname[0] == 0 &&
+ (altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
+#else
if (altq->qname[0] == 0) {
+#endif
/* detach and destroy the discipline */
error = altq_remove(altq);
} else
@@ -842,7 +852,12 @@ pf_commit_altq(u_int32_t ticket)
/* Attach new disciplines */
TAILQ_FOREACH(altq, pf_altqs_active, entries) {
+#ifdef __FreeBSD__
+ if (altq->qname[0] == 0 &&
+ (altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
+#else
if (altq->qname[0] == 0) {
+#endif
/* attach the discipline */
error = altq_pfattach(altq);
if (error == 0 && pf_altq_running)
@@ -857,7 +872,12 @@ pf_commit_altq(u_int32_t ticket)
/* Purge the old altq list */
while ((altq = TAILQ_FIRST(pf_altqs_inactive)) != NULL) {
TAILQ_REMOVE(pf_altqs_inactive, altq, entries);
+#ifdef __FreeBSD__
+ if (altq->qname[0] == 0 &&
+ (altq->local_flags & PFALTQ_FLAG_IF_REMOVED) == 0) {
+#else
if (altq->qname[0] == 0) {
+#endif
/* detach and destroy the discipline */
if (pf_altq_running)
error = pf_disable_altq(altq);
@@ -943,6 +963,76 @@ pf_disable_altq(struct pf_altq *altq)
return (error);
}
+
+#ifdef __FreeBSD__
+void
+pf_altq_ifnet_event(struct ifnet *ifp, int remove)
+{
+ struct ifnet *ifp1;
+ struct pf_altq *a1, *a2, *a3;
+ u_int32_t ticket;
+ int error = 0;
+
+ /* Interrupt userland queue modifications */
+ if (altqs_inactive_open)
+ pf_rollback_altq(ticket_altqs_inactive);
+
+ /* Start new altq ruleset */
+ if (pf_begin_altq(&ticket))
+ return;
+
+ /* Copy the current active set */
+ TAILQ_FOREACH(a1, pf_altqs_active, entries) {
+ a2 = pool_get(&pf_altq_pl, PR_NOWAIT);
+ if (a2 == NULL) {
+ error = ENOMEM;
+ break;
+ }
+ bcopy(a1, a2, sizeof(struct pf_altq));
+
+ if (a2->qname[0] != 0) {
+ if ((a2->qid = pf_qname2qid(a2->qname)) == 0) {
+ error = EBUSY;
+ pool_put(&pf_altq_pl, a2);
+ break;
+ }
+ a2->altq_disc = NULL;
+ TAILQ_FOREACH(a3, pf_altqs_inactive, entries) {
+ if (strncmp(a3->ifname, a2->ifname,
+ IFNAMSIZ) == 0 && a3->qname[0] == 0) {
+ a2->altq_disc = a3->altq_disc;
+ break;
+ }
+ }
+ }
+ /* Deactivate the interface in question */
+ a2->local_flags &= ~PFALTQ_FLAG_IF_REMOVED;
+ if ((ifp1 = ifunit(a2->ifname)) == NULL ||
+ (remove && ifp1 == ifp)) {
+ a2->local_flags |= PFALTQ_FLAG_IF_REMOVED;
+ } else {
+ PF_UNLOCK();
+ error = altq_add(a2);
+ PF_LOCK();
+
+ if (ticket != ticket_altqs_inactive)
+ error = EBUSY;
+
+ if (error) {
+ pool_put(&pf_altq_pl, a2);
+ break;
+ }
+ }
+
+ TAILQ_INSERT_TAIL(pf_altqs_inactive, a2, entries);
+ }
+
+ if (error != 0)
+ pf_rollback_altq(ticket);
+ else
+ pf_commit_altq(ticket);
+}
+#endif
#endif /* ALTQ */
int
@@ -2273,7 +2363,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
/* enable all altq interfaces on active list */
TAILQ_FOREACH(altq, pf_altqs_active, entries) {
+#ifdef __FreeBSD__
+ if (altq->qname[0] == 0 && (altq->local_flags &
+ PFALTQ_FLAG_IF_REMOVED) == 0) {
+#else
if (altq->qname[0] == 0) {
+#endif
error = pf_enable_altq(altq);
if (error != 0)
break;
@@ -2290,7 +2385,12 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
/* disable all altq interfaces on active list */
TAILQ_FOREACH(altq, pf_altqs_active, entries) {
+#ifdef __FreeBSD__
+ if (altq->qname[0] == 0 && (altq->local_flags &
+ PFALTQ_FLAG_IF_REMOVED) == 0) {
+#else
if (altq->qname[0] == 0) {
+#endif
error = pf_disable_altq(altq);
if (error != 0)
break;
@@ -2316,6 +2416,9 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
bcopy(&pa->altq, altq, sizeof(struct pf_altq));
+#ifdef __FreeBSD__
+ altq->local_flags = 0;
+#endif
/*
* if this is for a queue, find the discipline and
@@ -2327,6 +2430,7 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
pool_put(&pf_altq_pl, altq);
break;
}
+ altq->altq_disc = NULL;
TAILQ_FOREACH(a, pf_altqs_inactive, entries) {
if (strncmp(a->ifname, altq->ifname,
IFNAMSIZ) == 0 && a->qname[0] == 0) {
@@ -2337,11 +2441,17 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
}
#ifdef __FreeBSD__
- PF_UNLOCK();
+ struct ifnet *ifp;
+
+ if ((ifp = ifunit(altq->ifname)) == NULL) {
+ altq->local_flags |= PFALTQ_FLAG_IF_REMOVED;
+ } else {
+ PF_UNLOCK();
#endif
error = altq_add(altq);
#ifdef __FreeBSD__
- PF_LOCK();
+ PF_LOCK();
+ }
#endif
if (error) {
pool_put(&pf_altq_pl, altq);
@@ -2414,6 +2524,10 @@ pfioctl(dev_t dev, u_long cmd, caddr_t addr, int flags, struct proc *p)
break;
}
#ifdef __FreeBSD__
+ if ((altq->local_flags & PFALTQ_FLAG_IF_REMOVED) != 0) {
+ error = ENXIO;
+ break;
+ }
PF_UNLOCK();
#endif
error = altq_getqstats(altq, pq->buf, &nbytes);
OpenPOWER on IntegriCloud