diff options
-rw-r--r-- | sys/netinet/icmp6.h | 3 | ||||
-rw-r--r-- | sys/netinet/ip_input.c | 5 | ||||
-rw-r--r-- | sys/netinet/ip_output.c | 4 | ||||
-rw-r--r-- | sys/netinet6/icmp6.c | 16 | ||||
-rw-r--r-- | sys/netinet6/ip6_forward.c | 29 | ||||
-rw-r--r-- | sys/netinet6/ip6_output.c | 81 | ||||
-rw-r--r-- | sys/netinet6/ip6_var.h | 5 |
7 files changed, 111 insertions, 32 deletions
diff --git a/sys/netinet/icmp6.h b/sys/netinet/icmp6.h index 468b45ca43f..ef7df8dfdde 100644 --- a/sys/netinet/icmp6.h +++ b/sys/netinet/icmp6.h @@ -1,4 +1,4 @@ -/* $OpenBSD: icmp6.h,v 1.50 2020/10/28 17:27:35 bluhm Exp $ */ +/* $OpenBSD: icmp6.h,v 1.51 2021/01/11 13:28:53 bluhm Exp $ */ /* $KAME: icmp6.h,v 1.84 2003/04/23 10:26:51 itojun Exp $ */ /* @@ -599,6 +599,7 @@ void icmp6_prepare(struct mbuf *); void icmp6_redirect_input(struct mbuf *, int); void icmp6_redirect_output(struct mbuf *, struct rtentry *); int icmp6_sysctl(int *, u_int, void *, size_t *, void *, size_t); +struct rtentry *icmp6_mtudisc_clone(struct sockaddr_in6 *, u_int, int); struct ip6ctlparam; void icmp6_mtudisc_update(struct ip6ctlparam *, int); diff --git a/sys/netinet/ip_input.c b/sys/netinet/ip_input.c index 8258faf7477..3b07b80df12 100644 --- a/sys/netinet/ip_input.c +++ b/sys/netinet/ip_input.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_input.c,v 1.352 2020/11/16 06:44:38 gnezdo Exp $ */ +/* $OpenBSD: ip_input.c,v 1.353 2021/01/11 13:28:53 bluhm Exp $ */ /* $NetBSD: ip_input.c,v 1.30 1996/03/16 23:53:58 christos Exp $ */ /* @@ -1418,8 +1418,8 @@ ip_forward(struct mbuf *m, struct ifnet *ifp, struct rtentry *rt, int srcrt) goto freecopy; } + memset(&ro, 0, sizeof(ro)); sin = satosin(&ro.ro_dst); - memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_addr = ip->ip_dst; @@ -1429,6 +1429,7 @@ ip_forward(struct mbuf *m, struct ifnet *ifp, struct rtentry *rt, int srcrt) rt = rtalloc_mpath(sintosa(sin), &ip->ip_src.s_addr, m->m_pkthdr.ph_rtableid); if (rt == NULL) { + ipstat_inc(ips_noroute); icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_HOST, dest, 0); return; } diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c index 2792b7f6f70..7492bf47fda 100644 --- a/sys/netinet/ip_output.c +++ b/sys/netinet/ip_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip_output.c,v 1.359 2021/01/07 14:51:46 claudio Exp $ */ +/* $OpenBSD: ip_output.c,v 1.360 2021/01/11 13:28:53 bluhm Exp $ */ /* $NetBSD: ip_output.c,v 1.28 1996/02/13 23:43:07 christos Exp $ */ /* @@ -613,7 +613,7 @@ ip_output_ipsec_send(struct tdb *tdb, struct mbuf *m, struct route *ro, int fwd) ntohl(tdb->tdb_spi), tdb->tdb_mtu, rt, rt_mtucloned)); if (rt != NULL) { rt->rt_mtu = tdb->tdb_mtu; - if (ro && ro->ro_rt != NULL) { + if (ro != NULL && ro->ro_rt != NULL) { rtfree(ro->ro_rt); ro->ro_rt = rtalloc(&ro->ro_dst, RT_RESOLVE, m->m_pkthdr.ph_rtableid); diff --git a/sys/netinet6/icmp6.c b/sys/netinet6/icmp6.c index e27dbf9b696..378927ecfec 100644 --- a/sys/netinet6/icmp6.c +++ b/sys/netinet6/icmp6.c @@ -1,4 +1,4 @@ -/* $OpenBSD: icmp6.c,v 1.233 2020/10/28 17:27:35 bluhm Exp $ */ +/* $OpenBSD: icmp6.c,v 1.234 2021/01/11 13:28:53 bluhm Exp $ */ /* $KAME: icmp6.c,v 1.217 2001/06/20 15:03:29 jinmei Exp $ */ /* @@ -138,7 +138,6 @@ int icmp6_ratelimit(const struct in6_addr *, const int, const int); const char *icmp6_redirect_diag(struct in6_addr *, struct in6_addr *, struct in6_addr *); int icmp6_notify_error(struct mbuf *, int, int, int); -struct rtentry *icmp6_mtudisc_clone(struct sockaddr *, u_int); void icmp6_mtudisc_timeout(struct rtentry *, struct rttimer *); void icmp6_redirect_timeout(struct rtentry *, struct rttimer *); @@ -1015,7 +1014,7 @@ icmp6_mtudisc_update(struct ip6ctlparam *ip6cp, int validated) sin6.sin6_scope_id = in6_addr2scopeid(m->m_pkthdr.ph_ifidx, &sin6.sin6_addr); - rt = icmp6_mtudisc_clone(sin6tosa(&sin6), m->m_pkthdr.ph_rtableid); + rt = icmp6_mtudisc_clone(&sin6, m->m_pkthdr.ph_rtableid, 0); if (rt != NULL && ISSET(rt->rt_flags, RTF_HOST) && !(rt->rt_locks & RTV_MTU) && @@ -1784,15 +1783,18 @@ icmp6_ratelimit(const struct in6_addr *dst, const int type, const int code) } struct rtentry * -icmp6_mtudisc_clone(struct sockaddr *dst, u_int rtableid) +icmp6_mtudisc_clone(struct sockaddr_in6 *dst, u_int rtableid, int ipsec) { struct rtentry *rt; int error; - rt = rtalloc(dst, RT_RESOLVE, rtableid); + rt = rtalloc(sin6tosa(dst), RT_RESOLVE, rtableid); /* Check if the route is actually usable */ - if (!rtisvalid(rt) || (rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE))) + if (!rtisvalid(rt)) + goto bad; + /* IPsec needs the route only for PMTU, it can use reject for that */ + if (!ipsec && (rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE))) goto bad; /* @@ -1812,7 +1814,7 @@ icmp6_mtudisc_clone(struct sockaddr *dst, u_int rtableid) memset(&info, 0, sizeof(info)); info.rti_ifa = rt->rt_ifa; info.rti_flags = RTF_GATEWAY | RTF_HOST | RTF_DYNAMIC; - info.rti_info[RTAX_DST] = dst; + info.rti_info[RTAX_DST] = sin6tosa(dst); info.rti_info[RTAX_GATEWAY] = rt->rt_gateway; info.rti_info[RTAX_LABEL] = rtlabel_id2sa(rt->rt_labelid, &sa_rl); diff --git a/sys/netinet6/ip6_forward.c b/sys/netinet6/ip6_forward.c index 65fcb55b2a0..85994f30732 100644 --- a/sys/netinet6/ip6_forward.c +++ b/sys/netinet6/ip6_forward.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_forward.c,v 1.99 2020/11/26 18:55:12 tb Exp $ */ +/* $OpenBSD: ip6_forward.c,v 1.100 2021/01/11 13:28:54 bluhm Exp $ */ /* $KAME: ip6_forward.c,v 1.75 2001/06/29 12:42:13 jinmei Exp $ */ /* @@ -85,7 +85,8 @@ void ip6_forward(struct mbuf *m, struct rtentry *rt, int srcrt) { struct ip6_hdr *ip6 = mtod(m, struct ip6_hdr *); - struct sockaddr_in6 *dst, sin6; + struct sockaddr_in6 *sin6; + struct route_in6 ro; struct ifnet *ifp = NULL; int error = 0, type = 0, code = 0; struct mbuf *mcopy = NULL; @@ -160,15 +161,15 @@ reroute: } #endif /* IPSEC */ - dst = &sin6; - memset(dst, 0, sizeof(*dst)); - dst->sin6_len = sizeof(struct sockaddr_in6); - dst->sin6_family = AF_INET6; - dst->sin6_addr = ip6->ip6_dst; + memset(&ro, 0, sizeof(ro)); + sin6 = &ro.ro_dst; + sin6->sin6_family = AF_INET6; + sin6->sin6_len = sizeof(*sin6); + sin6->sin6_addr = ip6->ip6_dst; if (!rtisvalid(rt)) { rtfree(rt); - rt = rtalloc_mpath(sin6tosa(dst), &ip6->ip6_src.s6_addr32[0], + rt = rtalloc_mpath(sin6tosa(sin6), &ip6->ip6_src.s6_addr32[0], m->m_pkthdr.ph_rtableid); if (rt == NULL) { ip6stat_inc(ip6s_noroute); @@ -215,12 +216,12 @@ reroute: /* * Check if the packet needs encapsulation. * ipsp_process_packet will never come back to here. - * XXX ipsp_process_packet() calls ip6_output(), and there'll be no - * PMTU notification. is it okay? */ if (tdb != NULL) { /* Callee frees mbuf */ - error = ip6_output_ipsec_send(tdb, m, 0, 1); + ro.ro_rt = rt; + ro.ro_tableid = m->m_pkthdr.ph_rtableid; + error = ip6_output_ipsec_send(tdb, m, &ro, 0, 1); if (error) goto senderr; goto freecopy; @@ -228,7 +229,7 @@ reroute: #endif /* IPSEC */ if (rt->rt_flags & RTF_GATEWAY) - dst = satosin6(rt->rt_gateway); + sin6 = satosin6(rt->rt_gateway); /* * If we are to forward the packet using the same interface @@ -248,7 +249,7 @@ reroute: ip6_sendredirects && (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0) { if ((ifp->if_flags & IFF_POINTOPOINT) && - nd6_is_addr_neighbor(&sin6, ifp)) { + nd6_is_addr_neighbor(&ro.ro_dst, ifp)) { /* * If the incoming interface is equal to the outgoing * one, the link attached to the interface is @@ -320,7 +321,7 @@ reroute: goto out; } - error = ifp->if_output(ifp, m, sin6tosa(dst), rt); + error = ifp->if_output(ifp, m, sin6tosa(sin6), rt); if (error) { ip6stat_inc(ip6s_cantforward); } else { diff --git a/sys/netinet6/ip6_output.c b/sys/netinet6/ip6_output.c index c7eac1ebd0a..d85f100903a 100644 --- a/sys/netinet6/ip6_output.c +++ b/sys/netinet6/ip6_output.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_output.c,v 1.248 2020/12/22 13:37:48 bluhm Exp $ */ +/* $OpenBSD: ip6_output.c,v 1.249 2021/01/11 13:28:54 bluhm Exp $ */ /* $KAME: ip6_output.c,v 1.172 2001/03/25 09:55:56 itojun Exp $ */ /* @@ -106,6 +106,12 @@ #include <netinet/ip_ipsp.h> #include <netinet/ip_ah.h> #include <netinet/ip_esp.h> + +#ifdef ENCDEBUG +#define DPRINTF(x) do { if (encdebug) printf x ; } while (0) +#else +#define DPRINTF(x) +#endif #endif /* IPSEC */ struct ip6_exthdrs { @@ -426,7 +432,7 @@ reroute: * packet just because ip6_dst is different from what tdb has. * XXX */ - error = ip6_output_ipsec_send(tdb, m, + error = ip6_output_ipsec_send(tdb, m, ro, exthdrs.ip6e_rthdr ? 1 : 0, 0); goto done; } @@ -2762,14 +2768,19 @@ ip6_output_ipsec_lookup(struct mbuf *m, int *error, struct inpcb *inp) } int -ip6_output_ipsec_send(struct tdb *tdb, struct mbuf *m, int tunalready, int fwd) +ip6_output_ipsec_send(struct tdb *tdb, struct mbuf *m, struct route_in6 *ro, + int tunalready, int fwd) { #if NPF > 0 struct ifnet *encif; #endif + struct ip6_hdr *ip6; int error; #if NPF > 0 + /* + * Packet filter + */ if ((encif = enc_getif(tdb->tdb_rdomain, tdb->tdb_tap)) == NULL || pf_test(AF_INET6, fwd ? PF_FWD : PF_OUT, encif, &m) != PF_PASS) { m_freem(m); @@ -2786,7 +2797,69 @@ ip6_output_ipsec_send(struct tdb *tdb, struct mbuf *m, int tunalready, int fwd) */ in6_proto_cksum_out(m, encif); #endif - m->m_flags &= ~(M_BCAST | M_MCAST); /* just in case */ + + /* Check if we are allowed to fragment */ + ip6 = mtod(m, struct ip6_hdr *); + if (ip_mtudisc && tdb->tdb_mtu && + sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen) > tdb->tdb_mtu && + tdb->tdb_mtutimeout > gettime()) { + struct rtentry *rt = NULL; + int rt_mtucloned = 0; + int transportmode = 0; + + transportmode = (tdb->tdb_dst.sa.sa_family == AF_INET6) && + (IN6_ARE_ADDR_EQUAL(&tdb->tdb_dst.sin6.sin6_addr, + &ip6->ip6_dst)); + + /* Find a host route to store the mtu in */ + if (ro != NULL) + rt = ro->ro_rt; + /* but don't add a PMTU route for transport mode SAs */ + if (transportmode) + rt = NULL; + else if (rt == NULL || (rt->rt_flags & RTF_HOST) == 0) { + struct sockaddr_in6 sin6; + + memset(&sin6, 0, sizeof(sin6)); + sin6.sin6_family = AF_INET6; + sin6.sin6_len = sizeof(sin6); + sin6.sin6_addr = ip6->ip6_dst; + sin6.sin6_scope_id = + in6_addr2scopeid(m->m_pkthdr.ph_ifidx, + &ip6->ip6_dst); + error = in6_embedscope(&ip6->ip6_dst, &sin6, NULL); + if (error) { + /* should be impossible */ + ipsecstat_inc(ipsec_odrops); + m_freem(m); + return error; + } + rt = icmp6_mtudisc_clone(&sin6, + m->m_pkthdr.ph_rtableid, 1); + rt_mtucloned = 1; + } + DPRINTF(("%s: spi %08x mtu %d rt %p cloned %d\n", __func__, + ntohl(tdb->tdb_spi), tdb->tdb_mtu, rt, rt_mtucloned)); + if (rt != NULL) { + rt->rt_mtu = tdb->tdb_mtu; + if (ro != NULL && ro->ro_rt != NULL) { + rtfree(ro->ro_rt); + ro->ro_rt = rtalloc(sin6tosa(&ro->ro_dst), + RT_RESOLVE, m->m_pkthdr.ph_rtableid); + } + if (rt_mtucloned) + rtfree(rt); + } + ipsec_adjust_mtu(m, tdb->tdb_mtu); + m_freem(m); + return EMSGSIZE; + } + + /* + * Clear these -- they'll be set in the recursive invocation + * as needed. + */ + m->m_flags &= ~(M_BCAST | M_MCAST); /* Callee frees mbuf */ error = ipsp_process_packet(m, tdb, AF_INET6, tunalready); diff --git a/sys/netinet6/ip6_var.h b/sys/netinet6/ip6_var.h index 3d766f6aeda..640d89e5f6a 100644 --- a/sys/netinet6/ip6_var.h +++ b/sys/netinet6/ip6_var.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip6_var.h,v 1.86 2019/12/08 11:08:22 sashan Exp $ */ +/* $OpenBSD: ip6_var.h,v 1.87 2021/01/11 13:28:54 bluhm Exp $ */ /* $KAME: ip6_var.h,v 1.33 2000/06/11 14:59:20 jinmei Exp $ */ /* @@ -368,7 +368,8 @@ u_int32_t ip6_randomflowlabel(void); struct tdb; struct tdb * ip6_output_ipsec_lookup(struct mbuf *, int *, struct inpcb *); -int ip6_output_ipsec_send(struct tdb *, struct mbuf *, int, int); +int ip6_output_ipsec_send(struct tdb *, struct mbuf *, struct route_in6 *, + int, int); #endif /* IPSEC */ #endif /* _KERNEL */ |