From owner-freebsd-pf@FreeBSD.ORG Thu Mar 28 14:10:02 2013 Return-Path: Delivered-To: freebsd-pf@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 30FD5B42; Thu, 28 Mar 2013 14:10:02 +0000 (UTC) (envelope-from longwitz@incore.de) Received: from dss.incore.de (dss.incore.de [195.145.1.138]) by mx1.freebsd.org (Postfix) with ESMTP id B5C9FA51; Thu, 28 Mar 2013 14:10:01 +0000 (UTC) Received: from inetmail.dmz (inetmail.dmz [10.3.0.3]) by dss.incore.de (Postfix) with ESMTP id 0025C5DE81; Thu, 28 Mar 2013 15:03:28 +0100 (CET) X-Virus-Scanned: amavisd-new at incore.de Received: from dss.incore.de ([10.3.0.3]) by inetmail.dmz (inetmail.dmz [10.3.0.3]) (amavisd-new, port 10024) with LMTP id 6EJqRlHNY3jp; Thu, 28 Mar 2013 15:03:27 +0100 (CET) Received: from mail.incore (fwintern.dmz [10.0.0.253]) by dss.incore.de (Postfix) with ESMTP id B686E5DE9B; Thu, 28 Mar 2013 15:03:27 +0100 (CET) Received: from bsdlo.incore (bsdlo.incore [192.168.0.84]) by mail.incore (Postfix) with ESMTP id 97D3350879; Thu, 28 Mar 2013 15:03:27 +0100 (CET) Message-ID: <51544DAF.7000203@incore.de> Date: Thu, 28 Mar 2013 15:03:27 +0100 From: Andreas Longwitz User-Agent: Thunderbird 2.0.0.19 (X11/20090113) MIME-Version: 1.0 To: =?ISO-8859-15?Q?Ermal_Lu=E7i?= , freebsd-pf@freebsd.org Subject: Re: [patch] Reloading pf rules breaks connections on lo0 References: <5134C218.6060701@incore.de> <5149BE75.3040308@incore.de> <5149E3A8.3020608@incore.de> In-Reply-To: Content-Type: text/plain; charset=ISO-8859-15 Content-Transfer-Encoding: 8bit X-BeenThere: freebsd-pf@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "Technical discussion and general questions about packet filter \(pf\)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 28 Mar 2013 14:10:02 -0000 Ermal Luçi wrote: > > I say intended because so it behaves on the upstream. > By introducing another not needed option you introduce another hack on > top of the already hackish 'set skip' one. > > The correct 'fix' for it to behave correctly is to fetch the interface > list from pf(4) and verify if something needs to be cleared or not. > You can call pfi_get_ifaces and compare it with the defined 'set skip' > rules. > > That is easier than adding a new option. > I agree with your statements completely. The following patch for pfctl.c solves for me the lo0 breaking problem without introducing a new option. The patched pfctl clears the skip flag exactly for those actual skip interfaces not longer included in the new pf.conf anymore. --- pfctl.c.orig 2013-01-14 15:17:48.000000000 +0100 +++ pfctl.c 2013-03-27 22:01:37.000000000 +0100 @@ -67,6 +67,9 @@ 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 *); @@ -101,10 +104,13 @@ struct pf_ruleset *, int, int); int pfctl_load_rule(struct pfctl *, char *, struct pf_rule *, int); const char *pfctl_lookup_option(char *, const char **); +static void radix_perror(void); struct pf_anchor_global pf_anchors; struct pf_anchor pf_main_anchor; +struct pfr_buffer skip_b; + const char *clearopt; char *rulesopt; const char *showopt; @@ -296,6 +302,53 @@ return (0); } +void +radix_perror(void) +{ + extern char *__progname; + fprintf(stderr, "%s: %s.\n", __progname, pfr_strerror(errno)); +} + +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)) { + radix_perror(); + return (1); + } + 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) { @@ -1437,6 +1490,8 @@ 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))) || @@ -1861,6 +1916,7 @@ } else { if (ioctl(pf->dev, DIOCSETIFFLAG, &pi)) err(1, "DIOCSETIFFLAG"); + pfctl_check_skip_ifaces(ifname); } } return (0); @@ -2340,7 +2396,7 @@ } 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)) && -- Andreas Longwitz