| | 1959 | * Detects and edits an DHCP packet arriving from the internal net. |
|---|
| | 1960 | * |
|---|
| | 1961 | * @param pNetwork The network the frame is being sent to. |
|---|
| | 1962 | * @param pSG Pointer to the gather list for the frame. |
|---|
| | 1963 | * The flags and data content may be updated. |
|---|
| | 1964 | * @param pEthHdr Pointer to the ethernet header. This may also be |
|---|
| | 1965 | * updated if it's a unicast... |
|---|
| | 1966 | */ |
|---|
| | 1967 | static void intnetR0NetworkEditDhcpFromIntNet(PINTNETNETWORK pNetwork, PINTNETSG pSG, PRTNETETHERHDR pEthHdr) |
|---|
| | 1968 | { |
|---|
| | 1969 | /* |
|---|
| | 1970 | * Check the minimum size and get a linear copy of the thing to work on, |
|---|
| | 1971 | * using the temporary buffer if necessary. |
|---|
| | 1972 | */ |
|---|
| | 1973 | if (RT_UNLIKELY(pSG->cbTotal < sizeof(RTNETETHERHDR) + RTNETIPV4_MIN_LEN + RTNETUDP_MIN_LEN + RTNETBOOTP_DHCP_MIN_LEN)) |
|---|
| | 1974 | return; |
|---|
| | 1975 | /* |
|---|
| | 1976 | * Get a pointer to a linear copy of the full packet, using the |
|---|
| | 1977 | * temporary buffer if necessary. |
|---|
| | 1978 | */ |
|---|
| | 1979 | PCRTNETIPV4 pIpHdr = (PCRTNETIPV4)((PCRTNETETHERHDR)pSG->aSegs[0].pv + 1); |
|---|
| | 1980 | size_t cbPacket = pSG->cbTotal - sizeof(RTNETETHERHDR); |
|---|
| | 1981 | if (pSG->cSegsUsed > 1) |
|---|
| | 1982 | { |
|---|
| | 1983 | cbPacket = RT_MIN(cbPacket, INTNETNETWORK_TMP_SIZE); |
|---|
| | 1984 | Log6(("intnetR0NetworkEditDhcpFromIntNet: Copying IPv4/UDP/DHCP pkt %u\n", cbPacket)); |
|---|
| | 1985 | if (!intnetR0SgReadPart(pSG, sizeof(RTNETETHERHDR), cbPacket, pNetwork->pbTmp)) |
|---|
| | 1986 | return; |
|---|
| | 1987 | //pSG->fFlags |= INTNETSG_FLAGS_PKT_CP_IN_TMP; |
|---|
| | 1988 | pIpHdr = (PCRTNETIPV4)pNetwork->pbTmp; |
|---|
| | 1989 | } |
|---|
| | 1990 | |
|---|
| | 1991 | /* |
|---|
| | 1992 | * Validate the IP header and find the UDP packet. |
|---|
| | 1993 | */ |
|---|
| | 1994 | if (!RTNetIPv4IsHdrValid(pIpHdr, cbPacket, pSG->cbTotal - sizeof(RTNETETHERHDR))) |
|---|
| | 1995 | { |
|---|
| | 1996 | Log6(("intnetR0NetworkEditDhcpFromIntNet: bad ip header\n")); |
|---|
| | 1997 | return; |
|---|
| | 1998 | } |
|---|
| | 1999 | size_t cbIpHdr = pIpHdr->ip_hl * 4; |
|---|
| | 2000 | if ( pIpHdr->ip_p != RTNETIPV4_PROT_UDP /* DHCP is UDP. */ |
|---|
| | 2001 | || cbPacket < cbIpHdr + RTNETUDP_MIN_LEN + RTNETBOOTP_DHCP_MIN_LEN) /* Min DHCP packet len */ |
|---|
| | 2002 | return; |
|---|
| | 2003 | |
|---|
| | 2004 | size_t cbUdpPkt = cbPacket - cbIpHdr; |
|---|
| | 2005 | PCRTNETUDP pUdpHdr = (PCRTNETUDP)((uintptr_t)pIpHdr + cbIpHdr); |
|---|
| | 2006 | /* We are only interested in DHCP packets coming from client to server. */ |
|---|
| | 2007 | if ( RT_BE2H_U16(pUdpHdr->uh_dport) != RTNETIPV4_PORT_BOOTPS |
|---|
| | 2008 | || RT_BE2H_U16(pUdpHdr->uh_sport) != RTNETIPV4_PORT_BOOTPC) |
|---|
| | 2009 | return; |
|---|
| | 2010 | |
|---|
| | 2011 | /* |
|---|
| | 2012 | * Check if the DHCP message is valid and get the type. |
|---|
| | 2013 | */ |
|---|
| | 2014 | if (!RTNetIPv4IsUDPValid(pIpHdr, pUdpHdr, pUdpHdr + 1, cbUdpPkt)) |
|---|
| | 2015 | { |
|---|
| | 2016 | Log6(("intnetR0NetworkEditDhcpFromIntNet: Bad UDP packet\n")); |
|---|
| | 2017 | return; |
|---|
| | 2018 | } |
|---|
| | 2019 | PCRTNETBOOTP pDhcp = (PCRTNETBOOTP)(pUdpHdr + 1); |
|---|
| | 2020 | uint8_t MsgType; |
|---|
| | 2021 | if (!RTNetIPv4IsDHCPValid(pUdpHdr, pDhcp, cbUdpPkt - sizeof(*pUdpHdr), &MsgType)) |
|---|
| | 2022 | { |
|---|
| | 2023 | Log6(("intnetR0NetworkEditDhcpFromIntNet: Bad DHCP packet\n")); |
|---|
| | 2024 | return; |
|---|
| | 2025 | } |
|---|
| | 2026 | |
|---|
| | 2027 | switch (MsgType) |
|---|
| | 2028 | { |
|---|
| | 2029 | case RTNET_DHCP_MT_DISCOVER: |
|---|
| | 2030 | case RTNET_DHCP_MT_REQUEST: |
|---|
| | 2031 | Log6(("intnetR0NetworkEditDhcpFromIntNet: Setting broadcast flag in DHCP %#x, previously %x\n", MsgType, pDhcp->bp_flags)); |
|---|
| | 2032 | if (!(pDhcp->bp_flags & RT_H2BE_U16_C(RTNET_DHCP_FLAG_BROADCAST))) |
|---|
| | 2033 | { |
|---|
| | 2034 | /* Patch flags */ |
|---|
| | 2035 | uint16_t uFlags = pDhcp->bp_flags | RT_H2BE_U16_C(RTNET_DHCP_FLAG_BROADCAST); |
|---|
| | 2036 | intnetR0SgWritePart(pSG, (uint8_t*)&pDhcp->bp_flags - (uint8_t*)pIpHdr + sizeof(RTNETETHERHDR), sizeof(uFlags), &uFlags); |
|---|
| | 2037 | /* Patch UDP checksum */ |
|---|
| | 2038 | uint32_t uChecksum = (uint32_t)~pUdpHdr->uh_sum + RT_H2BE_U16_C(RTNET_DHCP_FLAG_BROADCAST); |
|---|
| | 2039 | while (uChecksum >> 16) |
|---|
| | 2040 | uChecksum = (uChecksum >> 16) + (uChecksum & 0xFFFF); |
|---|
| | 2041 | uChecksum = ~uChecksum; |
|---|
| | 2042 | intnetR0SgWritePart(pSG, (uint8_t*)&pUdpHdr->uh_sum - (uint8_t*)pIpHdr + sizeof(RTNETETHERHDR), sizeof(pUdpHdr->uh_sum), &uChecksum); |
|---|
| | 2043 | } |
|---|
| | 2044 | break; |
|---|
| | 2045 | } |
|---|
| | 2046 | } |
|---|
| | 2047 | |
|---|
| | 2048 | |
|---|
| | 2049 | /** |
|---|