aboutsummaryrefslogtreecommitdiff
path: root/src/vpn
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2012-01-21 20:05:03 +0000
committerChristian Grothoff <christian@grothoff.org>2012-01-21 20:05:03 +0000
commitb53c68458d1b7daa7a4320adb401daac62c4daed (patch)
tree30b8e4f0a249c225604f1d101b5dd4005dac67c0 /src/vpn
parentee731605205a1629d672e65e8372167460bb9f45 (diff)
downloadgnunet-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.c252
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 */
1611static void
1612make_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 */
1630static void
1631make_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,