move dns ops again, 2nd try
authorChristian Grothoff <christian@grothoff.org>
Mon, 25 Jun 2018 17:52:15 +0000 (19:52 +0200)
committerChristian Grothoff <christian@grothoff.org>
Mon, 25 Jun 2018 17:52:15 +0000 (19:52 +0200)
17 files changed:
configure.ac
po/POTFILES.in
src/Makefile.am
src/dns/Makefile.am
src/dns/dnsparser.c [deleted file]
src/dns/dnsstub.c [deleted file]
src/tun/regex.c [deleted file]
src/tun/test_regex.c [deleted file]
src/tun/test_tun.c [deleted file]
src/tun/tun.c [deleted file]
src/util/Makefile.am
src/util/dnsparser.c [new file with mode: 0644]
src/util/dnsstub.c [new file with mode: 0644]
src/util/regex.c [new file with mode: 0644]
src/util/test_regex.c [new file with mode: 0644]
src/util/test_tun.c [new file with mode: 0644]
src/util/tun.c [new file with mode: 0644]

index c8e3164169afd6b4be25adf4f88ec9334f2874ca..3d68ee9b0c11dbd5f10c38acf05e2dab812e109c 100644 (file)
@@ -1722,7 +1722,6 @@ src/testing/Makefile
 src/topology/Makefile
 src/transport/Makefile
 src/transport/transport.conf
-src/tun/Makefile
 src/util/Makefile
 src/util/resolver.conf
 src/vpn/Makefile
index de6bd90e456c34aa191b706ef441d56bc596df9b..38fa52508c29c48660f188a2e59b256485dd3d3e 100644 (file)
@@ -4,21 +4,13 @@ src/arm/arm_monitor_api.c
 src/arm/gnunet-arm.c
 src/arm/gnunet-service-arm.c
 src/arm/mockup-service.c
-src/ats-tests/ats-testing-experiment.c
-src/ats-tests/ats-testing-log.c
-src/ats-tests/ats-testing-preferences.c
-src/ats-tests/ats-testing-traffic.c
-src/ats-tests/ats-testing.c
-src/ats-tests/gnunet-ats-sim.c
-src/ats-tests/gnunet-solver-eval.c
-src/ats-tool/gnunet-ats.c
 src/ats/ats_api_connectivity.c
 src/ats/ats_api_performance.c
 src/ats/ats_api_scanner.c
 src/ats/ats_api_scheduling.c
 src/ats/gnunet-ats-solver-eval.c
-src/ats/gnunet-service-ats.c
 src/ats/gnunet-service-ats_addresses.c
+src/ats/gnunet-service-ats.c
 src/ats/gnunet-service-ats_connectivity.c
 src/ats/gnunet-service-ats_normalization.c
 src/ats/gnunet-service-ats_performance.c
@@ -29,6 +21,14 @@ src/ats/gnunet-service-ats_scheduling.c
 src/ats/plugin_ats_mlp.c
 src/ats/plugin_ats_proportional.c
 src/ats/plugin_ats_ril.c
+src/ats-tests/ats-testing.c
+src/ats-tests/ats-testing-experiment.c
+src/ats-tests/ats-testing-log.c
+src/ats-tests/ats-testing-preferences.c
+src/ats-tests/ats-testing-traffic.c
+src/ats-tests/gnunet-ats-sim.c
+src/ats-tests/gnunet-solver-eval.c
+src/ats-tool/gnunet-ats.c
 src/auction/gnunet-auction-create.c
 src/auction/gnunet-auction-info.c
 src/auction/gnunet-auction-join.c
@@ -40,8 +40,8 @@ src/block/plugin_block_test.c
 src/cadet/cadet_api.c
 src/cadet/cadet_test_lib.c
 src/cadet/desirability_table.c
-src/cadet/gnunet-cadet-profiler.c
 src/cadet/gnunet-cadet.c
+src/cadet/gnunet-cadet-profiler.c
 src/cadet/gnunet-service-cadet.c
 src/cadet/gnunet-service-cadet_channel.c
 src/cadet/gnunet-service-cadet_connection.c
@@ -57,15 +57,15 @@ src/consensus/gnunet-service-consensus.c
 src/consensus/plugin_block_consensus.c
 src/conversation/conversation_api.c
 src/conversation/conversation_api_call.c
-src/conversation/gnunet-conversation-test.c
 src/conversation/gnunet-conversation.c
-src/conversation/gnunet-helper-audio-playback-gst.c
+src/conversation/gnunet-conversation-test.c
+src/conversation/gnunet_gst.c
+src/conversation/gnunet_gst_test.c
 src/conversation/gnunet-helper-audio-playback.c
-src/conversation/gnunet-helper-audio-record-gst.c
+src/conversation/gnunet-helper-audio-playback-gst.c
 src/conversation/gnunet-helper-audio-record.c
+src/conversation/gnunet-helper-audio-record-gst.c
 src/conversation/gnunet-service-conversation.c
-src/conversation/gnunet_gst.c
-src/conversation/gnunet_gst_test.c
 src/conversation/microphone.c
 src/conversation/plugin_gnsrecord_conversation.c
 src/conversation/speaker.c
@@ -102,6 +102,7 @@ src/dht/dht_api.c
 src/dht/dht_test_lib.c
 src/dht/gnunet-dht-get.c
 src/dht/gnunet-dht-monitor.c
+src/dht/gnunet_dht_profiler.c
 src/dht/gnunet-dht-put.c
 src/dht/gnunet-service-dht.c
 src/dht/gnunet-service-dht_clients.c
@@ -110,11 +111,8 @@ src/dht/gnunet-service-dht_hello.c
 src/dht/gnunet-service-dht_neighbours.c
 src/dht/gnunet-service-dht_nse.c
 src/dht/gnunet-service-dht_routing.c
-src/dht/gnunet_dht_profiler.c
 src/dht/plugin_block_dht.c
 src/dns/dns_api.c
-src/dns/dnsparser.c
-src/dns/dnsstub.c
 src/dns/gnunet-dns-monitor.c
 src/dns/gnunet-dns-redirector.c
 src/dns/gnunet-helper-dns.c
@@ -126,8 +124,8 @@ src/dv/gnunet-dv.c
 src/dv/gnunet-service-dv.c
 src/dv/plugin_transport_dv.c
 src/exit/gnunet-daemon-exit.c
-src/exit/gnunet-helper-exit-windows.c
 src/exit/gnunet-helper-exit.c
+src/exit/gnunet-helper-exit-windows.c
 src/fragmentation/defragmentation.c
 src/fragmentation/fragmentation.c
 src/fs/fs_api.c
@@ -152,8 +150,8 @@ src/fs/gnunet-auto-share.c
 src/fs/gnunet-daemon-fsprofiler.c
 src/fs/gnunet-directory.c
 src/fs/gnunet-download.c
-src/fs/gnunet-fs-profiler.c
 src/fs/gnunet-fs.c
+src/fs/gnunet-fs-profiler.c
 src/fs/gnunet-helper-fs-publish.c
 src/fs/gnunet-publish.c
 src/fs/gnunet-search.c
@@ -173,10 +171,10 @@ src/gns/gns_tld_api.c
 src/gns/gnunet-bcd.c
 src/gns/gnunet-dns2gns.c
 src/gns/gnunet-gns-benchmark.c
+src/gns/gnunet-gns.c
 src/gns/gnunet-gns-helper-service-w32.c
 src/gns/gnunet-gns-import.c
 src/gns/gnunet-gns-proxy.c
-src/gns/gnunet-gns.c
 src/gns/gnunet-service-gns.c
 src/gns/gnunet-service-gns_interceptor.c
 src/gns/gnunet-service-gns_resolver.c
@@ -185,15 +183,15 @@ src/gns/nss/nss_gns_query.c
 src/gns/plugin_block_gns.c
 src/gns/plugin_gnsrecord_gns.c
 src/gns/plugin_rest_gns.c
-src/gns/w32nsp-install.c
-src/gns/w32nsp-resolve.c
-src/gns/w32nsp-uninstall.c
-src/gns/w32nsp.c
 src/gnsrecord/gnsrecord.c
 src/gnsrecord/gnsrecord_crypto.c
 src/gnsrecord/gnsrecord_misc.c
 src/gnsrecord/gnsrecord_serialization.c
 src/gnsrecord/plugin_gnsrecord_dns.c
+src/gns/w32nsp.c
+src/gns/w32nsp-install.c
+src/gns/w32nsp-resolve.c
+src/gns/w32nsp-uninstall.c
 src/hello/address.c
 src/hello/gnunet-hello.c
 src/hello/hello.c
@@ -202,6 +200,11 @@ src/hostlist/gnunet-daemon-hostlist_client.c
 src/hostlist/gnunet-daemon-hostlist_server.c
 src/identity-attribute/identity_attribute.c
 src/identity-attribute/plugin_identity_attribute_gnuid.c
+src/identity/gnunet-identity.c
+src/identity/gnunet-service-identity.c
+src/identity/identity_api.c
+src/identity/identity_api_lookup.c
+src/identity/plugin_rest_identity.c
 src/identity-provider/gnunet-idp.c
 src/identity-provider/gnunet-service-identity-provider.c
 src/identity-provider/identity_provider_api.c
@@ -210,20 +213,15 @@ src/identity-provider/plugin_gnsrecord_identity_provider.c
 src/identity-provider/plugin_identity_provider_sqlite.c
 src/identity-provider/plugin_rest_identity_provider.c
 src/identity-provider/plugin_rest_openid_connect.c
-src/identity/gnunet-identity.c
-src/identity/gnunet-service-identity.c
-src/identity/identity_api.c
-src/identity/identity_api_lookup.c
-src/identity/plugin_rest_identity.c
-src/json/json.c
-src/json/json_generator.c
-src/json/json_helper.c
-src/json/json_mhd.c
 src/jsonapi/jsonapi.c
 src/jsonapi/jsonapi_document.c
 src/jsonapi/jsonapi_error.c
 src/jsonapi/jsonapi_relationship.c
 src/jsonapi/jsonapi_resource.c
+src/json/json.c
+src/json/json_generator.c
+src/json/json_helper.c
+src/json/json_mhd.c
 src/multicast/gnunet-multicast.c
 src/multicast/gnunet-service-multicast.c
 src/multicast/multicast_api.c
@@ -237,8 +235,8 @@ src/namecache/namecache_api.c
 src/namecache/plugin_namecache_flat.c
 src/namecache/plugin_namecache_postgres.c
 src/namecache/plugin_namecache_sqlite.c
-src/namestore/gnunet-namestore-fcfsd.c
 src/namestore/gnunet-namestore.c
+src/namestore/gnunet-namestore-fcfsd.c
 src/namestore/gnunet-service-namestore.c
 src/namestore/gnunet-zoneimport.c
 src/namestore/namestore_api.c
@@ -254,10 +252,10 @@ src/nat-auto/gnunet-service-nat-auto.c
 src/nat-auto/gnunet-service-nat-auto_legacy.c
 src/nat-auto/nat_auto_api.c
 src/nat-auto/nat_auto_api_test.c
-src/nat/gnunet-helper-nat-client-windows.c
 src/nat/gnunet-helper-nat-client.c
-src/nat/gnunet-helper-nat-server-windows.c
+src/nat/gnunet-helper-nat-client-windows.c
 src/nat/gnunet-helper-nat-server.c
+src/nat/gnunet-helper-nat-server-windows.c
 src/nat/gnunet-nat.c
 src/nat/gnunet-service-nat.c
 src/nat/gnunet-service-nat_externalip.c
@@ -266,15 +264,15 @@ src/nat/gnunet-service-nat_mini.c
 src/nat/gnunet-service-nat_stun.c
 src/nat/nat_api.c
 src/nat/nat_api_stun.c
-src/nse/gnunet-nse-profiler.c
 src/nse/gnunet-nse.c
+src/nse/gnunet-nse-profiler.c
 src/nse/gnunet-service-nse.c
 src/nse/nse_api.c
-src/peerinfo-tool/gnunet-peerinfo.c
-src/peerinfo-tool/gnunet-peerinfo_plugins.c
 src/peerinfo/gnunet-service-peerinfo.c
 src/peerinfo/peerinfo_api.c
 src/peerinfo/peerinfo_api_notify.c
+src/peerinfo-tool/gnunet-peerinfo.c
+src/peerinfo-tool/gnunet-peerinfo_plugins.c
 src/peerstore/gnunet-peerstore.c
 src/peerstore/gnunet-service-peerstore.c
 src/peerstore/peerstore_api.c
@@ -319,20 +317,20 @@ src/revocation/gnunet-revocation.c
 src/revocation/gnunet-service-revocation.c
 src/revocation/plugin_block_revocation.c
 src/revocation/revocation_api.c
-src/rps/gnunet-rps-profiler.c
 src/rps/gnunet-rps.c
+src/rps/gnunet-rps-profiler.c
 src/rps/gnunet-service-rps.c
 src/rps/gnunet-service-rps_custommap.c
 src/rps/gnunet-service-rps_sampler.c
 src/rps/gnunet-service-rps_sampler_elem.c
 src/rps/gnunet-service-rps_view.c
-src/rps/rps-test_util.c
 src/rps/rps_api.c
+src/rps/rps-test_util.c
 src/scalarproduct/gnunet-scalarproduct.c
-src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c
-src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c
 src/scalarproduct/gnunet-service-scalarproduct_alice.c
 src/scalarproduct/gnunet-service-scalarproduct_bob.c
+src/scalarproduct/gnunet-service-scalarproduct-ecc_alice.c
+src/scalarproduct/gnunet-service-scalarproduct-ecc_bob.c
 src/scalarproduct/scalarproduct_api.c
 src/secretsharing/gnunet-secretsharing-profiler.c
 src/secretsharing/gnunet-service-secretsharing.c
@@ -361,16 +359,15 @@ src/statistics/gnunet-statistics.c
 src/statistics/statistics_api.c
 src/template/gnunet-service-template.c
 src/template/gnunet-template.c
-src/testbed-logger/gnunet-service-testbed-logger.c
-src/testbed-logger/testbed_logger_api.c
 src/testbed/generate-underlay-topology.c
 src/testbed/gnunet-daemon-latency-logger.c
 src/testbed/gnunet-daemon-testbed-blacklist.c
 src/testbed/gnunet-daemon-testbed-underlay.c
 src/testbed/gnunet-helper-testbed.c
+src/testbed/gnunet_mpi_test.c
 src/testbed/gnunet-service-test-barriers.c
-src/testbed/gnunet-service-testbed.c
 src/testbed/gnunet-service-testbed_barriers.c
+src/testbed/gnunet-service-testbed.c
 src/testbed/gnunet-service-testbed_cache.c
 src/testbed/gnunet-service-testbed_connectionpool.c
 src/testbed/gnunet-service-testbed_cpustatus.c
@@ -378,19 +375,20 @@ src/testbed/gnunet-service-testbed_links.c
 src/testbed/gnunet-service-testbed_meminfo.c
 src/testbed/gnunet-service-testbed_oc.c
 src/testbed/gnunet-service-testbed_peers.c
-src/testbed/gnunet-testbed-profiler.c
-src/testbed/gnunet_mpi_test.c
 src/testbed/gnunet_testbed_mpi_spawn.c
-src/testbed/testbed_api.c
+src/testbed/gnunet-testbed-profiler.c
+src/testbed-logger/gnunet-service-testbed-logger.c
+src/testbed-logger/testbed_logger_api.c
 src/testbed/testbed_api_barriers.c
+src/testbed/testbed_api.c
 src/testbed/testbed_api_hosts.c
 src/testbed/testbed_api_operations.c
 src/testbed/testbed_api_peers.c
 src/testbed/testbed_api_sd.c
 src/testbed/testbed_api_services.c
 src/testbed/testbed_api_statistics.c
-src/testbed/testbed_api_test.c
 src/testbed/testbed_api_testbed.c
+src/testbed/testbed_api_test.c
 src/testbed/testbed_api_topology.c
 src/testbed/testbed_api_underlay.c
 src/testing/gnunet-testing.c
@@ -399,28 +397,28 @@ src/testing/testing.c
 src/topology/friends.c
 src/topology/gnunet-daemon-topology.c
 src/transport/gnunet-helper-transport-bluetooth.c
-src/transport/gnunet-helper-transport-wlan-dummy.c
 src/transport/gnunet-helper-transport-wlan.c
-src/transport/gnunet-service-transport.c
+src/transport/gnunet-helper-transport-wlan-dummy.c
 src/transport/gnunet-service-transport_ats.c
+src/transport/gnunet-service-transport.c
 src/transport/gnunet-service-transport_hello.c
 src/transport/gnunet-service-transport_manipulation.c
 src/transport/gnunet-service-transport_neighbours.c
 src/transport/gnunet-service-transport_plugins.c
 src/transport/gnunet-service-transport_validation.c
+src/transport/gnunet-transport.c
 src/transport/gnunet-transport-certificate-creation.c
 src/transport/gnunet-transport-profiler.c
 src/transport/gnunet-transport-wlan-receiver.c
 src/transport/gnunet-transport-wlan-sender.c
-src/transport/gnunet-transport.c
 src/transport/plugin_transport_http_client.c
 src/transport/plugin_transport_http_common.c
 src/transport/plugin_transport_http_server.c
 src/transport/plugin_transport_smtp.c
 src/transport/plugin_transport_tcp.c
 src/transport/plugin_transport_template.c
-src/transport/plugin_transport_udp.c
 src/transport/plugin_transport_udp_broadcasting.c
+src/transport/plugin_transport_udp.c
 src/transport/plugin_transport_unix.c
 src/transport/plugin_transport_wlan.c
 src/transport/plugin_transport_xt.c
@@ -429,11 +427,6 @@ src/transport/tcp_connection_legacy.c
 src/transport/tcp_server_legacy.c
 src/transport/tcp_server_mst_legacy.c
 src/transport/tcp_service_legacy.c
-src/transport/transport-testing-filenames.c
-src/transport/transport-testing-loggers.c
-src/transport/transport-testing-main.c
-src/transport/transport-testing-send.c
-src/transport/transport-testing.c
 src/transport/transport_api_address_to_string.c
 src/transport/transport_api_blacklist.c
 src/transport/transport_api_core.c
@@ -442,8 +435,11 @@ src/transport/transport_api_manipulation.c
 src/transport/transport_api_monitor_peers.c
 src/transport/transport_api_monitor_plugins.c
 src/transport/transport_api_offer_hello.c
-src/tun/regex.c
-src/tun/tun.c
+src/transport/transport-testing.c
+src/transport/transport-testing-filenames.c
+src/transport/transport-testing-loggers.c
+src/transport/transport-testing-main.c
+src/transport/transport-testing-send.c
 src/util/bandwidth.c
 src/util/bio.c
 src/util/client.c
@@ -455,8 +451,8 @@ src/util/configuration_loader.c
 src/util/container_bloomfilter.c
 src/util/container_heap.c
 src/util/container_meta_data.c
-src/util/container_multihashmap.c
 src/util/container_multihashmap32.c
+src/util/container_multihashmap.c
 src/util/container_multipeermap.c
 src/util/container_multishortmap.c
 src/util/crypto_abe.c
@@ -474,10 +470,12 @@ src/util/crypto_random.c
 src/util/crypto_rsa.c
 src/util/crypto_symmetric.c
 src/util/disk.c
+src/util/dnsparser.c
+src/util/dnsstub.c
 src/util/getopt.c
 src/util/getopt_helpers.c
-src/util/gnunet-config-diff.c
 src/util/gnunet-config.c
+src/util/gnunet-config-diff.c
 src/util/gnunet-ecc.c
 src/util/gnunet-helper-w32-console.c
 src/util/gnunet-resolver.c
@@ -497,6 +495,7 @@ src/util/os_priority.c
 src/util/peer.c
 src/util/plugin.c
 src/util/program.c
+src/util/regex.c
 src/util/resolver_api.c
 src/util/scheduler.c
 src/util/service.c
@@ -505,16 +504,17 @@ src/util/socks.c
 src/util/speedup.c
 src/util/strings.c
 src/util/time.c
+src/util/tun.c
 src/util/w32cat.c
 src/util/win.c
 src/util/winproc.c
-src/vpn/gnunet-helper-vpn-windows.c
 src/vpn/gnunet-helper-vpn.c
+src/vpn/gnunet-helper-vpn-windows.c
 src/vpn/gnunet-service-vpn.c
 src/vpn/gnunet-vpn.c
 src/vpn/vpn_api.c
-src/zonemaster/gnunet-service-zonemaster-monitor.c
 src/zonemaster/gnunet-service-zonemaster.c
+src/zonemaster/gnunet-service-zonemaster-monitor.c
 src/fs/fs_api.h
 src/include/gnunet_common.h
 src/include/gnunet_mq_lib.h
index d8d5487066c4ab969753104ea86e183e2e1a35dc..00f30adc3b838bbc5090f4949f725adc60720a95 100644 (file)
@@ -83,7 +83,6 @@ SUBDIRS = \
   $(REST_DIR) \
   $(JSONAPI_DIR) \
   hello \
-  tun \
   block \
   statistics \
   arm \
index 9a4ecdcfd9eeb3c0fb33d5ddafbcfc2f8b6267a5..ca2685765e57467039304abf9beb5bff17862f12 100644 (file)
@@ -27,8 +27,6 @@ install-exec-hook:
 endif
 
 lib_LTLIBRARIES = \
-  libgnunetdnsparser.la \
-  libgnunetdnsstub.la \
   libgnunetdns.la
 
 libexec_PROGRAMS = \
@@ -47,9 +45,6 @@ check_SCRIPTS = \
  test_gnunet_dns.sh
 endif
 
-check_PROGRAMS = \
- test_hexcoder
-
 gnunet_helper_dns_SOURCES = \
  gnunet-helper-dns.c
 
@@ -57,7 +52,6 @@ gnunet_helper_dns_SOURCES = \
 gnunet_dns_monitor_SOURCES = \
  gnunet-dns-monitor.c
 gnunet_dns_monitor_LDADD = \
-  libgnunetdnsparser.la \
   libgnunetdns.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(GN_LIBINTL)
@@ -65,15 +59,12 @@ gnunet_dns_monitor_LDADD = \
 gnunet_zonewalk_SOURCES = \
  gnunet-zonewalk.c
 gnunet_zonewalk_LDADD = \
-  libgnunetdnsparser.la \
-  libgnunetdnsstub.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(GN_LIBINTL)
 
 gnunet_dns_redirector_SOURCES = \
  gnunet-dns-redirector.c
 gnunet_dns_redirector_LDADD = \
-  libgnunetdnsparser.la \
   libgnunetdns.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(GN_LIBINTL)
@@ -81,30 +72,10 @@ gnunet_dns_redirector_LDADD = \
 gnunet_service_dns_SOURCES = \
  gnunet-service-dns.c
 gnunet_service_dns_LDADD = \
-  libgnunetdnsstub.la \
-  $(top_builddir)/src/tun/libgnunettun.la \
   $(top_builddir)/src/statistics/libgnunetstatistics.la \
   $(top_builddir)/src/util/libgnunetutil.la \
   $(GN_LIBINTL)
 
-libgnunetdnsparser_la_SOURCES = \
- dnsparser.c
-libgnunetdnsparser_la_LIBADD = \
- $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \
-  -lidn
-libgnunetdnsparser_la_LDFLAGS = \
-  $(GN_LIB_LDFLAGS) \
-  -version-info 1:0:1
-
-libgnunetdnsstub_la_SOURCES = \
- dnsstub.c
-libgnunetdnsstub_la_LIBADD = \
-  $(top_builddir)/src/tun/libgnunettun.la \
- $(top_builddir)/src/util/libgnunetutil.la $(XLIB)
-libgnunetdnsstub_la_LDFLAGS = \
-  $(GN_LIB_LDFLAGS) \
-  -version-info 0:0:0
-
 libgnunetdns_la_SOURCES = \
  dns_api.c dns.h
 libgnunetdns_la_LIBADD = \
@@ -131,8 +102,3 @@ EXTRA_DIST = \
   $(check_SCRIPTS)
 
 
