1
|
diff --git a/sbin/pfctl/pfctl.c b/sbin/pfctl/pfctl.c
|
2
|
index 1e957f6..2903e32 100644
|
3
|
--- a/sbin/pfctl/pfctl.c
|
4
|
+++ b/sbin/pfctl/pfctl.c
|
5
|
@@ -124,6 +124,8 @@ int src_node_killers;
|
6
|
char *src_node_kill[2];
|
7
|
int state_killers;
|
8
|
char *state_kill[2];
|
9
|
+int if_kill;
|
10
|
+char *if_gw_kill;
|
11
|
int loadopt;
|
12
|
int altqsupport;
|
13
|
|
14
|
@@ -389,10 +391,46 @@ pfctl_clear_states(int dev, const char *iface, int opts)
|
15
|
sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname))
|
16
|
errx(1, "invalid interface: %s", iface);
|
17
|
|
18
|
- if (ioctl(dev, DIOCCLRSTATES, &psk))
|
19
|
- err(1, "DIOCCLRSTATES");
|
20
|
- if ((opts & PF_OPT_QUIET) == 0)
|
21
|
- fprintf(stderr, "%d states cleared\n", psk.psk_killed);
|
22
|
+ if (if_kill) {
|
23
|
+ struct addrinfo *res, *resp;
|
24
|
+ u_int killed;
|
25
|
+ int ret_ga;
|
26
|
+
|
27
|
+ if ((ret_ga = getaddrinfo(if_gw_kill, NULL, NULL, &res))) {
|
28
|
+ errx(1, "getaddrinfo: %s", gai_strerror(ret_ga));
|
29
|
+ /* NOTREACHED */
|
30
|
+ }
|
31
|
+ killed = 0;
|
32
|
+ for (resp = res; resp; resp = resp->ai_next) {
|
33
|
+ if (resp->ai_addr == NULL)
|
34
|
+ continue;
|
35
|
+
|
36
|
+ psk.psk_af = resp->ai_family;
|
37
|
+
|
38
|
+ if (psk.psk_af == AF_INET)
|
39
|
+ psk.psk_src.addr.v.a.addr.v4 =
|
40
|
+ ((struct sockaddr_in *)resp->ai_addr)->sin_addr;
|
41
|
+ else if (psk.psk_af == AF_INET6)
|
42
|
+ psk.psk_src.addr.v.a.addr.v6 =
|
43
|
+ ((struct sockaddr_in6 *)resp->ai_addr)->
|
44
|
+ sin6_addr;
|
45
|
+ else
|
46
|
+ errx(1, "Unknown address family %d", psk.psk_af);
|
47
|
+
|
48
|
+ if (ioctl(dev, DIOCCLRSTATES, &psk))
|
49
|
+ err(1, "DIOCCLRSTATES");
|
50
|
+ if ((opts & PF_OPT_QUIET) == 0)
|
51
|
+ killed += psk.psk_af;
|
52
|
+ }
|
53
|
+ if ((opts & PF_OPT_QUIET) == 0)
|
54
|
+ fprintf(stderr, "%d states cleared\n", killed);
|
55
|
+ } else {
|
56
|
+ if (ioctl(dev, DIOCCLRSTATES, &psk))
|
57
|
+ err(1, "DIOCCLRSTATES");
|
58
|
+ if ((opts & PF_OPT_QUIET) == 0)
|
59
|
+ fprintf(stderr, "%d states cleared\n", psk.psk_af);
|
60
|
+ }
|
61
|
+
|
62
|
return (0);
|
63
|
}
|
64
|
|
65
|
@@ -2024,7 +2062,7 @@ main(int argc, char *argv[])
|
66
|
usage();
|
67
|
|
68
|
while ((ch = getopt(argc, argv,
|
69
|
- "a:AdD:eqf:F:ghi:k:K:mnNOo:Pp:rRs:t:T:vx:y:z")) != -1) {
|
70
|
+ "a:AdD:eqf:F:gG:hi:k:K:mnNOo:Pp:rRs:t:T:vx:y:z")) != -1) {
|
71
|
switch (ch) {
|
72
|
case 'a':
|
73
|
anchoropt = optarg;
|
74
|
@@ -2093,6 +2131,16 @@ main(int argc, char *argv[])
|
75
|
case 'g':
|
76
|
opts |= PF_OPT_DEBUG;
|
77
|
break;
|
78
|
+ case 'G':
|
79
|
+ if (if_kill) {
|
80
|
+ warnx("can only specify -b twice");
|
81
|
+ usage();
|
82
|
+ /* NOTREACHED */
|
83
|
+ }
|
84
|
+ if_gw_kill = optarg;
|
85
|
+ if_kill++;
|
86
|
+ mode = O_RDWR;
|
87
|
+ break;
|
88
|
case 'A':
|
89
|
loadopt |= PFCTL_FLAG_ALTQ;
|
90
|
break;
|
91
|
diff --git a/sys/netpfil/pf/pf.c b/sys/netpfil/pf/pf.c
|
92
|
index a4134ca..cb38fcb 100644
|
93
|
--- a/sys/netpfil/pf/pf.c
|
94
|
+++ b/sys/netpfil/pf/pf.c
|
95
|
@@ -337,8 +337,8 @@ VNET_DEFINE(struct pf_limit, pf_limits[PF_LIMIT_MAX]);
|
96
|
return (PF_PASS); \
|
97
|
} while (0)
|
98
|
|
99
|
-#define BOUND_IFACE(r, k) \
|
100
|
- ((r)->rule_flag & PFRULE_IFBOUND) ? (k) : V_pfi_all
|
101
|
+#define BOUND_IFACE(r, k) k
|
102
|
+ /* ((r)->rule_flag & PFRULE_IFBOUND) ? (k) : V_pfi_all */
|
103
|
|
104
|
#define STATE_INC_COUNTERS(s) \
|
105
|
do { \
|
106
|
diff --git a/sys/netpfil/pf/pf_ioctl.c b/sys/netpfil/pf/pf_ioctl.c
|
107
|
index 4c0f1f5..1b94992 100644
|
108
|
--- a/sys/netpfil/pf/pf_ioctl.c
|
109
|
+++ b/sys/netpfil/pf/pf_ioctl.c
|
110
|
@@ -66,6 +66,8 @@ __FBSDID("$FreeBSD$");
|
111
|
#include <net/route.h>
|
112
|
#include <net/pfil.h>
|
113
|
#include <net/pfvar.h>
|
114
|
+#define TCPSTATES
|
115
|
+#include <netinet/tcp_fsm.h>
|
116
|
#include <net/if_pfsync.h>
|
117
|
#include <net/if_pflog.h>
|
118
|
|
119
|
@@ -1598,6 +1600,7 @@ DIOCCHANGERULE_error:
|
120
|
|
121
|
case DIOCCLRSTATES: {
|
122
|
struct pf_state *s;
|
123
|
+ struct pf_state_key *sk;
|
124
|
struct pfioc_state_kill *psk = (struct pfioc_state_kill *)addr;
|
125
|
u_int i, killed = 0;
|
126
|
|
127
|
@@ -1607,6 +1610,7 @@ DIOCCHANGERULE_error:
|
128
|
relock_DIOCCLRSTATES:
|
129
|
PF_HASHROW_LOCK(ih);
|
130
|
LIST_FOREACH(s, &ih->states, entry)
|
131
|
+ sk = s->key[PF_SK_WIRE];
|
132
|
if (!psk->psk_ifname[0] ||
|
133
|
!strcmp(psk->psk_ifname,
|
134
|
s->kif->pfik_name)) {
|
135
|
@@ -1618,6 +1622,20 @@ relock_DIOCCLRSTATES:
|
136
|
pf_unlink_state(s, PF_ENTER_LOCKED);
|
137
|
killed++;
|
138
|
goto relock_DIOCCLRSTATES;
|
139
|
+ } else if (sk->af == psk->psk_af &&
|
140
|
+ !PF_AZERO(&psk->psk_src.addr.v.a.addr, psk->psk_af) &&
|
141
|
+ !PF_AZERO(&s->rt_addr, sk->af) &&
|
142
|
+ PF_AEQ(&psk->psk_src.addr.v.a.addr, &s->rt_addr, sk->af)) {
|
143
|
+ if (sk->proto == IPPROTO_TCP)
|
144
|
+ s->src.state = PF_TCPS_PROXY_DST; /* XXX: Hack to send a RST back to the host */
|
145
|
+ /*
|
146
|
+ * Don't send out individual
|
147
|
+ * delete messages.
|
148
|
+ */
|
149
|
+ s->state_flags |= PFSTATE_NOSYNC;
|
150
|
+ pf_unlink_state(s, PF_ENTER_LOCKED);
|
151
|
+ killed++;
|
152
|
+ goto relock_DIOCCLRSTATES;
|
153
|
}
|
154
|
PF_HASHROW_UNLOCK(ih);
|
155
|
}
|