diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/net/if_pfsync.c | 10 | ||||
-rw-r--r-- | sys/net/pf.c | 180 | ||||
-rw-r--r-- | sys/net/pfvar.h | 10 |
3 files changed, 82 insertions, 118 deletions
diff --git a/sys/net/if_pfsync.c b/sys/net/if_pfsync.c index 9f47717440f..2b094dd855f 100644 --- a/sys/net/if_pfsync.c +++ b/sys/net/if_pfsync.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_pfsync.c,v 1.281 2021/01/18 18:29:19 mvs Exp $ */ +/* $OpenBSD: if_pfsync.c,v 1.282 2021/02/01 00:31:05 dlg Exp $ */ /* * Copyright (c) 2002 Michael Shalayeff @@ -613,6 +613,7 @@ pfsync_state_import(struct pfsync_state *sp, int flags) /* copy to state */ st->rt_addr = sp->rt_addr; + st->rt = sp->rt; st->creation = getuptime() - ntohl(sp->creation); st->expire = getuptime(); if (ntohl(sp->expire)) { @@ -643,7 +644,6 @@ pfsync_state_import(struct pfsync_state *sp, int flags) st->rule.ptr = r; st->anchor.ptr = NULL; - st->rt_kif = NULL; st->pfsync_time = getuptime(); st->sync_state = PFSYNC_S_NONE; @@ -1860,7 +1860,7 @@ pfsync_undefer(struct pfsync_deferral *pd, int drop) if (drop) m_freem(pd->pd_m); else { - if (st->rule.ptr->rt == PF_ROUTETO) { + if (st->rt == PF_ROUTETO) { if (pf_setup_pdesc(&pdesc, st->key[PF_SK_WIRE]->af, st->direction, st->kif, pd->pd_m, NULL) != PF_PASS) { @@ -1869,11 +1869,11 @@ pfsync_undefer(struct pfsync_deferral *pd, int drop) } switch (st->key[PF_SK_WIRE]->af) { case AF_INET: - pf_route(&pdesc, st->rule.ptr, st); + pf_route(&pdesc, st); break; #ifdef INET6 case AF_INET6: - pf_route6(&pdesc, st->rule.ptr, st); + pf_route6(&pdesc, st); break; #endif /* INET6 */ default: diff --git a/sys/net/pf.c b/sys/net/pf.c index 0f07fe93bc9..9c25d420d21 100644 --- a/sys/net/pf.c +++ b/sys/net/pf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pf.c,v 1.1105 2021/01/28 09:37:20 dlg Exp $ */ +/* $OpenBSD: pf.c,v 1.1106 2021/02/01 00:31:05 dlg Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -1180,6 +1180,7 @@ pf_state_export(struct pfsync_state *sp, struct pf_state *st) /* copy from state */ strlcpy(sp->ifname, st->kif->pfik_name, sizeof(sp->ifname)); + sp->rt = st->rt; sp->rt_addr = st->rt_addr; sp->creation = htonl(getuptime() - st->creation); expire = pf_state_expires(st); @@ -3430,16 +3431,13 @@ pf_set_rt_ifp(struct pf_state *s, struct pf_addr *saddr, sa_family_t af, struct pf_rule *r = s->rule.ptr; int rv; - s->rt_kif = NULL; if (!r->rt) return (0); rv = pf_map_addr(af, r, saddr, &s->rt_addr, NULL, sns, &r->route, PF_SN_ROUTE); - if (rv == 0) { - s->rt_kif = r->route.kif; - s->natrule.ptr = r; - } + if (rv == 0) + s->rt = r->rt; return (rv); } @@ -5963,15 +5961,13 @@ pf_rtlabel_match(struct pf_addr *addr, sa_family_t af, struct pf_addr_wrap *aw, /* pf_route() may change pd->m, adjust local copies after calling */ void -pf_route(struct pf_pdesc *pd, struct pf_rule *r, struct pf_state *s) +pf_route(struct pf_pdesc *pd, struct pf_state *s) { struct mbuf *m0, *m1; struct sockaddr_in *dst, sin; struct rtentry *rt = NULL; struct ip *ip; struct ifnet *ifp = NULL; - struct pf_addr naddr; - struct pf_src_node *sns[PF_SN_MAX]; int error = 0; unsigned int rtableid; @@ -5981,11 +5977,11 @@ pf_route(struct pf_pdesc *pd, struct pf_rule *r, struct pf_state *s) return; } - if (r->rt == PF_DUPTO) { + if (s->rt == PF_DUPTO) { if ((m0 = m_dup_pkt(pd->m, max_linkhdr, M_NOWAIT)) == NULL) return; } else { - if ((r->rt == PF_REPLYTO) == (r->direction == pd->dir)) + if ((s->rt == PF_REPLYTO) == (s->direction == pd->dir)) return; m0 = pd->m; pd->m = NULL; @@ -5999,48 +5995,45 @@ pf_route(struct pf_pdesc *pd, struct pf_rule *r, struct pf_state *s) ip = mtod(m0, struct ip *); - memset(&sin, 0, sizeof(sin)); - dst = &sin; - dst->sin_family = AF_INET; - dst->sin_len = sizeof(*dst); - dst->sin_addr = ip->ip_dst; - rtableid = m0->m_pkthdr.ph_rtableid; - if (pd->dir == PF_IN) { if (ip->ip_ttl <= IPTTLDEC) { - if (r->rt != PF_DUPTO) + if (s->rt != PF_DUPTO) { pf_send_icmp(m0, ICMP_TIMXCEED, ICMP_TIMXCEED_INTRANS, 0, - pd->af, r, pd->rdomain); + pd->af, s->rule.ptr, pd->rdomain); + } goto bad; } ip->ip_ttl -= IPTTLDEC; } - if (s == NULL) { - memset(sns, 0, sizeof(sns)); - if (pf_map_addr(AF_INET, r, - (struct pf_addr *)&ip->ip_src, - &naddr, NULL, sns, &r->route, PF_SN_ROUTE)) { - DPFPRINTF(LOG_ERR, - "%s: pf_map_addr() failed", __func__); - goto bad; - } + memset(&sin, 0, sizeof(sin)); + dst = &sin; + dst->sin_family = AF_INET; + dst->sin_len = sizeof(*dst); + dst->sin_addr = s->rt_addr.v4; + rtableid = m0->m_pkthdr.ph_rtableid; - if (!PF_AZERO(&naddr, AF_INET)) - dst->sin_addr.s_addr = naddr.v4.s_addr; - ifp = r->route.kif ? - r->route.kif->pfik_ifp : NULL; - } else { - if (!PF_AZERO(&s->rt_addr, AF_INET)) - dst->sin_addr.s_addr = - s->rt_addr.v4.s_addr; - ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL; + rt = rtalloc(sintosa(dst), RT_RESOLVE, rtableid); + if (!rtisvalid(rt)) { + if (s->rt != PF_DUPTO) { + pf_send_icmp(m0, ICMP_UNREACH, ICMP_UNREACH_HOST, + 0, pd->af, s->rule.ptr, pd->rdomain); + } + ipstat_inc(ips_noroute); + goto bad; } + + ifp = if_get(rt->rt_ifidx); if (ifp == NULL) goto bad; - if (r->rt != PF_DUPTO && pd->kif->pfik_ifp != ifp) { + /* A locally generated packet may have invalid source address. */ + if ((ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET && + (ifp->if_flags & IFF_LOOPBACK) == 0) + ip->ip_src = ifatoia(rt->rt_ifa)->ia_addr.sin_addr; + + if (s->rt != PF_DUPTO && pd->kif->pfik_ifp != ifp) { if (pf_test(AF_INET, PF_OUT, ifp, &m0) != PF_PASS) goto bad; else if (m0 == NULL) @@ -6053,20 +6046,6 @@ pf_route(struct pf_pdesc *pd, struct pf_rule *r, struct pf_state *s) ip = mtod(m0, struct ip *); } - rt = rtalloc(sintosa(dst), RT_RESOLVE, rtableid); - if (!rtisvalid(rt)) { - if (r->rt != PF_DUPTO) { - pf_send_icmp(m0, ICMP_UNREACH, ICMP_UNREACH_HOST, - 0, pd->af, s->rule.ptr, pd->rdomain); - } - ipstat_inc(ips_noroute); - goto bad; - } - /* A locally generated packet may have invalid source address. */ - if ((ntohl(ip->ip_src.s_addr) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET && - (ifp->if_flags & IFF_LOOPBACK) == 0) - ip->ip_src = ifatoia(rt->rt_ifa)->ia_addr.sin_addr; - in_proto_cksum_out(m0, ifp); if (ntohs(ip->ip_len) <= ifp->if_mtu) { @@ -6087,9 +6066,9 @@ pf_route(struct pf_pdesc *pd, struct pf_rule *r, struct pf_state *s) */ if (ip->ip_off & htons(IP_DF)) { ipstat_inc(ips_cantfrag); - if (r->rt != PF_DUPTO) + if (s->rt != PF_DUPTO) pf_send_icmp(m0, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG, - ifp->if_mtu, pd->af, r, pd->rdomain); + ifp->if_mtu, pd->af, s->rule.ptr, pd->rdomain); goto bad; } @@ -6113,6 +6092,7 @@ pf_route(struct pf_pdesc *pd, struct pf_rule *r, struct pf_state *s) ipstat_inc(ips_fragmented); done: + if_put(ifp); rtfree(rt); return; @@ -6124,15 +6104,13 @@ bad: #ifdef INET6 /* pf_route6() may change pd->m, adjust local copies after calling */ void -pf_route6(struct pf_pdesc *pd, struct pf_rule *r, struct pf_state *s) +pf_route6(struct pf_pdesc *pd, struct pf_state *s) { struct mbuf *m0; struct sockaddr_in6 *dst, sin6; struct rtentry *rt = NULL; struct ip6_hdr *ip6; struct ifnet *ifp = NULL; - struct pf_addr naddr; - struct pf_src_node *sns[PF_SN_MAX]; struct m_tag *mtag; unsigned int rtableid; @@ -6142,11 +6120,11 @@ pf_route6(struct pf_pdesc *pd, struct pf_rule *r, struct pf_state *s) return; } - if (r->rt == PF_DUPTO) { + if (s->rt == PF_DUPTO) { if ((m0 = m_dup_pkt(pd->m, max_linkhdr, M_NOWAIT)) == NULL) return; } else { - if ((r->rt == PF_REPLYTO) == (r->direction == pd->dir)) + if ((s->rt == PF_REPLYTO) == (s->direction == pd->dir)) return; m0 = pd->m; pd->m = NULL; @@ -6159,74 +6137,59 @@ pf_route6(struct pf_pdesc *pd, struct pf_rule *r, struct pf_state *s) } ip6 = mtod(m0, struct ip6_hdr *); - memset(&sin6, 0, sizeof(sin6)); - dst = &sin6; - dst->sin6_family = AF_INET6; - dst->sin6_len = sizeof(*dst); - dst->sin6_addr = ip6->ip6_dst; - rtableid = m0->m_pkthdr.ph_rtableid; - if (pd->dir == PF_IN) { if (ip6->ip6_hlim <= IPV6_HLIMDEC) { - if (r->rt != PF_DUPTO) + if (s->rt != PF_DUPTO) { pf_send_icmp(m0, ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT, 0, - pd->af, r, pd->rdomain); + pd->af, s->rule.ptr, pd->rdomain); + } goto bad; } ip6->ip6_hlim -= IPV6_HLIMDEC; } - if (s == NULL) { - memset(sns, 0, sizeof(sns)); - if (pf_map_addr(AF_INET6, r, (struct pf_addr *)&ip6->ip6_src, - &naddr, NULL, sns, &r->route, PF_SN_ROUTE)) { - DPFPRINTF(LOG_ERR, - "%s: pf_map_addr() failed", __func__); - goto bad; - } - if (!PF_AZERO(&naddr, AF_INET6)) - pf_addrcpy((struct pf_addr *)&dst->sin6_addr, - &naddr, AF_INET6); - ifp = r->route.kif ? r->route.kif->pfik_ifp : NULL; - } else { - if (!PF_AZERO(&s->rt_addr, AF_INET6)) - pf_addrcpy((struct pf_addr *)&dst->sin6_addr, - &s->rt_addr, AF_INET6); - ifp = s->rt_kif ? s->rt_kif->pfik_ifp : NULL; - } - if (ifp == NULL) - goto bad; - - if (r->rt != PF_DUPTO && pd->kif->pfik_ifp != ifp) { - if (pf_test(AF_INET6, PF_OUT, ifp, &m0) != PF_PASS) - goto bad; - else if (m0 == NULL) - goto done; - if (m0->m_len < sizeof(struct ip6_hdr)) { - DPFPRINTF(LOG_ERR, - "%s: m0->m_len < sizeof(struct ip6_hdr)", __func__); - goto bad; - } - } + memset(&sin6, 0, sizeof(sin6)); + dst = &sin6; + dst->sin6_family = AF_INET6; + dst->sin6_len = sizeof(*dst); + dst->sin6_addr = s->rt_addr.v6; + rtableid = m0->m_pkthdr.ph_rtableid; if (IN6_IS_SCOPE_EMBED(&dst->sin6_addr)) dst->sin6_addr.s6_addr16[1] = htons(ifp->if_index); rt = rtalloc(sin6tosa(dst), RT_RESOLVE, rtableid); if (!rtisvalid(rt)) { - if (r->rt != PF_DUPTO) { + if (s->rt != PF_DUPTO) { pf_send_icmp(m0, ICMP6_DST_UNREACH, ICMP6_DST_UNREACH_NOROUTE, 0, pd->af, s->rule.ptr, pd->rdomain); - } + } ip6stat_inc(ip6s_noroute); goto bad; } + + ifp = if_get(rt->rt_ifidx); + if (ifp == NULL) + goto bad; + /* A locally generated packet may have invalid source address. */ if (IN6_IS_ADDR_LOOPBACK(&ip6->ip6_src) && (ifp->if_flags & IFF_LOOPBACK) == 0) ip6->ip6_src = ifatoia6(rt->rt_ifa)->ia_addr.sin6_addr; + if (s->rt != PF_DUPTO && pd->kif->pfik_ifp != ifp) { + if (pf_test(AF_INET6, PF_OUT, ifp, &m0) != PF_PASS) + goto bad; + else if (m0 == NULL) + goto done; + if (m0->m_len < sizeof(struct ip6_hdr)) { + DPFPRINTF(LOG_ERR, + "%s: m0->m_len < sizeof(struct ip6_hdr)", __func__); + goto bad; + } + } + in6_proto_cksum_out(m0, ifp); /* @@ -6239,13 +6202,14 @@ pf_route6(struct pf_pdesc *pd, struct pf_rule *r, struct pf_state *s) ifp->if_output(ifp, m0, sin6tosa(dst), rt); } else { ip6stat_inc(ip6s_cantfrag); - if (r->rt != PF_DUPTO) + if (s->rt != PF_DUPTO) pf_send_icmp(m0, ICMP6_PACKET_TOO_BIG, 0, - ifp->if_mtu, pd->af, r, pd->rdomain); + ifp->if_mtu, pd->af, s->rule.ptr, pd->rdomain); goto bad; } done: + if_put(ifp); rtfree(rt); return; @@ -7286,14 +7250,14 @@ done: pd.m = NULL; break; default: - if (r->rt) { + if (s && s->rt) { switch (pd.af) { case AF_INET: - pf_route(&pd, r, s); + pf_route(&pd, s); break; #ifdef INET6 case AF_INET6: - pf_route6(&pd, r, s); + pf_route6(&pd, s); break; #endif /* INET6 */ } diff --git a/sys/net/pfvar.h b/sys/net/pfvar.h index ef80398538b..ae7742877ad 100644 --- a/sys/net/pfvar.h +++ b/sys/net/pfvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: pfvar.h,v 1.498 2021/01/12 00:10:34 bluhm Exp $ */ +/* $OpenBSD: pfvar.h,v 1.499 2021/02/01 00:31:05 dlg Exp $ */ /* * Copyright (c) 2001 Daniel Hartmeier @@ -762,7 +762,6 @@ struct pf_state { struct pf_sn_head src_nodes; struct pf_state_key *key[2]; /* addresses stack and wire */ struct pfi_kif *kif; - struct pfi_kif *rt_kif; u_int64_t packets[2]; u_int64_t bytes[2]; int32_t creation; @@ -797,6 +796,7 @@ struct pf_state { u_int16_t if_index_out; pf_refcnt_t refcnt; u_int16_t delay; + u_int8_t rt; }; /* @@ -852,7 +852,7 @@ struct pfsync_state { u_int8_t proto; u_int8_t direction; u_int8_t log; - u_int8_t pad0; + u_int8_t rt; u_int8_t timeout; u_int8_t sync_flags; u_int8_t updates; @@ -1798,8 +1798,8 @@ int pf_state_key_attach(struct pf_state_key *, struct pf_state *, int); int pf_translate(struct pf_pdesc *, struct pf_addr *, u_int16_t, struct pf_addr *, u_int16_t, u_int16_t, int); int pf_translate_af(struct pf_pdesc *); -void pf_route(struct pf_pdesc *, struct pf_rule *, struct pf_state *); -void pf_route6(struct pf_pdesc *, struct pf_rule *, struct pf_state *); +void pf_route(struct pf_pdesc *, struct pf_state *); +void pf_route6(struct pf_pdesc *, struct pf_state *); void pf_init_threshold(struct pf_threshold *, u_int32_t, u_int32_t); int pf_delay_pkt(struct mbuf *, u_int); |