-test_hexcoder_SOURCES = \
- test_hexcoder.c
-test_hexcoder_LDADD = \
- libgnunetdnsparser.la \
- $(top_builddir)/src/util/libgnunetutil.la
diff --git a/src/dns/dnsparser.c b/src/dns/dnsparser.c
deleted file mode 100644 (file)
index 32ad7c0..0000000
+++ /dev/null
@@ -1,1334 +0,0 @@
-/*
-      This file is part of GNUnet
-      Copyright (C) 2010-2014 GNUnet e.V.
-
-      GNUnet is free software: you can redistribute it and/or modify it
-      under the terms of the GNU Affero General Public License as published
-      by the Free Software Foundation, either version 3 of the License,
-      or (at your option) any later version.
-
-      GNUnet is distributed in the hope that it will be useful, but
-      WITHOUT ANY WARRANTY; without even the implied warranty of
-      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-      Affero General Public License for more details.
-     
-      You should have received a copy of the GNU Affero General Public License
-      along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/**
- * @file dns/dnsparser.c
- * @brief helper library to parse DNS packets.
- * @author Philipp Toelke
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include <idna.h>
-#if WINDOWS
-#include <idn-free.h>
-#endif
-#include "gnunet_util_lib.h"
-#include "gnunet_dnsparser_lib.h"
-#include "gnunet_tun_lib.h"
-
-
-/**
- * Check if a label in UTF-8 format can be coded into valid IDNA.
- * This can fail if the ASCII-conversion becomes longer than 63 characters.
- *
- * @param label label to check (UTF-8 string)
- * @return #GNUNET_OK if the label can be converted to IDNA,
- *         #GNUNET_SYSERR if the label is not valid for DNS names
- */
-int
-GNUNET_DNSPARSER_check_label (const char *label)
-{
-  char *output;
-  size_t slen;
-
-  if (NULL != strchr (label, '.'))
-    return GNUNET_SYSERR; /* not a label! Did you mean GNUNET_DNSPARSER_check_name? */
-  if (IDNA_SUCCESS !=
-      idna_to_ascii_8z (label, &output, IDNA_ALLOW_UNASSIGNED))
-    return GNUNET_SYSERR;
-  slen = strlen (output);
-#if WINDOWS
-  idn_free (output);
-#else
-  free (output);
-#endif
-  return (slen > 63) ? GNUNET_SYSERR : GNUNET_OK;
-}
-
-
-/**
- * Check if a label in UTF-8 format can be coded into valid IDNA.
- * This can fail if the ASCII-conversion becomes longer than 253 characters.
- *
- * @param name name to check (UTF-8 string)
- * @return #GNUNET_OK if the label can be converted to IDNA,
- *         #GNUNET_SYSERR if the label is not valid for DNS names
- */
-int
-GNUNET_DNSPARSER_check_name (const char *name)
-{
-  char *ldup;
-  char *output;
-  size_t slen;
-  char *tok;
-
-  ldup = GNUNET_strdup (name);
-  for (tok = strtok (ldup, "."); NULL != tok; tok = strtok (NULL, "."))
-    if (GNUNET_OK !=
-       GNUNET_DNSPARSER_check_label (tok))
-    {
-      GNUNET_free (ldup);
-      return GNUNET_SYSERR;
-    }
-  GNUNET_free (ldup);
-  if (IDNA_SUCCESS !=
-      idna_to_ascii_8z (name, &output, IDNA_ALLOW_UNASSIGNED))
-    return GNUNET_SYSERR;
-  slen = strlen (output);
-#if WINDOWS
-  idn_free (output);
-#else
-  free (output);
-#endif
-  return (slen > 253) ? GNUNET_SYSERR : GNUNET_OK;
-}
-
-
-/**
- * Free SOA information record.
- *
- * @param soa record to free
- */
-void
-GNUNET_DNSPARSER_free_soa (struct GNUNET_DNSPARSER_SoaRecord *soa)
-{
-  if (NULL == soa)
-    return;
-  GNUNET_free_non_null (soa->mname);
-  GNUNET_free_non_null (soa->rname);
-  GNUNET_free (soa);
-}
-
-
-/**
- * Free CERT information record.
- *
- * @param cert record to free
- */
-void
-GNUNET_DNSPARSER_free_cert (struct GNUNET_DNSPARSER_CertRecord *cert)
-{
-  if (NULL == cert)
-    return;
-  GNUNET_free_non_null (cert->certificate_data);
-  GNUNET_free (cert);
-}
-
-
-/**
- * Free SRV information record.
- *
- * @param srv record to free
- */
-void
-GNUNET_DNSPARSER_free_srv (struct GNUNET_DNSPARSER_SrvRecord *srv)
-{
-  if (NULL == srv)
-    return;
-  GNUNET_free_non_null (srv->target);
-  GNUNET_free (srv);
-}
-
-
-/**
- * Free MX information record.
- *
- * @param mx record to free
- */
-void
-GNUNET_DNSPARSER_free_mx (struct GNUNET_DNSPARSER_MxRecord *mx)
-{
-  if (NULL == mx)
-    return;
-  GNUNET_free_non_null (mx->mxhost);
-  GNUNET_free (mx);
-}
-
-
-/**
- * Free the given DNS record.
- *
- * @param r record to free
- */
-void
-GNUNET_DNSPARSER_free_record (struct GNUNET_DNSPARSER_Record *r)
-{
-  GNUNET_free_non_null (r->name);
-  switch (r->type)
-  {
-  case GNUNET_DNSPARSER_TYPE_MX:
-    GNUNET_DNSPARSER_free_mx (r->data.mx);
-    break;
-  case GNUNET_DNSPARSER_TYPE_SOA:
-    GNUNET_DNSPARSER_free_soa (r->data.soa);
-    break;
-  case GNUNET_DNSPARSER_TYPE_SRV:
-    GNUNET_DNSPARSER_free_srv (r->data.srv);
-    break;
-  case GNUNET_DNSPARSER_TYPE_CERT:
-    GNUNET_DNSPARSER_free_cert (r->data.cert);
-    break;
-  case GNUNET_DNSPARSER_TYPE_NS:
-  case GNUNET_DNSPARSER_TYPE_CNAME:
-  case GNUNET_DNSPARSER_TYPE_PTR:
-    GNUNET_free_non_null (r->data.hostname);
-    break;
-  default:
-    GNUNET_free_non_null (r->data.raw.data);
-    break;
-  }
-}
-
-
-/**
- * Parse name inside of a DNS query or record.
- *
- * @param udp_payload entire UDP payload
- * @param udp_payload_length length of @a udp_payload
- * @param off pointer to the offset of the name to parse in the udp_payload (to be
- *                    incremented by the size of the name)
- * @param depth current depth of our recursion (to prevent stack overflow)
- * @return name as 0-terminated C string on success, NULL if the payload is malformed
- */
-static char *
-parse_name (const char *udp_payload,
-           size_t udp_payload_length,
-           size_t *off,
-           unsigned int depth)
-{
-  const uint8_t *input = (const uint8_t *) udp_payload;
-  char *ret;
-  char *tmp;
-  char *xstr;
-  uint8_t len;
-  size_t xoff;
-  char *utf8;
-  Idna_rc rc;
-
-  ret = GNUNET_strdup ("");
-  while (1)
-  {
-    if (*off >= udp_payload_length)
-    {
-      GNUNET_break_op (0);
-      goto error;
-    }
-    len = input[*off];
-    if (0 == len)
-    {
-      (*off)++;
-      break;
-    }
-    if (len < 64)
-    {
-      if (*off + 1 + len > udp_payload_length)
-      {
-       GNUNET_break_op (0);
-       goto error;
-      }
-      GNUNET_asprintf (&tmp,
-                      "%.*s",
-                      (int) len,
-                      &udp_payload[*off + 1]);
-      if (IDNA_SUCCESS !=
-         (rc = idna_to_unicode_8z8z (tmp, &utf8, IDNA_ALLOW_UNASSIGNED)))
-      {
-       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-                   _("Failed to convert DNS IDNA name `%s' to UTF-8: %s\n"),
-                   tmp,
-                   idna_strerror (rc));
-       GNUNET_free (tmp);
-       GNUNET_asprintf (&tmp,
-                        "%s%.*s.",
-                        ret,
-                        (int) len,
-                        &udp_payload[*off + 1]);
-      }
-      else
-      {
-       GNUNET_free (tmp);
-       GNUNET_asprintf (&tmp,
-                        "%s%s.",
-                        ret,
-                        utf8);
-#if WINDOWS
-       idn_free (utf8);
-#else
-       free (utf8);
-#endif
-      }
-      GNUNET_free (ret);
-      ret = tmp;
-      *off += 1 + len;
-    }
-    else if ((64 | 128) == (len & (64 | 128)) )
-    {
-      if (depth > 32)
-      {
-       GNUNET_break_op (0);
-       goto error; /* hard bound on stack to prevent "infinite" recursion, disallow! */
-      }
-      /* pointer to string */
-      if (*off + 1 > udp_payload_length)
-      {
-       GNUNET_break_op (0);
-       goto error;
-      }
-      xoff = ((len - (64 | 128)) << 8) + input[*off+1];
-      xstr = parse_name (udp_payload,
-                        udp_payload_length,
-                        &xoff,
-                        depth + 1);
-      if (NULL == xstr)
-      {
-       GNUNET_break_op (0);
-       goto error;
-      }
-      GNUNET_asprintf (&tmp,
-                      "%s%s.",
-                      ret,
-                      xstr);
-      GNUNET_free (ret);
-      GNUNET_free (xstr);
-      ret = tmp;
-      if (strlen (ret) > udp_payload_length)
-      {
-       GNUNET_break_op (0);
-       goto error; /* we are looping (building an infinite string) */
-      }
-      *off += 2;
-      /* pointers always terminate names */
-      break;
-    }
-    else
-    {
-      /* neither pointer nor inline string, not supported... */
-      GNUNET_break_op (0);
-      goto error;
-    }
-  }
-  if (0 < strlen(ret))
-    ret[strlen(ret)-1] = '\0'; /* eat tailing '.' */
-  return ret;
- error:
-  GNUNET_break_op (0);
-  GNUNET_free (ret);
-  return NULL;
-}
-
-
-/**
- * Parse name inside of a DNS query or record.
- *
- * @param udp_payload entire UDP payload
- * @param udp_payload_length length of @a udp_payload
- * @param off pointer to the offset of the name to parse in the udp_payload (to be
- *                    incremented by the size of the name)
- * @return name as 0-terminated C string on success, NULL if the payload is malformed
- */
-char *
-GNUNET_DNSPARSER_parse_name (const char *udp_payload,
-                            size_t udp_payload_length,
-                            size_t *off)
-{
-  return parse_name (udp_payload, udp_payload_length, off, 0);
-}
-
-
-/**
- * Parse a DNS query entry.
- *
- * @param udp_payload entire UDP payload
- * @param udp_payload_length length of @a udp_payload
- * @param off pointer to the offset of the query to parse in the udp_payload (to be
- *                    incremented by the size of the query)
- * @param q where to write the query information
- * @return #GNUNET_OK on success, #GNUNET_SYSERR if the query is malformed
- */
-int
-GNUNET_DNSPARSER_parse_query (const char *udp_payload,
-                             size_t udp_payload_length,
-                             size_t *off,
-                             struct GNUNET_DNSPARSER_Query *q)
-{
-  char *name;
-  struct GNUNET_TUN_DnsQueryLine ql;
-
-  name = GNUNET_DNSPARSER_parse_name (udp_payload,
-                                     udp_payload_length,
-                                     off);
-  if (NULL == name)
-  {
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
-  }
-  q->name = name;
-  if (*off + sizeof (struct GNUNET_TUN_DnsQueryLine) > udp_payload_length)
-  {
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
-  }
-  GNUNET_memcpy (&ql, &udp_payload[*off], sizeof (ql));
-  *off += sizeof (ql);
-  q->type = ntohs (ql.type);
-  q->dns_traffic_class = ntohs (ql.dns_traffic_class);
-  return GNUNET_OK;
-}
-
-
-/**
- * Parse a DNS SOA record.
- *
- * @param udp_payload reference to UDP packet
- * @param udp_payload_length length of @a udp_payload
- * @param off pointer to the offset of the query to parse in the SOA record (to be
- *                    incremented by the size of the record), unchanged on error
- * @return the parsed SOA record, NULL on error
- */
-struct GNUNET_DNSPARSER_SoaRecord *
-GNUNET_DNSPARSER_parse_soa (const char *udp_payload,
-                           size_t udp_payload_length,
-                           size_t *off)
-{
-  struct GNUNET_DNSPARSER_SoaRecord *soa;
-  struct GNUNET_TUN_DnsSoaRecord soa_bin;
-  size_t old_off;
-
-  old_off = *off;
-  soa = GNUNET_new (struct GNUNET_DNSPARSER_SoaRecord);
-  soa->mname = GNUNET_DNSPARSER_parse_name (udp_payload,
-                                           udp_payload_length,
-                                           off);
-  soa->rname = GNUNET_DNSPARSER_parse_name (udp_payload,
-                                           udp_payload_length,
-                                           off);
-  if ( (NULL == soa->mname) ||
-       (NULL == soa->rname) ||
-       (*off + sizeof (struct GNUNET_TUN_DnsSoaRecord) > udp_payload_length) )
-  {
-    GNUNET_break_op (0);
-    GNUNET_DNSPARSER_free_soa (soa);
-    *off = old_off;
-    return NULL;
-  }
-  GNUNET_memcpy (&soa_bin,
-         &udp_payload[*off],
-         sizeof (struct GNUNET_TUN_DnsSoaRecord));
-  soa->serial = ntohl (soa_bin.serial);
-  soa->refresh = ntohl (soa_bin.refresh);
-  soa->retry = ntohl (soa_bin.retry);
-  soa->expire = ntohl (soa_bin.expire);
-  soa->minimum_ttl = ntohl (soa_bin.minimum);
-  (*off) += sizeof (struct GNUNET_TUN_DnsSoaRecord);
-  return soa;
-}
-
-
-/**
- * Parse a DNS MX record.
- *
- * @param udp_payload reference to UDP packet
- * @param udp_payload_length length of @a udp_payload
- * @param off pointer to the offset of the query to parse in the MX record (to be
- *                    incremented by the size of the record), unchanged on error
- * @return the parsed MX record, NULL on error
- */
-struct GNUNET_DNSPARSER_MxRecord *
-GNUNET_DNSPARSER_parse_mx (const char *udp_payload,
-                          size_t udp_payload_length,
-                          size_t *off)
-{
-  struct GNUNET_DNSPARSER_MxRecord *mx;
-  uint16_t mxpref;
-  size_t old_off;
-
-  old_off = *off;
-  if (*off + sizeof (uint16_t) > udp_payload_length)
-  {
-    GNUNET_break_op (0);
-    return NULL;
-  }
-  GNUNET_memcpy (&mxpref, &udp_payload[*off], sizeof (uint16_t));
-  (*off) += sizeof (uint16_t);
-  mx = GNUNET_new (struct GNUNET_DNSPARSER_MxRecord);
-  mx->preference = ntohs (mxpref);
-  mx->mxhost = GNUNET_DNSPARSER_parse_name (udp_payload,
-                                           udp_payload_length,
-                                           off);
-  if (NULL == mx->mxhost)
-  {
-    GNUNET_break_op (0);
-    GNUNET_DNSPARSER_free_mx (mx);
-    *off = old_off;
-    return NULL;
-  }
-  return mx;
-}
-
-
-/**
- * Parse a DNS SRV record.
- *
- * @param udp_payload reference to UDP packet
- * @param udp_payload_length length of @a udp_payload
- * @param off pointer to the offset of the query to parse in the SRV record (to be
- *                    incremented by the size of the record), unchanged on error
- * @return the parsed SRV record, NULL on error
- */
-struct GNUNET_DNSPARSER_SrvRecord *
-GNUNET_DNSPARSER_parse_srv (const char *udp_payload,
-                           size_t udp_payload_length,
-                           size_t *off)
-{
-  struct GNUNET_DNSPARSER_SrvRecord *srv;
-  struct GNUNET_TUN_DnsSrvRecord srv_bin;
-  size_t old_off;
-
-  old_off = *off;
-  if (*off + sizeof (struct GNUNET_TUN_DnsSrvRecord) > udp_payload_length)
-    return NULL;
-  GNUNET_memcpy (&srv_bin,
-         &udp_payload[*off],
-         sizeof (struct GNUNET_TUN_DnsSrvRecord));
-  (*off) += sizeof (struct GNUNET_TUN_DnsSrvRecord);
-  srv = GNUNET_new (struct GNUNET_DNSPARSER_SrvRecord);
-  srv->priority = ntohs (srv_bin.prio);
-  srv->weight = ntohs (srv_bin.weight);
-  srv->port = ntohs (srv_bin.port);
-  srv->target = GNUNET_DNSPARSER_parse_name (udp_payload,
-                                            udp_payload_length,
-                                            off);
-  if (NULL == srv->target)
-  {
-    GNUNET_DNSPARSER_free_srv (srv);
-    *off = old_off;
-    return NULL;
-  }
-  return srv;
-}
-
-
-/**
- * Parse a DNS CERT record.
- *
- * @param udp_payload reference to UDP packet
- * @param udp_payload_length length of @a udp_payload
- * @param off pointer to the offset of the query to parse in the CERT record (to be
- *                    incremented by the size of the record), unchanged on error
- * @return the parsed CERT record, NULL on error
- */
-struct GNUNET_DNSPARSER_CertRecord *
-GNUNET_DNSPARSER_parse_cert (const char *udp_payload,
-                             size_t udp_payload_length,
-                             size_t *off)
-{
-  struct GNUNET_DNSPARSER_CertRecord *cert;
-  struct GNUNET_TUN_DnsCertRecord dcert;
-
-  if (*off + sizeof (struct GNUNET_TUN_DnsCertRecord) >= udp_payload_length)
-  {
-    GNUNET_break_op (0);
-    return NULL;
-  }
-  GNUNET_memcpy (&dcert, &udp_payload[*off], sizeof (struct GNUNET_TUN_DnsCertRecord));
-  (*off) += sizeof (struct GNUNET_TUN_DnsCertRecord);
-  cert = GNUNET_new (struct GNUNET_DNSPARSER_CertRecord);
-  cert->cert_type = ntohs (dcert.cert_type);
-  cert->cert_tag = ntohs (dcert.cert_tag);
-  cert->algorithm = dcert.algorithm;
-  cert->certificate_size = udp_payload_length - (*off);
-  cert->certificate_data = GNUNET_malloc (cert->certificate_size);
-  GNUNET_memcpy (cert->certificate_data,
-          &udp_payload[*off],
-          cert->certificate_size);
-  (*off) += cert->certificate_size;
-  return cert;
-}
-
-
-/**
- * Parse a DNS record entry.
- *
- * @param udp_payload entire UDP payload
- * @param udp_payload_length length of @a udp_payload
- * @param off pointer to the offset of the record to parse in the udp_payload (to be
- *                    incremented by the size of the record)
- * @param r where to write the record information
- * @return #GNUNET_OK on success, #GNUNET_SYSERR if the record is malformed
- */
-int
-GNUNET_DNSPARSER_parse_record (const char *udp_payload,
-                              size_t udp_payload_length,
-                              size_t *off,
-                              struct GNUNET_DNSPARSER_Record *r)
-{
-  char *name;
-  struct GNUNET_TUN_DnsRecordLine rl;
-  size_t old_off;
-  uint16_t data_len;
-
-  name = GNUNET_DNSPARSER_parse_name (udp_payload,
-                                     udp_payload_length,
-                                     off);
-  if (NULL == name)
-  {
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
-  }
-  r->name = name;
-  if (*off + sizeof (struct GNUNET_TUN_DnsRecordLine) > udp_payload_length)
-  {
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
-  }
-  GNUNET_memcpy (&rl, &udp_payload[*off], sizeof (rl));
-  (*off) += sizeof (rl);
-  r->type = ntohs (rl.type);
-  r->dns_traffic_class = ntohs (rl.dns_traffic_class);
-  r->expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
-                                                                                       ntohl (rl.ttl)));
-  data_len = ntohs (rl.data_len);
-  if (*off + data_len > udp_payload_length)
-  {
-    GNUNET_break_op (0);
-    return GNUNET_SYSERR;
-  }
-  old_off = *off;
-  switch (r->type)
-  {
-  case GNUNET_DNSPARSER_TYPE_NS:
-  case GNUNET_DNSPARSER_TYPE_CNAME:
-  case GNUNET_DNSPARSER_TYPE_DNAME:
-  case GNUNET_DNSPARSER_TYPE_PTR:
-    r->data.hostname = GNUNET_DNSPARSER_parse_name (udp_payload,
-                                                   udp_payload_length,
-                                                   off);
-    if ( (NULL == r->data.hostname) ||
-        (old_off + data_len != *off) )
-      return GNUNET_SYSERR;
-    return GNUNET_OK;
-  case GNUNET_DNSPARSER_TYPE_SOA:
-    r->data.soa = GNUNET_DNSPARSER_parse_soa (udp_payload,
-                                             udp_payload_length,
-                                             off);
-    if ( (NULL == r->data.soa) ||
-        (old_off + data_len != *off) )
-    {
-      GNUNET_break_op (0);
-      return GNUNET_SYSERR;
-    }
-    return GNUNET_OK;
-  case GNUNET_DNSPARSER_TYPE_MX:
-    r->data.mx = GNUNET_DNSPARSER_parse_mx (udp_payload,
-                                           udp_payload_length,
-                                           off);
-    if ( (NULL == r->data.mx) ||
-        (old_off + data_len != *off) )
-    {
-      GNUNET_break_op (0);
-      return GNUNET_SYSERR;
-    }
-    return GNUNET_OK;
-  case GNUNET_DNSPARSER_TYPE_SRV:
-    r->data.srv = GNUNET_DNSPARSER_parse_srv (udp_payload,
-                                             udp_payload_length,
-                                             off);
-    if ( (NULL == r->data.srv) ||
-        (old_off + data_len != *off) )
-    {
-      GNUNET_break_op (0);
-      return GNUNET_SYSERR;
-    }
-    return GNUNET_OK;
-  default:
-    r->data.raw.data = GNUNET_malloc (data_len);
-    r->data.raw.data_len = data_len;
-    GNUNET_memcpy (r->data.raw.data,
-                   &udp_payload[*off],
-                   data_len);
-    break;
-  }
-  (*off) += data_len;
-  return GNUNET_OK;
-}
-
-
-/**
- * Parse a UDP payload of a DNS packet in to a nice struct for further
- * processing and manipulation.
- *
- * @param udp_payload wire-format of the DNS packet
- * @param udp_payload_length number of bytes in @a udp_payload
- * @return NULL on error, otherwise the parsed packet
- */
-struct GNUNET_DNSPARSER_Packet *
-GNUNET_DNSPARSER_parse (const char *udp_payload,
-                       size_t udp_payload_length)
-{
-  struct GNUNET_DNSPARSER_Packet *p;
-  const struct GNUNET_TUN_DnsHeader *dns;
-  size_t off;
-  unsigned int n;
-  unsigned int i;
-
-  if (udp_payload_length < sizeof (struct GNUNET_TUN_DnsHeader))
-    return NULL;
-  dns = (const struct GNUNET_TUN_DnsHeader *) udp_payload;
-  off = sizeof (struct GNUNET_TUN_DnsHeader);
-  p = GNUNET_new (struct GNUNET_DNSPARSER_Packet);
-  p->flags = dns->flags;
-  p->id = dns->id;
-  n = ntohs (dns->query_count);
-  if (n > 0)
-  {
-    p->queries = GNUNET_malloc (n * sizeof (struct GNUNET_DNSPARSER_Query));
-    p->num_queries = n;
-    for (i=0;i<n;i++)
-      if (GNUNET_OK !=
-         GNUNET_DNSPARSER_parse_query (udp_payload,
-                                       udp_payload_length,
-                                       &off,
-                                       &p->queries[i]))
-       goto error;
-  }
-  n = ntohs (dns->answer_rcount);
-  if (n > 0)
-  {
-    p->answers = GNUNET_malloc (n * sizeof (struct GNUNET_DNSPARSER_Record));
-    p->num_answers = n;
-    for (i=0;i<n;i++)
-      if (GNUNET_OK !=
-         GNUNET_DNSPARSER_parse_record (udp_payload,
-                                        udp_payload_length,
-                                        &off,
-                                        &p->answers[i]))
-       goto error;
-  }
-  n = ntohs (dns->authority_rcount);
-  if (n > 0)
-  {
-    p->authority_records = GNUNET_malloc (n * sizeof (struct GNUNET_DNSPARSER_Record));
-    p->num_authority_records = n;
-    for (i=0;i<n;i++)
-      if (GNUNET_OK !=
-         GNUNET_DNSPARSER_parse_record (udp_payload,
-                                        udp_payload_length,
-                                        &off,
-                                        &p->authority_records[i]))
-       goto error;
-  }
-  n = ntohs (dns->additional_rcount);
-  if (n > 0)
-  {
-    p->additional_records = GNUNET_malloc (n * sizeof (struct GNUNET_DNSPARSER_Record));
-    p->num_additional_records = n;
-    for (i=0;i<n;i++)
-      if (GNUNET_OK !=
-         GNUNET_DNSPARSER_parse_record (udp_payload,
-                                        udp_payload_length,
-                                        &off,
-                                        &p->additional_records[i]))
-       goto error;
-  }
-  return p;
- error:
-  GNUNET_break_op (0);
-  GNUNET_DNSPARSER_free_packet (p);
-  return NULL;
-}
-
-
-/**
- * Free memory taken by a packet.
- *
- * @param p packet to free
- */
-void
-GNUNET_DNSPARSER_free_packet (struct GNUNET_DNSPARSER_Packet *p)
-{
-  unsigned int i;
-
-  for (i=0;i<p->num_queries;i++)
-    GNUNET_free_non_null (p->queries[i].name);
-  GNUNET_free_non_null (p->queries);
-  for (i=0;i<p->num_answers;i++)
-    GNUNET_DNSPARSER_free_record (&p->answers[i]);
-  GNUNET_free_non_null (p->answers);
-  for (i=0;i<p->num_authority_records;i++)
-    GNUNET_DNSPARSER_free_record (&p->authority_records[i]);
-  GNUNET_free_non_null (p->authority_records);
-  for (i=0;i<p->num_additional_records;i++)
-    GNUNET_DNSPARSER_free_record (&p->additional_records[i]);
-  GNUNET_free_non_null (p->additional_records);
-  GNUNET_free (p);
-}
-
-
-/* ********************** DNS packet assembly code **************** */
-
-
-/**
- * Add a DNS name to the UDP packet at the given location, converting
- * the name to IDNA notation as necessary.
- *
- * @param dst where to write the name (UDP packet)
- * @param dst_len number of bytes in @a dst
- * @param off pointer to offset where to write the name (increment by bytes used)
- *            must not be changed if there is an error
- * @param name name to write
- * @return #GNUNET_SYSERR if @a name is invalid
- *         #GNUNET_NO if @a name did not fit
- *         #GNUNET_OK if @a name was added to @a dst
- */
-int
-GNUNET_DNSPARSER_builder_add_name (char *dst,
-                                  size_t dst_len,
-                                  size_t *off,
-                                  const char *name)
-{
-  const char *dot;
-  const char *idna_name;
-  char *idna_start;
-  size_t start;
-  size_t pos;
-  size_t len;
-  Idna_rc rc;
-
-  if (NULL == name)
-    return GNUNET_SYSERR;
-
-  if (IDNA_SUCCESS !=
-      (rc = idna_to_ascii_8z (name,
-                              &idna_start,
-                              IDNA_ALLOW_UNASSIGNED)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-               _("Failed to convert UTF-8 name `%s' to DNS IDNA format: %s\n"),
-               name,
-               idna_strerror (rc));
-    return GNUNET_NO;
-  }
-  idna_name = idna_start;
-  start = *off;
-  if (start + strlen (idna_name) + 2 > dst_len)
-    goto fail;
-  pos = start;
-  do
-  {
-    dot = strchr (idna_name, '.');
-    if (NULL == dot)
-      len = strlen (idna_name);
-    else
-      len = dot - idna_name;
-    if ( (len >= 64) || (0 == len) )
-    {
-      GNUNET_break (0);
-      goto fail; /* segment too long or empty */
-    }
-    dst[pos++] = (char) (uint8_t) len;
-    GNUNET_memcpy (&dst[pos],
-                   idna_name,
-                   len);
-    pos += len;
-    idna_name += len + 1; /* also skip dot */
-  }
-  while (NULL != dot);
-  dst[pos++] = '\0'; /* terminator */
-  *off = pos;
-#if WINDOWS
-  idn_free (idna_start);
-#else
-  free (idna_start);
-#endif
-  return GNUNET_OK;
- fail:
-#if WINDOWS
-  idn_free (idna_start);
-#else
-  free (idna_start);
-#endif
-  return GNUNET_NO;
-}
-
-
-/**
- * Add a DNS query to the UDP packet at the given location.
- *
- * @param dst where to write the query
- * @param dst_len number of bytes in @a dst
- * @param off pointer to offset where to write the query (increment by bytes used)
- *            must not be changed if there is an error
- * @param query query to write
- * @return #GNUNET_SYSERR if @a query is invalid
- *         #GNUNET_NO if @a query did not fit
- *         #GNUNET_OK if @a query was added to @a dst
- */
-int
-GNUNET_DNSPARSER_builder_add_query (char *dst,
-                                   size_t dst_len,
-                                   size_t *off,
-                                   const struct GNUNET_DNSPARSER_Query *query)
-{
-  int ret;
-  struct GNUNET_TUN_DnsQueryLine ql;
-
-  ret = GNUNET_DNSPARSER_builder_add_name (dst, dst_len - sizeof (struct GNUNET_TUN_DnsQueryLine), off, query->name);
-  if (ret != GNUNET_OK)
-    return ret;
-  ql.type = htons (query->type);
-  ql.dns_traffic_class = htons (query->dns_traffic_class);
-  GNUNET_memcpy (&dst[*off], &ql, sizeof (ql));
-  (*off) += sizeof (ql);
-  return GNUNET_OK;
-}
-
-
-/**
- * Add an MX record to the UDP packet at the given location.
- *
- * @param dst where to write the mx record
- * @param dst_len number of bytes in @a dst
- * @param off pointer to offset where to write the mx information (increment by bytes used);
- *            can also change if there was an error
- * @param mx mx information to write
- * @return #GNUNET_SYSERR if @a mx is invalid
- *         #GNUNET_NO if @a mx did not fit
- *         #GNUNET_OK if @a mx was added to @a dst
- */
-int
-GNUNET_DNSPARSER_builder_add_mx (char *dst,
-                                size_t dst_len,
-                                size_t *off,
-                                const struct GNUNET_DNSPARSER_MxRecord *mx)
-{
-  uint16_t mxpref;
-
-  if (*off + sizeof (uint16_t) > dst_len)
-    return GNUNET_NO;
-  mxpref = htons (mx->preference);
-  GNUNET_memcpy (&dst[*off],
-                &mxpref,
-                sizeof (mxpref));
-  (*off) += sizeof (mxpref);
-  return GNUNET_DNSPARSER_builder_add_name (dst,
-                                           dst_len,
-                                           off,
-                                           mx->mxhost);
-}
-
-
-/**
- * Add a CERT record to the UDP packet at the given location.
- *
- * @param dst where to write the CERT record
- * @param dst_len number of bytes in @a dst
- * @param off pointer to offset where to write the CERT information (increment by bytes used);
- *            can also change if there was an error
- * @param cert CERT information to write
- * @return #GNUNET_SYSERR if @a cert is invalid
- *         #GNUNET_NO if @a cert did not fit
- *         #GNUNET_OK if @a cert was added to @a dst
- */
-int
-GNUNET_DNSPARSER_builder_add_cert (char *dst,
-                                   size_t dst_len,
-                                   size_t *off,
-                                   const struct GNUNET_DNSPARSER_CertRecord *cert)
-{
-  struct GNUNET_TUN_DnsCertRecord dcert;
-
-  if ( (cert->cert_type > UINT16_MAX) ||
-       (cert->cert_tag > UINT16_MAX) ||
-       (cert->algorithm > UINT8_MAX) )
-  {
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-  if (*off + sizeof (struct GNUNET_TUN_DnsCertRecord) + cert->certificate_size > dst_len)
-    return GNUNET_NO;
-  dcert.cert_type = htons ((uint16_t) cert->cert_type);
-  dcert.cert_tag = htons ((uint16_t) cert->cert_tag);
-  dcert.algorithm = (uint8_t) cert->algorithm;
-  GNUNET_memcpy (&dst[*off], &dcert, sizeof (dcert));
-  (*off) += sizeof (dcert);
-  GNUNET_memcpy (&dst[*off], cert->certificate_data, cert->certificate_size);
-  (*off) += cert->certificate_size;
-  return GNUNET_OK;
-}
-
-
-/**
- * Add an SOA record to the UDP packet at the given location.
- *
- * @param dst where to write the SOA record
- * @param dst_len number of bytes in @a dst
- * @param off pointer to offset where to write the SOA information (increment by bytes used)
- *            can also change if there was an error
- * @param soa SOA information to write
- * @return #GNUNET_SYSERR if @a soa is invalid
- *         #GNUNET_NO if @a soa did not fit
- *         #GNUNET_OK if @a soa was added to @a dst
- */
-int
-GNUNET_DNSPARSER_builder_add_soa (char *dst,
-                                 size_t dst_len,
-                                 size_t *off,
-                                 const struct GNUNET_DNSPARSER_SoaRecord *soa)
-{
-  struct GNUNET_TUN_DnsSoaRecord sd;
-  int ret;
-
-  if ( (GNUNET_OK != (ret = GNUNET_DNSPARSER_builder_add_name (dst,
-                                                               dst_len,
-                                                               off,
-                                                               soa->mname))) ||
-       (GNUNET_OK != (ret = GNUNET_DNSPARSER_builder_add_name (dst,
-                                                               dst_len,
-                                                               off,
-                                                               soa->rname)) ) )
-    return ret;
-  if (*off + sizeof (struct GNUNET_TUN_DnsSoaRecord) > dst_len)
-    return GNUNET_NO;
-  sd.serial = htonl (soa->serial);
-  sd.refresh = htonl (soa->refresh);
-  sd.retry = htonl (soa->retry);
-  sd.expire = htonl (soa->expire);
-  sd.minimum = htonl (soa->minimum_ttl);
-  GNUNET_memcpy (&dst[*off], &sd, sizeof (sd));
-  (*off) += sizeof (sd);
-  return GNUNET_OK;
-}
-
-
-/**
- * Add an SRV record to the UDP packet at the given location.
- *
- * @param dst where to write the SRV record
- * @param dst_len number of bytes in @a dst
- * @param off pointer to offset where to write the SRV information (increment by bytes used)
- *            can also change if there was an error
- * @param srv SRV information to write
- * @return #GNUNET_SYSERR if @a srv is invalid
- *         #GNUNET_NO if @a srv did not fit
- *         #GNUNET_OK if @a srv was added to @a dst
- */
-int
-GNUNET_DNSPARSER_builder_add_srv (char *dst,
-                                 size_t dst_len,
-                                 size_t *off,
-                                 const struct GNUNET_DNSPARSER_SrvRecord *srv)
-{
-  struct GNUNET_TUN_DnsSrvRecord sd;
-  int ret;
-
-  if (*off + sizeof (struct GNUNET_TUN_DnsSrvRecord) > dst_len)
-    return GNUNET_NO;
-  sd.prio = htons (srv->priority);
-  sd.weight = htons (srv->weight);
-  sd.port = htons (srv->port);
-  GNUNET_memcpy (&dst[*off], &sd, sizeof (sd));
-  (*off) += sizeof (sd);
-  if (GNUNET_OK != (ret = GNUNET_DNSPARSER_builder_add_name (dst,
-                                   dst_len,
-                                   off,
-                                   srv->target)))
-    return ret;
-  return GNUNET_OK;
-}
-
-
-/**
- * Add a DNS record to the UDP packet at the given location.
- *
- * @param dst where to write the query
- * @param dst_len number of bytes in @a dst
- * @param off pointer to offset where to write the query (increment by bytes used)
- *            must not be changed if there is an error
- * @param record record to write
- * @return #GNUNET_SYSERR if @a record is invalid
- *         #GNUNET_NO if @a record did not fit
- *         #GNUNET_OK if @a record was added to @a dst
- */
-static int
-add_record (char *dst,
-           size_t dst_len,
-           size_t *off,
-           const struct GNUNET_DNSPARSER_Record *record)
-{
-  int ret;
-  size_t start;
-  size_t pos;
-  struct GNUNET_TUN_DnsRecordLine rl;
-
-  start = *off;
-  ret = GNUNET_DNSPARSER_builder_add_name (dst,
-                                           dst_len - sizeof (struct GNUNET_TUN_DnsRecordLine),
-                                           off,
-                                           record->name);
-  if (GNUNET_OK != ret)
-    return ret;
-  /* '*off' is now the position where we will need to write the record line */
-
-  pos = *off + sizeof (struct GNUNET_TUN_DnsRecordLine);
-  switch (record->type)
-  {
-  case GNUNET_DNSPARSER_TYPE_MX:
-    ret = GNUNET_DNSPARSER_builder_add_mx (dst,
-                                          dst_len,
-                                          &pos,
-                                          record->data.mx);
-    break;
-  case GNUNET_DNSPARSER_TYPE_CERT:
-    ret = GNUNET_DNSPARSER_builder_add_cert (dst,
-                                            dst_len,
-                                            &pos,
-                                            record->data.cert);
-    break;
-  case GNUNET_DNSPARSER_TYPE_SOA:
-    ret = GNUNET_DNSPARSER_builder_add_soa (dst,
-                                           dst_len,
-                                           &pos,
-                                           record->data.soa);
-    break;
-  case GNUNET_DNSPARSER_TYPE_NS:
-  case GNUNET_DNSPARSER_TYPE_CNAME:
-  case GNUNET_DNSPARSER_TYPE_PTR:
-    ret = GNUNET_DNSPARSER_builder_add_name (dst,
-                                            dst_len,
-                                            &pos,
-                                            record->data.hostname);
-    break;
-  case GNUNET_DNSPARSER_TYPE_SRV:
-    ret = GNUNET_DNSPARSER_builder_add_srv (dst,
-                                           dst_len,
-                                           &pos,
-                                           record->data.srv);
-    break;
-  default:
-    if (pos + record->data.raw.data_len > dst_len)
-    {
-      ret = GNUNET_NO;
-      break;
-    }
-    GNUNET_memcpy (&dst[pos],
-                  record->data.raw.data,
-                  record->data.raw.data_len);
-    pos += record->data.raw.data_len;
-    ret = GNUNET_OK;
-    break;
-  }
-  if (GNUNET_OK != ret)
-  {
-    *off = start;
-    return GNUNET_NO;
-  }
-
-  if (pos - (*off + sizeof (struct GNUNET_TUN_DnsRecordLine)) > UINT16_MAX)
-  {
-    /* record data too long */
-    *off = start;
-    return GNUNET_NO;
-  }
-  rl.type = htons (record->type);
-  rl.dns_traffic_class = htons (record->dns_traffic_class);
-  rl.ttl = htonl (GNUNET_TIME_absolute_get_remaining (record->expiration_time).rel_value_us / 1000LL / 1000LL); /* in seconds */
-  rl.data_len = htons ((uint16_t) (pos - (*off + sizeof (struct GNUNET_TUN_DnsRecordLine))));
-  GNUNET_memcpy (&dst[*off], &rl, sizeof (struct GNUNET_TUN_DnsRecordLine));
-  *off = pos;
-  return GNUNET_OK;
-}
-
-
-/**
- * Given a DNS packet @a p, generate the corresponding UDP payload.
- * Note that we do not attempt to pack the strings with pointers
- * as this would complicate the code and this is about being
- * simple and secure, not fast, fancy and broken like bind.
- *
- * @param p packet to pack
- * @param max maximum allowed size for the resulting UDP payload
- * @param buf set to a buffer with the packed message
- * @param buf_length set to the length of @a buf
- * @return #GNUNET_SYSERR if @a p is invalid
- *         #GNUNET_NO if @a p was truncated (but there is still a result in @a buf)
- *         #GNUNET_OK if @a p was packed completely into @a buf
- */
-int
-GNUNET_DNSPARSER_pack (const struct GNUNET_DNSPARSER_Packet *p,
-                      uint16_t max,
-                      char **buf,
-                      size_t *buf_length)
-{
-  struct GNUNET_TUN_DnsHeader dns;
-  size_t off;
-  char tmp[max];
-  unsigned int i;
-  int ret;
-  int trc;
-
-  if ( (p->num_queries > UINT16_MAX) ||
-       (p->num_answers > UINT16_MAX) ||
-       (p->num_authority_records > UINT16_MAX) ||
-       (p->num_additional_records > UINT16_MAX) )
-    return GNUNET_SYSERR;
-  dns.id = p->id;
-  dns.flags = p->flags;
-  dns.query_count = htons (p->num_queries);
-  dns.answer_rcount = htons (p->num_answers);
-  dns.authority_rcount = htons (p->num_authority_records);
-  dns.additional_rcount = htons (p->num_additional_records);
-
-  off = sizeof (struct GNUNET_TUN_DnsHeader);
-  trc = GNUNET_NO;
-  for (i=0;i<p->num_queries;i++)
-  {
-    ret = GNUNET_DNSPARSER_builder_add_query (tmp,
-                                             sizeof (tmp),
-                                             &off,
-                                             &p->queries[i]);
-    if (GNUNET_SYSERR == ret)
-      return GNUNET_SYSERR;
-    if (GNUNET_NO == ret)
-    {
-      dns.query_count = htons ((uint16_t) (i-1));
-      trc = GNUNET_YES;
-      break;
-    }
-  }
-  for (i=0;i<p->num_answers;i++)
-  {
-    ret = add_record (tmp,
-                     sizeof (tmp),
-                     &off,
-                     &p->answers[i]);
-    if (GNUNET_SYSERR == ret)
-      return GNUNET_SYSERR;
-    if (GNUNET_NO == ret)
-    {
-      dns.answer_rcount = htons ((uint16_t) (i-1));
-      trc = GNUNET_YES;
-      break;
-    }
-  }
-  for (i=0;i<p->num_authority_records;i++)
-  {
-    ret = add_record (tmp,
-                     sizeof (tmp),
-                     &off,
-                     &p->authority_records[i]);
-    if (GNUNET_SYSERR == ret)
-      return GNUNET_SYSERR;
-    if (GNUNET_NO == ret)
-    {
-      dns.authority_rcount = htons ((uint16_t) (i-1));
-      trc = GNUNET_YES;
-      break;
-    }
-  }
-  for (i=0;i<p->num_additional_records;i++)
-  {
-    ret = add_record (tmp,
-                     sizeof (tmp),
-                     &off,
-                     &p->additional_records[i]);
-    if (GNUNET_SYSERR == ret)
-      return GNUNET_SYSERR;
-    if (GNUNET_NO == ret)
-    {
-      dns.additional_rcount = htons (i-1);
-      trc = GNUNET_YES;
-      break;
-    }
-  }
-
-  if (GNUNET_YES == trc)
-    dns.flags.message_truncated = 1;
-  GNUNET_memcpy (tmp,
-                &dns,
-                sizeof (struct GNUNET_TUN_DnsHeader));
-
-  *buf = GNUNET_malloc (off);
-  *buf_length = off;
-  GNUNET_memcpy (*buf,
-                tmp,
-                off);
-  if (GNUNET_YES == trc)
-    return GNUNET_NO;
-  return GNUNET_OK;
-}
-
-
-/**
- * Convert a block of binary data to HEX.
- *
- * @param data binary data to convert
- * @param data_size number of bytes in @a data
- * @return HEX string (lower case)
- */
-char *
-GNUNET_DNSPARSER_bin_to_hex (const void *data,
-                             size_t data_size)
-{
-  char *ret;
-  size_t off;
-  const uint8_t *idata;
-
-  idata = data;
-  ret = GNUNET_malloc (data_size * 2 + 1);
-  for (off = 0; off < data_size; off++)
-    sprintf (&ret[off * 2],
-             "%02x",
-             idata[off]);
-  return ret;
-}
-
-
-/**
- * Convert a HEX string to block of binary data.
- *
- * @param hex HEX string to convert (may contain mixed case)
- * @param data where to write result, must be
- *             at least `strlen(hex)/2` bytes long
- * @return number of bytes written to data
- */
-size_t
-GNUNET_DNSPARSER_hex_to_bin (const char *hex,
-                             void *data)
-{
-  size_t data_size;
-  size_t off;
-  uint8_t *idata;
-  unsigned int h;
-  char in[3];
-
-  data_size = strlen (hex) / 2;
-  idata = data;
-  in[2] = '\0';
-  for (off = 0; off < data_size; off++)
-  {
-    in[0] = tolower ((unsigned char) hex[off * 2]);
-    in[1] = tolower ((unsigned char) hex[off * 2 + 1]);
-    if (1 != sscanf (in, "%x", &h))
-      return off;
-    idata[off] = (uint8_t) h;
-  }
-  return off;
-}
-
-
-/* end of dnsparser.c */
diff --git a/src/dns/dnsstub.c b/src/dns/dnsstub.c
deleted file mode 100644 (file)
index 969ff7b..0000000
+++ /dev/null
@@ -1,749 +0,0 @@
-/*
-     This file is part of GNUnet.
-     Copyright (C) 2012, 2018 GNUnet e.V.
-
-     GNUnet is free software: you can redistribute it and/or modify it
-     under the terms of the GNU Affero General Public License as published
-     by the Free Software Foundation, either version 3 of the License,
-     or (at your option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     Affero General Public License for more details.
-    
-     You should have received a copy of the GNU Affero General Public License
-     along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-/**
- * @file dns/dnsstub.c
- * @brief DNS stub resolver which sends DNS requests to an actual resolver
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_tun_lib.h"
-#include "gnunet_dnsstub_lib.h"
-
-/**
- * Timeout for retrying DNS queries.
- */
-#define DNS_RETRANSMIT_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250)
-
-
-/**
- * DNS Server used for resolution.
- */
-struct DnsServer;
-
-
-/**
- * UDP socket we are using for sending DNS requests to the Internet.
- */
-struct GNUNET_DNSSTUB_RequestSocket
-{
-
-  /**
-   * UDP socket we use for this request for IPv4
-   */
-  struct GNUNET_NETWORK_Handle *dnsout4;
-
-  /**
-   * UDP socket we use for this request for IPv6
-   */
-  struct GNUNET_NETWORK_Handle *dnsout6;
-
-  /**
-   * Function to call with result.
-   */
-  GNUNET_DNSSTUB_ResultCallback rc;
-
-  /**
-   * Closure for @e rc.
-   */
-  void *rc_cls;
-
-  /**
-   * Task for reading from dnsout4 and dnsout6.
-   */
-  struct GNUNET_SCHEDULER_Task *read_task;
-
-  /**
-   * Task for retrying transmission of the query.
-   */
-  struct GNUNET_SCHEDULER_Task *retry_task;
-
-  /**
-   * Next address we sent the DNS request to.
-   */
-  struct DnsServer *ds_pos;
-
-  /**
-   * Context this request executes in.
-   */
-  struct GNUNET_DNSSTUB_Context *ctx;
-
-  /**
-   * Query we sent to @e addr.
-   */
-  void *request;
-
-  /**
-   * Number of bytes in @a request.
-   */
-  size_t request_len;
-
-};
-
-
-/**
- * DNS Server used for resolution.
- */
-struct DnsServer
-{
-
-  /**
-   * Kept in a DLL.
-   */
-  struct DnsServer *next;
-
-  /**
-   * Kept in a DLL.
-   */
-  struct DnsServer *prev;
-
-  /**
-   * IP address of the DNS resolver.
-   */
-  struct sockaddr_storage ss;
-};
-
-
-/**
- * Handle to the stub resolver.
- */
-struct GNUNET_DNSSTUB_Context
-{
-
-  /**
-   * Array of all open sockets for DNS requests.
-   */
-  struct GNUNET_DNSSTUB_RequestSocket *sockets;
-
-  /**
-   * DLL of DNS resolvers we use.
-   */
-  struct DnsServer *dns_head;
-
-  /**
-   * DLL of DNS resolvers we use.
-   */
-  struct DnsServer *dns_tail;
-
-  /**
-   * How frequently do we retry requests?
-   */
-  struct GNUNET_TIME_Relative retry_freq;
-
-  /**
-   * Length of @e sockets array.
-   */
-  unsigned int num_sockets;
-
-};
-
-
-/**
- * We're done with a `struct GNUNET_DNSSTUB_RequestSocket`, close it for now.
- *
- * @param rs request socket to clean up
- */
-static void
-cleanup_rs (struct GNUNET_DNSSTUB_RequestSocket *rs)
-{
-  if (NULL != rs->dnsout4)
-  {
-    GNUNET_NETWORK_socket_close (rs->dnsout4);
-    rs->dnsout4 = NULL;
-  }
-  if (NULL != rs->dnsout6)
-  {
-    GNUNET_NETWORK_socket_close (rs->dnsout6);
-    rs->dnsout6 = NULL;
-  }
-  if (NULL != rs->read_task)
-  {
-    GNUNET_SCHEDULER_cancel (rs->read_task);
-    rs->read_task = NULL;
-  }
-  if (NULL != rs->retry_task)
-  {
-    GNUNET_SCHEDULER_cancel (rs->retry_task);
-    rs->retry_task = NULL;
-  }
-  if (NULL != rs->request)
-  {
-    GNUNET_free (rs->request);
-    rs->request = NULL;
-  }
-}
-
-
-/**
- * Open source port for sending DNS requests
- *
- * @param af AF_INET or AF_INET6
- * @return #GNUNET_OK on success
- */
-static struct GNUNET_NETWORK_Handle *
-open_socket (int af)
-{
-  struct sockaddr_in a4;
-  struct sockaddr_in6 a6;
-  struct sockaddr *sa;
-  socklen_t alen;
-  struct GNUNET_NETWORK_Handle *ret;
-
-  ret = GNUNET_NETWORK_socket_create (af, SOCK_DGRAM, 0);
-  if (NULL == ret)
-    return NULL;
-  switch (af)
-  {
-  case AF_INET:
-    memset (&a4, 0, alen = sizeof (struct sockaddr_in));
-    sa = (struct sockaddr *) &a4;
-    break;
-  case AF_INET6:
-    memset (&a6, 0, alen = sizeof (struct sockaddr_in6));
-    sa = (struct sockaddr *) &a6;
-    break;
-  default:
-    GNUNET_break (0);
-    GNUNET_NETWORK_socket_close (ret);
-    return NULL;
-  }
-  sa->sa_family = af;
-  if (GNUNET_OK != GNUNET_NETWORK_socket_bind (ret,
-                                              sa,
-                                              alen))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               _("Could not bind to any port: %s\n"),
-               STRERROR (errno));
-    GNUNET_NETWORK_socket_close (ret);
-    return NULL;
-  }
-  return ret;
-}
-
-
-/**
- * Get a socket of the specified address family to send out a
- * UDP DNS request to the Internet.
- *
- * @param ctx the DNSSTUB context
- * @return NULL on error
- */
-static struct GNUNET_DNSSTUB_RequestSocket *
-get_request_socket (struct GNUNET_DNSSTUB_Context *ctx)
-{
-  struct GNUNET_DNSSTUB_RequestSocket *rs;
-
-  for (unsigned int i=0;i<256;i++)
-  {
-    rs = &ctx->sockets[GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
-                                                 ctx->num_sockets)];
-    if (NULL == rs->rc)
-      break;
-  }
-  if (NULL != rs->rc)
-  {
-    /* signal "failure" */
-    rs->rc (rs->rc_cls,
-            NULL,
-            0);
-    rs->rc = NULL;
-  }
-  if (NULL != rs->read_task)
-  {
-    GNUNET_SCHEDULER_cancel (rs->read_task);
-    rs->read_task = NULL;
-  }
-  if (NULL != rs->retry_task)
-  {
-    GNUNET_SCHEDULER_cancel (rs->retry_task);
-    rs->retry_task = NULL;
-  }
-  if (NULL != rs->request)
-  {
-    GNUNET_free (rs->request);
-    rs->request = NULL;
-  }
-  rs->ctx = ctx;
-  return rs;
-}
-
-
-/**
- * Actually do the reading of a DNS packet from our UDP socket and see
- * if we have a valid, matching, pending request.
- *
- * @param rs request socket with callback details
- * @param dnsout socket to read from
- * @return #GNUNET_OK on success, #GNUNET_NO on drop, #GNUNET_SYSERR on IO-errors (closed socket)
- */
-static int
-do_dns_read (struct GNUNET_DNSSTUB_RequestSocket *rs,
-            struct GNUNET_NETWORK_Handle *dnsout)
-{
-  struct GNUNET_DNSSTUB_Context *ctx = rs->ctx;
-  ssize_t r;
-  int len;
-
-#ifndef MINGW
-  if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout),
-                  FIONREAD,
-                  &len))
-  {
-    /* conservative choice: */
-    len = UINT16_MAX;
-  }
-#else
-  /* port the code above? */
-  len = UINT16_MAX;
-#endif
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-             "Receiving %d byte DNS reply\n",
-             len);
-  {
-    unsigned char buf[len] GNUNET_ALIGN;
-    int found;
-    struct sockaddr_storage addr;
-    socklen_t addrlen;
-    struct GNUNET_TUN_DnsHeader *dns;
-
-    addrlen = sizeof (addr);
-    memset (&addr,
-            0,
-            sizeof (addr));
-    r = GNUNET_NETWORK_socket_recvfrom (dnsout,
-                                       buf,
-                                        sizeof (buf),
-                                       (struct sockaddr*) &addr,
-                                        &addrlen);
-    if (-1 == r)
-    {
-      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
-                           "recvfrom");
-      GNUNET_NETWORK_socket_close (dnsout);
-      return GNUNET_SYSERR;
-    }
-    found = GNUNET_NO;
-    for (struct DnsServer *ds = ctx->dns_head; NULL != ds; ds = ds->next)
-    {
-      if (0 == memcmp (&addr,
-                       &ds->ss,
-                       GNUNET_MIN (sizeof (struct sockaddr_storage),
-                                   addrlen)))
-      {
-        found = GNUNET_YES;
-        break;
-      }
-    }
-    if (GNUNET_NO == found)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Received DNS response from server we never asked (ignored)");
-      return GNUNET_NO;
-    }
-    if (sizeof (struct GNUNET_TUN_DnsHeader) > r)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                 _("Received DNS response that is too small (%u bytes)"),
-                 (unsigned int) r);
-      return GNUNET_NO;
-    }
-    dns = (struct GNUNET_TUN_DnsHeader *) buf;
-    if (NULL == rs->rc)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                 "Request timeout or cancelled; ignoring reply\n");
-      return GNUNET_NO;
-    }
-    rs->rc (rs->rc_cls,
-            dns,
-            r);
-  }
-  return GNUNET_OK;
-}
-
-
-/**
- * Read a DNS response from the (unhindered) UDP-Socket
- *
- * @param cls socket to read from
- */
-static void
-read_response (void *cls);
-
-
-/**
- * Schedule #read_response() task for @a rs.
- *
- * @param rs request to schedule read operation for
- */
-static void
-schedule_read (struct GNUNET_DNSSTUB_RequestSocket *rs)
-{
-  struct GNUNET_NETWORK_FDSet *rset;
-
-  if (NULL != rs->read_task)
-    GNUNET_SCHEDULER_cancel (rs->read_task);
-  rset = GNUNET_NETWORK_fdset_create ();
-  if (NULL != rs->dnsout4)
-    GNUNET_NETWORK_fdset_set (rset,
-                              rs->dnsout4);
-  if (NULL != rs->dnsout6)
-    GNUNET_NETWORK_fdset_set (rset,
-                              rs->dnsout6);
-  rs->read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
-                                              GNUNET_TIME_UNIT_FOREVER_REL,
-                                              rset,
-                                              NULL,
-                                              &read_response,
-                                               rs);
-  GNUNET_NETWORK_fdset_destroy (rset);
-}
-
-
-/**
- * Read a DNS response from the (unhindered) UDP-Socket
- *
- * @param cls `struct GNUNET_DNSSTUB_RequestSocket` to read from
- */
-static void
-read_response (void *cls)
-{
-  struct GNUNET_DNSSTUB_RequestSocket *rs = cls;
-  const struct GNUNET_SCHEDULER_TaskContext *tc;
-
-  rs->read_task = NULL;
-  tc = GNUNET_SCHEDULER_get_task_context ();
-  /* read and process ready sockets */
-  if ( (NULL != rs->dnsout4) &&
-       (GNUNET_NETWORK_fdset_isset (tc->read_ready,
-                                    rs->dnsout4)) &&
-       (GNUNET_SYSERR ==
-        do_dns_read (rs,
-                     rs->dnsout4)) )
-    rs->dnsout4 = NULL;
-  if ( (NULL != rs->dnsout6) &&
-       (GNUNET_NETWORK_fdset_isset (tc->read_ready,
-                                    rs->dnsout6)) &&
-       (GNUNET_SYSERR ==
-        do_dns_read (rs,
-                     rs->dnsout6)) )
-    rs->dnsout6 = NULL;
-  /* re-schedule read task */
-  schedule_read (rs);
-}
-
-
-/**
- * Task to (re)transmit the DNS query, possibly repeatedly until
- * we succeed.
- *
- * @param cls our `struct GNUNET_DNSSTUB_RequestSocket *`
- */
-static void
-transmit_query (void *cls)
-{
-  struct GNUNET_DNSSTUB_RequestSocket *rs = cls;
-  struct GNUNET_DNSSTUB_Context *ctx = rs->ctx;
-  const struct sockaddr *sa;
-  socklen_t salen;
-  struct DnsServer *ds;
-  struct GNUNET_NETWORK_Handle *dnsout;
-
-  rs->retry_task = GNUNET_SCHEDULER_add_delayed (ctx->retry_freq,
-                                                 &transmit_query,
-                                                 rs);
-  ds = rs->ds_pos;
-  rs->ds_pos = ds->next;
-  if (NULL == rs->ds_pos)
-    rs->ds_pos = ctx->dns_head;
-  GNUNET_assert (NULL != ds);
-  dnsout = NULL;
-  switch (ds->ss.ss_family)
-  {
-  case AF_INET:
-    if (NULL == rs->dnsout4)
-      rs->dnsout4 = open_socket (AF_INET);
-    dnsout = rs->dnsout4;
-    sa = (const struct sockaddr *) &ds->ss;
-    salen = sizeof (struct sockaddr_in);
-    break;
-  case AF_INET6:
-    if (NULL == rs->dnsout6)
-      rs->dnsout6 = open_socket (AF_INET6);
-    dnsout = rs->dnsout6;
-    sa = (const struct sockaddr *) &ds->ss;
-    salen = sizeof (struct sockaddr_in6);
-    break;
-  default:
-    return;
-  }
-  if (NULL == dnsout)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Unable to use configure DNS server, skipping\n");
-    return;
-  }
-  if (GNUNET_SYSERR ==
-      GNUNET_NETWORK_socket_sendto (dnsout,
-                                   rs->request,
-                                   rs->request_len,
-                                    sa,
-                                    salen))
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-               _("Failed to send DNS request to %s: %s\n"),
-               GNUNET_a2s (sa,
-                            salen),
-                STRERROR (errno));
-  else
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-               _("Sent DNS request to %s\n"),
-               GNUNET_a2s (sa,
-                            salen));
-  schedule_read (rs);
-}
-
-
-/**
- * Perform DNS resolution using our default IP from init.
- *
- * @param ctx stub resolver to use
- * @param request DNS request to transmit
- * @param request_len number of bytes in msg
- * @param rc function to call with result
- * @param rc_cls closure for 'rc'
- * @return socket used for the request, NULL on error
- */
-struct GNUNET_DNSSTUB_RequestSocket *
-GNUNET_DNSSTUB_resolve (struct GNUNET_DNSSTUB_Context *ctx,
-                        const void *request,
-                        size_t request_len,
-                        GNUNET_DNSSTUB_ResultCallback rc,
-                        void *rc_cls)
-{
-  struct GNUNET_DNSSTUB_RequestSocket *rs;
-
-  if (NULL == ctx->dns_head)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "No DNS server configured for resolution\n");
-    return NULL;
-  }
-  if (NULL == (rs = get_request_socket (ctx)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "No request socket available for DNS resolution\n");
-    return NULL;
-  }
-  rs->ds_pos = ctx->dns_head;
-  rs->rc = rc;
-  rs->rc_cls = rc_cls;
-  rs->request = GNUNET_memdup (request,
-                               request_len);
-  rs->request_len = request_len;
-  rs->retry_task = GNUNET_SCHEDULER_add_now (&transmit_query,
-                                             rs);
-  return rs;
-}
-
-
-/**
- * Cancel DNS resolution.
- *
- * @param rs resolution to cancel
- */
-void
-GNUNET_DNSSTUB_resolve_cancel (struct GNUNET_DNSSTUB_RequestSocket *rs)
-{
-  rs->rc = NULL;
-  if (NULL != rs->retry_task)
-  {
-    GNUNET_SCHEDULER_cancel (rs->retry_task);
-    rs->retry_task = NULL;
-  }
-  if (NULL != rs->read_task)
-  {
-    GNUNET_SCHEDULER_cancel (rs->read_task);
-    rs->read_task = NULL;
-  }
-}
-
-
-/**
- * Start a DNS stub resolver.
- *
- * @param num_sockets how many sockets should we open
- *        in parallel for DNS queries for this stub?
- * @return NULL on error
- */
-struct GNUNET_DNSSTUB_Context *
-GNUNET_DNSSTUB_start (unsigned int num_sockets)
-{
-  struct GNUNET_DNSSTUB_Context *ctx;
-
-  if (0 == num_sockets)
-  {
-    GNUNET_break (0);
-    return NULL;
-  }
-  ctx = GNUNET_new (struct GNUNET_DNSSTUB_Context);
-  ctx->num_sockets = num_sockets;
-  ctx->sockets = GNUNET_new_array (num_sockets,
-                                   struct GNUNET_DNSSTUB_RequestSocket);
-  ctx->retry_freq = DNS_RETRANSMIT_DELAY;
-  return ctx;
-}
-
-
-/**
- * Add nameserver for use by the DNSSTUB.  We will use
- * all provided nameservers for resolution (round-robin).
- *
- * @param ctx resolver context to modify
- * @param dns_ip target IP address to use (as string)
- * @return #GNUNET_OK on success
- */
-int
-GNUNET_DNSSTUB_add_dns_ip (struct GNUNET_DNSSTUB_Context *ctx,
-                           const char *dns_ip)
-{
-  struct DnsServer *ds;
-  struct in_addr i4;
-  struct in6_addr i6;
-
-  ds = GNUNET_new (struct DnsServer);
-  if (1 == inet_pton (AF_INET,
-                      dns_ip,
-                      &i4))
-  {
-    struct sockaddr_in *s4 = (struct sockaddr_in *) &ds->ss;
-
-    s4->sin_family = AF_INET;
-    s4->sin_port = htons (53);
-    s4->sin_addr = i4;
-#if HAVE_SOCKADDR_IN_SIN_LEN
-    s4->sin_len = (u_char) sizeof (struct sockaddr_in);
-#endif
-  }
-  else if (1 == inet_pton (AF_INET6,
-                           dns_ip,
-                           &i6))
-  {
-    struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &ds->ss;
-
-    s6->sin6_family = AF_INET6;
-    s6->sin6_port = htons (53);
-    s6->sin6_addr = i6;
-#if HAVE_SOCKADDR_IN_SIN_LEN
-    s6->sin6_len = (u_char) sizeof (struct sockaddr_in6);
-#endif
-  }
-  else
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-                "Malformed IP address `%s' for DNS server\n",
-                dns_ip);
-    GNUNET_free (ds);
-    return GNUNET_SYSERR;
-  }
-  GNUNET_CONTAINER_DLL_insert (ctx->dns_head,
-                               ctx->dns_tail,
-                               ds);
-  return GNUNET_OK;
-}
-
-
-/**
- * Add nameserver for use by the DNSSTUB.  We will use
- * all provided nameservers for resolution (round-robin).
- *
- * @param ctx resolver context to modify
- * @param sa socket address of DNS resolver to use
- * @return #GNUNET_OK on success
- */
-int
-GNUNET_DNSSTUB_add_dns_sa (struct GNUNET_DNSSTUB_Context *ctx,
-                           const struct sockaddr *sa)
-{
-  struct DnsServer *ds;
-
-  ds = GNUNET_new (struct DnsServer);
-  switch (sa->sa_family)
-  {
-  case AF_INET:
-    GNUNET_memcpy (&ds->ss,
-                   sa,
-                   sizeof (struct sockaddr_in));
-    break;
-  case AF_INET6:
-    GNUNET_memcpy (&ds->ss,
-                   sa,
-                   sizeof (struct sockaddr_in6));
-    break;
-  default:
-    GNUNET_break (0);
-    GNUNET_free (ds);
-    return GNUNET_SYSERR;
-  }
-  GNUNET_CONTAINER_DLL_insert (ctx->dns_head,
-                               ctx->dns_tail,
-                               ds);
-  return GNUNET_OK;
-}
-
-
-/**
- * How long should we try requests before timing out?
- * Only effective for requests issued after this call.
- *
- * @param ctx resolver context to modify
- * @param retry_freq how long to wait between retries
- */
-void
-GNUNET_DNSSTUB_set_retry (struct GNUNET_DNSSTUB_Context *ctx,
-                          struct GNUNET_TIME_Relative retry_freq)
-{
-  ctx->retry_freq = retry_freq;
-}
-
-
-/**
- * Cleanup DNSSTUB resolver.
- *
- * @param ctx stub resolver to clean up
- */
-void
-GNUNET_DNSSTUB_stop (struct GNUNET_DNSSTUB_Context *ctx)
-{
-  struct DnsServer *ds;
-
-  while (NULL != (ds = ctx->dns_head))
-  {
-    GNUNET_CONTAINER_DLL_remove (ctx->dns_head,
-                                 ctx->dns_tail,
-                                 ds);
-    GNUNET_free (ds);
-  }
-  for (unsigned int i=0;i<ctx->num_sockets;i++)
-    cleanup_rs (&ctx->sockets[i]);
-  GNUNET_free (ctx->sockets);
-  GNUNET_free (ctx);
-}
-
-
-/* end of dnsstub.c */
diff --git a/src/tun/regex.c b/src/tun/regex.c
deleted file mode 100644 (file)
index 7565a9e..0000000
+++ /dev/null
@@ -1,834 +0,0 @@
-/*
-     This file is part of GNUnet
-     Copyright (C) 2012, 2013, 2015 GNUnet e.V.
-
-     GNUnet is free software: you can redistribute it and/or modify it
-     under the terms of the GNU Affero General Public License as published
-     by the Free Software Foundation, either version 3 of the License,
-     or (at your option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     Affero General Public License for more details.
-    
-     You should have received a copy of the GNU Affero General Public License
-     along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-/**
- * @file src/tun/regex.c
- * @brief functions to convert IP networks to regexes
- * @author Maximilian Szengel
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_util_lib.h"
-#include "gnunet_tun_lib.h"
-
-/**
- * 'wildcard', matches all possible values (for HEX encoding).
- */
-#define DOT "(0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)"
-
-
-/**
- * Create a regex in @a rxstr from the given @a ip and @a netmask.
- *
- * @param ip IPv4 representation.
- * @param port destination port
- * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV4_REGEXLEN
- *              bytes long.
- */
-void
-GNUNET_TUN_ipv4toregexsearch (const struct in_addr *ip,
-                              uint16_t port,
-                              char *rxstr)
-{
-  GNUNET_snprintf (rxstr,
-                   GNUNET_TUN_IPV4_REGEXLEN,
-                   "4-%04X-%08X",
-                   (unsigned int) port,
-                   ntohl (ip->s_addr));
-}
-
-
-/**
- * Create a regex in @a rxstr from the given @a ipv6 and @a prefixlen.
- *
- * @param ipv6 IPv6 representation.
- * @param port destination port
- * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV6_REGEXLEN
- *              bytes long.
- */
-void
-GNUNET_TUN_ipv6toregexsearch (const struct in6_addr *ipv6,
-                              uint16_t port,
-                              char *rxstr)
-{
-  const uint32_t *addr;
-
-  addr = (const uint32_t *) ipv6;
-  GNUNET_snprintf (rxstr,
-                   GNUNET_TUN_IPV6_REGEXLEN,
-                   "6-%04X-%08X%08X%08X%08X",
-                   (unsigned int) port,
-                   ntohl (addr[0]),
-                   ntohl (addr[1]),
-                   ntohl (addr[2]),
-                   ntohl (addr[3]));
-}
-
-
-/**
- * Convert the given 4-bit (!) number to a regex.
- *
- * @param value the value, only the lowest 4 bits will be looked at
- * @param mask which bits in value are wildcards (any value)?
- */
-static char *
-nibble_to_regex (uint8_t value,
-                 uint8_t mask)
-{
-  char *ret;
-
-  value &= mask;
-  switch (mask)
-  {
-  case 0:
-    return GNUNET_strdup (DOT);
-  case 8:
-    GNUNET_asprintf (&ret,
-                     "(%X|%X|%X|%X|%X|%X|%X|%X)",
-                     value,
-                     value + 1,
-                     value + 2,
-                     value + 3,
-                     value + 4,
-                     value + 5,
-                     value + 6,
-                     value + 7);
-    return ret;
-  case 12:
-    GNUNET_asprintf (&ret,
-                     "(%X|%X|%X|%X)",
-                     value,
-                     value + 1,
-                     value + 2,
-                     value + 3);
-    return ret;
-  case 14:
-    GNUNET_asprintf (&ret,
-                     "(%X|%X)",
-                     value,
-                     value + 1);
-    return ret;
-  case 15:
-    GNUNET_asprintf (&ret,
-                     "%X",
-                     value);
-    return ret;
-  default:
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
-                _("Bad mask: %d\n"),
-                mask);
-    GNUNET_break (0);
-    return NULL;
-  }
-}
-
-
-/**
- * Convert the given 16-bit number to a regex.
- *
- * @param value the value
- * @param mask which bits in value are wildcards (any value)?
- */
-static char *
-num_to_regex (uint16_t value,
-              uint16_t mask)
-{
-  const uint8_t *v = (const uint8_t *) &value;
-  const uint8_t *m = (const uint8_t *) &mask;
-  char *a;
-  char *b;
-  char *c;
-  char *d;
-  char *ret;
-
-  a = nibble_to_regex (v[0] >> 4, m[0] >> 4);
-  b = nibble_to_regex (v[0] & 15, m[0] & 15);
-  c = nibble_to_regex (v[1] >> 4, m[1] >> 4);
-  d = nibble_to_regex (v[1] & 15, m[1] & 15);
-  ret = NULL;
-  if ( (NULL != a) &&
-       (NULL != b) &&
-       (NULL != c) &&
-       (NULL != d) )
-    GNUNET_asprintf (&ret,
-                     "%s%s%s%s",
-                     a, b, c, d);
-  GNUNET_free_non_null (a);
-  GNUNET_free_non_null (b);
-  GNUNET_free_non_null (c);
-  GNUNET_free_non_null (d);
-  return ret;
-}
-
-
-/**
- * Do we need to put parents around the given argument?
- *
- * @param arg part of a regular expression
- * @return #GNUNET_YES if we should parens,
- *         #GNUNET_NO if not
- */
-static int
-needs_parens (const char *arg)
-{
-  size_t off;
-  size_t len;
-  unsigned int op;
-
-  op = 0;
-  len = strlen (arg);
-  for (off=0;off<len;off++)
-  {
-    switch (arg[off])
-    {
-    case '(':
-      op++;
-      break;
-    case ')':
-      GNUNET_assert (op > 0);
-      op--;
-      break;
-    case '|':
-      if (0 == op)
-        return GNUNET_YES;
-      break;
-    default:
-      break;
-    }
-  }
-  return GNUNET_NO;
-}
-
-
-/**
- * Compute port policy for the given range of
- * port numbers.
- *
- * @param start starting offset
- * @param end end offset
- * @param step increment level (power of 16)
- * @param pp port policy to convert
- * @return corresponding regex
- */
-static char *
-compute_policy (unsigned int start,
-                unsigned int end,
-                unsigned int step,
-                const struct GNUNET_STRINGS_PortPolicy *pp)
-{
-  unsigned int i;
-  char before[36]; /* 16 * 2 + 3 dots + 0-terminator */
-  char middlel[33]; /* 16 * 2 + 0-terminator */
-  char middleh[33]; /* 16 * 2 + 0-terminator */
-  char after[36]; /* 16 * 2 + 3 dots + 0-terminator */
-  char beforep[36+2]; /* 16 * 2 + 3 dots + 0-terminator + ()*/
-  char middlehp[33+2]; /* 16 * 2 + 0-terminator + () */
-  char middlelp[33+2]; /* 16 * 2 + 0-terminator + () */
-  char afterp[36+2]; /* 16 * 2 + 3 dots + 0-terminator + () */
-  char dots[5 * strlen (DOT)];
-  char buf[3];
-  char *middle;
-  char *ret;
-  unsigned int xstep;
-  char *recl;
-  char *rech;
-  char *reclp;
-  char *rechp;
-  unsigned int start_port;
-  unsigned int end_port;
-
-  GNUNET_assert (GNUNET_YES == pp->negate_portrange);
-  start_port = pp->start_port;
-  if (1 == start_port)
-    start_port = 0;
-  end_port = pp->end_port;
-  GNUNET_assert ((end - start) / step <= 0xF);
-  before[0] = '\0';
-  middlel[0] = '\0';
-  middleh[0] = '\0';
-  after[0] = '\0';
-  for (i=start;i<=end;i+=step)
-  {
-    GNUNET_snprintf (buf,
-                     sizeof (buf),
-                     "%X|",
-                     (i - start) / step);
-    if (i / step < start_port / step)
-      strcat (before, buf);
-    else if (i / step > end_port / step)
-      strcat (after, buf);
-    else if (i / step == start_port / step)
-      strcat (middlel, buf);
-    else if (i / step == end_port / step)
-      strcat (middleh, buf);
-  }
-  if (strlen (before) > 0)
-    before[strlen (before)-1] = '\0';
-  if (strlen (middlel) > 0)
-    middlel[strlen (middlel)-1] = '\0';
-  if (strlen (middleh) > 0)
-    middleh[strlen (middleh)-1] = '\0';
-  if (strlen (after) > 0)
-    after[strlen (after)-1] = '\0';
-  if (needs_parens (before))
-    GNUNET_snprintf (beforep,
-                     sizeof (beforep),
-                     "(%s)",
-                     before);
-  else
-    strcpy (beforep, before);
-  if (needs_parens (middlel))
-    GNUNET_snprintf (middlelp,
-                     sizeof (middlelp),
-                     "(%s)",
-                     middlel);
-  else
-    strcpy (middlelp, middlel);
-  if (needs_parens (middleh))
-    GNUNET_snprintf (middlehp,
-                     sizeof (middlehp),
-                     "(%s)",
-                     middleh);
-  else
-    strcpy (middlehp, middleh);
-  if (needs_parens (after))
-    GNUNET_snprintf (afterp,
-                     sizeof (afterp),
-                     "(%s)",
-                     after);
-  else
-    strcpy (afterp, after);
-  dots[0] = '\0';
-  for (xstep=step/16;xstep>0;xstep/=16)
-    strcat (dots, DOT);
-  if (step >= 16)
-  {
-    if (strlen (middlel) > 0)
-      recl = compute_policy ((start_port / step) * step,
-                             (start_port / step) * step + step - 1,
-                             step / 16,
-                             pp);
-    else
-      recl = GNUNET_strdup ("");
-    if (strlen (middleh) > 0)
-      rech = compute_policy ((end_port / step) * step,
-                             (end_port / step) * step + step - 1,
-                             step / 16,
-                             pp);
-    else
-      rech = GNUNET_strdup ("");
-  }
-  else
-  {
-    recl = GNUNET_strdup ("");
-    rech = GNUNET_strdup ("");
-    middlel[0] = '\0';
-    middlelp[0] = '\0';
-    middleh[0] = '\0';
-    middlehp[0] = '\0';
-  }
-  if (needs_parens (recl))
-    GNUNET_asprintf (&reclp,
-                     "(%s)",
-                     recl);
-  else
-    reclp = GNUNET_strdup (recl);
-  if (needs_parens (rech))
-    GNUNET_asprintf (&rechp,
-                     "(%s)",
-                     rech);
-  else
-    rechp = GNUNET_strdup (rech);
-
-  if ( (strlen (middleh) > 0) &&
-       (strlen (rech) > 0) &&
-       (strlen (middlel) > 0) &&
-       (strlen (recl) > 0) )
-  {
-    GNUNET_asprintf (&middle,
-                     "%s%s|%s%s",
-                     middlel,
-                     reclp,
-                     middleh,
-                     rechp);
-  }
-  else if ( (strlen (middleh) > 0) &&
-            (strlen (rech) > 0) )
-  {
-    GNUNET_asprintf (&middle,
-                     "%s%s",
-                     middleh,
-                     rechp);
-  }
-  else if ( (strlen (middlel) > 0) &&
-            (strlen (recl) > 0) )
-  {
-    GNUNET_asprintf (&middle,
-                     "%s%s",
-                     middlel,
-                     reclp);
-  }
-  else
-  {
-    middle = GNUNET_strdup ("");
-  }
-  if ( (strlen(before) > 0) &&
-       (strlen(after) > 0) )
-  {
-    if (strlen (dots) > 0)
-    {
-      if (strlen (middle) > 0)
-        GNUNET_asprintf (&ret,
-                         "(%s%s|%s|%s%s)",
-                         beforep, dots,
-                         middle,
-                         afterp, dots);
-      else
-        GNUNET_asprintf (&ret,
-                         "(%s|%s)%s",
-                         beforep,
-                         afterp,
-                         dots);
-    }
-    else
-    {
-      if (strlen (middle) > 0)
-        GNUNET_asprintf (&ret,
-                         "(%s|%s|%s)",
-                         before,
-                         middle,
-                         after);
-      else if (1 == step)
-        GNUNET_asprintf (&ret,
-                         "%s|%s",
-                         before,
-                         after);
-      else
-        GNUNET_asprintf (&ret,
-                         "(%s|%s)",
-                         before,
-                         after);
-    }
-  }
-  else if (strlen (before) > 0)
-  {
-    if (strlen (dots) > 0)
-    {
-      if (strlen (middle) > 0)
-        GNUNET_asprintf (&ret,
-                         "(%s%s|%s)",
-                         beforep, dots,
-                         middle);
-      else
-        GNUNET_asprintf (&ret,
-                         "%s%s",
-                         beforep, dots);
-    }
-    else
-    {
-      if (strlen (middle) > 0)
-        GNUNET_asprintf (&ret,
-                         "(%s|%s)",
-                         before,
-                         middle);
-      else
-        GNUNET_asprintf (&ret,
-                         "%s",
-                         before);
-    }
-  }
-  else if (strlen (after) > 0)
-  {
-    if (strlen (dots) > 0)
-    {
-      if (strlen (middle) > 0)
-        GNUNET_asprintf (&ret,
-                         "(%s|%s%s)",
-                         middle,
-                         afterp, dots);
-      else
-        GNUNET_asprintf (&ret,
-                         "%s%s",
-                         afterp, dots);
-    }
-    else
-    {
-      if (strlen (middle) > 0)
-        GNUNET_asprintf (&ret,
-                         "%s|%s",
-                         middle,
-                         after);
-      else
-        GNUNET_asprintf (&ret,
-                         "%s",
-                         after);
-    }
-  }
-  else if (strlen (middle) > 0)
-  {
-    GNUNET_asprintf (&ret,
-                     "%s",
-                     middle);
-  }
-  else
-  {
-    ret = GNUNET_strdup ("");
-  }
-  GNUNET_free (middle);
-  GNUNET_free (reclp);
-  GNUNET_free (rechp);
-  GNUNET_free (recl);
-  GNUNET_free (rech);
-  return ret;
-}
-
-
-/**
- * Convert a port policy to a regular expression.  Note: this is a
- * very simplistic implementation, we might want to consider doing
- * something more sophisiticated (resulting in smaller regular
- * expressions) at a later time.
- *
- * @param pp port policy to convert
- * @return NULL on error
- */
-static char *
-port_to_regex (const struct GNUNET_STRINGS_PortPolicy *pp)
-{
-  char *reg;
-  char *ret;
-  char *pos;
-  unsigned int i;
-  unsigned int cnt;
-
-  if ( (0 == pp->start_port) ||
-       ( (1 == pp->start_port) &&
-         (0xFFFF == pp->end_port) &&
-         (GNUNET_NO == pp->negate_portrange)) )
-    return GNUNET_strdup (DOT DOT DOT DOT);
-  if ( (pp->start_port == pp->end_port) &&
-       (GNUNET_NO == pp->negate_portrange))
-  {
-    GNUNET_asprintf (&ret,
-                     "%04X",
-                     pp->start_port);
-    return ret;
-  }
-  if (pp->end_port < pp->start_port)
-    return NULL;
-
-  if (GNUNET_YES == pp->negate_portrange)
-  {
-    ret = compute_policy (0, 0xFFFF, 0x1000, pp);
-  }
-  else
-  {
-    cnt = pp->end_port - pp->start_port + 1;
-    reg = GNUNET_malloc (cnt * 5 + 1);
-    pos = reg;
-    for (i=1;i<=0xFFFF;i++)
-    {
-      if ( (i >= pp->start_port) && (i <= pp->end_port) )
-      {
-        if (pos == reg)
-        {
-          GNUNET_snprintf (pos,
-                           5,
-                           "%04X",
-                           i);
-        }
-        else
-        {
-          GNUNET_snprintf (pos,
-                           6,
-                           "|%04X",
-                           i);
-        }
-        pos += strlen (pos);
-      }
-    }
-    GNUNET_asprintf (&ret,
-                     "(%s)",
-                     reg);
-    GNUNET_free (reg);
-  }
-  return ret;
-}
-
-
-/**
- * Convert an address (IPv4 or IPv6) to a regex.
- *
- * @param addr address
- * @param mask network mask
- * @param len number of bytes in @a addr and @a mask
- * @return NULL on error, otherwise regex for the address
- */
-static char *
-address_to_regex (const void *addr,
-                  const void *mask,
-                  size_t len)
-{
-  const uint16_t *a = addr;
-  const uint16_t *m = mask;
-  char *ret;
-  char *tmp;
-  char *reg;
-  unsigned int i;
-
-  ret = NULL;
-  GNUNET_assert (1 != (len % 2));
-  for (i=0;i<len / 2;i++)
-  {
-    reg = num_to_regex (a[i], m[i]);
-    if (NULL == reg)
-    {
-      GNUNET_free_non_null (ret);
-      return NULL;
-    }
-    if (NULL == ret)
-    {
-      ret = reg;
-    }
-    else
-    {
-      GNUNET_asprintf (&tmp,
-                       "%s%s",
-                       ret, reg);
-      GNUNET_free (ret);
-      GNUNET_free (reg);
-      ret = tmp;
-    }
-  }
-  return ret;
-}
-
-
-/**
- * Convert a single line of an IPv4 policy to a regular expression.
- *
- * @param v4 line to convert
- * @return NULL on error
- */
-static char *
-ipv4_to_regex (const struct GNUNET_STRINGS_IPv4NetworkPolicy *v4)
-{
-  char *reg;
-  char *pp;
-  char *ret;
-
-  reg = address_to_regex (&v4->network,
-                          &v4->netmask,
-                          sizeof (struct in_addr));
-  if (NULL == reg)
-    return NULL;
-  pp = port_to_regex (&v4->pp);
-  if (NULL == pp)
-  {
-    GNUNET_free (reg);
-    return NULL;
-  }
-  GNUNET_asprintf (&ret,
-                   "4-%s-%s",
-                   pp, reg);
-  GNUNET_free (pp);
-  GNUNET_free (reg);
-  return ret;
-}
-
-
-/**
- * Convert a single line of an IPv4 policy to a regular expression.
- *
- * @param v6 line to convert
- * @return NULL on error
- */
-static char *
-ipv6_to_regex (const struct GNUNET_STRINGS_IPv6NetworkPolicy *v6)
-{
-  char *reg;
-  char *pp;
-  char *ret;
-
-  reg = address_to_regex (&v6->network,
-                          &v6->netmask,
-                          sizeof (struct in6_addr));
-  if (NULL == reg)
-    return NULL;
-  pp = port_to_regex (&v6->pp);
-  if (NULL == pp)
-  {
-    GNUNET_free (reg);
-    return NULL;
-  }
-  GNUNET_asprintf (&ret,
-                   "6-%s-%s",
-                   pp, reg);
-  GNUNET_free (pp);
-  GNUNET_free (reg);
-  return ret;
-}
-
-
-/**
- * Convert an exit policy to a regular expression.  The exit policy
- * specifies a set of subnets this peer is willing to serve as an
- * exit for; the resulting regular expression will match the
- * IPv4 address strings as returned by #GNUNET_TUN_ipv4toregexsearch().
- *
- * @param policy exit policy specification
- * @return regular expression, NULL on error
- */
-char *
-GNUNET_TUN_ipv4policy2regex (const char *policy)
-{
-  struct GNUNET_STRINGS_IPv4NetworkPolicy *np;
-  char *reg;
-  char *tmp;
-  char *line;
-  unsigned int i;
-
-  np = GNUNET_STRINGS_parse_ipv4_policy (policy);
-  if (NULL == np)
-    return NULL;
-  reg = NULL;
-  for (i=0; (0 == i) || (0 != np[i].network.s_addr); i++)
-  {
-    line = ipv4_to_regex (&np[i]);
-    if (NULL == line)
-    {
-      GNUNET_free_non_null (reg);
-      GNUNET_free (np);
-      return NULL;
-    }
-    if (NULL == reg)
-    {
-      reg = line;
-    }
-    else
-    {
-      GNUNET_asprintf (&tmp,
-                       "%s|(%s)",
-                       reg, line);
-      GNUNET_free (reg);
-      GNUNET_free (line);
-      reg = tmp;
-    }
-    if (0 == np[i].network.s_addr)
-      break;
-  }
-  GNUNET_free (np);
-  return reg;
-}
-
-
-/**
- * Convert an exit policy to a regular expression.  The exit policy
- * specifies a set of subnets this peer is willing to serve as an
- * exit for; the resulting regular expression will match the
- * IPv6 address strings as returned by #GNUNET_TUN_ipv6toregexsearch().
- *
- * @param policy exit policy specification
- * @return regular expression, NULL on error
- */
-char *
-GNUNET_TUN_ipv6policy2regex (const char *policy)
-{
-  struct in6_addr zero;
-  struct GNUNET_STRINGS_IPv6NetworkPolicy *np;
-  char *reg;
-  char *tmp;
-  char *line;
-  unsigned int i;
-
-  np = GNUNET_STRINGS_parse_ipv6_policy (policy);
-  if (NULL == np)
-    return NULL;
-  reg = NULL;
-  memset (&zero, 0, sizeof (struct in6_addr));
-  for (i=0; (0 == i) || (0 != memcmp (&zero, &np[i].network, sizeof (struct in6_addr))); i++)
-  {
-    line = ipv6_to_regex (&np[i]);
-    if (NULL == line)
-    {
-      GNUNET_free_non_null (reg);
-      GNUNET_free (np);
-      return NULL;
-    }
-    if (NULL == reg)
-    {
-      reg = line;
-    }
-    else
-    {
-      GNUNET_asprintf (&tmp,
-                       "%s|(%s)",
-                       reg, line);
-      GNUNET_free (reg);
-      GNUNET_free (line);
-      reg = tmp;
-    }
-    if (0 == memcmp (&zero, &np[i].network, sizeof (struct in6_addr)))
-      break;
-  }
-  GNUNET_free (np);
-  return reg;
-}
-
-
-/**
- * Hash the service name of a hosted service to the
- * hash code that is used to identify the service on
- * the network.
- *
- * @param service_name a string
- * @param hc corresponding hash
- */
-void
-GNUNET_TUN_service_name_to_hash (const char *service_name,
-                                 struct GNUNET_HashCode *hc)
-{
-  GNUNET_CRYPTO_hash (service_name,
-                      strlen (service_name),
-                      hc);
-}
-
-
-/**
- * Compute the CADET port given a service descriptor
- * (returned from #GNUNET_TUN_service_name_to_hash) and
- * a TCP/UDP port @a ip_port.
- *
- * @param desc service shared secret
- * @param ip_port TCP/UDP port, use 0 for ICMP
- * @param[out] cadet_port CADET port to use
- */
-void
-GNUNET_TUN_compute_service_cadet_port (const struct GNUNET_HashCode *desc,
-                                       uint16_t ip_port,
-                                       struct GNUNET_HashCode *cadet_port)
-{
-  uint16_t be_port = htons (ip_port);
-
-  *cadet_port = *desc;
-  GNUNET_memcpy (cadet_port,
-                 &be_port,
-                 sizeof (uint16_t));
-}
-
-
-/* end of regex.c */
diff --git a/src/tun/test_regex.c b/src/tun/test_regex.c
deleted file mode 100644 (file)
index 2e7d528..0000000
+++ /dev/null
@@ -1,179 +0,0 @@
-/*
-     This file is part of GNUnet
-     Copyright (C) 2012, 2013 GNUnet e.V.
-
-     GNUnet is free software: you can redistribute it and/or modify it
-     under the terms of the GNU Affero General Public License as published
-     by the Free Software Foundation, either version 3 of the License,
-     or (at your option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     Affero General Public License for more details.
-    
-     You should have received a copy of the GNU Affero General Public License
-     along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-/**
- * @file tun/test_regex.c
- * @brief simple test for regex.c iptoregex functions
- * @author Maximilian Szengel
- */
-#include "platform.h"
-#include "gnunet_tun_lib.h"
-
-/**
- * 'wildcard', matches all possible values (for HEX encoding).
- */
-#define DOT "(0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)"
-
-
-static int
-test_iptoregex (const char *ipv4,
-                uint16_t port,
-                const char *expectedv4,
-                const char *ipv6,
-                uint16_t port6,
-                const char *expectedv6)
-{
-  int error = 0;
-
-  struct in_addr a;
-  struct in6_addr b;
-  char rxv4[GNUNET_TUN_IPV4_REGEXLEN];
-  char rxv6[GNUNET_TUN_IPV6_REGEXLEN];
-
-  GNUNET_assert (1 == inet_pton (AF_INET, ipv4, &a));
-  GNUNET_TUN_ipv4toregexsearch (&a, port, rxv4);
-
-  if (0 != strcmp (rxv4, expectedv4))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Expected: %s but got: %s\n",
-                expectedv4,
-                rxv4);
-    error++;
-  }
-
-  GNUNET_assert (1 == inet_pton (AF_INET6, ipv6, &b));
-  GNUNET_TUN_ipv6toregexsearch (&b, port6, rxv6);
-  if (0 != strcmp (rxv6, expectedv6))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Expected: %s but got: %s\n",
-                expectedv6, rxv6);
-    error++;
-  }
-  return error;
-}
-
-
-static int
-test_policy4toregex (const char *policy,
-                     const char *regex)
-{
-  char *r;
-  int ret;
-
-  ret = 0;
-  r = GNUNET_TUN_ipv4policy2regex (policy);
-  if (NULL == r)
-  {
-    GNUNET_break (0);
-    return 1;
-  }
-  if (0 != strcmp (regex, r))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Expected: `%s' but got: `%s'\n",
-                regex, r);
-    ret = 2;
-  }
-  GNUNET_free (r);
-  return ret;
-}
-
-
-static int
-test_policy6toregex (const char *policy,
-                     const char *regex)
-{
-  char *r;
-  int ret;
-
-  ret = 0;
-  r = GNUNET_TUN_ipv6policy2regex (policy);
-  if (NULL == r)
-  {
-    GNUNET_break (0);
-    return 1;
-  }
-  if (0 != strcmp (regex, r))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Expected: `%s' but got: `%s'\n",
-                regex, r);
-    ret = 2;
-  }
-  GNUNET_free (r);
-  return ret;
-}
-
-
-int
-main (int argc, char *argv[])
-{
-  int error;
-  char *r;
-
-  GNUNET_log_setup ("test-regex", "WARNING", NULL);
-  error = 0;
-
-  /* this is just a performance test ... */
-  r = GNUNET_TUN_ipv4policy2regex ("1.2.3.4/16:!25;");
-  GNUNET_break (NULL != r);
-  GNUNET_free (r);
-
-  error +=
-    test_iptoregex ("192.1.2.3", 2086,
-                    "4-0826-C0010203",
-                    "FFFF::1", 8080,
-                    "6-1F90-FFFF0000000000000000000000000001");
-  error +=
-    test_iptoregex ("187.238.255.0", 80,
-                    "4-0050-BBEEFF00",
-                    "E1E1:73F9:51BE::0", 49,
-                    "6-0031-E1E173F951BE00000000000000000000");
-  error +=
-    test_policy4toregex ("192.1.2.0/24:80;",
-                         "4-0050-C00102" DOT DOT);
-  error +=
-    test_policy4toregex ("192.1.0.0/16;",
-                         "4-" DOT DOT DOT DOT "-C001" DOT DOT DOT DOT);
-  error +=
-    test_policy4toregex ("192.1.0.0/16:80-81;",
-                         "4-(0050|0051)-C001" DOT DOT DOT DOT);
-  error +=
-    test_policy4toregex ("192.1.0.0/8:!3-65535;",
-                         "4-000(0|1|2)-C0" DOT DOT DOT DOT DOT DOT);
-  error +=
-    test_policy4toregex ("192.1.0.0/8:!25-56;",
-                         "4-(0(0(0"DOT"|1(0|1|2|3|4|5|6|7|8)|3(9|A|B|C|D|E|F)|(4|5|6|7|8|9|A|B|C|D|E|F)"DOT")|(1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)"DOT DOT")|(1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)"DOT DOT DOT")-C0"DOT DOT DOT DOT DOT DOT);
-  error +=
-    test_policy6toregex ("E1E1::1;",
-                         "6-"DOT DOT DOT DOT"-E1E10000000000000000000000000001");
-  error +=
-    test_policy6toregex ("E1E1:ABCD::1/120;",
-                         "6-"DOT DOT DOT DOT"-E1E1ABCD0000000000000000000000" DOT DOT);
-  error +=
-    test_policy6toregex ("E1E1:ABCD::ABCD/126;",
-                         "6-"DOT DOT DOT DOT"-E1E1ABCD00000000000000000000ABC(C|D|E|F)");
-  error +=
-    test_policy6toregex ("E1E1:ABCD::ABCD/127;",
-                         "6-"DOT DOT DOT DOT"-E1E1ABCD00000000000000000000ABC(C|D)");
-  error +=
-    test_policy6toregex ("E1E1:ABCD::ABCD/128:80;",
-                         "6-0050-E1E1ABCD00000000000000000000ABCD");
-  return error;
-}
diff --git a/src/tun/test_tun.c b/src/tun/test_tun.c
deleted file mode 100644 (file)
index edbd4c0..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
-     This file is part of GNUnet.
-     Copyright (C) 2010, 2011, 2012 Christian Grothoff
-
-     GNUnet is free software: you can redistribute it and/or modify it
-     under the terms of the GNU Affero General Public License as published
-     by the Free Software Foundation, either version 3 of the License,
-     or (at your option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     Affero General Public License for more details.
-    
-     You should have received a copy of the GNU Affero General Public License
-     along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file tun/test_tun.c
- * @brief test for tun.c
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_tun_lib.h"
-
-static int ret;
-
-static void
-test_udp (size_t pll,
-         int pl_fill,
-         uint16_t crc)
-{
-  struct GNUNET_TUN_IPv4Header ip;
-  struct GNUNET_TUN_UdpHeader udp;
-  char payload[pll];
-  struct in_addr src;
-  struct in_addr dst;
-
-  GNUNET_assert (1 == inet_pton (AF_INET, "1.2.3.4", &src));
-  GNUNET_assert (1 == inet_pton (AF_INET, "122.2.3.5", &dst));
-  memset (payload, pl_fill, sizeof (payload));
-  GNUNET_TUN_initialize_ipv4_header (&ip,
-                                    IPPROTO_UDP,
-                                    pll + sizeof (udp),
-                                    &src,
-                                    &dst);
-  udp.source_port = htons (4242);
-  udp.destination_port = htons (4242);
-  udp.len = htons (pll);
-  GNUNET_TUN_calculate_udp4_checksum (&ip,
-                                     &udp,
-                                     payload,
-                                     pll);
-  if (crc != ntohs (udp.crc))
-  {
-    fprintf (stderr, "Got CRC: %u, wanted: %u\n",
-            ntohs (udp.crc),
-            crc);
-    ret = 1;
-  }
-}
-
-int main (int argc,
-         char **argv)
-{
-  test_udp (4, 3, 22439);
-  test_udp (4, 1, 23467);
-  test_udp (7, 17, 6516);
-  test_udp (12451, 251, 42771);
-  return ret;
-}
diff --git a/src/tun/tun.c b/src/tun/tun.c
deleted file mode 100644 (file)
index f85f722..0000000
+++ /dev/null
@@ -1,309 +0,0 @@
-/*
-     This file is part of GNUnet.
-     Copyright (C) 2010, 2011, 2012 Christian Grothoff
-
-     GNUnet is free software: you can redistribute it and/or modify it
-     under the terms of the GNU Affero General Public License as published
-     by the Free Software Foundation, either version 3 of the License,
-     or (at your option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     Affero General Public License for more details.
-    
-     You should have received a copy of the GNU Affero General Public License
-     along with this program.  If not, see <http://www.gnu.org/licenses/>.
-*/
-
-/**
- * @file tun/tun.c
- * @brief standard IP calculations for TUN interaction
- * @author Philipp Toelke
- * @author Christian Grothoff
- */
-#include "platform.h"
-#include "gnunet_tun_lib.h"
-
-/**
- * IP TTL we use for packets that we assemble (8 bit unsigned integer)
- */
-#define FRESH_TTL 64
-
-
-/**
- * Initialize an IPv4 header.
- *
- * @param ip header to initialize
- * @param protocol protocol to use (i.e. IPPROTO_UDP)
- * @param payload_length number of bytes of payload that follow (excluding IPv4 header)
- * @param src source IP address to use
- * @param dst destination IP address to use
- */
-void
-GNUNET_TUN_initialize_ipv4_header (struct GNUNET_TUN_IPv4Header *ip,
-                                  uint8_t protocol,
-                                  uint16_t payload_length,
-                                  const struct in_addr *src,
-                                  const struct in_addr *dst)
-{
-  GNUNET_assert (20 == sizeof (struct GNUNET_TUN_IPv4Header));
-  GNUNET_assert (payload_length <= UINT16_MAX - sizeof (struct GNUNET_TUN_IPv4Header));
-  memset (ip, 0, sizeof (struct GNUNET_TUN_IPv4Header));
-  ip->header_length =  sizeof (struct GNUNET_TUN_IPv4Header) / 4;
-  ip->version = 4;
-  ip->total_length = htons (sizeof (struct GNUNET_TUN_IPv4Header) + payload_length);
-  ip->identification = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
-                                                           65536);
-  ip->ttl = FRESH_TTL;
-  ip->protocol = protocol;
-  ip->source_address = *src;
-  ip->destination_address = *dst;
-  ip->checksum = GNUNET_CRYPTO_crc16_n (ip, sizeof (struct GNUNET_TUN_IPv4Header));
-}
-
-
-/**
- * Initialize an IPv6 header.
- *
- * @param ip header to initialize
- * @param protocol protocol to use (i.e. IPPROTO_UDP), technically "next_header" for IPv6
- * @param payload_length number of bytes of payload that follow (excluding IPv6 header)
- * @param src source IP address to use
- * @param dst destination IP address to use
- */
-void
-GNUNET_TUN_initialize_ipv6_header (struct GNUNET_TUN_IPv6Header *ip,
-                                  uint8_t protocol,
-                                  uint16_t payload_length,
-                                  const struct in6_addr *src,
-                                  const struct in6_addr *dst)
-{
-  GNUNET_assert (40 == sizeof (struct GNUNET_TUN_IPv6Header));
-  GNUNET_assert (payload_length <= UINT16_MAX - sizeof (struct GNUNET_TUN_IPv6Header));
-  memset (ip, 0, sizeof (struct GNUNET_TUN_IPv6Header));
-  ip->version = 6;
-  ip->next_header = protocol;
-  ip->payload_length = htons ((uint16_t) payload_length);
-  ip->hop_limit = FRESH_TTL;
-  ip->destination_address = *dst;
-  ip->source_address = *src;
-}
-
-
-/**
- * Calculate IPv4 TCP checksum.
- *
- * @param ip ipv4 header fully initialized
- * @param tcp TCP header (initialized except for CRC)
- * @param payload the TCP payload
- * @param payload_length number of bytes of TCP payload
- */
-void
-GNUNET_TUN_calculate_tcp4_checksum (const struct GNUNET_TUN_IPv4Header *ip,
-                                   struct GNUNET_TUN_TcpHeader *tcp,
-                                   const void *payload,
-                                   uint16_t payload_length)
-{
-  uint32_t sum;
-  uint16_t tmp;
-
-  GNUNET_assert (20 == sizeof (struct GNUNET_TUN_TcpHeader));
-  GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_IPv4Header) + sizeof (struct GNUNET_TUN_TcpHeader) ==
-                ntohs (ip->total_length));
-  GNUNET_assert (IPPROTO_TCP == ip->protocol);
-
-  tcp->crc = 0;
-  sum = GNUNET_CRYPTO_crc16_step (0,
-                                 &ip->source_address,
-                                 sizeof (struct in_addr) * 2);
-  tmp = htons (IPPROTO_TCP);
-  sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint16_t));
-  tmp = htons (payload_length + sizeof (struct GNUNET_TUN_TcpHeader));
-  sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint16_t));
-  sum = GNUNET_CRYPTO_crc16_step (sum, tcp, sizeof (struct GNUNET_TUN_TcpHeader));
-  sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
-  tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
-}
-
-
-/**
- * Calculate IPv6 TCP checksum.
- *
- * @param ip ipv6 header fully initialized
- * @param tcp header (initialized except for CRC)
- * @param payload the TCP payload
- * @param payload_length number of bytes of TCP payload
- */
-void
-GNUNET_TUN_calculate_tcp6_checksum (const struct GNUNET_TUN_IPv6Header *ip,
-                                   struct GNUNET_TUN_TcpHeader *tcp,
-                                   const void *payload,
-                                   uint16_t payload_length)
-{
-  uint32_t sum;
-  uint32_t tmp;
-
-  GNUNET_assert (20 == sizeof (struct GNUNET_TUN_TcpHeader));
-  GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_TcpHeader) ==
-                ntohs (ip->payload_length));
-  GNUNET_assert (IPPROTO_TCP == ip->next_header);
-  tcp->crc = 0;
-  sum = GNUNET_CRYPTO_crc16_step (0, &ip->source_address, 2 * sizeof (struct in6_addr));
-  tmp = htonl (sizeof (struct GNUNET_TUN_TcpHeader) + payload_length);
-  sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
-  tmp = htonl (IPPROTO_TCP);
-  sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
-  sum = GNUNET_CRYPTO_crc16_step (sum, tcp,
-                                 sizeof (struct GNUNET_TUN_TcpHeader));
-  sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
-  tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
-}
-
-
-/**
- * Calculate IPv4 UDP checksum.
- *
- * @param ip ipv4 header fully initialized
- * @param udp UDP header (initialized except for CRC)
- * @param payload the UDP payload
- * @param payload_length number of bytes of UDP payload
- */
-void
-GNUNET_TUN_calculate_udp4_checksum (const struct GNUNET_TUN_IPv4Header *ip,
-                                   struct GNUNET_TUN_UdpHeader *udp,
-                                   const void *payload,
-                                   uint16_t payload_length)
-{
-  uint32_t sum;
-  uint16_t tmp;
-
-  GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
-  GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_IPv4Header) + sizeof (struct GNUNET_TUN_UdpHeader) ==
-                ntohs (ip->total_length));
-  GNUNET_assert (IPPROTO_UDP == ip->protocol);
-
-  udp->crc = 0; /* technically optional, but we calculate it anyway, just to be sure */
-  sum = GNUNET_CRYPTO_crc16_step (0,
-                                 &ip->source_address,
-                                 sizeof (struct in_addr) * 2);
-  tmp = htons (IPPROTO_UDP);
-  sum = GNUNET_CRYPTO_crc16_step (sum,
-                                 &tmp,
-                                 sizeof (uint16_t));
-  tmp = htons (sizeof (struct GNUNET_TUN_UdpHeader) + payload_length);
-  sum = GNUNET_CRYPTO_crc16_step (sum,
-                                 &tmp,
-                                 sizeof (uint16_t));
-  sum = GNUNET_CRYPTO_crc16_step (sum,
-                                 udp,
-                                 sizeof (struct GNUNET_TUN_UdpHeader));
-  sum = GNUNET_CRYPTO_crc16_step (sum,
-                                 payload,
-                                 payload_length);
-  udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
-}
-
-
-/**
- * Calculate IPv6 UDP checksum.
- *
- * @param ip ipv6 header fully initialized
- * @param udp UDP header (initialized except for CRC)
- * @param payload the UDP payload
- * @param payload_length number of bytes of UDP payload
- */
-void
-GNUNET_TUN_calculate_udp6_checksum (const struct GNUNET_TUN_IPv6Header *ip,
-                                   struct GNUNET_TUN_UdpHeader *udp,
-                                   const void *payload,
-                                   uint16_t payload_length)
-{
-  uint32_t sum;
-  uint32_t tmp;
-
-  GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_UdpHeader) ==
-                ntohs (ip->payload_length));
-  GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_UdpHeader) ==
-                ntohs (udp->len));
-  GNUNET_assert (IPPROTO_UDP == ip->next_header);
-
-  udp->crc = 0;
-  sum = GNUNET_CRYPTO_crc16_step (0,
-                                 &ip->source_address,
-                                 sizeof (struct in6_addr) * 2);
-  tmp = htons (sizeof (struct GNUNET_TUN_UdpHeader) + payload_length); /* aka udp->len */
-  sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
-  tmp = htons (ip->next_header);
-  sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
-  sum = GNUNET_CRYPTO_crc16_step (sum, udp, sizeof (struct GNUNET_TUN_UdpHeader));
-  sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
-  udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
-}
-
-
-/**
- * Calculate ICMP checksum.
- *
- * @param icmp IMCP header (initialized except for CRC)
- * @param payload the ICMP payload
- * @param payload_length number of bytes of ICMP payload
- */
-void
-GNUNET_TUN_calculate_icmp_checksum (struct GNUNET_TUN_IcmpHeader *icmp,
-                                   const void *payload,
-                                   uint16_t payload_length)
-{
-  uint32_t sum;
-
-  GNUNET_assert (8 == sizeof (struct GNUNET_TUN_IcmpHeader));
-  icmp->crc = 0;
-  sum = GNUNET_CRYPTO_crc16_step (0,
-                                 icmp,
-                                 sizeof (struct GNUNET_TUN_IcmpHeader));
-  sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
-  icmp->crc = GNUNET_CRYPTO_crc16_finish (sum);
-}
-
-
-/**
- * Check if two sockaddrs are equal.
- *
- * @param sa one address
- * @param sb another address
- * @param include_port also check ports
- * @return #GNUNET_YES if they are equal
- */
-int
-GNUNET_TUN_sockaddr_cmp (const struct sockaddr *sa,
-                         const struct sockaddr *sb,
-                         int include_port)
-{
-  if (sa->sa_family != sb->sa_family)
-    return GNUNET_NO;
-
-  switch (sa->sa_family)
-  {
-  case AF_INET:
-    {
-      const struct sockaddr_in *sa4 = (const struct sockaddr_in *) sa;
-      const struct sockaddr_in *sb4 = (const struct sockaddr_in *) sb;
-      return (sa4->sin_addr.s_addr == sb4->sin_addr.s_addr);
-    }
-  case AF_INET6:
-    {
-      const struct sockaddr_in6 *sa6 = (const struct sockaddr_in6 *) sa;
-      const struct sockaddr_in6 *sb6 = (const struct sockaddr_in6 *) sb;
-
-      return (0 == memcmp(&sa6->sin6_addr,
-                          &sb6->sin6_addr,
-                          sizeof (struct in6_addr)));
-    }
-  default:
-    GNUNET_break (0);
-    return GNUNET_SYSERR;
-  }
-}
-
-
-/* end of tun.c */
index 4296199db419ece8e543d5a098055d96633cb1c4..ec7bcb016facbd2b4c44b85a3685db99be33f72c 100644 (file)
@@ -89,6 +89,8 @@ libgnunetutil_la_SOURCES = \
   crypto_rsa.c \
   disk.c \
   disk.h \
