diff options
author | Christian Grothoff <christian@grothoff.org> | 2012-01-21 20:05:03 +0000 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2012-01-21 20:05:03 +0000 |
commit | b53c68458d1b7daa7a4320adb401daac62c4daed (patch) | |
tree | 30b8e4f0a249c225604f1d101b5dd4005dac67c0 /src/vpn | |
parent | ee731605205a1629d672e65e8372167460bb9f45 (diff) | |
download | gnunet-b53c68458d1b7daa7a4320adb401daac62c4daed.tar.gz gnunet-b53c68458d1b7daa7a4320adb401daac62c4daed.zip |
-implementing ICMP PT and type checking on VPN->TUN link
Diffstat (limited to 'src/vpn')
-rw-r--r-- | src/vpn/gnunet-service-vpn.c | 252 |
1 files changed, 246 insertions, 6 deletions
diff --git a/src/vpn/gnunet-service-vpn.c b/src/vpn/gnunet-service-vpn.c index 403570e26..12b4eef4a 100644 --- a/src/vpn/gnunet-service-vpn.c +++ b/src/vpn/gnunet-service-vpn.c | |||
@@ -1600,6 +1600,44 @@ message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED, | |||
1600 | 1600 | ||
1601 | 1601 | ||
1602 | /** | 1602 | /** |
1603 | * Synthesize a plausible ICMP payload for an ICMP error | ||
1604 | * response on the given tunnel. | ||
1605 | * | ||
1606 | * @param ts tunnel information | ||
1607 | * @param ipp IPv4 header to fill in (ICMP payload) | ||
1608 | * @param udp "UDP" header to fill in (ICMP payload); might actually | ||
1609 | * also be the first 8 bytes of the TCP header | ||
1610 | */ | ||
1611 | static void | ||
1612 | make_up_icmpv4_payload (struct TunnelState *ts, | ||
1613 | struct GNUNET_TUN_IPv4Header *ipp, | ||
1614 | struct GNUNET_TUN_UdpHeader *udp) | ||
1615 | { | ||
1616 | /* FIXME */ | ||
1617 | GNUNET_break (0); | ||
1618 | } | ||
1619 | |||
1620 | |||
1621 | /** | ||
1622 | * Synthesize a plausible ICMP payload for an ICMP error | ||
1623 | * response on the given tunnel. | ||
1624 | * | ||
1625 | * @param ts tunnel information | ||
1626 | * @param ipp IPv6 header to fill in (ICMP payload) | ||
1627 | * @param udp "UDP" header to fill in (ICMP payload); might actually | ||
1628 | * also be the first 8 bytes of the TCP header | ||
1629 | */ | ||
1630 | static void | ||
1631 | make_up_icmpv6_payload (struct TunnelState *ts, | ||
1632 | struct GNUNET_TUN_IPv6Header *ipp, | ||
1633 | struct GNUNET_TUN_UdpHeader *udp) | ||
1634 | { | ||
1635 | /* FIXME */ | ||
1636 | GNUNET_break (0); | ||
1637 | } | ||
1638 | |||
1639 | |||
1640 | /** | ||
1603 | * We got an ICMP packet back from the MESH tunnel. Pass it on to the | 1641 | * We got an ICMP packet back from the MESH tunnel. Pass it on to the |
1604 | * local virtual interface via the helper. | 1642 | * local virtual interface via the helper. |
1605 | * | 1643 | * |
@@ -1663,13 +1701,14 @@ receive_icmp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, | |||
1663 | sizeof (struct GNUNET_TUN_Layer2PacketHeader) + | 1701 | sizeof (struct GNUNET_TUN_Layer2PacketHeader) + |
1664 | mlen; | 1702 | mlen; |
1665 | { | 1703 | { |
1666 | char buf[size]; | 1704 | /* reserve some extra space in case we have an ICMP type here where |
1705 | we will need to make up the payload ourselves */ | ||
1706 | char buf[size + sizeof (struct GNUNET_TUN_IPv4Header) + 8]; | ||
1667 | struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf; | 1707 | struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf; |
1668 | struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1]; | 1708 | struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1]; |
1669 | struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1]; | 1709 | struct GNUNET_TUN_IPv4Header *ipv4 = (struct GNUNET_TUN_IPv4Header *) &tun[1]; |
1670 | struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1]; | 1710 | struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv4[1]; |
1671 | msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); | 1711 | msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); |
1672 | msg->size = htons (size); | ||
1673 | tun->flags = htons (0); | 1712 | tun->flags = htons (0); |
1674 | tun->proto = htons (ETH_P_IPV4); | 1713 | tun->proto = htons (ETH_P_IPV4); |
1675 | GNUNET_TUN_initialize_ipv4_header (ipv4, | 1714 | GNUNET_TUN_initialize_ipv4_header (ipv4, |
@@ -1681,7 +1720,108 @@ receive_icmp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, | |||
1681 | memcpy (&icmp[1], | 1720 | memcpy (&icmp[1], |
1682 | &i2v[1], | 1721 | &i2v[1], |
1683 | mlen); | 1722 | mlen); |
1684 | /* FIXME: for some ICMP types, we need to adjust the payload here... */ | 1723 | /* For some ICMP types, we need to adjust (make up) the payload here. |
1724 | Also, depending on the AF used on the other side, we have to | ||
1725 | do ICMP PT (translate ICMP types) */ | ||
1726 | switch (ntohl (i2v->af)) | ||
1727 | { | ||
1728 | case AF_INET: | ||
1729 | switch (icmp->type) | ||
1730 | { | ||
1731 | case GNUNET_TUN_ICMPTYPE_ECHO_REPLY: | ||
1732 | case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST: | ||
1733 | break; | ||
1734 | case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE: | ||
1735 | case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH: | ||
1736 | case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED: | ||
1737 | { | ||
1738 | struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1]; | ||
1739 | struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1]; | ||
1740 | |||
1741 | if (mlen != 0) | ||
1742 | { | ||
1743 | /* sender did not strip ICMP payload? */ | ||
1744 | GNUNET_break_op (0); | ||
1745 | return GNUNET_SYSERR; | ||
1746 | } | ||
1747 | size += sizeof (struct GNUNET_TUN_IPv4Header) + 8; | ||
1748 | GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); | ||
1749 | make_up_icmpv4_payload (ts, ipp, udp); | ||
1750 | } | ||
1751 | break; | ||
1752 | default: | ||
1753 | GNUNET_break_op (0); | ||
1754 | GNUNET_STATISTICS_update (stats, | ||
1755 | gettext_noop ("# ICMPv4 packets dropped (type not allowed)"), | ||
1756 | 1, GNUNET_NO); | ||
1757 | return GNUNET_SYSERR; | ||
1758 | } | ||
1759 | /* end AF_INET */ | ||
1760 | break; | ||
1761 | case AF_INET6: | ||
1762 | /* ICMP PT 6-to-4 and possibly making up payloads */ | ||
1763 | switch (icmp->type) | ||
1764 | { | ||
1765 | case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE: | ||
1766 | icmp->type = GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE; | ||
1767 | { | ||
1768 | struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1]; | ||
1769 | struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1]; | ||
1770 | |||
1771 | if (mlen != 0) | ||
1772 | { | ||
1773 | /* sender did not strip ICMP payload? */ | ||
1774 | GNUNET_break_op (0); | ||
1775 | return GNUNET_SYSERR; | ||
1776 | } | ||
1777 | size += sizeof (struct GNUNET_TUN_IPv4Header) + 8; | ||
1778 | GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); | ||
1779 | make_up_icmpv4_payload (ts, ipp, udp); | ||
1780 | } | ||
1781 | break; | ||
1782 | case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED: | ||
1783 | icmp->type = GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED; | ||
1784 | { | ||
1785 | struct GNUNET_TUN_IPv4Header *ipp = (struct GNUNET_TUN_IPv4Header *) &icmp[1]; | ||
1786 | struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1]; | ||
1787 | |||
1788 | if (mlen != 0) | ||
1789 | { | ||
1790 | /* sender did not strip ICMP payload? */ | ||
1791 | GNUNET_break_op (0); | ||
1792 | return GNUNET_SYSERR; | ||
1793 | } | ||
1794 | size += sizeof (struct GNUNET_TUN_IPv4Header) + 8; | ||
1795 | GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); | ||
1796 | make_up_icmpv4_payload (ts, ipp, udp); | ||
1797 | } | ||
1798 | break; | ||
1799 | case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG: | ||
1800 | case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM: | ||
1801 | GNUNET_STATISTICS_update (stats, | ||
1802 | gettext_noop ("# ICMPv6 packets dropped (impossible PT to v4)"), | ||
1803 | 1, GNUNET_NO); | ||
1804 | return GNUNET_OK; | ||
1805 | case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST: | ||
1806 | icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REQUEST; | ||
1807 | break; | ||
1808 | case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY: | ||
1809 | icmp->type = GNUNET_TUN_ICMPTYPE_ECHO_REPLY; | ||
1810 | break; | ||
1811 | default: | ||
1812 | GNUNET_break_op (0); | ||
1813 | GNUNET_STATISTICS_update (stats, | ||
1814 | gettext_noop ("# ICMPv6 packets dropped (type not allowed)"), | ||
1815 | 1, GNUNET_NO); | ||
1816 | return GNUNET_SYSERR; | ||
1817 | } | ||
1818 | /* end AF_INET6 */ | ||
1819 | break; | ||
1820 | default: | ||
1821 | GNUNET_break_op (0); | ||
1822 | return GNUNET_SYSERR; | ||
1823 | } | ||
1824 | msg->size = htons (size); | ||
1685 | GNUNET_TUN_calculate_icmp_checksum (icmp, | 1825 | GNUNET_TUN_calculate_icmp_checksum (icmp, |
1686 | &i2v[1], | 1826 | &i2v[1], |
1687 | mlen); | 1827 | mlen); |
@@ -1700,13 +1840,12 @@ receive_icmp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, | |||
1700 | sizeof (struct GNUNET_TUN_Layer2PacketHeader) + | 1840 | sizeof (struct GNUNET_TUN_Layer2PacketHeader) + |
1701 | mlen; | 1841 | mlen; |
1702 | { | 1842 | { |
1703 | char buf[size]; | 1843 | char buf[size + sizeof (struct GNUNET_TUN_IPv6Header) + 8]; |
1704 | struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf; | 1844 | struct GNUNET_MessageHeader *msg = (struct GNUNET_MessageHeader *) buf; |
1705 | struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1]; | 1845 | struct GNUNET_TUN_Layer2PacketHeader *tun = (struct GNUNET_TUN_Layer2PacketHeader*) &msg[1]; |
1706 | struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1]; | 1846 | struct GNUNET_TUN_IPv6Header *ipv6 = (struct GNUNET_TUN_IPv6Header *) &tun[1]; |
1707 | struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1]; | 1847 | struct GNUNET_TUN_IcmpHeader *icmp = (struct GNUNET_TUN_IcmpHeader *) &ipv6[1]; |
1708 | msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); | 1848 | msg->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); |
1709 | msg->size = htons (size); | ||
1710 | tun->flags = htons (0); | 1849 | tun->flags = htons (0); |
1711 | tun->proto = htons (ETH_P_IPV6); | 1850 | tun->proto = htons (ETH_P_IPV6); |
1712 | GNUNET_TUN_initialize_ipv6_header (ipv6, | 1851 | GNUNET_TUN_initialize_ipv6_header (ipv6, |
@@ -1718,7 +1857,108 @@ receive_icmp_back (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, | |||
1718 | memcpy (&icmp[1], | 1857 | memcpy (&icmp[1], |
1719 | &i2v[1], | 1858 | &i2v[1], |
1720 | mlen); | 1859 | mlen); |
1721 | /* FIXME: for some ICMP types, we need to adjust the payload here... */ | 1860 | |
1861 | /* For some ICMP types, we need to adjust (make up) the payload here. | ||
1862 | Also, depending on the AF used on the other side, we have to | ||
1863 | do ICMP PT (translate ICMP types) */ | ||
1864 | switch (ntohl (i2v->af)) | ||
1865 | { | ||
1866 | case AF_INET: | ||
1867 | /* ICMP PT 4-to-6 and possibly making up payloads */ | ||
1868 | switch (icmp->type) | ||
1869 | { | ||
1870 | case GNUNET_TUN_ICMPTYPE_ECHO_REPLY: | ||
1871 | icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REPLY; | ||
1872 | break; | ||
1873 | case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST: | ||
1874 | icmp->type = GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST; | ||
1875 | break; | ||
1876 | case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE: | ||
1877 | icmp->type = GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE; | ||
1878 | { | ||
1879 | struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1]; | ||
1880 | struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1]; | ||
1881 | |||
1882 | if (mlen != 0) | ||
1883 | { | ||
1884 | /* sender did not strip ICMP payload? */ | ||
1885 | GNUNET_break_op (0); | ||
1886 | return GNUNET_SYSERR; | ||
1887 | } | ||
1888 | size += sizeof (struct GNUNET_TUN_IPv6Header) + 8; | ||
1889 | GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); | ||
1890 | make_up_icmpv6_payload (ts, ipp, udp); | ||
1891 | } | ||
1892 | break; | ||
1893 | case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED: | ||
1894 | icmp->type = GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED; | ||
1895 | { | ||
1896 | struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1]; | ||
1897 | struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1]; | ||
1898 | |||
1899 | if (mlen != 0) | ||
1900 | { | ||
1901 | /* sender did not strip ICMP payload? */ | ||
1902 | GNUNET_break_op (0); | ||
1903 | return GNUNET_SYSERR; | ||
1904 | } | ||
1905 | size += sizeof (struct GNUNET_TUN_IPv6Header) + 8; | ||
1906 | GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); | ||
1907 | make_up_icmpv6_payload (ts, ipp, udp); | ||
1908 | } | ||
1909 | break; | ||
1910 | case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH: | ||
1911 | GNUNET_STATISTICS_update (stats, | ||
1912 | gettext_noop ("# ICMPv4 packets dropped (impossible PT to v6)"), | ||
1913 | 1, GNUNET_NO); | ||
1914 | return GNUNET_OK; | ||
1915 | default: | ||
1916 | GNUNET_break_op (0); | ||
1917 | GNUNET_STATISTICS_update (stats, | ||
1918 | gettext_noop ("# ICMPv4 packets dropped (type not allowed)"), | ||
1919 | 1, GNUNET_NO); | ||
1920 | return GNUNET_SYSERR; | ||
1921 | } | ||
1922 | /* end AF_INET */ | ||
1923 | break; | ||
1924 | case AF_INET6: | ||
1925 | switch (icmp->type) | ||
1926 | { | ||
1927 | case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE: | ||
1928 | case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED: | ||
1929 | case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG: | ||
1930 | case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM: | ||
1931 | { | ||
1932 | struct GNUNET_TUN_IPv6Header *ipp = (struct GNUNET_TUN_IPv6Header *) &icmp[1]; | ||
1933 | struct GNUNET_TUN_UdpHeader *udp = (struct GNUNET_TUN_UdpHeader *) &ipp[1]; | ||
1934 | |||
1935 | if (mlen != 0) | ||
1936 | { | ||
1937 | /* sender did not strip ICMP payload? */ | ||
1938 | GNUNET_break_op (0); | ||
1939 | return GNUNET_SYSERR; | ||
1940 | } | ||
1941 | size += sizeof (struct GNUNET_TUN_IPv6Header) + 8; | ||
1942 | GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader)); | ||
1943 | make_up_icmpv6_payload (ts, ipp, udp); | ||
1944 | } | ||
1945 | break; | ||
1946 | case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST: | ||
1947 | break; | ||
1948 | default: | ||
1949 | GNUNET_break_op (0); | ||
1950 | GNUNET_STATISTICS_update (stats, | ||
1951 | gettext_noop ("# ICMPv6 packets dropped (type not allowed)"), | ||
1952 | 1, GNUNET_NO); | ||
1953 | return GNUNET_SYSERR; | ||
1954 | } | ||
1955 | /* end AF_INET6 */ | ||
1956 | break; | ||
1957 | default: | ||
1958 | GNUNET_break_op (0); | ||
1959 | return GNUNET_SYSERR; | ||
1960 | } | ||
1961 | msg->size = htons (size); | ||
1722 | GNUNET_TUN_calculate_icmp_checksum (icmp, | 1962 | GNUNET_TUN_calculate_icmp_checksum (icmp, |
1723 | &i2v[1], mlen); | 1963 | &i2v[1], mlen); |
1724 | (void) GNUNET_HELPER_send (helper_handle, | 1964 | (void) GNUNET_HELPER_send (helper_handle, |