--- sys/netinet/ip_divert.c.orig 2016-11-19 19:37:05.420210000 +0700 +++ sys/netinet/ip_divert.c 2017-05-11 04:29:25.369859000 +0700 @@ -464,6 +464,8 @@ div_output(struct socket *so, struct mbu if (options != NULL) m_freem(options); } else { + struct ifnet *ifp; + dt->info |= IPFW_IS_DIVERT | IPFW_INFO_IN; if (m->m_pkthdr.rcvif == NULL) { /* @@ -483,6 +485,37 @@ div_output(struct socket *so, struct mbu m->m_pkthdr.rcvif = ifa->ifa_ifp; ifa_free(ifa); } + + /* + * ip_input() can pass the packet to ip_tryforward() + * that expects broadcasts to have M_BCAST flag. + * Really bad things happen if incoming broadcast misses it. + * The same applies for multicasts. + * Restoration of M_BCAST is expensive, so do it here. + */ + + ifp = m->m_pkthdr.rcvif; + switch (ip->ip_v) { +#ifdef INET + case IPVERSION: + if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) + m->m_flags |= M_MCAST; + else if (in_broadcast(ip->ip_dst, ifp)) + m->m_flags |= M_BCAST; + break; +#endif + +#ifdef INET6 + case IPV6_VERSION >> 4: + struct ip6_hdr *ip6; + + ip6 = mtod(m, struct ip6_hdr *); + if (IN6_IS_ADDR_MULTICAST(&ip6->ip6_dst)) + m->m_flags |= M_MCAST; + break; +#endif + } + #ifdef MAC mac_socket_create_mbuf(so, m); #endif