+  dnsparser.c \
+  dnsstub.c \
   getopt.c \
   getopt_helpers.c \
   helper.c \
@@ -104,12 +106,14 @@ libgnunetutil_la_SOURCES = \
   peer.c \
   plugin.c \
   program.c \
+  regex.c \
   resolver_api.c resolver.h \
   scheduler.c \
   service.c \
   signal.c \
   strings.c \
   time.c \
+  tun.c \
   speedup.c speedup.h
 
 libgnunetutil_la_LIBADD = \
@@ -117,7 +121,7 @@ libgnunetutil_la_LIBADD = \
   $(LIBGCRYPT_LIBS) \
   $(LTLIBICONV) \
   $(LTLIBINTL) \
-  -lltdl $(Z_LIBS) -lunistring $(XLIB)
+  -lltdl -lidn $(Z_LIBS) -lunistring $(XLIB)
 
 libgnunetutil_la_LDFLAGS = \
   $(GN_LIB_LDFLAGS) \
@@ -291,19 +295,22 @@ check_PROGRAMS = \
  test_crypto_rsa \
  test_disk \
  test_getopt \
+ test_hexcoder \
  test_mq \
  test_os_network \
  test_peer \
  test_plugin \
  test_program \
+ test_regex \
  test_resolver_api.nc \
  test_scheduler \
  test_scheduler_delay \
  test_service \
  test_strings \
  test_strings_to_data \
