Project

General

Profile

Bug #8555 » FreeBSD-src.patch

Steven Brown, 07/15/2018 09:44 PM

View differences:

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;
(3-3/4)