untrusted comment: signature from openbsd 5.5 base secret key RWRGy8gxk9N93yf0s8n8AnuMxRTccsW2oR9NO25RY67cg1Oefuhuyi/Gc0wR4SO8D9ChLKUAH2kekcCG7pjCYxTynsq2dR9U/wk= OpenBSD 5.5 errata 14, Nov 17, 2014: A PF rule using an IPv4 address followed by an IPv6 address and then a dynamic address, e.g. "pass from {192.0.2.1 2001:db8::1} to (pppoe0)", will have an incorrect /32 mask applied to the dynamic address. This is the 2nd version of this patch. Apply patch using: signify -Vep /etc/signify/openbsd-55-base.pub -x 014_pfctl.patch.sig \ -m - | (cd /usr/src && patch -p0) Then build and install pfctl: cd /usr/src/sbin/pfctl make obj make make install Index: sbin/pfctl/parse.y =================================================================== RCS file: /cvs/src/sbin/pfctl/parse.y,v retrieving revision 1.631 retrieving revision 1.631.4.1 diff -u -p -r1.631 -r1.631.4.1 --- sbin/pfctl/parse.y 22 Jan 2014 00:21:16 -0000 1.631 +++ sbin/pfctl/parse.y 29 Oct 2014 15:36:15 -0000 1.631.4.1 @@ -5074,7 +5074,7 @@ expand_rule(struct pf_rule *r, int keepr char tagname[PF_TAG_NAME_SIZE]; char match_tagname[PF_TAG_NAME_SIZE]; u_int8_t flags, flagset, keep_state; - struct node_host *srch, *dsth; + struct node_host *srch, *dsth, *osrch, *odsth; struct redirspec binat; struct pf_rule rb; int dir = r->direction; @@ -5165,6 +5165,18 @@ expand_rule(struct pf_rule *r, int keepr r->af, src_host, src_port, dst_host, dst_port, proto->proto); + osrch = odsth = NULL; + if (src_host->addr.type == PF_ADDR_DYNIFTL) { + osrch = src_host; + if ((src_host = gen_dynnode(src_host, r->af)) == NULL) + err(1, "expand_rule: calloc"); + } + if (dst_host->addr.type == PF_ADDR_DYNIFTL) { + odsth = dst_host; + if ((dst_host = gen_dynnode(dst_host, r->af)) == NULL) + err(1, "expand_rule: calloc"); + } + error += check_netmask(src_host, r->af); error += check_netmask(dst_host, r->af); @@ -5314,6 +5326,14 @@ expand_rule(struct pf_rule *r, int keepr uid, gid, rcv, icmp_type, anchor_call); } + if (osrch && src_host->addr.type == PF_ADDR_DYNIFTL) { + free(src_host); + src_host = osrch; + } + if (odsth && dst_host->addr.type == PF_ADDR_DYNIFTL) { + free(dst_host); + dst_host = odsth; + } )))))))))); if (!keeprule) { Index: sbin/pfctl/pfctl_parser.c =================================================================== RCS file: /cvs/src/sbin/pfctl/pfctl_parser.c,v retrieving revision 1.298 retrieving revision 1.298.4.1 diff -u -p -r1.298 -r1.298.4.1 --- sbin/pfctl/pfctl_parser.c 20 Jan 2014 02:59:13 -0000 1.298 +++ sbin/pfctl/pfctl_parser.c 29 Oct 2014 15:36:15 -0000 1.298.4.1 @@ -1244,16 +1244,12 @@ int check_netmask(struct node_host *h, sa_family_t af) { struct node_host *n = NULL; - struct pf_addr *m; + struct pf_addr *m; for (n = h; n != NULL; n = n->next) { if (h->addr.type == PF_ADDR_TABLE) continue; m = &h->addr.v.a.mask; - /* fix up netmask for dynaddr */ - if (af == AF_INET && h->addr.type == PF_ADDR_DYNIFTL && - unmask(m, AF_INET6) > 32) - set_ipmask(n, 32); /* netmasks > 32 bit are invalid on v4 */ if (af == AF_INET && (m->addr32[1] || m->addr32[2] || m->addr32[3])) { @@ -1263,6 +1259,30 @@ check_netmask(struct node_host *h, sa_fa } } return (0); +} + +struct node_host * +gen_dynnode(struct node_host *h, sa_family_t af) +{ + struct node_host *n; + struct pf_addr *m; + + if (h->addr.type != PF_ADDR_DYNIFTL) + return (NULL); + + if ((n = calloc(1, sizeof(*n))) == NULL) + return (NULL); + bcopy(h, n, sizeof(*n)); + n->ifname = NULL; + n->next = NULL; + n->tail = NULL; + + /* fix up netmask */ + m = &n->addr.v.a.mask; + if (af == AF_INET && unmask(m, AF_INET6) > 32) + set_ipmask(n, 32); + + return (n); } /* interface lookup routines */ Index: sbin/pfctl/pfctl_parser.h =================================================================== RCS file: /cvs/src/sbin/pfctl/pfctl_parser.h,v retrieving revision 1.101 retrieving revision 1.101.4.1 diff -u -p -r1.101 -r1.101.4.1 --- sbin/pfctl/pfctl_parser.h 12 Oct 2013 12:16:12 -0000 1.101 +++ sbin/pfctl/pfctl_parser.h 29 Oct 2014 15:36:15 -0000 1.101.4.1 @@ -278,6 +278,7 @@ extern const struct pf_timeout pf_timeou void set_ipmask(struct node_host *, u_int8_t); int check_netmask(struct node_host *, sa_family_t); int unmask(struct pf_addr *, sa_family_t); +struct node_host *gen_dynnode(struct node_host *, sa_family_t); void ifa_load(void); unsigned int ifa_nametoindex(const char *); char *ifa_indextoname(unsigned int, char *);