From owner-svn-src-all@freebsd.org Sat Apr 28 13:16:59 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 714DDFAEC5B; Sat, 28 Apr 2018 13:16:59 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 21D878295A; Sat, 28 Apr 2018 13:16:59 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 180FB162CD; Sat, 28 Apr 2018 13:16:59 +0000 (UTC) (envelope-from kp@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w3SDGwwS033673; Sat, 28 Apr 2018 13:16:58 GMT (envelope-from kp@FreeBSD.org) Received: (from kp@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w3SDGwC9033672; Sat, 28 Apr 2018 13:16:58 GMT (envelope-from kp@FreeBSD.org) Message-Id: <201804281316.w3SDGwC9033672@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: kp set sender to kp@FreeBSD.org using -f From: Kristof Provost Date: Sat, 28 Apr 2018 13:16:58 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r333084 - head/sbin/pfctl X-SVN-Group: head X-SVN-Commit-Author: kp X-SVN-Commit-Paths: head/sbin/pfctl X-SVN-Commit-Revision: 333084 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 28 Apr 2018 13:16:59 -0000 Author: kp Date: Sat Apr 28 13:16:58 2018 New Revision: 333084 URL: https://svnweb.freebsd.org/changeset/base/333084 Log: 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 Modified: head/sbin/pfctl/pfctl.c Modified: head/sbin/pfctl/pfctl.c ============================================================================== --- head/sbin/pfctl/pfctl.c Sat Apr 28 12:24:05 2018 (r333083) +++ head/sbin/pfctl/pfctl.c Sat Apr 28 13:16:58 2018 (r333084) @@ -67,6 +67,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 *); @@ -106,6 +109,7 @@ const char *pfctl_lookup_option(char *, const char * c static struct pf_anchor_global pf_anchors; static struct pf_anchor pf_main_anchor; +static struct pfr_buffer skip_b; static const char *clearopt; static char *rulesopt; @@ -295,6 +299,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; @@ -1479,6 +1521,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))) || @@ -1889,6 +1933,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); @@ -2347,7 +2392,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)) &&