- test_time \
  test_speedup \
+ test_time \
+ test_tun \
  $(BENCHMARKS) \
  test_os_start_process \
  test_common_logging_runtime_loglevels
@@ -319,6 +326,20 @@ test_bio_SOURCES = \
 test_bio_LDADD = \
  libgnunetutil.la
 
+test_hexcoder_SOURCES = \
+ test_hexcoder.c
+test_hexcoder_LDADD = \
+ libgnunetutil.la
+
+test_tun_SOURCES = \
+ test_tun.c
+test_tun_LDADD = \
+ libgnunetutil.la 
+
+test_regex_SOURCES = \
+ test_regex.c
+test_regex_LDADD = \
+ libgnunetutil.la 
 
 test_os_start_process_SOURCES = \
  test_os_start_process.c
diff --git a/src/util/dnsparser.c b/src/util/dnsparser.c
new file mode 100644 (file)
index 0000000..32ad7c0
--- /dev/null
@@ -0,0 +1,1334 @@
+/*
+      This file is part of GNUnet
+      Copyright (C) 2010-2014 GNUnet e.V.
+
+      GNUnet is free software: you can redistribute it and/or modify it
+      under the terms of the GNU Affero General Public License as published
+      by the Free Software Foundation, either version 3 of the License,
+      or (at your option) any later version.
+
+      GNUnet is distributed in the hope that it will be useful, but
+      WITHOUT ANY WARRANTY; without even the implied warranty of
+      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+      Affero General Public License for more details.
+     
+      You should have received a copy of the GNU Affero General Public License
+      along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/**
+ * @file dns/dnsparser.c
+ * @brief helper library to parse DNS packets.
+ * @author Philipp Toelke
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include <idna.h>
+#if WINDOWS
+#include <idn-free.h>
+#endif
+#include "gnunet_util_lib.h"
+#include "gnunet_dnsparser_lib.h"
+#include "gnunet_tun_lib.h"
+
+
+/**
+ * Check if a label in UTF-8 format can be coded into valid IDNA.
+ * This can fail if the ASCII-conversion becomes longer than 63 characters.
+ *
+ * @param label label to check (UTF-8 string)
+ * @return #GNUNET_OK if the label can be converted to IDNA,
+ *         #GNUNET_SYSERR if the label is not valid for DNS names
+ */
+int
+GNUNET_DNSPARSER_check_label (const char *label)
+{
+  char *output;
+  size_t slen;
+
+  if (NULL != strchr (label, '.'))
+    return GNUNET_SYSERR; /* not a label! Did you mean GNUNET_DNSPARSER_check_name? */
+  if (IDNA_SUCCESS !=
+      idna_to_ascii_8z (label, &output, IDNA_ALLOW_UNASSIGNED))
+    return GNUNET_SYSERR;
+  slen = strlen (output);
+#if WINDOWS
+  idn_free (output);
+#else
+  free (output);
+#endif
+  return (slen > 63) ? GNUNET_SYSERR : GNUNET_OK;
+}
+
+
+/**
+ * Check if a label in UTF-8 format can be coded into valid IDNA.
+ * This can fail if the ASCII-conversion becomes longer than 253 characters.
+ *
+ * @param name name to check (UTF-8 string)
+ * @return #GNUNET_OK if the label can be converted to IDNA,
+ *         #GNUNET_SYSERR if the label is not valid for DNS names
+ */
+int
+GNUNET_DNSPARSER_check_name (const char *name)
+{
+  char *ldup;
+  char *output;
+  size_t slen;
+  char *tok;
+
+  ldup = GNUNET_strdup (name);
+  for (tok = strtok (ldup, "."); NULL != tok; tok = strtok (NULL, "."))
+    if (GNUNET_OK !=
+       GNUNET_DNSPARSER_check_label (tok))
+    {
+      GNUNET_free (ldup);
+      return GNUNET_SYSERR;
+    }
+  GNUNET_free (ldup);
+  if (IDNA_SUCCESS !=
+      idna_to_ascii_8z (name, &output, IDNA_ALLOW_UNASSIGNED))
+    return GNUNET_SYSERR;
+  slen = strlen (output);
+#if WINDOWS
+  idn_free (output);
+#else
+  free (output);
+#endif
+  return (slen > 253) ? GNUNET_SYSERR : GNUNET_OK;
+}
+
+
+/**
+ * Free SOA information record.
+ *
+ * @param soa record to free
+ */
+void
+GNUNET_DNSPARSER_free_soa (struct GNUNET_DNSPARSER_SoaRecord *soa)
+{
+  if (NULL == soa)
+    return;
+  GNUNET_free_non_null (soa->mname);
+  GNUNET_free_non_null (soa->rname);
+  GNUNET_free (soa);
+}
+
+
+/**
+ * Free CERT information record.
+ *
+ * @param cert record to free
+ */
+void
+GNUNET_DNSPARSER_free_cert (struct GNUNET_DNSPARSER_CertRecord *cert)
+{
+  if (NULL == cert)
+    return;
+  GNUNET_free_non_null (cert->certificate_data);
+  GNUNET_free (cert);
+}
+
+
+/**
+ * Free SRV information record.
+ *
+ * @param srv record to free
+ */
+void
+GNUNET_DNSPARSER_free_srv (struct GNUNET_DNSPARSER_SrvRecord *srv)
+{
+  if (NULL == srv)
+    return;
+  GNUNET_free_non_null (srv->target);
+  GNUNET_free (srv);
+}
+
+
+/**
+ * Free MX information record.
+ *
+ * @param mx record to free
+ */
+void
+GNUNET_DNSPARSER_free_mx (struct GNUNET_DNSPARSER_MxRecord *mx)
+{
+  if (NULL == mx)
+    return;
+  GNUNET_free_non_null (mx->mxhost);
+  GNUNET_free (mx);
+}
+
+
+/**
+ * Free the given DNS record.
+ *
+ * @param r record to free
+ */
+void
+GNUNET_DNSPARSER_free_record (struct GNUNET_DNSPARSER_Record *r)
+{
+  GNUNET_free_non_null (r->name);
+  switch (r->type)
+  {
+  case GNUNET_DNSPARSER_TYPE_MX:
+    GNUNET_DNSPARSER_free_mx (r->data.mx);
+    break;
+  case GNUNET_DNSPARSER_TYPE_SOA:
+    GNUNET_DNSPARSER_free_soa (r->data.soa);
+    break;
+  case GNUNET_DNSPARSER_TYPE_SRV:
+    GNUNET_DNSPARSER_free_srv (r->data.srv);
+    break;
+  case GNUNET_DNSPARSER_TYPE_CERT:
+    GNUNET_DNSPARSER_free_cert (r->data.cert);
+    break;
+  case GNUNET_DNSPARSER_TYPE_NS:
+  case GNUNET_DNSPARSER_TYPE_CNAME:
+  case GNUNET_DNSPARSER_TYPE_PTR:
+    GNUNET_free_non_null (r->data.hostname);
+    break;
+  default:
+    GNUNET_free_non_null (r->data.raw.data);
+    break;
+  }
+}
+
+
+/**
+ * Parse name inside of a DNS query or record.
+ *
+ * @param udp_payload entire UDP payload
+ * @param udp_payload_length length of @a udp_payload
+ * @param off pointer to the offset of the name to parse in the udp_payload (to be
+ *                    incremented by the size of the name)
+ * @param depth current depth of our recursion (to prevent stack overflow)
+ * @return name as 0-terminated C string on success, NULL if the payload is malformed
+ */
+static char *
+parse_name (const char *udp_payload,
+           size_t udp_payload_length,
+           size_t *off,
+           unsigned int depth)
+{
+  const uint8_t *input = (const uint8_t *) udp_payload;
+  char *ret;
+  char *tmp;
+  char *xstr;
+  uint8_t len;
+  size_t xoff;
+  char *utf8;
+  Idna_rc rc;
+
+  ret = GNUNET_strdup ("");
+  while (1)
+  {
+    if (*off >= udp_payload_length)
+    {
+      GNUNET_break_op (0);
+      goto error;
+    }
+    len = input[*off];
+    if (0 == len)
+    {
+      (*off)++;
+      break;
+    }
+    if (len < 64)
+    {
+      if (*off + 1 + len > udp_payload_length)
+      {
+       GNUNET_break_op (0);
+       goto error;
+      }
+      GNUNET_asprintf (&tmp,
+                      "%.*s",
+                      (int) len,
+                      &udp_payload[*off + 1]);
+      if (IDNA_SUCCESS !=
+         (rc = idna_to_unicode_8z8z (tmp, &utf8, IDNA_ALLOW_UNASSIGNED)))
+      {
+       GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                   _("Failed to convert DNS IDNA name `%s' to UTF-8: %s\n"),
+                   tmp,
+                   idna_strerror (rc));
+       GNUNET_free (tmp);
+       GNUNET_asprintf (&tmp,
+                        "%s%.*s.",
+                        ret,
+                        (int) len,
+                        &udp_payload[*off + 1]);
+      }
+      else
+      {
+       GNUNET_free (tmp);
+       GNUNET_asprintf (&tmp,
+                        "%s%s.",
+                        ret,
+                        utf8);
+#if WINDOWS
+       idn_free (utf8);
+#else
+       free (utf8);
+#endif
+      }
+      GNUNET_free (ret);
+      ret = tmp;
+      *off += 1 + len;
+    }
+    else if ((64 | 128) == (len & (64 | 128)) )
+    {
+      if (depth > 32)
+      {
+       GNUNET_break_op (0);
+       goto error; /* hard bound on stack to prevent "infinite" recursion, disallow! */
+      }
+      /* pointer to string */
+      if (*off + 1 > udp_payload_length)
+      {
+       GNUNET_break_op (0);
+       goto error;
+      }
+      xoff = ((len - (64 | 128)) << 8) + input[*off+1];
+      xstr = parse_name (udp_payload,
+                        udp_payload_length,
+                        &xoff,
+                        depth + 1);
+      if (NULL == xstr)
+      {
+       GNUNET_break_op (0);
+       goto error;
+      }
+      GNUNET_asprintf (&tmp,
+                      "%s%s.",
+                      ret,
+                      xstr);
+      GNUNET_free (ret);
+      GNUNET_free (xstr);
+      ret = tmp;
+      if (strlen (ret) > udp_payload_length)
+      {
+       GNUNET_break_op (0);
+       goto error; /* we are looping (building an infinite string) */
+      }
+      *off += 2;
+      /* pointers always terminate names */
+      break;
+    }
+    else
+    {
+      /* neither pointer nor inline string, not supported... */
+      GNUNET_break_op (0);
+      goto error;
+    }
+  }
+  if (0 < strlen(ret))
+    ret[strlen(ret)-1] = '\0'; /* eat tailing '.' */
+  return ret;
+ error:
+  GNUNET_break_op (0);
+  GNUNET_free (ret);
+  return NULL;
+}
+
+
+/**
+ * Parse name inside of a DNS query or record.
+ *
+ * @param udp_payload entire UDP payload
+ * @param udp_payload_length length of @a udp_payload
+ * @param off pointer to the offset of the name to parse in the udp_payload (to be
+ *                    incremented by the size of the name)
+ * @return name as 0-terminated C string on success, NULL if the payload is malformed
+ */
+char *
+GNUNET_DNSPARSER_parse_name (const char *udp_payload,
+                            size_t udp_payload_length,
+                            size_t *off)
+{
+  return parse_name (udp_payload, udp_payload_length, off, 0);
+}
+
+
+/**
+ * Parse a DNS query entry.
+ *
+ * @param udp_payload entire UDP payload
+ * @param udp_payload_length length of @a udp_payload
+ * @param off pointer to the offset of the query to parse in the udp_payload (to be
+ *                    incremented by the size of the query)
+ * @param q where to write the query information
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if the query is malformed
+ */
+int
+GNUNET_DNSPARSER_parse_query (const char *udp_payload,
+                             size_t udp_payload_length,
+                             size_t *off,
+                             struct GNUNET_DNSPARSER_Query *q)
+{
+  char *name;
+  struct GNUNET_TUN_DnsQueryLine ql;
+
+  name = GNUNET_DNSPARSER_parse_name (udp_payload,
+                                     udp_payload_length,
+                                     off);
+  if (NULL == name)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  q->name = name;
+  if (*off + sizeof (struct GNUNET_TUN_DnsQueryLine) > udp_payload_length)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_memcpy (&ql, &udp_payload[*off], sizeof (ql));
+  *off += sizeof (ql);
+  q->type = ntohs (ql.type);
+  q->dns_traffic_class = ntohs (ql.dns_traffic_class);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Parse a DNS SOA record.
+ *
+ * @param udp_payload reference to UDP packet
+ * @param udp_payload_length length of @a udp_payload
+ * @param off pointer to the offset of the query to parse in the SOA record (to be
+ *                    incremented by the size of the record), unchanged on error
+ * @return the parsed SOA record, NULL on error
+ */
+struct GNUNET_DNSPARSER_SoaRecord *
+GNUNET_DNSPARSER_parse_soa (const char *udp_payload,
+                           size_t udp_payload_length,
+                           size_t *off)
+{
+  struct GNUNET_DNSPARSER_SoaRecord *soa;
+  struct GNUNET_TUN_DnsSoaRecord soa_bin;
+  size_t old_off;
+
+  old_off = *off;
+  soa = GNUNET_new (struct GNUNET_DNSPARSER_SoaRecord);
+  soa->mname = GNUNET_DNSPARSER_parse_name (udp_payload,
+                                           udp_payload_length,
+                                           off);
+  soa->rname = GNUNET_DNSPARSER_parse_name (udp_payload,
+                                           udp_payload_length,
+                                           off);
+  if ( (NULL == soa->mname) ||
+       (NULL == soa->rname) ||
+       (*off + sizeof (struct GNUNET_TUN_DnsSoaRecord) > udp_payload_length) )
+  {
+    GNUNET_break_op (0);
+    GNUNET_DNSPARSER_free_soa (soa);
+    *off = old_off;
+    return NULL;
+  }
+  GNUNET_memcpy (&soa_bin,
+         &udp_payload[*off],
+         sizeof (struct GNUNET_TUN_DnsSoaRecord));
+  soa->serial = ntohl (soa_bin.serial);
+  soa->refresh = ntohl (soa_bin.refresh);
+  soa->retry = ntohl (soa_bin.retry);
+  soa->expire = ntohl (soa_bin.expire);
+  soa->minimum_ttl = ntohl (soa_bin.minimum);
+  (*off) += sizeof (struct GNUNET_TUN_DnsSoaRecord);
+  return soa;
+}
+
+
+/**
+ * Parse a DNS MX record.
+ *
+ * @param udp_payload reference to UDP packet
+ * @param udp_payload_length length of @a udp_payload
+ * @param off pointer to the offset of the query to parse in the MX record (to be
+ *                    incremented by the size of the record), unchanged on error
+ * @return the parsed MX record, NULL on error
+ */
+struct GNUNET_DNSPARSER_MxRecord *
+GNUNET_DNSPARSER_parse_mx (const char *udp_payload,
+                          size_t udp_payload_length,
+                          size_t *off)
+{
+  struct GNUNET_DNSPARSER_MxRecord *mx;
+  uint16_t mxpref;
+  size_t old_off;
+
+  old_off = *off;
+  if (*off + sizeof (uint16_t) > udp_payload_length)
+  {
+    GNUNET_break_op (0);
+    return NULL;
+  }
+  GNUNET_memcpy (&mxpref, &udp_payload[*off], sizeof (uint16_t));
+  (*off) += sizeof (uint16_t);
+  mx = GNUNET_new (struct GNUNET_DNSPARSER_MxRecord);
+  mx->preference = ntohs (mxpref);
+  mx->mxhost = GNUNET_DNSPARSER_parse_name (udp_payload,
+                                           udp_payload_length,
+                                           off);
+  if (NULL == mx->mxhost)
+  {
+    GNUNET_break_op (0);
+    GNUNET_DNSPARSER_free_mx (mx);
+    *off = old_off;
+    return NULL;
+  }
+  return mx;
+}
+
+
+/**
+ * Parse a DNS SRV record.
+ *
+ * @param udp_payload reference to UDP packet
+ * @param udp_payload_length length of @a udp_payload
+ * @param off pointer to the offset of the query to parse in the SRV record (to be
+ *                    incremented by the size of the record), unchanged on error
+ * @return the parsed SRV record, NULL on error
+ */
+struct GNUNET_DNSPARSER_SrvRecord *
+GNUNET_DNSPARSER_parse_srv (const char *udp_payload,
+                           size_t udp_payload_length,
+                           size_t *off)
+{
+  struct GNUNET_DNSPARSER_SrvRecord *srv;
+  struct GNUNET_TUN_DnsSrvRecord srv_bin;
+  size_t old_off;
+
+  old_off = *off;
+  if (*off + sizeof (struct GNUNET_TUN_DnsSrvRecord) > udp_payload_length)
+    return NULL;
+  GNUNET_memcpy (&srv_bin,
+         &udp_payload[*off],
+         sizeof (struct GNUNET_TUN_DnsSrvRecord));
+  (*off) += sizeof (struct GNUNET_TUN_DnsSrvRecord);
+  srv = GNUNET_new (struct GNUNET_DNSPARSER_SrvRecord);
+  srv->priority = ntohs (srv_bin.prio);
+  srv->weight = ntohs (srv_bin.weight);
+  srv->port = ntohs (srv_bin.port);
+  srv->target = GNUNET_DNSPARSER_parse_name (udp_payload,
+                                            udp_payload_length,
+                                            off);
+  if (NULL == srv->target)
+  {
+    GNUNET_DNSPARSER_free_srv (srv);
+    *off = old_off;
+    return NULL;
+  }
+  return srv;
+}
+
+
+/**
+ * Parse a DNS CERT record.
+ *
+ * @param udp_payload reference to UDP packet
+ * @param udp_payload_length length of @a udp_payload
+ * @param off pointer to the offset of the query to parse in the CERT record (to be
+ *                    incremented by the size of the record), unchanged on error
+ * @return the parsed CERT record, NULL on error
+ */
+struct GNUNET_DNSPARSER_CertRecord *
+GNUNET_DNSPARSER_parse_cert (const char *udp_payload,
+                             size_t udp_payload_length,
+                             size_t *off)
+{
+  struct GNUNET_DNSPARSER_CertRecord *cert;
+  struct GNUNET_TUN_DnsCertRecord dcert;
+
+  if (*off + sizeof (struct GNUNET_TUN_DnsCertRecord) >= udp_payload_length)
+  {
+    GNUNET_break_op (0);
+    return NULL;
+  }
+  GNUNET_memcpy (&dcert, &udp_payload[*off], sizeof (struct GNUNET_TUN_DnsCertRecord));
+  (*off) += sizeof (struct GNUNET_TUN_DnsCertRecord);
+  cert = GNUNET_new (struct GNUNET_DNSPARSER_CertRecord);
+  cert->cert_type = ntohs (dcert.cert_type);
+  cert->cert_tag = ntohs (dcert.cert_tag);
+  cert->algorithm = dcert.algorithm;
+  cert->certificate_size = udp_payload_length - (*off);
+  cert->certificate_data = GNUNET_malloc (cert->certificate_size);
+  GNUNET_memcpy (cert->certificate_data,
+          &udp_payload[*off],
+          cert->certificate_size);
+  (*off) += cert->certificate_size;
+  return cert;
+}
+
+
+/**
+ * Parse a DNS record entry.
+ *
+ * @param udp_payload entire UDP payload
+ * @param udp_payload_length length of @a udp_payload
+ * @param off pointer to the offset of the record to parse in the udp_payload (to be
+ *                    incremented by the size of the record)
+ * @param r where to write the record information
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if the record is malformed
+ */
+int
+GNUNET_DNSPARSER_parse_record (const char *udp_payload,
+                              size_t udp_payload_length,
+                              size_t *off,
+                              struct GNUNET_DNSPARSER_Record *r)
+{
+  char *name;
+  struct GNUNET_TUN_DnsRecordLine rl;
+  size_t old_off;
+  uint16_t data_len;
+
+  name = GNUNET_DNSPARSER_parse_name (udp_payload,
+                                     udp_payload_length,
+                                     off);
+  if (NULL == name)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  r->name = name;
+  if (*off + sizeof (struct GNUNET_TUN_DnsRecordLine) > udp_payload_length)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_memcpy (&rl, &udp_payload[*off], sizeof (rl));
+  (*off) += sizeof (rl);
+  r->type = ntohs (rl.type);
+  r->dns_traffic_class = ntohs (rl.dns_traffic_class);
+  r->expiration_time = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS,
+                                                                                       ntohl (rl.ttl)));
+  data_len = ntohs (rl.data_len);
+  if (*off + data_len > udp_payload_length)
+  {
+    GNUNET_break_op (0);
+    return GNUNET_SYSERR;
+  }
+  old_off = *off;
+  switch (r->type)
+  {
+  case GNUNET_DNSPARSER_TYPE_NS:
+  case GNUNET_DNSPARSER_TYPE_CNAME:
+  case GNUNET_DNSPARSER_TYPE_DNAME:
+  case GNUNET_DNSPARSER_TYPE_PTR:
+    r->data.hostname = GNUNET_DNSPARSER_parse_name (udp_payload,
+                                                   udp_payload_length,
+                                                   off);
+    if ( (NULL == r->data.hostname) ||
+        (old_off + data_len != *off) )
+      return GNUNET_SYSERR;
+    return GNUNET_OK;
+  case GNUNET_DNSPARSER_TYPE_SOA:
+    r->data.soa = GNUNET_DNSPARSER_parse_soa (udp_payload,
+                                             udp_payload_length,
+                                             off);
+    if ( (NULL == r->data.soa) ||
+        (old_off + data_len != *off) )
+    {
+      GNUNET_break_op (0);
+      return GNUNET_SYSERR;
+    }
+    return GNUNET_OK;
+  case GNUNET_DNSPARSER_TYPE_MX:
+    r->data.mx = GNUNET_DNSPARSER_parse_mx (udp_payload,
+                                           udp_payload_length,
+                                           off);
+    if ( (NULL == r->data.mx) ||
+        (old_off + data_len != *off) )
+    {
+      GNUNET_break_op (0);
+      return GNUNET_SYSERR;
+    }
+    return GNUNET_OK;
+  case GNUNET_DNSPARSER_TYPE_SRV:
+    r->data.srv = GNUNET_DNSPARSER_parse_srv (udp_payload,
+                                             udp_payload_length,
+                                             off);
+    if ( (NULL == r->data.srv) ||
+        (old_off + data_len != *off) )
+    {
+      GNUNET_break_op (0);
+      return GNUNET_SYSERR;
+    }
+    return GNUNET_OK;
+  default:
+    r->data.raw.data = GNUNET_malloc (data_len);
+    r->data.raw.data_len = data_len;
+    GNUNET_memcpy (r->data.raw.data,
+                   &udp_payload[*off],
+                   data_len);
+    break;
+  }
+  (*off) += data_len;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Parse a UDP payload of a DNS packet in to a nice struct for further
+ * processing and manipulation.
+ *
+ * @param udp_payload wire-format of the DNS packet
+ * @param udp_payload_length number of bytes in @a udp_payload
+ * @return NULL on error, otherwise the parsed packet
+ */
+struct GNUNET_DNSPARSER_Packet *
+GNUNET_DNSPARSER_parse (const char *udp_payload,
+                       size_t udp_payload_length)
+{
+  struct GNUNET_DNSPARSER_Packet *p;
+  const struct GNUNET_TUN_DnsHeader *dns;
+  size_t off;
+  unsigned int n;
+  unsigned int i;
+
+  if (udp_payload_length < sizeof (struct GNUNET_TUN_DnsHeader))
+    return NULL;
+  dns = (const struct GNUNET_TUN_DnsHeader *) udp_payload;
+  off = sizeof (struct GNUNET_TUN_DnsHeader);
+  p = GNUNET_new (struct GNUNET_DNSPARSER_Packet);
+  p->flags = dns->flags;
+  p->id = dns->id;
+  n = ntohs (dns->query_count);
+  if (n > 0)
+  {
+    p->queries = GNUNET_malloc (n * sizeof (struct GNUNET_DNSPARSER_Query));
+    p->num_queries = n;
+    for (i=0;i<n;i++)
+      if (GNUNET_OK !=
+         GNUNET_DNSPARSER_parse_query (udp_payload,
+                                       udp_payload_length,
+                                       &off,
+                                       &p->queries[i]))
+       goto error;
+  }
+  n = ntohs (dns->answer_rcount);
+  if (n > 0)
+  {
+    p->answers = GNUNET_malloc (n * sizeof (struct GNUNET_DNSPARSER_Record));
+    p->num_answers = n;
+    for (i=0;i<n;i++)
+      if (GNUNET_OK !=
+         GNUNET_DNSPARSER_parse_record (udp_payload,
+                                        udp_payload_length,
+                                        &off,
+                                        &p->answers[i]))
+       goto error;
+  }
+  n = ntohs (dns->authority_rcount);
+  if (n > 0)
+  {
+    p->authority_records = GNUNET_malloc (n * sizeof (struct GNUNET_DNSPARSER_Record));
+    p->num_authority_records = n;
+    for (i=0;i<n;i++)
+      if (GNUNET_OK !=
+         GNUNET_DNSPARSER_parse_record (udp_payload,
+                                        udp_payload_length,
+                                        &off,
+                                        &p->authority_records[i]))
+       goto error;
+  }
+  n = ntohs (dns->additional_rcount);
+  if (n > 0)
+  {
+    p->additional_records = GNUNET_malloc (n * sizeof (struct GNUNET_DNSPARSER_Record));
+    p->num_additional_records = n;
+    for (i=0;i<n;i++)
+      if (GNUNET_OK !=
+         GNUNET_DNSPARSER_parse_record (udp_payload,
+                                        udp_payload_length,
+                                        &off,
+                                        &p->additional_records[i]))
+       goto error;
+  }
+  return p;
+ error:
+  GNUNET_break_op (0);
+  GNUNET_DNSPARSER_free_packet (p);
+  return NULL;
+}
+
+
+/**
+ * Free memory taken by a packet.
+ *
+ * @param p packet to free
+ */
+void
+GNUNET_DNSPARSER_free_packet (struct GNUNET_DNSPARSER_Packet *p)
+{
+  unsigned int i;
+
+  for (i=0;i<p->num_queries;i++)
+    GNUNET_free_non_null (p->queries[i].name);
+  GNUNET_free_non_null (p->queries);
+  for (i=0;i<p->num_answers;i++)
+    GNUNET_DNSPARSER_free_record (&p->answers[i]);
+  GNUNET_free_non_null (p->answers);
+  for (i=0;i<p->num_authority_records;i++)
+    GNUNET_DNSPARSER_free_record (&p->authority_records[i]);
+  GNUNET_free_non_null (p->authority_records);
+  for (i=0;i<p->num_additional_records;i++)
+    GNUNET_DNSPARSER_free_record (&p->additional_records[i]);
+  GNUNET_free_non_null (p->additional_records);
+  GNUNET_free (p);
+}
+
+
+/* ********************** DNS packet assembly code **************** */
+
+
+/**
+ * Add a DNS name to the UDP packet at the given location, converting
+ * the name to IDNA notation as necessary.
+ *
+ * @param dst where to write the name (UDP packet)
+ * @param dst_len number of bytes in @a dst
+ * @param off pointer to offset where to write the name (increment by bytes used)
+ *            must not be changed if there is an error
+ * @param name name to write
+ * @return #GNUNET_SYSERR if @a name is invalid
+ *         #GNUNET_NO if @a name did not fit
+ *         #GNUNET_OK if @a name was added to @a dst
+ */
+int
+GNUNET_DNSPARSER_builder_add_name (char *dst,
+                                  size_t dst_len,
+                                  size_t *off,
+                                  const char *name)
+{
+  const char *dot;
+  const char *idna_name;
+  char *idna_start;
+  size_t start;
+  size_t pos;
+  size_t len;
+  Idna_rc rc;
+
+  if (NULL == name)
+    return GNUNET_SYSERR;
+
+  if (IDNA_SUCCESS !=
+      (rc = idna_to_ascii_8z (name,
+                              &idna_start,
+                              IDNA_ALLOW_UNASSIGNED)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+               _("Failed to convert UTF-8 name `%s' to DNS IDNA format: %s\n"),
+               name,
+               idna_strerror (rc));
+    return GNUNET_NO;
+  }
+  idna_name = idna_start;
+  start = *off;
+  if (start + strlen (idna_name) + 2 > dst_len)
+    goto fail;
+  pos = start;
+  do
+  {
+    dot = strchr (idna_name, '.');
+    if (NULL == dot)
+      len = strlen (idna_name);
+    else
+      len = dot - idna_name;
+    if ( (len >= 64) || (0 == len) )
+    {
+      GNUNET_break (0);
+      goto fail; /* segment too long or empty */
+    }
+    dst[pos++] = (char) (uint8_t) len;
+    GNUNET_memcpy (&dst[pos],
+                   idna_name,
+                   len);
+    pos += len;
+    idna_name += len + 1; /* also skip dot */
+  }
+  while (NULL != dot);
+  dst[pos++] = '\0'; /* terminator */
+  *off = pos;
+#if WINDOWS
+  idn_free (idna_start);
+#else
+  free (idna_start);
+#endif
+  return GNUNET_OK;
+ fail:
+#if WINDOWS
+  idn_free (idna_start);
+#else
+  free (idna_start);
+#endif
+  return GNUNET_NO;
+}
+
+
+/**
+ * Add a DNS query to the UDP packet at the given location.
+ *
+ * @param dst where to write the query
+ * @param dst_len number of bytes in @a dst
+ * @param off pointer to offset where to write the query (increment by bytes used)
+ *            must not be changed if there is an error
+ * @param query query to write
+ * @return #GNUNET_SYSERR if @a query is invalid
+ *         #GNUNET_NO if @a query did not fit
+ *         #GNUNET_OK if @a query was added to @a dst
+ */
+int
+GNUNET_DNSPARSER_builder_add_query (char *dst,
+                                   size_t dst_len,
+                                   size_t *off,
+                                   const struct GNUNET_DNSPARSER_Query *query)
+{
+  int ret;
+  struct GNUNET_TUN_DnsQueryLine ql;
+
+  ret = GNUNET_DNSPARSER_builder_add_name (dst, dst_len - sizeof (struct GNUNET_TUN_DnsQueryLine), off, query->name);
+  if (ret != GNUNET_OK)
+    return ret;
+  ql.type = htons (query->type);
+  ql.dns_traffic_class = htons (query->dns_traffic_class);
+  GNUNET_memcpy (&dst[*off], &ql, sizeof (ql));
+  (*off) += sizeof (ql);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Add an MX record to the UDP packet at the given location.
+ *
+ * @param dst where to write the mx record
+ * @param dst_len number of bytes in @a dst
+ * @param off pointer to offset where to write the mx information (increment by bytes used);
+ *            can also change if there was an error
+ * @param mx mx information to write
+ * @return #GNUNET_SYSERR if @a mx is invalid
+ *         #GNUNET_NO if @a mx did not fit
+ *         #GNUNET_OK if @a mx was added to @a dst
+ */
+int
+GNUNET_DNSPARSER_builder_add_mx (char *dst,
+                                size_t dst_len,
+                                size_t *off,
+                                const struct GNUNET_DNSPARSER_MxRecord *mx)
+{
+  uint16_t mxpref;
+
+  if (*off + sizeof (uint16_t) > dst_len)
+    return GNUNET_NO;
+  mxpref = htons (mx->preference);
+  GNUNET_memcpy (&dst[*off],
+                &mxpref,
+                sizeof (mxpref));
+  (*off) += sizeof (mxpref);
+  return GNUNET_DNSPARSER_builder_add_name (dst,
+                                           dst_len,
+                                           off,
+                                           mx->mxhost);
+}
+
+
+/**
+ * Add a CERT record to the UDP packet at the given location.
+ *
+ * @param dst where to write the CERT record
+ * @param dst_len number of bytes in @a dst
+ * @param off pointer to offset where to write the CERT information (increment by bytes used);
+ *            can also change if there was an error
+ * @param cert CERT information to write
+ * @return #GNUNET_SYSERR if @a cert is invalid
+ *         #GNUNET_NO if @a cert did not fit
+ *         #GNUNET_OK if @a cert was added to @a dst
+ */
+int
+GNUNET_DNSPARSER_builder_add_cert (char *dst,
+                                   size_t dst_len,
+                                   size_t *off,
+                                   const struct GNUNET_DNSPARSER_CertRecord *cert)
+{
+  struct GNUNET_TUN_DnsCertRecord dcert;
+
+  if ( (cert->cert_type > UINT16_MAX) ||
+       (cert->cert_tag > UINT16_MAX) ||
+       (cert->algorithm > UINT8_MAX) )
+  {
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+  if (*off + sizeof (struct GNUNET_TUN_DnsCertRecord) + cert->certificate_size > dst_len)
+    return GNUNET_NO;
+  dcert.cert_type = htons ((uint16_t) cert->cert_type);
+  dcert.cert_tag = htons ((uint16_t) cert->cert_tag);
+  dcert.algorithm = (uint8_t) cert->algorithm;
+  GNUNET_memcpy (&dst[*off], &dcert, sizeof (dcert));
+  (*off) += sizeof (dcert);
+  GNUNET_memcpy (&dst[*off], cert->certificate_data, cert->certificate_size);
+  (*off) += cert->certificate_size;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Add an SOA record to the UDP packet at the given location.
+ *
+ * @param dst where to write the SOA record
+ * @param dst_len number of bytes in @a dst
+ * @param off pointer to offset where to write the SOA information (increment by bytes used)
+ *            can also change if there was an error
+ * @param soa SOA information to write
+ * @return #GNUNET_SYSERR if @a soa is invalid
+ *         #GNUNET_NO if @a soa did not fit
+ *         #GNUNET_OK if @a soa was added to @a dst
+ */
+int
+GNUNET_DNSPARSER_builder_add_soa (char *dst,
+                                 size_t dst_len,
+                                 size_t *off,
+                                 const struct GNUNET_DNSPARSER_SoaRecord *soa)
+{
+  struct GNUNET_TUN_DnsSoaRecord sd;
+  int ret;
+
+  if ( (GNUNET_OK != (ret = GNUNET_DNSPARSER_builder_add_name (dst,
+                                                               dst_len,
+                                                               off,
+                                                               soa->mname))) ||
+       (GNUNET_OK != (ret = GNUNET_DNSPARSER_builder_add_name (dst,
+                                                               dst_len,
+                                                               off,
+                                                               soa->rname)) ) )
+    return ret;
+  if (*off + sizeof (struct GNUNET_TUN_DnsSoaRecord) > dst_len)
+    return GNUNET_NO;
+  sd.serial = htonl (soa->serial);
+  sd.refresh = htonl (soa->refresh);
+  sd.retry = htonl (soa->retry);
+  sd.expire = htonl (soa->expire);
+  sd.minimum = htonl (soa->minimum_ttl);
+  GNUNET_memcpy (&dst[*off], &sd, sizeof (sd));
+  (*off) += sizeof (sd);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Add an SRV record to the UDP packet at the given location.
+ *
+ * @param dst where to write the SRV record
+ * @param dst_len number of bytes in @a dst
+ * @param off pointer to offset where to write the SRV information (increment by bytes used)
+ *            can also change if there was an error
+ * @param srv SRV information to write
+ * @return #GNUNET_SYSERR if @a srv is invalid
+ *         #GNUNET_NO if @a srv did not fit
+ *         #GNUNET_OK if @a srv was added to @a dst
+ */
+int
+GNUNET_DNSPARSER_builder_add_srv (char *dst,
+                                 size_t dst_len,
+                                 size_t *off,
+                                 const struct GNUNET_DNSPARSER_SrvRecord *srv)
+{
+  struct GNUNET_TUN_DnsSrvRecord sd;
+  int ret;
+
+  if (*off + sizeof (struct GNUNET_TUN_DnsSrvRecord) > dst_len)
+    return GNUNET_NO;
+  sd.prio = htons (srv->priority);
+  sd.weight = htons (srv->weight);
+  sd.port = htons (srv->port);
+  GNUNET_memcpy (&dst[*off], &sd, sizeof (sd));
+  (*off) += sizeof (sd);
+  if (GNUNET_OK != (ret = GNUNET_DNSPARSER_builder_add_name (dst,
+                                   dst_len,
+                                   off,
+                                   srv->target)))
+    return ret;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Add a DNS record to the UDP packet at the given location.
+ *
+ * @param dst where to write the query
+ * @param dst_len number of bytes in @a dst
+ * @param off pointer to offset where to write the query (increment by bytes used)
+ *            must not be changed if there is an error
+ * @param record record to write
+ * @return #GNUNET_SYSERR if @a record is invalid
+ *         #GNUNET_NO if @a record did not fit
+ *         #GNUNET_OK if @a record was added to @a dst
+ */
+static int
+add_record (char *dst,
+           size_t dst_len,
+           size_t *off,
+           const struct GNUNET_DNSPARSER_Record *record)
+{
+  int ret;
+  size_t start;
+  size_t pos;
+  struct GNUNET_TUN_DnsRecordLine rl;
+
+  start = *off;
+  ret = GNUNET_DNSPARSER_builder_add_name (dst,
+                                           dst_len - sizeof (struct GNUNET_TUN_DnsRecordLine),
+                                           off,
+                                           record->name);
+  if (GNUNET_OK != ret)
+    return ret;
+  /* '*off' is now the position where we will need to write the record line */
+
+  pos = *off + sizeof (struct GNUNET_TUN_DnsRecordLine);
+  switch (record->type)
+  {
+  case GNUNET_DNSPARSER_TYPE_MX:
+    ret = GNUNET_DNSPARSER_builder_add_mx (dst,
+                                          dst_len,
+                                          &pos,
+                                          record->data.mx);
+    break;
+  case GNUNET_DNSPARSER_TYPE_CERT:
+    ret = GNUNET_DNSPARSER_builder_add_cert (dst,
+                                            dst_len,
+                                            &pos,
+                                            record->data.cert);
+    break;
+  case GNUNET_DNSPARSER_TYPE_SOA:
+    ret = GNUNET_DNSPARSER_builder_add_soa (dst,
+                                           dst_len,
+                                           &pos,
+                                           record->data.soa);
+    break;
+  case GNUNET_DNSPARSER_TYPE_NS:
+  case GNUNET_DNSPARSER_TYPE_CNAME:
+  case GNUNET_DNSPARSER_TYPE_PTR:
+    ret = GNUNET_DNSPARSER_builder_add_name (dst,
+                                            dst_len,
+                                            &pos,
+                                            record->data.hostname);
+    break;
+  case GNUNET_DNSPARSER_TYPE_SRV:
+    ret = GNUNET_DNSPARSER_builder_add_srv (dst,
+                                           dst_len,
+                                           &pos,
+                                           record->data.srv);
+    break;
+  default:
+    if (pos + record->data.raw.data_len > dst_len)
+    {
+      ret = GNUNET_NO;
+      break;
+    }
+    GNUNET_memcpy (&dst[pos],
+                  record->data.raw.data,
+                  record->data.raw.data_len);
+    pos += record->data.raw.data_len;
+    ret = GNUNET_OK;
+    break;
+  }
+  if (GNUNET_OK != ret)
+  {
+    *off = start;
+    return GNUNET_NO;
+  }
+
+  if (pos - (*off + sizeof (struct GNUNET_TUN_DnsRecordLine)) > UINT16_MAX)
+  {
+    /* record data too long */
+    *off = start;
+    return GNUNET_NO;
+  }
+  rl.type = htons (record->type);
+  rl.dns_traffic_class = htons (record->dns_traffic_class);
+  rl.ttl = htonl (GNUNET_TIME_absolute_get_remaining (record->expiration_time).rel_value_us / 1000LL / 1000LL); /* in seconds */
+  rl.data_len = htons ((uint16_t) (pos - (*off + sizeof (struct GNUNET_TUN_DnsRecordLine))));
+  GNUNET_memcpy (&dst[*off], &rl, sizeof (struct GNUNET_TUN_DnsRecordLine));
+  *off = pos;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Given a DNS packet @a p, generate the corresponding UDP payload.
+ * Note that we do not attempt to pack the strings with pointers
+ * as this would complicate the code and this is about being
+ * simple and secure, not fast, fancy and broken like bind.
+ *
+ * @param p packet to pack
+ * @param max maximum allowed size for the resulting UDP payload
+ * @param buf set to a buffer with the packed message
+ * @param buf_length set to the length of @a buf
+ * @return #GNUNET_SYSERR if @a p is invalid
+ *         #GNUNET_NO if @a p was truncated (but there is still a result in @a buf)
+ *         #GNUNET_OK if @a p was packed completely into @a buf
+ */
+int
+GNUNET_DNSPARSER_pack (const struct GNUNET_DNSPARSER_Packet *p,
+                      uint16_t max,
+                      char **buf,
+                      size_t *buf_length)
+{
+  struct GNUNET_TUN_DnsHeader dns;
+  size_t off;
+  char tmp[max];
+  unsigned int i;
+  int ret;
+  int trc;
+
+  if ( (p->num_queries > UINT16_MAX) ||
+       (p->num_answers > UINT16_MAX) ||
+       (p->num_authority_records > UINT16_MAX) ||
+       (p->num_additional_records > UINT16_MAX) )
+    return GNUNET_SYSERR;
+  dns.id = p->id;
+  dns.flags = p->flags;
+  dns.query_count = htons (p->num_queries);
+  dns.answer_rcount = htons (p->num_answers);
+  dns.authority_rcount = htons (p->num_authority_records);
+  dns.additional_rcount = htons (p->num_additional_records);
+
+  off = sizeof (struct GNUNET_TUN_DnsHeader);
+  trc = GNUNET_NO;
+  for (i=0;i<p->num_queries;i++)
+  {
+    ret = GNUNET_DNSPARSER_builder_add_query (tmp,
+                                             sizeof (tmp),
+                                             &off,
+                                             &p->queries[i]);
+    if (GNUNET_SYSERR == ret)
+      return GNUNET_SYSERR;
+    if (GNUNET_NO == ret)
+    {
+      dns.query_count = htons ((uint16_t) (i-1));
+      trc = GNUNET_YES;
+      break;
+    }
+  }
+  for (i=0;i<p->num_answers;i++)
+  {
+    ret = add_record (tmp,
+                     sizeof (tmp),
+                     &off,
+                     &p->answers[i]);
+    if (GNUNET_SYSERR == ret)
+      return GNUNET_SYSERR;
+    if (GNUNET_NO == ret)
+    {
+      dns.answer_rcount = htons ((uint16_t) (i-1));
+      trc = GNUNET_YES;
+      break;
+    }
+  }
+  for (i=0;i<p->num_authority_records;i++)
+  {
+    ret = add_record (tmp,
+                     sizeof (tmp),
+                     &off,
+                     &p->authority_records[i]);
+    if (GNUNET_SYSERR == ret)
+      return GNUNET_SYSERR;
+    if (GNUNET_NO == ret)
+    {
+      dns.authority_rcount = htons ((uint16_t) (i-1));
+      trc = GNUNET_YES;
+      break;
+    }
+  }
+  for (i=0;i<p->num_additional_records;i++)
+  {
+    ret = add_record (tmp,
+                     sizeof (tmp),
+                     &off,
+                     &p->additional_records[i]);
+    if (GNUNET_SYSERR == ret)
+      return GNUNET_SYSERR;
+    if (GNUNET_NO == ret)
+    {
+      dns.additional_rcount = htons (i-1);
+      trc = GNUNET_YES;
+      break;
+    }
+  }
+
+  if (GNUNET_YES == trc)
+    dns.flags.message_truncated = 1;
+  GNUNET_memcpy (tmp,
+                &dns,
+                sizeof (struct GNUNET_TUN_DnsHeader));
+
+  *buf = GNUNET_malloc (off);
+  *buf_length = off;
+  GNUNET_memcpy (*buf,
+                tmp,
+                off);
+  if (GNUNET_YES == trc)
+    return GNUNET_NO;
+  return GNUNET_OK;
+}
+
+
+/**
+ * Convert a block of binary data to HEX.
+ *
+ * @param data binary data to convert
+ * @param data_size number of bytes in @a data
+ * @return HEX string (lower case)
+ */
+char *
+GNUNET_DNSPARSER_bin_to_hex (const void *data,
+                             size_t data_size)
+{
+  char *ret;
+  size_t off;
+  const uint8_t *idata;
+
+  idata = data;
+  ret = GNUNET_malloc (data_size * 2 + 1);
+  for (off = 0; off < data_size; off++)
+    sprintf (&ret[off * 2],
+             "%02x",
+             idata[off]);
+  return ret;
+}
+
+
+/**
+ * Convert a HEX string to block of binary data.
+ *
+ * @param hex HEX string to convert (may contain mixed case)
+ * @param data where to write result, must be
+ *             at least `strlen(hex)/2` bytes long
+ * @return number of bytes written to data
+ */
+size_t
+GNUNET_DNSPARSER_hex_to_bin (const char *hex,
+                             void *data)
+{
+  size_t data_size;
+  size_t off;
+  uint8_t *idata;
+  unsigned int h;
+  char in[3];
+
+  data_size = strlen (hex) / 2;
+  idata = data;
+  in[2] = '\0';
+  for (off = 0; off < data_size; off++)
+  {
+    in[0] = tolower ((unsigned char) hex[off * 2]);
+    in[1] = tolower ((unsigned char) hex[off * 2 + 1]);
+    if (1 != sscanf (in, "%x", &h))
+      return off;
+    idata[off] = (uint8_t) h;
+  }
+  return off;
+}
+
+
+/* end of dnsparser.c */
diff --git a/src/util/dnsstub.c b/src/util/dnsstub.c
new file mode 100644 (file)
index 0000000..969ff7b
--- /dev/null
@@ -0,0 +1,749 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2012, 2018 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Affero General Public License for more details.
+    
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @file dns/dnsstub.c
+ * @brief DNS stub resolver which sends DNS requests to an actual resolver
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_tun_lib.h"
+#include "gnunet_dnsstub_lib.h"
+
+/**
+ * Timeout for retrying DNS queries.
+ */
+#define DNS_RETRANSMIT_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250)
+
+
+/**
+ * DNS Server used for resolution.
+ */
+struct DnsServer;
+
+
+/**
+ * UDP socket we are using for sending DNS requests to the Internet.
+ */
+struct GNUNET_DNSSTUB_RequestSocket
+{
+
+  /**
+   * UDP socket we use for this request for IPv4
+   */
+  struct GNUNET_NETWORK_Handle *dnsout4;
+
+  /**
+   * UDP socket we use for this request for IPv6
+   */
+  struct GNUNET_NETWORK_Handle *dnsout6;
+
+  /**
+   * Function to call with result.
+   */
+  GNUNET_DNSSTUB_ResultCallback rc;
+
+  /**
+   * Closure for @e rc.
+   */
+  void *rc_cls;
+
+  /**
+   * Task for reading from dnsout4 and dnsout6.
+   */
+  struct GNUNET_SCHEDULER_Task *read_task;
+
+  /**
+   * Task for retrying transmission of the query.
+   */
+  struct GNUNET_SCHEDULER_Task *retry_task;
+
+  /**
+   * Next address we sent the DNS request to.
+   */
+  struct DnsServer *ds_pos;
+
+  /**
+   * Context this request executes in.
+   */
+  struct GNUNET_DNSSTUB_Context *ctx;
+
+  /**
+   * Query we sent to @e addr.
+   */
+  void *request;
+
+  /**
+   * Number of bytes in @a request.
+   */
+  size_t request_len;
+
+};
+
+
+/**
+ * DNS Server used for resolution.
+ */
+struct DnsServer
+{
+
+  /**
+   * Kept in a DLL.
+   */
+  struct DnsServer *next;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct DnsServer *prev;
+
+  /**
+   * IP address of the DNS resolver.
+   */
+  struct sockaddr_storage ss;
+};
+
+
+/**
+ * Handle to the stub resolver.
+ */
+struct GNUNET_DNSSTUB_Context
+{
+
+  /**
+   * Array of all open sockets for DNS requests.
+   */
+  struct GNUNET_DNSSTUB_RequestSocket *sockets;
+
+  /**
+   * DLL of DNS resolvers we use.
+   */
+  struct DnsServer *dns_head;
+
+  /**
+   * DLL of DNS resolvers we use.
+   */
+  struct DnsServer *dns_tail;
+
+  /**
+   * How frequently do we retry requests?
+   */
+  struct GNUNET_TIME_Relative retry_freq;
+
+  /**
+   * Length of @e sockets array.
+   */
+  unsigned int num_sockets;
+
+};
+
+
+/**
+ * We're done with a `struct GNUNET_DNSSTUB_RequestSocket`, close it for now.
+ *
+ * @param rs request socket to clean up
+ */
+static void
+cleanup_rs (struct GNUNET_DNSSTUB_RequestSocket *rs)
+{
+  if (NULL != rs->dnsout4)
+  {
+    GNUNET_NETWORK_socket_close (rs->dnsout4);
+    rs->dnsout4 = NULL;
+  }
+  if (NULL != rs->dnsout6)
+  {
+    GNUNET_NETWORK_socket_close (rs->dnsout6);
+    rs->dnsout6 = NULL;
+  }
+  if (NULL != rs->read_task)
+  {
+    GNUNET_SCHEDULER_cancel (rs->read_task);
+    rs->read_task = NULL;
+  }
+  if (NULL != rs->retry_task)
+  {
+    GNUNET_SCHEDULER_cancel (rs->retry_task);
+    rs->retry_task = NULL;
+  }
+  if (NULL != rs->request)
+  {
+    GNUNET_free (rs->request);
+    rs->request = NULL;
+  }
+}
+
+
+/**
+ * Open source port for sending DNS requests
+ *
+ * @param af AF_INET or AF_INET6
+ * @return #GNUNET_OK on success
+ */
+static struct GNUNET_NETWORK_Handle *
+open_socket (int af)
+{
+  struct sockaddr_in a4;
+  struct sockaddr_in6 a6;
+  struct sockaddr *sa;
+  socklen_t alen;
+  struct GNUNET_NETWORK_Handle *ret;
+
+  ret = GNUNET_NETWORK_socket_create (af, SOCK_DGRAM, 0);
+  if (NULL == ret)
+    return NULL;
+  switch (af)
+  {
+  case AF_INET:
+    memset (&a4, 0, alen = sizeof (struct sockaddr_in));
+    sa = (struct sockaddr *) &a4;
+    break;
+  case AF_INET6:
+    memset (&a6, 0, alen = sizeof (struct sockaddr_in6));
+    sa = (struct sockaddr *) &a6;
+    break;
+  default:
+    GNUNET_break (0);
+    GNUNET_NETWORK_socket_close (ret);
+    return NULL;
+  }
+  sa->sa_family = af;
+  if (GNUNET_OK != GNUNET_NETWORK_socket_bind (ret,
+                                              sa,
+                                              alen))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+               _("Could not bind to any port: %s\n"),
+               STRERROR (errno));
+    GNUNET_NETWORK_socket_close (ret);
+    return NULL;
+  }
+  return ret;
+}
+
+
+/**
+ * Get a socket of the specified address family to send out a
+ * UDP DNS request to the Internet.
+ *
+ * @param ctx the DNSSTUB context
+ * @return NULL on error
+ */
+static struct GNUNET_DNSSTUB_RequestSocket *
+get_request_socket (struct GNUNET_DNSSTUB_Context *ctx)
+{
+  struct GNUNET_DNSSTUB_RequestSocket *rs;
+
+  for (unsigned int i=0;i<256;i++)
+  {
+    rs = &ctx->sockets[GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_NONCE,
+                                                 ctx->num_sockets)];
+    if (NULL == rs->rc)
+      break;
+  }
+  if (NULL != rs->rc)
+  {
+    /* signal "failure" */
+    rs->rc (rs->rc_cls,
+            NULL,
+            0);
+    rs->rc = NULL;
+  }
+  if (NULL != rs->read_task)
+  {
+    GNUNET_SCHEDULER_cancel (rs->read_task);
+    rs->read_task = NULL;
+  }
+  if (NULL != rs->retry_task)
+  {
+    GNUNET_SCHEDULER_cancel (rs->retry_task);
+    rs->retry_task = NULL;
+  }
+  if (NULL != rs->request)
+  {
+    GNUNET_free (rs->request);
+    rs->request = NULL;
+  }
+  rs->ctx = ctx;
+  return rs;
+}
+
+
+/**
+ * Actually do the reading of a DNS packet from our UDP socket and see
+ * if we have a valid, matching, pending request.
+ *
+ * @param rs request socket with callback details
+ * @param dnsout socket to read from
+ * @return #GNUNET_OK on success, #GNUNET_NO on drop, #GNUNET_SYSERR on IO-errors (closed socket)
+ */
+static int
+do_dns_read (struct GNUNET_DNSSTUB_RequestSocket *rs,
+            struct GNUNET_NETWORK_Handle *dnsout)
+{
+  struct GNUNET_DNSSTUB_Context *ctx = rs->ctx;
+  ssize_t r;
+  int len;
+
+#ifndef MINGW
+  if (0 != ioctl (GNUNET_NETWORK_get_fd (dnsout),
+                  FIONREAD,
+                  &len))
+  {
+    /* conservative choice: */
+    len = UINT16_MAX;
+  }
+#else
+  /* port the code above? */
+  len = UINT16_MAX;
+#endif
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+             "Receiving %d byte DNS reply\n",
+             len);
+  {
+    unsigned char buf[len] GNUNET_ALIGN;
+    int found;
+    struct sockaddr_storage addr;
+    socklen_t addrlen;
+    struct GNUNET_TUN_DnsHeader *dns;
+
+    addrlen = sizeof (addr);
+    memset (&addr,
+            0,
+            sizeof (addr));
+    r = GNUNET_NETWORK_socket_recvfrom (dnsout,
+                                       buf,
+                                        sizeof (buf),
+                                       (struct sockaddr*) &addr,
+                                        &addrlen);
+    if (-1 == r)
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
+                           "recvfrom");
+      GNUNET_NETWORK_socket_close (dnsout);
+      return GNUNET_SYSERR;
+    }
+    found = GNUNET_NO;
+    for (struct DnsServer *ds = ctx->dns_head; NULL != ds; ds = ds->next)
+    {
+      if (0 == memcmp (&addr,
+                       &ds->ss,
+                       GNUNET_MIN (sizeof (struct sockaddr_storage),
+                                   addrlen)))
+      {
+        found = GNUNET_YES;
+        break;
+      }
+    }
+    if (GNUNET_NO == found)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "Received DNS response from server we never asked (ignored)");
+      return GNUNET_NO;
+    }
+    if (sizeof (struct GNUNET_TUN_DnsHeader) > r)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                 _("Received DNS response that is too small (%u bytes)"),
+                 (unsigned int) r);
+      return GNUNET_NO;
+    }
+    dns = (struct GNUNET_TUN_DnsHeader *) buf;
+    if (NULL == rs->rc)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                 "Request timeout or cancelled; ignoring reply\n");
+      return GNUNET_NO;
+    }
+    rs->rc (rs->rc_cls,
+            dns,
+            r);
+  }
+  return GNUNET_OK;
+}
+
+
+/**
+ * Read a DNS response from the (unhindered) UDP-Socket
+ *
+ * @param cls socket to read from
+ */
+static void
+read_response (void *cls);
+
+
+/**
+ * Schedule #read_response() task for @a rs.
+ *
+ * @param rs request to schedule read operation for
+ */
+static void
+schedule_read (struct GNUNET_DNSSTUB_RequestSocket *rs)
+{
+  struct GNUNET_NETWORK_FDSet *rset;
+
+  if (NULL != rs->read_task)
+    GNUNET_SCHEDULER_cancel (rs->read_task);
+  rset = GNUNET_NETWORK_fdset_create ();
+  if (NULL != rs->dnsout4)
+    GNUNET_NETWORK_fdset_set (rset,
+                              rs->dnsout4);
+  if (NULL != rs->dnsout6)
+    GNUNET_NETWORK_fdset_set (rset,
+                              rs->dnsout6);
+  rs->read_task = GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
+                                              GNUNET_TIME_UNIT_FOREVER_REL,
+                                              rset,
+                                              NULL,
+                                              &read_response,
+                                               rs);
+  GNUNET_NETWORK_fdset_destroy (rset);
+}
+
+
+/**
+ * Read a DNS response from the (unhindered) UDP-Socket
+ *
+ * @param cls `struct GNUNET_DNSSTUB_RequestSocket` to read from
+ */
+static void
+read_response (void *cls)
+{
+  struct GNUNET_DNSSTUB_RequestSocket *rs = cls;
+  const struct GNUNET_SCHEDULER_TaskContext *tc;
+
+  rs->read_task = NULL;
+  tc = GNUNET_SCHEDULER_get_task_context ();
+  /* read and process ready sockets */
+  if ( (NULL != rs->dnsout4) &&
+       (GNUNET_NETWORK_fdset_isset (tc->read_ready,
+                                    rs->dnsout4)) &&
+       (GNUNET_SYSERR ==
+        do_dns_read (rs,
+                     rs->dnsout4)) )
+    rs->dnsout4 = NULL;
+  if ( (NULL != rs->dnsout6) &&
+       (GNUNET_NETWORK_fdset_isset (tc->read_ready,
+                                    rs->dnsout6)) &&
+       (GNUNET_SYSERR ==
+        do_dns_read (rs,
+                     rs->dnsout6)) )
+    rs->dnsout6 = NULL;
+  /* re-schedule read task */
+  schedule_read (rs);
+}
+
+
+/**
+ * Task to (re)transmit the DNS query, possibly repeatedly until
+ * we succeed.
+ *
+ * @param cls our `struct GNUNET_DNSSTUB_RequestSocket *`
+ */
+static void
+transmit_query (void *cls)
+{
+  struct GNUNET_DNSSTUB_RequestSocket *rs = cls;
+  struct GNUNET_DNSSTUB_Context *ctx = rs->ctx;
+  const struct sockaddr *sa;
+  socklen_t salen;
+  struct DnsServer *ds;
+  struct GNUNET_NETWORK_Handle *dnsout;
+
+  rs->retry_task = GNUNET_SCHEDULER_add_delayed (ctx->retry_freq,
+                                                 &transmit_query,
+                                                 rs);
+  ds = rs->ds_pos;
+  rs->ds_pos = ds->next;
+  if (NULL == rs->ds_pos)
+    rs->ds_pos = ctx->dns_head;
+  GNUNET_assert (NULL != ds);
+  dnsout = NULL;
+  switch (ds->ss.ss_family)
+  {
+  case AF_INET:
+    if (NULL == rs->dnsout4)
+      rs->dnsout4 = open_socket (AF_INET);
+    dnsout = rs->dnsout4;
+    sa = (const struct sockaddr *) &ds->ss;
+    salen = sizeof (struct sockaddr_in);
+    break;
+  case AF_INET6:
+    if (NULL == rs->dnsout6)
+      rs->dnsout6 = open_socket (AF_INET6);
+    dnsout = rs->dnsout6;
+    sa = (const struct sockaddr *) &ds->ss;
+    salen = sizeof (struct sockaddr_in6);
+    break;
+  default:
+    return;
+  }
+  if (NULL == dnsout)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Unable to use configure DNS server, skipping\n");
+    return;
+  }
+  if (GNUNET_SYSERR ==
+      GNUNET_NETWORK_socket_sendto (dnsout,
+                                   rs->request,
+                                   rs->request_len,
+                                    sa,
+                                    salen))
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+               _("Failed to send DNS request to %s: %s\n"),
+               GNUNET_a2s (sa,
+                            salen),
+                STRERROR (errno));
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+               _("Sent DNS request to %s\n"),
+               GNUNET_a2s (sa,
+                            salen));
+  schedule_read (rs);
+}
+
+
+/**
+ * Perform DNS resolution using our default IP from init.
+ *
+ * @param ctx stub resolver to use
+ * @param request DNS request to transmit
+ * @param request_len number of bytes in msg
+ * @param rc function to call with result
+ * @param rc_cls closure for 'rc'
+ * @return socket used for the request, NULL on error
+ */
+struct GNUNET_DNSSTUB_RequestSocket *
+GNUNET_DNSSTUB_resolve (struct GNUNET_DNSSTUB_Context *ctx,
+                        const void *request,
+                        size_t request_len,
+                        GNUNET_DNSSTUB_ResultCallback rc,
+                        void *rc_cls)
+{
+  struct GNUNET_DNSSTUB_RequestSocket *rs;
+
+  if (NULL == ctx->dns_head)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "No DNS server configured for resolution\n");
+    return NULL;
+  }
+  if (NULL == (rs = get_request_socket (ctx)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "No request socket available for DNS resolution\n");
+    return NULL;
+  }
+  rs->ds_pos = ctx->dns_head;
+  rs->rc = rc;
+  rs->rc_cls = rc_cls;
+  rs->request = GNUNET_memdup (request,
+                               request_len);
+  rs->request_len = request_len;
+  rs->retry_task = GNUNET_SCHEDULER_add_now (&transmit_query,
+                                             rs);
+  return rs;
+}
+
+
+/**
+ * Cancel DNS resolution.
+ *
+ * @param rs resolution to cancel
+ */
+void
+GNUNET_DNSSTUB_resolve_cancel (struct GNUNET_DNSSTUB_RequestSocket *rs)
+{
+  rs->rc = NULL;
+  if (NULL != rs->retry_task)
+  {
+    GNUNET_SCHEDULER_cancel (rs->retry_task);
+    rs->retry_task = NULL;
+  }
+  if (NULL != rs->read_task)
+  {
+    GNUNET_SCHEDULER_cancel (rs->read_task);
+    rs->read_task = NULL;
+  }
+}
+
+
+/**
+ * Start a DNS stub resolver.
+ *
+ * @param num_sockets how many sockets should we open
+ *        in parallel for DNS queries for this stub?
+ * @return NULL on error
+ */
+struct GNUNET_DNSSTUB_Context *
+GNUNET_DNSSTUB_start (unsigned int num_sockets)
+{
+  struct GNUNET_DNSSTUB_Context *ctx;
+
+  if (0 == num_sockets)
+  {
+    GNUNET_break (0);
+    return NULL;
+  }
+  ctx = GNUNET_new (struct GNUNET_DNSSTUB_Context);
+  ctx->num_sockets = num_sockets;
+  ctx->sockets = GNUNET_new_array (num_sockets,
+                                   struct GNUNET_DNSSTUB_RequestSocket);
+  ctx->retry_freq = DNS_RETRANSMIT_DELAY;
+  return ctx;
+}
+
+
+/**
+ * Add nameserver for use by the DNSSTUB.  We will use
+ * all provided nameservers for resolution (round-robin).
+ *
+ * @param ctx resolver context to modify
+ * @param dns_ip target IP address to use (as string)
+ * @return #GNUNET_OK on success
+ */
+int
+GNUNET_DNSSTUB_add_dns_ip (struct GNUNET_DNSSTUB_Context *ctx,
+                           const char *dns_ip)
+{
+  struct DnsServer *ds;
+  struct in_addr i4;
+  struct in6_addr i6;
+
+  ds = GNUNET_new (struct DnsServer);
+  if (1 == inet_pton (AF_INET,
+                      dns_ip,
+                      &i4))
+  {
+    struct sockaddr_in *s4 = (struct sockaddr_in *) &ds->ss;
+
+    s4->sin_family = AF_INET;
+    s4->sin_port = htons (53);
+    s4->sin_addr = i4;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+    s4->sin_len = (u_char) sizeof (struct sockaddr_in);
+#endif
+  }
+  else if (1 == inet_pton (AF_INET6,
+                           dns_ip,
+                           &i6))
+  {
+    struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) &ds->ss;
+
+    s6->sin6_family = AF_INET6;
+    s6->sin6_port = htons (53);
+    s6->sin6_addr = i6;
+#if HAVE_SOCKADDR_IN_SIN_LEN
+    s6->sin6_len = (u_char) sizeof (struct sockaddr_in6);
+#endif
+  }
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "Malformed IP address `%s' for DNS server\n",
+                dns_ip);
+    GNUNET_free (ds);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_CONTAINER_DLL_insert (ctx->dns_head,
+                               ctx->dns_tail,
+                               ds);
+  return GNUNET_OK;
+}
+
+
+/**
+ * Add nameserver for use by the DNSSTUB.  We will use
+ * all provided nameservers for resolution (round-robin).
+ *
+ * @param ctx resolver context to modify
+ * @param sa socket address of DNS resolver to use
+ * @return #GNUNET_OK on success
+ */
+int
+GNUNET_DNSSTUB_add_dns_sa (struct GNUNET_DNSSTUB_Context *ctx,
+                           const struct sockaddr *sa)
+{
+  struct DnsServer *ds;
+
+  ds = GNUNET_new (struct DnsServer);
+  switch (sa->sa_family)
+  {
+  case AF_INET:
+    GNUNET_memcpy (&ds->ss,
+                   sa,
+                   sizeof (struct sockaddr_in));
+    break;
+  case AF_INET6:
+    GNUNET_memcpy (&ds->ss,
+                   sa,
+                   sizeof (struct sockaddr_in6));
+    break;
+  default:
+    GNUNET_break (0);
+    GNUNET_free (ds);
+    return GNUNET_SYSERR;
+  }
+  GNUNET_CONTAINER_DLL_insert (ctx->dns_head,
+                               ctx->dns_tail,
+                               ds);
+  return GNUNET_OK;
+}
+
+
+/**
+ * How long should we try requests before timing out?
+ * Only effective for requests issued after this call.
+ *
+ * @param ctx resolver context to modify
+ * @param retry_freq how long to wait between retries
+ */
+void
+GNUNET_DNSSTUB_set_retry (struct GNUNET_DNSSTUB_Context *ctx,
+                          struct GNUNET_TIME_Relative retry_freq)
+{
+  ctx->retry_freq = retry_freq;
+}
+
+
+/**
+ * Cleanup DNSSTUB resolver.
+ *
+ * @param ctx stub resolver to clean up
+ */
+void
+GNUNET_DNSSTUB_stop (struct GNUNET_DNSSTUB_Context *ctx)
+{
+  struct DnsServer *ds;
+
+  while (NULL != (ds = ctx->dns_head))
+  {
+    GNUNET_CONTAINER_DLL_remove (ctx->dns_head,
+                                 ctx->dns_tail,
+                                 ds);
+    GNUNET_free (ds);
+  }
+  for (unsigned int i=0;i<ctx->num_sockets;i++)
+    cleanup_rs (&ctx->sockets[i]);
+  GNUNET_free (ctx->sockets);
+  GNUNET_free (ctx);
+}
+
+
+/* end of dnsstub.c */
diff --git a/src/util/regex.c b/src/util/regex.c
new file mode 100644 (file)
index 0000000..7565a9e
--- /dev/null
@@ -0,0 +1,834 @@
+/*
+     This file is part of GNUnet
+     Copyright (C) 2012, 2013, 2015 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Affero General Public License for more details.
+    
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @file src/tun/regex.c
+ * @brief functions to convert IP networks to regexes
+ * @author Maximilian Szengel
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_util_lib.h"
+#include "gnunet_tun_lib.h"
+
+/**
+ * 'wildcard', matches all possible values (for HEX encoding).
+ */
+#define DOT "(0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)"
+
+
+/**
+ * Create a regex in @a rxstr from the given @a ip and @a netmask.
+ *
+ * @param ip IPv4 representation.
+ * @param port destination port
+ * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV4_REGEXLEN
+ *              bytes long.
+ */
+void
+GNUNET_TUN_ipv4toregexsearch (const struct in_addr *ip,
+                              uint16_t port,
+                              char *rxstr)
+{
+  GNUNET_snprintf (rxstr,
+                   GNUNET_TUN_IPV4_REGEXLEN,
+                   "4-%04X-%08X",
+                   (unsigned int) port,
+                   ntohl (ip->s_addr));
+}
+
+
+/**
+ * Create a regex in @a rxstr from the given @a ipv6 and @a prefixlen.
+ *
+ * @param ipv6 IPv6 representation.
+ * @param port destination port
+ * @param rxstr generated regex, must be at least #GNUNET_TUN_IPV6_REGEXLEN
+ *              bytes long.
+ */
+void
+GNUNET_TUN_ipv6toregexsearch (const struct in6_addr *ipv6,
+                              uint16_t port,
+                              char *rxstr)
+{
+  const uint32_t *addr;
+
+  addr = (const uint32_t *) ipv6;
+  GNUNET_snprintf (rxstr,
+                   GNUNET_TUN_IPV6_REGEXLEN,
+                   "6-%04X-%08X%08X%08X%08X",
+                   (unsigned int) port,
+                   ntohl (addr[0]),
+                   ntohl (addr[1]),
+                   ntohl (addr[2]),
+                   ntohl (addr[3]));
+}
+
+
+/**
+ * Convert the given 4-bit (!) number to a regex.
+ *
+ * @param value the value, only the lowest 4 bits will be looked at
+ * @param mask which bits in value are wildcards (any value)?
+ */
+static char *
+nibble_to_regex (uint8_t value,
+                 uint8_t mask)
+{
+  char *ret;
+
+  value &= mask;
+  switch (mask)
+  {
+  case 0:
+    return GNUNET_strdup (DOT);
+  case 8:
+    GNUNET_asprintf (&ret,
+                     "(%X|%X|%X|%X|%X|%X|%X|%X)",
+                     value,
+                     value + 1,
+                     value + 2,
+                     value + 3,
+                     value + 4,
+                     value + 5,
+                     value + 6,
+                     value + 7);
+    return ret;
+  case 12:
+    GNUNET_asprintf (&ret,
+                     "(%X|%X|%X|%X)",
+                     value,
+                     value + 1,
+                     value + 2,
+                     value + 3);
+    return ret;
+  case 14:
+    GNUNET_asprintf (&ret,
+                     "(%X|%X)",
+                     value,
+                     value + 1);
+    return ret;
+  case 15:
+    GNUNET_asprintf (&ret,
+                     "%X",
+                     value);
+    return ret;
+  default:
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                _("Bad mask: %d\n"),
+                mask);
+    GNUNET_break (0);
+    return NULL;
+  }
+}
+
+
+/**
+ * Convert the given 16-bit number to a regex.
+ *
+ * @param value the value
+ * @param mask which bits in value are wildcards (any value)?
+ */
+static char *
+num_to_regex (uint16_t value,
+              uint16_t mask)
+{
+  const uint8_t *v = (const uint8_t *) &value;
+  const uint8_t *m = (const uint8_t *) &mask;
+  char *a;
+  char *b;
+  char *c;
+  char *d;
+  char *ret;
+
+  a = nibble_to_regex (v[0] >> 4, m[0] >> 4);
+  b = nibble_to_regex (v[0] & 15, m[0] & 15);
+  c = nibble_to_regex (v[1] >> 4, m[1] >> 4);
+  d = nibble_to_regex (v[1] & 15, m[1] & 15);
+  ret = NULL;
+  if ( (NULL != a) &&
+       (NULL != b) &&
+       (NULL != c) &&
+       (NULL != d) )
+    GNUNET_asprintf (&ret,
+                     "%s%s%s%s",
+                     a, b, c, d);
+  GNUNET_free_non_null (a);
+  GNUNET_free_non_null (b);
+  GNUNET_free_non_null (c);
+  GNUNET_free_non_null (d);
+  return ret;
+}
+
+
+/**
+ * Do we need to put parents around the given argument?
+ *
+ * @param arg part of a regular expression
+ * @return #GNUNET_YES if we should parens,
+ *         #GNUNET_NO if not
+ */
+static int
+needs_parens (const char *arg)
+{
+  size_t off;
+  size_t len;
+  unsigned int op;
+
+  op = 0;
+  len = strlen (arg);
+  for (off=0;off<len;off++)
+  {
+    switch (arg[off])
+    {
+    case '(':
+      op++;
+      break;
+    case ')':
+      GNUNET_assert (op > 0);
+      op--;
+      break;
+    case '|':
+      if (0 == op)
+        return GNUNET_YES;
+      break;
+    default:
+      break;
+    }
+  }
+  return GNUNET_NO;
+}
+
+
+/**
+ * Compute port policy for the given range of
+ * port numbers.
+ *
+ * @param start starting offset
+ * @param end end offset
+ * @param step increment level (power of 16)
+ * @param pp port policy to convert
+ * @return corresponding regex
+ */
+static char *
+compute_policy (unsigned int start,
+                unsigned int end,
+                unsigned int step,
+                const struct GNUNET_STRINGS_PortPolicy *pp)
+{
+  unsigned int i;
+  char before[36]; /* 16 * 2 + 3 dots + 0-terminator */
+  char middlel[33]; /* 16 * 2 + 0-terminator */
+  char middleh[33]; /* 16 * 2 + 0-terminator */
+  char after[36]; /* 16 * 2 + 3 dots + 0-terminator */
+  char beforep[36+2]; /* 16 * 2 + 3 dots + 0-terminator + ()*/
+  char middlehp[33+2]; /* 16 * 2 + 0-terminator + () */
+  char middlelp[33+2]; /* 16 * 2 + 0-terminator + () */
+  char afterp[36+2]; /* 16 * 2 + 3 dots + 0-terminator + () */
+  char dots[5 * strlen (DOT)];
+  char buf[3];
+  char *middle;
+  char *ret;
+  unsigned int xstep;
+  char *recl;
+  char *rech;
+  char *reclp;
+  char *rechp;
+  unsigned int start_port;
+  unsigned int end_port;
+
+  GNUNET_assert (GNUNET_YES == pp->negate_portrange);
+  start_port = pp->start_port;
+  if (1 == start_port)
+    start_port = 0;
+  end_port = pp->end_port;
+  GNUNET_assert ((end - start) / step <= 0xF);
+  before[0] = '\0';
+  middlel[0] = '\0';
+  middleh[0] = '\0';
+  after[0] = '\0';
+  for (i=start;i<=end;i+=step)
+  {
+    GNUNET_snprintf (buf,
+                     sizeof (buf),
+                     "%X|",
+                     (i - start) / step);
+    if (i / step < start_port / step)
+      strcat (before, buf);
+    else if (i / step > end_port / step)
+      strcat (after, buf);
+    else if (i / step == start_port / step)
+      strcat (middlel, buf);
+    else if (i / step == end_port / step)
+      strcat (middleh, buf);
+  }
+  if (strlen (before) > 0)
+    before[strlen (before)-1] = '\0';
+  if (strlen (middlel) > 0)
+    middlel[strlen (middlel)-1] = '\0';
+  if (strlen (middleh) > 0)
+    middleh[strlen (middleh)-1] = '\0';
+  if (strlen (after) > 0)
+    after[strlen (after)-1] = '\0';
+  if (needs_parens (before))
+    GNUNET_snprintf (beforep,
+                     sizeof (beforep),
+                     "(%s)",
+                     before);
+  else
+    strcpy (beforep, before);
+  if (needs_parens (middlel))
+    GNUNET_snprintf (middlelp,
+                     sizeof (middlelp),
+                     "(%s)",
+                     middlel);
+  else
+    strcpy (middlelp, middlel);
+  if (needs_parens (middleh))
+    GNUNET_snprintf (middlehp,
+                     sizeof (middlehp),
+                     "(%s)",
+                     middleh);
+  else
+    strcpy (middlehp, middleh);
+  if (needs_parens (after))
+    GNUNET_snprintf (afterp,
+                     sizeof (afterp),
+                     "(%s)",
+                     after);
+  else
+    strcpy (afterp, after);
+  dots[0] = '\0';
+  for (xstep=step/16;xstep>0;xstep/=16)
+    strcat (dots, DOT);
+  if (step >= 16)
+  {
+    if (strlen (middlel) > 0)
+      recl = compute_policy ((start_port / step) * step,
+                             (start_port / step) * step + step - 1,
+                             step / 16,
+                             pp);
+    else
+      recl = GNUNET_strdup ("");
+    if (strlen (middleh) > 0)
+      rech = compute_policy ((end_port / step) * step,
+                             (end_port / step) * step + step - 1,
+                             step / 16,
+                             pp);
+    else
+      rech = GNUNET_strdup ("");
+  }
+  else
+  {
+    recl = GNUNET_strdup ("");
+    rech = GNUNET_strdup ("");
+    middlel[0] = '\0';
+    middlelp[0] = '\0';
+    middleh[0] = '\0';
+    middlehp[0] = '\0';
+  }
+  if (needs_parens (recl))
+    GNUNET_asprintf (&reclp,
+                     "(%s)",
+                     recl);
+  else
+    reclp = GNUNET_strdup (recl);
+  if (needs_parens (rech))
+    GNUNET_asprintf (&rechp,
+                     "(%s)",
+                     rech);
+  else
+    rechp = GNUNET_strdup (rech);
+
+  if ( (strlen (middleh) > 0) &&
+       (strlen (rech) > 0) &&
+       (strlen (middlel) > 0) &&
+       (strlen (recl) > 0) )
+  {
+    GNUNET_asprintf (&middle,
+                     "%s%s|%s%s",
+                     middlel,
+                     reclp,
+                     middleh,
+                     rechp);
+  }
+  else if ( (strlen (middleh) > 0) &&
+            (strlen (rech) > 0) )
+  {
+    GNUNET_asprintf (&middle,
+                     "%s%s",
+                     middleh,
+                     rechp);
+  }
+  else if ( (strlen (middlel) > 0) &&
+            (strlen (recl) > 0) )
+  {
+    GNUNET_asprintf (&middle,
+                     "%s%s",
+                     middlel,
+                     reclp);
+  }
+  else
+  {
+    middle = GNUNET_strdup ("");
+  }
+  if ( (strlen(before) > 0) &&
+       (strlen(after) > 0) )
+  {
+    if (strlen (dots) > 0)
+    {
+      if (strlen (middle) > 0)
+        GNUNET_asprintf (&ret,
+                         "(%s%s|%s|%s%s)",
+                         beforep, dots,
+                         middle,
+                         afterp, dots);
+      else
+        GNUNET_asprintf (&ret,
+                         "(%s|%s)%s",
+                         beforep,
+                         afterp,
+                         dots);
+    }
+    else
+    {
+      if (strlen (middle) > 0)
+        GNUNET_asprintf (&ret,
+                         "(%s|%s|%s)",
+                         before,
+                         middle,
+                         after);
+      else if (1 == step)
+        GNUNET_asprintf (&ret,
+                         "%s|%s",
+                         before,
+                         after);
+      else
+        GNUNET_asprintf (&ret,
+                         "(%s|%s)",
+                         before,
+                         after);
+    }
+  }
+  else if (strlen (before) > 0)
+  {
+    if (strlen (dots) > 0)
+    {
+      if (strlen (middle) > 0)
+        GNUNET_asprintf (&ret,
+                         "(%s%s|%s)",
+                         beforep, dots,
+                         middle);
+      else
+        GNUNET_asprintf (&ret,
+                         "%s%s",
+                         beforep, dots);
+    }
+    else
+    {
+      if (strlen (middle) > 0)
+        GNUNET_asprintf (&ret,
+                         "(%s|%s)",
+                         before,
+                         middle);
+      else
+        GNUNET_asprintf (&ret,
+                         "%s",
+                         before);
+    }
+  }
+  else if (strlen (after) > 0)
+  {
+    if (strlen (dots) > 0)
+    {
+      if (strlen (middle) > 0)
+        GNUNET_asprintf (&ret,
+                         "(%s|%s%s)",
+                         middle,
+                         afterp, dots);
+      else
+        GNUNET_asprintf (&ret,
+                         "%s%s",
+                         afterp, dots);
+    }
+    else
+    {
+      if (strlen (middle) > 0)
+        GNUNET_asprintf (&ret,
+                         "%s|%s",
+                         middle,
+                         after);
+      else
+        GNUNET_asprintf (&ret,
+                         "%s",
+                         after);
+    }
+  }
+  else if (strlen (middle) > 0)
+  {
+    GNUNET_asprintf (&ret,
+                     "%s",
+                     middle);
+  }
+  else
+  {
+    ret = GNUNET_strdup ("");
+  }
+  GNUNET_free (middle);
+  GNUNET_free (reclp);
+  GNUNET_free (rechp);
+  GNUNET_free (recl);
+  GNUNET_free (rech);
+  return ret;
+}
+
+
+/**
+ * Convert a port policy to a regular expression.  Note: this is a
+ * very simplistic implementation, we might want to consider doing
+ * something more sophisiticated (resulting in smaller regular
+ * expressions) at a later time.
+ *
+ * @param pp port policy to convert
+ * @return NULL on error
+ */
+static char *
+port_to_regex (const struct GNUNET_STRINGS_PortPolicy *pp)
+{
+  char *reg;
+  char *ret;
+  char *pos;
+  unsigned int i;
+  unsigned int cnt;
+
+  if ( (0 == pp->start_port) ||
+       ( (1 == pp->start_port) &&
+         (0xFFFF == pp->end_port) &&
+         (GNUNET_NO == pp->negate_portrange)) )
+    return GNUNET_strdup (DOT DOT DOT DOT);
+  if ( (pp->start_port == pp->end_port) &&
+       (GNUNET_NO == pp->negate_portrange))
+  {
+    GNUNET_asprintf (&ret,
+                     "%04X",
+                     pp->start_port);
+    return ret;
+  }
+  if (pp->end_port < pp->start_port)
+    return NULL;
+
+  if (GNUNET_YES == pp->negate_portrange)
+  {
+    ret = compute_policy (0, 0xFFFF, 0x1000, pp);
+  }
+  else
+  {
+    cnt = pp->end_port - pp->start_port + 1;
+    reg = GNUNET_malloc (cnt * 5 + 1);
+    pos = reg;
+    for (i=1;i<=0xFFFF;i++)
+    {
+      if ( (i >= pp->start_port) && (i <= pp->end_port) )
+      {
+        if (pos == reg)
+        {
+          GNUNET_snprintf (pos,
+                           5,
+                           "%04X",
+                           i);
+        }
+        else
+        {
+          GNUNET_snprintf (pos,
+                           6,
+                           "|%04X",
+                           i);
+        }
+        pos += strlen (pos);
+      }
+    }
+    GNUNET_asprintf (&ret,
+                     "(%s)",
+                     reg);
+    GNUNET_free (reg);
+  }
+  return ret;
+}
+
+
+/**
+ * Convert an address (IPv4 or IPv6) to a regex.
+ *
+ * @param addr address
+ * @param mask network mask
+ * @param len number of bytes in @a addr and @a mask
+ * @return NULL on error, otherwise regex for the address
+ */
+static char *
+address_to_regex (const void *addr,
+                  const void *mask,
+                  size_t len)
+{
+  const uint16_t *a = addr;
+  const uint16_t *m = mask;
+  char *ret;
+  char *tmp;
+  char *reg;
+  unsigned int i;
+
+  ret = NULL;
+  GNUNET_assert (1 != (len % 2));
+  for (i=0;i<len / 2;i++)
+  {
+    reg = num_to_regex (a[i], m[i]);
+    if (NULL == reg)
+    {
+      GNUNET_free_non_null (ret);
+      return NULL;
+    }
+    if (NULL == ret)
+    {
+      ret = reg;
+    }
+    else
+    {
+      GNUNET_asprintf (&tmp,
+                       "%s%s",
+                       ret, reg);
+      GNUNET_free (ret);
+      GNUNET_free (reg);
+      ret = tmp;
+    }
+  }
+  return ret;
+}
+
+
+/**
+ * Convert a single line of an IPv4 policy to a regular expression.
+ *
+ * @param v4 line to convert
+ * @return NULL on error
+ */
+static char *
+ipv4_to_regex (const struct GNUNET_STRINGS_IPv4NetworkPolicy *v4)
+{
+  char *reg;
+  char *pp;
+  char *ret;
+
+  reg = address_to_regex (&v4->network,
+                          &v4->netmask,
+                          sizeof (struct in_addr));
+  if (NULL == reg)
+    return NULL;
+  pp = port_to_regex (&v4->pp);
+  if (NULL == pp)
+  {
+    GNUNET_free (reg);
+    return NULL;
+  }
+  GNUNET_asprintf (&ret,
+                   "4-%s-%s",
+                   pp, reg);
+  GNUNET_free (pp);
+  GNUNET_free (reg);
+  return ret;
+}
+
+
+/**
+ * Convert a single line of an IPv4 policy to a regular expression.
+ *
+ * @param v6 line to convert
+ * @return NULL on error
+ */
+static char *
+ipv6_to_regex (const struct GNUNET_STRINGS_IPv6NetworkPolicy *v6)
+{
+  char *reg;
+  char *pp;
+  char *ret;
+
+  reg = address_to_regex (&v6->network,
+                          &v6->netmask,
+                          sizeof (struct in6_addr));
+  if (NULL == reg)
+    return NULL;
+  pp = port_to_regex (&v6->pp);
+  if (NULL == pp)
+  {
+    GNUNET_free (reg);
+    return NULL;
+  }
+  GNUNET_asprintf (&ret,
+                   "6-%s-%s",
+                   pp, reg);
+  GNUNET_free (pp);
+  GNUNET_free (reg);
+  return ret;
+}
+
+
+/**
+ * Convert an exit policy to a regular expression.  The exit policy
+ * specifies a set of subnets this peer is willing to serve as an
+ * exit for; the resulting regular expression will match the
+ * IPv4 address strings as returned by #GNUNET_TUN_ipv4toregexsearch().
+ *
+ * @param policy exit policy specification
+ * @return regular expression, NULL on error
+ */
+char *
+GNUNET_TUN_ipv4policy2regex (const char *policy)
+{
+  struct GNUNET_STRINGS_IPv4NetworkPolicy *np;
+  char *reg;
+  char *tmp;
+  char *line;
+  unsigned int i;
+
+  np = GNUNET_STRINGS_parse_ipv4_policy (policy);
+  if (NULL == np)
+    return NULL;
+  reg = NULL;
+  for (i=0; (0 == i) || (0 != np[i].network.s_addr); i++)
+  {
+    line = ipv4_to_regex (&np[i]);
+    if (NULL == line)
+    {
+      GNUNET_free_non_null (reg);
+      GNUNET_free (np);
+      return NULL;
+    }
+    if (NULL == reg)
+    {
+      reg = line;
+    }
+    else
+    {
+      GNUNET_asprintf (&tmp,
+                       "%s|(%s)",
+                       reg, line);
+      GNUNET_free (reg);
+      GNUNET_free (line);
+      reg = tmp;
+    }
+    if (0 == np[i].network.s_addr)
+      break;
+  }
+  GNUNET_free (np);
+  return reg;
+}
+
+
+/**
+ * Convert an exit policy to a regular expression.  The exit policy
+ * specifies a set of subnets this peer is willing to serve as an
+ * exit for; the resulting regular expression will match the
+ * IPv6 address strings as returned by #GNUNET_TUN_ipv6toregexsearch().
+ *
+ * @param policy exit policy specification
+ * @return regular expression, NULL on error
+ */
+char *
+GNUNET_TUN_ipv6policy2regex (const char *policy)
+{
+  struct in6_addr zero;
+  struct GNUNET_STRINGS_IPv6NetworkPolicy *np;
+  char *reg;
+  char *tmp;
+  char *line;
+  unsigned int i;
+
+  np = GNUNET_STRINGS_parse_ipv6_policy (policy);
+  if (NULL == np)
+    return NULL;
+  reg = NULL;
+  memset (&zero, 0, sizeof (struct in6_addr));
+  for (i=0; (0 == i) || (0 != memcmp (&zero, &np[i].network, sizeof (struct in6_addr))); i++)
+  {
+    line = ipv6_to_regex (&np[i]);
+    if (NULL == line)
+    {
+      GNUNET_free_non_null (reg);
+      GNUNET_free (np);
+      return NULL;
+    }
+    if (NULL == reg)
+    {
+      reg = line;
+    }
+    else
+    {
+      GNUNET_asprintf (&tmp,
+                       "%s|(%s)",
+                       reg, line);
+      GNUNET_free (reg);
+      GNUNET_free (line);
+      reg = tmp;
+    }
+    if (0 == memcmp (&zero, &np[i].network, sizeof (struct in6_addr)))
+      break;
+  }
+  GNUNET_free (np);
+  return reg;
+}
+
+
+/**
+ * Hash the service name of a hosted service to the
+ * hash code that is used to identify the service on
+ * the network.
+ *
+ * @param service_name a string
+ * @param hc corresponding hash
+ */
+void
+GNUNET_TUN_service_name_to_hash (const char *service_name,
+                                 struct GNUNET_HashCode *hc)
+{
+  GNUNET_CRYPTO_hash (service_name,
+                      strlen (service_name),
+                      hc);
+}
+
+
+/**
+ * Compute the CADET port given a service descriptor
+ * (returned from #GNUNET_TUN_service_name_to_hash) and
+ * a TCP/UDP port @a ip_port.
+ *
+ * @param desc service shared secret
+ * @param ip_port TCP/UDP port, use 0 for ICMP
+ * @param[out] cadet_port CADET port to use
+ */
+void
+GNUNET_TUN_compute_service_cadet_port (const struct GNUNET_HashCode *desc,
+                                       uint16_t ip_port,
+                                       struct GNUNET_HashCode *cadet_port)
+{
+  uint16_t be_port = htons (ip_port);
+
+  *cadet_port = *desc;
+  GNUNET_memcpy (cadet_port,
+                 &be_port,
+                 sizeof (uint16_t));
+}
+
+
+/* end of regex.c */
diff --git a/src/util/test_regex.c b/src/util/test_regex.c
new file mode 100644 (file)
index 0000000..2e7d528
--- /dev/null
@@ -0,0 +1,179 @@
+/*
+     This file is part of GNUnet
+     Copyright (C) 2012, 2013 GNUnet e.V.
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Affero General Public License for more details.
+    
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+/**
+ * @file tun/test_regex.c
+ * @brief simple test for regex.c iptoregex functions
+ * @author Maximilian Szengel
+ */
+#include "platform.h"
+#include "gnunet_tun_lib.h"
+
+/**
+ * 'wildcard', matches all possible values (for HEX encoding).
+ */
+#define DOT "(0|1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)"
+
+
+static int
+test_iptoregex (const char *ipv4,
+                uint16_t port,
+                const char *expectedv4,
+                const char *ipv6,
+                uint16_t port6,
+                const char *expectedv6)
+{
+  int error = 0;
+
+  struct in_addr a;
+  struct in6_addr b;
+  char rxv4[GNUNET_TUN_IPV4_REGEXLEN];
+  char rxv6[GNUNET_TUN_IPV6_REGEXLEN];
+
+  GNUNET_assert (1 == inet_pton (AF_INET, ipv4, &a));
+  GNUNET_TUN_ipv4toregexsearch (&a, port, rxv4);
+
+  if (0 != strcmp (rxv4, expectedv4))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Expected: %s but got: %s\n",
+                expectedv4,
+                rxv4);
+    error++;
+  }
+
+  GNUNET_assert (1 == inet_pton (AF_INET6, ipv6, &b));
+  GNUNET_TUN_ipv6toregexsearch (&b, port6, rxv6);
+  if (0 != strcmp (rxv6, expectedv6))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Expected: %s but got: %s\n",
+                expectedv6, rxv6);
+    error++;
+  }
+  return error;
+}
+
+
+static int
+test_policy4toregex (const char *policy,
+                     const char *regex)
+{
+  char *r;
+  int ret;
+
+  ret = 0;
+  r = GNUNET_TUN_ipv4policy2regex (policy);
+  if (NULL == r)
+  {
+    GNUNET_break (0);
+    return 1;
+  }
+  if (0 != strcmp (regex, r))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Expected: `%s' but got: `%s'\n",
+                regex, r);
+    ret = 2;
+  }
+  GNUNET_free (r);
+  return ret;
+}
+
+
+static int
+test_policy6toregex (const char *policy,
+                     const char *regex)
+{
+  char *r;
+  int ret;
+
+  ret = 0;
+  r = GNUNET_TUN_ipv6policy2regex (policy);
+  if (NULL == r)
+  {
+    GNUNET_break (0);
+    return 1;
+  }
+  if (0 != strcmp (regex, r))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Expected: `%s' but got: `%s'\n",
+                regex, r);
+    ret = 2;
+  }
+  GNUNET_free (r);
+  return ret;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  int error;
+  char *r;
+
+  GNUNET_log_setup ("test-regex", "WARNING", NULL);
+  error = 0;
+
+  /* this is just a performance test ... */
+  r = GNUNET_TUN_ipv4policy2regex ("1.2.3.4/16:!25;");
+  GNUNET_break (NULL != r);
+  GNUNET_free (r);
+
+  error +=
+    test_iptoregex ("192.1.2.3", 2086,
+                    "4-0826-C0010203",
+                    "FFFF::1", 8080,
+                    "6-1F90-FFFF0000000000000000000000000001");
+  error +=
+    test_iptoregex ("187.238.255.0", 80,
+                    "4-0050-BBEEFF00",
+                    "E1E1:73F9:51BE::0", 49,
+                    "6-0031-E1E173F951BE00000000000000000000");
+  error +=
+    test_policy4toregex ("192.1.2.0/24:80;",
+                         "4-0050-C00102" DOT DOT);
+  error +=
+    test_policy4toregex ("192.1.0.0/16;",
+                         "4-" DOT DOT DOT DOT "-C001" DOT DOT DOT DOT);
+  error +=
+    test_policy4toregex ("192.1.0.0/16:80-81;",
+                         "4-(0050|0051)-C001" DOT DOT DOT DOT);
+  error +=
+    test_policy4toregex ("192.1.0.0/8:!3-65535;",
+                         "4-000(0|1|2)-C0" DOT DOT DOT DOT DOT DOT);
+  error +=
+    test_policy4toregex ("192.1.0.0/8:!25-56;",
+                         "4-(0(0(0"DOT"|1(0|1|2|3|4|5|6|7|8)|3(9|A|B|C|D|E|F)|(4|5|6|7|8|9|A|B|C|D|E|F)"DOT")|(1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)"DOT DOT")|(1|2|3|4|5|6|7|8|9|A|B|C|D|E|F)"DOT DOT DOT")-C0"DOT DOT DOT DOT DOT DOT);
+  error +=
+    test_policy6toregex ("E1E1::1;",
+                         "6-"DOT DOT DOT DOT"-E1E10000000000000000000000000001");
+  error +=
+    test_policy6toregex ("E1E1:ABCD::1/120;",
+                         "6-"DOT DOT DOT DOT"-E1E1ABCD0000000000000000000000" DOT DOT);
+  error +=
+    test_policy6toregex ("E1E1:ABCD::ABCD/126;",
+                         "6-"DOT DOT DOT DOT"-E1E1ABCD00000000000000000000ABC(C|D|E|F)");
+  error +=
+    test_policy6toregex ("E1E1:ABCD::ABCD/127;",
+                         "6-"DOT DOT DOT DOT"-E1E1ABCD00000000000000000000ABC(C|D)");
+  error +=
+    test_policy6toregex ("E1E1:ABCD::ABCD/128:80;",
+                         "6-0050-E1E1ABCD00000000000000000000ABCD");
+  return error;
+}
diff --git a/src/util/test_tun.c b/src/util/test_tun.c
new file mode 100644 (file)
index 0000000..edbd4c0
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2010, 2011, 2012 Christian Grothoff
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Affero General Public License for more details.
+    
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file tun/test_tun.c
+ * @brief test for tun.c
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_tun_lib.h"
+
+static int ret;
+
+static void
+test_udp (size_t pll,
+         int pl_fill,
+         uint16_t crc)
+{
+  struct GNUNET_TUN_IPv4Header ip;
+  struct GNUNET_TUN_UdpHeader udp;
+  char payload[pll];
+  struct in_addr src;
+  struct in_addr dst;
+
+  GNUNET_assert (1 == inet_pton (AF_INET, "1.2.3.4", &src));
+  GNUNET_assert (1 == inet_pton (AF_INET, "122.2.3.5", &dst));
+  memset (payload, pl_fill, sizeof (payload));
+  GNUNET_TUN_initialize_ipv4_header (&ip,
+                                    IPPROTO_UDP,
+                                    pll + sizeof (udp),
+                                    &src,
+                                    &dst);
+  udp.source_port = htons (4242);
+  udp.destination_port = htons (4242);
+  udp.len = htons (pll);
+  GNUNET_TUN_calculate_udp4_checksum (&ip,
+                                     &udp,
+                                     payload,
+                                     pll);
+  if (crc != ntohs (udp.crc))
+  {
+    fprintf (stderr, "Got CRC: %u, wanted: %u\n",
+            ntohs (udp.crc),
+            crc);
+    ret = 1;
+  }
+}
+
+int main (int argc,
+         char **argv)
+{
+  test_udp (4, 3, 22439);
+  test_udp (4, 1, 23467);
+  test_udp (7, 17, 6516);
+  test_udp (12451, 251, 42771);
+  return ret;
+}
diff --git a/src/util/tun.c b/src/util/tun.c
new file mode 100644 (file)
index 0000000..f85f722
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+     This file is part of GNUnet.
+     Copyright (C) 2010, 2011, 2012 Christian Grothoff
+
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
+
+     GNUnet is distributed in the hope that it will be useful, but
+     WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+     Affero General Public License for more details.
+    
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file tun/tun.c
+ * @brief standard IP calculations for TUN interaction
+ * @author Philipp Toelke
+ * @author Christian Grothoff
+ */
+#include "platform.h"
+#include "gnunet_tun_lib.h"
+
+/**
+ * IP TTL we use for packets that we assemble (8 bit unsigned integer)
+ */
+#define FRESH_TTL 64
+
+
+/**
+ * Initialize an IPv4 header.
+ *
+ * @param ip header to initialize
+ * @param protocol protocol to use (i.e. IPPROTO_UDP)
+ * @param payload_length number of bytes of payload that follow (excluding IPv4 header)
+ * @param src source IP address to use
+ * @param dst destination IP address to use
+ */
+void
+GNUNET_TUN_initialize_ipv4_header (struct GNUNET_TUN_IPv4Header *ip,
+                                  uint8_t protocol,
+                                  uint16_t payload_length,
+                                  const struct in_addr *src,
+                                  const struct in_addr *dst)
+{
+  GNUNET_assert (20 == sizeof (struct GNUNET_TUN_IPv4Header));
+  GNUNET_assert (payload_length <= UINT16_MAX - sizeof (struct GNUNET_TUN_IPv4Header));
+  memset (ip, 0, sizeof (struct GNUNET_TUN_IPv4Header));
+  ip->header_length =  sizeof (struct GNUNET_TUN_IPv4Header) / 4;
+  ip->version = 4;
+  ip->total_length = htons (sizeof (struct GNUNET_TUN_IPv4Header) + payload_length);
+  ip->identification = (uint16_t) GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK,
+                                                           65536);
+  ip->ttl = FRESH_TTL;
+  ip->protocol = protocol;
+  ip->source_address = *src;
+  ip->destination_address = *dst;
+  ip->checksum = GNUNET_CRYPTO_crc16_n (ip, sizeof (struct GNUNET_TUN_IPv4Header));
+}
+
+
+/**
+ * Initialize an IPv6 header.
+ *
+ * @param ip header to initialize
+ * @param protocol protocol to use (i.e. IPPROTO_UDP), technically "next_header" for IPv6
+ * @param payload_length number of bytes of payload that follow (excluding IPv6 header)
+ * @param src source IP address to use
+ * @param dst destination IP address to use
+ */
+void
+GNUNET_TUN_initialize_ipv6_header (struct GNUNET_TUN_IPv6Header *ip,
+                                  uint8_t protocol,
+                                  uint16_t payload_length,
+                                  const struct in6_addr *src,
+                                  const struct in6_addr *dst)
+{
+  GNUNET_assert (40 == sizeof (struct GNUNET_TUN_IPv6Header));
+  GNUNET_assert (payload_length <= UINT16_MAX - sizeof (struct GNUNET_TUN_IPv6Header));
+  memset (ip, 0, sizeof (struct GNUNET_TUN_IPv6Header));
+  ip->version = 6;
+  ip->next_header = protocol;
+  ip->payload_length = htons ((uint16_t) payload_length);
+  ip->hop_limit = FRESH_TTL;
+  ip->destination_address = *dst;
+  ip->source_address = *src;
+}
+
+
+/**
+ * Calculate IPv4 TCP checksum.
+ *
+ * @param ip ipv4 header fully initialized
+ * @param tcp TCP header (initialized except for CRC)
+ * @param payload the TCP payload
+ * @param payload_length number of bytes of TCP payload
+ */
+void
+GNUNET_TUN_calculate_tcp4_checksum (const struct GNUNET_TUN_IPv4Header *ip,
+                                   struct GNUNET_TUN_TcpHeader *tcp,
+                                   const void *payload,
+                                   uint16_t payload_length)
+{
+  uint32_t sum;
+  uint16_t tmp;
+
+  GNUNET_assert (20 == sizeof (struct GNUNET_TUN_TcpHeader));
+  GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_IPv4Header) + sizeof (struct GNUNET_TUN_TcpHeader) ==
+                ntohs (ip->total_length));
+  GNUNET_assert (IPPROTO_TCP == ip->protocol);
+
+  tcp->crc = 0;
+  sum = GNUNET_CRYPTO_crc16_step (0,
+                                 &ip->source_address,
+                                 sizeof (struct in_addr) * 2);
+  tmp = htons (IPPROTO_TCP);
+  sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint16_t));
+  tmp = htons (payload_length + sizeof (struct GNUNET_TUN_TcpHeader));
+  sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint16_t));
+  sum = GNUNET_CRYPTO_crc16_step (sum, tcp, sizeof (struct GNUNET_TUN_TcpHeader));
+  sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
+  tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
+}
+
+
+/**
+ * Calculate IPv6 TCP checksum.
+ *
+ * @param ip ipv6 header fully initialized
+ * @param tcp header (initialized except for CRC)
+ * @param payload the TCP payload
+ * @param payload_length number of bytes of TCP payload
+ */
+void
+GNUNET_TUN_calculate_tcp6_checksum (const struct GNUNET_TUN_IPv6Header *ip,
+                                   struct GNUNET_TUN_TcpHeader *tcp,
+                                   const void *payload,
+                                   uint16_t payload_length)
+{
+  uint32_t sum;
+  uint32_t tmp;
+
+  GNUNET_assert (20 == sizeof (struct GNUNET_TUN_TcpHeader));
+  GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_TcpHeader) ==
+                ntohs (ip->payload_length));
+  GNUNET_assert (IPPROTO_TCP == ip->next_header);
+  tcp->crc = 0;
+  sum = GNUNET_CRYPTO_crc16_step (0, &ip->source_address, 2 * sizeof (struct in6_addr));
+  tmp = htonl (sizeof (struct GNUNET_TUN_TcpHeader) + payload_length);
+  sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
+  tmp = htonl (IPPROTO_TCP);
+  sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
+  sum = GNUNET_CRYPTO_crc16_step (sum, tcp,
+                                 sizeof (struct GNUNET_TUN_TcpHeader));
+  sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
+  tcp->crc = GNUNET_CRYPTO_crc16_finish (sum);
+}
+
+
+/**
+ * Calculate IPv4 UDP checksum.
+ *
+ * @param ip ipv4 header fully initialized
+ * @param udp UDP header (initialized except for CRC)
+ * @param payload the UDP payload
+ * @param payload_length number of bytes of UDP payload
+ */
+void
+GNUNET_TUN_calculate_udp4_checksum (const struct GNUNET_TUN_IPv4Header *ip,
+                                   struct GNUNET_TUN_UdpHeader *udp,
+                                   const void *payload,
+                                   uint16_t payload_length)
+{
+  uint32_t sum;
+  uint16_t tmp;
+
+  GNUNET_assert (8 == sizeof (struct GNUNET_TUN_UdpHeader));
+  GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_IPv4Header) + sizeof (struct GNUNET_TUN_UdpHeader) ==
+                ntohs (ip->total_length));
+  GNUNET_assert (IPPROTO_UDP == ip->protocol);
+
+  udp->crc = 0; /* technically optional, but we calculate it anyway, just to be sure */
+  sum = GNUNET_CRYPTO_crc16_step (0,
+                                 &ip->source_address,
+                                 sizeof (struct in_addr) * 2);
+  tmp = htons (IPPROTO_UDP);
+  sum = GNUNET_CRYPTO_crc16_step (sum,
+                                 &tmp,
+                                 sizeof (uint16_t));
+  tmp = htons (sizeof (struct GNUNET_TUN_UdpHeader) + payload_length);
+  sum = GNUNET_CRYPTO_crc16_step (sum,
+                                 &tmp,
+                                 sizeof (uint16_t));
+  sum = GNUNET_CRYPTO_crc16_step (sum,
+                                 udp,
+                                 sizeof (struct GNUNET_TUN_UdpHeader));
+  sum = GNUNET_CRYPTO_crc16_step (sum,
+                                 payload,
+                                 payload_length);
+  udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
+}
+
+
+/**
+ * Calculate IPv6 UDP checksum.
+ *
+ * @param ip ipv6 header fully initialized
+ * @param udp UDP header (initialized except for CRC)
+ * @param payload the UDP payload
+ * @param payload_length number of bytes of UDP payload
+ */
+void
+GNUNET_TUN_calculate_udp6_checksum (const struct GNUNET_TUN_IPv6Header *ip,
+                                   struct GNUNET_TUN_UdpHeader *udp,
+                                   const void *payload,
+                                   uint16_t payload_length)
+{
+  uint32_t sum;
+  uint32_t tmp;
+
+  GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_UdpHeader) ==
+                ntohs (ip->payload_length));
+  GNUNET_assert (payload_length + sizeof (struct GNUNET_TUN_UdpHeader) ==
+                ntohs (udp->len));
+  GNUNET_assert (IPPROTO_UDP == ip->next_header);
+
+  udp->crc = 0;
+  sum = GNUNET_CRYPTO_crc16_step (0,
+                                 &ip->source_address,
+                                 sizeof (struct in6_addr) * 2);
+  tmp = htons (sizeof (struct GNUNET_TUN_UdpHeader) + payload_length); /* aka udp->len */
+  sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
+  tmp = htons (ip->next_header);
+  sum = GNUNET_CRYPTO_crc16_step (sum, &tmp, sizeof (uint32_t));
+  sum = GNUNET_CRYPTO_crc16_step (sum, udp, sizeof (struct GNUNET_TUN_UdpHeader));
+  sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
+  udp->crc = GNUNET_CRYPTO_crc16_finish (sum);
+}
+
+
+/**
+ * Calculate ICMP checksum.
+ *
+ * @param icmp IMCP header (initialized except for CRC)
+ * @param payload the ICMP payload
+ * @param payload_length number of bytes of ICMP payload
+ */
+void
+GNUNET_TUN_calculate_icmp_checksum (struct GNUNET_TUN_IcmpHeader *icmp,
+                                   const void *payload,
+                                   uint16_t payload_length)
+{
+  uint32_t sum;
+
+  GNUNET_assert (8 == sizeof (struct GNUNET_TUN_IcmpHeader));
+  icmp->crc = 0;
+  sum = GNUNET_CRYPTO_crc16_step (0,
+                                 icmp,
+                                 sizeof (struct GNUNET_TUN_IcmpHeader));
+  sum = GNUNET_CRYPTO_crc16_step (sum, payload, payload_length);
+  icmp->crc = GNUNET_CRYPTO_crc16_finish (sum);
+}
+
+
+/**
+ * Check if two sockaddrs are equal.
+ *
+ * @param sa one address
+ * @param sb another address
+ * @param include_port also check ports
+ * @return #GNUNET_YES if they are equal
+ */
+int
+GNUNET_TUN_sockaddr_cmp (const struct sockaddr *sa,
+                         const struct sockaddr *sb,
+                         int include_port)
+{
+  if (sa->sa_family != sb->sa_family)
+    return GNUNET_NO;
+
+  switch (sa->sa_family)
+  {
+  case AF_INET:
+    {
+      const struct sockaddr_in *sa4 = (const struct sockaddr_in *) sa;
+      const struct sockaddr_in *sb4 = (const struct sockaddr_in *) sb;
+      return (sa4->sin_addr.s_addr == sb4->sin_addr.s_addr);
+    }
+  case AF_INET6:
+    {
+      const struct sockaddr_in6 *sa6 = (const struct sockaddr_in6 *) sa;
+      const struct sockaddr_in6 *sb6 = (const struct sockaddr_in6 *) sb;
+
+      return (0 == memcmp(&sa6->sin6_addr,
+                          &sb6->sin6_addr,
+                          sizeof (struct in6_addr)));
+    }
+  default:
+    GNUNET_break (0);
+    return GNUNET_SYSERR;
+  }
+}
+
+
+/* end of tun.c */