Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 2 May 2018 22:36:11 +0000 (UTC)
From:      Kristof Provost <kp@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org
Subject:   svn commit: r333187 - stable/10/sbin/pfctl
Message-ID:  <201805022236.w42MaBiw031085@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kp
Date: Wed May  2 22:36:10 2018
New Revision: 333187
URL: https://svnweb.freebsd.org/changeset/base/333187

Log:
  MFC r333084:
  
  pfctl: Don't break connections on skipped interfaces on reload
  
  On reload we used to first flush everything, including the list of skipped
  interfaces.  This can lead to termination of these connections if they send
  packets before the new configuration is applied.
  
  Note that this doesn't currently happen on 12 or 11, because of special EACCES
  handling introduced in r315514. This special behaviour in tcp_output() may
  change, hence the fix in pfctl.
  
  PR:		214613
  Submitted by:	Andreas Longwitz <longwitz at incore.de>

Modified:
  stable/10/sbin/pfctl/pfctl.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/10/sbin/pfctl/pfctl.c
==============================================================================
--- stable/10/sbin/pfctl/pfctl.c	Wed May  2 22:11:16 2018	(r333186)
+++ stable/10/sbin/pfctl/pfctl.c	Wed May  2 22:36:10 2018	(r333187)
@@ -68,6 +68,9 @@ void	 usage(void);
 int	 pfctl_enable(int, int);
 int	 pfctl_disable(int, int);
 int	 pfctl_clear_stats(int, int);
+int	 pfctl_get_skip_ifaces(void);
+int	 pfctl_check_skip_ifaces(char *);
+int	 pfctl_clear_skip_ifaces(struct pfctl *);
 int	 pfctl_clear_interface_flags(int, int);
 int	 pfctl_clear_rules(int, int, char *);
 int	 pfctl_clear_nat(int, int, char *);
@@ -107,6 +110,7 @@ const char	*pfctl_lookup_option(char *, const char **)
 
 struct pf_anchor_global	 pf_anchors;
 struct pf_anchor	 pf_main_anchor;
+static struct pfr_buffer skip_b;
 
 const char	*clearopt;
 char		*rulesopt;
@@ -298,6 +302,44 @@ pfctl_clear_stats(int dev, int opts)
 }
 
 int
+pfctl_get_skip_ifaces(void)
+{
+	bzero(&skip_b, sizeof(skip_b));
+	skip_b.pfrb_type = PFRB_IFACES;
+	for (;;) {
+		pfr_buf_grow(&skip_b, skip_b.pfrb_size);
+		skip_b.pfrb_size = skip_b.pfrb_msize;
+		if (pfi_get_ifaces(NULL, skip_b.pfrb_caddr, &skip_b.pfrb_size))
+			err(1, "pfi_get_ifaces");
+		if (skip_b.pfrb_size <= skip_b.pfrb_msize)
+			break;
+	}
+	return (0);
+}
+
+int
+pfctl_check_skip_ifaces(char *ifname)
+{
+	struct pfi_kif		*p;
+
+	PFRB_FOREACH(p, &skip_b)
+		if ((p->pfik_flags & PFI_IFLAG_SKIP) && !strcmp(ifname, p->pfik_name))
+			p->pfik_flags &= ~PFI_IFLAG_SKIP;
+	return (0);
+}
+
+int
+pfctl_clear_skip_ifaces(struct pfctl *pf)
+{
+	struct pfi_kif		*p;
+
+	PFRB_FOREACH(p, &skip_b)
+		if (p->pfik_flags & PFI_IFLAG_SKIP)
+			pfctl_set_interface_flags(pf, p->pfik_name, PFI_IFLAG_SKIP, 0);
+	return (0);
+}
+
+int
 pfctl_clear_interface_flags(int dev, int opts)
 {
 	struct pfioc_iface	pi;
@@ -1482,6 +1524,8 @@ pfctl_rules(int dev, char *filename, int opts, int opt
 		else
 			goto _error;
 	}
+	if (loadopt & PFCTL_FLAG_OPTION)
+		pfctl_clear_skip_ifaces(&pf);
 
 	if ((pf.loadopt & PFCTL_FLAG_FILTER &&
 	    (pfctl_load_ruleset(&pf, path, rs, PF_RULESET_SCRUB, 0))) ||
@@ -1890,6 +1934,7 @@ pfctl_set_interface_flags(struct pfctl *pf, char *ifna
 		} else {
 			if (ioctl(pf->dev, DIOCSETIFFLAG, &pi))
 				err(1, "DIOCSETIFFLAG");
+			pfctl_check_skip_ifaces(ifname);
 		}
 	}
 	return (0);
@@ -2348,7 +2393,7 @@ main(int argc, char *argv[])
 
 	if ((rulesopt != NULL) && (loadopt & PFCTL_FLAG_OPTION) &&
 	    !anchorname[0])
-		if (pfctl_clear_interface_flags(dev, opts | PF_OPT_QUIET))
+		if (pfctl_get_skip_ifaces())
 			error = 1;
 
 	if (rulesopt != NULL && !(opts & (PF_OPT_MERGE|PF_OPT_NOACTION)) &&



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201805022236.w42MaBiw031085>