diff options
Diffstat (limited to 'src/exit')
-rw-r--r-- | src/exit/exit.h | 83 | ||||
-rw-r--r-- | src/exit/gnunet-daemon-exit.c | 478 |
2 files changed, 559 insertions, 2 deletions
diff --git a/src/exit/exit.h b/src/exit/exit.h index 3cd4292bd..92918b92a 100644 --- a/src/exit/exit.h +++ b/src/exit/exit.h | |||
@@ -206,4 +206,87 @@ struct GNUNET_EXIT_UdpReplyMessage | |||
206 | }; | 206 | }; |
207 | 207 | ||
208 | 208 | ||
209 | /** | ||
210 | * Message send via mesh to an exit daemon to send | ||
211 | * ICMP data to a local service. | ||
212 | */ | ||
213 | struct GNUNET_EXIT_IcmpServiceMessage | ||
214 | { | ||
215 | /** | ||
216 | * Type is GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE | ||
217 | */ | ||
218 | struct GNUNET_MessageHeader header; | ||
219 | |||
220 | /** | ||
221 | * Address family, AF_INET or AF_INET6, in network byte order. | ||
222 | */ | ||
223 | int32_t af; | ||
224 | |||
225 | /** | ||
226 | * Identification for the desired service. | ||
227 | */ | ||
228 | GNUNET_HashCode service_descriptor; | ||
229 | |||
230 | /** | ||
231 | * ICMP header to use. | ||
232 | */ | ||
233 | struct GNUNET_TUN_IcmpHeader icmp_header; | ||
234 | |||
235 | /* followed by ICMP payload */ | ||
236 | }; | ||
237 | |||
238 | |||
239 | /** | ||
240 | * Message send via mesh to an exit daemon to forward | ||
241 | * ICMP data to the Internet. | ||
242 | */ | ||
243 | struct GNUNET_EXIT_IcmpInternetMessage | ||
244 | { | ||
245 | /** | ||
246 | * Type is GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET | ||
247 | */ | ||
248 | struct GNUNET_MessageHeader header; | ||
249 | |||
250 | /** | ||
251 | * Address family, AF_INET or AF_INET6, in network byte order. | ||
252 | */ | ||
253 | int32_t af; | ||
254 | |||
255 | /** | ||
256 | * ICMP header to use. | ||
257 | */ | ||
258 | struct GNUNET_TUN_IcmpHeader icmp_header; | ||
259 | |||
260 | /* followed by IP address of the destination; either | ||
261 | 'struct in_addr' or 'struct in6_addr', depending on af */ | ||
262 | |||
263 | /* followed by ICMP payload */ | ||
264 | }; | ||
265 | |||
266 | |||
267 | /** | ||
268 | * Message send via mesh to the vpn service to send | ||
269 | * ICMP data to the VPN's TUN interface. | ||
270 | */ | ||
271 | struct GNUNET_EXIT_IcmpToVPNMessage | ||
272 | { | ||
273 | /** | ||
274 | * Type is GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN | ||
275 | */ | ||
276 | struct GNUNET_MessageHeader header; | ||
277 | |||
278 | /** | ||
279 | * Address family, AF_INET or AF_INET6, in network byte order. | ||
280 | */ | ||
281 | int32_t af; | ||
282 | |||
283 | /** | ||
284 | * ICMP header to use. | ||
285 | */ | ||
286 | struct GNUNET_TUN_IcmpHeader icmp_header; | ||
287 | |||
288 | /* followed by ICMP payload */ | ||
289 | }; | ||
290 | |||
291 | |||
209 | #endif | 292 | #endif |
diff --git a/src/exit/gnunet-daemon-exit.c b/src/exit/gnunet-daemon-exit.c index 8e29351f8..7201c61cc 100644 --- a/src/exit/gnunet-daemon-exit.c +++ b/src/exit/gnunet-daemon-exit.c | |||
@@ -565,6 +565,188 @@ send_packet_to_mesh_tunnel (struct GNUNET_MESH_Tunnel *mesh_tunnel, | |||
565 | 565 | ||
566 | 566 | ||
567 | /** | 567 | /** |
568 | * @brief Handles an ICMP packet received from the helper. | ||
569 | * | ||
570 | * @param icmp A pointer to the Packet | ||
571 | * @param pktlen number of bytes in 'icmp' | ||
572 | * @param af address family (AFINET or AF_INET6) | ||
573 | * @param destination_ip destination IP-address of the IP packet (should | ||
574 | * be our local address) | ||
575 | * @param source_ip original source IP-address of the IP packet (should | ||
576 | * be the original destination address) | ||
577 | */ | ||
578 | static void | ||
579 | icmp_from_helper (const struct GNUNET_TUN_IcmpHeader *icmp, | ||
580 | size_t pktlen, | ||
581 | int af, | ||
582 | const void *destination_ip, | ||
583 | const void *source_ip) | ||
584 | { | ||
585 | struct TunnelState *state; | ||
586 | struct TunnelMessageQueue *tnq; | ||
587 | struct GNUNET_EXIT_IcmpToVPNMessage *i2v; | ||
588 | const struct GNUNET_TUN_IPv4Header *ipv4; | ||
589 | const struct GNUNET_TUN_IPv6Header *ipv6; | ||
590 | const struct GNUNET_TUN_UdpHeader *udp; | ||
591 | size_t mlen; | ||
592 | uint16_t spt; | ||
593 | uint16_t dpt; | ||
594 | uint8_t protocol; | ||
595 | |||
596 | { | ||
597 | char sbuf[INET6_ADDRSTRLEN]; | ||
598 | char dbuf[INET6_ADDRSTRLEN]; | ||
599 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
600 | "Received ICMP packet going from %s to %s\n", | ||
601 | inet_ntop (af, | ||
602 | source_ip, | ||
603 | sbuf, sizeof (sbuf)), | ||
604 | inet_ntop (af, | ||
605 | source_ip, | ||
606 | dbuf, sizeof (dbuf))); | ||
607 | } | ||
608 | if (pktlen < sizeof (struct GNUNET_TUN_IcmpHeader)) | ||
609 | { | ||
610 | /* blame kernel */ | ||
611 | GNUNET_break (0); | ||
612 | return; | ||
613 | } | ||
614 | |||
615 | /* Find out if this is an ICMP packet in response to an existing | ||
616 | TCP/UDP packet and if so, figure out ports / protocol of the | ||
617 | existing session from the IP data in the ICMP payload */ | ||
618 | spt = 0; | ||
619 | dpt = 0; | ||
620 | protocol = IPPROTO_ICMP; | ||
621 | switch (af) | ||
622 | { | ||
623 | case AF_INET: | ||
624 | switch (icmp->type) | ||
625 | { | ||
626 | case GNUNET_TUN_ICMPTYPE_ECHO_REPLY: | ||
627 | case GNUNET_TUN_ICMPTYPE_ECHO_REQUEST: | ||
628 | break; | ||
629 | case GNUNET_TUN_ICMPTYPE_DESTINATION_UNREACHABLE: | ||
630 | case GNUNET_TUN_ICMPTYPE_SOURCE_QUENCH: | ||
631 | case GNUNET_TUN_ICMPTYPE_TIME_EXCEEDED: | ||
632 | if (pktlen < | ||
633 | sizeof (struct GNUNET_TUN_IcmpHeader) + | ||
634 | sizeof (struct GNUNET_TUN_IPv4Header) + 8) | ||
635 | { | ||
636 | /* blame kernel */ | ||
637 | GNUNET_break (0); | ||
638 | return; | ||
639 | } | ||
640 | ipv4 = (const struct GNUNET_TUN_IPv4Header *) &icmp[1]; | ||
641 | protocol = ipv4->protocol; | ||
642 | /* could be TCP or UDP, but both have the ports in the right | ||
643 | place, so that doesn't matter here */ | ||
644 | udp = (const struct GNUNET_TUN_UdpHeader *) &ipv4[1]; | ||
645 | spt = ntohs (udp->spt); | ||
646 | dpt = ntohs (udp->dpt); | ||
647 | break; | ||
648 | default: | ||
649 | GNUNET_STATISTICS_update (stats, | ||
650 | gettext_noop ("# ICMP packets dropped (not allowed)"), | ||
651 | 1, GNUNET_NO); | ||
652 | return; | ||
653 | } | ||
654 | break; | ||
655 | case AF_INET6: | ||
656 | switch (icmp->type) | ||
657 | { | ||
658 | case GNUNET_TUN_ICMPTYPE6_DESTINATION_UNREACHABLE: | ||
659 | case GNUNET_TUN_ICMPTYPE6_PACKET_TOO_BIG: | ||
660 | case GNUNET_TUN_ICMPTYPE6_TIME_EXCEEDED: | ||
661 | case GNUNET_TUN_ICMPTYPE6_PARAMETER_PROBLEM: | ||
662 | if (pktlen < | ||
663 | sizeof (struct GNUNET_TUN_IcmpHeader) + | ||
664 | sizeof (struct GNUNET_TUN_IPv6Header) + 8) | ||
665 | { | ||
666 | /* blame kernel */ | ||
667 | GNUNET_break (0); | ||
668 | return; | ||
669 | } | ||
670 | ipv6 = (const struct GNUNET_TUN_IPv6Header *) &icmp[1]; | ||
671 | protocol = ipv6->next_header; | ||
672 | /* could be TCP or UDP, but both have the ports in the right | ||
673 | place, so that doesn't matter here */ | ||
674 | udp = (const struct GNUNET_TUN_UdpHeader *) &ipv6[1]; | ||
675 | spt = ntohs (udp->spt); | ||
676 | dpt = ntohs (udp->dpt); | ||
677 | break; | ||
678 | case GNUNET_TUN_ICMPTYPE6_ECHO_REQUEST: | ||
679 | case GNUNET_TUN_ICMPTYPE6_ECHO_REPLY: | ||
680 | break; | ||
681 | default: | ||
682 | GNUNET_STATISTICS_update (stats, | ||
683 | gettext_noop ("# ICMP packets dropped (not allowed)"), | ||
684 | 1, GNUNET_NO); | ||
685 | return; | ||
686 | } | ||
687 | break; | ||
688 | default: | ||
689 | GNUNET_assert (0); | ||
690 | } | ||
691 | switch (protocol) | ||
692 | { | ||
693 | case IPPROTO_ICMP: | ||
694 | state = get_redirect_state (af, IPPROTO_ICMP, | ||
695 | source_ip, 0, | ||
696 | destination_ip, 0, | ||
697 | NULL); | ||
698 | break; | ||
699 | case IPPROTO_UDP: | ||
700 | state = get_redirect_state (af, IPPROTO_UDP, | ||
701 | source_ip, | ||
702 | spt, | ||
703 | destination_ip, | ||
704 | dpt, | ||
705 | NULL); | ||
706 | break; | ||
707 | case IPPROTO_TCP: | ||
708 | state = get_redirect_state (af, IPPROTO_TCP, | ||
709 | source_ip, | ||
710 | spt, | ||
711 | destination_ip, | ||
712 | dpt, | ||
713 | NULL); | ||
714 | break; | ||
715 | default: | ||
716 | GNUNET_STATISTICS_update (stats, | ||
717 | gettext_noop ("# ICMP packets dropped (not allowed)"), | ||
718 | 1, GNUNET_NO); | ||
719 | return; | ||
720 | } | ||
721 | if (NULL == state) | ||
722 | { | ||
723 | GNUNET_log (GNUNET_ERROR_TYPE_INFO, | ||
724 | _("Packet dropped, have no matching connection information\n")); | ||
725 | return; | ||
726 | } | ||
727 | mlen = sizeof (struct GNUNET_EXIT_IcmpToVPNMessage) + pktlen - sizeof (struct GNUNET_TUN_IcmpHeader); | ||
728 | tnq = GNUNET_malloc (sizeof (struct TunnelMessageQueue) + mlen); | ||
729 | tnq->payload = &tnq[1]; | ||
730 | tnq->len = mlen; | ||
731 | i2v = (struct GNUNET_EXIT_IcmpToVPNMessage *) &tnq[1]; | ||
732 | i2v->header.size = htons ((uint16_t) mlen); | ||
733 | i2v->header.type = htons (GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_VPN); | ||
734 | i2v->af = htonl (af); | ||
735 | memcpy (&i2v->icmp_header, | ||
736 | icmp, | ||
737 | pktlen); | ||
738 | /* FIXME: should we sanitize the host-specific payload here? On the | ||
739 | one hand, quite a bit of what we send is meaningless on the other | ||
740 | side (our IPs, ports, etc.); on the other hand, trying to compact | ||
741 | the packet would be very messy, and blanking fields out is also | ||
742 | hardly productive as they seem to contain nothing remotely | ||
743 | sensitive. */ | ||
744 | send_packet_to_mesh_tunnel (state->tunnel, | ||
745 | tnq); | ||
746 | } | ||
747 | |||
748 | |||
749 | /** | ||
568 | * @brief Handles an UDP packet received from the helper. | 750 | * @brief Handles an UDP packet received from the helper. |
569 | * | 751 | * |
570 | * @param udp A pointer to the Packet | 752 | * @param udp A pointer to the Packet |
@@ -808,6 +990,12 @@ message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED, | |||
808 | &pkt4->destination_address, | 990 | &pkt4->destination_address, |
809 | &pkt4->source_address); | 991 | &pkt4->source_address); |
810 | break; | 992 | break; |
993 | case IPPROTO_ICMP: | ||
994 | icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt4[1], size, | ||
995 | AF_INET, | ||
996 | &pkt4->destination_address, | ||
997 | &pkt4->source_address); | ||
998 | break; | ||
811 | default: | 999 | default: |
812 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 1000 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
813 | _("IPv4 packet with unsupported next header received. Ignored.\n")); | 1001 | _("IPv4 packet with unsupported next header received. Ignored.\n")); |
@@ -847,6 +1035,12 @@ message_token (void *cls GNUNET_UNUSED, void *client GNUNET_UNUSED, | |||
847 | &pkt6->destination_address, | 1035 | &pkt6->destination_address, |
848 | &pkt6->source_address); | 1036 | &pkt6->source_address); |
849 | break; | 1037 | break; |
1038 | case IPPROTO_ICMP: | ||
1039 | icmp_from_helper ((const struct GNUNET_TUN_IcmpHeader *) &pkt6[1], size, | ||
1040 | AF_INET6, | ||
1041 | &pkt6->destination_address, | ||
1042 | &pkt6->source_address); | ||
1043 | break; | ||
850 | default: | 1044 | default: |
851 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, | 1045 | GNUNET_log (GNUNET_ERROR_TYPE_WARNING, |
852 | _("IPv6 packet with unsupported next header received. Ignored.\n")); | 1046 | _("IPv6 packet with unsupported next header received. Ignored.\n")); |
@@ -1465,7 +1659,7 @@ receive_tcp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, | |||
1465 | } | 1659 | } |
1466 | v6 = (const struct in6_addr*) &start[1]; | 1660 | v6 = (const struct in6_addr*) &start[1]; |
1467 | payload = &v6[1]; | 1661 | payload = &v6[1]; |
1468 | pkt_len -= sizeof (struct in_addr); | 1662 | pkt_len -= sizeof (struct in6_addr); |
1469 | state->ri.remote_address.address.ipv6 = *v6; | 1663 | state->ri.remote_address.address.ipv6 = *v6; |
1470 | break; | 1664 | break; |
1471 | default: | 1665 | default: |
@@ -1562,6 +1756,284 @@ receive_tcp_data (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, | |||
1562 | 1756 | ||
1563 | 1757 | ||
1564 | /** | 1758 | /** |
1759 | * Send an ICMP packet via the TUN interface. | ||
1760 | * | ||
1761 | * @param destination_address IP to use for the ICMP packet's destination | ||
1762 | * @param source_address IP to use for the ICMP packet's source | ||
1763 | * @param icmp_header ICMP header to send | ||
1764 | * @param payload payload of the ICMP packet (does NOT include ICMP header) | ||
1765 | * @param payload_length number of bytes of data in payload | ||
1766 | */ | ||
1767 | static void | ||
1768 | send_icmp_packet_via_tun (const struct SocketAddress *destination_address, | ||
1769 | const struct SocketAddress *source_address, | ||
1770 | const struct GNUNET_TUN_IcmpHeader *icmp_header, | ||
1771 | const void *payload, size_t payload_length) | ||
1772 | { | ||
1773 | size_t len; | ||
1774 | struct GNUNET_TUN_IcmpHeader *icmp; | ||
1775 | |||
1776 | GNUNET_STATISTICS_update (stats, | ||
1777 | gettext_noop ("# ICMP packets sent via TUN"), | ||
1778 | 1, GNUNET_NO); | ||
1779 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1780 | "Sending packet with %u bytes ICMP payload via TUN\n", | ||
1781 | (unsigned int) payload_length); | ||
1782 | len = sizeof (struct GNUNET_MessageHeader) + sizeof (struct GNUNET_TUN_Layer2PacketHeader); | ||
1783 | switch (destination_address->af) | ||
1784 | { | ||
1785 | case AF_INET: | ||
1786 | len += sizeof (struct GNUNET_TUN_IPv4Header); | ||
1787 | break; | ||
1788 | case AF_INET6: | ||
1789 | len += sizeof (struct GNUNET_TUN_IPv6Header); | ||
1790 | break; | ||
1791 | default: | ||
1792 | GNUNET_break (0); | ||
1793 | return; | ||
1794 | } | ||
1795 | len += sizeof (struct GNUNET_TUN_IcmpHeader); | ||
1796 | len += payload_length; | ||
1797 | if (len >= GNUNET_SERVER_MAX_MESSAGE_SIZE) | ||
1798 | { | ||
1799 | GNUNET_break (0); | ||
1800 | return; | ||
1801 | } | ||
1802 | { | ||
1803 | char buf[len]; | ||
1804 | struct GNUNET_MessageHeader *hdr; | ||
1805 | struct GNUNET_TUN_Layer2PacketHeader *tun; | ||
1806 | |||
1807 | hdr= (struct GNUNET_MessageHeader *) buf; | ||
1808 | hdr->type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); | ||
1809 | hdr->size = htons (len); | ||
1810 | tun = (struct GNUNET_TUN_Layer2PacketHeader*) &hdr[1]; | ||
1811 | tun->flags = htons (0); | ||
1812 | switch (source_address->af) | ||
1813 | { | ||
1814 | case AF_INET: | ||
1815 | { | ||
1816 | struct GNUNET_TUN_IPv4Header * ipv4 = (struct GNUNET_TUN_IPv4Header*) &tun[1]; | ||
1817 | |||
1818 | tun->proto = htons (ETH_P_IPV4); | ||
1819 | GNUNET_TUN_initialize_ipv4_header (ipv4, | ||
1820 | IPPROTO_ICMP, | ||
1821 | sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length, | ||
1822 | &source_address->address.ipv4, | ||
1823 | &destination_address->address.ipv4); | ||
1824 | icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv4[1]; | ||
1825 | } | ||
1826 | break; | ||
1827 | case AF_INET6: | ||
1828 | { | ||
1829 | struct GNUNET_TUN_IPv6Header * ipv6 = (struct GNUNET_TUN_IPv6Header*) &tun[1]; | ||
1830 | |||
1831 | tun->proto = htons (ETH_P_IPV6); | ||
1832 | GNUNET_TUN_initialize_ipv6_header (ipv6, | ||
1833 | IPPROTO_ICMP, | ||
1834 | sizeof (struct GNUNET_TUN_IcmpHeader) + payload_length, | ||
1835 | &source_address->address.ipv6, | ||
1836 | &destination_address->address.ipv6); | ||
1837 | icmp = (struct GNUNET_TUN_IcmpHeader*) &ipv6[1]; | ||
1838 | } | ||
1839 | break; | ||
1840 | default: | ||
1841 | GNUNET_assert (0); | ||
1842 | break; | ||
1843 | } | ||
1844 | *icmp = *icmp_header; | ||
1845 | memcpy (&icmp[1], | ||
1846 | payload, | ||
1847 | payload_length); | ||
1848 | GNUNET_TUN_calculate_icmp_checksum (icmp, | ||
1849 | payload, | ||
1850 | payload_length); | ||
1851 | (void) GNUNET_HELPER_send (helper_handle, | ||
1852 | (const struct GNUNET_MessageHeader*) buf, | ||
1853 | GNUNET_YES, | ||
1854 | NULL, NULL); | ||
1855 | } | ||
1856 | } | ||
1857 | |||
1858 | |||
1859 | /** | ||
1860 | * Process a request to forward ICMP data to the Internet via this peer. | ||
1861 | * | ||
1862 | * @param cls closure, NULL | ||
1863 | * @param tunnel connection to the other end | ||
1864 | * @param tunnel_ctx pointer to our 'struct TunnelState *' | ||
1865 | * @param sender who sent the message | ||
1866 | * @param message the actual message | ||
1867 | * @param atsi performance data for the connection | ||
1868 | * @return GNUNET_OK to keep the connection open, | ||
1869 | * GNUNET_SYSERR to close it (signal serious error) | ||
1870 | */ | ||
1871 | static int | ||
1872 | receive_icmp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, | ||
1873 | void **tunnel_ctx GNUNET_UNUSED, | ||
1874 | const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED, | ||
1875 | const struct GNUNET_MessageHeader *message, | ||
1876 | const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED) | ||
1877 | { | ||
1878 | struct TunnelState *state = *tunnel_ctx; | ||
1879 | const struct GNUNET_EXIT_IcmpInternetMessage *msg; | ||
1880 | uint16_t pkt_len = ntohs (message->size); | ||
1881 | const struct in_addr *v4; | ||
1882 | const struct in6_addr *v6; | ||
1883 | const void *payload; | ||
1884 | int af; | ||
1885 | |||
1886 | GNUNET_STATISTICS_update (stats, | ||
1887 | gettext_noop ("# Bytes received from MESH"), | ||
1888 | pkt_len, GNUNET_NO); | ||
1889 | GNUNET_STATISTICS_update (stats, | ||
1890 | gettext_noop ("# ICMP IP-exit requests received via mesh"), | ||
1891 | 1, GNUNET_NO); | ||
1892 | if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpInternetMessage)) | ||
1893 | { | ||
1894 | GNUNET_break_op (0); | ||
1895 | return GNUNET_SYSERR; | ||
1896 | } | ||
1897 | msg = (const struct GNUNET_EXIT_IcmpInternetMessage*) message; | ||
1898 | pkt_len -= sizeof (struct GNUNET_EXIT_IcmpInternetMessage); | ||
1899 | |||
1900 | af = (int) ntohl (msg->af); | ||
1901 | state->ri.remote_address.af = af; | ||
1902 | switch (af) | ||
1903 | { | ||
1904 | case AF_INET: | ||
1905 | if (pkt_len < sizeof (struct in_addr)) | ||
1906 | { | ||
1907 | GNUNET_break_op (0); | ||
1908 | return GNUNET_SYSERR; | ||
1909 | } | ||
1910 | if (! ipv4_exit) | ||
1911 | { | ||
1912 | GNUNET_break_op (0); | ||
1913 | return GNUNET_SYSERR; | ||
1914 | } | ||
1915 | v4 = (const struct in_addr*) &msg[1]; | ||
1916 | payload = &v4[1]; | ||
1917 | pkt_len -= sizeof (struct in_addr); | ||
1918 | state->ri.remote_address.address.ipv4 = *v4; | ||
1919 | break; | ||
1920 | case AF_INET6: | ||
1921 | if (pkt_len < sizeof (struct in6_addr)) | ||
1922 | { | ||
1923 | GNUNET_break_op (0); | ||
1924 | return GNUNET_SYSERR; | ||
1925 | } | ||
1926 | if (! ipv6_exit) | ||
1927 | { | ||
1928 | GNUNET_break_op (0); | ||
1929 | return GNUNET_SYSERR; | ||
1930 | } | ||
1931 | v6 = (const struct in6_addr*) &msg[1]; | ||
1932 | payload = &v6[1]; | ||
1933 | pkt_len -= sizeof (struct in6_addr); | ||
1934 | state->ri.remote_address.address.ipv6 = *v6; | ||
1935 | break; | ||
1936 | default: | ||
1937 | GNUNET_break_op (0); | ||
1938 | return GNUNET_SYSERR; | ||
1939 | } | ||
1940 | |||
1941 | { | ||
1942 | char buf[INET6_ADDRSTRLEN]; | ||
1943 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
1944 | "Received ICMP data from %s for forwarding to %s\n", | ||
1945 | GNUNET_i2s (sender), | ||
1946 | inet_ntop (af, | ||
1947 | &state->ri.remote_address.address, | ||
1948 | buf, sizeof (buf))); | ||
1949 | } | ||
1950 | |||
1951 | /* FIXME: check that ICMP type is something we want to support */ | ||
1952 | |||
1953 | state->ri.remote_address.proto = IPPROTO_ICMP; | ||
1954 | state->ri.remote_address.port = 0; | ||
1955 | state->ri.local_address.port = 0; | ||
1956 | if (NULL == state->heap_node) | ||
1957 | setup_state_record (state); | ||
1958 | |||
1959 | send_icmp_packet_via_tun (&state->ri.remote_address, | ||
1960 | &state->ri.local_address, | ||
1961 | &msg->icmp_header, | ||
1962 | payload, pkt_len); | ||
1963 | return GNUNET_YES; | ||
1964 | } | ||
1965 | |||
1966 | |||
1967 | /** | ||
1968 | * Process a request via mesh to send ICMP data to a service | ||
1969 | * offered by this system. | ||
1970 | * | ||
1971 | * @param cls closure, NULL | ||
1972 | * @param tunnel connection to the other end | ||
1973 | * @param tunnel_ctx pointer to our 'struct TunnelState *' | ||
1974 | * @param sender who sent the message | ||
1975 | * @param message the actual message | ||
1976 | * @param atsi performance data for the connection | ||
1977 | * @return GNUNET_OK to keep the connection open, | ||
1978 | * GNUNET_SYSERR to close it (signal serious error) | ||
1979 | */ | ||
1980 | static int | ||
1981 | receive_icmp_service (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, | ||
1982 | void **tunnel_ctx, | ||
1983 | const struct GNUNET_PeerIdentity *sender GNUNET_UNUSED, | ||
1984 | const struct GNUNET_MessageHeader *message, | ||
1985 | const struct GNUNET_ATS_Information *atsi GNUNET_UNUSED) | ||
1986 | { | ||
1987 | struct TunnelState *state = *tunnel_ctx; | ||
1988 | const struct GNUNET_EXIT_IcmpServiceMessage *msg; | ||
1989 | uint16_t pkt_len = ntohs (message->size); | ||
1990 | |||
1991 | GNUNET_STATISTICS_update (stats, | ||
1992 | gettext_noop ("# Bytes received from MESH"), | ||
1993 | pkt_len, GNUNET_NO); | ||
1994 | GNUNET_STATISTICS_update (stats, | ||
1995 | gettext_noop ("# ICMP service requests received via mesh"), | ||
1996 | 1, GNUNET_NO); | ||
1997 | /* check that we got at least a valid header */ | ||
1998 | if (pkt_len < sizeof (struct GNUNET_EXIT_IcmpServiceMessage)) | ||
1999 | { | ||
2000 | GNUNET_break_op (0); | ||
2001 | return GNUNET_SYSERR; | ||
2002 | } | ||
2003 | msg = (const struct GNUNET_EXIT_IcmpServiceMessage*) message; | ||
2004 | pkt_len -= sizeof (struct GNUNET_EXIT_IcmpServiceMessage); | ||
2005 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
2006 | "Received data from %s for forwarding to ICMP service %s\n", | ||
2007 | GNUNET_i2s (sender), | ||
2008 | GNUNET_h2s (&msg->service_descriptor)); | ||
2009 | if (NULL == state->serv) | ||
2010 | { | ||
2011 | /* first packet to service must not be ICMP (cannot determine service!) */ | ||
2012 | GNUNET_break_op (0); | ||
2013 | return GNUNET_SYSERR; | ||
2014 | } | ||
2015 | if (state->serv->address.af != ntohl (msg->af)) | ||
2016 | { | ||
2017 | GNUNET_STATISTICS_update (stats, | ||
2018 | gettext_noop ("# ICMP service requests discarded (incompatible af)"), | ||
2019 | 1, GNUNET_NO); | ||
2020 | return GNUNET_SYSERR; | ||
2021 | } | ||
2022 | |||
2023 | /* FIXME: check that ICMP type is something we want to support */ | ||
2024 | |||
2025 | state->ri.remote_address = state->serv->address; | ||
2026 | setup_state_record (state); | ||
2027 | |||
2028 | send_icmp_packet_via_tun (&state->ri.remote_address, | ||
2029 | &state->ri.local_address, | ||
2030 | &msg->icmp_header, | ||
2031 | &msg[1], pkt_len); | ||
2032 | return GNUNET_YES; | ||
2033 | } | ||
2034 | |||
2035 | |||
2036 | /** | ||
1565 | * Send a UDP packet via the TUN interface. | 2037 | * Send a UDP packet via the TUN interface. |
1566 | * | 2038 | * |
1567 | * @param destination_address IP and port to use for the UDP packet's destination | 2039 | * @param destination_address IP and port to use for the UDP packet's destination |
@@ -1725,7 +2197,7 @@ receive_udp_remote (void *cls GNUNET_UNUSED, struct GNUNET_MESH_Tunnel *tunnel, | |||
1725 | } | 2197 | } |
1726 | v6 = (const struct in6_addr*) &msg[1]; | 2198 | v6 = (const struct in6_addr*) &msg[1]; |
1727 | payload = &v6[1]; | 2199 | payload = &v6[1]; |
1728 | pkt_len -= sizeof (struct in_addr); | 2200 | pkt_len -= sizeof (struct in6_addr); |
1729 | state->ri.remote_address.address.ipv6 = *v6; | 2201 | state->ri.remote_address.address.ipv6 = *v6; |
1730 | break; | 2202 | break; |
1731 | default: | 2203 | default: |
@@ -2144,6 +2616,8 @@ run (void *cls, char *const *args GNUNET_UNUSED, | |||
2144 | const struct GNUNET_CONFIGURATION_Handle *cfg_) | 2616 | const struct GNUNET_CONFIGURATION_Handle *cfg_) |
2145 | { | 2617 | { |
2146 | static struct GNUNET_MESH_MessageHandler handlers[] = { | 2618 | static struct GNUNET_MESH_MessageHandler handlers[] = { |
2619 | {&receive_icmp_service, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_SERVICE, 0}, | ||
2620 | {&receive_icmp_remote, GNUNET_MESSAGE_TYPE_VPN_ICMP_TO_INTERNET, 0}, | ||
2147 | {&receive_udp_service, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE, 0}, | 2621 | {&receive_udp_service, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_SERVICE, 0}, |
2148 | {&receive_udp_remote, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET, 0}, | 2622 | {&receive_udp_remote, GNUNET_MESSAGE_TYPE_VPN_UDP_TO_INTERNET, 0}, |
2149 | {&receive_tcp_service, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START, 0}, | 2623 | {&receive_tcp_service, GNUNET_MESSAGE_TYPE_VPN_TCP_TO_SERVICE_START, 0}, |