--- sys/netinet/libalias/alias.c.orig 2020-09-10 09:32:29.529203000 +0700 +++ sys/netinet/libalias/alias.c 2022-01-12 13:47:52.834633000 +0700 @@ -732,21 +732,37 @@ ProtoAliasOut(struct libalias *la, struc } +#define MF_ISSET(_pip) (ntohs((_pip)->ip_off) & IP_MF) +#define FRAG_NO_HDR(_pip) (ntohs((_pip)->ip_off) & IP_OFFMASK) + +static struct udphdr * +ValidateUdpLength(struct ip *pip) +{ + struct udphdr *ud; + size_t dlen; + +#ifdef _KERNEL + KASSERT(!FRAG_NO_HDR(pip), ("header-less fragment isn't expected here")); +#endif + dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2); + if (dlen < sizeof(struct udphdr)) + return (NULL); + ud = (struct udphdr *)ip_next(pip); + if (!MF_ISSET(pip) && dlen < ntohs(ud->uh_ulen)) + return (NULL); + return (ud); +} + static int UdpAliasIn(struct libalias *la, struct ip *pip) { struct udphdr *ud; struct alias_link *lnk; - int dlen; LIBALIAS_LOCK_ASSERT(la); - dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2); - if (dlen < sizeof(struct udphdr)) - return (PKT_ALIAS_IGNORED); - - ud = (struct udphdr *)ip_next(pip); - if (dlen < ntohs(ud->uh_ulen)) + ud = ValidateUdpLength(pip); + if (ud == NULL) return (PKT_ALIAS_IGNORED); lnk = FindUdpTcpIn(la, pip->ip_src, pip->ip_dst, @@ -836,19 +852,15 @@ UdpAliasOut(struct libalias *la, struct u_short dest_port; u_short proxy_server_port; int proxy_type; - int dlen, error; + int error; LIBALIAS_LOCK_ASSERT(la); -/* Return if proxy-only mode is enabled and not proxyrule found.*/ - dlen = ntohs(pip->ip_len) - (pip->ip_hl << 2); - if (dlen < sizeof(struct udphdr)) - return (PKT_ALIAS_IGNORED); - - ud = (struct udphdr *)ip_next(pip); - if (dlen < ntohs(ud->uh_ulen)) + ud = ValidateUdpLength(pip); + if (ud == NULL) return (PKT_ALIAS_IGNORED); + /* Return if proxy-only mode is enabled and not proxyrule found.*/ proxy_type = ProxyCheck(la, &proxy_server_address, &proxy_server_port, pip->ip_src, pip->ip_dst, ud->uh_dport, pip->ip_p); @@ -1362,8 +1374,14 @@ LibAliasInLocked(struct libalias *la, ch goto getout; } + if (FRAG_NO_HDR(pip)) { + iresult = FragmentIn(la, pip->ip_src, &pip->ip_dst, pip->ip_id, + &pip->ip_sum); + goto getout; + } + iresult = PKT_ALIAS_IGNORED; - if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { + switch (pip->ip_p) { case IPPROTO_ICMP: iresult = IcmpAliasIn(la, pip); @@ -1406,7 +1424,7 @@ LibAliasInLocked(struct libalias *la, ch break; } - if (ntohs(pip->ip_off) & IP_MF) { + if (MF_ISSET(pip)) { struct alias_link *lnk; lnk = FindFragmentIn1(la, pip->ip_src, alias_addr, pip->ip_id); @@ -1417,10 +1435,6 @@ LibAliasInLocked(struct libalias *la, ch iresult = PKT_ALIAS_ERROR; } } - } else { - iresult = FragmentIn(la, pip->ip_src, &pip->ip_dst, pip->ip_id, - &pip->ip_sum); - } getout: return (iresult); @@ -1520,8 +1534,14 @@ LibAliasOutLocked(struct libalias *la, c } else if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY) { SetDefaultAliasAddress(la, pip->ip_src); } + + if (FRAG_NO_HDR(pip)) { + iresult = FragmentOut(la, &pip->ip_src, &pip->ip_sum); + goto getout_restore; + } + iresult = PKT_ALIAS_IGNORED; - if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) { + switch (pip->ip_p) { case IPPROTO_ICMP: iresult = IcmpAliasOut(la, pip, create); @@ -1562,10 +1582,8 @@ LibAliasOutLocked(struct libalias *la, c pip->ip_dst, pip->ip_p, &pip->ip_sum, create); break; } - } else { - iresult = FragmentOut(la, &pip->ip_src, &pip->ip_sum); - } +getout_restore: SetDefaultAliasAddress(la, addr_save); getout: return (iresult);