Bug #8555 » FreeBSD-src.patch
| sbin/pfctl/pf_print_state.c | ||
|---|---|---|
| 352 | 352 |
bcopy(&s->id, &id, sizeof(u_int64_t)); |
| 353 | 353 |
printf(" id: %016jx creatorid: %08x",
|
| 354 | 354 |
(uintmax_t )be64toh(id), ntohl(s->creatorid)); |
| 355 |
printf(" gateway: ");
|
|
| 356 |
print_host(&s->rt_addr, 0, s->af, opts); |
|
| 355 | 357 |
printf("\n");
|
| 358 | ||
| 356 | 359 |
} |
| 357 | 360 |
} |
| 358 | 361 | |
| sbin/pfctl/pfctl.8 | ||
|---|---|---|
| 35 | 35 |
.Sh SYNOPSIS |
| 36 | 36 |
.Nm pfctl |
| 37 | 37 |
.Bk -words |
| 38 |
.Op Fl AdeghmNnOPqRrvz |
|
| 38 |
.Op Fl AdeghMmNnOPqRrvz
|
|
| 39 | 39 |
.Op Fl a Ar anchor |
| 40 | 40 |
.Oo Fl D Ar macro Ns = |
| 41 | 41 |
.Ar value Oc |
| ... | ... | |
| 45 | 45 |
.Op Fl K Ar host | network |
| 46 | 46 |
.Xo |
| 47 | 47 |
.Oo Fl k |
| 48 |
.Ar host | network | label | id |
|
| 48 |
.Ar host | network | label | id | gateway
|
|
| 49 | 49 |
.Oc Xc |
| 50 | 50 |
.Op Fl o Ar level |
| 51 | 51 |
.Op Fl p Ar device |
| ... | ... | |
| 256 | 256 |
entries from the first host/network to the second. |
| 257 | 257 |
.It Xo |
| 258 | 258 |
.Fl k |
| 259 |
.Ar host | network | label | id |
|
| 259 |
.Ar host | network | label | id | gateway
|
|
| 260 | 260 |
.Xc |
| 261 | 261 |
Kill all of the state entries matching the specified |
| 262 | 262 |
.Ar host , |
| 263 | 263 |
.Ar network , |
| 264 | 264 |
.Ar label , |
| 265 |
.Ar id , |
|
| 265 | 266 |
or |
| 266 |
.Ar id .
|
|
| 267 |
.Ar gateway.
|
|
| 267 | 268 |
.Pp |
| 268 | 269 |
For example, to kill all of the state entries originating from |
| 269 | 270 |
.Dq host : |
| ... | ... | |
| 317 | 318 |
firewall with hostid 00000002 use: |
| 318 | 319 |
.Pp |
| 319 | 320 |
.Dl # pfctl -k id -k 4823e84500000018/2 |
| 321 |
.Pp |
|
| 322 |
It is also possible to kill states created from a rule with the route-to/reply-to |
|
| 323 |
parameter set to route the connection through a particular gateway. |
|
| 324 |
Note that rules routing via a the default routing table (not via a route-to |
|
| 325 |
rule) will have their rt_addr set as 0.0.0.0 or ::. To kill all states using |
|
| 326 |
a gateway of 192.168.0.1 use: |
|
| 327 |
.Pp |
|
| 328 |
.Dl # pfctl -k gateway -k 192.168.0.1 |
|
| 329 |
.Pp |
|
| 330 |
A network prefix length can also be specified. |
|
| 331 |
To kill all states using a gateway in 192.168.0.0/24: |
|
| 332 |
.Pp |
|
| 333 |
.Dl # pfctl -k gateway -k 192.168.0.0/24 |
|
| 334 |
.It Fl M |
|
| 335 |
Kill matching states in the opposite direction (on other interfaces) when killing states. |
|
| 336 |
This applies to states killed using the -k option and also will apply to the flush |
|
| 337 |
command when flushing states. This is useful when an interface is specified when flushing states. Example: |
|
| 338 |
.Pp |
|
| 339 |
.Dl # pfctl -M -i interface -Fs |
|
| 320 | 340 |
.It Fl m |
| 321 | 341 |
Merge in explicitly given options without resetting those |
| 322 | 342 |
which are omitted. |
| sbin/pfctl/pfctl.c | ||
|---|---|---|
| 74 | 74 |
void pfctl_addrprefix(char *, struct pf_addr *); |
| 75 | 75 |
int pfctl_kill_src_nodes(int, const char *, int); |
| 76 | 76 |
int pfctl_net_kill_states(int, const char *, int); |
| 77 |
int pfctl_gateway_kill_states(int, const char *, int); |
|
| 77 | 78 |
int pfctl_label_kill_states(int, const char *, int); |
| 78 | 79 |
int pfctl_kill_schedule(int, const char *, int); |
| 79 | 80 |
int pfctl_id_kill_states(int, const char *, int); |
| ... | ... | |
| 235 | 236 |
extern char *__progname; |
| 236 | 237 | |
| 237 | 238 |
fprintf(stderr, |
| 238 |
"usage: %s [-AdeghmNnOPqRrvz] [-a anchor] [-D macro=value] [-F modifier]\n" |
|
| 239 |
"usage: %s [-AdeghMmNnOPqRrvz] [-a anchor] [-D macro=value] [-F modifier]\n"
|
|
| 239 | 240 |
"\t[-f file] [-i interface] [-K host | network]\n" |
| 240 | 241 |
"\t[-k host | network | label | id] [-o level] [-p device]\n" |
| 241 | 242 |
"\t[-s modifier] [-t table -T command [address ...]] [-x level]\n", |
| ... | ... | |
| 380 | 381 |
struct pfioc_state_kill psk; |
| 381 | 382 | |
| 382 | 383 |
memset(&psk, 0, sizeof(psk)); |
| 383 |
if (iface != NULL && strlcpy(psk.psk_ifname, iface, |
|
| 384 |
sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) |
|
| 385 |
errx(1, "invalid interface: %s", iface); |
|
| 384 |
if (iface != NULL) {
|
|
| 385 |
if (strlcpy(psk.psk_ifname, iface, |
|
| 386 |
sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) {
|
|
| 387 |
errx(1, "invalid interface: %s", iface); |
|
| 388 |
} else if (opts & PF_OPT_KILLMATCH) {
|
|
| 389 |
psk.psk_flag |= PSK_FLAG_KILLMATCH; |
|
| 390 |
} |
|
| 391 |
} |
|
| 386 | 392 | |
| 387 | 393 |
if (ioctl(dev, DIOCCLRSTATES, &psk)) |
| 388 | 394 |
err(1, "DIOCCLRSTATES"); |
| ... | ... | |
| 564 | 570 |
sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) |
| 565 | 571 |
errx(1, "invalid interface: %s", iface); |
| 566 | 572 | |
| 573 |
if (opts & PF_OPT_KILLMATCH) {
|
|
| 574 |
psk.psk_flag |= PSK_FLAG_KILLMATCH; |
|
| 575 |
} |
|
| 576 | ||
| 567 | 577 |
pfctl_addrprefix(state_kill[0], &psk.psk_src.addr.v.a.mask); |
| 568 | 578 | |
| 569 | 579 |
if ((ret_ga = getaddrinfo(state_kill[0], NULL, NULL, &res[0]))) {
|
| ... | ... | |
| 650 | 660 |
return (0); |
| 651 | 661 |
} |
| 652 | 662 | |
| 663 |
int |
|
| 664 |
pfctl_gateway_kill_states(int dev, const char *iface, int opts) |
|
| 665 |
{
|
|
| 666 |
struct pfioc_state_kill psk; |
|
| 667 |
struct addrinfo *res, *resp; |
|
| 668 |
struct sockaddr last_src; |
|
| 669 |
int killed; |
|
| 670 |
int ret_ga; |
|
| 671 | ||
| 672 |
killed = 0; |
|
| 673 | ||
| 674 |
memset(&psk, 0, sizeof(psk)); |
|
| 675 |
memset(&psk.psk_rt_addr.addr.v.a.mask, 0xff, |
|
| 676 |
sizeof(psk.psk_rt_addr.addr.v.a.mask)); |
|
| 677 |
memset(&last_src, 0xff, sizeof(last_src)); |
|
| 678 |
if (iface != NULL && strlcpy(psk.psk_ifname, iface, |
|
| 679 |
sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) |
|
| 680 |
errx(1, "invalid interface: %s", iface); |
|
| 681 | ||
| 682 |
if (opts & PF_OPT_KILLMATCH) {
|
|
| 683 |
psk.psk_flag |= PSK_FLAG_KILLMATCH; |
|
| 684 |
} |
|
| 685 | ||
| 686 |
pfctl_addrprefix(state_kill[1], &psk.psk_rt_addr.addr.v.a.mask); |
|
| 687 | ||
| 688 |
if ((ret_ga = getaddrinfo(state_kill[1], NULL, NULL, &res))) {
|
|
| 689 |
errx(1, "getaddrinfo: %s", gai_strerror(ret_ga)); |
|
| 690 |
/* NOTREACHED */ |
|
| 691 |
} |
|
| 692 |
for (resp = res; resp; resp = resp->ai_next) {
|
|
| 693 |
if (resp->ai_addr == NULL) |
|
| 694 |
continue; |
|
| 695 |
/* We get lots of duplicates. Catch the easy ones */ |
|
| 696 |
if (memcmp(&last_src, resp->ai_addr, sizeof(last_src)) == 0) |
|
| 697 |
continue; |
|
| 698 |
last_src = *(struct sockaddr *)resp->ai_addr; |
|
| 699 | ||
| 700 |
psk.psk_af = resp->ai_family; |
|
| 701 | ||
| 702 |
if (psk.psk_af == AF_INET) |
|
| 703 |
psk.psk_rt_addr.addr.v.a.addr.v4 = |
|
| 704 |
((struct sockaddr_in *)resp->ai_addr)->sin_addr; |
|
| 705 |
else if (psk.psk_af == AF_INET6) |
|
| 706 |
psk.psk_rt_addr.addr.v.a.addr.v6 = |
|
| 707 |
((struct sockaddr_in6 *)resp->ai_addr)-> |
|
| 708 |
sin6_addr; |
|
| 709 |
else |
|
| 710 |
errx(1, "Unknown address family %d", psk.psk_af); |
|
| 711 | ||
| 712 |
if (ioctl(dev, DIOCKILLSTATES, &psk)) |
|
| 713 |
err(1, "DIOCKILLSTATES"); |
|
| 714 |
killed += psk.psk_killed; |
|
| 715 |
} |
|
| 716 | ||
| 717 |
freeaddrinfo(res); |
|
| 718 | ||
| 719 |
if ((opts & PF_OPT_QUIET) == 0) |
|
| 720 |
fprintf(stderr, "killed %d states\n", killed); |
|
| 721 |
return (0); |
|
| 722 |
} |
|
| 723 | ||
| 653 | 724 |
int |
| 654 | 725 |
pfctl_kill_schedule(int dev, const char *sched, int opts) |
| 655 | 726 |
{
|
| ... | ... | |
| 679 | 750 |
usage(); |
| 680 | 751 |
} |
| 681 | 752 |
memset(&psk, 0, sizeof(psk)); |
| 753 | ||
| 754 |
if (opts & PF_OPT_KILLMATCH) {
|
|
| 755 |
psk.psk_flag |= PSK_FLAG_KILLMATCH; |
|
| 756 |
} |
|
| 757 | ||
| 682 | 758 |
if (iface != NULL && strlcpy(psk.psk_ifname, iface, |
| 683 | 759 |
sizeof(psk.psk_ifname)) >= sizeof(psk.psk_ifname)) |
| 684 | 760 |
errx(1, "invalid interface: %s", iface); |
| ... | ... | |
| 707 | 783 |
} |
| 708 | 784 | |
| 709 | 785 |
memset(&psk, 0, sizeof(psk)); |
| 786 | ||
| 787 |
if (opts & PF_OPT_KILLMATCH) {
|
|
| 788 |
psk.psk_flag |= PSK_FLAG_KILLMATCH; |
|
| 789 |
} |
|
| 790 | ||
| 710 | 791 |
if ((sscanf(state_kill[1], "%jx/%x", |
| 711 | 792 |
&psk.psk_pfcmp.id, &psk.psk_pfcmp.creatorid)) == 2) |
| 712 | 793 |
HTONL(psk.psk_pfcmp.creatorid); |
| ... | ... | |
| 2027 | 2108 |
usage(); |
| 2028 | 2109 | |
| 2029 | 2110 |
while ((ch = getopt(argc, argv, |
| 2030 |
"a:AdD:eqf:F:ghi:k:K:mnNOo:Pp:rRs:t:T:vx:y:z")) != -1) {
|
|
| 2111 |
"a:AdD:eqf:F:ghi:k:K:mMnNOo:Pp:rRs:t:T:vx:y:z")) != -1) {
|
|
| 2031 | 2112 |
switch (ch) {
|
| 2032 | 2113 |
case 'a': |
| 2033 | 2114 |
anchoropt = optarg; |
| ... | ... | |
| 2080 | 2161 |
case 'm': |
| 2081 | 2162 |
opts |= PF_OPT_MERGE; |
| 2082 | 2163 |
break; |
| 2164 |
case 'M': |
|
| 2165 |
opts |= PF_OPT_KILLMATCH; |
|
| 2166 |
break; |
|
| 2083 | 2167 |
case 'n': |
| 2084 | 2168 |
opts |= PF_OPT_NOACTION; |
| 2085 | 2169 |
break; |
| ... | ... | |
| 2348 | 2432 |
pfctl_label_kill_states(dev, ifaceopt, opts); |
| 2349 | 2433 |
else if (!strcmp(state_kill[0], "id")) |
| 2350 | 2434 |
pfctl_id_kill_states(dev, ifaceopt, opts); |
| 2435 |
else if (!strcmp(state_kill[0], "gateway")) |
|
| 2436 |
pfctl_gateway_kill_states(dev, ifaceopt, opts); |
|
| 2351 | 2437 |
else |
| 2352 | 2438 |
pfctl_net_kill_states(dev, ifaceopt, opts); |
| 2353 | 2439 |
} |
| sbin/pfctl/pfctl_parser.h | ||
|---|---|---|
| 51 | 51 |
#define PF_OPT_NUMERIC 0x1000 |
| 52 | 52 |
#define PF_OPT_MERGE 0x2000 |
| 53 | 53 |
#define PF_OPT_RECURSE 0x4000 |
| 54 |
#define PF_OPT_KILLMATCH 0x8000 |
|
| 54 | 55 | |
| 55 | 56 |
#define PF_TH_ALL 0xFF |
| 56 | 57 | |
| share/man/man4/pf.4 | ||
|---|---|---|
| 338 | 338 |
Remove matching entries from the state table. |
| 339 | 339 |
This ioctl returns the number of killed states in |
| 340 | 340 |
.Va psk_killed . |
| 341 |
The psk_flag can be set with PSK_FLAG_KILLMATCH to also look |
|
| 342 |
for and kill a matching state in the opposite direction for |
|
| 343 |
each state matching the original criteria. |
|
| 341 | 344 |
.Bd -literal |
| 342 | 345 |
struct pfioc_state_kill {
|
| 343 | 346 |
struct pf_state_cmp psk_pfcmp; |
| ... | ... | |
| 345 | 348 |
int psk_proto; |
| 346 | 349 |
struct pf_rule_addr psk_src; |
| 347 | 350 |
struct pf_rule_addr psk_dst; |
| 351 |
struct pf_rule_addr psk_rt_addr; |
|
| 348 | 352 |
char psk_ifname[IFNAMSIZ]; |
| 349 | 353 |
char psk_label[PF_RULE_LABEL_SIZE]; |
| 354 |
int psk_flag; |
|
| 350 | 355 |
u_int psk_killed; |
| 351 | 356 |
}; |
| 352 | 357 |
.Ed |
| ... | ... | |
| 358 | 363 |
.Va psk_af , |
| 359 | 364 |
.Va psk_proto , |
| 360 | 365 |
.Va psk_src , |
| 366 |
.Va psk_dst , |
|
| 361 | 367 |
and |
| 362 |
.Va psk_dst
|
|
| 368 |
.Va psk_rt_addr
|
|
| 363 | 369 |
fields of the |
| 364 | 370 |
.Vt pfioc_state_kill |
| 365 | 371 |
structure. |
| sys/net/pfvar.h | ||
|---|---|---|
| 1309 | 1309 |
int psk_proto; |
| 1310 | 1310 |
struct pf_rule_addr psk_src; |
| 1311 | 1311 |
struct pf_rule_addr psk_dst; |
| 1312 |
struct pf_rule_addr psk_rt_addr; |
|
| 1312 | 1313 |
char psk_ifname[IFNAMSIZ]; |
| 1313 | 1314 |
char psk_label[PF_RULE_LABEL_SIZE]; |
| 1315 |
int psk_flag; |
|
| 1314 | 1316 |
u_int psk_killed; |
| 1315 | 1317 |
}; |
| 1316 | 1318 | |
| 1319 |
#define PSK_FLAG_KILLMATCH 0x0001 |
|
| 1320 | ||
| 1317 | 1321 |
struct pfioc_schedule_kill {
|
| 1318 | 1322 |
int numberkilled; |
| 1319 | 1323 |
char schedule[PF_RULE_LABEL_SIZE]; |
| sys/netpfil/pf/pf_ioctl.c | ||
|---|---|---|
| 1655 | 1655 |
* Don't send out individual |
| 1656 | 1656 |
* delete messages. |
| 1657 | 1657 |
*/ |
| 1658 |
if (psk->psk_flag & PSK_FLAG_KILLMATCH) {
|
|
| 1659 |
u_int dir; |
|
| 1660 |
struct pf_state *match; |
|
| 1661 |
struct pf_state_key_cmp key; |
|
| 1662 |
int idx, more = 0; |
|
| 1663 | ||
| 1664 |
bzero(&key, sizeof(key)); |
|
| 1665 | ||
| 1666 |
if (s->direction == PF_OUT) {
|
|
| 1667 |
dir = PF_IN; |
|
| 1668 |
idx = PF_SK_STACK; |
|
| 1669 |
} else {
|
|
| 1670 |
dir = PF_OUT; |
|
| 1671 |
idx = PF_SK_WIRE; |
|
| 1672 |
} |
|
| 1673 | ||
| 1674 |
key.af = s->key[idx]->af; |
|
| 1675 |
key.proto = s->key[idx]->proto; |
|
| 1676 |
PF_ACPY(&key.addr[0], &s->key[idx]->addr[1],key.af); |
|
| 1677 |
key.port[0] = s->key[idx]->port[1]; |
|
| 1678 |
PF_ACPY(&key.addr[1], &s->key[idx]->addr[0],key.af); |
|
| 1679 |
key.port[1] = s->key[idx]->port[0]; |
|
| 1680 | ||
| 1681 |
match = pf_find_state_all(&key, dir, &more); |
|
| 1682 |
if (match && !more) {
|
|
| 1683 |
pf_unlink_state(match, 0); |
|
| 1684 |
killed++; |
|
| 1685 |
} |
|
| 1686 | ||
| 1687 |
} |
|
| 1688 | ||
| 1658 | 1689 |
s->state_flags |= PFSTATE_NOSYNC; |
| 1659 | 1690 |
pf_unlink_state(s, PF_ENTER_LOCKED); |
| 1660 | 1691 |
killed++; |
| ... | ... | |
| 1717 | 1748 |
&psk->psk_dst.addr.v.a.addr, |
| 1718 | 1749 |
&psk->psk_dst.addr.v.a.mask, |
| 1719 | 1750 |
dstaddr, sk->af) && |
| 1751 |
PF_MATCHA(psk->psk_rt_addr.neg, |
|
| 1752 |
&psk->psk_rt_addr.addr.v.a.addr, |
|
| 1753 |
&psk->psk_rt_addr.addr.v.a.mask, |
|
| 1754 |
&s->rt_addr, sk->af) && |
|
| 1720 | 1755 |
(psk->psk_src.port_op == 0 || |
| 1721 | 1756 |
pf_match_port(psk->psk_src.port_op, |
| 1722 | 1757 |
psk->psk_src.port[0], psk->psk_src.port[1], |
| ... | ... | |
| 1732 | 1767 |
(!psk->psk_ifname[0] || |
| 1733 | 1768 |
!strcmp(psk->psk_ifname, |
| 1734 | 1769 |
s->kif->pfik_name))) {
|
| 1770 |
if (psk->psk_flag & PSK_FLAG_KILLMATCH) {
|
|
| 1771 |
u_int dir; |
|
| 1772 |
struct pf_state *match; |
|
| 1773 |
struct pf_state_key_cmp key; |
|
| 1774 |
int idx, more = 0; |
|
| 1775 | ||
| 1776 |
bzero(&key, sizeof(key)); |
|
| 1777 | ||
| 1778 |
if (s->direction == PF_OUT) {
|
|
| 1779 |
dir = PF_IN; |
|
| 1780 |
idx = PF_SK_STACK; |
|
| 1781 |
} else {
|
|
| 1782 |
dir = PF_OUT; |
|
| 1783 |
idx = PF_SK_WIRE; |
|
| 1784 |
} |
|
| 1785 | ||
| 1786 |
key.af = s->key[idx]->af; |
|
| 1787 |
key.proto = s->key[idx]->proto; |
|
| 1788 |
PF_ACPY(&key.addr[0], &s->key[idx]->addr[1],key.af); |
|
| 1789 |
key.port[0] = s->key[idx]->port[1]; |
|
| 1790 |
PF_ACPY(&key.addr[1], &s->key[idx]->addr[0],key.af); |
|
| 1791 |
key.port[1] = s->key[idx]->port[0]; |
|
| 1792 | ||
| 1793 |
match = pf_find_state_all(&key, dir, &more); |
|
| 1794 |
if (match && !more) {
|
|
| 1795 |
pf_unlink_state(match, 0); |
|
| 1796 |
killed++; |
|
| 1797 |
} |
|
| 1798 | ||
| 1799 |
} |
|
| 1735 | 1800 |
pf_unlink_state(s, PF_ENTER_LOCKED); |
| 1736 | 1801 |
killed++; |
| 1737 | 1802 |
goto relock_DIOCKILLSTATES; |