From: Philipp Tölke Date: Wed, 26 Oct 2011 07:13:23 +0000 (+0000) Subject: handle dns over ipv6 and 6-to-4 and 4-to-6 X-Git-Tag: initial-import-from-subversion-38251~16247 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=913f88d980ef4fcc4153336042387a17ad8e428b;p=oweals%2Fgnunet.git handle dns over ipv6 and 6-to-4 and 4-to-6 --- diff --git a/contrib/defaults.conf b/contrib/defaults.conf index 3a7223a73..3b7519b18 100644 --- a/contrib/defaults.conf +++ b/contrib/defaults.conf @@ -470,6 +470,7 @@ IPV6PREFIX = 32 IPV4ADDR = 10.11.10.1 IPV4MASK = 255.255.0.0 VIRTDNS = 10.11.10.2 +VIRTDNS6 = 1234::17 IFNAME = vpn-gnunet [exit] diff --git a/src/vpn/gnunet-daemon-vpn-helper.c b/src/vpn/gnunet-daemon-vpn-helper.c index 4d2bbf819..1790c2b00 100644 --- a/src/vpn/gnunet-daemon-vpn-helper.c +++ b/src/vpn/gnunet-daemon-vpn-helper.c @@ -174,52 +174,114 @@ helper_write (void *cls GNUNET_assert (20 == sizeof (struct ip_hdr)); GNUNET_assert (8 == sizeof (struct udp_pkt)); + size_t data_len = len - sizeof (struct answer_packet) + 1; - size_t net_len = sizeof (struct ip_hdr) + sizeof (struct udp_dns) + data_len; - size_t pkt_len = - sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) + net_len; - - struct ip_udp_dns *pkt = alloca (pkt_len); - - GNUNET_assert (pkt != NULL); - memset (pkt, 0, pkt_len); - - /* set the gnunet-header */ - pkt->shdr.size = htons (pkt_len); - pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); - - /* set the tun-header (no flags and ethertype of IPv4) */ - pkt->tun.flags = 0; - pkt->tun.type = htons (0x0800); - - /* set the ip-header */ - pkt->ip_hdr.version = 4; - pkt->ip_hdr.hdr_lngth = 5; - pkt->ip_hdr.diff_serv = 0; - pkt->ip_hdr.tot_lngth = htons (net_len); - pkt->ip_hdr.ident = 0; - pkt->ip_hdr.flags = 0; - pkt->ip_hdr.frag_off = 0; - pkt->ip_hdr.ttl = 255; - pkt->ip_hdr.proto = IPPROTO_UDP; - pkt->ip_hdr.chks = 0; /* Will be calculated later */ - pkt->ip_hdr.sadr = ans->pkt.from; - pkt->ip_hdr.dadr = ans->pkt.to; - - pkt->ip_hdr.chks = calculate_ip_checksum ((uint16_t *) & pkt->ip_hdr, 5 * 4); - - /* set the udp-header */ - pkt->udp_dns.udp_hdr.spt = htons (53); - pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port; - pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip_hdr)); - pkt->udp_dns.udp_hdr.crc = 0; /* Optional for IPv4 */ - - memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len); + + void* buf; + size_t pkt_len; + + if (ans->pkt.addrlen == 16) + { + size_t net_len = sizeof (struct ip6_hdr) + sizeof (struct udp_dns) + data_len; + pkt_len = + sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) + net_len; + + struct ip6_udp_dns *pkt = alloca (pkt_len); + + GNUNET_assert (pkt != NULL); + memset (pkt, 0, pkt_len); + + /* set the gnunet-header */ + pkt->shdr.size = htons (pkt_len); + pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); + + /* set the tun-header (no flags and ethertype of IPv4) */ + pkt->tun.flags = 0; + pkt->tun.type = htons (0x86dd); + + memcpy(&pkt->ip6_hdr.sadr, ans->pkt.from, 16); + memcpy(&pkt->ip6_hdr.dadr, ans->pkt.to, 16); + + /* set the udp-header */ + pkt->udp_dns.udp_hdr.spt = htons (53); + pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port; + pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip6_hdr)); + pkt->udp_dns.udp_hdr.crc = 0; + uint32_t sum = 0; + + sum = + calculate_checksum_update (sum, (uint16_t *) & pkt->ip6_hdr.sadr, 16); + sum = + calculate_checksum_update (sum, (uint16_t *) & pkt->ip6_hdr.dadr, 16); + uint32_t tmp = (pkt->udp_dns.udp_hdr.len & 0xffff); + + sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4); + tmp = htons (((pkt->ip6_hdr.nxthdr & 0x00ff))); + sum = calculate_checksum_update (sum, (uint16_t *) & tmp, 4); + + sum = + calculate_checksum_update (sum, (uint16_t *) & pkt->udp_dns.udp_hdr, + ntohs (net_len - sizeof(struct ip6_hdr))); + pkt->udp_dns.udp_hdr.crc = calculate_checksum_end (sum); + + pkt->ip6_hdr.version = 6; + pkt->ip6_hdr.paylgth = net_len - sizeof (struct ip6_hdr); + pkt->ip6_hdr.nxthdr = IPPROTO_UDP; + pkt->ip6_hdr.hoplmt = 0xff; + + memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len); + buf = pkt; + } + else if (ans->pkt.addrlen == 4) + { + size_t net_len = sizeof (struct ip_hdr) + sizeof (struct udp_dns) + data_len; + pkt_len = + sizeof (struct GNUNET_MessageHeader) + sizeof (struct pkt_tun) + net_len; + + struct ip_udp_dns *pkt = alloca (pkt_len); + + GNUNET_assert (pkt != NULL); + memset (pkt, 0, pkt_len); + + /* set the gnunet-header */ + pkt->shdr.size = htons (pkt_len); + pkt->shdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_HELPER); + + /* set the tun-header (no flags and ethertype of IPv4) */ + pkt->tun.flags = 0; + pkt->tun.type = htons (0x0800); + + /* set the ip-header */ + pkt->ip_hdr.version = 4; + pkt->ip_hdr.hdr_lngth = 5; + pkt->ip_hdr.diff_serv = 0; + pkt->ip_hdr.tot_lngth = htons (net_len); + pkt->ip_hdr.ident = 0; + pkt->ip_hdr.flags = 0; + pkt->ip_hdr.frag_off = 0; + pkt->ip_hdr.ttl = 255; + pkt->ip_hdr.proto = IPPROTO_UDP; + pkt->ip_hdr.chks = 0; /* Will be calculated later */ + + memcpy(&pkt->ip_hdr.sadr, ans->pkt.from, 4); + memcpy(&pkt->ip_hdr.dadr, ans->pkt.to, 4); + + pkt->ip_hdr.chks = calculate_ip_checksum ((uint16_t *) & pkt->ip_hdr, 5 * 4); + + /* set the udp-header */ + pkt->udp_dns.udp_hdr.spt = htons (53); + pkt->udp_dns.udp_hdr.dpt = ans->pkt.dst_port; + pkt->udp_dns.udp_hdr.len = htons (net_len - sizeof (struct ip_hdr)); + pkt->udp_dns.udp_hdr.crc = 0; /* Optional for IPv4 */ + + memcpy (&pkt->udp_dns.data, ans->pkt.data, data_len); + buf = pkt; + } GNUNET_CONTAINER_DLL_remove (answer_proc_head, answer_proc_tail, ans); GNUNET_free (ans); - if (GNUNET_DISK_file_write (helper_handle->fh_to_helper, pkt, pkt_len) < 0) + if (GNUNET_DISK_file_write (helper_handle->fh_to_helper, buf, pkt_len) < 0) { cleanup_helper (helper_handle); GNUNET_SCHEDULER_add_now (start_helper_and_schedule, NULL); @@ -258,10 +320,36 @@ message_token (void *cls __attribute__ ((unused)), void *client switch (pkt6->ip6_hdr.nxthdr) { - case IPPROTO_TCP: case IPPROTO_UDP: - pkt6_tcp = (struct ip6_tcp *) pkt6; pkt6_udp = (struct ip6_udp *) pkt6; + /* Send dns-packets to the service-dns */ + if (ntohs (pkt6_udp->udp_hdr.dpt) == 53) + { + /* 9 = 8 for the udp-header + 1 for the unsigned char data[1]; */ + size_t len = sizeof (struct query_packet) + ntohs (pkt6_udp->udp_hdr.len) - 9; + + struct query_packet_list *query = + GNUNET_malloc (len + 2 * sizeof (struct query_packet_list *)); + query->pkt.hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_QUERY_DNS); + query->pkt.hdr.size = htons (len); + memcpy(query->pkt.orig_to, &pkt6->ip6_hdr.dadr, 16); + memcpy(query->pkt.orig_from, &pkt6->ip6_hdr.sadr, 16); + query->pkt.addrlen = 16; + query->pkt.src_port = pkt6_udp->udp_hdr.spt; + memcpy (query->pkt.data, pkt6_udp->data, ntohs (pkt6_udp->udp_hdr.len) - 8); + + GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, query); + + GNUNET_assert (head != NULL); + + if (dns_connection != NULL && dns_transmit_handle == NULL) + dns_transmit_handle = GNUNET_CLIENT_notify_transmit_ready (dns_connection, len, + GNUNET_TIME_UNIT_FOREVER_REL, + GNUNET_YES, &send_query, NULL); + break; + } + case IPPROTO_TCP: + pkt6_tcp = (struct ip6_tcp *) pkt6; if ((key = address6_mapping_exists (pkt6->ip6_hdr.dadr)) != NULL) { @@ -438,8 +526,9 @@ message_token (void *cls __attribute__ ((unused)), void *client GNUNET_malloc (len + 2 * sizeof (struct query_packet_list *)); query->pkt.hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_QUERY_DNS); query->pkt.hdr.size = htons (len); - query->pkt.orig_to = pkt->ip_hdr.dadr; - query->pkt.orig_from = pkt->ip_hdr.sadr; + memcpy(query->pkt.orig_to, &pkt->ip_hdr.dadr, 4); + memcpy(query->pkt.orig_from, &pkt->ip_hdr.sadr, 4); + query->pkt.addrlen = 4; query->pkt.src_port = udp->udp_hdr.spt; memcpy (query->pkt.data, udp->data, ntohs (udp->udp_hdr.len) - 8); diff --git a/src/vpn/gnunet-service-dns-p.h b/src/vpn/gnunet-service-dns-p.h index c48786d66..020700385 100644 --- a/src/vpn/gnunet-service-dns-p.h +++ b/src/vpn/gnunet-service-dns-p.h @@ -10,15 +10,16 @@ struct query_packet /** * The IP-Address this query was originally sent to */ - unsigned orig_to:32 GNUNET_PACKED; + char orig_to[16]; /** * The IP-Address this query was originally sent from */ - unsigned orig_from:32 GNUNET_PACKED; + char orig_from[16]; /** * The UDP-Portthis query was originally sent from */ - unsigned src_port:16 GNUNET_PACKED; + char addrlen; + uint16_t src_port GNUNET_PACKED; unsigned char data[1]; /* The DNS-Packet */ }; @@ -76,8 +77,9 @@ struct answer_packet struct GNUNET_MessageHeader hdr; enum GNUNET_DNS_ANSWER_Subtype subtype GNUNET_PACKED; - unsigned from:32 GNUNET_PACKED; - unsigned to:32 GNUNET_PACKED; + char from[16]; + char to[16]; + char addrlen; unsigned dst_port:16 GNUNET_PACKED; /* -- */ diff --git a/src/vpn/gnunet-service-dns.c b/src/vpn/gnunet-service-dns.c index 81f5cad98..38ce3c147 100644 --- a/src/vpn/gnunet-service-dns.c +++ b/src/vpn/gnunet-service-dns.c @@ -50,6 +50,7 @@ struct GNUNET_CONNECTION_TransmitHandle *server_notify; * sent through gnunet. The port of this socket will not be hijacked. */ static struct GNUNET_NETWORK_Handle *dnsout; +static struct GNUNET_NETWORK_Handle *dnsout6; /** * The port bound to the socket dnsout @@ -90,8 +91,9 @@ static struct unsigned valid:1; struct GNUNET_SERVER_Client *client; struct GNUNET_MESH_Tunnel *tunnel; - uint32_t local_ip; - uint32_t remote_ip; + char local_ip[16]; + char remote_ip[16]; + char addrlen; uint16_t local_port; char *name; uint8_t namelen; @@ -485,9 +487,9 @@ receive_mesh_answer (void *cls memcpy (answer->pkt.addr, pdns->answers[0]->data, ntohs (pdns->answers[0]->data_len)); - answer->pkt.from = query_states[dns->s.id].remote_ip; - - answer->pkt.to = query_states[dns->s.id].local_ip; + memcpy(answer->pkt.from, query_states[dns->s.id].remote_ip, query_states[dns->s.id].addrlen); + memcpy(answer->pkt.to, query_states[dns->s.id].local_ip, query_states[dns->s.id].addrlen); + answer->pkt.addrlen = query_states[dns->s.id].addrlen; answer->pkt.dst_port = query_states[dns->s.id].local_port; struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data; @@ -589,9 +591,9 @@ send_rev_query (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) answer->pkt.hdr.size = htons (len); answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_REV; - answer->pkt.from = query_states[id].remote_ip; + memcpy(answer->pkt.from, query_states[id].remote_ip, query_states[id].addrlen); + memcpy(answer->pkt.to, query_states[id].local_ip, query_states[id].addrlen); - answer->pkt.to = query_states[id].local_ip; answer->pkt.dst_port = query_states[id].local_port; struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data; @@ -700,9 +702,9 @@ receive_dht (void *cls, struct GNUNET_TIME_Absolute exp memcpy (&answer->pkt.service_descr.ports, &rec->ports, sizeof (answer->pkt.service_descr.ports)); - answer->pkt.from = query_states[id].remote_ip; + memcpy(answer->pkt.from, query_states[id].remote_ip, query_states[id].addrlen); + memcpy(answer->pkt.to, query_states[id].local_ip, query_states[id].addrlen); - answer->pkt.to = query_states[id].local_ip; answer->pkt.dst_port = query_states[id].local_port; struct dns_pkt *dpkt = (struct dns_pkt *) answer->pkt.data; @@ -784,9 +786,10 @@ receive_query (void *cls query_states[dns->s.id].valid = GNUNET_YES; query_states[dns->s.id].client = client; - query_states[dns->s.id].local_ip = pkt->orig_from; + memcpy(query_states[dns->s.id].local_ip, pkt->orig_from, pkt->addrlen); + query_states[dns->s.id].addrlen = pkt->addrlen; query_states[dns->s.id].local_port = pkt->src_port; - query_states[dns->s.id].remote_ip = pkt->orig_to; + memcpy(query_states[dns->s.id].remote_ip, pkt->orig_to, pkt->addrlen); query_states[dns->s.id].namelen = strlen ((char *) dns->data) + 1; if (query_states[dns->s.id].name != NULL) GNUNET_free (query_states[dns->s.id].name); @@ -883,27 +886,56 @@ receive_query (void *cls } } - char *virt_dns; - unsigned int virt_dns_bytes; + unsigned char virt_dns_bytes[16]; - if (GNUNET_SYSERR == - GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS", &virt_dns)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "No entry 'VIRTDNS' in configuration!\n"); - exit (1); - } + if (pkt->addrlen == 4) + { + char *virt_dns; - if (1 != inet_pton (AF_INET, virt_dns, &virt_dns_bytes)) - { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing 'VIRTDNS': %s; %m!\n", - virt_dns); - exit (1); - } + if (GNUNET_SYSERR == + GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS", &virt_dns)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No entry 'VIRTDNS' in configuration!\n"); + exit (1); + } - GNUNET_free (virt_dns); + if (1 != inet_pton (AF_INET, virt_dns, &virt_dns_bytes)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing 'VIRTDNS': %s; %m!\n", + virt_dns); + exit (1); + } + + GNUNET_free (virt_dns); + } + else if (pkt->addrlen == 16) + { + char *virt_dns; + + if (GNUNET_SYSERR == + GNUNET_CONFIGURATION_get_value_string (cfg, "vpn", "VIRTDNS6", &virt_dns)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No entry 'VIRTDNS6' in configuration!\n"); + exit (1); + } + + if (1 != inet_pton (AF_INET6, virt_dns, &virt_dns_bytes)) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing 'VIRTDNS6': %s; %m!\n", + virt_dns); + exit (1); + } + + GNUNET_free (virt_dns); + } + else + { + GNUNET_assert(0); + } - if (virt_dns_bytes == pkt->orig_to) + if (memcmp(virt_dns_bytes,pkt->orig_to, pkt->addrlen) == 0) { /* This is a packet that was sent directly to the virtual dns-server * @@ -958,17 +990,32 @@ receive_query (void *cls /* The query should be sent to the network */ + if (pkt->addrlen == 4) + { + struct sockaddr_in dest; - struct sockaddr_in dest; + memset (&dest, 0, sizeof dest); + dest.sin_port = htons (53); + memcpy(&dest.sin_addr.s_addr, pkt->orig_to, pkt->addrlen); - memset (&dest, 0, sizeof dest); - dest.sin_port = htons (53); - dest.sin_addr.s_addr = pkt->orig_to; + GNUNET_NETWORK_socket_sendto (dnsout, dns, + ntohs (pkt->hdr.size) - + sizeof (struct query_packet) + 1, + (struct sockaddr *) &dest, sizeof dest); + } + else if (pkt->addrlen == 16) + { + struct sockaddr_in6 dest; - GNUNET_NETWORK_socket_sendto (dnsout, dns, - ntohs (pkt->hdr.size) - - sizeof (struct query_packet) + 1, - (struct sockaddr *) &dest, sizeof dest); + memset (&dest, 0, sizeof dest); + dest.sin6_port = htons (53); + memcpy(&dest.sin6_addr, pkt->orig_to, pkt->addrlen); + + GNUNET_NETWORK_socket_sendto (dnsout6, dns, + ntohs (pkt->hdr.size) - + sizeof (struct query_packet) + 1, + (struct sockaddr *) &dest, sizeof dest); + } outfree: free_parsed_dns_packet (pdns); @@ -980,6 +1027,39 @@ out: static void read_response (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); +static void +read_response6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc); + +static int +open_port6 () +{ + struct sockaddr_in6 addr; + + dnsout6 = GNUNET_NETWORK_socket_create (AF_INET6, SOCK_DGRAM, 0); + if (dnsout6 == NULL) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not create socket: %m\n"); + return GNUNET_SYSERR; + } + memset (&addr, 0, sizeof (struct sockaddr_in6)); + + addr.sin6_family = AF_INET6; + int err = GNUNET_NETWORK_socket_bind (dnsout6, + (struct sockaddr *) &addr, + sizeof (struct sockaddr_in6)); + + if (err != GNUNET_OK) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Could not bind a port: %m\n"); + return GNUNET_SYSERR; + } + + GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout6, + &read_response6, NULL); + + return GNUNET_YES; +} + static int open_port () { @@ -1018,6 +1098,57 @@ open_port () return GNUNET_YES; } +void handle_response(struct dns_pkt* dns, struct sockaddr *addr, socklen_t addrlen, int r); + +/** + * Read a response-packet of the UDP-Socket + */ +static void +read_response6 (void *cls + __attribute__ ((unused)), + const struct GNUNET_SCHEDULER_TaskContext *tc) +{ + struct sockaddr_in6 addr; + socklen_t addrlen = sizeof (addr); + int r; + int len; + + if (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN) + return; + + memset (&addr, 0, sizeof addr); + +#ifndef MINGW + if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout6), FIONREAD, &len)) + { + (void)open_port6 (); + return; + } +#else + /* port the code above? */ + len = 65536; +#endif + + unsigned char buf[len]; + struct dns_pkt *dns = (struct dns_pkt *) buf; + + r = GNUNET_NETWORK_socket_recvfrom (dnsout, buf, sizeof (buf), + (struct sockaddr *) &addr, &addrlen); + + if (r < 0) + { + (void)open_port6 (); + return; + } + + struct sockaddr *addr_ = GNUNET_malloc(sizeof addr); + memcpy (addr_, &addr, sizeof addr); + handle_response(dns, addr_, 4, r); + + GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout6, + &read_response6, NULL); +} + /** * Read a response-packet of the UDP-Socket */ @@ -1050,14 +1181,14 @@ read_response (void *cls /* port the code above? */ len = 65536; #endif - { - unsigned char buf[len]; - struct dns_pkt *dns = (struct dns_pkt *) buf; - r = GNUNET_NETWORK_socket_recvfrom (dnsout, buf, sizeof (buf), - (struct sockaddr *) &addr, &addrlen); + unsigned char buf[len]; + struct dns_pkt *dns = (struct dns_pkt *) buf; - if (r < 0) + r = GNUNET_NETWORK_socket_recvfrom (dnsout, buf, sizeof (buf), + (struct sockaddr *) &addr, &addrlen); + + if (r < 0) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "recvfrom"); @@ -1067,86 +1198,112 @@ read_response (void *cls return; } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Answer to query %d\n", - ntohs (dns->s.id)); + struct sockaddr *addr_ = GNUNET_malloc(sizeof addr); + memcpy (addr_, &addr, sizeof addr); + handle_response(dns, addr_, 4, r); + + GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout, + &read_response, NULL); +} + +void +handle_response(struct dns_pkt* dns, struct sockaddr *addr, socklen_t addrlen, int r) +{ + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Answer to query %d\n", + ntohs (dns->s.id)); + - if (query_states[dns->s.id].valid == GNUNET_YES) + if (query_states[dns->s.id].valid == GNUNET_YES) { if (query_states[dns->s.id].tunnel != NULL) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Answer to query %d for a remote peer!\n", - ntohs (dns->s.id)); - /* This response should go through a tunnel */ - uint32_t *c = - GNUNET_malloc (4 + sizeof (struct GNUNET_MESH_Tunnel *) + r); - *c = r; - struct GNUNET_MESH_Tunnel **t = (struct GNUNET_MESH_Tunnel **) (c + 1); - - *t = query_states[dns->s.id].tunnel; - memcpy (t + 1, dns, r); - if (NULL == - GNUNET_MESH_tunnel_get_data (query_states[dns->s.id].tunnel)) { - struct GNUNET_MESH_TransmitHandle *th = - GNUNET_MESH_notify_transmit_ready (query_states[dns->s.id].tunnel, - GNUNET_YES, - 32, - GNUNET_TIME_UNIT_MINUTES, - NULL, - r + - sizeof (struct - GNUNET_MessageHeader), - mesh_send_response, c); - - GNUNET_MESH_tunnel_set_data (query_states[dns->s.id].tunnel, th); - } - else - { - struct tunnel_notify_queue *head = - GNUNET_MESH_tunnel_get_head (query_states[dns->s.id].tunnel); - struct tunnel_notify_queue *tail = - GNUNET_MESH_tunnel_get_tail (query_states[dns->s.id].tunnel); - - struct tunnel_notify_queue *element = - GNUNET_malloc (sizeof (struct tunnel_notify_queue)); - element->cls = c; - element->len = r + sizeof (struct GNUNET_MessageHeader); - element->cb = mesh_send_response; - - GNUNET_CONTAINER_DLL_insert_tail (head, tail, element); - GNUNET_MESH_tunnel_set_head (query_states[dns->s.id].tunnel, head); - GNUNET_MESH_tunnel_set_tail (query_states[dns->s.id].tunnel, tail); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "Answer to query %d for a remote peer!\n", + ntohs (dns->s.id)); + /* This response should go through a tunnel */ + uint32_t *c = + GNUNET_malloc (4 + sizeof (struct GNUNET_MESH_Tunnel *) + r); + *c = r; + struct GNUNET_MESH_Tunnel **t = (struct GNUNET_MESH_Tunnel **) (c + 1); + + *t = query_states[dns->s.id].tunnel; + memcpy (t + 1, dns, r); + if (NULL == + GNUNET_MESH_tunnel_get_data (query_states[dns->s.id].tunnel)) + { + struct GNUNET_MESH_TransmitHandle *th = + GNUNET_MESH_notify_transmit_ready (query_states[dns->s.id].tunnel, + GNUNET_YES, + 32, + GNUNET_TIME_UNIT_MINUTES, + NULL, + r + + sizeof (struct + GNUNET_MessageHeader), + mesh_send_response, c); + + GNUNET_MESH_tunnel_set_data (query_states[dns->s.id].tunnel, th); + } + else + { + struct tunnel_notify_queue *head = + GNUNET_MESH_tunnel_get_head (query_states[dns->s.id].tunnel); + struct tunnel_notify_queue *tail = + GNUNET_MESH_tunnel_get_tail (query_states[dns->s.id].tunnel); + + struct tunnel_notify_queue *element = + GNUNET_malloc (sizeof (struct tunnel_notify_queue)); + element->cls = c; + element->len = r + sizeof (struct GNUNET_MessageHeader); + element->cb = mesh_send_response; + + GNUNET_CONTAINER_DLL_insert_tail (head, tail, element); + GNUNET_MESH_tunnel_set_head (query_states[dns->s.id].tunnel, head); + GNUNET_MESH_tunnel_set_tail (query_states[dns->s.id].tunnel, tail); + } } - } else - { - query_states[dns->s.id].valid = GNUNET_NO; + { + query_states[dns->s.id].valid = GNUNET_NO; - size_t len = sizeof (struct answer_packet) + r - 1; /* 1 for the unsigned char data[1]; */ - struct answer_packet_list *answer = + size_t len = sizeof (struct answer_packet) + r - 1; /* 1 for the unsigned char data[1]; */ + struct answer_packet_list *answer = GNUNET_malloc (len + 2 * sizeof (struct answer_packet_list *)); - answer->pkt.hdr.type = + answer->pkt.hdr.type = htons (GNUNET_MESSAGE_TYPE_VPN_DNS_LOCAL_RESPONSE_DNS); - answer->pkt.hdr.size = htons (len); - answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_IP; - answer->pkt.from = addr.sin_addr.s_addr; - answer->pkt.to = query_states[dns->s.id].local_ip; - answer->pkt.dst_port = query_states[dns->s.id].local_port; - memcpy (answer->pkt.data, buf, r); - - GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer); - - if (server_notify == NULL) - server_notify = GNUNET_SERVER_notify_transmit_ready (query_states[dns->s.id].client, - len, GNUNET_TIME_UNIT_FOREVER_REL, - &send_answer, - query_states[dns->s.id].client); - } + answer->pkt.hdr.size = htons (len); + answer->pkt.subtype = GNUNET_DNS_ANSWER_TYPE_IP; + answer->pkt.addrlen = addrlen; + if (addrlen == 16) + { + struct sockaddr_in6 *addr_ = (struct sockaddr_in6*)addr; + memcpy(answer->pkt.from, &addr_->sin6_addr, addrlen); + memcpy(answer->pkt.to, query_states[dns->s.id].local_ip, addrlen); + } + else if (addrlen == 4) + { + struct sockaddr_in *addr_ = (struct sockaddr_in*)addr; + memcpy(answer->pkt.from, &addr_->sin_addr.s_addr, addrlen); + memcpy(answer->pkt.to, query_states[dns->s.id].local_ip, addrlen); + } + else + { + GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "addrlen = %d\n", addrlen); + GNUNET_assert(0); + } + answer->pkt.dst_port = query_states[dns->s.id].local_port; + memcpy (answer->pkt.data, dns, r); + + GNUNET_CONTAINER_DLL_insert_after (head, tail, tail, answer); + + if (server_notify == NULL) + server_notify = GNUNET_SERVER_notify_transmit_ready (query_states[dns->s.id].client, + len, GNUNET_TIME_UNIT_FOREVER_REL, + &send_answer, + query_states[dns->s.id].client); + } } - } - GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL, dnsout, - &read_response, NULL); + GNUNET_free(addr); } @@ -1422,6 +1579,11 @@ run (void *cls, struct GNUNET_SERVER_Handle *server, GNUNET_APPLICATION_TYPE_END }; + if (GNUNET_YES != open_port6 ()) + { + GNUNET_SCHEDULER_shutdown (); + return; + } if (GNUNET_YES != open_port ()) { diff --git a/src/vpn/gnunet-vpn-packet.h b/src/vpn/gnunet-vpn-packet.h index 47fa69847..e2082f9a1 100644 --- a/src/vpn/gnunet-vpn-packet.h +++ b/src/vpn/gnunet-vpn-packet.h @@ -40,8 +40,8 @@ struct ip_hdr unsigned proto:8 GNUNET_PACKED; unsigned chks:16 GNUNET_PACKED; - unsigned sadr:32 GNUNET_PACKED; - unsigned dadr:32 GNUNET_PACKED; + uint32_t sadr GNUNET_PACKED; + uint32_t dadr GNUNET_PACKED; }; #define TCP_FLAG_SYN 2