diff options
Diffstat (limited to 'src/vpn/gnunet-service-dns.c')
-rw-r--r-- | src/vpn/gnunet-service-dns.c | 182 |
1 files changed, 117 insertions, 65 deletions
diff --git a/src/vpn/gnunet-service-dns.c b/src/vpn/gnunet-service-dns.c index a735788b1..6e194ac73 100644 --- a/src/vpn/gnunet-service-dns.c +++ b/src/vpn/gnunet-service-dns.c | |||
@@ -83,13 +83,14 @@ static struct answer_packet_list *tail; | |||
83 | * some information needed to handle this query | 83 | * some information needed to handle this query |
84 | * | 84 | * |
85 | * It currently allocates at least | 85 | * It currently allocates at least |
86 | * (1 + machine-width + 32 + 32 + 16 + machine-width + 8) * 65536 bit | 86 | * (1 + machine-width + machine-width + 32 + 32 + 16 + machine-width + 8) * 65536 bit |
87 | * = 1.7 MiB on 64 bit. | 87 | * = 17 MiB on 64 bit. |
88 | * = 1.2 MiB on 32 bit. | 88 | * = 11 MiB on 32 bit. |
89 | */ | 89 | */ |
90 | static struct { | 90 | static struct { |
91 | unsigned valid:1; | 91 | unsigned valid:1; |
92 | struct GNUNET_SERVER_Client* client; | 92 | struct GNUNET_SERVER_Client* client; |
93 | struct GNUNET_MESH_Tunnel *tunnel; | ||
93 | uint32_t local_ip; | 94 | uint32_t local_ip; |
94 | uint32_t remote_ip; | 95 | uint32_t remote_ip; |
95 | uint16_t local_port; | 96 | uint16_t local_port; |
@@ -202,6 +203,26 @@ struct tunnel_cls { | |||
202 | 203 | ||
203 | struct tunnel_cls *remote_pending[UINT16_MAX]; | 204 | struct tunnel_cls *remote_pending[UINT16_MAX]; |
204 | 205 | ||
206 | static size_t | ||
207 | mesh_send_response (void *cls, size_t size, void *buf) | ||
208 | { | ||
209 | GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); | ||
210 | struct GNUNET_MessageHeader *hdr = buf; | ||
211 | uint32_t *sz = cls; | ||
212 | struct dns_pkt *dns = (struct dns_pkt *) (sz + 1); | ||
213 | hdr->type = htons (GNUNET_MESSAGE_TYPE_REMOTE_ANSWER_DNS); | ||
214 | hdr->size = htons (*sz + sizeof (struct GNUNET_MessageHeader)); | ||
215 | |||
216 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, | ||
217 | "Sending response, size=%d, sz=%d, sz+hdr=%d\n", size, *sz, | ||
218 | *sz + sizeof (struct GNUNET_MessageHeader)); | ||
219 | |||
220 | GNUNET_assert (size >= (*sz + sizeof (struct GNUNET_MessageHeader))); | ||
221 | |||
222 | memcpy (hdr + 1, dns, *sz); | ||
223 | GNUNET_free (cls); | ||
224 | return ntohs (hdr->size); | ||
225 | } | ||
205 | 226 | ||
206 | static size_t | 227 | static size_t |
207 | mesh_send (void *cls, size_t size, void *buf) | 228 | mesh_send (void *cls, size_t size, void *buf) |
@@ -259,6 +280,23 @@ receive_mesh_query (void *cls, | |||
259 | const struct GNUNET_MessageHeader *message, | 280 | const struct GNUNET_MessageHeader *message, |
260 | const struct GNUNET_TRANSPORT_ATS_Information *atsi) | 281 | const struct GNUNET_TRANSPORT_ATS_Information *atsi) |
261 | { | 282 | { |
283 | struct dns_pkt *dns = (struct dns_pkt*)(message + 1); | ||
284 | |||
285 | struct sockaddr_in dest; | ||
286 | memset(&dest, 0, sizeof dest); | ||
287 | dest.sin_port = htons(53); | ||
288 | /* TODO: read from config */ | ||
289 | inet_pton(AF_INET, "8.8.8.8", &dest.sin_addr); | ||
290 | |||
291 | query_states[dns->s.id].tunnel = tunnel; | ||
292 | query_states[dns->s.id].valid = GNUNET_YES; | ||
293 | |||
294 | GNUNET_NETWORK_socket_sendto(dnsout, | ||
295 | dns, | ||
296 | ntohs(message->size) - sizeof(struct GNUNET_MessageHeader), | ||
297 | (struct sockaddr*) &dest, | ||
298 | sizeof dest); | ||
299 | |||
262 | return GNUNET_SYSERR; | 300 | return GNUNET_SYSERR; |
263 | } | 301 | } |
264 | 302 | ||
@@ -764,75 +802,89 @@ open_port () | |||
764 | * Read a response-packet of the UDP-Socket | 802 | * Read a response-packet of the UDP-Socket |
765 | */ | 803 | */ |
766 | static void | 804 | static void |
767 | read_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) { | 805 | read_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) |
768 | struct sockaddr_in addr; | 806 | { |
769 | socklen_t addrlen = sizeof (addr); | 807 | struct sockaddr_in addr; |
770 | int r; | 808 | socklen_t addrlen = sizeof (addr); |
771 | int len; | 809 | int r; |
810 | int len; | ||
772 | 811 | ||
773 | if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) | 812 | if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) |
774 | return; | 813 | return; |
775 | 814 | ||
776 | memset(&addr, 0, sizeof addr); | 815 | memset (&addr, 0, sizeof addr); |
777 | 816 | ||
778 | #ifndef MINGW | 817 | #ifndef MINGW |
779 | if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout), | 818 | if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout), FIONREAD, &len)) |
780 | FIONREAD, &len)) | 819 | { |
820 | unhijack (dnsoutport); | ||
821 | open_port (); | ||
822 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, hijack, NULL); | ||
823 | return; | ||
824 | } | ||
825 | #else | ||
826 | /* port the code above? */ | ||
827 | len = 65536; | ||
828 | #endif | ||
829 | { | ||
830 | unsigned char buf[len]; | ||
831 | struct dns_pkt *dns = (struct dns_pkt *) buf; | ||
832 | |||
833 | r = GNUNET_NETWORK_socket_recvfrom (dnsout, | ||
834 | buf, | ||
835 | sizeof (buf), | ||
836 | (struct sockaddr *) &addr, &addrlen); | ||
837 | |||
838 | if (r < 0) | ||
781 | { | 839 | { |
782 | unhijack(dnsoutport); | 840 | unhijack (dnsoutport); |
783 | open_port(); | 841 | open_port (); |
784 | GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_SECONDS, hijack, NULL); | 842 | GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, hijack, NULL); |
785 | return; | 843 | return; |
786 | } | 844 | } |
787 | #else | 845 | |
788 | /* port the code above? */ | 846 | if (query_states[dns->s.id].valid == GNUNET_YES) |
789 | len = 65536; | 847 | { |
790 | #endif | 848 | if (query_states[dns->s.id].tunnel != NULL) |
791 | { | 849 | { |
792 | unsigned char buf[len]; | 850 | uint32_t *c = GNUNET_malloc(4 + r); |
793 | struct dns_pkt* dns = (struct dns_pkt*)buf; | 851 | *c = r; |
794 | 852 | memcpy(c+1, dns, r); | |
795 | r = GNUNET_NETWORK_socket_recvfrom (dnsout, | 853 | GNUNET_MESH_notify_transmit_ready (query_states[dns->s.id].tunnel, |
796 | buf, | 854 | GNUNET_YES, |
797 | sizeof (buf), | 855 | 32, |
798 | (struct sockaddr*)&addr, | 856 | GNUNET_TIME_UNIT_MINUTES, |
799 | &addrlen); | 857 | NULL, r + sizeof(struct GNUNET_MessageHeader), mesh_send_response, c); |
800 | 858 | } | |
801 | if (r < 0) | 859 | else |
802 | { | 860 | { |
803 | unhijack(dnsoutport); | 861 | query_states[dns->s.id].valid = GNUNET_NO; |
804 | open_port(); | 862 | |
805 | GNUNET_SCHEDULER_add_delayed(GNUNET_TIME_UNIT_SECONDS, hijack, NULL); | 863 | size_t len = sizeof (struct answer_packet) + r - 1; /* 1 for the unsigned char data[1]; */ |
806 | return; | 864 | struct answer_packet_list *answer = |
807 | } | 865 | GNUNET_malloc (len + 2 * sizeof (struct answer_packet_list *)); |
808 | 866 | answer->pkt.hdr.type = | |
809 | if (query_states[dns->s.id].valid == GNUNET_YES) | 867 | htons (GNUNET_MESSAGE_TYPE_LOCAL_RESPONSE_DNS); |
810 | { | 868 | answer->pkt.hdr.size = htons (len); |
811 | query_states[dns->s.id].valid = GNUNET_NO; | 869 | answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_IP; |
812 | 870 | answer->pkt.from = addr.sin_addr.s_addr; | |
813 | size_t len = sizeof(struct answer_packet) + r - 1; /* 1 for the unsigned char data[1]; */ | 871 | answer->pkt.to = query_states[dns->s.id].local_ip; |
814 | struct answer_packet_list* answer = GNUNET_malloc(len + 2*sizeof(struct answer_packet_list*)); | 872 | answer->pkt.dst_port = query_states[dns->s.id].local_port; |
815 | answer->pkt.hdr.type = htons(GNUNET_MESSAGE_TYPE_LOCAL_RESPONSE_DNS); | 873 | memcpy (answer->pkt.data, buf, r); |
816 | answer->pkt.hdr.size = htons(len); | 874 | |
817 | answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_IP; | 875 | GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer); |
818 | answer->pkt.from = addr.sin_addr.s_addr; | 876 | |
819 | answer->pkt.to = query_states[dns->s.id].local_ip; | 877 | GNUNET_SERVER_notify_transmit_ready (query_states[dns->s.id]. |
820 | answer->pkt.dst_port = query_states[dns->s.id].local_port; | 878 | client, len, |
821 | memcpy(answer->pkt.data, buf, r); | 879 | GNUNET_TIME_UNIT_FOREVER_REL, |
822 | 880 | &send_answer, | |
823 | GNUNET_CONTAINER_DLL_insert_after(head, tail, tail, answer); | 881 | query_states[dns->s.id]. |
824 | 882 | client); | |
825 | GNUNET_SERVER_notify_transmit_ready(query_states[dns->s.id].client, | 883 | } |
826 | len, | 884 | } |
827 | GNUNET_TIME_UNIT_FOREVER_REL, | 885 | } |
828 | &send_answer, | 886 | GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, |
829 | query_states[dns->s.id].client); | 887 | dnsout, &read_response, NULL); |
830 | } | ||
831 | } | ||
832 | GNUNET_SCHEDULER_add_read_net(GNUNET_TIME_UNIT_FOREVER_REL, | ||
833 | dnsout, | ||
834 | &read_response, | ||
835 | NULL); | ||
836 | } | 888 | } |
837 | 889 | ||
838 | 890 | ||